bcchapi 1.0.6 → 1.0.7

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.
@@ -0,0 +1,38 @@
1
+ # This workflow will run tests using node and then publish a package to GitHub Packages when a release is created
2
+ # For more information see: https://docs.github.com/en/actions/publishing-packages/publishing-nodejs-packages
3
+
4
+ name: Publish to NPM
5
+
6
+ on:
7
+ push:
8
+ branches: main
9
+
10
+ jobs:
11
+ build:
12
+ runs-on: ubuntu-latest
13
+ permissions:
14
+ contents: read
15
+ steps:
16
+ - uses: actions/checkout@v4
17
+ - uses: actions/setup-node@v3
18
+ with:
19
+ node-version: 20
20
+ - run: npm ci
21
+ - run: npm test -- --run
22
+ - run: npm run build
23
+
24
+ publish-npm:
25
+ needs: build
26
+ runs-on: ubuntu-latest
27
+ permissions:
28
+ id-token: write
29
+ steps:
30
+ - uses: actions/checkout@v4
31
+ - uses: actions/setup-node@v3
32
+ with:
33
+ node-version: 20
34
+ registry-url: https://registry.npmjs.org/
35
+ - run: npm ci
36
+ - run: npm publish --provenance
37
+ env:
38
+ NODE_AUTH_TOKEN: ${{secrets.NPM_TOKEN}}
package/CHANGELOG.md CHANGED
@@ -5,7 +5,17 @@ All notable changes to this project will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
- ## [Unreleased]
8
+ ## [1.0.7] - 2025-02-19
9
+
10
+ ### Changed
11
+
12
+ - Moved API response handlers from `utils.ts` to new `handlers.ts` file
13
+ - Improved date handling in `utils.ts`
14
+ - Fixed date validation in client test
15
+ - Updated dependencies:
16
+ - `@vitest/coverage-v8` from `^1.6.0` to `^3.0.6`
17
+ - `rimraf` from `^5.0.7` to `^6.0.1`
18
+ - `vitest` from `^1.6.0` to `^3.0.6`
9
19
 
10
20
  ## [1.0.6] - 2024-06-13
11
21
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "bcchapi",
3
- "version": "1.0.6",
3
+ "version": "1.0.7",
4
4
  "description": "API para acceder al Web Service del Banco Central de Chile.",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -32,15 +32,15 @@
32
32
  "@types/node": "^20.14.2",
33
33
  "@typescript-eslint/eslint-plugin": "^6.21.0",
34
34
  "@typescript-eslint/parser": "^6.21.0",
35
- "@vitest/coverage-v8": "^1.6.0",
35
+ "@vitest/coverage-v8": "^3.0.6",
36
36
  "eslint": "^8.57.0",
37
37
  "eslint-config-prettier": "^9.1.0",
38
38
  "eslint-plugin-import": "^2.29.1",
39
39
  "prettier": "^3.3.2",
40
- "rimraf": "^5.0.7",
40
+ "rimraf": "^6.0.1",
41
41
  "ts-node": "^10.9.2",
42
42
  "typescript": "^5.4.5",
43
- "vitest": "^1.6.0"
43
+ "vitest": "^3.0.6"
44
44
  },
