bcchapi 1.0.8 → 2.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.
Files changed (71) hide show
  1. package/CHANGELOG.md +10 -42
  2. package/LICENSE +18 -4
  3. package/README.md +83 -91
  4. package/dist/client/client.d.ts +60 -0
  5. package/dist/client/client.d.ts.map +1 -0
  6. package/dist/client/client.js +126 -0
  7. package/dist/client/client.js.map +1 -0
  8. package/dist/client/index.d.ts +4 -0
  9. package/dist/client/index.d.ts.map +1 -0
  10. package/dist/client/index.js +3 -0
  11. package/dist/client/index.js.map +1 -0
  12. package/dist/client/types.d.ts +136 -0
  13. package/dist/client/types.d.ts.map +1 -0
  14. package/dist/client/types.js +53 -0
  15. package/dist/client/types.js.map +1 -0
  16. package/dist/index.d.ts +5 -0
  17. package/dist/index.d.ts.map +1 -0
  18. package/dist/index.js +4 -0
  19. package/dist/index.js.map +1 -0
  20. package/dist/series/index.d.ts +2 -0
  21. package/dist/series/index.d.ts.map +1 -0
  22. package/dist/series/index.js +2 -0
  23. package/dist/series/index.js.map +1 -0
  24. package/dist/series/series.d.ts +213 -0
  25. package/dist/series/series.d.ts.map +1 -0
  26. package/dist/series/series.js +213 -0
  27. package/dist/series/series.js.map +1 -0
  28. package/dist/utils/dates.d.ts +30 -0
  29. package/dist/utils/dates.d.ts.map +1 -0
  30. package/dist/utils/dates.js +67 -0
  31. package/dist/utils/dates.js.map +1 -0
  32. package/dist/utils/index.d.ts +4 -0
  33. package/dist/utils/index.d.ts.map +1 -0
  34. package/dist/utils/index.js +4 -0
  35. package/dist/utils/index.js.map +1 -0
  36. package/dist/utils/stats.d.ts +112 -0
  37. package/dist/utils/stats.d.ts.map +1 -0
  38. package/dist/utils/stats.js +185 -0
  39. package/dist/utils/stats.js.map +1 -0
  40. package/dist/utils/transform.d.ts +79 -0
  41. package/dist/utils/transform.d.ts.map +1 -0
  42. package/dist/utils/transform.js +101 -0
  43. package/dist/utils/transform.js.map +1 -0
  44. package/package.json +62 -40
  45. package/.eslintignore +0 -3
  46. package/.eslintrc.json +0 -21
  47. package/.github/workflows/npm-publish.yml +0 -38
  48. package/.prettierrc.json +0 -17
  49. package/.vscode/extensions.json +0 -3
  50. package/.vscode/settings.json +0 -4
  51. package/src/client.ts +0 -109
  52. package/src/errors.ts +0 -36
  53. package/src/handlers.ts +0 -69
  54. package/src/index.ts +0 -8
  55. package/src/types.ts +0 -115
  56. package/src/utils.ts +0 -37
  57. package/test/client.test.ts +0 -226
  58. package/test/fixtures/index.ts +0 -15
  59. package/test/fixtures/responses/credentials.invalid.json +0 -11
  60. package/test/fixtures/responses/getseries.invalid.json +0 -11
  61. package/test/fixtures/responses/getseries.success.json +0 -87
  62. package/test/fixtures/responses/searchseries.invalid.json +0 -11
  63. package/test/fixtures/responses/searchseries.success.json +0 -22
  64. package/test/handlers/handle-get-series.test.ts +0 -45
  65. package/test/handlers/handle-search-series.test.ts +0 -48
  66. package/test/mocks/fetch.mock.ts +0 -76
  67. package/test/utils/is-valid-date.test.ts +0 -17
  68. package/test/utils/reverse-date.test.ts +0 -11
  69. package/tsconfig.eslint.json +0 -5
  70. package/tsconfig.json +0 -9
  71. package/vitest.config.mts +0 -9
package/CHANGELOG.md CHANGED
@@ -2,53 +2,21 @@
2
2
 
3
3
  All notable changes to this project will be documented in this file.
4
4
 
5
- The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6
- and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
5
+ The format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/) and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
6
 
8
- ## [1.0.8] - 2025-02-19
7
+ ---
9
8
 
10
- ### Fixed
9
+ ## [0.1.0] - 2026-03-10
11
10
 
12
- - Fixed `extends` missing full path in `tsconfig.json`
13
-
14
- ## [1.0.7] - 2025-02-19
15
-
16
- ### Changed
17
-
18
- - Moved API response handlers from `utils.ts` to new `handlers.ts` file
19
- - Improved date handling in `utils.ts`
20
- - Fixed date validation in client test
21
- - Updated dependencies:
22
- - `@vitest/coverage-v8` from `^1.6.0` to `^3.0.6`
23
- - `rimraf` from `^5.0.7` to `^6.0.1`
24
- - `vitest` from `^1.6.0` to `^3.0.6`
25
-
26
- ## [1.0.6] - 2024-06-13
27
-
28
- ### Changed
29
-
30
- - Updated the following dependencies:
31
- - `@types/node` from `20.12.7` to `2.14.2`
32
- - `@vitest/coverage-v8` from `1.5.1` to `1.6.0`
33
- - `rimraf` from `5.0.5` to `5.0.7`
34
- - `prettier` from `3.2.5` to `3.3.2`
35
- - `vitest` from `1.5.1` to `1.6.0`
36
-
37
- ## [1.0.5] - 2024-04-24
38
11
 
