laplace-api 5.2.3 → 5.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "laplace-api",
3
- "version": "5.2.3",
3
+ "version": "5.3.0",
4
4
  "description": "Client library for Laplace API for the US stock market and BIST (Istanbul stock market) fundamental financial data.",
5
5
  "main": "index.js",
6
6
  "scripts": {
@@ -22,6 +22,23 @@ export enum NewsType {
22
22
 
23
23
  export enum NewsOrderBy {
24
24
  TIMESTAMP = "timestamp",
25
+ QUALITY_SCORE = "quality_score",
26
+ }
27
+
28
+ export interface GetNewsV2Params {
29
+ newsType?: NewsType;
30
+ orderBy?: NewsOrderBy;
31
+ orderByDirection?: SortDirection;
32
+ symbols?: string;
33
+ categories?: string;
34
+ sectors?: string;
35
+ industries?: string;
36
+ qualityScoreMin?: number;
37
+ qualityScoreMax?: number;
38
+ timestampFrom?: string;
39
+ timestampTo?: string;
40
+ page?: number;
41
+ size?: number;
25
42
  }
26
43
 
27
44
  export interface News {
@@ -80,6 +97,11 @@ export interface NewsIndustry {
80
97
  meanType: number;
81
98
  }
82
99
 
100
+ export interface NewsCategory {
101
+ id: string;
102
+ name: string;
103
+ }
104
+
83
105
  export class NewsClient extends Client {
84
106
  async getHighlights(
85
107
  region: Region,
@@ -96,6 +118,16 @@ export class NewsClient extends Client {
96
118
  }
97
119
 
98
120
 
121
+ async getNewsCategories(locale?: Locale): Promise<NewsCategory[]> {
122
+ return this.sendRequest<NewsCategory[]>({
123
+ method: "GET",
124
+ url: "/api/v1/news/categories",
125
+ params: {
126
+ ...(locale != null && { locale }),
127
+ },
128
+ });
129
+ }
130
+
99
131
  async getNews(
100
132
  region: Region,
101
133
  locale: Locale,
@@ -127,22 +159,32 @@ export class NewsClient extends Client {
127
159
  async getNewsV2(
128
160
  region: Region,
129
161
  locale: Locale,
130
- newsType?: NewsType,
131
- page?: number,
132
- size?: number,
133
- orderBy?: NewsOrderBy,
134
- orderByDirection?: SortDirection,
135
- extraFilters?: string
162
+ options?: GetNewsV2Params
136
163
  ): Promise<PaginatedResponse<NewsV2>> {
137
164
  const params = {
138
165
  region,
139
166
  locale,
140
- ...(newsType != null && { newsType }),
141
- ...(page != null && { page }),
142
- ...(size != null && { size }),
143
- ...(orderBy != null && { orderBy }),
144
- ...(orderByDirection != null && { orderByDirection }),
145
- ...(extraFilters != null && { extraFilters }),
167
+ ...(options?.newsType != null && { newsType: options.newsType }),
168
+ ...(options?.orderBy != null && { orderBy: options.orderBy }),
169
+ ...(options?.orderByDirection != null && {
170
+ orderByDirection: options.orderByDirection,
171
+ }),
172
+ ...(options?.symbols != null && { symbols: options.symbols }),
173
+ ...(options?.categories != null && { categories: options.categories }),
174
+ ...(options?.sectors != null && { sectors: options.sectors }),
175
+ ...(options?.industries != null && { industries: options.industries }),
176
+ ...(options?.qualityScoreMin != null && {
177
+ qualityScoreMin: options.qualityScoreMin,
178
+ }),
179
+ ...(options?.qualityScoreMax != null && {
180
+ qualityScoreMax: options.qualityScoreMax,
181
+ }),
182
+ ...(options?.timestampFrom != null && {
183
+ timestampFrom: options.timestampFrom,
184
+ }),
185
+ ...(options?.timestampTo != null && { timestampTo: options.timestampTo }),
186
+ ...(options?.page != null && { page: options.page }),
187
+ ...(options?.size != null && { size: options.size }),
146
188
  };
147
189
 
148
190
  return this.sendRequest<PaginatedResponse<NewsV2>>({
@@ -34,6 +34,13 @@ const mockNewsHighlightsResponse = {
34
34
  ]
35
35
  };
36
36
 
37
+ const mockNewsCategoriesResponse = [
38
+ { id: "13702", name: "General News" },
39
+ { id: "13703", name: "Sector News" },
40
+ { id: "13704", name: "Market News" },
41
+ { id: "13705", name: "Stock Spesific News" }
42
+ ];
43
+
37
44
  const mockNewsResponse = {
38
45
  items: [
39
46
  {
@@ -107,6 +114,17 @@ describe("NewsClient", () => {
107
114
  if (first != null) expect(typeof first).toBe("string");
108
115
  });
109
116
 
117
+ test("getNewsCategories returns valid data", async () => {
118
+ const resp = await client.getNewsCategories(Locale.En);
119
+
120
+ expect(Array.isArray(resp)).toBe(true);
121
+ expect(resp.length).toBeGreaterThan(0);
122
+
123
+ const c = resp[0];
124
+ expect(typeof c.id).toBe("string");
125
+ expect(typeof c.name).toBe("string");
126
+ });
127
+
110
128
  test("getNews returns valid paginated data", async () => {
111
129
  const resp = await client.getNews(
112
130
  Region.Us,
@@ -197,15 +215,13 @@ describe("NewsClient", () => {
197
215
  });
198
216
 
199
217
  test("getNewsV2 returns valid paginated data", async () => {
200
- const resp = await client.getNewsV2(
201
- Region.Us,
202
- Locale.Tr,
203
- NewsType.BRIEFS,
204
- 0,
205
- 10,
206
- NewsOrderBy.TIMESTAMP,
207
- SortDirection.Desc
208
- );
218
+ const resp = await client.getNewsV2(Region.Us, Locale.Tr, {
219
+ newsType: NewsType.BRIEFS,
220
+ page: 0,
221
+ size: 10,
222
+ orderBy: NewsOrderBy.TIMESTAMP,
223
+ orderByDirection: SortDirection.Desc,
224
+ });
209
225
 
210
226
  expect(resp).toBeDefined();
211
227
  expect(typeof resp.recordCount).toBe("number");
@@ -300,6 +316,42 @@ describe("NewsClient", () => {
300
316
  });
301
317
  });
302
318
 
319
+ describe("getNewsCategories", () => {
320
+ test("calls correct endpoint/params and matches raw response", async () => {
321
+ cli.request.mockResolvedValueOnce({ data: mockNewsCategoriesResponse });
322
+
323
+ const resp = await client.getNewsCategories(Locale.En);
324
+
325
+ expect(cli.request).toHaveBeenCalledTimes(1);
326
+ const call = cli.request.mock.calls[0][0];
327
+
328
+ expect(call.method).toBe("GET");
329
+ expect(call.url).toBe("/api/v1/news/categories");
330
+ expect(call.params).toEqual({ locale: Locale.En });
331
+
332
+ expect(resp).toEqual(mockNewsCategoriesResponse);
333
+ });
334
+
335
+ test("does not send locale when undefined", async () => {
336
+ cli.request.mockResolvedValueOnce({ data: mockNewsCategoriesResponse });
337
+
338
+ await client.getNewsCategories();
339
+
340
+ const call = cli.request.mock.calls[0][0];
341
+ expect(call.params).toEqual({});
342
+ });
343
+
344
+ test("bubbles up request error", async () => {
345
+ cli.request.mockRejectedValueOnce(new Error("Failed to fetch categories"));
346
+
347
+ await expect(client.getNewsCategories(Locale.En)).rejects.toThrow(
348
+ "Failed to fetch categories"
349
+ );
350
+
351
+ expect(cli.request).toHaveBeenCalledTimes(1);
352
+ });
353
+ });
354
+
303
355
  describe("getNews", () => {
304
356
  test("calls correct endpoint/params and matches raw response", async () => {
305
357
  cli.request.mockResolvedValueOnce({ data: mockNewsResponse });
@@ -406,16 +458,21 @@ describe("NewsClient", () => {
406
458
  test("calls correct endpoint/params and matches raw response", async () => {
407
459
  cli.request.mockResolvedValueOnce({ data: mockNewsV2Response });
408
460
 
409
- const resp = await client.getNewsV2(
410
- Region.Tr,
411
- Locale.Tr,
412
- NewsType.BRIEFS,
413
- 1,
414
- 10,
415
- NewsOrderBy.TIMESTAMP,
416
- SortDirection.Desc,
417
- undefined
418
- );
461
+ const resp = await client.getNewsV2(Region.Tr, Locale.Tr, {
462
+ newsType: NewsType.BRIEFS,
463
+ page: 1,
464
+ size: 10,
465
+ orderBy: NewsOrderBy.TIMESTAMP,
466
+ orderByDirection: SortDirection.Desc,
467
+ symbols: "AAPL,MSFT",
468
+ categories: "Sector News",
469
+ sectors: "Technology",
470
+ industries: "Software",
471
+ qualityScoreMin: 7,
472
+ qualityScoreMax: 10,
473
+ timestampFrom: "2026-05-01",
474
+ timestampTo: "2026-06-01",
475
+ });
419
476
 
420
477
  expect(cli.request).toHaveBeenCalledTimes(1);
421
478
  const call = cli.request.mock.calls[0][0];
@@ -429,7 +486,15 @@ describe("NewsClient", () => {
429
486
  page: 1,
430
487
  size: 10,
431
488
  orderBy: NewsOrderBy.TIMESTAMP,
432
- orderByDirection: SortDirection.Desc
489
+ orderByDirection: SortDirection.Desc,
490
+ symbols: "AAPL,MSFT",
491
+ categories: "Sector News",
492
+ sectors: "Technology",
493
+ industries: "Software",
494
+ qualityScoreMin: 7,
495
+ qualityScoreMax: 10,
496
+ timestampFrom: "2026-05-01",
497
+ timestampTo: "2026-06-01",
433
498
  });
434
499
 
435
500
  expect(resp.recordCount).toBe(352);
@@ -457,15 +522,13 @@ describe("NewsClient", () => {
457
522
  cli.request.mockRejectedValueOnce(new Error("Failed to fetch news v2"));
458
523
 
459
524
  await expect(
460
- client.getNewsV2(
461
- Region.Tr,
462
- Locale.Tr,
463
- NewsType.REUTERS,
464
- 0,
465
- 10,
466
- NewsOrderBy.TIMESTAMP,
467
- SortDirection.Desc
468
- )
525
+ client.getNewsV2(Region.Tr, Locale.Tr, {
526
+ newsType: NewsType.REUTERS,
527
+ page: 0,
528
+ size: 10,
529
+ orderBy: NewsOrderBy.TIMESTAMP,
530
+ orderByDirection: SortDirection.Desc,
531
+ })
469
532
  ).rejects.toThrow("Failed to fetch news v2");
470
533
 
471
534
  expect(cli.request).toHaveBeenCalledTimes(1);