@tigeropenapi/tigeropen 0.1.0 → 0.4.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/README.md +475 -104
- package/dist/cjs/client/api-request.js +16 -10
- package/dist/cjs/client/api-response.js +23 -3
- package/dist/cjs/client/case-convert.js +35 -0
- package/dist/cjs/client/http-client.js +47 -21
- package/dist/cjs/client/index.js +6 -2
- package/dist/cjs/config/client-config.js +130 -49
- package/dist/cjs/config/domain.js +21 -2
- package/dist/cjs/config/index.js +3 -1
- package/dist/cjs/index.js +1 -1
- package/dist/cjs/model/contract.js +1 -2
- package/dist/cjs/model/enums.js +89 -7
- package/dist/cjs/model/order-helpers.js +9 -9
- package/dist/cjs/model/order-status.js +46 -0
- package/dist/cjs/model/order.js +5 -2
- package/dist/cjs/model/position.js +1 -2
- package/dist/cjs/model/quote-requests.js +11 -0
- package/dist/cjs/model/quote.js +7 -0
- package/dist/cjs/model/trade-requests.js +13 -0
- package/dist/cjs/model/trade.js +2 -0
- package/dist/cjs/push/index.js +6 -3
- package/dist/cjs/push/pb/AssetData.js +208 -0
- package/dist/cjs/push/pb/KlineData.js +184 -0
- package/dist/cjs/push/pb/OptionTopData.js +427 -0
- package/dist/cjs/push/pb/OrderStatusData.js +592 -0
- package/dist/cjs/push/pb/OrderTransactionData.js +256 -0
- package/dist/cjs/push/pb/PositionData.js +316 -0
- package/dist/cjs/push/pb/PushData.js +219 -0
- package/dist/cjs/push/pb/QuoteBBOData.js +160 -0
- package/dist/cjs/push/pb/QuoteBasicData.js +329 -0
- package/dist/cjs/push/pb/QuoteData.js +507 -0
- package/dist/cjs/push/pb/QuoteDepthData.js +220 -0
- package/dist/cjs/push/pb/Request.js +278 -0
- package/dist/cjs/push/pb/Response.js +97 -0
- package/dist/cjs/push/pb/SocketCommon.js +86 -0
- package/dist/cjs/push/pb/StockTopData.js +199 -0
- package/dist/cjs/push/pb/TickData.js +202 -0
- package/dist/cjs/push/pb/TradeTickData.js +308 -0
- package/dist/cjs/push/pb/index.js +49 -0
- package/dist/cjs/push/proto-message.js +135 -0
- package/dist/cjs/push/push-client.js +361 -163
- package/dist/cjs/push/push-message.js +8 -60
- package/dist/cjs/push/varint.js +76 -0
- package/dist/cjs/quote/index.js +3 -2
- package/dist/cjs/quote/quote-client.js +440 -94
- package/dist/cjs/signer/signer.js +10 -10
- package/dist/cjs/trade/trade-client.js +197 -62
- package/dist/esm/client/api-request.js +14 -8
- package/dist/esm/client/api-response.js +22 -3
- package/dist/esm/client/case-convert.js +31 -0
- package/dist/esm/client/http-client.js +48 -22
- package/dist/esm/client/index.js +3 -2
- package/dist/esm/config/client-config.js +131 -51
- package/dist/esm/config/domain.js +20 -2
- package/dist/esm/config/index.js +2 -2
- package/dist/esm/index.js +1 -1
- package/dist/esm/model/contract.js +1 -2
- package/dist/esm/model/enums.js +87 -6
- package/dist/esm/model/order-helpers.js +9 -9
- package/dist/esm/model/order-status.js +43 -0
- package/dist/esm/model/order.js +5 -2
- package/dist/esm/model/position.js +1 -2
- package/dist/esm/model/quote-requests.js +10 -0
- package/dist/esm/model/quote.js +6 -0
- package/dist/esm/model/trade-requests.js +12 -0
- package/dist/esm/model/trade.js +1 -0
- package/dist/esm/push/index.js +4 -2
- package/dist/esm/push/pb/AssetData.js +205 -0
- package/dist/esm/push/pb/KlineData.js +181 -0
- package/dist/esm/push/pb/OptionTopData.js +424 -0
- package/dist/esm/push/pb/OrderStatusData.js +589 -0
- package/dist/esm/push/pb/OrderTransactionData.js +253 -0
- package/dist/esm/push/pb/PositionData.js +313 -0
- package/dist/esm/push/pb/PushData.js +216 -0
- package/dist/esm/push/pb/QuoteBBOData.js +157 -0
- package/dist/esm/push/pb/QuoteBasicData.js +326 -0
- package/dist/esm/push/pb/QuoteData.js +504 -0
- package/dist/esm/push/pb/QuoteDepthData.js +217 -0
- package/dist/esm/push/pb/Request.js +275 -0
- package/dist/esm/push/pb/Response.js +94 -0
- package/dist/esm/push/pb/SocketCommon.js +83 -0
- package/dist/esm/push/pb/StockTopData.js +196 -0
- package/dist/esm/push/pb/TickData.js +199 -0
- package/dist/esm/push/pb/TradeTickData.js +305 -0
- package/dist/esm/push/pb/index.js +25 -0
- package/dist/esm/push/proto-message.js +127 -0
- package/dist/esm/push/push-client.js +329 -164
- package/dist/esm/push/push-message.js +7 -56
- package/dist/esm/push/varint.js +72 -0
- package/dist/esm/quote/index.js +2 -2
- package/dist/esm/quote/quote-client.js +439 -94
- package/dist/esm/signer/signer.js +10 -10
- package/dist/esm/trade/trade-client.js +197 -62
- package/dist/types/client/api-request.d.ts +12 -11
- package/dist/types/client/api-response.d.ts +15 -7
- package/dist/types/client/case-convert.d.ts +16 -0
- package/dist/types/client/http-client.d.ts +26 -14
- package/dist/types/client/index.d.ts +3 -2
- package/dist/types/config/client-config.d.ts +29 -13
- package/dist/types/config/domain.d.ts +9 -0
- package/dist/types/config/index.d.ts +2 -2
- package/dist/types/index.d.ts +1 -1
- package/dist/types/model/contract.d.ts +13 -29
- package/dist/types/model/enums.d.ts +60 -6
- package/dist/types/model/order-helpers.d.ts +21 -20
- package/dist/types/model/order-status.d.ts +14 -0
- package/dist/types/model/order.d.ts +101 -55
- package/dist/types/model/position.d.ts +26 -24
- package/dist/types/model/quote-requests.d.ts +344 -0
- package/dist/types/model/quote.d.ts +572 -0
- package/dist/types/model/trade-requests.d.ts +195 -0
- package/dist/types/model/trade.d.ts +235 -0
- package/dist/types/push/callbacks.d.ts +32 -51
- package/dist/types/push/index.d.ts +5 -3
- package/dist/types/push/pb/AssetData.d.ts +47 -0
- package/dist/types/push/pb/KlineData.d.ts +43 -0
- package/dist/types/push/pb/OptionTopData.d.ts +76 -0
- package/dist/types/push/pb/OrderStatusData.d.ts +100 -0
- package/dist/types/push/pb/OrderTransactionData.d.ts +51 -0
- package/dist/types/push/pb/PositionData.d.ts +63 -0
- package/dist/types/push/pb/PushData.d.ts +46 -0
- package/dist/types/push/pb/QuoteBBOData.d.ts +35 -0
- package/dist/types/push/pb/QuoteBasicData.d.ts +66 -0
- package/dist/types/push/pb/QuoteData.d.ts +94 -0
- package/dist/types/push/pb/QuoteDepthData.d.ts +37 -0
- package/dist/types/push/pb/Request.d.ts +44 -0
- package/dist/types/push/pb/Response.d.ts +30 -0
- package/dist/types/push/pb/SocketCommon.d.ts +64 -0
- package/dist/types/push/pb/StockTopData.d.ts +37 -0
- package/dist/types/push/pb/TickData.d.ts +44 -0
- package/dist/types/push/pb/TradeTickData.d.ts +53 -0
- package/dist/types/push/pb/index.d.ts +39 -0
- package/dist/types/push/proto-message.d.ts +33 -0
- package/dist/types/push/push-client.d.ts +100 -68
- package/dist/types/push/push-message.d.ts +7 -147
- package/dist/types/push/varint.d.ts +23 -0
- package/dist/types/quote/index.d.ts +2 -2
- package/dist/types/quote/quote-client.d.ts +154 -47
- package/dist/types/signer/signer.d.ts +6 -6
- package/dist/types/trade/trade-client.d.ts +106 -38
- package/package.json +11 -6
|
@@ -1,17 +1,23 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
/**
|
|
3
|
-
* API 请求构造模块
|
|
4
|
-
*/
|
|
5
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
3
|
exports.createApiRequest = createApiRequest;
|
|
7
4
|
/**
|
|
8
|
-
*
|
|
5
|
+
* API request builder.
|
|
6
|
+
*
|
|
7
|
+
* Requests use camelCase parameters in TypeScript (idiomatic), but the
|
|
8
|
+
* server wire format is snake_case, so we convert keys before serializing.
|
|
9
|
+
*/
|
|
10
|
+
const case_convert_1 = require("./case-convert");
|
|
11
|
+
/**
|
|
12
|
+
* Create an API request, serializing business parameters to JSON as bizContent.
|
|
13
|
+
* camelCase keys are automatically converted to snake_case to match the server.
|
|
9
14
|
*
|
|
10
|
-
* @param method - API
|
|
11
|
-
* @param bizParams -
|
|
12
|
-
* @
|
|
15
|
+
* @param method - API method name
|
|
16
|
+
* @param bizParams - Business parameters (object, string, or null); objects are converted recursively
|
|
17
|
+
* @param version - Optional API version override
|
|
18
|
+
* @returns ApiRequest object
|
|
13
19
|
*/
|
|
14
|
-
function createApiRequest(method, bizParams) {
|
|
20
|
+
function createApiRequest(method, bizParams, version) {
|
|
15
21
|
let bizContent;
|
|
16
22
|
if (typeof bizParams === 'string') {
|
|
17
23
|
bizContent = bizParams;
|
|
@@ -20,7 +26,7 @@ function createApiRequest(method, bizParams) {
|
|
|
20
26
|
bizContent = '{}';
|
|
21
27
|
}
|
|
22
28
|
else {
|
|
23
|
-
bizContent = JSON.stringify(bizParams);
|
|
29
|
+
bizContent = JSON.stringify((0, case_convert_1.keysToSnakeCase)(bizParams));
|
|
24
30
|
}
|
|
25
|
-
return { method, bizContent };
|
|
31
|
+
return { method, bizContent, version };
|
|
26
32
|
}
|
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.parseApiResponse = parseApiResponse;
|
|
4
|
+
exports.unmarshalData = unmarshalData;
|
|
4
5
|
/**
|
|
5
|
-
* API
|
|
6
|
+
* API response parsing.
|
|
6
7
|
*/
|
|
7
8
|
const errors_1 = require("./errors");
|
|
8
9
|
/**
|
|
9
|
-
*
|
|
10
|
-
*
|
|
10
|
+
* Parse the raw HTTP response body.
|
|
11
|
+
* Throws TigerError when code != 0.
|
|
11
12
|
*/
|
|
12
13
|
function parseApiResponse(body) {
|
|
13
14
|
const resp = JSON.parse(body);
|
|
@@ -16,3 +17,22 @@ function parseApiResponse(body) {
|
|
|
16
17
|
}
|
|
17
18
|
return resp;
|
|
18
19
|
}
|
|
20
|
+
/**
|
|
21
|
+
* Decode an ApiResponse.data payload into a typed value.
|
|
22
|
+
* Handles the server's occasional double-encoded JSON (where `data` is a
|
|
23
|
+
* JSON string that itself wraps JSON), seen on some trade endpoints.
|
|
24
|
+
*/
|
|
25
|
+
function unmarshalData(data) {
|
|
26
|
+
if (data == null)
|
|
27
|
+
return undefined;
|
|
28
|
+
if (typeof data === 'string') {
|
|
29
|
+
// Attempt to parse JSON string (double-encoded case)
|
|
30
|
+
try {
|
|
31
|
+
return JSON.parse(data);
|
|
32
|
+
}
|
|
33
|
+
catch {
|
|
34
|
+
return data;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
return data;
|
|
38
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Case conversion utilities.
|
|
4
|
+
*
|
|
5
|
+
* TypeScript SDK uses camelCase idiomatically. The server expects
|
|
6
|
+
* snake_case for request field names and returns camelCase for responses.
|
|
7
|
+
* These helpers convert camelCase objects to snake_case before
|
|
8
|
+
* serialization; response side needs no conversion.
|
|
9
|
+
*/
|
|
10
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
11
|
+
exports.camelToSnake = camelToSnake;
|
|
12
|
+
exports.keysToSnakeCase = keysToSnakeCase;
|
|
13
|
+
/** Convert a single camelCase key to snake_case. */
|
|
14
|
+
function camelToSnake(key) {
|
|
15
|
+
return key.replace(/[A-Z]/g, (c) => '_' + c.toLowerCase());
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Recursively convert all object keys from camelCase to snake_case.
|
|
19
|
+
* Preserves arrays, primitives, and Date/null/undefined.
|
|
20
|
+
* Keys already containing an underscore are kept as-is (already snake_case).
|
|
21
|
+
*/
|
|
22
|
+
function keysToSnakeCase(value) {
|
|
23
|
+
if (Array.isArray(value)) {
|
|
24
|
+
return value.map((v) => keysToSnakeCase(v));
|
|
25
|
+
}
|
|
26
|
+
if (value && typeof value === 'object' && value.constructor === Object) {
|
|
27
|
+
const out = {};
|
|
28
|
+
for (const [k, v] of Object.entries(value)) {
|
|
29
|
+
const newKey = k.includes('_') ? k : camelToSnake(k);
|
|
30
|
+
out[newKey] = keysToSnakeCase(v);
|
|
31
|
+
}
|
|
32
|
+
return out;
|
|
33
|
+
}
|
|
34
|
+
return value;
|
|
35
|
+
}
|
|
@@ -7,7 +7,7 @@ const errors_1 = require("./errors");
|
|
|
7
7
|
const retry_1 = require("./retry");
|
|
8
8
|
const api_response_1 = require("./api-response");
|
|
9
9
|
/** SDK 版本号 */
|
|
10
|
-
const SDK_VERSION = '0.
|
|
10
|
+
const SDK_VERSION = '0.4.0';
|
|
11
11
|
/** User-Agent 字符串 */
|
|
12
12
|
const USER_AGENT = `openapi-typescript-sdk-${SDK_VERSION}`;
|
|
13
13
|
/** 默认字符集 */
|
|
@@ -17,29 +17,33 @@ const DEFAULT_SIGN_TYPE = 'RSA';
|
|
|
17
17
|
/** 默认 API 版本 */
|
|
18
18
|
const DEFAULT_VERSION = '2.0';
|
|
19
19
|
/**
|
|
20
|
-
* HttpClient
|
|
20
|
+
* HttpClient handles HTTP requests, signing, retry, and timeout
|
|
21
21
|
*/
|
|
22
22
|
class HttpClient {
|
|
23
|
-
constructor(config, retryPolicy) {
|
|
23
|
+
constructor(config, retryPolicy, options) {
|
|
24
24
|
this.config = config;
|
|
25
25
|
this.retryPolicy = retryPolicy ?? (0, retry_1.defaultRetryPolicy)();
|
|
26
|
+
this.targetUrl = options?.useQuoteServerUrl ? config.quoteServerUrl : config.serverUrl;
|
|
26
27
|
}
|
|
27
28
|
/**
|
|
28
|
-
*
|
|
29
|
+
* Build common request parameters
|
|
29
30
|
*/
|
|
30
|
-
buildCommonParams(apiMethod, bizContent) {
|
|
31
|
+
buildCommonParams(apiMethod, bizContent, version) {
|
|
31
32
|
const params = {
|
|
32
33
|
tiger_id: this.config.tigerId,
|
|
33
34
|
method: apiMethod,
|
|
34
35
|
charset: DEFAULT_CHARSET,
|
|
35
36
|
sign_type: DEFAULT_SIGN_TYPE,
|
|
36
37
|
timestamp: new Date().toISOString().replace('T', ' ').substring(0, 19),
|
|
37
|
-
version: DEFAULT_VERSION,
|
|
38
|
+
version: version || DEFAULT_VERSION,
|
|
38
39
|
biz_content: bizContent,
|
|
39
40
|
};
|
|
40
41
|
if (this.config.language) {
|
|
41
42
|
params['language'] = this.config.language;
|
|
42
43
|
}
|
|
44
|
+
if (this.config.deviceId) {
|
|
45
|
+
params['device_id'] = this.config.deviceId;
|
|
46
|
+
}
|
|
43
47
|
return params;
|
|
44
48
|
}
|
|
45
49
|
/**
|
|
@@ -50,7 +54,7 @@ class HttpClient {
|
|
|
50
54
|
return (0, signer_1.signWithRSA)(this.config.privateKey, content);
|
|
51
55
|
}
|
|
52
56
|
/**
|
|
53
|
-
*
|
|
57
|
+
* Send HTTP POST request
|
|
54
58
|
*/
|
|
55
59
|
async doHttpPost(params) {
|
|
56
60
|
const body = JSON.stringify(params);
|
|
@@ -61,7 +65,7 @@ class HttpClient {
|
|
|
61
65
|
if (this.config.token) {
|
|
62
66
|
headers['Authorization'] = this.config.token;
|
|
63
67
|
}
|
|
64
|
-
const response = await fetch(this.
|
|
68
|
+
const response = await fetch(this.targetUrl, {
|
|
65
69
|
method: 'POST',
|
|
66
70
|
headers,
|
|
67
71
|
body,
|
|
@@ -70,11 +74,11 @@ class HttpClient {
|
|
|
70
74
|
return response.text();
|
|
71
75
|
}
|
|
72
76
|
/**
|
|
73
|
-
*
|
|
74
|
-
*
|
|
77
|
+
* Execute a structured API request, returning a parsed ApiResponse.
|
|
78
|
+
* Used internally by QuoteClient/TradeClient.
|
|
75
79
|
*/
|
|
76
80
|
async executeRequest(request) {
|
|
77
|
-
const params = this.buildCommonParams(request.method, request.bizContent);
|
|
81
|
+
const params = this.buildCommonParams(request.method, request.bizContent, request.version);
|
|
78
82
|
const sign = this.signParams(params);
|
|
79
83
|
params['sign'] = sign;
|
|
80
84
|
let lastErr;
|
|
@@ -88,7 +92,9 @@ class HttpClient {
|
|
|
88
92
|
}
|
|
89
93
|
try {
|
|
90
94
|
const body = await this.doHttpPost(params);
|
|
91
|
-
|
|
95
|
+
const response = (0, api_response_1.parseApiResponse)(body);
|
|
96
|
+
this.verifyResponseSign(params['timestamp'], response.sign);
|
|
97
|
+
return response;
|
|
92
98
|
}
|
|
93
99
|
catch (err) {
|
|
94
100
|
lastErr = err;
|
|
@@ -100,22 +106,22 @@ class HttpClient {
|
|
|
100
106
|
throw lastErr;
|
|
101
107
|
}
|
|
102
108
|
/**
|
|
103
|
-
*
|
|
109
|
+
* General-purpose API call method.
|
|
104
110
|
*
|
|
105
|
-
* @param apiMethod - API
|
|
106
|
-
* @param requestJson -
|
|
107
|
-
* @returns
|
|
111
|
+
* @param apiMethod - API method name (e.g. "market_state", "place_order")
|
|
112
|
+
* @param requestJson - Raw biz_content JSON string
|
|
113
|
+
* @returns Raw response JSON string, unparsed
|
|
108
114
|
*/
|
|
109
115
|
async execute(apiMethod, requestJson) {
|
|
110
|
-
//
|
|
116
|
+
// Parameter validation
|
|
111
117
|
if (!apiMethod) {
|
|
112
|
-
throw new errors_1.TigerError(-1, 'api_method
|
|
118
|
+
throw new errors_1.TigerError(-1, 'api_method must not be empty');
|
|
113
119
|
}
|
|
114
120
|
try {
|
|
115
121
|
JSON.parse(requestJson);
|
|
116
122
|
}
|
|
117
123
|
catch {
|
|
118
|
-
throw new errors_1.TigerError(-1, 'request_json
|
|
124
|
+
throw new errors_1.TigerError(-1, 'request_json is not valid JSON');
|
|
119
125
|
}
|
|
120
126
|
const params = this.buildCommonParams(apiMethod, requestJson);
|
|
121
127
|
const sign = this.signParams(params);
|
|
@@ -130,7 +136,11 @@ class HttpClient {
|
|
|
130
136
|
await this.sleep(backoff);
|
|
131
137
|
}
|
|
132
138
|
try {
|
|
133
|
-
|
|
139
|
+
const body = await this.doHttpPost(params);
|
|
140
|
+
// Verify response signature even for raw responses
|
|
141
|
+
const parsed = JSON.parse(body);
|
|
142
|
+
this.verifyResponseSign(params['timestamp'], parsed.sign);
|
|
143
|
+
return body;
|
|
134
144
|
}
|
|
135
145
|
catch (err) {
|
|
136
146
|
lastErr = err;
|
|
@@ -141,9 +151,25 @@ class HttpClient {
|
|
|
141
151
|
}
|
|
142
152
|
throw lastErr;
|
|
143
153
|
}
|
|
144
|
-
/**
|
|
154
|
+
/** Delay for the specified milliseconds */
|
|
145
155
|
sleep(ms) {
|
|
146
156
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
147
157
|
}
|
|
158
|
+
/**
|
|
159
|
+
* Verify the response signature using the tiger public key.
|
|
160
|
+
*
|
|
161
|
+
* @param timestamp - The timestamp sent in the request params
|
|
162
|
+
* @param signBase64 - The `sign` field from the response body
|
|
163
|
+
* @throws TigerError if the signature is missing or invalid
|
|
164
|
+
*/
|
|
165
|
+
verifyResponseSign(timestamp, signBase64) {
|
|
166
|
+
if (!signBase64) {
|
|
167
|
+
throw new errors_1.TigerError(-1, 'Response signature is missing');
|
|
168
|
+
}
|
|
169
|
+
const valid = (0, signer_1.verifyWithRSA)(this.config.tigerPublicKey, timestamp, signBase64);
|
|
170
|
+
if (!valid) {
|
|
171
|
+
throw new errors_1.TigerError(-1, 'Response signature verification failed');
|
|
172
|
+
}
|
|
173
|
+
}
|
|
148
174
|
}
|
|
149
175
|
exports.HttpClient = HttpClient;
|
package/dist/cjs/client/index.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.parseApiResponse = exports.createApiRequest = exports.isTradeOperation = exports.defaultRetryPolicy = exports.RetryPolicy = exports.classifyErrorCode = exports.TigerError = exports.HttpClient = void 0;
|
|
3
|
+
exports.keysToSnakeCase = exports.camelToSnake = exports.unmarshalData = exports.parseApiResponse = exports.createApiRequest = exports.isTradeOperation = exports.defaultRetryPolicy = exports.RetryPolicy = exports.classifyErrorCode = exports.TigerError = exports.HttpClient = void 0;
|
|
4
4
|
/**
|
|
5
|
-
*
|
|
5
|
+
* Transport layer exports.
|
|
6
6
|
*/
|
|
7
7
|
var http_client_1 = require("./http-client");
|
|
8
8
|
Object.defineProperty(exports, "HttpClient", { enumerable: true, get: function () { return http_client_1.HttpClient; } });
|
|
@@ -17,3 +17,7 @@ var api_request_1 = require("./api-request");
|
|
|
17
17
|
Object.defineProperty(exports, "createApiRequest", { enumerable: true, get: function () { return api_request_1.createApiRequest; } });
|
|
18
18
|
var api_response_1 = require("./api-response");
|
|
19
19
|
Object.defineProperty(exports, "parseApiResponse", { enumerable: true, get: function () { return api_response_1.parseApiResponse; } });
|
|
20
|
+
Object.defineProperty(exports, "unmarshalData", { enumerable: true, get: function () { return api_response_1.unmarshalData; } });
|
|
21
|
+
var case_convert_1 = require("./case-convert");
|
|
22
|
+
Object.defineProperty(exports, "camelToSnake", { enumerable: true, get: function () { return case_convert_1.camelToSnake; } });
|
|
23
|
+
Object.defineProperty(exports, "keysToSnakeCase", { enumerable: true, get: function () { return case_convert_1.keysToSnakeCase; } });
|
|
@@ -1,61 +1,129 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.loadPropertiesFile = loadPropertiesFile;
|
|
3
4
|
exports.createClientConfig = createClientConfig;
|
|
4
5
|
/**
|
|
5
|
-
* ClientConfig -
|
|
6
|
+
* ClientConfig - Client configuration management
|
|
6
7
|
*
|
|
7
|
-
*
|
|
8
|
-
* -
|
|
9
|
-
* -
|
|
10
|
-
* -
|
|
8
|
+
* Aggregates all configuration parameters with support for:
|
|
9
|
+
* - Direct code configuration
|
|
10
|
+
* - Properties file loading (explicit path or auto-discovery)
|
|
11
|
+
* - Environment variable overrides
|
|
11
12
|
*
|
|
12
|
-
*
|
|
13
|
+
* Priority: environment variables > code options (incl. config file) > defaults
|
|
13
14
|
*/
|
|
14
15
|
const fs_1 = require("fs");
|
|
16
|
+
const path_1 = require("path");
|
|
17
|
+
const os_1 = require("os");
|
|
15
18
|
const config_parser_1 = require("./config-parser");
|
|
16
19
|
const domain_1 = require("./domain");
|
|
17
|
-
/**
|
|
20
|
+
/** Default config file name */
|
|
21
|
+
const CONFIG_FILE_NAME = 'tiger_openapi_config.properties';
|
|
22
|
+
/** Defaults */
|
|
18
23
|
const DEFAULT_LANGUAGE = 'zh_CN';
|
|
19
24
|
const DEFAULT_TIMEOUT = 15;
|
|
20
25
|
const DEFAULT_SERVER_URL = 'https://openapi.tigerfintech.com/gateway';
|
|
21
|
-
|
|
22
|
-
|
|
26
|
+
/** Tiger public key for response signature verification (Base64-encoded) */
|
|
27
|
+
const TIGER_PUBLIC_KEY = 'MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDNF3G8SoEcCZh2rshUbayDgLLrj6rKgzNMxDL2HSnKcB0+GPOsndqSv+a4IBu9+I3fyBp5hkyMMG2+AXugd9pMpy6VxJxlNjhX1MYbNTZJUT4nudki4uh+LMOkIBHOceGNXjgB+cXqmlUnjlqha/HgboeHSnSgpM3dKSJQlIOsDwIDAQAB';
|
|
28
|
+
/** Environment variable names */
|
|
23
29
|
const ENV_TIGER_ID = 'TIGEROPEN_TIGER_ID';
|
|
24
30
|
const ENV_PRIVATE_KEY = 'TIGEROPEN_PRIVATE_KEY';
|
|
25
31
|
const ENV_ACCOUNT = 'TIGEROPEN_ACCOUNT';
|
|
32
|
+
const ENV_TOKEN = 'TIGEROPEN_TOKEN';
|
|
26
33
|
/**
|
|
27
|
-
*
|
|
34
|
+
* Load and parse a Java-style properties file.
|
|
28
35
|
*
|
|
29
|
-
*
|
|
30
|
-
*
|
|
36
|
+
* @param filePath - Absolute or relative path to the properties file
|
|
37
|
+
* @returns Parsed key-value pairs, or empty object if the file cannot be read
|
|
38
|
+
*/
|
|
39
|
+
function loadPropertiesFile(filePath) {
|
|
40
|
+
try {
|
|
41
|
+
const content = (0, fs_1.readFileSync)(filePath, 'utf-8');
|
|
42
|
+
return (0, config_parser_1.parsePropertiesString)(content);
|
|
43
|
+
}
|
|
44
|
+
catch {
|
|
45
|
+
return {};
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Discover the config file by searching well-known locations.
|
|
50
|
+
*
|
|
51
|
+
* Search order:
|
|
52
|
+
* 1. `./tiger_openapi_config.properties` (current working directory)
|
|
53
|
+
* 2. `~/.tigeropen/tiger_openapi_config.properties` (home directory)
|
|
54
|
+
*
|
|
55
|
+
* @returns The resolved file path, or `undefined` if not found
|
|
56
|
+
*/
|
|
57
|
+
function discoverConfigFile() {
|
|
58
|
+
const candidates = [
|
|
59
|
+
(0, path_1.join)(process.cwd(), CONFIG_FILE_NAME),
|
|
60
|
+
(0, path_1.join)((0, os_1.homedir)(), '.tigeropen', CONFIG_FILE_NAME),
|
|
61
|
+
];
|
|
62
|
+
for (const candidate of candidates) {
|
|
63
|
+
if ((0, fs_1.existsSync)(candidate)) {
|
|
64
|
+
return candidate;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
return undefined;
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Auto-detect device identifier from the first non-internal MAC address.
|
|
31
71
|
*
|
|
32
|
-
* @
|
|
33
|
-
|
|
34
|
-
|
|
72
|
+
* @returns MAC address string, or empty string if none found
|
|
73
|
+
*/
|
|
74
|
+
function detectDeviceId() {
|
|
75
|
+
const interfaces = (0, os_1.networkInterfaces)();
|
|
76
|
+
for (const [, addrs] of Object.entries(interfaces)) {
|
|
77
|
+
if (!addrs)
|
|
78
|
+
continue;
|
|
79
|
+
for (const addr of addrs) {
|
|
80
|
+
if (!addr.internal && addr.mac && addr.mac !== '00:00:00:00:00:00') {
|
|
81
|
+
return addr.mac;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
return '';
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Create a client configuration.
|
|
89
|
+
*
|
|
90
|
+
* When called with no arguments (or without `propertiesFilePath`), the function
|
|
91
|
+
* automatically searches for `tiger_openapi_config.properties` in the current
|
|
92
|
+
* directory and `~/.tigeropen/`. Discovered values serve as defaults; explicit
|
|
93
|
+
* options and environment variables take precedence.
|
|
94
|
+
*
|
|
95
|
+
* Priority: environment variables > code options > config file > defaults
|
|
96
|
+
*
|
|
97
|
+
* @param options - Configuration options (optional)
|
|
98
|
+
* @returns Complete client configuration object
|
|
99
|
+
* @throws When tigerId or privateKey is empty after all resolution
|
|
35
100
|
*/
|
|
36
101
|
function createClientConfig(options) {
|
|
37
|
-
|
|
102
|
+
const opts = options ?? {};
|
|
103
|
+
// Load properties: explicit path > auto-discovery
|
|
38
104
|
let fileProps = {};
|
|
39
|
-
if (
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
105
|
+
if (opts.propertiesFilePath) {
|
|
106
|
+
fileProps = loadPropertiesFile(opts.propertiesFilePath);
|
|
107
|
+
}
|
|
108
|
+
else {
|
|
109
|
+
const discovered = discoverConfigFile();
|
|
110
|
+
if (discovered) {
|
|
111
|
+
fileProps = loadPropertiesFile(discovered);
|
|
46
112
|
}
|
|
47
113
|
}
|
|
48
|
-
//
|
|
49
|
-
let tigerId =
|
|
50
|
-
let privateKey =
|
|
51
|
-
let account =
|
|
52
|
-
|
|
53
|
-
const
|
|
54
|
-
const
|
|
55
|
-
|
|
114
|
+
// Merge values (code options override config file)
|
|
115
|
+
let tigerId = opts.tigerId || fileProps['tiger_id'] || '';
|
|
116
|
+
let privateKey = opts.privateKey || resolvePrivateKey(fileProps) || '';
|
|
117
|
+
let account = opts.account || fileProps['account'] || '';
|
|
118
|
+
let token = opts.token || fileProps['token'];
|
|
119
|
+
const license = opts.license || fileProps['license'];
|
|
120
|
+
const language = opts.language || fileProps['language'] || DEFAULT_LANGUAGE;
|
|
121
|
+
const timezone = opts.timezone || fileProps['timezone'];
|
|
122
|
+
// Environment variables override everything
|
|
56
123
|
const envTigerId = process.env[ENV_TIGER_ID];
|
|
57
124
|
const envPrivateKey = process.env[ENV_PRIVATE_KEY];
|
|
58
125
|
const envAccount = process.env[ENV_ACCOUNT];
|
|
126
|
+
const envToken = process.env[ENV_TOKEN];
|
|
59
127
|
if (envTigerId) {
|
|
60
128
|
tigerId = envTigerId;
|
|
61
129
|
}
|
|
@@ -65,25 +133,24 @@ function createClientConfig(options) {
|
|
|
65
133
|
if (envAccount) {
|
|
66
134
|
account = envAccount;
|
|
67
135
|
}
|
|
68
|
-
|
|
136
|
+
if (envToken) {
|
|
137
|
+
token = envToken;
|
|
138
|
+
}
|
|
139
|
+
// Validate required fields
|
|
69
140
|
if (!tigerId) {
|
|
70
|
-
throw new Error(`tigerId
|
|
141
|
+
throw new Error(`tigerId is required. Set it via options.tigerId, a config file, or the ${ENV_TIGER_ID} environment variable.`);
|
|
71
142
|
}
|
|
72
143
|
if (!privateKey) {
|
|
73
|
-
throw new Error(`privateKey
|
|
144
|
+
throw new Error(`privateKey is required. Set it via options.privateKey, a config file, or the ${ENV_PRIVATE_KEY} environment variable.`);
|
|
74
145
|
}
|
|
75
|
-
//
|
|
76
|
-
const
|
|
77
|
-
const enableDynamicDomain = options.enableDynamicDomain ?? true;
|
|
146
|
+
// Resolve server URL: explicit > dynamic domain > default
|
|
147
|
+
const enableDynamicDomain = opts.enableDynamicDomain ?? true;
|
|
78
148
|
let serverUrl;
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
else if (options.serverUrl) {
|
|
83
|
-
serverUrl = options.serverUrl;
|
|
149
|
+
let quoteServerUrl;
|
|
150
|
+
if (opts.serverUrl) {
|
|
151
|
+
serverUrl = opts.serverUrl;
|
|
84
152
|
}
|
|
85
153
|
else {
|
|
86
|
-
// 尝试动态域名获取
|
|
87
154
|
let dynamicUrl = '';
|
|
88
155
|
if (enableDynamicDomain) {
|
|
89
156
|
const domainConf = (0, domain_1.queryDomains)(license);
|
|
@@ -91,6 +158,18 @@ function createClientConfig(options) {
|
|
|
91
158
|
}
|
|
92
159
|
serverUrl = dynamicUrl || DEFAULT_SERVER_URL;
|
|
93
160
|
}
|
|
161
|
+
// Resolve quote server URL: explicit > dynamic domain > serverUrl fallback
|
|
162
|
+
if (opts.quoteServerUrl) {
|
|
163
|
+
quoteServerUrl = opts.quoteServerUrl;
|
|
164
|
+
}
|
|
165
|
+
else {
|
|
166
|
+
let dynamicQuoteUrl = '';
|
|
167
|
+
if (enableDynamicDomain) {
|
|
168
|
+
const domainConf = (0, domain_1.queryDomains)(license);
|
|
169
|
+
dynamicQuoteUrl = (0, domain_1.resolveDynamicQuoteServerUrl)(domainConf, license);
|
|
170
|
+
}
|
|
171
|
+
quoteServerUrl = dynamicQuoteUrl || serverUrl;
|
|
172
|
+
}
|
|
94
173
|
return {
|
|
95
174
|
tigerId,
|
|
96
175
|
privateKey,
|
|
@@ -98,16 +177,18 @@ function createClientConfig(options) {
|
|
|
98
177
|
license,
|
|
99
178
|
language,
|
|
100
179
|
timezone,
|
|
101
|
-
timeout:
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
tokenRefreshDuration: options.tokenRefreshDuration,
|
|
180
|
+
timeout: opts.timeout ?? DEFAULT_TIMEOUT,
|
|
181
|
+
token,
|
|
182
|
+
tokenRefreshDuration: opts.tokenRefreshDuration,
|
|
105
183
|
serverUrl,
|
|
184
|
+
quoteServerUrl,
|
|
185
|
+
deviceId: detectDeviceId(),
|
|
186
|
+
tigerPublicKey: TIGER_PUBLIC_KEY,
|
|
106
187
|
};
|
|
107
188
|
}
|
|
108
189
|
/**
|
|
109
|
-
*
|
|
110
|
-
*
|
|
190
|
+
* Resolve private key from properties.
|
|
191
|
+
* Priority: private_key > private_key_pk8 > private_key_pk1
|
|
111
192
|
*/
|
|
112
193
|
function resolvePrivateKey(props) {
|
|
113
194
|
return props['private_key'] || props['private_key_pk8'] || props['private_key_pk1'] || '';
|
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
8
8
|
exports.queryDomains = queryDomains;
|
|
9
9
|
exports.resolveDynamicServerUrl = resolveDynamicServerUrl;
|
|
10
|
+
exports.resolveDynamicQuoteServerUrl = resolveDynamicQuoteServerUrl;
|
|
10
11
|
/** 域名花园地址 */
|
|
11
12
|
const DOMAIN_GARDEN_ADDRESS = 'https://cg.play-analytics.com';
|
|
12
13
|
/** 动态域名查询超时(毫秒) */
|
|
@@ -67,8 +68,26 @@ function resolveDynamicServerUrl(domainConf, license) {
|
|
|
67
68
|
return '';
|
|
68
69
|
}
|
|
69
70
|
/**
|
|
70
|
-
*
|
|
71
|
-
*
|
|
71
|
+
* Resolve the quote server URL from dynamic domain configuration.
|
|
72
|
+
* Uses the `{LICENSE}-QUOTE` key, falling back to empty string.
|
|
73
|
+
*
|
|
74
|
+
* @param domainConf - Domain configuration map from queryDomains
|
|
75
|
+
* @param license - License type (e.g. "TBNZ")
|
|
76
|
+
* @returns Quote server URL with gateway suffix, or empty string
|
|
77
|
+
*/
|
|
78
|
+
function resolveDynamicQuoteServerUrl(domainConf, license) {
|
|
79
|
+
if (!domainConf || Object.keys(domainConf).length === 0) {
|
|
80
|
+
return '';
|
|
81
|
+
}
|
|
82
|
+
const key = license ? `${license}-QUOTE` : `${DOMAIN_KEY_COMMON}-QUOTE`;
|
|
83
|
+
if (typeof domainConf[key] === 'string') {
|
|
84
|
+
return domainConf[key] + GATEWAY_SUFFIX;
|
|
85
|
+
}
|
|
86
|
+
return '';
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Synchronous HTTP GET request (Node.js environment).
|
|
90
|
+
* Uses child_process.execSync for synchronous requests with fast timeout.
|
|
72
91
|
*/
|
|
73
92
|
function syncHttpGet(url, timeoutMs) {
|
|
74
93
|
try {
|
package/dist/cjs/config/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.resolveDynamicServerUrl = exports.queryDomains = exports.createClientConfig = exports.parsePropertiesString = exports.parsePropertiesFile = void 0;
|
|
3
|
+
exports.resolveDynamicQuoteServerUrl = exports.resolveDynamicServerUrl = exports.queryDomains = exports.loadPropertiesFile = exports.createClientConfig = exports.parsePropertiesString = exports.parsePropertiesFile = void 0;
|
|
4
4
|
/**
|
|
5
5
|
* 配置层导出
|
|
6
6
|
*/
|
|
@@ -9,6 +9,8 @@ Object.defineProperty(exports, "parsePropertiesFile", { enumerable: true, get: f
|
|
|
9
9
|
Object.defineProperty(exports, "parsePropertiesString", { enumerable: true, get: function () { return config_parser_1.parsePropertiesString; } });
|
|
10
10
|
var client_config_1 = require("./client-config");
|
|
11
11
|
Object.defineProperty(exports, "createClientConfig", { enumerable: true, get: function () { return client_config_1.createClientConfig; } });
|
|
12
|
+
Object.defineProperty(exports, "loadPropertiesFile", { enumerable: true, get: function () { return client_config_1.loadPropertiesFile; } });
|
|
12
13
|
var domain_1 = require("./domain");
|
|
13
14
|
Object.defineProperty(exports, "queryDomains", { enumerable: true, get: function () { return domain_1.queryDomains; } });
|
|
14
15
|
Object.defineProperty(exports, "resolveDynamicServerUrl", { enumerable: true, get: function () { return domain_1.resolveDynamicServerUrl; } });
|
|
16
|
+
Object.defineProperty(exports, "resolveDynamicQuoteServerUrl", { enumerable: true, get: function () { return domain_1.resolveDynamicQuoteServerUrl; } });
|
package/dist/cjs/index.js
CHANGED