@tetrascience-npm/ts-connectors-sdk 3.1.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.
- package/CHANGELOG.md +201 -0
- package/LICENSE +201 -0
- package/README.md +123 -0
- package/dist/api-tests/configuration.test.d.ts +2 -0
- package/dist/api-tests/configuration.test.d.ts.map +1 -0
- package/dist/api-tests/configuration.test.js +49 -0
- package/dist/api-tests/configuration.test.js.map +1 -0
- package/dist/api-tests/connector-lifetime.test.d.ts +2 -0
- package/dist/api-tests/connector-lifetime.test.d.ts.map +1 -0
- package/dist/api-tests/connector-lifetime.test.js +64 -0
- package/dist/api-tests/connector-lifetime.test.js.map +1 -0
- package/dist/api-tests/connector-shutdown.test.d.ts +2 -0
- package/dist/api-tests/connector-shutdown.test.d.ts.map +1 -0
- package/dist/api-tests/connector-shutdown.test.js +76 -0
- package/dist/api-tests/connector-shutdown.test.js.map +1 -0
- package/dist/api-tests/fixture/assertions.d.ts +4 -0
- package/dist/api-tests/fixture/assertions.d.ts.map +1 -0
- package/dist/api-tests/fixture/assertions.js +8 -0
- package/dist/api-tests/fixture/assertions.js.map +1 -0
- package/dist/api-tests/fixture/config.d.ts +65 -0
- package/dist/api-tests/fixture/config.d.ts.map +1 -0
- package/dist/api-tests/fixture/config.js +24 -0
- package/dist/api-tests/fixture/config.js.map +1 -0
- package/dist/api-tests/fixture/connector-api.d.ts +126 -0
- package/dist/api-tests/fixture/connector-api.d.ts.map +1 -0
- package/dist/api-tests/fixture/connector-api.js +151 -0
- package/dist/api-tests/fixture/connector-api.js.map +1 -0
- package/dist/api-tests/fixture/connectors/test-connector.d.ts +39 -0
- package/dist/api-tests/fixture/connectors/test-connector.d.ts.map +1 -0
- package/dist/api-tests/fixture/connectors/test-connector.js +188 -0
- package/dist/api-tests/fixture/connectors/test-connector.js.map +1 -0
- package/dist/api-tests/fixture/create-http-client.d.ts +6 -0
- package/dist/api-tests/fixture/create-http-client.d.ts.map +1 -0
- package/dist/api-tests/fixture/create-http-client.js +52 -0
- package/dist/api-tests/fixture/create-http-client.js.map +1 -0
- package/dist/api-tests/fixture/fixture.d.ts +34 -0
- package/dist/api-tests/fixture/fixture.d.ts.map +1 -0
- package/dist/api-tests/fixture/fixture.js +62 -0
- package/dist/api-tests/fixture/fixture.js.map +1 -0
- package/dist/api-tests/fixture/test-connector-factory.d.ts +21 -0
- package/dist/api-tests/fixture/test-connector-factory.d.ts.map +1 -0
- package/dist/api-tests/fixture/test-connector-factory.js +78 -0
- package/dist/api-tests/fixture/test-connector-factory.js.map +1 -0
- package/dist/api-tests/label-validation.test.d.ts +2 -0
- package/dist/api-tests/label-validation.test.d.ts.map +1 -0
- package/dist/api-tests/label-validation.test.js +158 -0
- package/dist/api-tests/label-validation.test.js.map +1 -0
- package/dist/api-tests/standalone-cloudwatch-logs.test.d.ts +2 -0
- package/dist/api-tests/standalone-cloudwatch-logs.test.d.ts.map +1 -0
- package/dist/api-tests/standalone-cloudwatch-logs.test.js +32 -0
- package/dist/api-tests/standalone-cloudwatch-logs.test.js.map +1 -0
- package/dist/api-tests/user-agent.test.d.ts +2 -0
- package/dist/api-tests/user-agent.test.d.ts.map +1 -0
- package/dist/api-tests/user-agent.test.js +191 -0
- package/dist/api-tests/user-agent.test.js.map +1 -0
- package/dist/src/api.d.ts +353 -0
- package/dist/src/api.d.ts.map +1 -0
- package/dist/src/api.js +278 -0
- package/dist/src/api.js.map +1 -0
- package/dist/src/auth/auth-token-provider.d.ts +7 -0
- package/dist/src/auth/auth-token-provider.d.ts.map +1 -0
- package/dist/src/auth/auth-token-provider.js +3 -0
- package/dist/src/auth/auth-token-provider.js.map +1 -0
- package/dist/src/auth/aws-client-provider.d.ts +11 -0
- package/dist/src/auth/aws-client-provider.d.ts.map +1 -0
- package/dist/src/auth/aws-client-provider.js +3 -0
- package/dist/src/auth/aws-client-provider.js.map +1 -0
- package/dist/src/auth/aws-env-client-provider.d.ts +20 -0
- package/dist/src/auth/aws-env-client-provider.d.ts.map +1 -0
- package/dist/src/auth/aws-env-client-provider.js +69 -0
- package/dist/src/auth/aws-env-client-provider.js.map +1 -0
- package/dist/src/auth/aws-refresh-client-provider.d.ts +26 -0
- package/dist/src/auth/aws-refresh-client-provider.d.ts.map +1 -0
- package/dist/src/auth/aws-refresh-client-provider.js +111 -0
- package/dist/src/auth/aws-refresh-client-provider.js.map +1 -0
- package/dist/src/auth/aws-secret-auth-token-provider.d.ts +9 -0
- package/dist/src/auth/aws-secret-auth-token-provider.d.ts.map +1 -0
- package/dist/src/auth/aws-secret-auth-token-provider.js +58 -0
- package/dist/src/auth/aws-secret-auth-token-provider.js.map +1 -0
- package/dist/src/auth/index.d.ts +7 -0
- package/dist/src/auth/index.d.ts.map +1 -0
- package/dist/src/auth/index.js +23 -0
- package/dist/src/auth/index.js.map +1 -0
- package/dist/src/auth/predefined-auth-token-provider.d.ts +7 -0
- package/dist/src/auth/predefined-auth-token-provider.d.ts.map +1 -0
- package/dist/src/auth/predefined-auth-token-provider.js +24 -0
- package/dist/src/auth/predefined-auth-token-provider.js.map +1 -0
- package/dist/src/auth/user-supplied-auth-token-provider.d.ts +7 -0
- package/dist/src/auth/user-supplied-auth-token-provider.d.ts.map +1 -0
- package/dist/src/auth/user-supplied-auth-token-provider.js +24 -0
- package/dist/src/auth/user-supplied-auth-token-provider.js.map +1 -0
- package/dist/src/certificates.d.ts +6 -0
- package/dist/src/certificates.d.ts.map +1 -0
- package/dist/src/certificates.js +88 -0
- package/dist/src/certificates.js.map +1 -0
- package/dist/src/checksums.d.ts +50 -0
- package/dist/src/checksums.d.ts.map +1 -0
- package/dist/src/checksums.js +32 -0
- package/dist/src/checksums.js.map +1 -0
- package/dist/src/config.d.ts +41 -0
- package/dist/src/config.d.ts.map +1 -0
- package/dist/src/config.js +35 -0
- package/dist/src/config.js.map +1 -0
- package/dist/src/connector.d.ts +101 -0
- package/dist/src/connector.d.ts.map +1 -0
- package/dist/src/connector.js +374 -0
- package/dist/src/connector.js.map +1 -0
- package/dist/src/get-log-event-size.d.ts +3 -0
- package/dist/src/get-log-event-size.d.ts.map +1 -0
- package/dist/src/get-log-event-size.js +9 -0
- package/dist/src/get-log-event-size.js.map +1 -0
- package/dist/src/https-proxy-agent.d.ts +15 -0
- package/dist/src/https-proxy-agent.d.ts.map +1 -0
- package/dist/src/https-proxy-agent.js +31 -0
- package/dist/src/https-proxy-agent.js.map +1 -0
- package/dist/src/index.d.ts +9 -0
- package/dist/src/index.d.ts.map +1 -0
- package/dist/src/index.js +25 -0
- package/dist/src/index.js.map +1 -0
- package/dist/src/logger.d.ts +60 -0
- package/dist/src/logger.d.ts.map +1 -0
- package/dist/src/logger.js +284 -0
- package/dist/src/logger.js.map +1 -0
- package/dist/src/manifest.d.ts +4 -0
- package/dist/src/manifest.d.ts.map +1 -0
- package/dist/src/manifest.js +30 -0
- package/dist/src/manifest.js.map +1 -0
- package/dist/src/metrics.d.ts +59 -0
- package/dist/src/metrics.d.ts.map +1 -0
- package/dist/src/metrics.js +125 -0
- package/dist/src/metrics.js.map +1 -0
- package/dist/src/polling-connector.d.ts +50 -0
- package/dist/src/polling-connector.d.ts.map +1 -0
- package/dist/src/polling-connector.js +169 -0
- package/dist/src/polling-connector.js.map +1 -0
- package/dist/src/schemas.d.ts +77 -0
- package/dist/src/schemas.d.ts.map +1 -0
- package/dist/src/schemas.js +80 -0
- package/dist/src/schemas.js.map +1 -0
- package/dist/src/streamToString.d.ts +3 -0
- package/dist/src/streamToString.d.ts.map +1 -0
- package/dist/src/streamToString.js +25 -0
- package/dist/src/streamToString.js.map +1 -0
- package/dist/src/tdp-client.d.ts +307 -0
- package/dist/src/tdp-client.d.ts.map +1 -0
- package/dist/src/tdp-client.js +823 -0
- package/dist/src/tdp-client.js.map +1 -0
- package/dist/src/to-cloudwatch-log-event.d.ts +4 -0
- package/dist/src/to-cloudwatch-log-event.d.ts.map +1 -0
- package/dist/src/to-cloudwatch-log-event.js +10 -0
- package/dist/src/to-cloudwatch-log-event.js.map +1 -0
- package/dist/src/types.d.ts +57 -0
- package/dist/src/types.d.ts.map +1 -0
- package/dist/src/types.js +30 -0
- package/dist/src/types.js.map +1 -0
- package/dist/src/utils.d.ts +10 -0
- package/dist/src/utils.d.ts.map +1 -0
- package/dist/src/utils.js +20 -0
- package/dist/src/utils.js.map +1 -0
- package/dist/test/api.test.d.ts +2 -0
- package/dist/test/api.test.d.ts.map +1 -0
- package/dist/test/api.test.js +245 -0
- package/dist/test/api.test.js.map +1 -0
- package/dist/test/auth/aws-env-client-provider.test.d.ts +2 -0
- package/dist/test/auth/aws-env-client-provider.test.d.ts.map +1 -0
- package/dist/test/auth/aws-env-client-provider.test.js +56 -0
- package/dist/test/auth/aws-env-client-provider.test.js.map +1 -0
- package/dist/test/auth/aws-refresh-client-provider.test.d.ts +2 -0
- package/dist/test/auth/aws-refresh-client-provider.test.d.ts.map +1 -0
- package/dist/test/auth/aws-refresh-client-provider.test.js +118 -0
- package/dist/test/auth/aws-refresh-client-provider.test.js.map +1 -0
- package/dist/test/auth/aws-secret-auth-token-provider.test.d.ts +2 -0
- package/dist/test/auth/aws-secret-auth-token-provider.test.d.ts.map +1 -0
- package/dist/test/auth/aws-secret-auth-token-provider.test.js +74 -0
- package/dist/test/auth/aws-secret-auth-token-provider.test.js.map +1 -0
- package/dist/test/auth/predefined-auth-token-provider.test.d.ts +2 -0
- package/dist/test/auth/predefined-auth-token-provider.test.d.ts.map +1 -0
- package/dist/test/auth/predefined-auth-token-provider.test.js +24 -0
- package/dist/test/auth/predefined-auth-token-provider.test.js.map +1 -0
- package/dist/test/auth/user-supplied-auth-token-provider.test.d.ts +2 -0
- package/dist/test/auth/user-supplied-auth-token-provider.test.d.ts.map +1 -0
- package/dist/test/auth/user-supplied-auth-token-provider.test.js +24 -0
- package/dist/test/auth/user-supplied-auth-token-provider.test.js.map +1 -0
- package/dist/test/certificates.test.d.ts +2 -0
- package/dist/test/certificates.test.d.ts.map +1 -0
- package/dist/test/certificates.test.js +83 -0
- package/dist/test/certificates.test.js.map +1 -0
- package/dist/test/checksums.test.d.ts +2 -0
- package/dist/test/checksums.test.d.ts.map +1 -0
- package/dist/test/checksums.test.js +29 -0
- package/dist/test/checksums.test.js.map +1 -0
- package/dist/test/connector-shutdown.test.d.ts +2 -0
- package/dist/test/connector-shutdown.test.d.ts.map +1 -0
- package/dist/test/connector-shutdown.test.js +145 -0
- package/dist/test/connector-shutdown.test.js.map +1 -0
- package/dist/test/connector.test.d.ts +2 -0
- package/dist/test/connector.test.d.ts.map +1 -0
- package/dist/test/connector.test.js +286 -0
- package/dist/test/connector.test.js.map +1 -0
- package/dist/test/healthstatus-enum-values.test.d.ts +2 -0
- package/dist/test/healthstatus-enum-values.test.d.ts.map +1 -0
- package/dist/test/healthstatus-enum-values.test.js +18 -0
- package/dist/test/healthstatus-enum-values.test.js.map +1 -0
- package/dist/test/logger.test.d.ts +2 -0
- package/dist/test/logger.test.d.ts.map +1 -0
- package/dist/test/logger.test.js +301 -0
- package/dist/test/logger.test.js.map +1 -0
- package/dist/test/manifest.test.d.ts +2 -0
- package/dist/test/manifest.test.d.ts.map +1 -0
- package/dist/test/manifest.test.js +55 -0
- package/dist/test/manifest.test.js.map +1 -0
- package/dist/test/polling-connector.test.d.ts +2 -0
- package/dist/test/polling-connector.test.d.ts.map +1 -0
- package/dist/test/polling-connector.test.js +170 -0
- package/dist/test/polling-connector.test.js.map +1 -0
- package/dist/test/schemas.test.d.ts +2 -0
- package/dist/test/schemas.test.d.ts.map +1 -0
- package/dist/test/schemas.test.js +211 -0
- package/dist/test/schemas.test.js.map +1 -0
- package/dist/test/tdp-client.test.d.ts +2 -0
- package/dist/test/tdp-client.test.d.ts.map +1 -0
- package/dist/test/tdp-client.test.js +1204 -0
- package/dist/test/tdp-client.test.js.map +1 -0
- package/dist/test/test-connector/index.d.ts +2 -0
- package/dist/test/test-connector/index.d.ts.map +1 -0
- package/dist/test/test-connector/index.js +23 -0
- package/dist/test/test-connector/index.js.map +1 -0
- package/dist/test/test-connector/test-connector.d.ts +7 -0
- package/dist/test/test-connector/test-connector.d.ts.map +1 -0
- package/dist/test/test-connector/test-connector.js +32 -0
- package/dist/test/test-connector/test-connector.js.map +1 -0
- package/dist/test/test-utils/api-mocks.d.ts +6 -0
- package/dist/test/test-utils/api-mocks.d.ts.map +1 -0
- package/dist/test/test-utils/api-mocks.js +19 -0
- package/dist/test/test-utils/api-mocks.js.map +1 -0
- package/dist/test/test-utils/aws-mocks.d.ts +8 -0
- package/dist/test/test-utils/aws-mocks.d.ts.map +1 -0
- package/dist/test/test-utils/aws-mocks.js +39 -0
- package/dist/test/test-utils/aws-mocks.js.map +1 -0
- package/dist/test/test-utils/regex.d.ts +2 -0
- package/dist/test/test-utils/regex.d.ts.map +1 -0
- package/dist/test/test-utils/regex.js +7 -0
- package/dist/test/test-utils/regex.js.map +1 -0
- package/dist/test/utils.test.d.ts +2 -0
- package/dist/test/utils.test.d.ts.map +1 -0
- package/dist/test/utils.test.js +17 -0
- package/dist/test/utils.test.js.map +1 -0
- package/dist/tsconfig.tsbuildinfo +1 -0
- package/dist/vitest.config.d.mts +3 -0
- package/dist/vitest.config.d.mts.map +1 -0
- package/dist/vitest.config.mjs +20 -0
- package/dist/vitest.config.mjs.map +1 -0
- package/package.json +133 -0
|
@@ -0,0 +1,823 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
19
|
+
if (mod && mod.__esModule) return mod;
|
|
20
|
+
var result = {};
|
|
21
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
22
|
+
__setModuleDefault(result, mod);
|
|
23
|
+
return result;
|
|
24
|
+
};
|
|
25
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
26
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
27
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
28
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
29
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
30
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
31
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
32
|
+
});
|
|
33
|
+
};
|
|
34
|
+
var __rest = (this && this.__rest) || function (s, e) {
|
|
35
|
+
var t = {};
|
|
36
|
+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
|
|
37
|
+
t[p] = s[p];
|
|
38
|
+
if (s != null && typeof Object.getOwnPropertySymbols === "function")
|
|
39
|
+
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
|
|
40
|
+
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
|
|
41
|
+
t[p[i]] = s[p[i]];
|
|
42
|
+
}
|
|
43
|
+
return t;
|
|
44
|
+
};
|
|
45
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
46
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
47
|
+
};
|
|
48
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
49
|
+
exports.TDPClient = exports.Directive = void 0;
|
|
50
|
+
exports.sanitizeConfig = sanitizeConfig;
|
|
51
|
+
const fs = __importStar(require("node:fs"));
|
|
52
|
+
const s3 = __importStar(require("@aws-sdk/client-s3"));
|
|
53
|
+
const sqs = __importStar(require("@aws-sdk/client-sqs"));
|
|
54
|
+
const lib_storage_1 = require("@aws-sdk/lib-storage");
|
|
55
|
+
const node_http_handler_1 = require("@smithy/node-http-handler");
|
|
56
|
+
const axios_1 = __importStar(require("axios"));
|
|
57
|
+
const dotenv = __importStar(require("dotenv"));
|
|
58
|
+
const events_1 = __importDefault(require("events"));
|
|
59
|
+
const fsPromises = __importStar(require("fs/promises"));
|
|
60
|
+
const hpagent_1 = require("hpagent");
|
|
61
|
+
const http = __importStar(require("http"));
|
|
62
|
+
const https = __importStar(require("https"));
|
|
63
|
+
const proxy_agent_1 = require("proxy-agent");
|
|
64
|
+
const proxy_from_env_1 = require("proxy-from-env");
|
|
65
|
+
const tls = __importStar(require("tls"));
|
|
66
|
+
const ts_lib_shared_schema_1 = require("ts-lib-shared-schema");
|
|
67
|
+
const uuid_1 = require("uuid");
|
|
68
|
+
const zlib_1 = __importDefault(require("zlib"));
|
|
69
|
+
const zod_1 = require("zod");
|
|
70
|
+
const api_1 = require("./api");
|
|
71
|
+
const certificates_1 = require("./certificates");
|
|
72
|
+
const auth_1 = require("./auth");
|
|
73
|
+
const checksums_1 = require("./checksums");
|
|
74
|
+
const config_1 = require("./config");
|
|
75
|
+
const https_proxy_agent_1 = require("./https-proxy-agent");
|
|
76
|
+
const logger_1 = require("./logger");
|
|
77
|
+
const schemas_1 = require("./schemas");
|
|
78
|
+
const types_1 = require("./types");
|
|
79
|
+
const utils_1 = require("./utils");
|
|
80
|
+
const manifest_1 = require("./manifest");
|
|
81
|
+
const hubProxyPath = '/etc/hub/proxy.env';
|
|
82
|
+
const HP_AGENT = 'hpagent';
|
|
83
|
+
const AWS_SQS_TIMEOUT = 20 * 1000;
|
|
84
|
+
// Key in connector KV store for connector SDK settings
|
|
85
|
+
// The value is expected to be a JSON object
|
|
86
|
+
const TS_SDK_SETTINGS_KEY = 'TS_SDK';
|
|
87
|
+
const TS_SDK_DISABLE_USER_AGENT_HTTP_HEADER = 'TS_SDK_DISABLE_USER_AGENT_HTTP_HEADER';
|
|
88
|
+
const DestinationIdSchema = zod_1.z
|
|
89
|
+
.string()
|
|
90
|
+
.uuid({ message: 'destinationId must be a valid UUID' })
|
|
91
|
+
.refine((id) => id[14] === '4', 'destinationId must be a UUIDv4');
|
|
92
|
+
var Directive;
|
|
93
|
+
(function (Directive) {
|
|
94
|
+
Directive[Directive["Append"] = 0] = "Append";
|
|
95
|
+
Directive[Directive["Replace"] = 1] = "Replace";
|
|
96
|
+
})(Directive || (exports.Directive = Directive = {}));
|
|
97
|
+
const safeAxiosRequestKeys = [
|
|
98
|
+
'url',
|
|
99
|
+
'method',
|
|
100
|
+
'baseURL',
|
|
101
|
+
'baseUrl',
|
|
102
|
+
'params',
|
|
103
|
+
'timeout',
|
|
104
|
+
'withCredentials',
|
|
105
|
+
'responseType',
|
|
106
|
+
'responseEncoding',
|
|
107
|
+
'xsrfCookieName',
|
|
108
|
+
'xsrfHeaderName',
|
|
109
|
+
'maxContentLength',
|
|
110
|
+
'maxBodyLength',
|
|
111
|
+
'maxRedirects',
|
|
112
|
+
'decompress',
|
|
113
|
+
];
|
|
114
|
+
function sanitizeConfig(config) {
|
|
115
|
+
if (!config)
|
|
116
|
+
return config;
|
|
117
|
+
const rval = {};
|
|
118
|
+
for (const key of safeAxiosRequestKeys) {
|
|
119
|
+
if (key in config) {
|
|
120
|
+
rval[key] = config[key];
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
return rval;
|
|
124
|
+
}
|
|
125
|
+
class TDPClient {
|
|
126
|
+
get connector() {
|
|
127
|
+
return this._connector;
|
|
128
|
+
}
|
|
129
|
+
get manifest() {
|
|
130
|
+
if (!this.isInitialized) {
|
|
131
|
+
this.logger.error('Client is not initialized - manifest will be empty');
|
|
132
|
+
}
|
|
133
|
+
return this._manifest;
|
|
134
|
+
}
|
|
135
|
+
constructor(options) {
|
|
136
|
+
this.commands = new events_1.default();
|
|
137
|
+
this.isProxyInitialized = false;
|
|
138
|
+
this.listeningForCommands = false;
|
|
139
|
+
this.config = new config_1.TDPClientConfig(options);
|
|
140
|
+
this.logger = this.createLogger();
|
|
141
|
+
this._certificates = [];
|
|
142
|
+
}
|
|
143
|
+
get isInitialized() {
|
|
144
|
+
var _a;
|
|
145
|
+
return this.jwt && ((_a = this.api) === null || _a === void 0 ? void 0 : _a.v1); // && this.connector;
|
|
146
|
+
}
|
|
147
|
+
get certificates() {
|
|
148
|
+
if (!this.isInitialized) {
|
|
149
|
+
this.logger.error('Client is not initialized - certificate array will be empty');
|
|
150
|
+
}
|
|
151
|
+
return this._certificates;
|
|
152
|
+
}
|
|
153
|
+
setUserAgent(userAgent) {
|
|
154
|
+
var _a;
|
|
155
|
+
this.logger.debug('Setting TDPClient user agent, will be used for all API requests and axios clients created from this point on', {
|
|
156
|
+
userAgent,
|
|
157
|
+
});
|
|
158
|
+
this.userAgent = userAgent;
|
|
159
|
+
(_a = this.api) === null || _a === void 0 ? void 0 : _a.setUserAgent(userAgent);
|
|
160
|
+
}
|
|
161
|
+
assertInitialized() {
|
|
162
|
+
if (!this.isInitialized) {
|
|
163
|
+
throw new Error('Client is not initialized');
|
|
164
|
+
}
|
|
165
|
+
return {
|
|
166
|
+
api: this.api,
|
|
167
|
+
s3Client: this.awsClientProvider.getS3Client(),
|
|
168
|
+
sqsClient: this.awsClientProvider.getSqsClient(),
|
|
169
|
+
authTokenProvider: this.authTokenProvider,
|
|
170
|
+
};
|
|
171
|
+
}
|
|
172
|
+
assertProxyInitialized() {
|
|
173
|
+
if (!this.isProxyInitialized) {
|
|
174
|
+
throw new Error('Proxy settings are not initialized');
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
get apiInstance() {
|
|
178
|
+
return this.assertInitialized().api.v1;
|
|
179
|
+
}
|
|
180
|
+
getAdditionalAxiosHeaders() {
|
|
181
|
+
const headers = new axios_1.AxiosHeaders();
|
|
182
|
+
if (this.userAgent) {
|
|
183
|
+
headers['user-agent'] = this.userAgent;
|
|
184
|
+
}
|
|
185
|
+
return headers;
|
|
186
|
+
}
|
|
187
|
+
/*
|
|
188
|
+
* Creates an axios instance with extra provided certificates, TDP jwt + orgSlug headers.
|
|
189
|
+
* @param tdpEndpoint - The TDP endpoint
|
|
190
|
+
* @param orgSlug - The organization slug
|
|
191
|
+
* @param jwt - The TDP jwt
|
|
192
|
+
* @param certificates - The extra certificates to include
|
|
193
|
+
* @param timeout_ms - The axios http request timeout in milliseconds
|
|
194
|
+
*/
|
|
195
|
+
createAxiosInstanceWithCertificatesAndHeaders(tdpEndpoint, orgSlug, jwt, certificates, timeout_ms) {
|
|
196
|
+
const additionalHeaders = this.getAdditionalAxiosHeaders();
|
|
197
|
+
return axios_1.default.create(Object.assign(Object.assign({}, this.createProxyAgentsForBaseUrl({
|
|
198
|
+
baseUrl: tdpEndpoint,
|
|
199
|
+
rejectUnauthorized: shouldRejectUnauthorized(),
|
|
200
|
+
includeAdditionalCertificates: certificates,
|
|
201
|
+
})), { proxy: false, timeout: timeout_ms !== undefined ? timeout_ms : this.config.httpRequestTimeout, baseURL: tdpEndpoint, headers: Object.assign({ [ts_lib_shared_schema_1.HTTPAuthKeys.scopeToOrgHeaderKey]: orgSlug, [ts_lib_shared_schema_1.HTTPAuthKeys.jwtAuthTokenHeaderKey]: jwt }, additionalHeaders) }));
|
|
202
|
+
}
|
|
203
|
+
/**
|
|
204
|
+
* Creates an axios instance for the given base url, with the given config and rejectUnauthorized, and using
|
|
205
|
+
* the appropriate proxies configured for the connector. TDPClient.init must be called first. baseUrl is required
|
|
206
|
+
* to select the correct proxy, but should otherwise match config.baseUrl.
|
|
207
|
+
* @param options.baseUrl base url for proxy selection when this connector is hosted in a Hub
|
|
208
|
+
* @param options.config axios config
|
|
209
|
+
* @param options.rejectUnauthorized rejectUnauthorized, passed to the underlying http(s) Agent
|
|
210
|
+
* @param options.includeAdditionalCertificates whether to include organization certificates in the http agent
|
|
211
|
+
* @param timeout_ms - The axios http request timeout in milliseconds
|
|
212
|
+
* @returns an Axios instance configured with these settings and with proxying http(s) Agents
|
|
213
|
+
*/
|
|
214
|
+
createAxiosInstance({ baseUrl, config, timeout_ms, rejectUnauthorized = true, includeAdditionalCertificates = true, }) {
|
|
215
|
+
this.assertInitialized();
|
|
216
|
+
this.logger.info('Creating axios instance', { baseUrl, config: sanitizeConfig(config), rejectUnauthorized });
|
|
217
|
+
const headers = this.getAdditionalAxiosHeaders();
|
|
218
|
+
return axios_1.default.create(Object.assign(Object.assign(Object.assign({ baseURL: baseUrl, timeout: timeout_ms !== undefined ? timeout_ms : this.config.httpRequestTimeout }, this.createProxyAgentsForBaseUrl({ baseUrl, rejectUnauthorized, includeAdditionalCertificates })), { proxy: false, headers }), config));
|
|
219
|
+
}
|
|
220
|
+
/**
|
|
221
|
+
* Creates httpAgent and httpsAgent appropriate for proxied connections to the given baseUrl.
|
|
222
|
+
* Reads proxy env vars to determine which proxy, if any, to use for a given url. npm proxy-agent
|
|
223
|
+
* and npm https-proxy-agent do not support rejectUnauthorized, which must be set on the agent level.
|
|
224
|
+
* Until we can fork npm proxy-agent to add this support, we cannot easily support per-request proxy selection
|
|
225
|
+
* like proxy-agent does, so we need the baseUrl up front to select a proxy.
|
|
226
|
+
* If using this with axios, use createAxiosInstance instead, or be sure to specify proxy: false to circumvent
|
|
227
|
+
* a related axios bug.
|
|
228
|
+
* @param options.baseURL The URL that determines which proxy env var (http_proxy, https_proxy, no_proxy) should apply
|
|
229
|
+
* @param options.rejectUnauthorized Whether to inject unauthorized requests in the httpsAgent
|
|
230
|
+
* @param options.includeAdditionalCertificates Whether to include organization certificates in the httpsAgent.
|
|
231
|
+
* If omitted or set falsy: only Node's built-in certificates will be included
|
|
232
|
+
* If set to true, built-in plus org certificates will be included.
|
|
233
|
+
* If set to an array, built-in plus this array of certificates will be included.
|
|
234
|
+
* @returns httpAgent and httpsAgent with proxy, rejectUnauthorized, and includeAdditionalCertificates settings
|
|
235
|
+
*/
|
|
236
|
+
createProxyAgentsForBaseUrl({ baseUrl, rejectUnauthorized = true, includeAdditionalCertificates = true, }) {
|
|
237
|
+
this.assertProxyInitialized();
|
|
238
|
+
this.logger.info('Checking proxy for url', { baseUrl });
|
|
239
|
+
const proxyUrl = (0, proxy_from_env_1.getProxyForUrl)(baseUrl);
|
|
240
|
+
const builtInCertStrings = tls.rootCertificates;
|
|
241
|
+
const orgCertStrings = includeAdditionalCertificates === true ? this.certificates.map((c) => c.content) : [];
|
|
242
|
+
const additionalCertStrings = Array.isArray(includeAdditionalCertificates) ? includeAdditionalCertificates : [];
|
|
243
|
+
const ca = [...builtInCertStrings, ...orgCertStrings, ...additionalCertStrings];
|
|
244
|
+
if (orgCertStrings.length > 0) {
|
|
245
|
+
this.logger.info(`Using ${orgCertStrings.length} organization certificates`, {
|
|
246
|
+
certificates: this.certificates.map((c) => ({ id: c.id, name: c.name })),
|
|
247
|
+
});
|
|
248
|
+
}
|
|
249
|
+
if (additionalCertStrings.length > 0) {
|
|
250
|
+
this.logger.info(`Using ${additionalCertStrings.length} additional certificates`);
|
|
251
|
+
}
|
|
252
|
+
if (proxyUrl) {
|
|
253
|
+
this.logger.info('Creating HttpProxyAgent and HttpsProxyAgent with proxyUrl', {
|
|
254
|
+
rejectUnauthorized,
|
|
255
|
+
includeAdditionalCertificates,
|
|
256
|
+
});
|
|
257
|
+
const httpAgent = new hpagent_1.HttpProxyAgent({ proxy: proxyUrl });
|
|
258
|
+
let httpsAgent;
|
|
259
|
+
if (shouldUseHpAgent()) {
|
|
260
|
+
this.logger.info('Using hpagent for https agent');
|
|
261
|
+
httpsAgent = new hpagent_1.HttpsProxyAgent({
|
|
262
|
+
proxy: proxyUrl,
|
|
263
|
+
proxyRequestOptions: { ca },
|
|
264
|
+
rejectUnauthorized,
|
|
265
|
+
});
|
|
266
|
+
}
|
|
267
|
+
else {
|
|
268
|
+
this.logger.info('Using default https agent');
|
|
269
|
+
httpsAgent = new https_proxy_agent_1.PatchedHttpsProxyAgent(proxyUrl, {
|
|
270
|
+
ca,
|
|
271
|
+
rejectUnauthorized,
|
|
272
|
+
});
|
|
273
|
+
}
|
|
274
|
+
return {
|
|
275
|
+
httpAgent,
|
|
276
|
+
httpsAgent,
|
|
277
|
+
};
|
|
278
|
+
}
|
|
279
|
+
if (rejectUnauthorized !== undefined) {
|
|
280
|
+
this.logger.info('Creating http.Agent and https.Agent with rejectUnauthorized', { rejectUnauthorized });
|
|
281
|
+
return {
|
|
282
|
+
httpAgent: new http.Agent(),
|
|
283
|
+
httpsAgent: new https.Agent({ rejectUnauthorized, ca }),
|
|
284
|
+
};
|
|
285
|
+
}
|
|
286
|
+
this.logger.info('No proxy settings detected, returning undefined');
|
|
287
|
+
return undefined;
|
|
288
|
+
}
|
|
289
|
+
/**
|
|
290
|
+
* Creates a NodeHttpHandler using npm proxy-agent, which will select a correct proxy per request.
|
|
291
|
+
* Only works for connections where rejectUnauthorized or additional certificates are not needed,
|
|
292
|
+
* such as to AWS or trusted servers; if you need to connect to an untrusted server or use organization certificates,
|
|
293
|
+
* use createProxyAgentsForBaseUrl and specify a baseUrl and (optionally) rejectUnauthorized: false.
|
|
294
|
+
* @returns A NodeHttpHandler with agents that will choose a correct proxy for each request.
|
|
295
|
+
*/
|
|
296
|
+
createProxyNodeHttpHandler() {
|
|
297
|
+
this.assertProxyInitialized();
|
|
298
|
+
this.logger.info('Creating NodeHttpHandler');
|
|
299
|
+
return new node_http_handler_1.NodeHttpHandler({
|
|
300
|
+
httpAgent: new proxy_agent_1.ProxyAgent(),
|
|
301
|
+
httpsAgent: new proxy_agent_1.ProxyAgent(),
|
|
302
|
+
});
|
|
303
|
+
}
|
|
304
|
+
createLogger() {
|
|
305
|
+
return new logger_1.Logger({
|
|
306
|
+
writeToCloudwatch: !!process.env.CONNECTOR_TOKEN && process.env.SKIP_CLOUDWATCH !== 'true',
|
|
307
|
+
orgSlug: this.config.orgSlug,
|
|
308
|
+
connectorId: this.config.connectorId,
|
|
309
|
+
metadata: {
|
|
310
|
+
hubId: this.config.hubId,
|
|
311
|
+
},
|
|
312
|
+
});
|
|
313
|
+
}
|
|
314
|
+
init() {
|
|
315
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
316
|
+
yield this.loadProxySettingsToEnv();
|
|
317
|
+
if (process.env.CONNECTOR_TOKEN) {
|
|
318
|
+
const localTdpCertificates = yield (0, certificates_1.loadCertificatesFromLocalVolume)(this.config, this.logger);
|
|
319
|
+
const axiosClientWithLocalCertificates = this.createAxiosInstanceWithCertificatesAndHeaders(this.config.tdpEndpoint, this.config.orgSlug, process.env.CONNECTOR_TOKEN, localTdpCertificates);
|
|
320
|
+
this.awsClientProvider = new auth_1.AwsRefreshClientProvider(this.createProxyNodeHttpHandler(), axiosClientWithLocalCertificates, this.config.awsRegion, this.config.connectorId, this.logger);
|
|
321
|
+
this.authTokenProvider = new auth_1.UserSuppliedAuthTokenProvider(process.env.CONNECTOR_TOKEN);
|
|
322
|
+
if (!process.env.SKIP_CLOUDWATCH) {
|
|
323
|
+
yield this.logger.startCloudwatch(this.awsClientProvider.getCloudwatchLogsClient());
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
else {
|
|
327
|
+
this.awsClientProvider = new auth_1.AwsEnvClientProvider(this.config.awsRegion, this.createProxyNodeHttpHandler());
|
|
328
|
+
this.authTokenProvider =
|
|
329
|
+
this.config.authTokenProvider ||
|
|
330
|
+
new auth_1.AwsSecretAuthTokenProvider(this.awsClientProvider.getSsmClient(), this.config.jwtTokenParameter);
|
|
331
|
+
}
|
|
332
|
+
this.logger.info(`Retrieving auth token`, {
|
|
333
|
+
jwtTokenParameter: this.config.jwtTokenParameter,
|
|
334
|
+
hasEnvToken: !!process.env.CONNECTOR_TOKEN,
|
|
335
|
+
});
|
|
336
|
+
const authToken = yield this.authTokenProvider.getAuthToken();
|
|
337
|
+
this.logger.info('Retrieved auth token');
|
|
338
|
+
this.jwt = authToken.value;
|
|
339
|
+
const tdpCertificates = yield (0, certificates_1.loadTdpCertificates)(this.awsClientProvider.getS3Client(), this.logger, this.config);
|
|
340
|
+
this.api = new api_1.Api(this.config, this.createAxiosInstanceWithCertificatesAndHeaders(this.config.tdpEndpoint, this.config.orgSlug, this.jwt, tdpCertificates), this.logger);
|
|
341
|
+
const requestId = (0, uuid_1.v4)();
|
|
342
|
+
const options = { requestId };
|
|
343
|
+
try {
|
|
344
|
+
this._certificates = yield this.getCertificates(options);
|
|
345
|
+
this.logger.info(`Loaded ${this._certificates.length} organization certificates`, {
|
|
346
|
+
certificates: this._certificates.map((c) => ({ id: c.id, name: c.name })),
|
|
347
|
+
requestId,
|
|
348
|
+
});
|
|
349
|
+
}
|
|
350
|
+
catch (ex) {
|
|
351
|
+
this.logger.error('Error loading organization certificates. Initialization will continue, but untrusted SSL connections will fail.', ex, requestId);
|
|
352
|
+
}
|
|
353
|
+
yield this.loadConnectorManifest();
|
|
354
|
+
yield this.reloadConnector(options);
|
|
355
|
+
this.logger.info('TDPClient.init complete');
|
|
356
|
+
});
|
|
357
|
+
}
|
|
358
|
+
loadConnectorManifest() {
|
|
359
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
360
|
+
try {
|
|
361
|
+
this._manifest = yield (0, manifest_1.getConnectorManifest)(this.config.manifestFile, this.logger);
|
|
362
|
+
}
|
|
363
|
+
catch (err) {
|
|
364
|
+
this.logger.error('Error loading connector manifest', err);
|
|
365
|
+
this._manifest = null;
|
|
366
|
+
}
|
|
367
|
+
});
|
|
368
|
+
}
|
|
369
|
+
loadProxySettingsToEnv() {
|
|
370
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
371
|
+
this.logger.info('Loading proxy settings from Hub');
|
|
372
|
+
try {
|
|
373
|
+
// dotenv will silently no-op if the file doesn't exist or isn't readable, so we check here for better logging
|
|
374
|
+
yield fsPromises.access(hubProxyPath, fs.constants.R_OK);
|
|
375
|
+
// Axios only supports no_proxy via environment, not via explicit configuration.
|
|
376
|
+
// So we just use environment for everything.
|
|
377
|
+
dotenv.config({ path: hubProxyPath });
|
|
378
|
+
// Log whether settings exist, but don't log them, they may contain auth information
|
|
379
|
+
this.logger.info('Loaded proxy settings from Hub', {
|
|
380
|
+
isNoProxySet: !!process.env.no_proxy,
|
|
381
|
+
isHttpProxySet: !!process.env.http_proxy,
|
|
382
|
+
isHttpsProxySet: !!process.env.https_proxy,
|
|
383
|
+
});
|
|
384
|
+
this.isProxyInitialized = true;
|
|
385
|
+
}
|
|
386
|
+
catch (ex) {
|
|
387
|
+
if (ex.code === 'ENOENT') {
|
|
388
|
+
this.logger.info('No Hub env proxy file found', { hubProxyPath });
|
|
389
|
+
this.isProxyInitialized = true;
|
|
390
|
+
if (process.env.NO_PROXY && !process.env.no_proxy) {
|
|
391
|
+
this.logger.info('Setting no_proxy from NO_PROXY');
|
|
392
|
+
process.env.no_proxy = process.env.NO_PROXY;
|
|
393
|
+
}
|
|
394
|
+
if (process.env.HTTP_PROXY && !process.env.http_proxy) {
|
|
395
|
+
this.logger.info('Setting http_proxy from HTTP_PROXY');
|
|
396
|
+
process.env.http_proxy = process.env.HTTP_PROXY;
|
|
397
|
+
}
|
|
398
|
+
if (process.env.HTTPS_PROXY && !process.env.https_proxy) {
|
|
399
|
+
this.logger.info('Setting https_proxy from HTTPS_PROXY');
|
|
400
|
+
process.env.https_proxy = process.env.HTTPS_PROXY;
|
|
401
|
+
}
|
|
402
|
+
this.logger.info('Environment proxy settings', {
|
|
403
|
+
isNoProxySet: !!process.env.no_proxy,
|
|
404
|
+
isHttpProxySet: !!process.env.http_proxy,
|
|
405
|
+
isHttpsProxySet: !!process.env.https_proxy,
|
|
406
|
+
});
|
|
407
|
+
return;
|
|
408
|
+
}
|
|
409
|
+
this.logger.error('Error reading proxy env file', ex);
|
|
410
|
+
throw ex;
|
|
411
|
+
}
|
|
412
|
+
});
|
|
413
|
+
}
|
|
414
|
+
startCommandsListener() {
|
|
415
|
+
this.logger.info('Starting commands listener');
|
|
416
|
+
this.listeningForCommands = true;
|
|
417
|
+
setImmediate(() => __awaiter(this, void 0, void 0, function* () {
|
|
418
|
+
while (this.listeningForCommands) {
|
|
419
|
+
try {
|
|
420
|
+
const message = yield this.waitForCommandMessage();
|
|
421
|
+
if (message) {
|
|
422
|
+
yield this.handleCommandSqsMessages(message);
|
|
423
|
+
}
|
|
424
|
+
}
|
|
425
|
+
catch (err) {
|
|
426
|
+
this.logger.error('Error handling command', err);
|
|
427
|
+
}
|
|
428
|
+
}
|
|
429
|
+
}));
|
|
430
|
+
}
|
|
431
|
+
stopCommandsListener() {
|
|
432
|
+
this.logger.info('Stopping commands listener');
|
|
433
|
+
this.listeningForCommands = false;
|
|
434
|
+
}
|
|
435
|
+
waitForCommandMessage() {
|
|
436
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
437
|
+
const waitTimeSeconds = 20;
|
|
438
|
+
const { Messages = [] } = yield this.assertInitialized().sqsClient.send(new sqs.ReceiveMessageCommand({
|
|
439
|
+
QueueUrl: this._connector.commandQueue,
|
|
440
|
+
MaxNumberOfMessages: 1,
|
|
441
|
+
WaitTimeSeconds: waitTimeSeconds,
|
|
442
|
+
}), {
|
|
443
|
+
abortSignal: AbortSignal.timeout(waitTimeSeconds + AWS_SQS_TIMEOUT),
|
|
444
|
+
});
|
|
445
|
+
return Messages.length > 0 ? Messages[0] : null;
|
|
446
|
+
});
|
|
447
|
+
}
|
|
448
|
+
handleCommandSqsMessages(message) {
|
|
449
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
450
|
+
this.logger.info('Handling command message', { messageId: message.MessageId });
|
|
451
|
+
const { Body, ReceiptHandle } = message;
|
|
452
|
+
const messageBody = JSON.parse(Body);
|
|
453
|
+
const expiresAt = new Date(messageBody.expiresAt);
|
|
454
|
+
if (expiresAt < new Date()) {
|
|
455
|
+
this.logger.info('Command expiry date passed, rejecting', {
|
|
456
|
+
messageId: message.MessageId,
|
|
457
|
+
action: messageBody.action,
|
|
458
|
+
expiresAt,
|
|
459
|
+
});
|
|
460
|
+
yield this.sendCommandResponse(Object.assign(Object.assign({}, messageBody), { status: types_1.CommandStatus.REJECTED, body: {
|
|
461
|
+
reason: `Command expiry date [${expiresAt.toISOString()}] is passed`,
|
|
462
|
+
} }));
|
|
463
|
+
}
|
|
464
|
+
else {
|
|
465
|
+
this.logger.info('Marking command processing', {
|
|
466
|
+
messageId: message.MessageId,
|
|
467
|
+
action: messageBody.action,
|
|
468
|
+
});
|
|
469
|
+
yield this.sendCommandResponse(Object.assign(Object.assign({}, messageBody), { status: types_1.CommandStatus.PROCESSING }));
|
|
470
|
+
if (messageBody.bodyDelivery === types_1.PayloadDelivery.REFERENCED && messageBody.bodyUrl) {
|
|
471
|
+
this.logger.info('Command body is referenced, downloading', { messageId: message.MessageId });
|
|
472
|
+
messageBody.body = yield this.downloadContent(messageBody.bodyUrl);
|
|
473
|
+
}
|
|
474
|
+
this.logger.info('Emitting command events', {
|
|
475
|
+
messageId: message.MessageId,
|
|
476
|
+
action: messageBody.action,
|
|
477
|
+
});
|
|
478
|
+
this.commands.emit('command', messageBody);
|
|
479
|
+
this.commands.emit(messageBody.action, messageBody);
|
|
480
|
+
}
|
|
481
|
+
this.logger.info('Deleting SQS message', { messageId: message.MessageId });
|
|
482
|
+
yield this.assertInitialized().sqsClient.send(new sqs.DeleteMessageCommand({
|
|
483
|
+
QueueUrl: this._connector.commandQueue,
|
|
484
|
+
ReceiptHandle,
|
|
485
|
+
}), { abortSignal: AbortSignal.timeout(AWS_SQS_TIMEOUT) });
|
|
486
|
+
this.logger.info('Deleted SQS message', { messageId: message.MessageId });
|
|
487
|
+
});
|
|
488
|
+
}
|
|
489
|
+
downloadContent(url) {
|
|
490
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
491
|
+
const { baseUrl, remainingPart } = (0, utils_1.splitUrl)(url);
|
|
492
|
+
const axios = this.createAxiosInstance({ baseUrl });
|
|
493
|
+
const { data } = yield axios.get(remainingPart);
|
|
494
|
+
return data;
|
|
495
|
+
});
|
|
496
|
+
}
|
|
497
|
+
/**
|
|
498
|
+
* Send a command response to the TDP
|
|
499
|
+
* @param command - The command response to send
|
|
500
|
+
* @param command.commandId - The command ID
|
|
501
|
+
* @param command.targetId - The target ID (connector ID)
|
|
502
|
+
* @param command.status - The status of the command
|
|
503
|
+
* @param command.body - The body of the command
|
|
504
|
+
* @param command.responseBodyUploadUrl - The URL to upload the response body to.
|
|
505
|
+
* Should be passed over from the command request
|
|
506
|
+
*/
|
|
507
|
+
sendCommandResponse(command) {
|
|
508
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
509
|
+
this.logger.info('Sending command response', {
|
|
510
|
+
commandId: command.commandId,
|
|
511
|
+
});
|
|
512
|
+
const { commandId, targetId, status, body } = command;
|
|
513
|
+
const messageBody = {
|
|
514
|
+
commandId,
|
|
515
|
+
targetId,
|
|
516
|
+
status,
|
|
517
|
+
body,
|
|
518
|
+
responseBodyDelivery: types_1.PayloadDelivery.EMBEDDED,
|
|
519
|
+
createdAt: new Date().toISOString(),
|
|
520
|
+
};
|
|
521
|
+
if (this.shouldDeliverCommandPayloadViaUpload(command)) {
|
|
522
|
+
this.logger.info('Uploading command response body', { commandId: command.commandId });
|
|
523
|
+
yield this.uploadCommandResponseBody(command.responseBodyUploadUrl, command.body);
|
|
524
|
+
messageBody.responseBodyDelivery = types_1.PayloadDelivery.REFERENCED;
|
|
525
|
+
messageBody.body = undefined;
|
|
526
|
+
}
|
|
527
|
+
this.assertInitialized().sqsClient.send(new sqs.SendMessageCommand({
|
|
528
|
+
QueueUrl: this.config.outboundCommandQueue,
|
|
529
|
+
MessageBody: JSON.stringify(messageBody),
|
|
530
|
+
}), { abortSignal: AbortSignal.timeout(AWS_SQS_TIMEOUT) });
|
|
531
|
+
this.logger.info('Sent command response', { commandId: command.commandId });
|
|
532
|
+
});
|
|
533
|
+
}
|
|
534
|
+
shouldDeliverCommandPayloadViaUpload(command) {
|
|
535
|
+
if (!command.responseBodyUploadUrl || !command.body) {
|
|
536
|
+
return false;
|
|
537
|
+
}
|
|
538
|
+
const { commandId, targetId, status, body } = command;
|
|
539
|
+
const messageBody = {
|
|
540
|
+
commandId,
|
|
541
|
+
targetId,
|
|
542
|
+
status,
|
|
543
|
+
body,
|
|
544
|
+
responseBodyDelivery: types_1.PayloadDelivery.EMBEDDED,
|
|
545
|
+
createdAt: new Date().toISOString(),
|
|
546
|
+
};
|
|
547
|
+
const messageSize = Buffer.byteLength(JSON.stringify(messageBody), 'utf8');
|
|
548
|
+
const maxEmbeddedMessageSize = 256 * 1024;
|
|
549
|
+
return messageSize > maxEmbeddedMessageSize;
|
|
550
|
+
}
|
|
551
|
+
uploadCommandResponseBody(uploadUrl, responseBody) {
|
|
552
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
553
|
+
const { baseUrl, remainingPart } = (0, utils_1.splitUrl)(uploadUrl);
|
|
554
|
+
const axios = this.createAxiosInstance({ baseUrl });
|
|
555
|
+
const bodyString = JSON.stringify(responseBody);
|
|
556
|
+
const compressedBodyString = zlib_1.default.gzipSync(Buffer.from(bodyString));
|
|
557
|
+
yield axios.put(remainingPart, compressedBodyString, {
|
|
558
|
+
headers: {
|
|
559
|
+
'Content-Type': 'application/json',
|
|
560
|
+
'Content-Encoding': 'gzip',
|
|
561
|
+
},
|
|
562
|
+
});
|
|
563
|
+
});
|
|
564
|
+
}
|
|
565
|
+
getCertificates(options) {
|
|
566
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
567
|
+
return this.apiInstance.getCertificates(options);
|
|
568
|
+
});
|
|
569
|
+
}
|
|
570
|
+
getConfig(_a, options_1) {
|
|
571
|
+
return __awaiter(this, arguments, void 0, function* ({ version }, options) {
|
|
572
|
+
return this.apiInstance.getConnectorConfig(this.config.connectorId, { version }, options);
|
|
573
|
+
});
|
|
574
|
+
}
|
|
575
|
+
getConnector() {
|
|
576
|
+
return __awaiter(this, arguments, void 0, function* ({ resolveSecrets, include } = {}, options) {
|
|
577
|
+
return this.apiInstance.getConnectorById(this.config.connectorId, { resolveSecrets, include }, options);
|
|
578
|
+
});
|
|
579
|
+
}
|
|
580
|
+
reloadConnector(options) {
|
|
581
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
582
|
+
this._connector = yield this.getConnector({
|
|
583
|
+
resolveSecrets: true,
|
|
584
|
+
include: ['config', 'artifact'],
|
|
585
|
+
}, options);
|
|
586
|
+
yield this.configureUserAgent();
|
|
587
|
+
});
|
|
588
|
+
}
|
|
589
|
+
hasUserAgentSetToDisabled() {
|
|
590
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
591
|
+
let value = undefined;
|
|
592
|
+
try {
|
|
593
|
+
value = yield this.getValue(TS_SDK_SETTINGS_KEY);
|
|
594
|
+
}
|
|
595
|
+
catch (err) {
|
|
596
|
+
this.logger.error('Error getting connector value for user agent', err);
|
|
597
|
+
}
|
|
598
|
+
if (value === undefined) {
|
|
599
|
+
return false;
|
|
600
|
+
}
|
|
601
|
+
const disableUserAgent = value[TS_SDK_DISABLE_USER_AGENT_HTTP_HEADER];
|
|
602
|
+
return disableUserAgent === true;
|
|
603
|
+
});
|
|
604
|
+
}
|
|
605
|
+
configureUserAgent() {
|
|
606
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
607
|
+
const disabledUserAgent = yield this.hasUserAgentSetToDisabled();
|
|
608
|
+
if (disabledUserAgent === true) {
|
|
609
|
+
this.logger.info('User-Agent header is disabled');
|
|
610
|
+
return;
|
|
611
|
+
}
|
|
612
|
+
let userAgent = 'PluggableConnector';
|
|
613
|
+
const manifest = this._manifest;
|
|
614
|
+
if (manifest) {
|
|
615
|
+
this.logger.debug('Configuring user agent using artifact details from manifest');
|
|
616
|
+
const version = manifest.version.startsWith('v') ? manifest.version : `v${manifest.version}`;
|
|
617
|
+
userAgent += ` ${manifest.slug} ${version}`;
|
|
618
|
+
}
|
|
619
|
+
else {
|
|
620
|
+
this.logger.debug('Manifest not found, using default user agent');
|
|
621
|
+
userAgent += ` ${this.constructor.name}`;
|
|
622
|
+
}
|
|
623
|
+
this.setUserAgent(userAgent);
|
|
624
|
+
});
|
|
625
|
+
}
|
|
626
|
+
getValue(key, options) {
|
|
627
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
628
|
+
const [value] = yield this.getValues([key], options);
|
|
629
|
+
return value;
|
|
630
|
+
});
|
|
631
|
+
}
|
|
632
|
+
getValues(...args) {
|
|
633
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
634
|
+
let options;
|
|
635
|
+
let keys;
|
|
636
|
+
if (Array.isArray(args[0])) {
|
|
637
|
+
keys = args[0];
|
|
638
|
+
options = args[1];
|
|
639
|
+
}
|
|
640
|
+
else {
|
|
641
|
+
options = { requestId: undefined };
|
|
642
|
+
keys = args;
|
|
643
|
+
}
|
|
644
|
+
const { values } = yield this.apiInstance.getConnectorData(this.config.connectorId, { keys }, options);
|
|
645
|
+
return values.map(({ value }) => value);
|
|
646
|
+
});
|
|
647
|
+
}
|
|
648
|
+
saveValue(key, value, options) {
|
|
649
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
650
|
+
const _a = options || {}, { requestId } = _a, requestOptions = __rest(_a, ["requestId"]);
|
|
651
|
+
const [{ value: savedValue }] = yield this.saveValues([Object.assign({ key, value }, requestOptions)], { requestId });
|
|
652
|
+
return savedValue;
|
|
653
|
+
});
|
|
654
|
+
}
|
|
655
|
+
saveValues(values, options) {
|
|
656
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
657
|
+
const { values: savedValues } = yield this.apiInstance.saveConnectorData(this.config.connectorId, { values }, options);
|
|
658
|
+
return savedValues;
|
|
659
|
+
});
|
|
660
|
+
}
|
|
661
|
+
getFiles(query, options) {
|
|
662
|
+
return this.apiInstance.getConnectorFiles(this.config.connectorId, query, options);
|
|
663
|
+
}
|
|
664
|
+
saveFile(file) {
|
|
665
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
666
|
+
var _a;
|
|
667
|
+
const { files, failures } = yield this.saveFiles([file]);
|
|
668
|
+
if (failures.length > 0) {
|
|
669
|
+
const failure = failures === null || failures === void 0 ? void 0 : failures[0];
|
|
670
|
+
this.logger.error('File save failed', {
|
|
671
|
+
fileId: file.id,
|
|
672
|
+
uniqueExternalId: file.uniqueExternalId,
|
|
673
|
+
failure,
|
|
674
|
+
});
|
|
675
|
+
throw new Error((_a = failure === null || failure === void 0 ? void 0 : failure.message) !== null && _a !== void 0 ? _a : 'File save failed');
|
|
676
|
+
}
|
|
677
|
+
return files === null || files === void 0 ? void 0 : files[0];
|
|
678
|
+
});
|
|
679
|
+
}
|
|
680
|
+
saveFiles(files, options) {
|
|
681
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
682
|
+
return this.apiInstance.updateConnectorFiles(this.config.connectorId, { files }, options);
|
|
683
|
+
});
|
|
684
|
+
}
|
|
685
|
+
reportMetrics(metrics, options) {
|
|
686
|
+
return this.apiInstance.reportMetrics(this.config.connectorId, { metrics }, options);
|
|
687
|
+
}
|
|
688
|
+
reportHealthStatus(request, options) {
|
|
689
|
+
return this.apiInstance.health(this.config.connectorId, request, options);
|
|
690
|
+
}
|
|
691
|
+
heartbeat(options) {
|
|
692
|
+
return this.apiInstance.heartbeat(this.config.connectorId, options);
|
|
693
|
+
}
|
|
694
|
+
/**
|
|
695
|
+
* Determine PartSize for Upload based on object size
|
|
696
|
+
*
|
|
697
|
+
* @param objectSize size in bytes of object to upload
|
|
698
|
+
*/
|
|
699
|
+
calculatePartSize(objectSize) {
|
|
700
|
+
const DEFAULT_PART_SIZE = 1024 * 1024 * 5; // AWS lower limit
|
|
701
|
+
const AWS_MAX_PARTS = 10000;
|
|
702
|
+
if (!objectSize) {
|
|
703
|
+
return DEFAULT_PART_SIZE;
|
|
704
|
+
}
|
|
705
|
+
else {
|
|
706
|
+
// inflate object size by a byte to avoid possible annoying boundary
|
|
707
|
+
// issues
|
|
708
|
+
return Math.max(DEFAULT_PART_SIZE, Math.ceil((objectSize + 1) / AWS_MAX_PARTS));
|
|
709
|
+
}
|
|
710
|
+
}
|
|
711
|
+
/**
|
|
712
|
+
* Uploads a file to the TDP datalake
|
|
713
|
+
|
|
714
|
+
* @param {UploadFileRequest} request - The upload file request
|
|
715
|
+
* @param {boolean} [strictMtlValidation=false] - Whether to throw an error if the request MTL is invalid.
|
|
716
|
+
* If false, will just log a warning.
|
|
717
|
+
* @returns {Promise<UploadFileResponse>} - Uploaded file bucket, key, version, and id
|
|
718
|
+
* @throws {Error} - If the client is not initialized
|
|
719
|
+
* @throws {Error} - If the request has invalid MTL and strictMtlValidation is true
|
|
720
|
+
*/
|
|
721
|
+
uploadFile(request_1) {
|
|
722
|
+
return __awaiter(this, arguments, void 0, function* (request, strictMtlValidation = false) {
|
|
723
|
+
var _a, _b, _c, _d, _e;
|
|
724
|
+
if (!this.isInitialized) {
|
|
725
|
+
throw new Error('Client is not initialized');
|
|
726
|
+
}
|
|
727
|
+
try {
|
|
728
|
+
request = (0, schemas_1.validateUploadFileRequestAndThrowFriendlyError)(request);
|
|
729
|
+
}
|
|
730
|
+
catch (ex) {
|
|
731
|
+
if (strictMtlValidation) {
|
|
732
|
+
this.logger.error('Invalid MTL on upload file request', ex);
|
|
733
|
+
throw ex;
|
|
734
|
+
}
|
|
735
|
+
else {
|
|
736
|
+
this.logger.warn('Invalid MTL on upload file request', ex);
|
|
737
|
+
}
|
|
738
|
+
}
|
|
739
|
+
if (request.destinationId != null) {
|
|
740
|
+
// will throw with error message if destinationId invalid
|
|
741
|
+
DestinationIdSchema.parse(request.destinationId);
|
|
742
|
+
}
|
|
743
|
+
const { orgSlug, connectorId, datalakeBucket } = this.config;
|
|
744
|
+
const idForKey = (_a = request.destinationId) !== null && _a !== void 0 ? _a : connectorId;
|
|
745
|
+
const fileId = request.fileId || (0, uuid_1.v4)();
|
|
746
|
+
const traceId = request.traceId || fileId;
|
|
747
|
+
const key = this.buildS3Key(orgSlug, idForKey, ts_lib_shared_schema_1.FileCategories.RAW, request.filepath);
|
|
748
|
+
this.logger.debug('Uploading file', {
|
|
749
|
+
fileId,
|
|
750
|
+
traceId,
|
|
751
|
+
key,
|
|
752
|
+
});
|
|
753
|
+
const customMetadata = request.metadataDirective === Directive.Replace
|
|
754
|
+
? request.metadata || {}
|
|
755
|
+
: Object.assign(Object.assign({}, this._connector.metadata), request.metadata);
|
|
756
|
+
const customTags = request.tagsDirective === Directive.Replace
|
|
757
|
+
? request.tags || []
|
|
758
|
+
: [...(this._connector.tags || []), ...(request.tags || [])];
|
|
759
|
+
const parameterChecksums = (_b = request.checksums) !== null && _b !== void 0 ? _b : {};
|
|
760
|
+
const metadataChecksums = (0, checksums_1.mapChecksumData)(parameterChecksums);
|
|
761
|
+
const awsChecksums = {
|
|
762
|
+
ChecksumAlgorithm: parameterChecksums.s3AdditionalChecksum || s3.ChecksumAlgorithm.SHA256,
|
|
763
|
+
};
|
|
764
|
+
const artifact = this._connector.artifact;
|
|
765
|
+
const connectorSlug = artifact.slug;
|
|
766
|
+
const hostType = (_c = this._connector) === null || _c === void 0 ? void 0 : _c.hostType;
|
|
767
|
+
const isHubConnector = hostType === api_1.ConnectorHostType.HUB;
|
|
768
|
+
const integrationType = isHubConnector ? ts_lib_shared_schema_1.IntegrationTypes.HUB : ts_lib_shared_schema_1.IntegrationTypes.API;
|
|
769
|
+
const integrationId = isHubConnector ? (_d = this._connector) === null || _d === void 0 ? void 0 : _d.hub.id : ts_lib_shared_schema_1.Constants.API_UPLOAD_V1_INTEGRATION_ID;
|
|
770
|
+
const trace = request.trace || {};
|
|
771
|
+
const traceMetadata = this.transformTraceMetadata(trace);
|
|
772
|
+
if (request.labels && request.labels.length) {
|
|
773
|
+
const labelKey = this.buildS3Key(orgSlug, idForKey, ts_lib_shared_schema_1.FileCategories.TMP, `${request.filepath}/${fileId}.labels`);
|
|
774
|
+
const labelFile = JSON.stringify(request.labels);
|
|
775
|
+
yield this.assertInitialized().s3Client.send(new s3.PutObjectCommand(Object.assign({ Bucket: datalakeBucket, Key: labelKey, Body: labelFile, ServerSideEncryption: 'aws:kms', SSEKMSKeyId: this.config.kmsKeyId }, awsChecksums)));
|
|
776
|
+
}
|
|
777
|
+
const upload = new lib_storage_1.Upload({
|
|
778
|
+
client: this.assertInitialized().s3Client,
|
|
779
|
+
params: Object.assign(Object.assign(Object.assign(Object.assign({ Bucket: datalakeBucket, Key: key, Body: request.content, ServerSideEncryption: 'aws:kms', SSEKMSKeyId: this.config.kmsKeyId }, awsChecksums), (request.contentType ? { ContentType: request.contentType } : {})), (request.contentEncoding ? { ContentEncoding: request.contentEncoding } : {})), { Metadata: Object.assign(Object.assign(Object.assign(Object.assign({}, metadataChecksums), traceMetadata), { [ts_lib_shared_schema_1.S3MetadataFields.FILE_ID]: fileId, [ts_lib_shared_schema_1.S3MetadataFields.TRACE_ID]: traceId, [ts_lib_shared_schema_1.S3MetadataFields.INTEGRATION_TYPE]: integrationType, [ts_lib_shared_schema_1.S3MetadataFields.INTEGRATION_ID]: integrationId, [ts_lib_shared_schema_1.S3MetadataFields.CONNECTOR_NAMESPACE]: artifact.namespace, [ts_lib_shared_schema_1.S3MetadataFields.CONNECTOR_SLUG]: connectorSlug, [ts_lib_shared_schema_1.S3MetadataFields.CONNECTOR_VERSION]: artifact.version, [ts_lib_shared_schema_1.S3MetadataFields.CUSTOM_METADATA]: new URLSearchParams(customMetadata).toString(), [ts_lib_shared_schema_1.S3MetadataFields.CUSTOM_TAGS]: (0, utils_1.unique)(customTags).join(','), [ts_lib_shared_schema_1.S3MetadataFields.SOURCE_ID]: connectorId, [ts_lib_shared_schema_1.S3MetadataFields.SOURCE_NAME]: (_e = this._connector) === null || _e === void 0 ? void 0 : _e.name, [ts_lib_shared_schema_1.S3MetadataFields.SOURCE_TYPE]: request.sourceType || artifact.sourceType || ts_lib_shared_schema_1.SourceTypes.UNKNOWN, [ts_lib_shared_schema_1.S3MetadataFields.DO_NOT_INHERIT_LABELS]: request.labelsDirective === Directive.Replace ? utils_1.Bool.True : utils_1.Bool.False }), (request.destinationId ? { [ts_lib_shared_schema_1.S3MetadataFields.DESTINATION_ID]: request.destinationId } : {})) }),
|
|
780
|
+
partSize: this.calculatePartSize(request.objectSize),
|
|
781
|
+
abortController: request.abortController,
|
|
782
|
+
});
|
|
783
|
+
const { VersionId: versionId } = yield upload.done();
|
|
784
|
+
this.logger.debug('Uploaded file', {
|
|
785
|
+
fileId,
|
|
786
|
+
traceId,
|
|
787
|
+
key,
|
|
788
|
+
versionId,
|
|
789
|
+
});
|
|
790
|
+
return {
|
|
791
|
+
fileId,
|
|
792
|
+
bucket: datalakeBucket,
|
|
793
|
+
key,
|
|
794
|
+
versionId: versionId,
|
|
795
|
+
};
|
|
796
|
+
});
|
|
797
|
+
}
|
|
798
|
+
/**
|
|
799
|
+
* Transforms the metadata fields of a trace to include the "ts_" prefix
|
|
800
|
+
* @example
|
|
801
|
+
* // returns { ts_field1: 'value1', ts_field2: 'value2' }
|
|
802
|
+
* transformTraceMetadata({ field1: 'value1', field2: 'value2' })
|
|
803
|
+
*
|
|
804
|
+
* @param {Trace} trace - The trace object to be transformed
|
|
805
|
+
* @returns {object} - An object with transformed trace metadata.
|
|
806
|
+
*/
|
|
807
|
+
transformTraceMetadata(trace) {
|
|
808
|
+
return Object.keys(trace).reduce((meta, field) => (Object.assign(Object.assign({}, meta), { [`ts_${field}`]: trace[field] })), {});
|
|
809
|
+
}
|
|
810
|
+
buildS3Key(orgSlug, idForKey, category, filepath) {
|
|
811
|
+
const prefix = `${orgSlug}/${idForKey}/${category}`;
|
|
812
|
+
return filepath.startsWith('/') ? prefix + filepath : `${prefix}/${filepath}`;
|
|
813
|
+
}
|
|
814
|
+
}
|
|
815
|
+
exports.TDPClient = TDPClient;
|
|
816
|
+
const shouldUseHpAgent = () => process.env.HTTPS_AGENT === HP_AGENT;
|
|
817
|
+
const shouldRejectUnauthorized = () => {
|
|
818
|
+
if (process.env.NODE_TLS_REJECT_UNAUTHORIZED === undefined) {
|
|
819
|
+
return true;
|
|
820
|
+
}
|
|
821
|
+
return !['false', '0'].includes(process.env.NODE_TLS_REJECT_UNAUTHORIZED);
|
|
822
|
+
};
|
|
823
|
+
//# sourceMappingURL=tdp-client.js.map
|