@invezgo/sdk 1.0.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/LICENSE +22 -0
- package/README.md +350 -0
- package/dist/client.d.ts +21 -0
- package/dist/client.d.ts.map +1 -0
- package/dist/endpoints/ai.d.ts +98 -0
- package/dist/endpoints/ai.d.ts.map +1 -0
- package/dist/endpoints/analysis.d.ts +225 -0
- package/dist/endpoints/analysis.d.ts.map +1 -0
- package/dist/endpoints/health.d.ts +24 -0
- package/dist/endpoints/health.d.ts.map +1 -0
- package/dist/endpoints/journals.d.ts +45 -0
- package/dist/endpoints/journals.d.ts.map +1 -0
- package/dist/endpoints/membership.d.ts +33 -0
- package/dist/endpoints/membership.d.ts.map +1 -0
- package/dist/endpoints/portfolios.d.ts +14 -0
- package/dist/endpoints/portfolios.d.ts.map +1 -0
- package/dist/endpoints/posts.d.ts +42 -0
- package/dist/endpoints/posts.d.ts.map +1 -0
- package/dist/endpoints/profile.d.ts +34 -0
- package/dist/endpoints/profile.d.ts.map +1 -0
- package/dist/endpoints/screener.d.ts +34 -0
- package/dist/endpoints/screener.d.ts.map +1 -0
- package/dist/endpoints/search.d.ts +18 -0
- package/dist/endpoints/search.d.ts.map +1 -0
- package/dist/endpoints/trades.d.ts +31 -0
- package/dist/endpoints/trades.d.ts.map +1 -0
- package/dist/endpoints/watchlists.d.ts +51 -0
- package/dist/endpoints/watchlists.d.ts.map +1 -0
- package/dist/index.d.ts +18 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.esm.js +944 -0
- package/dist/index.esm.js.map +1 -0
- package/dist/index.js +944 -0
- package/dist/index.js.map +1 -0
- package/dist/invezgo.d.ts +38 -0
- package/dist/invezgo.d.ts.map +1 -0
- package/dist/types.d.ts +304 -0
- package/dist/types.d.ts.map +1 -0
- package/package.json +61 -0
package/dist/index.js
ADDED
|
@@ -0,0 +1,944 @@
|
|
|
1
|
+
class InvezgoError extends Error {
|
|
2
|
+
constructor(statusCode, message, error, response) {
|
|
3
|
+
super(message);
|
|
4
|
+
this.statusCode = statusCode;
|
|
5
|
+
this.message = message;
|
|
6
|
+
this.error = error;
|
|
7
|
+
this.response = response;
|
|
8
|
+
this.name = 'InvezgoError';
|
|
9
|
+
Object.setPrototypeOf(this, InvezgoError.prototype);
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
class HttpClient {
|
|
13
|
+
constructor(config) {
|
|
14
|
+
// Ensure baseURL doesn't have trailing slash since paths start with /
|
|
15
|
+
const baseURL = config.baseURL || 'https://api.invezgo.com';
|
|
16
|
+
this.baseURL = baseURL.endsWith('/') ? baseURL.slice(0, -1) : baseURL;
|
|
17
|
+
this.apiKey = config.apiKey;
|
|
18
|
+
this.timeout = config.timeout || 30000;
|
|
19
|
+
if (!this.apiKey) {
|
|
20
|
+
throw new Error('API Key is required');
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
async request(method, path, options = {}) {
|
|
24
|
+
const url = `${this.baseURL}${path}`;
|
|
25
|
+
const controller = new AbortController();
|
|
26
|
+
const timeoutId = setTimeout(() => controller.abort(), options.timeout || this.timeout);
|
|
27
|
+
try {
|
|
28
|
+
const headers = {
|
|
29
|
+
'Authorization': `Bearer ${this.apiKey}`,
|
|
30
|
+
'Content-Type': 'application/json',
|
|
31
|
+
...options.headers,
|
|
32
|
+
};
|
|
33
|
+
const response = await fetch(url, {
|
|
34
|
+
method,
|
|
35
|
+
headers,
|
|
36
|
+
signal: controller.signal,
|
|
37
|
+
});
|
|
38
|
+
clearTimeout(timeoutId);
|
|
39
|
+
// Handle 204 No Content
|
|
40
|
+
if (response.status === 204) {
|
|
41
|
+
return [];
|
|
42
|
+
}
|
|
43
|
+
const data = await response.json().catch(() => ({}));
|
|
44
|
+
// Handle error responses
|
|
45
|
+
if (!response.ok) {
|
|
46
|
+
throw new InvezgoError(response.status, data?.message || response.statusText, data?.error, data);
|
|
47
|
+
}
|
|
48
|
+
return data;
|
|
49
|
+
}
|
|
50
|
+
catch (error) {
|
|
51
|
+
clearTimeout(timeoutId);
|
|
52
|
+
if (error.name === 'AbortError') {
|
|
53
|
+
throw new InvezgoError(408, 'Request timeout', 'Timeout');
|
|
54
|
+
}
|
|
55
|
+
if (error instanceof InvezgoError) {
|
|
56
|
+
throw error;
|
|
57
|
+
}
|
|
58
|
+
throw new InvezgoError(500, error.message || 'Unknown error occurred', 'InternalError', error);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
async get(path, params, options) {
|
|
62
|
+
let url = path;
|
|
63
|
+
if (params && Object.keys(params).length > 0) {
|
|
64
|
+
const searchParams = new URLSearchParams();
|
|
65
|
+
Object.entries(params).forEach(([key, value]) => {
|
|
66
|
+
if (value !== undefined && value !== null) {
|
|
67
|
+
if (Array.isArray(value)) {
|
|
68
|
+
value.forEach(v => searchParams.append(key, String(v)));
|
|
69
|
+
}
|
|
70
|
+
else {
|
|
71
|
+
searchParams.append(key, String(value));
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
});
|
|
75
|
+
url = `${path}?${searchParams.toString()}`;
|
|
76
|
+
}
|
|
77
|
+
return this.request('GET', url, options);
|
|
78
|
+
}
|
|
79
|
+
async post(path, body, options) {
|
|
80
|
+
const requestOptions = {
|
|
81
|
+
...options,
|
|
82
|
+
headers: {
|
|
83
|
+
...options?.headers,
|
|
84
|
+
},
|
|
85
|
+
};
|
|
86
|
+
const controller = new AbortController();
|
|
87
|
+
const timeoutId = setTimeout(() => controller.abort(), requestOptions.timeout || this.timeout);
|
|
88
|
+
try {
|
|
89
|
+
const url = `${this.baseURL}${path}`;
|
|
90
|
+
const headers = {
|
|
91
|
+
'Authorization': `Bearer ${this.apiKey}`,
|
|
92
|
+
'Content-Type': 'application/json',
|
|
93
|
+
...requestOptions.headers,
|
|
94
|
+
};
|
|
95
|
+
const response = await fetch(url, {
|
|
96
|
+
method: 'POST',
|
|
97
|
+
headers,
|
|
98
|
+
body: body ? JSON.stringify(body) : undefined,
|
|
99
|
+
signal: controller.signal,
|
|
100
|
+
});
|
|
101
|
+
clearTimeout(timeoutId);
|
|
102
|
+
if (response.status === 204) {
|
|
103
|
+
return {};
|
|
104
|
+
}
|
|
105
|
+
const data = await response.json().catch(() => ({}));
|
|
106
|
+
if (!response.ok) {
|
|
107
|
+
throw new InvezgoError(response.status, data?.message || response.statusText, data?.error, data);
|
|
108
|
+
}
|
|
109
|
+
return data;
|
|
110
|
+
}
|
|
111
|
+
catch (error) {
|
|
112
|
+
clearTimeout(timeoutId);
|
|
113
|
+
if (error.name === 'AbortError') {
|
|
114
|
+
throw new InvezgoError(408, 'Request timeout', 'Timeout');
|
|
115
|
+
}
|
|
116
|
+
if (error instanceof InvezgoError) {
|
|
117
|
+
throw error;
|
|
118
|
+
}
|
|
119
|
+
throw new InvezgoError(500, error.message || 'Unknown error occurred', 'InternalError', error);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
async put(path, body, options) {
|
|
123
|
+
const controller = new AbortController();
|
|
124
|
+
const timeoutId = setTimeout(() => controller.abort(), options?.timeout || this.timeout);
|
|
125
|
+
try {
|
|
126
|
+
const url = `${this.baseURL}${path}`;
|
|
127
|
+
const headers = {
|
|
128
|
+
'Authorization': `Bearer ${this.apiKey}`,
|
|
129
|
+
'Content-Type': 'application/json',
|
|
130
|
+
...options?.headers,
|
|
131
|
+
};
|
|
132
|
+
const response = await fetch(url, {
|
|
133
|
+
method: 'PUT',
|
|
134
|
+
headers,
|
|
135
|
+
body: body ? JSON.stringify(body) : undefined,
|
|
136
|
+
signal: controller.signal,
|
|
137
|
+
});
|
|
138
|
+
clearTimeout(timeoutId);
|
|
139
|
+
if (response.status === 204) {
|
|
140
|
+
return {};
|
|
141
|
+
}
|
|
142
|
+
const data = await response.json().catch(() => ({}));
|
|
143
|
+
if (!response.ok) {
|
|
144
|
+
throw new InvezgoError(response.status, data?.message || response.statusText, data?.error, data);
|
|
145
|
+
}
|
|
146
|
+
return data;
|
|
147
|
+
}
|
|
148
|
+
catch (error) {
|
|
149
|
+
clearTimeout(timeoutId);
|
|
150
|
+
if (error.name === 'AbortError') {
|
|
151
|
+
throw new InvezgoError(408, 'Request timeout', 'Timeout');
|
|
152
|
+
}
|
|
153
|
+
if (error instanceof InvezgoError) {
|
|
154
|
+
throw error;
|
|
155
|
+
}
|
|
156
|
+
throw new InvezgoError(500, error.message || 'Unknown error occurred', 'InternalError', error);
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
async patch(path, body, options) {
|
|
160
|
+
const controller = new AbortController();
|
|
161
|
+
const timeoutId = setTimeout(() => controller.abort(), options?.timeout || this.timeout);
|
|
162
|
+
try {
|
|
163
|
+
const url = `${this.baseURL}${path}`;
|
|
164
|
+
const headers = {
|
|
165
|
+
'Authorization': `Bearer ${this.apiKey}`,
|
|
166
|
+
'Content-Type': 'application/json',
|
|
167
|
+
...options?.headers,
|
|
168
|
+
};
|
|
169
|
+
const response = await fetch(url, {
|
|
170
|
+
method: 'PATCH',
|
|
171
|
+
headers,
|
|
172
|
+
body: body ? JSON.stringify(body) : undefined,
|
|
173
|
+
signal: controller.signal,
|
|
174
|
+
});
|
|
175
|
+
clearTimeout(timeoutId);
|
|
176
|
+
if (response.status === 204) {
|
|
177
|
+
return {};
|
|
178
|
+
}
|
|
179
|
+
const data = await response.json().catch(() => ({}));
|
|
180
|
+
if (!response.ok) {
|
|
181
|
+
throw new InvezgoError(response.status, data?.message || response.statusText, data?.error, data);
|
|
182
|
+
}
|
|
183
|
+
return data;
|
|
184
|
+
}
|
|
185
|
+
catch (error) {
|
|
186
|
+
clearTimeout(timeoutId);
|
|
187
|
+
if (error.name === 'AbortError') {
|
|
188
|
+
throw new InvezgoError(408, 'Request timeout', 'Timeout');
|
|
189
|
+
}
|
|
190
|
+
if (error instanceof InvezgoError) {
|
|
191
|
+
throw error;
|
|
192
|
+
}
|
|
193
|
+
throw new InvezgoError(500, error.message || 'Unknown error occurred', 'InternalError', error);
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
async delete(path, params, options) {
|
|
197
|
+
let url = path;
|
|
198
|
+
if (params && Object.keys(params).length > 0) {
|
|
199
|
+
const searchParams = new URLSearchParams();
|
|
200
|
+
Object.entries(params).forEach(([key, value]) => {
|
|
201
|
+
if (value !== undefined && value !== null) {
|
|
202
|
+
if (Array.isArray(value)) {
|
|
203
|
+
value.forEach(v => searchParams.append(key, String(v)));
|
|
204
|
+
}
|
|
205
|
+
else {
|
|
206
|
+
searchParams.append(key, String(value));
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
});
|
|
210
|
+
url = `${path}?${searchParams.toString()}`;
|
|
211
|
+
}
|
|
212
|
+
return this.request('DELETE', url, options);
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
class AnalysisEndpoints {
|
|
217
|
+
constructor(client) {
|
|
218
|
+
this.client = client;
|
|
219
|
+
}
|
|
220
|
+
/**
|
|
221
|
+
* Get list of all stocks listed on BEI
|
|
222
|
+
*/
|
|
223
|
+
async getStockList() {
|
|
224
|
+
return this.client.get('/analysis/list/stock');
|
|
225
|
+
}
|
|
226
|
+
/**
|
|
227
|
+
* Get list of all brokers/securities on BEI
|
|
228
|
+
*/
|
|
229
|
+
async getBrokerList() {
|
|
230
|
+
return this.client.get('/analysis/list/broker');
|
|
231
|
+
}
|
|
232
|
+
/**
|
|
233
|
+
* Get complete company information
|
|
234
|
+
*/
|
|
235
|
+
async getInformation(code) {
|
|
236
|
+
return this.client.get(`/analysis/information/${code}`);
|
|
237
|
+
}
|
|
238
|
+
/**
|
|
239
|
+
* Get top gainer and loser stocks for a specific date
|
|
240
|
+
*/
|
|
241
|
+
async getTopChange(date) {
|
|
242
|
+
return this.client.get('/analysis/top/change', { date });
|
|
243
|
+
}
|
|
244
|
+
/**
|
|
245
|
+
* Get top foreign accumulation and distribution
|
|
246
|
+
*/
|
|
247
|
+
async getTopForeign(date) {
|
|
248
|
+
return this.client.get('/analysis/top/foreign', { date });
|
|
249
|
+
}
|
|
250
|
+
/**
|
|
251
|
+
* Get top accumulation and distribution (bandarmologi)
|
|
252
|
+
*/
|
|
253
|
+
async getTopAccumulation(date) {
|
|
254
|
+
return this.client.get('/analysis/top/accumulation', { date });
|
|
255
|
+
}
|
|
256
|
+
/**
|
|
257
|
+
* Get intraday chart data
|
|
258
|
+
*/
|
|
259
|
+
async getIntradayChart(code, market = 'RG') {
|
|
260
|
+
return this.client.get(`/analysis/intraday/${code}`, { market });
|
|
261
|
+
}
|
|
262
|
+
/**
|
|
263
|
+
* Get order book data
|
|
264
|
+
*/
|
|
265
|
+
async getOrderBook(code, market = 'RG') {
|
|
266
|
+
return this.client.get(`/analysis/order-book/${code}`, { market });
|
|
267
|
+
}
|
|
268
|
+
/**
|
|
269
|
+
* Get complete stock chart data
|
|
270
|
+
*/
|
|
271
|
+
async getChart(code, params) {
|
|
272
|
+
return this.client.get(`/analysis/chart/stock/${code}`, params);
|
|
273
|
+
}
|
|
274
|
+
/**
|
|
275
|
+
* Get stock chart with technical indicator
|
|
276
|
+
*/
|
|
277
|
+
async getIndicatorChart(code, indicator, params) {
|
|
278
|
+
return this.client.get(`/analysis/chart/stock/${indicator}/${code}`, params);
|
|
279
|
+
}
|
|
280
|
+
/**
|
|
281
|
+
* Get shareholder detail (ownership)
|
|
282
|
+
*/
|
|
283
|
+
async getShareholderDetail(code) {
|
|
284
|
+
return this.client.get(`/analysis/shareholder-detail/${code}`);
|
|
285
|
+
}
|
|
286
|
+
/**
|
|
287
|
+
* Get number of shareholders
|
|
288
|
+
*/
|
|
289
|
+
async getShareholderNumber(code) {
|
|
290
|
+
return this.client.get(`/analysis/shareholder/number/${code}`);
|
|
291
|
+
}
|
|
292
|
+
/**
|
|
293
|
+
* Get shareholder composition
|
|
294
|
+
*/
|
|
295
|
+
async getShareholder(code) {
|
|
296
|
+
return this.client.get(`/analysis/shareholder/${code}`);
|
|
297
|
+
}
|
|
298
|
+
/**
|
|
299
|
+
* Get KSEI shareholder data
|
|
300
|
+
*/
|
|
301
|
+
async getShareholderKSEI(code, range) {
|
|
302
|
+
return this.client.get(`/analysis/shareholder/ksei/${code}`, {
|
|
303
|
+
range: Math.min(range, 12),
|
|
304
|
+
});
|
|
305
|
+
}
|
|
306
|
+
/**
|
|
307
|
+
* Get broker summary for a stock
|
|
308
|
+
*/
|
|
309
|
+
async getBrokerSummaryStock(code, params) {
|
|
310
|
+
return this.client.get(`/analysis/summary/stock/${code}`, params);
|
|
311
|
+
}
|
|
312
|
+
/**
|
|
313
|
+
* Get broker summary for a broker
|
|
314
|
+
*/
|
|
315
|
+
async getBrokerSummaryBroker(code, params) {
|
|
316
|
+
return this.client.get(`/analysis/summary/broker/${code}`, params);
|
|
317
|
+
}
|
|
318
|
+
/**
|
|
319
|
+
* Get broker summary chart for a stock
|
|
320
|
+
*/
|
|
321
|
+
async getBrokerSummaryChartStock(code, params) {
|
|
322
|
+
return this.client.get(`/analysis/summary-chart/stock/${code}`, params);
|
|
323
|
+
}
|
|
324
|
+
/**
|
|
325
|
+
* Get broker summary chart for a broker
|
|
326
|
+
*/
|
|
327
|
+
async getBrokerSummaryChartBroker(code, params) {
|
|
328
|
+
return this.client.get(`/analysis/summary-chart/broker/${code}`, params);
|
|
329
|
+
}
|
|
330
|
+
/**
|
|
331
|
+
* Get inventory chart for a stock
|
|
332
|
+
*/
|
|
333
|
+
async getInventoryChartStock(code, params) {
|
|
334
|
+
const requestParams = { ...params };
|
|
335
|
+
if (params.filter) {
|
|
336
|
+
requestParams.filter = params.filter;
|
|
337
|
+
}
|
|
338
|
+
return this.client.get(`/analysis/inventory-chart/stock/${code}`, requestParams);
|
|
339
|
+
}
|
|
340
|
+
/**
|
|
341
|
+
* Get inventory chart for a broker
|
|
342
|
+
*/
|
|
343
|
+
async getInventoryChartBroker(code, params) {
|
|
344
|
+
const requestParams = { ...params };
|
|
345
|
+
if (params.filter) {
|
|
346
|
+
requestParams.filter = params.filter;
|
|
347
|
+
}
|
|
348
|
+
return this.client.get(`/analysis/inventory-chart/broker/${code}`, requestParams);
|
|
349
|
+
}
|
|
350
|
+
/**
|
|
351
|
+
* Get momentum chart
|
|
352
|
+
*/
|
|
353
|
+
async getMomentumChart(code, params) {
|
|
354
|
+
return this.client.get(`/analysis/momentum-chart/${code}`, params);
|
|
355
|
+
}
|
|
356
|
+
/**
|
|
357
|
+
* Get intraday inventory chart
|
|
358
|
+
*/
|
|
359
|
+
async getIntradayInventoryChart(code, params) {
|
|
360
|
+
return this.client.get(`/analysis/intraday-inventory-chart/${code}`, params);
|
|
361
|
+
}
|
|
362
|
+
/**
|
|
363
|
+
* Get sankey/crossing chart
|
|
364
|
+
*/
|
|
365
|
+
async getSankeyChart(code, params) {
|
|
366
|
+
return this.client.get(`/analysis/sankey-chart/${code}`, params);
|
|
367
|
+
}
|
|
368
|
+
/**
|
|
369
|
+
* Get price table
|
|
370
|
+
*/
|
|
371
|
+
async getPriceTable(code, date) {
|
|
372
|
+
return this.client.get(`/analysis/price-table/${code}`, { date });
|
|
373
|
+
}
|
|
374
|
+
/**
|
|
375
|
+
* Get time table
|
|
376
|
+
*/
|
|
377
|
+
async getTimeTable(code, params) {
|
|
378
|
+
return this.client.get(`/analysis/time-table/${code}`, params);
|
|
379
|
+
}
|
|
380
|
+
/**
|
|
381
|
+
* Get price diary
|
|
382
|
+
*/
|
|
383
|
+
async getPriceDiary(code) {
|
|
384
|
+
return this.client.get(`/analysis/price-diary/${code}`);
|
|
385
|
+
}
|
|
386
|
+
/**
|
|
387
|
+
* Get price seasonality
|
|
388
|
+
*/
|
|
389
|
+
async getPriceSeasonality(code, range) {
|
|
390
|
+
return this.client.get(`/analysis/price-seasonality/${code}`, {
|
|
391
|
+
range: Math.min(range, 60),
|
|
392
|
+
});
|
|
393
|
+
}
|
|
394
|
+
/**
|
|
395
|
+
* Get shareholders above 5%
|
|
396
|
+
*/
|
|
397
|
+
async getShareholderAbove(params) {
|
|
398
|
+
return this.client.get('/analysis/shareholder-above', params);
|
|
399
|
+
}
|
|
400
|
+
/**
|
|
401
|
+
* Get shareholder above 5% chart
|
|
402
|
+
*/
|
|
403
|
+
async getShareholderAboveChart(code, params) {
|
|
404
|
+
return this.client.get(`/analysis/shareholder-above-chart/${code}`, params);
|
|
405
|
+
}
|
|
406
|
+
/**
|
|
407
|
+
* Get insider trading data
|
|
408
|
+
*/
|
|
409
|
+
async getInsiderTrading(params) {
|
|
410
|
+
return this.client.get('/analysis/shareholder-insider', params);
|
|
411
|
+
}
|
|
412
|
+
/**
|
|
413
|
+
* Get insider chart
|
|
414
|
+
*/
|
|
415
|
+
async getInsiderChart(code, params) {
|
|
416
|
+
return this.client.get(`/analysis/insider-chart/${code}`, params);
|
|
417
|
+
}
|
|
418
|
+
/**
|
|
419
|
+
* Get financial statement
|
|
420
|
+
*/
|
|
421
|
+
async getFinancialStatement(code, params) {
|
|
422
|
+
return this.client.get(`/analysis/financial-statement/${code}`, { ...params, limit: Math.min(params.limit, 20) });
|
|
423
|
+
}
|
|
424
|
+
/**
|
|
425
|
+
* Get financial statement chart
|
|
426
|
+
*/
|
|
427
|
+
async getFinancialStatementChart(code, params) {
|
|
428
|
+
return this.client.get(`/analysis/financial-statement-chart/${code}`, { ...params, limit: Math.min(Number(params.limit), 20).toString() });
|
|
429
|
+
}
|
|
430
|
+
/**
|
|
431
|
+
* Get key statistics
|
|
432
|
+
*/
|
|
433
|
+
async getKeyStat(code, params) {
|
|
434
|
+
return this.client.get(`/analysis/keystat/${code}`, {
|
|
435
|
+
...params,
|
|
436
|
+
limit: Math.min(params.limit, 20),
|
|
437
|
+
});
|
|
438
|
+
}
|
|
439
|
+
/**
|
|
440
|
+
* Get key statistics chart
|
|
441
|
+
*/
|
|
442
|
+
async getKeyStatChart(code, params) {
|
|
443
|
+
return this.client.get(`/analysis/keystat-chart/${code}`, params);
|
|
444
|
+
}
|
|
445
|
+
}
|
|
446
|
+
|
|
447
|
+
class WatchlistsEndpoints {
|
|
448
|
+
constructor(client) {
|
|
449
|
+
this.client = client;
|
|
450
|
+
}
|
|
451
|
+
/**
|
|
452
|
+
* Get list of watchlists
|
|
453
|
+
*/
|
|
454
|
+
async list(group) {
|
|
455
|
+
return this.client.get('/watchlists', { group: group || 'null' });
|
|
456
|
+
}
|
|
457
|
+
/**
|
|
458
|
+
* Add stock to watchlist
|
|
459
|
+
*/
|
|
460
|
+
async add(dto) {
|
|
461
|
+
return this.client.post('/watchlists', dto);
|
|
462
|
+
}
|
|
463
|
+
/**
|
|
464
|
+
* Delete watchlist
|
|
465
|
+
*/
|
|
466
|
+
async delete(params) {
|
|
467
|
+
return this.client.delete('/watchlists', params);
|
|
468
|
+
}
|
|
469
|
+
/**
|
|
470
|
+
* Get list of watchlist groups
|
|
471
|
+
*/
|
|
472
|
+
async listGroups() {
|
|
473
|
+
return this.client.get('/watchlists/group');
|
|
474
|
+
}
|
|
475
|
+
/**
|
|
476
|
+
* Add new watchlist group
|
|
477
|
+
*/
|
|
478
|
+
async addGroup(dto) {
|
|
479
|
+
return this.client.post('/watchlists/group', dto);
|
|
480
|
+
}
|
|
481
|
+
/**
|
|
482
|
+
* Update watchlist
|
|
483
|
+
*/
|
|
484
|
+
async update(id, dto) {
|
|
485
|
+
return this.client.put(`/watchlists/${id}`, dto);
|
|
486
|
+
}
|
|
487
|
+
/**
|
|
488
|
+
* Update watchlist note
|
|
489
|
+
*/
|
|
490
|
+
async updateNote(id, dto) {
|
|
491
|
+
return this.client.patch(`/watchlists/${id}`, dto);
|
|
492
|
+
}
|
|
493
|
+
}
|
|
494
|
+
|
|
495
|
+
class JournalsEndpoints {
|
|
496
|
+
constructor(client) {
|
|
497
|
+
this.client = client;
|
|
498
|
+
}
|
|
499
|
+
/**
|
|
500
|
+
* Extract journal from file
|
|
501
|
+
* Note: This method may need special handling depending on your environment
|
|
502
|
+
*/
|
|
503
|
+
async extractFromFile(file) {
|
|
504
|
+
const formData = new FormData();
|
|
505
|
+
formData.append('file', file);
|
|
506
|
+
// Note: When using FormData, don't set Content-Type header
|
|
507
|
+
// Browser/Node will set it automatically with boundary
|
|
508
|
+
const controller = new AbortController();
|
|
509
|
+
const url = `${this.client.baseURL}/journals/file`;
|
|
510
|
+
const response = await fetch(url, {
|
|
511
|
+
method: 'POST',
|
|
512
|
+
headers: {
|
|
513
|
+
'Authorization': `Bearer ${this.client.apiKey}`,
|
|
514
|
+
},
|
|
515
|
+
body: formData,
|
|
516
|
+
signal: controller.signal,
|
|
517
|
+
});
|
|
518
|
+
if (!response.ok) {
|
|
519
|
+
const data = await response.json().catch(() => ({}));
|
|
520
|
+
throw new Error(data?.message || 'Failed to extract journal from file');
|
|
521
|
+
}
|
|
522
|
+
return response.json().catch(() => ({}));
|
|
523
|
+
}
|
|
524
|
+
/**
|
|
525
|
+
* Add new journal transaction
|
|
526
|
+
*/
|
|
527
|
+
async add(dto) {
|
|
528
|
+
return this.client.post('/journals', dto);
|
|
529
|
+
}
|
|
530
|
+
/**
|
|
531
|
+
* List journal transactions
|
|
532
|
+
*/
|
|
533
|
+
async list() {
|
|
534
|
+
return this.client.get('/journals');
|
|
535
|
+
}
|
|
536
|
+
/**
|
|
537
|
+
* Delete journal
|
|
538
|
+
*/
|
|
539
|
+
async delete(params) {
|
|
540
|
+
return this.client.delete('/journals', params);
|
|
541
|
+
}
|
|
542
|
+
/**
|
|
543
|
+
* Get journal transactions summary
|
|
544
|
+
*/
|
|
545
|
+
async getSummary() {
|
|
546
|
+
return this.client.get('/journals/summary');
|
|
547
|
+
}
|
|
548
|
+
/**
|
|
549
|
+
* Update journal transaction note
|
|
550
|
+
*/
|
|
551
|
+
async updateNote(id, dto) {
|
|
552
|
+
return this.client.patch(`/journals/${id}`, dto);
|
|
553
|
+
}
|
|
554
|
+
}
|
|
555
|
+
|
|
556
|
+
class PortfoliosEndpoints {
|
|
557
|
+
constructor(client) {
|
|
558
|
+
this.client = client;
|
|
559
|
+
}
|
|
560
|
+
/**
|
|
561
|
+
* Get list of portfolios
|
|
562
|
+
*/
|
|
563
|
+
async list() {
|
|
564
|
+
return this.client.get('/portfolios');
|
|
565
|
+
}
|
|
566
|
+
/**
|
|
567
|
+
* Get portfolio summary
|
|
568
|
+
*/
|
|
569
|
+
async getSummary() {
|
|
570
|
+
return this.client.get('/portfolios/summary');
|
|
571
|
+
}
|
|
572
|
+
}
|
|
573
|
+
|
|
574
|
+
class AiEndpoints {
|
|
575
|
+
constructor(client) {
|
|
576
|
+
this.client = client;
|
|
577
|
+
}
|
|
578
|
+
/**
|
|
579
|
+
* AI analysis of KSEI shareholder data
|
|
580
|
+
*/
|
|
581
|
+
async analyzeShareholderKSEI(code) {
|
|
582
|
+
return this.client.get(`/ai/shareholder/ksei/${code}`);
|
|
583
|
+
}
|
|
584
|
+
/**
|
|
585
|
+
* AI analysis of inventory chart
|
|
586
|
+
*/
|
|
587
|
+
async analyzeInventoryChart(code, params) {
|
|
588
|
+
return this.client.get(`/ai/inventory-chart/stock/${code}`, params);
|
|
589
|
+
}
|
|
590
|
+
/**
|
|
591
|
+
* AI analysis of stock news
|
|
592
|
+
*/
|
|
593
|
+
async analyzeNews(code) {
|
|
594
|
+
return this.client.get(`/ai/news/${code}`);
|
|
595
|
+
}
|
|
596
|
+
/**
|
|
597
|
+
* AI analysis of broker summary
|
|
598
|
+
*/
|
|
599
|
+
async analyzeBrokerSummary(code, params) {
|
|
600
|
+
return this.client.get(`/ai/summary/stock/${code}`, params);
|
|
601
|
+
}
|
|
602
|
+
/**
|
|
603
|
+
* AI analysis of insider trading
|
|
604
|
+
*/
|
|
605
|
+
async analyzeInsider(params) {
|
|
606
|
+
return this.client.get('/ai/shareholder-insider', params);
|
|
607
|
+
}
|
|
608
|
+
/**
|
|
609
|
+
* AI analysis of shareholders above 5%
|
|
610
|
+
*/
|
|
611
|
+
async analyzeShareholderAbove(params) {
|
|
612
|
+
return this.client.get('/ai/shareholder-above', params);
|
|
613
|
+
}
|
|
614
|
+
/**
|
|
615
|
+
* AI analysis of intraday inventory chart
|
|
616
|
+
*/
|
|
617
|
+
async analyzeIntradayInventory(code, params) {
|
|
618
|
+
return this.client.get(`/ai/intraday-inventory-chart/${code}`, params);
|
|
619
|
+
}
|
|
620
|
+
/**
|
|
621
|
+
* AI analysis of sankey/crossing chart
|
|
622
|
+
*/
|
|
623
|
+
async analyzeSankeyChart(code, params) {
|
|
624
|
+
return this.client.get(`/ai/sankey-chart/${code}`, params);
|
|
625
|
+
}
|
|
626
|
+
/**
|
|
627
|
+
* AI analysis of shareholder table
|
|
628
|
+
*/
|
|
629
|
+
async analyzeShareholder(code) {
|
|
630
|
+
return this.client.get(`/ai/shareholder/${code}`);
|
|
631
|
+
}
|
|
632
|
+
/**
|
|
633
|
+
* AI analysis of financial statement
|
|
634
|
+
*/
|
|
635
|
+
async analyzeFinancialStatement(code, params) {
|
|
636
|
+
return this.client.get(`/ai/financial-statement/${code}`, params);
|
|
637
|
+
}
|
|
638
|
+
/**
|
|
639
|
+
* AI analysis of key statistics
|
|
640
|
+
*/
|
|
641
|
+
async analyzeKeyStat(code, params) {
|
|
642
|
+
return this.client.get(`/ai/keystat/${code}`, params);
|
|
643
|
+
}
|
|
644
|
+
}
|
|
645
|
+
|
|
646
|
+
class SearchEndpoints {
|
|
647
|
+
constructor(client) {
|
|
648
|
+
this.client = client;
|
|
649
|
+
}
|
|
650
|
+
/**
|
|
651
|
+
* Search for stocks or users
|
|
652
|
+
*/
|
|
653
|
+
async search(query) {
|
|
654
|
+
return this.client.get('/search', { query });
|
|
655
|
+
}
|
|
656
|
+
/**
|
|
657
|
+
* Search for stocks
|
|
658
|
+
*/
|
|
659
|
+
async searchStock(query, cursor) {
|
|
660
|
+
return this.client.get('/search/stock', { query, cursor });
|
|
661
|
+
}
|
|
662
|
+
/**
|
|
663
|
+
* Search for users
|
|
664
|
+
*/
|
|
665
|
+
async searchUser(query, cursor) {
|
|
666
|
+
return this.client.get('/search/user', { query, cursor });
|
|
667
|
+
}
|
|
668
|
+
}
|
|
669
|
+
|
|
670
|
+
class ProfileEndpoints {
|
|
671
|
+
constructor(client) {
|
|
672
|
+
this.client = client;
|
|
673
|
+
}
|
|
674
|
+
/**
|
|
675
|
+
* Get user profile details
|
|
676
|
+
*/
|
|
677
|
+
async getUserDetails(username) {
|
|
678
|
+
return this.client.get(`/profile/detail/${username}`);
|
|
679
|
+
}
|
|
680
|
+
/**
|
|
681
|
+
* Get user posts
|
|
682
|
+
*/
|
|
683
|
+
async getUserPosts(username, page, limit) {
|
|
684
|
+
return this.client.get(`/profile/posts/${username}`, { page, limit });
|
|
685
|
+
}
|
|
686
|
+
/**
|
|
687
|
+
* Get user posts by category
|
|
688
|
+
*/
|
|
689
|
+
async getCategoryPosts(username, category, page, limit) {
|
|
690
|
+
return this.client.get(`/profile/posts/${username}/${category}`, { page, limit });
|
|
691
|
+
}
|
|
692
|
+
/**
|
|
693
|
+
* Get user watchlist
|
|
694
|
+
*/
|
|
695
|
+
async getUserWatchlist(username) {
|
|
696
|
+
return this.client.get(`/profile/watchlist/${username}`);
|
|
697
|
+
}
|
|
698
|
+
/**
|
|
699
|
+
* Get user followers
|
|
700
|
+
*/
|
|
701
|
+
async getFollowers(username) {
|
|
702
|
+
return this.client.get(`/profile/follow/${username}`);
|
|
703
|
+
}
|
|
704
|
+
/**
|
|
705
|
+
* Get users being followed
|
|
706
|
+
*/
|
|
707
|
+
async getFollowing(username) {
|
|
708
|
+
return this.client.get(`/profile/following/${username}`);
|
|
709
|
+
}
|
|
710
|
+
/**
|
|
711
|
+
* Get user memberships
|
|
712
|
+
*/
|
|
713
|
+
async getMemberships(username) {
|
|
714
|
+
return this.client.get(`/profile/membership/${username}`);
|
|
715
|
+
}
|
|
716
|
+
}
|
|
717
|
+
|
|
718
|
+
class MembershipEndpoints {
|
|
719
|
+
constructor(client) {
|
|
720
|
+
this.client = client;
|
|
721
|
+
}
|
|
722
|
+
/**
|
|
723
|
+
* Get list of memberships
|
|
724
|
+
*/
|
|
725
|
+
async list() {
|
|
726
|
+
return this.client.get('/membership');
|
|
727
|
+
}
|
|
728
|
+
/**
|
|
729
|
+
* Add new membership
|
|
730
|
+
*/
|
|
731
|
+
async add(dto) {
|
|
732
|
+
return this.client.post('/membership', dto);
|
|
733
|
+
}
|
|
734
|
+
/**
|
|
735
|
+
* Get membership scope
|
|
736
|
+
*/
|
|
737
|
+
async getScope() {
|
|
738
|
+
return this.client.get('/membership/scope');
|
|
739
|
+
}
|
|
740
|
+
/**
|
|
741
|
+
* Get membership transactions
|
|
742
|
+
*/
|
|
743
|
+
async getTransactions() {
|
|
744
|
+
return this.client.get('/membership/list');
|
|
745
|
+
}
|
|
746
|
+
/**
|
|
747
|
+
* Update membership
|
|
748
|
+
*/
|
|
749
|
+
async update(id, dto) {
|
|
750
|
+
return this.client.put(`/membership/${id}`, dto);
|
|
751
|
+
}
|
|
752
|
+
/**
|
|
753
|
+
* Delete membership
|
|
754
|
+
*/
|
|
755
|
+
async delete(id) {
|
|
756
|
+
return this.client.delete(`/membership/${id}`);
|
|
757
|
+
}
|
|
758
|
+
}
|
|
759
|
+
|
|
760
|
+
class PostsEndpoints {
|
|
761
|
+
constructor(client) {
|
|
762
|
+
this.client = client;
|
|
763
|
+
}
|
|
764
|
+
/**
|
|
765
|
+
* Get all posts
|
|
766
|
+
*/
|
|
767
|
+
async getAll() {
|
|
768
|
+
return this.client.get('/posts');
|
|
769
|
+
}
|
|
770
|
+
/**
|
|
771
|
+
* Get posts by category
|
|
772
|
+
*/
|
|
773
|
+
async getByCategory(category) {
|
|
774
|
+
return this.client.get(`/posts/category/${category}`);
|
|
775
|
+
}
|
|
776
|
+
/**
|
|
777
|
+
* Get posts for a stock
|
|
778
|
+
*/
|
|
779
|
+
async getStockPosts(code) {
|
|
780
|
+
return this.client.get(`/posts/space/${code}`);
|
|
781
|
+
}
|
|
782
|
+
/**
|
|
783
|
+
* Get stock posts by category
|
|
784
|
+
*/
|
|
785
|
+
async getStockCategoryPosts(code, category) {
|
|
786
|
+
return this.client.get(`/posts/space/category/${code}/${category}`);
|
|
787
|
+
}
|
|
788
|
+
/**
|
|
789
|
+
* Get post details
|
|
790
|
+
*/
|
|
791
|
+
async getPostById(id) {
|
|
792
|
+
return this.client.get(`/posts/detail/${id}`);
|
|
793
|
+
}
|
|
794
|
+
/**
|
|
795
|
+
* Get post comments
|
|
796
|
+
*/
|
|
797
|
+
async getComments(id) {
|
|
798
|
+
return this.client.get(`/posts/comment/${id}`);
|
|
799
|
+
}
|
|
800
|
+
/**
|
|
801
|
+
* Get liked posts
|
|
802
|
+
*/
|
|
803
|
+
async getLiked() {
|
|
804
|
+
return this.client.get('/posts/like');
|
|
805
|
+
}
|
|
806
|
+
/**
|
|
807
|
+
* Get favorite posts
|
|
808
|
+
*/
|
|
809
|
+
async getFavorites() {
|
|
810
|
+
return this.client.get('/posts/favorite');
|
|
811
|
+
}
|
|
812
|
+
/**
|
|
813
|
+
* Get post voters
|
|
814
|
+
*/
|
|
815
|
+
async getVoters(id) {
|
|
816
|
+
return this.client.get(`/posts/vote/${id}`);
|
|
817
|
+
}
|
|
818
|
+
}
|
|
819
|
+
|
|
820
|
+
class TradesEndpoints {
|
|
821
|
+
constructor(client) {
|
|
822
|
+
this.client = client;
|
|
823
|
+
}
|
|
824
|
+
/**
|
|
825
|
+
* Get list of realized trades
|
|
826
|
+
*/
|
|
827
|
+
async list() {
|
|
828
|
+
return this.client.get('/trades');
|
|
829
|
+
}
|
|
830
|
+
/**
|
|
831
|
+
* Delete trades
|
|
832
|
+
*/
|
|
833
|
+
async delete(params) {
|
|
834
|
+
return this.client.delete('/trades', params);
|
|
835
|
+
}
|
|
836
|
+
/**
|
|
837
|
+
* Get trades summary
|
|
838
|
+
*/
|
|
839
|
+
async getSummary() {
|
|
840
|
+
return this.client.get('/trades/summary');
|
|
841
|
+
}
|
|
842
|
+
/**
|
|
843
|
+
* Get trades summary chart
|
|
844
|
+
*/
|
|
845
|
+
async getSummaryChart() {
|
|
846
|
+
return this.client.get('/trades/summary-chart');
|
|
847
|
+
}
|
|
848
|
+
/**
|
|
849
|
+
* Update trade note
|
|
850
|
+
*/
|
|
851
|
+
async updateNote(id, dto) {
|
|
852
|
+
return this.client.patch(`/trades/${id}`, dto);
|
|
853
|
+
}
|
|
854
|
+
}
|
|
855
|
+
|
|
856
|
+
class ScreenerEndpoints {
|
|
857
|
+
constructor(client) {
|
|
858
|
+
this.client = client;
|
|
859
|
+
}
|
|
860
|
+
/**
|
|
861
|
+
* Get list of preset screeners
|
|
862
|
+
*/
|
|
863
|
+
async list() {
|
|
864
|
+
return this.client.get('/screener');
|
|
865
|
+
}
|
|
866
|
+
/**
|
|
867
|
+
* Save preset screener
|
|
868
|
+
*/
|
|
869
|
+
async save(dto) {
|
|
870
|
+
return this.client.post('/screener', dto);
|
|
871
|
+
}
|
|
872
|
+
/**
|
|
873
|
+
* Run screener
|
|
874
|
+
*/
|
|
875
|
+
async screen(dto) {
|
|
876
|
+
return this.client.post('/screener/screen', dto);
|
|
877
|
+
}
|
|
878
|
+
}
|
|
879
|
+
|
|
880
|
+
class HealthEndpoints {
|
|
881
|
+
constructor(client) {
|
|
882
|
+
this.client = client;
|
|
883
|
+
}
|
|
884
|
+
/**
|
|
885
|
+
* Check API status
|
|
886
|
+
*/
|
|
887
|
+
async check() {
|
|
888
|
+
return this.client.get('/health');
|
|
889
|
+
}
|
|
890
|
+
/**
|
|
891
|
+
* Check database status
|
|
892
|
+
*/
|
|
893
|
+
async checkDatabase() {
|
|
894
|
+
return this.client.get('/health/database');
|
|
895
|
+
}
|
|
896
|
+
/**
|
|
897
|
+
* Full health check (API and database)
|
|
898
|
+
*/
|
|
899
|
+
async fullCheck() {
|
|
900
|
+
return this.client.get('/health/full');
|
|
901
|
+
}
|
|
902
|
+
}
|
|
903
|
+
|
|
904
|
+
class Invezgo {
|
|
905
|
+
constructor(config) {
|
|
906
|
+
this.client = new HttpClient(config);
|
|
907
|
+
// Initialize all endpoint modules
|
|
908
|
+
this.analysis = new AnalysisEndpoints(this.client);
|
|
909
|
+
this.watchlists = new WatchlistsEndpoints(this.client);
|
|
910
|
+
this.journals = new JournalsEndpoints(this.client);
|
|
911
|
+
this.portfolios = new PortfoliosEndpoints(this.client);
|
|
912
|
+
this.ai = new AiEndpoints(this.client);
|
|
913
|
+
this.search = new SearchEndpoints(this.client);
|
|
914
|
+
this.profile = new ProfileEndpoints(this.client);
|
|
915
|
+
this.membership = new MembershipEndpoints(this.client);
|
|
916
|
+
this.posts = new PostsEndpoints(this.client);
|
|
917
|
+
this.trades = new TradesEndpoints(this.client);
|
|
918
|
+
this.screener = new ScreenerEndpoints(this.client);
|
|
919
|
+
this.health = new HealthEndpoints(this.client);
|
|
920
|
+
}
|
|
921
|
+
/**
|
|
922
|
+
* Update API key
|
|
923
|
+
*/
|
|
924
|
+
setApiKey(apiKey) {
|
|
925
|
+
this.client.apiKey = apiKey;
|
|
926
|
+
}
|
|
927
|
+
/**
|
|
928
|
+
* Get current API key (without exposing it)
|
|
929
|
+
*/
|
|
930
|
+
hasApiKey() {
|
|
931
|
+
return !!this.client.apiKey;
|
|
932
|
+
}
|
|
933
|
+
}
|
|
934
|
+
|
|
935
|
+
/**
|
|
936
|
+
* Invezgo SDK for JavaScript and TypeScript
|
|
937
|
+
*
|
|
938
|
+
* Official SDK for accessing Invezgo API - Indonesia Stock Market Data
|
|
939
|
+
*
|
|
940
|
+
* @packageDocumentation
|
|
941
|
+
*/
|
|
942
|
+
|
|
943
|
+
export { Invezgo, InvezgoError, JournalsEndpoints, MembershipEndpoints, ScreenerEndpoints, TradesEndpoints, WatchlistsEndpoints, Invezgo as default };
|
|
944
|
+
//# sourceMappingURL=index.js.map
|