bcchapi 1.0.0 → 1.0.1

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.
Files changed (44) hide show
  1. package/.eslintignore +3 -0
  2. package/.eslintrc.json +21 -0
  3. package/.prettierrc.json +17 -0
  4. package/.vscode/extensions.json +3 -0
  5. package/.vscode/settings.json +4 -0
  6. package/dist/client.d.ts +50 -0
  7. package/dist/client.js +93 -0
  8. package/dist/errors.d.ts +21 -0
  9. package/dist/errors.js +37 -0
  10. package/dist/helpers/is-valid-date.d.ts +1 -0
  11. package/dist/helpers/is-valid-date.js +12 -0
  12. package/dist/helpers/parsers.d.ts +3 -0
  13. package/dist/helpers/parsers.js +51 -0
  14. package/dist/helpers/reverse-date.d.ts +1 -0
  15. package/dist/helpers/reverse-date.js +6 -0
  16. package/dist/index.d.ts +3 -0
  17. package/dist/index.js +11 -0
  18. package/dist/types.d.ts +109 -0
  19. package/dist/types.js +2 -0
  20. package/package.json +10 -2
  21. package/src/client.ts +51 -52
  22. package/src/errors.ts +2 -2
  23. package/src/helpers/is-valid-date.ts +9 -0
  24. package/src/helpers/parsers.ts +56 -0
  25. package/src/helpers/reverse-date.ts +3 -0
  26. package/src/index.ts +8 -3
  27. package/src/types.ts +113 -0
  28. package/test/client.test.ts +89 -59
  29. package/test/fixtures/index.ts +1 -1
  30. package/test/fixtures/responses/credentials.invalid.json +1 -1
  31. package/test/fixtures/responses/getseries.invalid.json +1 -1
  32. package/test/fixtures/responses/getseries.success.json +1 -1
  33. package/test/fixtures/responses/searchseries.invalid.json +1 -1
  34. package/test/fixtures/responses/searchseries.success.json +13 -11
  35. package/test/{helpers.test.ts → helpers/is-valid-date.test.ts} +3 -12
  36. package/test/helpers/parse-get-series.test.ts +45 -0
  37. package/test/helpers/parse-search-series.test.ts +48 -0
  38. package/test/helpers/reverse-date.test.ts +11 -0
  39. package/test/mocks/fetch.mock.ts +18 -13
  40. package/tsconfig.eslint.json +5 -0
  41. package/tsconfig.json +1 -1
  42. package/src/helpers.ts +0 -13
  43. package/src/response.ts +0 -175
  44. package/test/response.test.ts +0 -71