39
12
  ### Added
40
13
 
41
- - This CHANGELOG file to document changes to the project.
14
+ - Add date, transform, and stats utility functions
15
+ - Add SERIES constants with curated well-known series IDs
16
+ - Add Client, ApiError, and HttpError with full test coverage
17
+
42
18
 
43
- ### Changed
19
+ ---
44
20
 
45
- - Updated the following dependencies:
46
- - `@tsconfig/node20` from `20.1.2` to `20.1.4`
47
- - `@types/node` from `20.11.5` to `2.12.7`
48
- - `@typescript-eslint/eslint-plugin` from `6.19.0` to `6.21.0`
49
- - `@typescript-eslint/parser` from `6.19.0` to `6.21.0`
50
- - `@vitest/coverage-v8` from `1.2.1` to `1.5.1`
51
- - `eslint` from `8.56.0` to `8.57.0`
52
- - `prettier` from `3.2.4` to `3.2.5`
53
- - `typescript` from `5.3.3` to `5.4.5`
54
- - `vitest` from `1.2.1` to `1.5.1`
21
+ [0.1.0]: https://github.com/airarrazaval/bcch/compare/v0.0.1...v0.1.0
22
+ [Unreleased]: https://github.com/airarrazaval/bcch/compare/v0.1.0...HEAD
package/LICENSE CHANGED
@@ -1,7 +1,21 @@
1
- Copyright 2024 Alfredo Irarrazaval
1
+ MIT License
2
2
 
3
- Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
3
+ Copyright (c) 2026 airarrazaval
4
4
 
5
- The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
6
11
 
7
- THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,124 +1,116 @@
1
- # BCCHAPI
1
+ # Node.js Library Template
2
2
 