45
45
  "engines": {
46
46
  "node": ">=18.19.0",
package/src/client.ts CHANGED
@@ -1,7 +1,8 @@
1
1
  import * as querystring from 'node:querystring';
2
2
  import * as assert from 'node:assert/strict';
3
3
  import { GetSeriesResponse, SearchSeriesResponse, ApiResponse } from './types';
4
- import { isValidDate, parseGetSeriesResponse, parseSearchSeriesResponse } from './utils';
4
+ import { handleGetSeriesResponse, handleSearchSeriesResponse } from './handlers';
5
+ import { isValidDate } from './utils';
5
6
 
6
7
  export interface ClientConfig {
7
8
  /**
@@ -25,7 +26,6 @@ export class Client {
25
26
  static apiURL = 'https://si3.bcentral.cl/SieteRestWS/SieteRestWS.ashx';
26
27
 
27
28
  private username: string;
28
-
29
29
  private password: string;
30
30
 
31
31
  constructor(config: ClientConfig) {
@@ -33,14 +33,14 @@ export class Client {
33
33
  this.password = config.pass;
34
34
  }
35
35
 
36
- async request(query: Record<string, string>): Promise<ApiResponse> {
36
+ async request<T extends ApiResponse>(query: Record<string, string>): Promise<T> {
37
37
  const queryString = querystring.stringify({
38
38
  user: this.username,
39
39
  pass: this.password,
40
40
  ...query,
41
41
  });
42
42
 
43
- return (await fetch(`${Client.apiURL}?${queryString}`)).json() as Promise<ApiResponse>;
43
+ return (await fetch(`${Client.apiURL}?${queryString}`)).json() as Promise<T>;
44
44
  }
45
45
 
46
46
  /**
@@ -83,7 +83,7 @@ export class Client {
83
83
  assert.ok(query.firstdate <= query.lastdate, 'invalid date range');
84
84
  }
85
85
 
86
- return this.request(query).then(parseGetSeriesResponse);
86
+ return this.request(query).then(handleGetSeriesResponse);
87
87
  }
88
88
 
89
89
  /**
@@ -104,6 +104,6 @@ export class Client {
104
104
  function: 'SearchSeries',
105
105
  };
106
106
 
107
- return this.request(query).then(parseSearchSeriesResponse);
107
+ return this.request(query).then(handleSearchSeriesResponse);
108
108
  }
109
109
  }
@@ -0,0 +1,69 @@
1
+ import {
2
+ ErrorCodes,
3
+ InvalidFrequencyError,
4
+ InvalidCredentialsError,
5
+ InvalidSeriesError,
6
+ WebServiceError,
7
+ } from './errors';
8
+ import {
9
+ ApiResponse,
10
+ SeriesObservation,
11
+ SeriesMetadata,
12
+ ErrorResponse,
13
+ GetSeriesResponse,
14
+ SearchSeriesResponse,
15
+ } from './types';
16
+ import { reverseDate } from './utils';
17
+
18
+ /**
19
+ * Parses the GetSeries function API response.
20
+ */
21
+ export function handleGetSeriesResponse<T extends ApiResponse>(response: T): GetSeriesResponse {
22
+ if (response.Codigo !== 0) {
23
+ switch (response.Codigo) {
24
+ case ErrorCodes.InvalidCredentials:
25
+ throw new InvalidCredentialsError(response as ApiResponse as ErrorResponse);
26
+ case ErrorCodes.InvalidSeries:
27
+ throw new InvalidSeriesError(response as ApiResponse as ErrorResponse);
28
+ default:
29
+ throw new WebServiceError(response as ApiResponse as ErrorResponse);
30
+ }
31
+ }
32
+
33
+ return {
34
+ seriesId: response.Series.seriesId || '',
35
+ description: response.Series.descripIng || '',
36
+ data: (response.Series.Obs || []).map((obs: SeriesObservation) => ({
37
+ date: reverseDate(obs.indexDateString),
38
+ value: parseFloat(obs.value),
39
+ })),
40
+ };
41
+ }
42
+
43
+ /**
44
+ * Parses the SearchSeries function API response.
45
+ */
46
+ export function handleSearchSeriesResponse<T extends ApiResponse>(
47
+ response: T,
48
+ ): SearchSeriesResponse {
49
+ if (response.Codigo !== 0) {
50
+ switch (response.Codigo) {
51
+ case ErrorCodes.InvalidCredentials:
52
+ throw new InvalidCredentialsError(response as ApiResponse as ErrorResponse);
53
+ case ErrorCodes.InvalidFrequency:
54
+ throw new InvalidFrequencyError(response as ApiResponse as ErrorResponse);
55
+ default:
56
+ throw new WebServiceError(response as ApiResponse as ErrorResponse);
57
+ }
58
+ }
59
+
60
+ return response.SeriesInfos.map((series: SeriesMetadata) => ({
61
+ seriesId: series.seriesId,
62
+ frequency: series.frequencyCode,
63
+ title: series.englishTitle,
64
+ firstObservedAt: reverseDate(series.firstObservation),
65
+ lastObservedAt: reverseDate(series.lastObservation),
66
+ updatedAt: reverseDate(series.updatedAt),
67
+ createdAt: reverseDate(series.createdAt),
68
+ }));
69
+ }
package/src/types.ts CHANGED
@@ -1,3 +1,5 @@
1
+ export type StatusCode = 'OK' | 'ND';
2
+
1
3
  export interface SeriesObservation {
2
4
  /**
3
5
  * Series observed date in DD-MM-YYYY format.
@@ -10,7 +12,7 @@ export interface SeriesObservation {
10
12
  /**
11
13
  * Series observed value status code (ND = no data recorded).
12
14
  */
13
- statusCode: 'OK' | 'ND';
15
+ statusCode: StatusCode;
14
16
  }
15
17
 
16
18
  export interface SeriesHistory {
@@ -75,20 +77,20 @@ export interface ApiResponse {
75
77
  /**
76
78
  * Response status code.
77
79
  */
78
- Codigo: number;
80
+ readonly Codigo: number;
79
81
  /**
80
82
  * Response status message.
81
83
  */
82
- Descripcion: string;
84
+ readonly Descripcion: string;
83
85
 
84
86
  /**
85
87
  * Series historic information.
86
88
  */
87
- Series: SeriesHistory | NullSeries;
89
+ readonly Series: Readonly<SeriesHistory | NullSeries>;
88
90
  /**
89
91
  * Series metadata information.
90
92
  */
91
- SeriesInfos: SeriesMetadata[];
93
+ readonly SeriesInfos: ReadonlyArray<SeriesMetadata>;
92
94
  }
93
95
 
94
96
  export interface ErrorResponse extends ApiResponse {
package/src/utils.ts CHANGED
@@ -1,29 +1,24 @@
1
- import {
2
- ErrorCodes,
3
- InvalidFrequencyError,
4
- InvalidCredentialsError,
5
- InvalidSeriesError,
6
- WebServiceError,
7
- } from './errors';
8
- import {
9
- ApiResponse,
10
- SeriesObservation,
11
- SeriesMetadata,
12
- ErrorResponse,
13
- GetSeriesResponse,
14
- SearchSeriesResponse,
15
- } from './types';
16
-
17
1
  /**
18
2
  * Determines wether a given value can be parsed to a valid date.
19
3
  */
20
4
  export function isValidDate(date: unknown): boolean {
21
5
  if (typeof date === 'string') {
22
- return !Number.isNaN(Date.parse(date));
23
- }
24
- if (date instanceof Date) {
6
+ // Validate format YYYY-MM-DD
7
+ const isISOString = date.match(/^\d{4}-\d{2}-\d{2}$/);
8
+
9
+ if (!isISOString) {
10
+ return false;
11
+ }
12
+
13
+ // Validate parsed date timestamp
14
+ const timestamp = Date.parse(date);
15
+
16
+ return !Number.isNaN(timestamp);
17
+ } else if (date instanceof Date) {
18
+ // Validate date object
25
19
  return !Number.isNaN(date.getTime());
26
20
  }
21
+ // Is invalid date
27
22
  return false;
28
23
  }
29
24
 
@@ -31,58 +26,12 @@ export function isValidDate(date: unknown): boolean {
31
26
  * Reverses a date string from DD-MM-YYYY to YYYY-MM-DD format.
32
27
  */
33
28
  export function reverseDate(date: string): string {
34
- return date.split('-').reverse().join('-');
35
- }
36
-
37
- /**
38
- * Parses the GetSeries function API response.
39
- */
40
- export function parseGetSeriesResponse<T extends ApiResponse>(response: T): GetSeriesResponse {
41
- if (response.Codigo !== 0) {
42
- switch (response.Codigo) {
43
- case ErrorCodes.InvalidCredentials:
44
- throw new InvalidCredentialsError(response as ApiResponse as ErrorResponse);
45
- case ErrorCodes.InvalidSeries:
46
- throw new InvalidSeriesError(response as ApiResponse as ErrorResponse);
47
- default:
48
- throw new WebServiceError(response as ApiResponse as ErrorResponse);
49
- }
29
+ if (/^\d{4}-\d{2}-\d{2}$/.test(date)) {
30
+ return date;
50
31
  }
51
32
 
52
- return {
53
- seriesId: response.Series.seriesId || '',
54
- description: response.Series.descripIng || '',
55
- data: (response.Series.Obs || []).map((obs: SeriesObservation) => ({
56
- date: reverseDate(obs.indexDateString),
57
- value: parseFloat(obs.value),
58
- })),
59
- };
60
- }
61
-
62
- /**
63
- * Parses the SearchSeries function API response.
64
- */
65
- export function parseSearchSeriesResponse<T extends ApiResponse>(
66
- response: T,
67
- ): SearchSeriesResponse {
68
- if (response.Codigo !== 0) {
69
- switch (response.Codigo) {
70
- case ErrorCodes.InvalidCredentials:
71
- throw new InvalidCredentialsError(response as ApiResponse as ErrorResponse);
72
- case ErrorCodes.InvalidFrequency:
73
- throw new InvalidFrequencyError(response as ApiResponse as ErrorResponse);
74
- default:
75
- throw new WebServiceError(response as ApiResponse as ErrorResponse);
76
- }
33
+ if (!/^\d{2}-\d{2}-\d{4}$/.test(date)) {
34
+ throw new Error('Invalid date format. Expected DD-MM-YYYY');
77
35
  }
78
-
79
- return response.SeriesInfos.map((series: SeriesMetadata) => ({
80
- seriesId: series.seriesId,
81
- frequency: series.frequencyCode,
82
- title: series.englishTitle,
83
- firstObservedAt: reverseDate(series.firstObservation),
84
- lastObservedAt: reverseDate(series.lastObservation),
85
- updatedAt: reverseDate(series.updatedAt),
86
- createdAt: reverseDate(series.createdAt),
87
- }));
36
+ return date.split('-').reverse().join('-');
88
37
  }
@@ -112,8 +112,8 @@ describe('Client', () => {
112
112
  expect(series.data).toHaveLength(15);
113
113
 
114
114
  for (let i = 0; i < series.data.length; i += 1) {
115
- expect(reverseDate(series.data[i].date)).toBe(
116
- fixtures.response.getSeriesSuccess.Series.Obs[i].indexDateString,
115
+ expect(series.data[i].date).toBe(
116
+ reverseDate(fixtures.response.getSeriesSuccess.Series.Obs[i].indexDateString),
117
117
  );
118
118
  expect(series.data[i].value.toFixed(2)).toBe(
119
119
  fixtures.response.getSeriesSuccess.Series.Obs[i].value,
@@ -140,8 +140,8 @@ describe('Client', () => {
140
140
  expect(series.data).toHaveLength(5);
141
141
 
142
142
  for (let i = 0; i < series.data.length; i += 1) {
143
- expect(reverseDate(series.data[i].date)).toBe(
144
- fixtures.response.getSeriesSuccess.Series.Obs[i].indexDateString,
143
+ expect(series.data[i].date).toBe(
144
+ reverseDate(fixtures.response.getSeriesSuccess.Series.Obs[i].indexDateString),
145
145
  );
146
146
  expect(series.data[i].value.toFixed(2)).toBe(
147
147
  fixtures.response.getSeriesSuccess.Series.Obs[i].value,
@@ -1,12 +1,12 @@
1
1
  import { describe, it, expect } from 'vitest';
2
2
  import * as Errors from '../../src/errors';
3
- import { parseGetSeriesResponse } from '../../src/utils';
3
+ import { handleGetSeriesResponse } from '../../src/handlers';
4
4
  import { ApiResponse } from '../../src/types';
5
5
  import fixtures from '../fixtures';
6
6
 
7
- describe('parseGetSeriesResponse', () => {
7
+ describe('handleGetSeriesResponse', () => {
8
8
  it('should parse correctly a valid response', () => {
9
- const parsed = parseGetSeriesResponse(
9
+ const parsed = handleGetSeriesResponse(
10
10
  fixtures.response.getSeriesSuccess as unknown as ApiResponse,
11
11
  );
12
12
 
@@ -29,17 +29,17 @@ describe('parseGetSeriesResponse', () => {
29
29
 
30
30
  it('should throw an InvalidCredentialsError if the response code is -5', () => {
31
31
  expect(() =>
32
- parseGetSeriesResponse(fixtures.response.credentialsInvalid as unknown as ApiResponse),
32
+ handleGetSeriesResponse(fixtures.response.credentialsInvalid as unknown as ApiResponse),
33
33
  ).toThrow(Errors.InvalidCredentialsError);
34
34
  });
35
35
 
36
36
  it('should throw an InvalidSeriesError if the response code is -50', () => {
37
37
  expect(() =>
38
- parseGetSeriesResponse(fixtures.response.getSeriesInvalid as unknown as ApiResponse),
38
+ handleGetSeriesResponse(fixtures.response.getSeriesInvalid as unknown as ApiResponse),
39
39
  ).toThrow(Errors.InvalidSeriesError);
40
40
  });
41
41
 
42
42
  it('should throw a ResponseError if the response code is unknown', () => {
43
- expect(() => parseGetSeriesResponse({} as ApiResponse)).toThrow(Errors.WebServiceError);
43
+ expect(() => handleGetSeriesResponse({} as ApiResponse)).toThrow(Errors.WebServiceError);
44
44
  });
45
45
  });
@@ -1,12 +1,12 @@
1
1
  import { describe, it, expect } from 'vitest';
2
2
  import * as Errors from '../../src/errors';
3
3
  import { ApiResponse } from '../../src/types';
4
- import { parseSearchSeriesResponse } from '../../src/utils';
4
+ import { handleSearchSeriesResponse } from '../../src/handlers';
5
5
  import fixtures from '../fixtures';
6
6
 
7
- describe('parseSearchSeriesResponse', () => {
7
+ describe('handleSearchSeriesResponse', () => {
8
8
  it('should parse correctly a valid response', () => {
9
- const parsed = parseSearchSeriesResponse(
9
+ const parsed = handleSearchSeriesResponse(
10
10
  fixtures.response.searchSeriesSuccess as unknown as ApiResponse,
11
11
  );
12
12
 
@@ -32,17 +32,17 @@ describe('parseSearchSeriesResponse', () => {
32
32
 
33
33
  it('should throw an InvalidCredentialsError if the response code is -5', () => {
34
34
  expect(() =>
35
- parseSearchSeriesResponse(fixtures.response.credentialsInvalid as unknown as ApiResponse),
35
+ handleSearchSeriesResponse(fixtures.response.credentialsInvalid as unknown as ApiResponse),
36
36
  ).toThrow(Errors.InvalidCredentialsError);
37
37
  });
38
38
 
39
39
  it('should throw an InvalidFrequencyError if the response code is -1', () => {
40
40
  expect(() =>
41
- parseSearchSeriesResponse(fixtures.response.searchSeriesInvalid as unknown as ApiResponse),
41
+ handleSearchSeriesResponse(fixtures.response.searchSeriesInvalid as unknown as ApiResponse),
42
42
  ).toThrow(Errors.InvalidFrequencyError);
43
43
  });
44
44
 
45
45
  it('should throw a ResponseError if the response code is unknown', () => {
46
- expect(() => parseSearchSeriesResponse({} as ApiResponse)).toThrow(Errors.WebServiceError);
46
+ expect(() => handleSearchSeriesResponse({} as ApiResponse)).toThrow(Errors.WebServiceError);
47
47
  });
48
48
  });
package/dist/client.d.ts DELETED
@@ -1,50 +0,0 @@
1
- import { GetSeriesResponse, SearchSeriesResponse, ApiResponse } from './types';
2
- export interface ClientConfig {
3
- /**
4
- * Client username (registered email).
5
- */
6
- user: string;
7
- /**
8
- * Client password.
9
- */
10
- pass: string;
11
- }
12
- export declare enum Frequency {
13
- Daily = "DAILY",
14
- Monthly = "MONTHLY",
15
- Quarterly = "QUARTERLY",
16
- Annual = "ANNUAL"
17
- }
18
- export declare class Client {
19
- static apiURL: string;
20
- private username;
21
- private password;
22
- constructor(config: ClientConfig);
23
- request(query: Record<string, string>): Promise<ApiResponse>;
24
- /**
25
- * Fetches the list of observed values for a given series.
26
- */
27
- getSeries(params: {
28
- /**
29
- * Series identifier.
30
- */
31
- series: string;
32
- /**
33
- * First date of the range to fetch.
34
- */
35
- since?: string | Date;
36
- /**
37
- * Last date of the range to fetch.
38
- */
39
- until?: string | Date;
40
- }): Promise<GetSeriesResponse>;
41
- /**
42
- * Fetches the list of available series by frequency and their metadata.
43
- */
44
- searchSeries(params: {
45
- /**
46
- * Frequency for which you want to consult the catalog of available series.
47
- */
48
- frequency: Frequency;
49
- }): Promise<SearchSeriesResponse>;
50
- }
package/dist/client.js DELETED
@@ -1,89 +0,0 @@
1
- "use strict";
2
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
- if (k2 === undefined) k2 = k;
4
- var desc = Object.getOwnPropertyDescriptor(m, k);
5
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
- desc = { enumerable: true, get: function() { return m[k]; } };
7
- }
8
- Object.defineProperty(o, k2, desc);
9
- }) : (function(o, m, k, k2) {
10
- if (k2 === undefined) k2 = k;
11
- o[k2] = m[k];
12
- }));
13
- var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
- Object.defineProperty(o, "default", { enumerable: true, value: v });
15
- }) : function(o, v) {
16
- o["default"] = v;
17
- });
18
- var __importStar = (this && this.__importStar) || function (mod) {
19
- if (mod && mod.__esModule) return mod;
20
- var result = {};
21
- if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
- __setModuleDefault(result, mod);
23
- return result;
24
- };
25
- Object.defineProperty(exports, "__esModule", { value: true });
26
- exports.Client = exports.Frequency = void 0;
27
- const querystring = __importStar(require("node:querystring"));
28
- const assert = __importStar(require("node:assert/strict"));
29
- const utils_1 = require("./utils");
30
- var Frequency;
31
- (function (Frequency) {
32
- Frequency["Daily"] = "DAILY";
33
- Frequency["Monthly"] = "MONTHLY";
34
- Frequency["Quarterly"] = "QUARTERLY";
35
- Frequency["Annual"] = "ANNUAL";
36
- })(Frequency || (exports.Frequency = Frequency = {}));
37
- class Client {
38
- static apiURL = 'https://si3.bcentral.cl/SieteRestWS/SieteRestWS.ashx';
39
- username;
40
- password;
41
- constructor(config) {
42
- this.username = config.user;
43
- this.password = config.pass;
44
- }
45
- async request(query) {
46
- const queryString = querystring.stringify({
47
- user: this.username,
48
- pass: this.password,
49
- ...query,
50
- });
51
- return (await fetch(`${Client.apiURL}?${queryString}`)).json();
52
- }
53
- /**
54
- * Fetches the list of observed values for a given series.
55
- */
56
- async getSeries(params) {
57
- const { series, since, until } = params;
58
- assert.ok(series && typeof series === 'string', 'series must be a non-empty string');
59
- const query = {
60
- timeseries: series,
61
- function: 'GetSeries',
62
- };
63
- if (since) {
64
- assert.ok((0, utils_1.isValidDate)(since), '"since" is not a valid date string or Date object');
65
- query.firstdate = typeof since === 'string' ? since : since.toISOString().slice(0, 10);
66
- }
67
- if (until) {
68
- assert.ok((0, utils_1.isValidDate)(until), '"until" is not a valid date string or Date object');
69
- query.lastdate = typeof until === 'string' ? until : until.toISOString().slice(0, 10);
70
- }
71
- if (query.firstdate && query.lastdate) {
72
- assert.ok(query.firstdate <= query.lastdate, 'invalid date range');
73
- }
74
- return this.request(query).then(utils_1.parseGetSeriesResponse);
75
- }
76
- /**
77
- * Fetches the list of available series by frequency and their metadata.
78
- */
79
- async searchSeries(params) {
80
- const { frequency } = params;
81
- assert.ok(frequency && typeof frequency === 'string', 'frequency must be a non-empty string');
82
- const query = {
83
- frequency,
84
- function: 'SearchSeries',
85
- };
86
- return this.request(query).then(utils_1.parseSearchSeriesResponse);
87
- }
88
- }
89
- exports.Client = Client;
package/dist/errors.d.ts DELETED
@@ -1,21 +0,0 @@
1
- import { ErrorResponse } from './types';
2
- export declare enum ErrorCodes {
3
- InvalidCredentials = -5,
4
- InvalidFrequency = -1,
5
- InvalidSeries = -50,
6
- InvalidDateRange = -1,
7
- Unknown = -1
8
- }
9
- export declare class WebServiceError extends Error {
10
- response?: ErrorResponse;
11
- constructor(response?: ErrorResponse, message?: string);
12
- }
13
- export declare class InvalidFrequencyError extends WebServiceError {
14
- constructor(response?: ErrorResponse);
15
- }
16
- export declare class InvalidCredentialsError extends WebServiceError {
17
- constructor(response?: ErrorResponse);
18
- }
19
- export declare class InvalidSeriesError extends WebServiceError {
20
- constructor(response?: ErrorResponse);
21
- }
package/dist/errors.js DELETED
@@ -1,37 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.InvalidSeriesError = exports.InvalidCredentialsError = exports.InvalidFrequencyError = exports.WebServiceError = exports.ErrorCodes = void 0;
4
- var ErrorCodes;
5
- (function (ErrorCodes) {
6
- ErrorCodes[ErrorCodes["InvalidCredentials"] = -5] = "InvalidCredentials";
7
- ErrorCodes[ErrorCodes["InvalidFrequency"] = -1] = "InvalidFrequency";
8
- ErrorCodes[ErrorCodes["InvalidSeries"] = -50] = "InvalidSeries";
9
- ErrorCodes[ErrorCodes["InvalidDateRange"] = -1] = "InvalidDateRange";
10
- ErrorCodes[ErrorCodes["Unknown"] = -1] = "Unknown";
11
- })(ErrorCodes || (exports.ErrorCodes = ErrorCodes = {}));
12
- class WebServiceError extends Error {
13
- response;
14
- constructor(response, message) {
15
- super(message || response?.Descripcion || 'Unknown service error');
16
- this.response = response;
17
- }
18
- }
19
- exports.WebServiceError = WebServiceError;
20
- class InvalidFrequencyError extends WebServiceError {
21
- constructor(response) {
22
- super(response, 'Invalid frequency code (must be DAILY, MONTHLY, QUARTERLY or ANNUAL)');
23
- }
24
- }
25
- exports.InvalidFrequencyError = InvalidFrequencyError;
26
- class InvalidCredentialsError extends WebServiceError {
27
- constructor(response) {
28
- super(response, 'Invalid username or password');
29
- }
30
- }
31
- exports.InvalidCredentialsError = InvalidCredentialsError;
32
- class InvalidSeriesError extends WebServiceError {
33
- constructor(response) {
34
- super(response, 'Invalid series id');
35
- }
36
- }
37
- exports.InvalidSeriesError = InvalidSeriesError;
package/dist/index.d.ts DELETED
@@ -1,3 +0,0 @@
1
- export { Client, ClientConfig, Frequency } from './client';
2
- export { ApiResponse, ErrorResponse, GetSeriesResponse, SearchSeriesResponse } from './types';
3
- export { WebServiceError, InvalidCredentialsError, InvalidFrequencyError, InvalidSeriesError, } from './errors';
package/dist/index.js DELETED
@@ -1,11 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.InvalidSeriesError = exports.InvalidFrequencyError = exports.InvalidCredentialsError = exports.WebServiceError = exports.Frequency = exports.Client = void 0;
4
- var client_1 = require("./client");
5
- Object.defineProperty(exports, "Client", { enumerable: true, get: function () { return client_1.Client; } });
6
- Object.defineProperty(exports, "Frequency", { enumerable: true, get: function () { return client_1.Frequency; } });
7
- var errors_1 = require("./errors");
8
- Object.defineProperty(exports, "WebServiceError", { enumerable: true, get: function () { return errors_1.WebServiceError; } });
9
- Object.defineProperty(exports, "InvalidCredentialsError", { enumerable: true, get: function () { return errors_1.InvalidCredentialsError; } });
10
- Object.defineProperty(exports, "InvalidFrequencyError", { enumerable: true, get: function () { return errors_1.InvalidFrequencyError; } });
11
- Object.defineProperty(exports, "InvalidSeriesError", { enumerable: true, get: function () { return errors_1.InvalidSeriesError; } });
package/dist/types.d.ts DELETED
@@ -1,108 +0,0 @@
1
- export interface SeriesObservation {
2
- /**
3
- * Series observed date in DD-MM-YYYY format.
4
- */
5
- indexDateString: string;
6
- /**
7
- * Series observed value.
8
- */
9
- value: string;
10
- /**
11
- * Series observed value status code (ND = no data recorded).
12
- */
13
- statusCode: 'OK' | 'ND';
14
- }
15
- export interface SeriesHistory {
16
- /**
17
- * Series identifier.
18
- */
19
- seriesId: string;
20
- /**
21
- * Series name in Spanish.
22
- */
23
- descripEsp: string;
24
- /**
25
- * Series name in English.
26
- */
27
- descripIng: string;
28
- /**
29
- * List of series observed values.
30
- */
31
- Obs: SeriesObservation[];
32
- }
33
- export type NullSeries = {
34
- [key in keyof SeriesHistory]: null;
35
- };
36
- export interface SeriesMetadata {
37
- /**
38
- * Series identifier.
39
- */
40
- seriesId: string;
41
- /**
42
- * Series frequency.
43
- */
44
- frequencyCode: string;
45
- /**
46
- * Series name in Spanish.
47
- */
48
- spanishTitle: string;
49
- /**
50
- * Series name in English.
51
- */
52
- englishTitle: string;
53
- /**
54
- * Date of first observation in DD-MM-YYYY format.
55
- */
56
- firstObservation: string;
57
- /**
58
- * Date of last observation in DD-MM-YYYY format.
59
- */
60
- lastObservation: string;
61
- /**
62
- * Date of last update in DD-MM-YYYY format.
63
- */
64
- updatedAt: string;
65
- /**
66
- * Date of creation in DD-MM-YYYY format.
67
- */
68
- createdAt: string;
69
- }
70
- export interface ApiResponse {
71
- /**
72
- * Response status code.
73
- */
74
- Codigo: number;
75
- /**
76
- * Response status message.
77
- */
78
- Descripcion: string;
79
- /**
80
- * Series historic information.
81
- */
82
- Series: SeriesHistory | NullSeries;
83
- /**
84
- * Series metadata information.
85
- */
86
- SeriesInfos: SeriesMetadata[];
87
- }
88
- export interface ErrorResponse extends ApiResponse {
89
- Series: NullSeries;
90
- SeriesInfos: never[];
91
- }
92
- export interface GetSeriesResponse {
93
- seriesId: string;
94
- description: string;
95
- data: ReadonlyArray<{
96
- date: string;
97
- value: number;
98
- }>;
99
- }
100
- export type SearchSeriesResponse = ReadonlyArray<{
101
- seriesId: string;
102
- frequency: string;
103
- title: string;
104
- firstObservedAt: string;
105
- lastObservedAt: string;
106
- updatedAt: string;
107
- createdAt: string;
108
- }>;
package/dist/types.js DELETED
@@ -1,2 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
package/dist/utils.d.ts DELETED
@@ -1,17 +0,0 @@
1
- import { ApiResponse, GetSeriesResponse, SearchSeriesResponse } from './types';
2
- /**
3
- * Determines wether a given value can be parsed to a valid date.
4
- */
5
- export declare function isValidDate(date: unknown): boolean;
6
- /**
7
- * Reverses a date string from DD-MM-YYYY to YYYY-MM-DD format.
8
- */
9
- export declare function reverseDate(date: string): string;
10
- /**
11
- * Parses the GetSeries function API response.
12
- */
13
- export declare function parseGetSeriesResponse<T extends ApiResponse>(response: T): GetSeriesResponse;
14
- /**
15
- * Parses the SearchSeries function API response.
16
- */
17
- export declare function parseSearchSeriesResponse<T extends ApiResponse>(response: T): SearchSeriesResponse;
package/dist/utils.js DELETED
@@ -1,73 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.parseSearchSeriesResponse = exports.parseGetSeriesResponse = exports.reverseDate = exports.isValidDate = void 0;
4
- const errors_1 = require("./errors");
5
- /**
6
- * Determines wether a given value can be parsed to a valid date.
7
- */
8
- function isValidDate(date) {
9
- if (typeof date === 'string') {
10
- return !Number.isNaN(Date.parse(date));
11
- }
12
- if (date instanceof Date) {
13
- return !Number.isNaN(date.getTime());
14
- }
15
- return false;
16
- }
17
- exports.isValidDate = isValidDate;
18
- /**
19
- * Reverses a date string from DD-MM-YYYY to YYYY-MM-DD format.
20
- */
21
- function reverseDate(date) {
22
- return date.split('-').reverse().join('-');
23
- }
24
- exports.reverseDate = reverseDate;
25
- /**
26
- * Parses the GetSeries function API response.
27
- */
28
- function parseGetSeriesResponse(response) {
29
- if (response.Codigo !== 0) {
30
- switch (response.Codigo) {
31
- case errors_1.ErrorCodes.InvalidCredentials:
32
- throw new errors_1.InvalidCredentialsError(response);
33
- case errors_1.ErrorCodes.InvalidSeries:
34
- throw new errors_1.InvalidSeriesError(response);
35
- default:
36
- throw new errors_1.WebServiceError(response);
37
- }
38
- }
39
- return {
40
- seriesId: response.Series.seriesId || '',
41
- description: response.Series.descripIng || '',
42
- data: (response.Series.Obs || []).map((obs) => ({
43
- date: reverseDate(obs.indexDateString),
44
- value: parseFloat(obs.value),
45
- })),
46
- };
47
- }
48
- exports.parseGetSeriesResponse = parseGetSeriesResponse;
49
- /**
50
- * Parses the SearchSeries function API response.
51
- */
52
- function parseSearchSeriesResponse(response) {
53
- if (response.Codigo !== 0) {
54
- switch (response.Codigo) {
55
- case errors_1.ErrorCodes.InvalidCredentials:
56
- throw new errors_1.InvalidCredentialsError(response);
57
- case errors_1.ErrorCodes.InvalidFrequency:
58
- throw new errors_1.InvalidFrequencyError(response);
59
- default:
60
- throw new errors_1.WebServiceError(response);
61
- }
62
- }
63
- return response.SeriesInfos.map((series) => ({
64
- seriesId: series.seriesId,
65
- frequency: series.frequencyCode,
66
- title: series.englishTitle,
67
- firstObservedAt: reverseDate(series.firstObservation),
68
- lastObservedAt: reverseDate(series.lastObservation),
69
- updatedAt: reverseDate(series.updatedAt),
70
- createdAt: reverseDate(series.createdAt),
71
- }));
72
- }
73
- exports.parseSearchSeriesResponse = parseSearchSeriesResponse;