package/.eslintignore ADDED
@@ -0,0 +1,3 @@
1
+ node_modules
2
+ coverage
3
+ dist
package/.eslintrc.json ADDED
@@ -0,0 +1,21 @@
1
+ {
2
+ "env": {
3
+ "es2021": true,
4
+ "node": true
5
+ },
6
+ "extends": ["eslint:recommended", "plugin:@typescript-eslint/recommended", "prettier"],
7
+ "overrides": [],
8
+ "parser": "@typescript-eslint/parser",
9
+ "parserOptions": {
10
+ "ecmaVersion": "latest",
11
+ "sourceType": "module",
12
+ "project": "./tsconfig.eslint.json"
13
+ },
14
+ "plugins": ["@typescript-eslint"],
15
+ "rules": {
16
+ "max-classes-per-file": "off",
17
+ "eol-last": ["error", "always"],
18
+ "@typescript-eslint/no-unused-vars": "error",
19
+ "@typescript-eslint/consistent-type-definitions": ["error", "interface"]
20
+ }
21
+ }
@@ -0,0 +1,17 @@
1
+ {
2
+ "semi": true,
3
+ "singleQuote": true,
4
+ "arrowParens": "always",
5
+ "trailingComma": "all",
6
+ "tabWidth": 2,
7
+ "printWidth": 100,
8
+ "endOfLine": "lf",
9
+ "overrides": [
10
+ {
11
+ "files": "*.json",
12
+ "options": {
13
+ "trailingComma": "none"
14
+ }
15
+ }
16
+ ]
17
+ }
@@ -0,0 +1,3 @@
1
+ {
2
+ "recommendations": ["esbenp.prettier-vscode"]
3
+ }
@@ -0,0 +1,4 @@
1
+ {
2
+ "editor.defaultFormatter": "esbenp.prettier-vscode",
3
+ "editor.formatOnSave": true
4
+ }
@@ -0,0 +1,50 @@
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 ADDED
@@ -0,0 +1,93 @@
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
+ var __importDefault = (this && this.__importDefault) || function (mod) {
26
+ return (mod && mod.__esModule) ? mod : { "default": mod };
27
+ };
28
+ Object.defineProperty(exports, "__esModule", { value: true });
29
+ exports.Client = exports.Frequency = void 0;
30
+ const querystring = __importStar(require("node:querystring"));
31
+ const assert = __importStar(require("node:assert/strict"));
32
+ const parsers_1 = require("./helpers/parsers");
33
+ const is_valid_date_1 = __importDefault(require("./helpers/is-valid-date"));
34
+ var Frequency;
35
+ (function (Frequency) {
36
+ Frequency["Daily"] = "DAILY";
37
+ Frequency["Monthly"] = "MONTHLY";
38
+ Frequency["Quarterly"] = "QUARTERLY";
39
+ Frequency["Annual"] = "ANNUAL";
40
+ })(Frequency || (exports.Frequency = Frequency = {}));
41
+ class Client {
42
+ static apiURL = 'https://si3.bcentral.cl/SieteRestWS/SieteRestWS.ashx';
43
+ username;
44
+ password;
45
+ constructor(config) {
46
+ this.username = config.user;
47
+ this.password = config.pass;
48
+ }
49
+ async request(query) {
50
+ const queryString = querystring.stringify({
51
+ user: this.username,
52
+ pass: this.password,
53
+ ...query,
54
+ });
55
+ return (await fetch(`${Client.apiURL}?${queryString}`)).json();
56
+ }
57
+ /**
58
+ * Fetches the list of observed values for a given series.
59
+ */
60
+ async getSeries(params) {
61
+ const { series, since, until } = params;
62
+ assert.ok(series && typeof series === 'string', 'series must be a non-empty string');
63
+ const query = {
64
+ timeseries: series,
65
+ function: 'GetSeries',
66
+ };
67
+ if (since) {
68
+ assert.ok((0, is_valid_date_1.default)(since), '"since" is not a valid date string or Date object');
69
+ query.firstdate = typeof since === 'string' ? since : since.toISOString().slice(0, 10);
70
+ }
71
+ if (until) {
72
+ assert.ok((0, is_valid_date_1.default)(until), '"until" is not a valid date string or Date object');
73
+ query.lastdate = typeof until === 'string' ? until : until.toISOString().slice(0, 10);
74
+ }
75
+ if (query.firstdate && query.lastdate) {
76
+ assert.ok(query.firstdate <= query.lastdate, 'invalid date range');
77
+ }
78
+ return this.request(query).then(parsers_1.parseGetSeriesResponse);
79
+ }
80
+ /**
81
+ * Fetches the list of available series by frequency and their metadata.
82
+ */
83
+ async searchSeries(params) {
84
+ const { frequency } = params;
85
+ assert.ok(frequency && typeof frequency === 'string', 'frequency must be a non-empty string');
86
+ const query = {
87
+ frequency,
88
+ function: 'SearchSeries',
89
+ };
90
+ return this.request(query).then(parsers_1.parseSearchSeriesResponse);
91
+ }
92
+ }
93
+ exports.Client = Client;
@@ -0,0 +1,21 @@
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 ADDED
@@ -0,0 +1,37 @@
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;
@@ -0,0 +1 @@
1
+ export default function isValidDate(date: unknown): boolean;
@@ -0,0 +1,12 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ function isValidDate(date) {
4
+ if (typeof date === 'string') {
5
+ return !Number.isNaN(Date.parse(date));
6
+ }
7
+ if (date instanceof Date) {
8
+ return !Number.isNaN(date.getTime());
9
+ }
10
+ return false;
11
+ }
12
+ exports.default = isValidDate;
@@ -0,0 +1,3 @@
1
+ import { ApiResponse, GetSeriesResponse, SearchSeriesResponse } from '../types';
2
+ export declare function parseGetSeriesResponse<T extends ApiResponse>(response: T): GetSeriesResponse;
3
+ export declare function parseSearchSeriesResponse<T extends ApiResponse>(response: T): SearchSeriesResponse;
@@ -0,0 +1,51 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.parseSearchSeriesResponse = exports.parseGetSeriesResponse = void 0;
7
+ const reverse_date_1 = __importDefault(require("./reverse-date"));
8
+ const errors_1 = require("../errors");
9
+ function parseGetSeriesResponse(response) {
10
+ if (response.Codigo !== 0) {
11
+ switch (response.Codigo) {
12
+ case errors_1.ErrorCodes.InvalidCredentials:
13
+ throw new errors_1.InvalidCredentialsError();
14
+ case errors_1.ErrorCodes.InvalidSeries:
15
+ throw new errors_1.InvalidSeriesError();
16
+ default:
17
+ throw new errors_1.WebServiceError(response);
18
+ }
19
+ }
20
+ return {
21
+ seriesId: response.Series.seriesId || '',
22
+ description: response.Series.descripIng || '',
23
+ data: (response.Series.Obs || []).map((obs) => ({
24
+ date: (0, reverse_date_1.default)(obs.indexDateString),
25
+ value: parseFloat(obs.value),
26
+ })),
27
+ };
28
+ }
29
+ exports.parseGetSeriesResponse = parseGetSeriesResponse;
30
+ function parseSearchSeriesResponse(response) {
31
+ if (response.Codigo !== 0) {
32
+ switch (response.Codigo) {
33
+ case errors_1.ErrorCodes.InvalidCredentials:
34
+ throw new errors_1.InvalidCredentialsError();
35
+ case errors_1.ErrorCodes.InvalidFrequency:
36
+ throw new errors_1.InvalidFrequencyError();
37
+ default:
38
+ throw new errors_1.WebServiceError(response);
39
+ }
40
+ }
41
+ return response.SeriesInfos.map((series) => ({
42
+ seriesId: series.seriesId,
43
+ frequency: series.frequencyCode,
44
+ title: series.englishTitle,
45
+ firstObservedAt: (0, reverse_date_1.default)(series.firstObservation),
46
+ lastObservedAt: (0, reverse_date_1.default)(series.lastObservation),
47
+ updatedAt: (0, reverse_date_1.default)(series.updatedAt),
48
+ createdAt: (0, reverse_date_1.default)(series.createdAt),
49
+ }));
50
+ }
51
+ exports.parseSearchSeriesResponse = parseSearchSeriesResponse;
@@ -0,0 +1 @@
1
+ export default function reverseDate(date: string): string;
@@ -0,0 +1,6 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ function reverseDate(date) {
4
+ return date.split('-').reverse().join('-');
5
+ }
6
+ exports.default = reverseDate;
@@ -0,0 +1,3 @@
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 ADDED
@@ -0,0 +1,11 @@
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; } });
@@ -0,0 +1,109 @@
1
+ interface SeriesValue {
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
+ 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: SeriesValue[];
32
+ }
33
+ type NullSeries = {
34
+ [key in keyof SeriesHistory]: null;
35
+ };
36
+ 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
+ }>;
109
+ export {};
package/dist/types.js ADDED
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
package/package.json CHANGED
@@ -1,13 +1,15 @@
1
1
  {
2
2
  "name": "bcchapi",
3
- "version": "1.0.0",
3
+ "version": "1.0.1",
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",
7
7
  "scripts": {
8
8
  "build": "rimraf dist && tsc",
9
9
  "test": "vitest",
10
- "coverage": "vitest --coverage"
10
+ "coverage": "vitest --coverage",
11
+ "lint": "eslint --ignore-path .eslintignore --ext .ts",
12
+ "format": "prettier --ignore-path .gitignore --write \"**/*.+(js|ts|json)\""
11
13
  },
12
14
  "repository": {
13
15
  "type": "git",
@@ -28,7 +30,13 @@
28
30
  "devDependencies": {
29
31
  "@tsconfig/node20": "^20.1.2",
30
32
  "@types/node": "^20.11.5",
33
+ "@typescript-eslint/eslint-plugin": "^6.19.0",
34
+ "@typescript-eslint/parser": "^6.19.0",
31
35
  "@vitest/coverage-v8": "^1.2.1",
36
+ "eslint": "^8.56.0",
37
+ "eslint-config-prettier": "^9.1.0",
38
+ "eslint-plugin-import": "^2.29.1",
39
+ "prettier": "^3.2.4",
32
40
  "rimraf": "^5.0.5",
33
41
  "ts-node": "^10.9.2",
34
42
  "typescript": "^5.3.3",
package/src/client.ts CHANGED
@@ -1,16 +1,10 @@
1
1
  import * as querystring from 'node:querystring';
2
2
  import * as assert from 'node:assert/strict';
3
- import {
4
- GetSeriesResponse,
5
- SearchSeriesResponse,
6
- Frequency,
7
- parseGetSeriesResponse,
8
- parseSearchSeriesResponse,
9
- ApiResponse,
10
- } from './response';
11
- import { isValidDate } from './helpers';
12
-
13
- export type ClientConfig = {
3
+ import { GetSeriesResponse, SearchSeriesResponse, ApiResponse } from './types';
4
+ import { parseGetSeriesResponse, parseSearchSeriesResponse } from './helpers/parsers';
5
+ import isValidDate from './helpers/is-valid-date';
6
+
7
+ export interface ClientConfig {
14
8
  /**
15
9
  * Client username (registered email).
16
10
  */
@@ -19,33 +13,20 @@ export type ClientConfig = {
19
13
  * Client password.
20
14
  */
21
15
  pass: string;
22
- };
23
-
24
- export type GetSeriesInput = {
25
- /**
26
- * Series identifier.
27
- */
28
- series: string;
29
- /**
30
- * First date of the range to fetch.
31
- */
32
- since?: string | Date;
33
- /**
34
- * Last date of the range to fetch.
35
- */
36
- until?: string | Date;
37
- };
16
+ }
38
17
 
39
- export type SearchSeriesInput = {
40
- /**
41
- * Frequency for which you want to consult the catalog of available series.
42
- */
43
- frequency: Frequency;
44
- };
18
+ export enum Frequency {
19
+ Daily = 'DAILY',
20
+ Monthly = 'MONTHLY',
21
+ Quarterly = 'QUARTERLY',
22
+ Annual = 'ANNUAL',
23
+ }
45
24
 
46
25
  export class Client {
47
26
  static apiURL = 'https://si3.bcentral.cl/SieteRestWS/SieteRestWS.ashx';
27
+
48
28
  private username: string;
29
+
49
30
  private password: string;
50
31
 
51
32
  constructor(config: ClientConfig) {
@@ -53,59 +34,77 @@ export class Client {
53
34
  this.password = config.pass;
54
35
  }
55
36
 
56
- async request(params: Record<string, string>): Promise<ApiResponse> {
57
- const query = querystring.stringify({
37
+ async request(query: Record<string, string>): Promise<ApiResponse> {
38
+ const queryString = querystring.stringify({
58
39
  user: this.username,
59
40
  pass: this.password,
60
- ...params,
41
+ ...query,
61
42
  });
62
43
 
63
- return (await fetch(`${Client.apiURL}?${query}`)).json() as Promise<ApiResponse>;
44
+ return (await fetch(`${Client.apiURL}?${queryString}`)).json() as Promise<ApiResponse>;
64
45
  }
65
46
 
66
47
  /**
67
48
  * Fetches the list of observed values for a given series.
68
49
  */
69
- async getSeries(input: GetSeriesInput): Promise<GetSeriesResponse> {
70
- const { series, since, until } = input;
50
+ async getSeries(params: {
51
+ /**
52
+ * Series identifier.
53
+ */
54
+ series: string;
55
+ /**
56
+ * First date of the range to fetch.
57
+ */
58
+ since?: string | Date;
59
+ /**
60
+ * Last date of the range to fetch.
61
+ */
62
+ until?: string | Date;
63
+ }): Promise<GetSeriesResponse> {
64
+ const { series, since, until } = params;
71
65
 
72
66
  assert.ok(series && typeof series === 'string', 'series must be a non-empty string');
73
67
 
74
- const params: Record<string, string> = {
68
+ const query: Record<string, string> = {
75
69
  timeseries: series,
76
70
  function: 'GetSeries',
77
71
  };
78
72
 
79
73
  if (since) {
80
74
  assert.ok(isValidDate(since), '"since" is not a valid date string or Date object');
81
- params.firstdate = typeof since === 'string' ? since : since.toISOString().slice(0, 10);
75
+ query.firstdate = typeof since === 'string' ? since : since.toISOString().slice(0, 10);
82
76
  }
83
77
 
84
78
  if (until) {
85
79
  assert.ok(isValidDate(until), '"until" is not a valid date string or Date object');
86
- params.lastdate = typeof until === 'string' ? until : until.toISOString().slice(0, 10);
80
+ query.lastdate = typeof until === 'string' ? until : until.toISOString().slice(0, 10);
87
81
  }
88
82
 
89
- if (params.firstdate && params.lastdate) {
90
- assert.ok(params.firstdate <= params.lastdate, 'invalid date range');
83
+ if (query.firstdate && query.lastdate) {
84
+ assert.ok(query.firstdate <= query.lastdate, 'invalid date range');
91
85
  }
92
86
 
93
- return this.request(params).then(parseGetSeriesResponse);
87
+ return this.request(query).then(parseGetSeriesResponse);
94
88
  }
95
89
 
96
90
  /**
97
91
  * Fetches the list of available series by frequency and their metadata.
98
92
  */
99
- async searchSeries(input: SearchSeriesInput): Promise<SearchSeriesResponse> {
100
- const { frequency } = input;
101
-
93
+ async searchSeries(params: {
94
+ /**
95
+ * Frequency for which you want to consult the catalog of available series.
96
+ */
97
+ frequency: Frequency;
98
+ }): Promise<SearchSeriesResponse> {
99
+ const { frequency } = params;
100
+
102
101
  assert.ok(frequency && typeof frequency === 'string', 'frequency must be a non-empty string');
103
-
104
- const params: Record<string, string> = {
102
+
103
+ const query: Record<string, string> = {
105
104
  frequency,
106
105
  function: 'SearchSeries',
107
106
  };
108
107
 
109
- return this.request(params).then(parseSearchSeriesResponse);
108
+ return this.request(query).then(parseSearchSeriesResponse);
110
109
  }
111
- }
110
+ }