3
- [Statistical Data Base API](https://si3.bcentral.cl/Siete/es/Siete/API) client of the Central Bank of Chile.
3
+ A minimal, opinionated template for publishing Node.js libraries written in TypeScript.
4
4
 
5
- The Central Bank of Chile provides a web service that allows searching and extracting economic information contained in its Statistical Data Base (BDE). The records are displayed in a format useful for developers and analysts who wish to automate their query processes.
5
+ ## Features
6
6
 
7
- The API currently supports only to functions: `GetSeries` (default) used for retrieveng historical data on a specific series, and `SearchSeries` used for searching series by frequency code (ie: daily, monthly, quearterly or yearly).
7
+ - **TypeScript** with strict settings and `NodeNext` module resolution
8
+ - **ESM-only** output (`"type": "module"`)
9
+ - **Node.js 24+** target
10
+ - **Testing** via Node.js built-in test runner (`node:test`) with [tsx](https://github.com/privatenumber/tsx) for TypeScript support
11
+ - **Linting** with [oxlint](https://oxc.rs/docs/guide/usage/linter)
12
+ - **Formatting** with [oxfmt](https://github.com/nicolo-ribaudo/oxfmt)
13
+ - **Type declarations** and source maps included in the build output
14
+ - **API documentation** generation with [TypeDoc](https://typedoc.org) and TSDoc comments
15
+ - **Changelog** generation from [Conventional Commits](https://www.conventionalcommits.org) via [git-cliff](https://git-cliff.org)
16
+ - **CI/CD** via GitHub Actions: automated checks on PRs and tag-triggered npm publishing with SLSA provenance
8
17
 
9
- For further information on how to use the API directly, please refer to the [official documentation](https://si3.bcentral.cl/estadisticas/Principal1/Web_Services/doc_en.htm). Usage of the API is subject to the restrictions defined in the [Terms and Conditions](https://si3.bcentral.cl/estadisticas/Principal1/Web_Services/index_BDE_TC.htm) of the Statistical Data Base API of the Central Bank of Chile. As of January of 2024, **the API allows up to 5 requests per second per user**.
18
+ ## Getting Started
10
19
 
11
- ## Installation
20
+ 1. Click **Use this template** on GitHub to create a new repository.
21
+ 2. Clone your new repo and install dependencies:
12
22
 
13
- ```
14
- npm i -S bcchapi
15
- ```
23
+ ```sh
24
+ npm install
25
+ ```
16
26
 
17
- ## Usage
27
+ 3. Replace the contents of [src/index.ts](src/index.ts) with your library code.
28
+ 4. Update `name`, `version`, and `description` in [package.json](package.json).
29
+ 5. Update the `exports` field in [package.json](package.json) if you need multiple entry points.
30
+ 6. Add an `NPM_TOKEN` secret to your repository under **Settings → Secrets and variables → Actions**.
18
31
 
19
- ```javascript
20
- // ESM
21
- import { Client } from 'bcchapi';
32
+ ## Project Structure
22
33
 
23
- // CommonJS
24
- const { Client } = require('bcchapi');
34
+ ```text
35
+ src/ # Library source code
36
+ tests/ # Test files (*.test.ts)
37
+ dist/ # Compiled output (generated, not committed)
38
+ tsconfig.json # TypeScript config for type-checking
39
+ tsconfig.build.json # TypeScript config for compilation
25
40
  ```
26
41
 
27
- ### Authentication
42
+ ## Development
28
43
 
29
- To authenticate the API calls you first need to register at the [Statistical Data Base Website](https://si3.bcentral.cl/Siete/es/Siete/API) of the Central Bank of Chile, login and activate your credentials.
44
+ Start the test watcher while you write code:
30
45
 
31
- ```js
32
- const client = new Client({
33
- user: 'jdoe@example.com',
34
- pass: 'secret',
35
- });
46
+ ```sh
47
+ npm run dev
36
48
  ```
37
49
 
38
- ### GetSeries
50
+ Before opening a pull request, verify everything passes:
39
51
 
40
- Allows you to retrieve historic data series.
52
+ ```sh
53
+ npm run typecheck && npm run lint && npm run format:check && npm test
54
+ ```
41
55
 
42
- - Series Catalogue: [EN](https://si3.bcentral.cl/estadisticas/Principal1/Web_Services/Webservices/series_EN.xlsx) | [ES](https://si3.bcentral.cl/estadisticas/Principal1/Web_Services/Webservices/series.xlsx)
56
+ ## Scripts
43
57
 
44
- #### Parameters
58
+ | Command | Description |
59
+ | ----------------------- | -------------------------------------------------------------- |
60
+ | `npm run dev` | Run tests in watch mode |
61
+ | `npm run build` | Compile TypeScript to `dist/` |
62
+ | `npm test` | Run tests |
63
+ | `npm run test:coverage` | Run tests with coverage report |
64
+ | `npm run typecheck` | Type-check without emitting files |
65
+ | `npm run lint` | Lint source and tests |
66
+ | `npm run lint:fix` | Lint and auto-fix issues |
67
+ | `npm run format` | Format all files |
68
+ | `npm run format:check` | Check formatting without modifying files |
69
+ | `npm run clean` | Remove `dist/` and `docs/` |
70
+ | `npm run docs` | Generate API documentation in `docs/` |
71
+ | `npm run changelog` | Regenerate `CHANGELOG.md` from commits (used before releasing) |
45
72
 
46
- | name | type | required | description | example |
47
- | ------ | ------------------ | -------- | ------------------------------- | ---------------------- |
48
- | series | `string` | Yes | The series identifier | `'F072.EUR.USD.N.O.D'` |
49
- | since | `string` or `Date` | No | The starting date of the series | `'2020-12-01'` |
50
- | until | `string` or `Date` | No | The ending date of the series | `'2020-12-02'` |
73
+ ## GitHub Actions
51
74
 
52
- > **NOTE**: The API does not implements pagination, so if you need to retrieve a large amount of data, you should use the `since` and `until` parameters to split the request into smaller chunks.
75
+ ### CI (`ci.yml`)
53
76
 
54
- #### Example
77
+ Runs on every pull request and push to `main`:
55
78
 
56
- ```js
57
- const series = await client.getSeries({
58
- series: 'F072.EUR.USD.N.O.D',
59
- since: '2020-12-01',
60
- until: '2020-12-02',
61
- });
79
+ 1. Verify package signatures (`npm audit signatures`)
80
+ 2. Audit production dependencies for vulnerabilities (`npm audit --omit=dev`)
81
+ 3. Typecheck
82
+ 4. Lint
83
+ 5. Format check
84
+ 6. Test
85
+ 7. Build
62
86
 
63
- console.log(series);
64
- ```
87
+ ### Publish (`publish.yml`)
65
88
 
66
- _Output_
67
-
68
- ```js
69
- {
70
- seriesId: 'F072.EUR.USD.N.O.D',
71
- description: 'Euro per US dollar',
72
- data: [
73
- { date: '2020-12-01', value: 0.8373 },
74
- { date: '2020-12-02', value: 0.8304 }
75
- ]
76
- }
77
- ```
89
+ Runs automatically when a version tag (e.g. `v1.2.3`) is pushed. Runs `prepublishOnly`
90
+ (typecheck → lint → clean → build) then publishes to npm with
91
+ [SLSA provenance attestation](https://docs.npmjs.com/generating-provenance-statements).
78
92
 
79
- ### SearchSeries
93
+ **Do not run `npm publish` manually.** Use the release flow below instead.
80
94
 
81
- Allows you to search for series by their frequency code (ie: daily, monthly, quarterly, yearly).
95
+ ## Releasing
82
96
 
83
- #### Parameters
97
+ ```sh
98
+ # 1. Regenerate CHANGELOG.md from commits (auto-determines next version)
99
+ npm run changelog
84
100
 
85
- | name | type | required | description | example |
86
- | --------- | -------- | -------- | ------------------------------------------------------------------------ | --------- |
87
- | frequency | `string` | Yes | The frequency code to search (`DAILY`, `MONTHLY`, `QUARTERLY`, `ANNUAL`) | `'DAILY'` |
101
+ # 2. Review CHANGELOG.md, update comparison links at the bottom, then commit
102
+ git add CHANGELOG.md && git commit -m "chore: release vX.Y.Z"
88
103
 
89
- #### Example
104
+ # 3. Bump version in package.json to match what git-cliff determined
105
+ npm version patch # or minor / major
90
106
 
91
- ```js
92
- import { Frequency } from 'bcchapi';
107
+ # 4. Push — the publish workflow triggers automatically on the version tag
108
+ git push --follow-tags
109
+ ```
93
110
 
94
- const result = await client.searchSeries({ frequency: Frequency.DAILY });
111
+ Only `dist/`, `README.md`, `CHANGELOG.md`, and `LICENSE` are included in the published
112
+ package (see `files` in [package.json](package.json)).
95
113
 
96
- console.log(result);
97
- ```
114
+ ## Requirements
98
115
 
99
- _Output_
100
-
101
- ```js
102
- [
103
- ...
104
- {
105
- seriesId: 'F021.AHP.STO.N.CLP.0.D',
106
- frequency: 'DAILY',
107
- title: 'Time savings deposits, including those for housing',
108
- firstObservedAt: '2011-01-03',
109
- lastObservedAt: '2023-12-29',
110
- updatedAt: '2024-01-08',
111
- createdAt: '2024-01-08'
112
- },
113
- {
114
- seriesId: 'F021.BMO.STO.N.CLP.0.D',
115
- frequency: 'DAILY',
116
- title: 'Monetary base ',
117
- firstObservedAt: '2011-01-03',
118
- lastObservedAt: '2023-12-29',
119
- updatedAt: '2024-01-08',
120
- createdAt: '2024-01-08'
121
- },
122
- ...
123
- ]
124
- ```
116
+ - Node.js >= 24.0.0
@@ -0,0 +1,60 @@
1
+ import type { ClientOptions, Frequency, GetSeriesOptions, SeriesData, SeriesInfo } from './types.js';
2
+ /**
3
+ * HTTP client for the Banco Central de Chile REST API.
4
+ *
5
+ * @example
6
+ * ```ts
7
+ * import { Client } from 'bcch/client';
8
+ *
9
+ * const client = new Client({ user: 'me@example.com', pass: 'secret' });
10
+ * const data = await client.getSeries('F022.TPM.TIN.D001.NO.Z.D', {
11
+ * firstdate: '2024-01-01',
12
+ * });
13
+ * console.log(data.observations);
14
+ * ```
15
+ */
16
+ export declare class Client {
17
+ private readonly user;
18
+ private readonly pass;
19
+ private readonly fetch;
20
+ constructor(options: ClientOptions);
21
+ /**
22
+ * Fetches observations for a single time series.
23
+ *
24
+ * @param seriesId - BCCH series identifier (e.g. `'F022.TPM.TIN.D001.NO.Z.D'`).
25
+ * Values from the `SERIES` constants in `bcch/series` are accepted directly.
26
+ * @param options - Optional date range filter.
27
+ * @returns Parsed series data including all observations in the requested range.
28
+ * @throws {ApiError} When the API returns a non-zero `Codigo`.
29
+ * @throws {HttpError} When the API returns a non-ok HTTP status.
30
+ * @throws {Error} When a network failure occurs; original error is set as `cause`.
31
+ *
32
+ * @example
33
+ * ```ts
34
+ * const data = await client.getSeries('F073.UFF.PRE.Z.D', {
35
+ * firstdate: '2024-01-01',
36
+ * lastdate: '2024-12-31',
37
+ * });
38
+ * ```
39
+ */
40
+ getSeries(seriesId: string, options?: GetSeriesOptions): Promise<SeriesData>;
41
+ /**
42
+ * Searches for available series filtered by observation frequency.
43
+ *
44
+ * @param frequency - One of `'DAILY'`, `'MONTHLY'`, `'QUARTERLY'`, or `'ANNUAL'`.
45
+ * @returns Array of series metadata matching the given frequency.
46
+ * @throws {ApiError} When the API returns a non-zero `Codigo`.
47
+ * @throws {HttpError} When the API returns a non-ok HTTP status.
48
+ * @throws {Error} When a network failure occurs; original error is set as `cause`.
49
+ *
50
+ * @example
51
+ * ```ts
52
+ * const monthlySeries = await client.searchSeries('MONTHLY');
53
+ * console.log(monthlySeries.map(s => s.englishTitle));
54
+ * ```
55
+ */
56
+ searchSeries(frequency: Frequency): Promise<SeriesInfo[]>;
57
+ private baseParams;
58
+ private request;
59
+ }
60
+ //# sourceMappingURL=client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/client/client.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,aAAa,EACb,SAAS,EACT,gBAAgB,EAEhB,UAAU,EACV,UAAU,EACX,MAAM,YAAY,CAAC;AAyCpB;;;;;;;;;;;;;GAaG;AACH,qBAAa,MAAM;IACjB,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAS;IAC9B,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAS;IAC9B,OAAO,CAAC,QAAQ,CAAC,KAAK,CAA0B;gBAEpC,OAAO,EAAE,aAAa;IAMlC;;;;;;;;;;;;;;;;;;OAkBG;IACG,SAAS,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,gBAAgB,GAAG,OAAO,CAAC,UAAU,CAAC;IA+BlF;;;;;;;;;;;;;;OAcG;IACG,YAAY,CAAC,SAAS,EAAE,SAAS,GAAG,OAAO,CAAC,UAAU,EAAE,CAAC;IAuB/D,OAAO,CAAC,UAAU;YAOJ,OAAO;CAgBtB"}
@@ -0,0 +1,126 @@
1
+ import { ApiError, HttpError } from './types.js';
2
+ const API_URL = 'https://si3.bcentral.cl/SieteRestWS/SieteRestWS.ashx';
3
+ /**
4
+ * HTTP client for the Banco Central de Chile REST API.
5
+ *
6
+ * @example
7
+ * ```ts
8
+ * import { Client } from 'bcch/client';
9
+ *
10
+ * const client = new Client({ user: 'me@example.com', pass: 'secret' });
11
+ * const data = await client.getSeries('F022.TPM.TIN.D001.NO.Z.D', {
12
+ * firstdate: '2024-01-01',
13
+ * });
14
+ * console.log(data.observations);
15
+ * ```
16
+ */
17
+ export class Client {
18
+ user;
19
+ pass;
20
+ fetch;
21
+ constructor(options) {
22
+ this.user = options.user;
23
+ this.pass = options.pass;
24
+ this.fetch = options.fetch ?? globalThis.fetch;
25
+ }
26
+ /**
27
+ * Fetches observations for a single time series.
28
+ *
29
+ * @param seriesId - BCCH series identifier (e.g. `'F022.TPM.TIN.D001.NO.Z.D'`).
30
+ * Values from the `SERIES` constants in `bcch/series` are accepted directly.
31
+ * @param options - Optional date range filter.
32
+ * @returns Parsed series data including all observations in the requested range.
33
+ * @throws {ApiError} When the API returns a non-zero `Codigo`.
34
+ * @throws {HttpError} When the API returns a non-ok HTTP status.
35
+ * @throws {Error} When a network failure occurs; original error is set as `cause`.
36
+ *
37
+ * @example
38
+ * ```ts
39
+ * const data = await client.getSeries('F073.UFF.PRE.Z.D', {
40
+ * firstdate: '2024-01-01',
41
+ * lastdate: '2024-12-31',
42
+ * });
43
+ * ```
44
+ */
45
+ async getSeries(seriesId, options) {
46
+ const params = this.baseParams();
47
+ params.set('function', 'GetSeries');
48
+ params.set('timeseries', seriesId);
49
+ if (options?.firstdate !== undefined) {
50
+ params.set('firstdate', options.firstdate);
51
+ }
52
+ if (options?.lastdate !== undefined) {
53
+ params.set('lastdate', options.lastdate);
54
+ }
55
+ const raw = await this.request(params);
56
+ if (raw.Codigo !== 0 || raw.Series === null) {
57
+ throw new ApiError(`BCCH API error: ${raw.Descripcion}`, raw.Codigo, raw.Descripcion);
58
+ }
59
+ const observations = raw.Series.Obs.map((obs) => ({
60
+ indexDateString: obs.indexDateString,
61
+ value: obs.value,
62
+ statusCode: obs.statusCode,
63
+ }));
64
+ return {
65
+ seriesId: raw.Series.seriesId,
66
+ descripEsp: raw.Series.descripEsp,
67
+ descripIng: raw.Series.descripIng,
68
+ observations,
69
+ };
70
+ }
71
+ /**
72
+ * Searches for available series filtered by observation frequency.
73
+ *
74
+ * @param frequency - One of `'DAILY'`, `'MONTHLY'`, `'QUARTERLY'`, or `'ANNUAL'`.
75
+ * @returns Array of series metadata matching the given frequency.
76
+ * @throws {ApiError} When the API returns a non-zero `Codigo`.
77
+ * @throws {HttpError} When the API returns a non-ok HTTP status.
78
+ * @throws {Error} When a network failure occurs; original error is set as `cause`.
79
+ *
80
+ * @example
81
+ * ```ts
82
+ * const monthlySeries = await client.searchSeries('MONTHLY');
83
+ * console.log(monthlySeries.map(s => s.englishTitle));
84
+ * ```
85
+ */
86
+ async searchSeries(frequency) {
87
+ const params = this.baseParams();
88
+ params.set('function', 'SearchSeries');
89
+ params.set('frequency', frequency);
90
+ const raw = await this.request(params);
91
+ if (raw.Codigo !== 0) {
92
+ throw new ApiError(`BCCH API error: ${raw.Descripcion}`, raw.Codigo, raw.Descripcion);
93
+ }
94
+ return (raw.SeriesInfos ?? []).map((info) => ({
95
+ seriesId: info.seriesId,
96
+ frequencyCode: info.frequencyCode,
97
+ spanishTitle: info.spanishTitle,
98
+ englishTitle: info.englishTitle,
99
+ firstObservation: info.firstObservation,
100
+ lastObservation: info.lastObservation,
101
+ updatedAt: info.updatedAt,
102
+ createdAt: info.createdAt,
103
+ }));
104
+ }
105
+ baseParams() {
106
+ const params = new URLSearchParams();
107
+ params.set('user', this.user);
108
+ params.set('pass', this.pass);
109
+ return params;
110
+ }
111
+ async request(params) {
112
+ const url = `${API_URL}?${params.toString()}`;
113
+ let response;
114
+ try {
115
+ response = await this.fetch(url);
116
+ }
117
+ catch (err) {
118
+ throw new Error('BCCH request failed', { cause: err });
119
+ }
120
+ if (!response.ok) {
121
+ throw new HttpError(`HTTP error ${response.status}`, response.status);
122
+ }
123
+ return response.json();
124
+ }
125
+ }
126
+ //# sourceMappingURL=client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/client/client.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAUjD,MAAM,OAAO,GAAG,sDAAsD,CAAC;AAuCvE;;;;;;;;;;;;;GAaG;AACH,MAAM,OAAO,MAAM;IACA,IAAI,CAAS;IACb,IAAI,CAAS;IACb,KAAK,CAA0B;IAEhD,YAAY,OAAsB;QAChC,IAAI,CAAC,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;QACzB,IAAI,CAAC,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;QACzB,IAAI,CAAC,KAAK,GAAG,OAAO,CAAC,KAAK,IAAI,UAAU,CAAC,KAAK,CAAC;IACjD,CAAC;IAED;;;;;;;;;;;;;;;;;;OAkBG;IACH,KAAK,CAAC,SAAS,CAAC,QAAgB,EAAE,OAA0B;QAC1D,MAAM,MAAM,GAAG,IAAI,CAAC,UAAU,EAAE,CAAC;QACjC,MAAM,CAAC,GAAG,CAAC,UAAU,EAAE,WAAW,CAAC,CAAC;QACpC,MAAM,CAAC,GAAG,CAAC,YAAY,EAAE,QAAQ,CAAC,CAAC;QACnC,IAAI,OAAO,EAAE,SAAS,KAAK,SAAS,EAAE,CAAC;YACrC,MAAM,CAAC,GAAG,CAAC,WAAW,EAAE,OAAO,CAAC,SAAS,CAAC,CAAC;QAC7C,CAAC;QACD,IAAI,OAAO,EAAE,QAAQ,KAAK,SAAS,EAAE,CAAC;YACpC,MAAM,CAAC,GAAG,CAAC,UAAU,EAAE,OAAO,CAAC,QAAQ,CAAC,CAAC;QAC3C,CAAC;QAED,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,OAAO,CAAuB,MAAM,CAAC,CAAC;QAE7D,IAAI,GAAG,CAAC,MAAM,KAAK,CAAC,IAAI,GAAG,CAAC,MAAM,KAAK,IAAI,EAAE,CAAC;YAC5C,MAAM,IAAI,QAAQ,CAAC,mBAAmB,GAAG,CAAC,WAAW,EAAE,EAAE,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,WAAW,CAAC,CAAC;QACxF,CAAC;QAED,MAAM,YAAY,GAAkB,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;YAC/D,eAAe,EAAE,GAAG,CAAC,eAAe;YACpC,KAAK,EAAE,GAAG,CAAC,KAAK;YAChB,UAAU,EAAE,GAAG,CAAC,UAAU;SAC3B,CAAC,CAAC,CAAC;QAEJ,OAAO;YACL,QAAQ,EAAE,GAAG,CAAC,MAAM,CAAC,QAAQ;YAC7B,UAAU,EAAE,GAAG,CAAC,MAAM,CAAC,UAAU;YACjC,UAAU,EAAE,GAAG,CAAC,MAAM,CAAC,UAAU;YACjC,YAAY;SACb,CAAC;IACJ,CAAC;IAED;;;;;;;;;;;;;;OAcG;IACH,KAAK,CAAC,YAAY,CAAC,SAAoB;QACrC,MAAM,MAAM,GAAG,IAAI,CAAC,UAAU,EAAE,CAAC;QACjC,MAAM,CAAC,GAAG,CAAC,UAAU,EAAE,cAAc,CAAC,CAAC;QACvC,MAAM,CAAC,GAAG,CAAC,WAAW,EAAE,SAAS,CAAC,CAAC;QAEnC,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,OAAO,CAA0B,MAAM,CAAC,CAAC;QAEhE,IAAI,GAAG,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACrB,MAAM,IAAI,QAAQ,CAAC,mBAAmB,GAAG,CAAC,WAAW,EAAE,EAAE,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,WAAW,CAAC,CAAC;QACxF,CAAC;QAED,OAAO,CAAC,GAAG,CAAC,WAAW,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;YAC5C,QAAQ,EAAE,IAAI,CAAC,QAAQ;YACvB,aAAa,EAAE,IAAI,CAAC,aAAa;YACjC,YAAY,EAAE,IAAI,CAAC,YAAY;YAC/B,YAAY,EAAE,IAAI,CAAC,YAAY;YAC/B,gBAAgB,EAAE,IAAI,CAAC,gBAAgB;YACvC,eAAe,EAAE,IAAI,CAAC,eAAe;YACrC,SAAS,EAAE,IAAI,CAAC,SAAS;YACzB,SAAS,EAAE,IAAI,CAAC,SAAS;SAC1B,CAAC,CAAC,CAAC;IACN,CAAC;IAEO,UAAU;QAChB,MAAM,MAAM,GAAG,IAAI,eAAe,EAAE,CAAC;QACrC,MAAM,CAAC,GAAG,CAAC,MAAM,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC;QAC9B,MAAM,CAAC,GAAG,CAAC,MAAM,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC;QAC9B,OAAO,MAAM,CAAC;IAChB,CAAC;IAEO,KAAK,CAAC,OAAO,CAAI,MAAuB;QAC9C,MAAM,GAAG,GAAG,GAAG,OAAO,IAAI,MAAM,CAAC,QAAQ,EAAE,EAAE,CAAC;QAC9C,IAAI,QAAkB,CAAC;QAEvB,IAAI,CAAC;YACH,QAAQ,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QACnC,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,MAAM,IAAI,KAAK,CAAC,qBAAqB,EAAE,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC,CAAC;QACzD,CAAC;QAED,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;YACjB,MAAM,IAAI,SAAS,CAAC,cAAc,QAAQ,CAAC,MAAM,EAAE,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC;QACxE,CAAC;QAED,OAAO,QAAQ,CAAC,IAAI,EAAgB,CAAC;IACvC,CAAC;CACF"}
@@ -0,0 +1,4 @@
1
+ export { Client } from './client.js';
2
+ export { ApiError, HttpError } from './types.js';
3
+ export type { ClientOptions, Frequency, GetSeriesOptions, Observation, SeriesData, SeriesInfo, } from './types.js';
4
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/client/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACrC,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AACjD,YAAY,EACV,aAAa,EACb,SAAS,EACT,gBAAgB,EAChB,WAAW,EACX,UAAU,EACV,UAAU,GACX,MAAM,YAAY,CAAC"}
@@ -0,0 +1,3 @@
1
+ export { Client } from './client.js';
2
+ export { ApiError, HttpError } from './types.js';
3
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/client/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACrC,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC"}
@@ -0,0 +1,136 @@
1
+ /**
2
+ * Credentials and configuration for {@link Client}.
3
+ */
4
+ export interface ClientOptions {
5
+ /** BCCH account email. */
6
+ user: string;
7
+ /** BCCH account password. */
8
+ pass: string;
9
+ /**
10
+ * HTTP client used for all requests.
11
+ *
12
+ * Defaults to the global `fetch`. Inject a custom implementation in tests
13
+ * to avoid real network calls.
14
+ *
15
+ * @defaultValue `globalThis.fetch`
16
+ */
17
+ fetch?: typeof globalThis.fetch;
18
+ }
19
+ /**
20
+ * A single observation returned by the BCCH API.
21
+ *
22
+ * Dates are in the wire format `"DD-MM-YYYY"` as returned by the API.
23
+ * Values are raw numeric strings; an empty string indicates a data gap.
24
+ * Use {@link https://github.com/airarrazaval/bcch | bcch/utils} to parse
25
+ * and transform observations.
26
+ */
27
+ export interface Observation {
28
+ /** Observation date in `"DD-MM-YYYY"` format. */
29
+ indexDateString: string;
30
+ /**
31
+ * Numeric value as a string.
32
+ *
33
+ * An empty string (`""`) indicates a gap in the series (no observation
34
+ * for that date). Use `parseValue` from `bcch/utils` to convert to a
35
+ * `number | null`.
36
+ */
37
+ value: string;
38
+ /** Observation status code (e.g. `"OK"`, `"NO_OBS"`). */
39
+ statusCode: string;
40
+ }
41
+ /**
42
+ * Time series data returned by {@link Client.getSeries}.
43
+ */
44
+ export interface SeriesData {
45
+ /** BCCH series identifier. */
46
+ seriesId: string;
47
+ /** Series description in Spanish. */
48
+ descripEsp: string;
49
+ /** Series description in English. */
50
+ descripIng: string;
51
+ /** Ordered array of observations, earliest first. */
52
+ observations: Observation[];
53
+ }
54
+ /**
55
+ * Date range filter for {@link Client.getSeries}.
56
+ */
57
+ export interface GetSeriesOptions {
58
+ /**
59
+ * Start date in `"YYYY-MM-DD"` format.
60
+ *
61
+ * Defaults to the earliest available observation when omitted.
62
+ */
63
+ firstdate?: string;
64
+ /**
65
+ * End date in `"YYYY-MM-DD"` format.
66
+ *
67
+ * Defaults to the most recent available observation when omitted.
68
+ */
69
+ lastdate?: string;
70
+ }
71
+ /**
72
+ * Metadata for a single series returned by {@link Client.searchSeries}.
73
+ */
74
+ export interface SeriesInfo {
75
+ /** BCCH series identifier. */
76
+ seriesId: string;
77
+ /** Frequency code (e.g. `"DAILY"`, `"MONTHLY"`). */
78
+ frequencyCode: string;
79
+ /** Series title in Spanish. */
80
+ spanishTitle: string;
81
+ /** Series title in English. */
82
+ englishTitle: string;
83
+ /** Date of the first available observation in `"DD-MM-YYYY"` format. */
84
+ firstObservation: string;
85
+ /** Date of the last available observation in `"DD-MM-YYYY"` format. */
86
+ lastObservation: string;
87
+ /** Date the series was last updated in `"DD-MM-YYYY"` format. */
88
+ updatedAt: string;
89
+ /** Date the series was created in `"DD-MM-YYYY"` format. */
90
+ createdAt: string;
91
+ }
92
+ /**
93
+ * Observation frequency accepted by {@link Client.searchSeries}.
94
+ */
95
+ export type Frequency = 'DAILY' | 'MONTHLY' | 'QUARTERLY' | 'ANNUAL';
96
+ /**
97
+ * Thrown when the BCCH API returns a non-zero `Codigo` in the response body.
98
+ *
99
+ * @example
100
+ * ```ts
101
+ * try {
102
+ * await client.getSeries('INVALID');
103
+ * } catch (err) {
104
+ * if (err instanceof ApiError) {
105
+ * console.error(`API error ${err.codigo}: ${err.descripcion}`);
106
+ * }
107
+ * }
108
+ * ```
109
+ */
110
+ export declare class ApiError extends Error {
111
+ /** Non-zero `Codigo` value from the API response. */
112
+ readonly codigo: number;
113
+ /** `Descripcion` string from the API response. */
114
+ readonly descripcion: string;
115
+ constructor(message: string, codigo: number, descripcion: string);
116
+ }
117
+ /**
118
+ * Thrown when the BCCH API returns a non-ok HTTP status code.
119
+ *
120
+ * @example
121
+ * ```ts
122
+ * try {
123
+ * await client.getSeries('F022.TPM.TIN.D001.NO.Z.D');
124
+ * } catch (err) {
125
+ * if (err instanceof HttpError) {
126
+ * console.error(`HTTP ${err.status}`);
127
+ * }
128
+ * }
129
+ * ```
130
+ */
131
+ export declare class HttpError extends Error {
132
+ /** HTTP status code. */
133
+ readonly status: number;
134
+ constructor(message: string, status: number);
135
+ }
136
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/client/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,0BAA0B;IAC1B,IAAI,EAAE,MAAM,CAAC;IAEb,6BAA6B;IAC7B,IAAI,EAAE,MAAM,CAAC;IAEb;;;;;;;OAOG;IACH,KAAK,CAAC,EAAE,OAAO,UAAU,CAAC,KAAK,CAAC;CACjC;AAED;;;;;;;GAOG;AACH,MAAM,WAAW,WAAW;IAC1B,iDAAiD;IACjD,eAAe,EAAE,MAAM,CAAC;IAExB;;;;;;OAMG;IACH,KAAK,EAAE,MAAM,CAAC;IAEd,yDAAyD;IACzD,UAAU,EAAE,MAAM,CAAC;CACpB;AAED;;GAEG;AACH,MAAM,WAAW,UAAU;IACzB,8BAA8B;IAC9B,QAAQ,EAAE,MAAM,CAAC;IAEjB,qCAAqC;IACrC,UAAU,EAAE,MAAM,CAAC;IAEnB,qCAAqC;IACrC,UAAU,EAAE,MAAM,CAAC;IAEnB,qDAAqD;IACrD,YAAY,EAAE,WAAW,EAAE,CAAC;CAC7B;AAED;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B;;;;OAIG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IAEnB;;;;OAIG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED;;GAEG;AACH,MAAM,WAAW,UAAU;IACzB,8BAA8B;IAC9B,QAAQ,EAAE,MAAM,CAAC;IAEjB,oDAAoD;IACpD,aAAa,EAAE,MAAM,CAAC;IAEtB,+BAA+B;IAC/B,YAAY,EAAE,MAAM,CAAC;IAErB,+BAA+B;IAC/B,YAAY,EAAE,MAAM,CAAC;IAErB,wEAAwE;IACxE,gBAAgB,EAAE,MAAM,CAAC;IAEzB,uEAAuE;IACvE,eAAe,EAAE,MAAM,CAAC;IAExB,iEAAiE;IACjE,SAAS,EAAE,MAAM,CAAC;IAElB,4DAA4D;IAC5D,SAAS,EAAE,MAAM,CAAC;CACnB;AAED;;GAEG;AACH,MAAM,MAAM,SAAS,GAAG,OAAO,GAAG,SAAS,GAAG,WAAW,GAAG,QAAQ,CAAC;AAMrE;;;;;;;;;;;;;GAaG;AACH,qBAAa,QAAS,SAAQ,KAAK;IACjC,qDAAqD;IACrD,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IAExB,kDAAkD;IAClD,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;gBAEjB,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM;CAMjE;AAED;;;;;;;;;;;;;GAaG;AACH,qBAAa,SAAU,SAAQ,KAAK;IAClC,wBAAwB;IACxB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;gBAEZ,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM;CAK5C"}