@tdengine/websocket 3.2.2 → 3.3.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/lib/package.json +64 -0
- package/lib/src/client/retryConfig.d.ts +10 -0
- package/lib/src/client/retryConfig.d.ts.map +1 -0
- package/lib/src/client/retryConfig.js +46 -0
- package/lib/src/client/wsClient.d.ts +24 -7
- package/lib/src/client/wsClient.d.ts.map +1 -1
- package/lib/src/client/wsClient.js +164 -137
- package/lib/src/client/wsConnector.d.ts +55 -9
- package/lib/src/client/wsConnector.d.ts.map +1 -1
- package/lib/src/client/wsConnector.js +522 -102
- package/lib/src/client/wsConnectorPool.d.ts +5 -1
- package/lib/src/client/wsConnectorPool.d.ts.map +1 -1
- package/lib/src/client/wsConnectorPool.js +67 -52
- package/lib/src/client/wsEventCallback.d.ts +3 -0
- package/lib/src/client/wsEventCallback.d.ts.map +1 -1
- package/lib/src/client/wsEventCallback.js +67 -8
- package/lib/src/client/wsResponse.d.ts +0 -3
- package/lib/src/client/wsResponse.d.ts.map +1 -1
- package/lib/src/client/wsResponse.js +0 -3
- package/lib/src/common/addressConnectionTracker.d.ts +11 -0
- package/lib/src/common/addressConnectionTracker.d.ts.map +1 -0
- package/lib/src/common/addressConnectionTracker.js +53 -0
- package/lib/src/common/config.d.ts +3 -0
- package/lib/src/common/config.d.ts.map +1 -1
- package/lib/src/common/config.js +6 -0
- package/lib/src/common/constant.d.ts +1 -0
- package/lib/src/common/constant.d.ts.map +1 -1
- package/lib/src/common/constant.js +6 -1
- package/lib/src/common/dsn.d.ts +30 -0
- package/lib/src/common/dsn.d.ts.map +1 -0
- package/lib/src/common/dsn.js +221 -0
- package/lib/src/common/taosResult.d.ts.map +1 -1
- package/lib/src/common/taosResult.js +0 -5
- package/lib/src/common/urlParser.d.ts +32 -0
- package/lib/src/common/urlParser.d.ts.map +1 -0
- package/lib/src/common/urlParser.js +201 -0
- package/lib/src/common/utils.d.ts +6 -1
- package/lib/src/common/utils.d.ts.map +1 -1
- package/lib/src/common/utils.js +74 -22
- package/lib/src/index.d.ts.map +1 -1
- package/lib/src/sql/wsSql.d.ts.map +1 -1
- package/lib/src/sql/wsSql.js +2 -2
- package/lib/src/stmt/FieldBindParams.d.ts.map +1 -1
- package/lib/src/stmt/wsColumnInfo.d.ts.map +1 -1
- package/lib/src/stmt/wsParams1.d.ts.map +1 -1
- package/lib/src/stmt/wsParams1.js +26 -26
- package/lib/src/stmt/wsParams2.d.ts.map +1 -1
- package/lib/src/stmt/wsParams2.js +0 -3
- package/lib/src/stmt/wsParamsBase.d.ts.map +1 -1
- package/lib/src/stmt/wsProto.d.ts.map +1 -1
- package/lib/src/stmt/wsProto.js +16 -16
- package/lib/src/stmt/wsStmt1.d.ts.map +1 -1
- package/lib/src/stmt/wsStmt2.d.ts +12 -4
- package/lib/src/stmt/wsStmt2.d.ts.map +1 -1
- package/lib/src/stmt/wsStmt2.js +182 -64
- package/lib/src/stmt/wsTableInfo.d.ts.map +1 -1
- package/lib/src/tmq/config.d.ts +4 -2
- package/lib/src/tmq/config.d.ts.map +1 -1
- package/lib/src/tmq/config.js +30 -13
- package/lib/src/tmq/constant.d.ts +4 -0
- package/lib/src/tmq/constant.d.ts.map +1 -1
- package/lib/src/tmq/constant.js +4 -0
- package/lib/src/tmq/tmqResponse.d.ts.map +1 -1
- package/lib/src/tmq/tmqResponse.js +1 -4
- package/lib/src/tmq/wsTmq.d.ts +4 -1
- package/lib/src/tmq/wsTmq.d.ts.map +1 -1
- package/lib/src/tmq/wsTmq.js +55 -27
- package/lib/test/bulkPulling/a.test.d.ts +2 -0
- package/lib/test/bulkPulling/a.test.d.ts.map +1 -0
- package/lib/test/bulkPulling/a.test.js +166 -0
- package/lib/test/bulkPulling/cloud.tmq.test.js +3 -2
- package/lib/test/bulkPulling/decimal.test.js +8 -8
- package/lib/test/bulkPulling/dsn.test.d.ts +2 -0
- package/lib/test/bulkPulling/dsn.test.d.ts.map +1 -0
- package/lib/test/bulkPulling/dsn.test.js +397 -0
- package/lib/test/bulkPulling/queryTables.test.js +1 -1
- package/lib/test/bulkPulling/retryConfig.test.d.ts +2 -0
- package/lib/test/bulkPulling/retryConfig.test.d.ts.map +1 -0
- package/lib/test/bulkPulling/retryConfig.test.js +34 -0
- package/lib/test/bulkPulling/schemaless.test.js +15 -14
- package/lib/test/bulkPulling/sql.failover.test.d.ts +2 -0
- package/lib/test/bulkPulling/sql.failover.test.d.ts.map +1 -0
- package/lib/test/bulkPulling/sql.failover.test.js +338 -0
- package/lib/test/bulkPulling/sql.test.js +116 -44
- package/lib/test/bulkPulling/stmt1.func.test.js +31 -30
- package/lib/test/bulkPulling/stmt1.type.test.js +1 -1
- package/lib/test/bulkPulling/stmt2.failover.test.d.ts +2 -0
- package/lib/test/bulkPulling/stmt2.failover.test.d.ts.map +1 -0
- package/lib/test/bulkPulling/stmt2.failover.test.js +313 -0
- package/lib/test/bulkPulling/stmt2.func.test.js +37 -36
- package/lib/test/bulkPulling/stmt2.init.failover.test.d.ts +2 -0
- package/lib/test/bulkPulling/stmt2.init.failover.test.d.ts.map +1 -0
- package/lib/test/bulkPulling/stmt2.init.failover.test.js +50 -0
- package/lib/test/bulkPulling/stmt2.type.test.js +1 -1
- package/lib/test/bulkPulling/tmq.config.test.d.ts +2 -0
- package/lib/test/bulkPulling/tmq.config.test.d.ts.map +1 -0
- package/lib/test/bulkPulling/tmq.config.test.js +77 -0
- package/lib/test/bulkPulling/tmq.failover.test.d.ts +2 -0
- package/lib/test/bulkPulling/tmq.failover.test.d.ts.map +1 -0
- package/lib/test/bulkPulling/tmq.failover.test.js +404 -0
- package/lib/test/bulkPulling/tmq.test.js +135 -14
- package/lib/test/bulkPulling/urlParser.test.d.ts +2 -0
- package/lib/test/bulkPulling/urlParser.test.d.ts.map +1 -0
- package/lib/test/bulkPulling/urlParser.test.js +452 -0
- package/lib/test/bulkPulling/wsClient.reconnect.integration.test.d.ts +2 -0
- package/lib/test/bulkPulling/wsClient.reconnect.integration.test.d.ts.map +1 -0
- package/lib/test/bulkPulling/wsClient.reconnect.integration.test.js +184 -0
- package/lib/test/bulkPulling/wsClient.recovery.test.d.ts +2 -0
- package/lib/test/bulkPulling/wsClient.recovery.test.d.ts.map +1 -0
- package/lib/test/bulkPulling/wsClient.recovery.test.js +104 -0
- package/lib/test/bulkPulling/wsConfig.dsn.test.d.ts +2 -0
- package/lib/test/bulkPulling/wsConfig.dsn.test.d.ts.map +1 -0
- package/lib/test/bulkPulling/wsConfig.dsn.test.js +39 -0
- package/lib/test/bulkPulling/wsConnectPool.test.js +7 -7
- package/lib/test/bulkPulling/wsConnector.failover.test.d.ts +2 -0
- package/lib/test/bulkPulling/wsConnector.failover.test.d.ts.map +1 -0
- package/lib/test/bulkPulling/wsConnector.failover.test.js +497 -0
- package/lib/test/bulkPulling/wsConnectorPool.key.test.d.ts +2 -0
- package/lib/test/bulkPulling/wsConnectorPool.key.test.d.ts.map +1 -0
- package/lib/test/bulkPulling/wsConnectorPool.key.test.js +52 -0
- package/lib/test/bulkPulling/wsConnectorPool.keyAuth.test.d.ts +2 -0
- package/lib/test/bulkPulling/wsConnectorPool.keyAuth.test.d.ts.map +1 -0
- package/lib/test/bulkPulling/wsConnectorPool.keyAuth.test.js +28 -0
- package/lib/test/bulkPulling/wsEventCallback.test.d.ts +2 -0
- package/lib/test/bulkPulling/wsEventCallback.test.d.ts.map +1 -0
- package/lib/test/bulkPulling/wsEventCallback.test.js +54 -0
- package/lib/test/bulkPulling/wsProxy.failover.integration.test.d.ts +2 -0
- package/lib/test/bulkPulling/wsProxy.failover.integration.test.d.ts.map +1 -0
- package/lib/test/bulkPulling/wsProxy.failover.integration.test.js +120 -0
- package/lib/test/bulkPulling/wsProxy.failover.test.d.ts +2 -0
- package/lib/test/bulkPulling/wsProxy.failover.test.d.ts.map +1 -0
- package/lib/test/bulkPulling/wsProxy.failover.test.js +465 -0
- package/lib/test/client/wsClient.recovery.test.d.ts +2 -0
- package/lib/test/client/wsClient.recovery.test.d.ts.map +1 -0
- package/lib/test/client/wsClient.recovery.test.js +122 -0
- package/lib/test/client/wsConnectPool.test.d.ts +2 -0
- package/lib/test/client/wsConnectPool.test.d.ts.map +1 -0
- package/lib/test/client/wsConnectPool.test.js +147 -0
- package/lib/test/client/wsConnector.failover.test.d.ts +2 -0
- package/lib/test/client/wsConnector.failover.test.d.ts.map +1 -0
- package/lib/test/client/wsConnector.failover.test.js +681 -0
- package/lib/test/client/wsConnector.leastConnections.test.d.ts +2 -0
- package/lib/test/client/wsConnector.leastConnections.test.d.ts.map +1 -0
- package/lib/test/client/wsConnector.leastConnections.test.js +71 -0
- package/lib/test/client/wsConnectorPool.key.test.d.ts +2 -0
- package/lib/test/client/wsConnectorPool.key.test.d.ts.map +1 -0
- package/lib/test/client/wsConnectorPool.key.test.js +127 -0
- package/lib/test/client/wsEventCallback.test.d.ts +2 -0
- package/lib/test/client/wsEventCallback.test.d.ts.map +1 -0
- package/lib/test/client/wsEventCallback.test.js +98 -0
- package/lib/test/common/addressConnectionTracker.test.d.ts +2 -0
- package/lib/test/common/addressConnectionTracker.test.d.ts.map +1 -0
- package/lib/test/common/addressConnectionTracker.test.js +74 -0
- package/lib/test/common/dsn.test.d.ts +2 -0
- package/lib/test/common/dsn.test.d.ts.map +1 -0
- package/lib/test/common/dsn.test.js +406 -0
- package/lib/test/common/log.test.d.ts +2 -0
- package/lib/test/common/log.test.d.ts.map +1 -0
- package/lib/test/common/log.test.js +54 -0
- package/lib/test/common/utils.test.d.ts +2 -0
- package/lib/test/common/utils.test.d.ts.map +1 -0
- package/lib/test/common/utils.test.js +13 -0
- package/lib/test/common/wsConfig.dsn.test.d.ts +2 -0
- package/lib/test/common/wsConfig.dsn.test.d.ts.map +1 -0
- package/lib/test/common/wsConfig.dsn.test.js +39 -0
- package/lib/test/helpers/utils.d.ts +27 -0
- package/lib/test/helpers/utils.d.ts.map +1 -0
- package/lib/test/helpers/utils.js +341 -0
- package/lib/test/helpers/wsFailoverProxy.d.ts +109 -0
- package/lib/test/helpers/wsFailoverProxy.d.ts.map +1 -0
- package/lib/test/helpers/wsFailoverProxy.js +420 -0
- package/lib/test/helpers/wsProxy.d.ts +110 -0
- package/lib/test/helpers/wsProxy.d.ts.map +1 -0
- package/lib/test/helpers/wsProxy.js +429 -0
- package/lib/test/sql/core/decimal.test.d.ts +2 -0
- package/lib/test/sql/core/decimal.test.d.ts.map +1 -0
- package/lib/test/sql/core/decimal.test.js +153 -0
- package/lib/test/sql/core/queryTables.test.d.ts +2 -0
- package/lib/test/sql/core/queryTables.test.d.ts.map +1 -0
- package/lib/test/sql/core/queryTables.test.js +506 -0
- package/lib/test/sql/core/schemaless.test.d.ts +2 -0
- package/lib/test/sql/core/schemaless.test.d.ts.map +1 -0
- package/lib/test/sql/core/schemaless.test.js +102 -0
- package/lib/test/sql/core/sql.test.d.ts +2 -0
- package/lib/test/sql/core/sql.test.d.ts.map +1 -0
- package/lib/test/sql/core/sql.test.js +324 -0
- package/lib/test/sql/decimal.test.d.ts +2 -0
- package/lib/test/sql/decimal.test.d.ts.map +1 -0
- package/lib/test/sql/decimal.test.js +153 -0
- package/lib/test/sql/failover/sql.failover.test.d.ts +2 -0
- package/lib/test/sql/failover/sql.failover.test.d.ts.map +1 -0
- package/lib/test/sql/failover/sql.failover.test.js +341 -0
- package/lib/test/sql/queryTables.test.d.ts +2 -0
- package/lib/test/sql/queryTables.test.d.ts.map +1 -0
- package/lib/test/sql/queryTables.test.js +506 -0
- package/lib/test/sql/schemaless.test.d.ts +2 -0
- package/lib/test/sql/schemaless.test.d.ts.map +1 -0
- package/lib/test/sql/schemaless.test.js +102 -0
- package/lib/test/sql/sql.failover.test.d.ts +2 -0
- package/lib/test/sql/sql.failover.test.d.ts.map +1 -0
- package/lib/test/sql/sql.failover.test.js +341 -0
- package/lib/test/sql/sql.test.d.ts +2 -0
- package/lib/test/sql/sql.test.d.ts.map +1 -0
- package/lib/test/sql/sql.test.js +324 -0
- package/lib/test/stmt/failover/stmt2.failover.mock.test.d.ts +2 -0
- package/lib/test/stmt/failover/stmt2.failover.mock.test.d.ts.map +1 -0
- package/lib/test/stmt/failover/stmt2.failover.mock.test.js +341 -0
- package/lib/test/stmt/failover/stmt2.failover.test.d.ts +2 -0
- package/lib/test/stmt/failover/stmt2.failover.test.d.ts.map +1 -0
- package/lib/test/stmt/failover/stmt2.failover.test.js +384 -0
- package/lib/test/stmt/stmt1.func.test.d.ts +2 -0
- package/lib/test/stmt/stmt1.func.test.d.ts.map +1 -0
- package/lib/test/stmt/stmt1.func.test.js +418 -0
- package/lib/test/stmt/stmt1.type.test.d.ts +2 -0
- package/lib/test/stmt/stmt1.type.test.d.ts.map +1 -0
- package/lib/test/stmt/stmt1.type.test.js +399 -0
- package/lib/test/stmt/stmt2.failover.mock.test.d.ts +2 -0
- package/lib/test/stmt/stmt2.failover.mock.test.d.ts.map +1 -0
- package/lib/test/stmt/stmt2.failover.mock.test.js +341 -0
- package/lib/test/stmt/stmt2.failover.test.d.ts +2 -0
- package/lib/test/stmt/stmt2.failover.test.d.ts.map +1 -0
- package/lib/test/stmt/stmt2.failover.test.js +384 -0
- package/lib/test/stmt/stmt2.func.test.d.ts +2 -0
- package/lib/test/stmt/stmt2.func.test.d.ts.map +1 -0
- package/lib/test/stmt/stmt2.func.test.js +537 -0
- package/lib/test/stmt/stmt2.type.test.d.ts +2 -0
- package/lib/test/stmt/stmt2.type.test.d.ts.map +1 -0
- package/lib/test/stmt/stmt2.type.test.js +401 -0
- package/lib/test/stmt/v1/stmt1.func.test.d.ts +2 -0
- package/lib/test/stmt/v1/stmt1.func.test.d.ts.map +1 -0
- package/lib/test/stmt/v1/stmt1.func.test.js +418 -0
- package/lib/test/stmt/v1/stmt1.type.test.d.ts +2 -0
- package/lib/test/stmt/v1/stmt1.type.test.d.ts.map +1 -0
- package/lib/test/stmt/v1/stmt1.type.test.js +399 -0
- package/lib/test/stmt/v2/stmt2.func.test.d.ts +2 -0
- package/lib/test/stmt/v2/stmt2.func.test.d.ts.map +1 -0
- package/lib/test/stmt/v2/stmt2.func.test.js +537 -0
- package/lib/test/stmt/v2/stmt2.type.test.d.ts +2 -0
- package/lib/test/stmt/v2/stmt2.type.test.d.ts.map +1 -0
- package/lib/test/stmt/v2/stmt2.type.test.js +401 -0
- package/lib/test/tmq/cloud/cloud.tmq.test.d.ts +2 -0
- package/lib/test/tmq/cloud/cloud.tmq.test.d.ts.map +1 -0
- package/lib/test/tmq/cloud/cloud.tmq.test.js +84 -0
- package/lib/test/tmq/cloud/tmq.cloud.test.d.ts +2 -0
- package/lib/test/tmq/cloud/tmq.cloud.test.d.ts.map +1 -0
- package/lib/test/tmq/cloud/tmq.cloud.test.js +82 -0
- package/lib/test/tmq/core/tmq.config.test.d.ts +2 -0
- package/lib/test/tmq/core/tmq.config.test.d.ts.map +1 -0
- package/lib/test/tmq/core/tmq.config.test.js +83 -0
- package/lib/test/tmq/core/tmq.test.d.ts +2 -0
- package/lib/test/tmq/core/tmq.test.d.ts.map +1 -0
- package/lib/test/tmq/core/tmq.test.js +513 -0
- package/lib/test/tmq/failover/tmq.failover.test.d.ts +2 -0
- package/lib/test/tmq/failover/tmq.failover.test.d.ts.map +1 -0
- package/lib/test/tmq/failover/tmq.failover.test.js +404 -0
- package/lib/test/tmq/tmq.cloud.test.d.ts +2 -0
- package/lib/test/tmq/tmq.cloud.test.d.ts.map +1 -0
- package/lib/test/tmq/tmq.cloud.test.js +82 -0
- package/lib/test/tmq/tmq.config.test.d.ts +2 -0
- package/lib/test/tmq/tmq.config.test.d.ts.map +1 -0
- package/lib/test/tmq/tmq.config.test.js +94 -0
- package/lib/test/tmq/tmq.failover.test.d.ts +2 -0
- package/lib/test/tmq/tmq.failover.test.d.ts.map +1 -0
- package/lib/test/tmq/tmq.failover.test.js +404 -0
- package/lib/test/tmq/tmq.test.d.ts +2 -0
- package/lib/test/tmq/tmq.test.d.ts.map +1 -0
- package/lib/test/tmq/tmq.test.js +513 -0
- package/lib/test/unit/connectionManager.test.d.ts +2 -0
- package/lib/test/unit/connectionManager.test.d.ts.map +1 -0
- package/lib/test/unit/connectionManager.test.js +91 -0
- package/lib/test/utils.d.ts +4 -0
- package/lib/test/utils.d.ts.map +1 -1
- package/lib/test/utils.js +11 -17
- package/package.json +1 -1
- package/readme.md +2 -2
|
@@ -0,0 +1,221 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.CLOUD_DEFAULT_PORT = exports.DEFAULT_PORT = exports.Dsn = exports.Address = exports.WS_TMQ_ENDPOINT = exports.WS_SQL_ENDPOINT = void 0;
|
|
4
|
+
exports.parse = parse;
|
|
5
|
+
exports.isCloudServiceHost = isCloudServiceHost;
|
|
6
|
+
exports.getDefaultPortForHost = getDefaultPortForHost;
|
|
7
|
+
const wsError_1 = require("./wsError");
|
|
8
|
+
exports.WS_SQL_ENDPOINT = "sql";
|
|
9
|
+
exports.WS_TMQ_ENDPOINT = "tmq";
|
|
10
|
+
const WS_SQL_PATH = "ws";
|
|
11
|
+
const WS_TMQ_PATH = "rest/tmq";
|
|
12
|
+
class Address {
|
|
13
|
+
constructor(host, port) {
|
|
14
|
+
this.host = host;
|
|
15
|
+
this.port = port;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
exports.Address = Address;
|
|
19
|
+
const REDACTED = "[REDACTED]";
|
|
20
|
+
const SENSITIVE_PARAM_KEYS = new Set([
|
|
21
|
+
"token",
|
|
22
|
+
"bearer_token",
|
|
23
|
+
"td.connect.token",
|
|
24
|
+
]);
|
|
25
|
+
function shouldMaskParam(key) {
|
|
26
|
+
return SENSITIVE_PARAM_KEYS.has(key.toLowerCase());
|
|
27
|
+
}
|
|
28
|
+
class Dsn {
|
|
29
|
+
constructor(scheme, username, password, addresses, database, params, endpoint = exports.WS_SQL_ENDPOINT) {
|
|
30
|
+
this.scheme = scheme;
|
|
31
|
+
this.username = username;
|
|
32
|
+
this.password = password;
|
|
33
|
+
this.addresses = addresses.map((address) => new Address(address.host, address.port));
|
|
34
|
+
this.database = database;
|
|
35
|
+
this.params = new Map(params);
|
|
36
|
+
this.endpoint = endpoint;
|
|
37
|
+
}
|
|
38
|
+
toString() {
|
|
39
|
+
const params = {};
|
|
40
|
+
for (const [key, value] of this.params.entries()) {
|
|
41
|
+
params[key] = shouldMaskParam(key) ? REDACTED : value;
|
|
42
|
+
}
|
|
43
|
+
return JSON.stringify({
|
|
44
|
+
scheme: this.scheme,
|
|
45
|
+
username: this.username,
|
|
46
|
+
password: this.password.length > 0 ? REDACTED : this.password,
|
|
47
|
+
addresses: this.addresses,
|
|
48
|
+
database: this.database,
|
|
49
|
+
params,
|
|
50
|
+
endpoint: this.endpoint,
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
path() {
|
|
54
|
+
return this.endpoint === exports.WS_TMQ_ENDPOINT ? WS_TMQ_PATH : WS_SQL_PATH;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
exports.Dsn = Dsn;
|
|
58
|
+
/**
|
|
59
|
+
* Parse a multi-host TDengine WebSocket URL.
|
|
60
|
+
* Format: ws://username:password@host1:port1,host2:port2,[::1]:port3/db?key=value
|
|
61
|
+
*/
|
|
62
|
+
function parse(url) {
|
|
63
|
+
if (!url || url.trim().length === 0) {
|
|
64
|
+
throw new wsError_1.TDWebSocketClientError(wsError_1.ErrorCode.ERR_INVALID_URL, "URL must not be empty");
|
|
65
|
+
}
|
|
66
|
+
// Extract scheme
|
|
67
|
+
const schemeMatch = url.match(/^(wss?):\/\//i);
|
|
68
|
+
if (!schemeMatch) {
|
|
69
|
+
throw new wsError_1.TDWebSocketClientError(wsError_1.ErrorCode.ERR_INVALID_URL, "Invalid URL scheme, expected ws:// or wss://");
|
|
70
|
+
}
|
|
71
|
+
const scheme = schemeMatch[1].toLowerCase();
|
|
72
|
+
let remainder = url.slice(schemeMatch[0].length);
|
|
73
|
+
// Isolate authority from path/query before parsing userinfo.
|
|
74
|
+
const slashIndex = remainder.indexOf("/");
|
|
75
|
+
const queryMarkIndex = remainder.indexOf("?");
|
|
76
|
+
let authorityEndIndex = remainder.length;
|
|
77
|
+
if (slashIndex !== -1) {
|
|
78
|
+
authorityEndIndex = Math.min(authorityEndIndex, slashIndex);
|
|
79
|
+
}
|
|
80
|
+
if (queryMarkIndex !== -1) {
|
|
81
|
+
authorityEndIndex = Math.min(authorityEndIndex, queryMarkIndex);
|
|
82
|
+
}
|
|
83
|
+
const authority = remainder.slice(0, authorityEndIndex);
|
|
84
|
+
const suffix = remainder.slice(authorityEndIndex);
|
|
85
|
+
// Extract username:password@ from authority only.
|
|
86
|
+
let username = "";
|
|
87
|
+
let password = "";
|
|
88
|
+
const atIndex = authority.lastIndexOf("@");
|
|
89
|
+
let hostPort = authority;
|
|
90
|
+
if (atIndex !== -1) {
|
|
91
|
+
const userInfo = authority.slice(0, atIndex);
|
|
92
|
+
hostPort = authority.slice(atIndex + 1);
|
|
93
|
+
const colonIndex = userInfo.indexOf(":");
|
|
94
|
+
if (colonIndex !== -1) {
|
|
95
|
+
username = userInfo.slice(0, colonIndex);
|
|
96
|
+
password = userInfo.slice(colonIndex + 1);
|
|
97
|
+
}
|
|
98
|
+
else {
|
|
99
|
+
username = userInfo;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
remainder = `${hostPort}${suffix}`;
|
|
103
|
+
// Extract query params (after ?)
|
|
104
|
+
let params = new Map();
|
|
105
|
+
const queryIndex = remainder.indexOf("?");
|
|
106
|
+
let queryString = "";
|
|
107
|
+
if (queryIndex !== -1) {
|
|
108
|
+
queryString = remainder.slice(queryIndex + 1);
|
|
109
|
+
remainder = remainder.slice(0, queryIndex);
|
|
110
|
+
const searchParams = new URLSearchParams(queryString);
|
|
111
|
+
searchParams.forEach((value, key) => {
|
|
112
|
+
params.set(key, value);
|
|
113
|
+
});
|
|
114
|
+
}
|
|
115
|
+
// Extract database (after /)
|
|
116
|
+
let database = "";
|
|
117
|
+
const pathIndex = remainder.indexOf("/");
|
|
118
|
+
if (pathIndex !== -1) {
|
|
119
|
+
database = remainder.slice(pathIndex + 1);
|
|
120
|
+
remainder = remainder.slice(0, pathIndex);
|
|
121
|
+
}
|
|
122
|
+
// remainder is now the host list: host1:port1,host2:port2,[::1]:port3
|
|
123
|
+
const hosts = parseHostList(remainder);
|
|
124
|
+
if (hosts.length === 0) {
|
|
125
|
+
throw new wsError_1.TDWebSocketClientError(wsError_1.ErrorCode.ERR_INVALID_URL, "No hosts found in URL");
|
|
126
|
+
}
|
|
127
|
+
// Deduplicate hosts (preserve order, keep first occurrence)
|
|
128
|
+
const seen = new Set();
|
|
129
|
+
const dedupedHosts = [];
|
|
130
|
+
for (const h of hosts) {
|
|
131
|
+
const key = `${h.host}:${h.port}`;
|
|
132
|
+
if (!seen.has(key)) {
|
|
133
|
+
seen.add(key);
|
|
134
|
+
dedupedHosts.push(h);
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
return new Dsn(scheme, username, password, dedupedHosts, database, params);
|
|
138
|
+
}
|
|
139
|
+
exports.DEFAULT_PORT = 6041;
|
|
140
|
+
exports.CLOUD_DEFAULT_PORT = 443;
|
|
141
|
+
function isCloudServiceHost(host) {
|
|
142
|
+
const normalizedHost = host.toLowerCase();
|
|
143
|
+
return (normalizedHost.includes("cloud.tdengine.com") ||
|
|
144
|
+
normalizedHost.includes("cloud.taosdata.com"));
|
|
145
|
+
}
|
|
146
|
+
function getDefaultPortForHost(host) {
|
|
147
|
+
return isCloudServiceHost(host) ? exports.CLOUD_DEFAULT_PORT : exports.DEFAULT_PORT;
|
|
148
|
+
}
|
|
149
|
+
/**
|
|
150
|
+
* Parse comma-separated host list. Supports IPv6 in brackets.
|
|
151
|
+
* Examples: "host1:6041,host2:6042", "[::1]:6041,host2:6042"
|
|
152
|
+
*/
|
|
153
|
+
function parseHostList(hostStr) {
|
|
154
|
+
if (!hostStr || hostStr.trim().length === 0) {
|
|
155
|
+
return [];
|
|
156
|
+
}
|
|
157
|
+
const hosts = [];
|
|
158
|
+
let i = 0;
|
|
159
|
+
while (i < hostStr.length) {
|
|
160
|
+
// Skip comma separator
|
|
161
|
+
if (hostStr[i] === ",") {
|
|
162
|
+
i++;
|
|
163
|
+
continue;
|
|
164
|
+
}
|
|
165
|
+
if (hostStr[i] === "[") {
|
|
166
|
+
// IPv6 address in brackets
|
|
167
|
+
const closeBracket = hostStr.indexOf("]", i);
|
|
168
|
+
if (closeBracket === -1) {
|
|
169
|
+
throw new wsError_1.TDWebSocketClientError(wsError_1.ErrorCode.ERR_INVALID_URL, `Unclosed bracket in IPv6 address: ${hostStr.slice(i)}`);
|
|
170
|
+
}
|
|
171
|
+
const ipv6Host = hostStr.slice(i + 1, closeBracket);
|
|
172
|
+
let port = getDefaultPortForHost(ipv6Host);
|
|
173
|
+
let next = closeBracket + 1;
|
|
174
|
+
if (next < hostStr.length && hostStr[next] === ":") {
|
|
175
|
+
const portEnd = hostStr.indexOf(",", next);
|
|
176
|
+
const portStr = portEnd === -1
|
|
177
|
+
? hostStr.slice(next + 1)
|
|
178
|
+
: hostStr.slice(next + 1, portEnd);
|
|
179
|
+
port = parsePort(portStr, hostStr, ipv6Host);
|
|
180
|
+
i = portEnd === -1 ? hostStr.length : portEnd;
|
|
181
|
+
}
|
|
182
|
+
else {
|
|
183
|
+
i = next;
|
|
184
|
+
}
|
|
185
|
+
hosts.push(new Address(`[${ipv6Host}]`, port));
|
|
186
|
+
}
|
|
187
|
+
else {
|
|
188
|
+
// Regular host or IPv4
|
|
189
|
+
const commaIndex = hostStr.indexOf(",", i);
|
|
190
|
+
const segment = commaIndex === -1
|
|
191
|
+
? hostStr.slice(i)
|
|
192
|
+
: hostStr.slice(i, commaIndex);
|
|
193
|
+
const lastColon = segment.lastIndexOf(":");
|
|
194
|
+
if (lastColon !== -1) {
|
|
195
|
+
const host = segment.slice(0, lastColon);
|
|
196
|
+
const port = parsePort(segment.slice(lastColon + 1), hostStr, host);
|
|
197
|
+
hosts.push(new Address(host, port));
|
|
198
|
+
}
|
|
199
|
+
else {
|
|
200
|
+
hosts.push(new Address(segment, getDefaultPortForHost(segment)));
|
|
201
|
+
}
|
|
202
|
+
i = commaIndex === -1 ? hostStr.length : commaIndex;
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
return hosts;
|
|
206
|
+
}
|
|
207
|
+
function parsePort(portStr, context, host) {
|
|
208
|
+
// If port string is empty, use default port
|
|
209
|
+
if (portStr.length === 0) {
|
|
210
|
+
return getDefaultPortForHost(host);
|
|
211
|
+
}
|
|
212
|
+
// Validate that port string contains only digits
|
|
213
|
+
if (!/^\d+$/.test(portStr)) {
|
|
214
|
+
throw new wsError_1.TDWebSocketClientError(wsError_1.ErrorCode.ERR_INVALID_URL, `Invalid port "${portStr}" in host string: ${context}`);
|
|
215
|
+
}
|
|
216
|
+
const port = parseInt(portStr, 10);
|
|
217
|
+
if (isNaN(port) || port < 1 || port > 65535) {
|
|
218
|
+
throw new wsError_1.TDWebSocketClientError(wsError_1.ErrorCode.ERR_INVALID_URL, `Invalid port "${portStr}" in host string: ${context}`);
|
|
219
|
+
}
|
|
220
|
+
return port;
|
|
221
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"taosResult.d.ts","sourceRoot":"","sources":["../../../src/common/taosResult.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;
|
|
1
|
+
{"version":3,"file":"taosResult.d.ts","sourceRoot":"","sources":["../../../src/common/taosResult.ts"],"names":[],"mappings":"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"}
|
|
@@ -449,7 +449,6 @@ function readSolidData(dataBuffer, colDataHead, meta, fields_scale) {
|
|
|
449
449
|
}
|
|
450
450
|
case constant_1.TDengineTypeCode.TIMESTAMP: {
|
|
451
451
|
return dataBuffer.getBigInt64(colDataHead, true);
|
|
452
|
-
// could change
|
|
453
452
|
}
|
|
454
453
|
case constant_1.TDengineTypeCode.DECIMAL: {
|
|
455
454
|
let decimalHighPart = dataBuffer.getBigInt64(colDataHead + 8, true);
|
|
@@ -471,13 +470,11 @@ function readBinary(dataBuffer, colDataHead, length) {
|
|
|
471
470
|
return buff;
|
|
472
471
|
}
|
|
473
472
|
function readVarchar(dataBuffer, colDataHead, length, textDecoder) {
|
|
474
|
-
// let buff = dataBuffer.slice(colDataHead, colDataHead + length)
|
|
475
473
|
let dataView = new DataView(dataBuffer, colDataHead, length);
|
|
476
474
|
return textDecoder.decode(dataView);
|
|
477
475
|
}
|
|
478
476
|
function readNchar(dataBuffer, colDataHead, length) {
|
|
479
477
|
let data = [];
|
|
480
|
-
// let buff: ArrayBuffer = dataBuffer.slice(colDataHead, colDataHead + length);
|
|
481
478
|
let dataView = new DataView(dataBuffer, colDataHead, length);
|
|
482
479
|
for (let i = 0; i < length / 4; i++) {
|
|
483
480
|
data.push((0, ut8Helper_1.appendRune)(dataView.getUint32(i * 4, true)));
|
|
@@ -485,7 +482,6 @@ function readNchar(dataBuffer, colDataHead, length) {
|
|
|
485
482
|
return data.join("");
|
|
486
483
|
}
|
|
487
484
|
function getString(dataBuffer, colDataHead, length, textDecoder) {
|
|
488
|
-
// let buff = dataBuffer.slice(colDataHead, colDataHead + length - 1)
|
|
489
485
|
let dataView = new Uint8Array(dataBuffer.buffer, dataBuffer.byteOffset + colDataHead, length - 1);
|
|
490
486
|
return textDecoder.decode(dataView);
|
|
491
487
|
}
|
|
@@ -514,7 +510,6 @@ function bitmapLen(n) {
|
|
|
514
510
|
return (n + ((1 << 3) - 1)) >> 3;
|
|
515
511
|
}
|
|
516
512
|
function getScaleFromRowBlock(buffer, colIndex, startOffset) {
|
|
517
|
-
// for decimal: |___bytes___|__empty__|___prec___|__scale___|
|
|
518
513
|
let backupPos = buffer.byteOffset + startOffset + 28 + colIndex * 5 + 1;
|
|
519
514
|
let scaleBuffer = new DataView(buffer.buffer, backupPos);
|
|
520
515
|
let scale = scaleBuffer.getInt32(0, true);
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
export interface HostInfo {
|
|
2
|
+
host: string;
|
|
3
|
+
port: number;
|
|
4
|
+
}
|
|
5
|
+
export interface ParsedUrl {
|
|
6
|
+
hosts: HostInfo[];
|
|
7
|
+
scheme: string;
|
|
8
|
+
username: string;
|
|
9
|
+
password: string;
|
|
10
|
+
database: string;
|
|
11
|
+
params: Map<string, string>;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Parse a multi-host TDengine WebSocket URL.
|
|
15
|
+
* Format: ws://username:password@host1:port1,host2:port2,[::1]:port3/db?key=value
|
|
16
|
+
*/
|
|
17
|
+
export declare function parseMultiHostUrl(url: string): ParsedUrl;
|
|
18
|
+
/**
|
|
19
|
+
* Build a single-host URL from parsed components + a specific host.
|
|
20
|
+
* Used by ConnectionManager to create WebSocketConnector URLs.
|
|
21
|
+
*/
|
|
22
|
+
export declare function buildHostUrl(parsed: ParsedUrl, host: HostInfo, extraParams?: Map<string, string>): URL;
|
|
23
|
+
/**
|
|
24
|
+
* Extract retry options from parsed URL params.
|
|
25
|
+
*/
|
|
26
|
+
export declare function extractRetryOptions(params: Map<string, string>): {
|
|
27
|
+
retries?: number;
|
|
28
|
+
retryBackoffMs?: number;
|
|
29
|
+
retryBackoffMaxMs?: number;
|
|
30
|
+
resendWrite?: boolean;
|
|
31
|
+
};
|
|
32
|
+
//# sourceMappingURL=urlParser.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"urlParser.d.ts","sourceRoot":"","sources":["../../../src/common/urlParser.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,QAAQ;IACrB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,SAAS;IACtB,KAAK,EAAE,QAAQ,EAAE,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAC/B;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,CAqFxD;AA0FD;;;GAGG;AACH,wBAAgB,YAAY,CACxB,MAAM,EAAE,SAAS,EACjB,IAAI,EAAE,QAAQ,EACd,WAAW,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,GAClC,GAAG,CA0BL;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG;IAC9D,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,WAAW,CAAC,EAAE,OAAO,CAAC;CACzB,CAgBA"}
|
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.parseMultiHostUrl = parseMultiHostUrl;
|
|
4
|
+
exports.buildHostUrl = buildHostUrl;
|
|
5
|
+
exports.extractRetryOptions = extractRetryOptions;
|
|
6
|
+
const wsError_1 = require("./wsError");
|
|
7
|
+
/**
|
|
8
|
+
* Parse a multi-host TDengine WebSocket URL.
|
|
9
|
+
* Format: ws://username:password@host1:port1,host2:port2,[::1]:port3/db?key=value
|
|
10
|
+
*/
|
|
11
|
+
function parseMultiHostUrl(url) {
|
|
12
|
+
if (!url || url.trim().length === 0) {
|
|
13
|
+
throw new wsError_1.TDWebSocketClientError(wsError_1.ErrorCode.ERR_INVALID_URL, "URL must not be empty");
|
|
14
|
+
}
|
|
15
|
+
// Extract scheme
|
|
16
|
+
const schemeMatch = url.match(/^(wss?):\/\//i);
|
|
17
|
+
if (!schemeMatch) {
|
|
18
|
+
throw new wsError_1.TDWebSocketClientError(wsError_1.ErrorCode.ERR_INVALID_URL, `Invalid URL scheme, expected ws:// or wss://, got: ${url}`);
|
|
19
|
+
}
|
|
20
|
+
const scheme = schemeMatch[1].toLowerCase();
|
|
21
|
+
let remainder = url.slice(schemeMatch[0].length);
|
|
22
|
+
// Extract username:password@ if present
|
|
23
|
+
let username = "";
|
|
24
|
+
let password = "";
|
|
25
|
+
const atIndex = remainder.indexOf("@");
|
|
26
|
+
if (atIndex !== -1) {
|
|
27
|
+
const userInfo = remainder.slice(0, atIndex);
|
|
28
|
+
remainder = remainder.slice(atIndex + 1);
|
|
29
|
+
const colonIndex = userInfo.indexOf(":");
|
|
30
|
+
if (colonIndex !== -1) {
|
|
31
|
+
username = userInfo.slice(0, colonIndex);
|
|
32
|
+
password = userInfo.slice(colonIndex + 1);
|
|
33
|
+
}
|
|
34
|
+
else {
|
|
35
|
+
username = userInfo;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
// Extract query params (after ?)
|
|
39
|
+
let params = new Map();
|
|
40
|
+
const queryIndex = remainder.indexOf("?");
|
|
41
|
+
let queryString = "";
|
|
42
|
+
if (queryIndex !== -1) {
|
|
43
|
+
queryString = remainder.slice(queryIndex + 1);
|
|
44
|
+
remainder = remainder.slice(0, queryIndex);
|
|
45
|
+
const searchParams = new URLSearchParams(queryString);
|
|
46
|
+
searchParams.forEach((value, key) => {
|
|
47
|
+
params.set(key, value);
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
// Extract database (after /)
|
|
51
|
+
let database = "";
|
|
52
|
+
const pathIndex = remainder.indexOf("/");
|
|
53
|
+
if (pathIndex !== -1) {
|
|
54
|
+
database = remainder.slice(pathIndex + 1);
|
|
55
|
+
remainder = remainder.slice(0, pathIndex);
|
|
56
|
+
}
|
|
57
|
+
// remainder is now the host list: host1:port1,host2:port2,[::1]:port3
|
|
58
|
+
const hosts = parseHostList(remainder);
|
|
59
|
+
if (hosts.length === 0) {
|
|
60
|
+
throw new wsError_1.TDWebSocketClientError(wsError_1.ErrorCode.ERR_INVALID_URL, "No hosts found in URL");
|
|
61
|
+
}
|
|
62
|
+
// Deduplicate hosts (preserve order, keep first occurrence)
|
|
63
|
+
const seen = new Set();
|
|
64
|
+
const dedupedHosts = [];
|
|
65
|
+
for (const h of hosts) {
|
|
66
|
+
const key = `${h.host}:${h.port}`;
|
|
67
|
+
if (!seen.has(key)) {
|
|
68
|
+
seen.add(key);
|
|
69
|
+
dedupedHosts.push(h);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
return {
|
|
73
|
+
hosts: dedupedHosts,
|
|
74
|
+
scheme,
|
|
75
|
+
username,
|
|
76
|
+
password,
|
|
77
|
+
database,
|
|
78
|
+
params,
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
const DEFAULT_PORT = 6041;
|
|
82
|
+
/**
|
|
83
|
+
* Parse comma-separated host list. Supports IPv6 in brackets.
|
|
84
|
+
* Examples: "host1:6041,host2:6042", "[::1]:6041,host2:6042"
|
|
85
|
+
*/
|
|
86
|
+
function parseHostList(hostStr) {
|
|
87
|
+
if (!hostStr || hostStr.trim().length === 0) {
|
|
88
|
+
return [];
|
|
89
|
+
}
|
|
90
|
+
const hosts = [];
|
|
91
|
+
let i = 0;
|
|
92
|
+
while (i < hostStr.length) {
|
|
93
|
+
// Skip comma separator
|
|
94
|
+
if (hostStr[i] === ",") {
|
|
95
|
+
i++;
|
|
96
|
+
continue;
|
|
97
|
+
}
|
|
98
|
+
if (hostStr[i] === "[") {
|
|
99
|
+
// IPv6 address in brackets
|
|
100
|
+
const closeBracket = hostStr.indexOf("]", i);
|
|
101
|
+
if (closeBracket === -1) {
|
|
102
|
+
throw new wsError_1.TDWebSocketClientError(wsError_1.ErrorCode.ERR_INVALID_URL, `Unclosed bracket in IPv6 address: ${hostStr.slice(i)}`);
|
|
103
|
+
}
|
|
104
|
+
const ipv6Host = hostStr.slice(i + 1, closeBracket);
|
|
105
|
+
let port = DEFAULT_PORT;
|
|
106
|
+
let next = closeBracket + 1;
|
|
107
|
+
if (next < hostStr.length && hostStr[next] === ":") {
|
|
108
|
+
const portEnd = hostStr.indexOf(",", next);
|
|
109
|
+
const portStr = portEnd === -1
|
|
110
|
+
? hostStr.slice(next + 1)
|
|
111
|
+
: hostStr.slice(next + 1, portEnd);
|
|
112
|
+
port = parsePort(portStr, hostStr);
|
|
113
|
+
i = portEnd === -1 ? hostStr.length : portEnd;
|
|
114
|
+
}
|
|
115
|
+
else {
|
|
116
|
+
i = next;
|
|
117
|
+
}
|
|
118
|
+
hosts.push({ host: `[${ipv6Host}]`, port });
|
|
119
|
+
}
|
|
120
|
+
else {
|
|
121
|
+
// Regular host or IPv4
|
|
122
|
+
const commaIndex = hostStr.indexOf(",", i);
|
|
123
|
+
const segment = commaIndex === -1
|
|
124
|
+
? hostStr.slice(i)
|
|
125
|
+
: hostStr.slice(i, commaIndex);
|
|
126
|
+
const lastColon = segment.lastIndexOf(":");
|
|
127
|
+
if (lastColon !== -1) {
|
|
128
|
+
const host = segment.slice(0, lastColon);
|
|
129
|
+
const port = parsePort(segment.slice(lastColon + 1), hostStr);
|
|
130
|
+
hosts.push({ host, port });
|
|
131
|
+
}
|
|
132
|
+
else {
|
|
133
|
+
hosts.push({ host: segment, port: DEFAULT_PORT });
|
|
134
|
+
}
|
|
135
|
+
i = commaIndex === -1 ? hostStr.length : commaIndex;
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
return hosts;
|
|
139
|
+
}
|
|
140
|
+
function parsePort(portStr, context) {
|
|
141
|
+
// If port string is empty, use default port
|
|
142
|
+
if (portStr.length === 0) {
|
|
143
|
+
return DEFAULT_PORT;
|
|
144
|
+
}
|
|
145
|
+
// Validate that port string contains only digits
|
|
146
|
+
if (!/^\d+$/.test(portStr)) {
|
|
147
|
+
throw new wsError_1.TDWebSocketClientError(wsError_1.ErrorCode.ERR_INVALID_URL, `Invalid port "${portStr}" in host string: ${context}`);
|
|
148
|
+
}
|
|
149
|
+
const port = parseInt(portStr, 10);
|
|
150
|
+
if (isNaN(port) || port < 1 || port > 65535) {
|
|
151
|
+
throw new wsError_1.TDWebSocketClientError(wsError_1.ErrorCode.ERR_INVALID_URL, `Invalid port "${portStr}" in host string: ${context}`);
|
|
152
|
+
}
|
|
153
|
+
return port;
|
|
154
|
+
}
|
|
155
|
+
/**
|
|
156
|
+
* Build a single-host URL from parsed components + a specific host.
|
|
157
|
+
* Used by ConnectionManager to create WebSocketConnector URLs.
|
|
158
|
+
*/
|
|
159
|
+
function buildHostUrl(parsed, host, extraParams) {
|
|
160
|
+
const origin = `${parsed.scheme}://${host.host}:${host.port}`;
|
|
161
|
+
const url = new URL(origin + "/ws");
|
|
162
|
+
if (parsed.username) {
|
|
163
|
+
url.username = parsed.username;
|
|
164
|
+
}
|
|
165
|
+
if (parsed.password) {
|
|
166
|
+
url.password = parsed.password;
|
|
167
|
+
}
|
|
168
|
+
// Copy non-retry params
|
|
169
|
+
const retryParams = new Set(["retries", "retry_backoff_ms", "retry_backoff_max_ms", "resend_write"]);
|
|
170
|
+
parsed.params.forEach((value, key) => {
|
|
171
|
+
if (!retryParams.has(key)) {
|
|
172
|
+
url.searchParams.set(key, value);
|
|
173
|
+
}
|
|
174
|
+
});
|
|
175
|
+
if (extraParams) {
|
|
176
|
+
extraParams.forEach((value, key) => {
|
|
177
|
+
url.searchParams.set(key, value);
|
|
178
|
+
});
|
|
179
|
+
}
|
|
180
|
+
return url;
|
|
181
|
+
}
|
|
182
|
+
/**
|
|
183
|
+
* Extract retry options from parsed URL params.
|
|
184
|
+
*/
|
|
185
|
+
function extractRetryOptions(params) {
|
|
186
|
+
const result = {};
|
|
187
|
+
if (params.has("retries")) {
|
|
188
|
+
result.retries = parseInt(params.get("retries"), 10);
|
|
189
|
+
}
|
|
190
|
+
if (params.has("retry_backoff_ms")) {
|
|
191
|
+
result.retryBackoffMs = parseInt(params.get("retry_backoff_ms"), 10);
|
|
192
|
+
}
|
|
193
|
+
if (params.has("retry_backoff_max_ms")) {
|
|
194
|
+
result.retryBackoffMaxMs = parseInt(params.get("retry_backoff_max_ms"), 10);
|
|
195
|
+
}
|
|
196
|
+
if (params.has("resend_write")) {
|
|
197
|
+
const val = params.get("resend_write").toLowerCase();
|
|
198
|
+
result.resendWrite = val === "true" || val === "1";
|
|
199
|
+
}
|
|
200
|
+
return result;
|
|
201
|
+
}
|
|
@@ -1,5 +1,7 @@
|
|
|
1
|
+
import { TmqConfig } from "../tmq/config";
|
|
1
2
|
import { WSConfig } from "./config";
|
|
2
|
-
|
|
3
|
+
import { Dsn } from "./dsn";
|
|
4
|
+
export declare function getDsn(wsConfig: WSConfig): Dsn;
|
|
3
5
|
export declare function isEmpty(value: any): boolean;
|
|
4
6
|
export declare function getBinarySql(action: bigint, reqId: bigint, resultId: bigint, sql?: string): ArrayBuffer;
|
|
5
7
|
export declare function zigzagDecode(n: number): number;
|
|
@@ -15,4 +17,7 @@ export declare function safeDecodeURIComponent(str: string): string;
|
|
|
15
17
|
*/
|
|
16
18
|
export declare function compareVersions(v1: string, v2: string): number;
|
|
17
19
|
export declare function decimalToString(valueStr: string, fields_scale: bigint | null): string;
|
|
20
|
+
export declare function maskSensitiveForLog(message: string): string;
|
|
21
|
+
export declare function maskUrlForLog(url: URL | null): string;
|
|
22
|
+
export declare function maskTmqConfigForLog(config: TmqConfig): string;
|
|
18
23
|
//# sourceMappingURL=utils.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../../src/common/utils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAC;
|
|
1
|
+
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../../src/common/utils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAC1C,OAAO,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAC;AACpC,OAAO,EAAE,GAAG,EAAS,MAAM,OAAO,CAAC;AAGnC,wBAAgB,MAAM,CAAC,QAAQ,EAAE,QAAQ,GAAG,GAAG,CA0C9C;AAED,wBAAgB,OAAO,CAAC,KAAK,EAAE,GAAG,GAAG,OAAO,CAI3C;AAED,wBAAgB,YAAY,CACxB,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,MAAM,EACb,QAAQ,EAAE,MAAM,EAChB,GAAG,CAAC,EAAE,MAAM,GACb,WAAW,CA2Bb;AAED,wBAAgB,YAAY,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAE9C;AAED,wBAAgB,sBAAsB,CAAC,GAAG,EAAE,MAAM,UAWjD;AAED;;;;;;;;GAQG;AACH,wBAAgB,eAAe,CAAC,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,MAAM,CAW9D;AAkDD,wBAAgB,eAAe,CAC3B,QAAQ,EAAE,MAAM,EAChB,YAAY,EAAE,MAAM,GAAG,IAAI,GAC5B,MAAM,CAkBR;AAKD,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAE3D;AAED,wBAAgB,aAAa,CAAC,GAAG,EAAE,GAAG,GAAG,IAAI,GAAG,MAAM,CAcrD;AAED,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,SAAS,GAAG,MAAM,CAmB7D"}
|
package/lib/src/common/utils.js
CHANGED
|
@@ -1,49 +1,65 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
3
|
+
exports.getDsn = getDsn;
|
|
4
4
|
exports.isEmpty = isEmpty;
|
|
5
5
|
exports.getBinarySql = getBinarySql;
|
|
6
6
|
exports.zigzagDecode = zigzagDecode;
|
|
7
7
|
exports.safeDecodeURIComponent = safeDecodeURIComponent;
|
|
8
8
|
exports.compareVersions = compareVersions;
|
|
9
9
|
exports.decimalToString = decimalToString;
|
|
10
|
+
exports.maskSensitiveForLog = maskSensitiveForLog;
|
|
11
|
+
exports.maskUrlForLog = maskUrlForLog;
|
|
12
|
+
exports.maskTmqConfigForLog = maskTmqConfigForLog;
|
|
13
|
+
const dsn_1 = require("./dsn");
|
|
10
14
|
const wsError_1 = require("./wsError");
|
|
11
|
-
function
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
+
function getDsn(wsConfig) {
|
|
16
|
+
const dsn = (0, dsn_1.parse)(wsConfig.getUrl());
|
|
17
|
+
const user = wsConfig.getUser();
|
|
18
|
+
if (user) {
|
|
19
|
+
dsn.username = user;
|
|
15
20
|
}
|
|
16
|
-
|
|
17
|
-
|
|
21
|
+
const password = wsConfig.getPwd();
|
|
22
|
+
if (password) {
|
|
23
|
+
dsn.password = password;
|
|
18
24
|
}
|
|
19
|
-
|
|
25
|
+
const token = wsConfig.getToken();
|
|
20
26
|
if (token) {
|
|
21
|
-
|
|
27
|
+
dsn.params.set("token", token);
|
|
22
28
|
}
|
|
23
|
-
|
|
29
|
+
else if (dsn.params.has("token")) {
|
|
30
|
+
wsConfig.setToken(dsn.params.get("token") || "");
|
|
31
|
+
}
|
|
32
|
+
const bearerToken = wsConfig.getBearerToken();
|
|
33
|
+
if (bearerToken) {
|
|
34
|
+
dsn.params.set("bearer_token", bearerToken);
|
|
35
|
+
}
|
|
36
|
+
else if (dsn.params.has("bearer_token")) {
|
|
37
|
+
wsConfig.setBearerToken(dsn.params.get("bearer_token") || "");
|
|
38
|
+
}
|
|
39
|
+
const timezone = wsConfig.getTimezone();
|
|
24
40
|
if (timezone) {
|
|
25
|
-
|
|
41
|
+
dsn.params.set("timezone", timezone);
|
|
26
42
|
}
|
|
27
|
-
if (
|
|
28
|
-
wsConfig.
|
|
43
|
+
else if (dsn.params.has("timezone")) {
|
|
44
|
+
wsConfig.setTimezone(dsn.params.get("timezone") || "");
|
|
29
45
|
}
|
|
30
|
-
|
|
31
|
-
|
|
46
|
+
const db = wsConfig.getDb();
|
|
47
|
+
if (db && db.length > 0) {
|
|
48
|
+
dsn.database = db;
|
|
32
49
|
}
|
|
33
|
-
|
|
34
|
-
|
|
50
|
+
else if (dsn.database.length > 0) {
|
|
51
|
+
wsConfig.setDb(dsn.database);
|
|
52
|
+
}
|
|
53
|
+
return dsn;
|
|
35
54
|
}
|
|
36
55
|
function isEmpty(value) {
|
|
37
56
|
if (value === null || value === undefined)
|
|
38
57
|
return true;
|
|
39
|
-
// if (typeof value === 'string' && value.trim() === '') return true;
|
|
40
58
|
if (Array.isArray(value) && value.length === 0)
|
|
41
59
|
return true;
|
|
42
|
-
// if (typeof value === 'object' && Object.keys(value).length === 0) return true;
|
|
43
60
|
return false;
|
|
44
61
|
}
|
|
45
62
|
function getBinarySql(action, reqId, resultId, sql) {
|
|
46
|
-
// construct msg
|
|
47
63
|
if (sql) {
|
|
48
64
|
const encoder = new TextEncoder();
|
|
49
65
|
const buffer = encoder.encode(sql);
|
|
@@ -153,12 +169,10 @@ function decimalToString(valueStr, fields_scale) {
|
|
|
153
169
|
const isNegative = decimalStr.startsWith("-");
|
|
154
170
|
const absStr = isNegative ? decimalStr.slice(1) : decimalStr;
|
|
155
171
|
if (absStr.length <= scale) {
|
|
156
|
-
// If the length of the number is less than or equal to the precision, add 0 before it.
|
|
157
172
|
const paddedStr = absStr.padStart(scale + 1, "0");
|
|
158
173
|
decimalStr = (isNegative ? "-" : "") + "0." + paddedStr.slice(1);
|
|
159
174
|
}
|
|
160
175
|
else {
|
|
161
|
-
// 在指定位置插入小数点
|
|
162
176
|
const integerPart = absStr.slice(0, absStr.length - scale);
|
|
163
177
|
const decimalPart = absStr.slice(absStr.length - scale);
|
|
164
178
|
decimalStr =
|
|
@@ -167,3 +181,41 @@ function decimalToString(valueStr, fields_scale) {
|
|
|
167
181
|
}
|
|
168
182
|
return decimalStr;
|
|
169
183
|
}
|
|
184
|
+
const SENSITIVE_FIELD_REGEX = /("(?:password|token|bearer_token|td\.connect\.token)"\s*:\s*)"([^"\\]*(?:\\.[^"\\]*)*)"/g;
|
|
185
|
+
function maskSensitiveForLog(message) {
|
|
186
|
+
return message.replace(SENSITIVE_FIELD_REGEX, '$1"[REDACTED]"');
|
|
187
|
+
}
|
|
188
|
+
function maskUrlForLog(url) {
|
|
189
|
+
if (!url) {
|
|
190
|
+
return "";
|
|
191
|
+
}
|
|
192
|
+
const masked = new URL(url.toString());
|
|
193
|
+
masked.password = "[REDACTED]";
|
|
194
|
+
if (masked.searchParams.has("token")) {
|
|
195
|
+
masked.searchParams.set("token", "[REDACTED]");
|
|
196
|
+
}
|
|
197
|
+
if (masked.searchParams.has("bearer_token")) {
|
|
198
|
+
masked.searchParams.set("bearer_token", "[REDACTED]");
|
|
199
|
+
}
|
|
200
|
+
return masked.toString().replace(/%5BREDACTED%5D/g, "[REDACTED]");
|
|
201
|
+
}
|
|
202
|
+
function maskTmqConfigForLog(config) {
|
|
203
|
+
const masked = {
|
|
204
|
+
...config,
|
|
205
|
+
otherConfigs: Object.fromEntries(config.otherConfigs)
|
|
206
|
+
};
|
|
207
|
+
return JSON.stringify(masked, (key, value) => {
|
|
208
|
+
switch (key) {
|
|
209
|
+
case 'dsn':
|
|
210
|
+
case 'sqlDsn':
|
|
211
|
+
return value ? value.toString() : value;
|
|
212
|
+
case 'token':
|
|
213
|
+
case 'password':
|
|
214
|
+
case 'bearer_token':
|
|
215
|
+
case 'td.connect.token':
|
|
216
|
+
return value ? '[REDACTED]' : value;
|
|
217
|
+
default:
|
|
218
|
+
return value;
|
|
219
|
+
}
|
|
220
|
+
});
|
|
221
|
+
}
|