bsuir-iis-api 0.6.7 → 0.9.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/CHANGELOG.md CHANGED
@@ -1,12 +1,67 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.9.0
4
+
5
+ ### Minor Changes
6
+
7
+ - 323feb4: New public APIs, cache, hooks, deps versions update, new JSdoc, etc.
8
+
3
9
  All notable changes to this project are documented in this file.
4
10
 
5
11
  The format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6
12
  and the project follows [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
13
  This changelog is maintained manually and updated in release commits.
8
14
 
9
- ## [Unreleased]
15
+ ## [0.8.0] - 2026-05-10
16
+
17
+ ### Added
18
+
19
+ - Public exports for schedule utilities: `normalizeSchedule` and `filterLessons`.
20
+ - Public re-export of `ScheduleFilterOptions` type from `src/index.ts`.
21
+ - Global cancellation support via `createBsuirClient({ signal })`.
22
+ - `src/modules/index.ts` barrel for module factory imports.
23
+ - In-memory GET cache via `createBsuirClient({ cache: { ttlMs, maxEntries } })`.
24
+ - In-flight GET request deduplication via `dedupeInFlight`.
25
+ - Opt-in runtime response-shape validation via `validateResponses` and `BsuirResponseValidationError`.
26
+ - Request lifecycle hooks via `createBsuirClient({ hooks })`: `onRequest`, `onRetry`, `onResponse`, `onError`.
27
+ - API Extractor configuration (`api-extractor.json`) and npm scripts for local/update and CI checks.
28
+ - `POST` method support in `requestJson` via `options.method` and `options.body`.
29
+
30
+ ### Fixed
31
+
32
+ - `schedule.getGroup/getEmployee` return typing now follows client-level `defaultRaw` when `raw` is omitted.
33
+ - `normalizeSchedule` no longer duplicates day-item flattening work and avoids repeated `auditories` normalization per lesson.
34
+ - Strict date parsing in `parseDdMmYyyy` now rejects non-existent calendar dates (for example `31.02.2026`).
35
+ - `BsuirNetworkError` now relies on standard `Error.cause` instead of duplicate `causeError` field.
36
+ - Client option validation now rejects invalid timeout/retry configuration values early.
37
+ - `week.ts`: passing an empty string now throws a clear `BsuirValidationError` ("is an empty string") instead of a misleading "must be a positive integer" message.
38
+ - `filterLessons`: `weekNumber: 0` is now rejected with `assertPositiveInt` instead of silently passing.
39
+ - `http.ts`: cache eviction now uses pseudo-LRU (oldest-inserted Map key, O(1)) instead of an O(n) scan; `inFlightPromise` is typed as `Promise<T>` to eliminate unsafe `as Promise<unknown>` cast.
40
+ - `http.ts`: restored file integrity after shell heredoc substitution corrupted ES module imports; fixed `@typescript-eslint/no-unsafe-call` error on `inFlight` read by shifting the `as T` cast to the Promise type before `await`.
41
+
42
+ ### Changed
43
+
44
+ - JSDoc for `defaultRaw` client option now clarifies that a per-call `raw` option takes priority and includes an `@example` for both cases.
45
+ - Dev tooling: bumped TypeScript to 6.0.3, ESLint to ^10.2.1, Vitest and `@vitest/coverage-v8` to ^4.1.4, `@types/node` to ^25.6.0, `@typescript-eslint/*` and `typescript-eslint` to ^8.58.2, `@changesets/cli` to ^2.31.0, `@microsoft/api-extractor` to ^7.58.5, Prettier to ^3.8.3, `globals` to ^17.5.0; regenerated `package-lock.json`.
46
+ - CI now validates API report compatibility via `npm run api:report:check` (Node 24 job in matrix).
47
+ - `vitest.config.ts`: added coverage thresholds (`lines: 80`, `functions: 80`) to enforce minimum test coverage on CI.
48
+
49
+ ## [0.7.0] - 2026-04-19
50
+
51
+ ### Added
52
+
53
+ - `BsuirConfigurationError` when the runtime has no `fetch` and none was passed to `createBsuirClient({ fetch })`.
54
+
55
+ ### Changed
56
+
57
+ - HTTP client (2xx): valid JSON is parsed even when the server omits `application/json` in `Content-Type`; if the header declares JSON and the body is invalid, empty, or truncated, `BsuirApiError` (`Invalid JSON response payload`) is thrown; an empty body without a JSON `Content-Type` yields an empty string `""`.
58
+ - `package.json` `engines.node`: `>=20.0.0`. GitHub Actions **CI** runs on Node.js 20, 22, and 24 (`fail-fast: false`).
59
+
60
+ ### Documentation
61
+
62
+ - README: **Runtime requirements** (Node 20+ and CI), **Errors** (`BsuirConfigurationError`), **Successful HTTP responses (body parsing)**.
63
+ - JSDoc on catalog `listAll` methods (student groups, employees, faculties, departments, specialities, auditories), including caller abort / `AbortError` behavior.
64
+ - `.cursorrules` in the repository aligned with ESM-only build and the actual stack (Vitest, tsup, ESLint, native `fetch`).
10
65
 
11
66
  ## [0.6.7] - 2026-04-02
12
67
 
package/README.md CHANGED
@@ -4,7 +4,7 @@ Type-safe ESM SDK for [BSUIR IIS API](https://iis.bsuir.by/api/) with support fo
4
4
 
5
5
  ## Runtime requirements
6
6
 
7
- - **Node.js** `>=24` as declared in `package.json` (`engines`).
7
+ - **Node.js** `>=20` as declared in `package.json` (`engines`). CI runs on Node 20, 22, and 24.
8
8
  - A global **`fetch`** implementation, or pass `fetch` into `createBsuirClient({ fetch })` (for tests or polyfills).
9
9
  - **`AbortController` / `AbortSignal`** for cancellation and timeouts. When `AbortSignal.any` is available (current Node and modern browsers), the client combines the per-request timeout with your `signal` using the platform API; otherwise it merges them manually with `setTimeout`, so timeouts still apply together with a caller-provided `AbortSignal`.
10
10
 
@@ -38,11 +38,24 @@ const client = createBsuirClient({
38
38
  retryDelayMs: 300,
39
39
  retryMaxDelayMs: 3000,
40
40
  retryJitter: true,
41
+ cache: { ttlMs: 60_000, maxEntries: 200 },
42
+ dedupeInFlight: true,
43
+ validateResponses: false,
44
+ hooks: {
45
+ onRetry: ({ endpoint, delayMs, reason }) => {
46
+ console.log("retry", endpoint, delayMs, reason);
47
+ }
48
+ },
41
49
  defaultRaw: false
42
50
  });
43
51
  ```
44
52
 
45
53
  - `fetch` can be passed for custom runtime/testing.
54
+ - `signal` in `createBsuirClient({ signal })` acts as a global cancellation signal for all requests made by that client.
55
+ - `cache` stores successful GET responses in-memory for the configured TTL.
56
+ - `dedupeInFlight` reuses the same in-flight GET request for concurrent callers (when no per-request signal is passed).
57
+ - `validateResponses` enables runtime payload-shape checks for key endpoints.
58
+ - `hooks` provides lifecycle callbacks (`onRequest`, `onRetry`, `onResponse`, `onError`) for observability.
46
59
  - `AbortSignal` is supported by all read methods.
47
60
 
48
61
  ## API
@@ -84,9 +97,11 @@ When IIS responds with HTTP `404` or `400` (no list, missing resource, or endpoi
84
97
  SDK throws typed errors:
85
98
 
86
99
  - `BsuirApiError` for HTTP errors (contains `status`, `endpoint`, `body`). **Exception:** `client.announcements.byEmployee` / `byDepartment` resolve to `[]` on IIS HTTP `404` or `400` instead of throwing (see Announcements above).
87
- - `BsuirNetworkError` for transport errors (contains `endpoint`, `causeError`, and standard `cause`)
100
+ - `BsuirNetworkError` for transport errors (contains `endpoint` and standard `cause`)
101
+ - `BsuirResponseValidationError` for invalid payload shapes when `validateResponses: true`
88
102
  - `BsuirTimeoutError` for timeouts (contains `endpoint`, `timeoutMs`)
89
103
  - `BsuirValidationError` for invalid input parameters
104
+ - `BsuirConfigurationError` when the runtime has no `fetch` and none was passed to `createBsuirClient({ fetch })`
90
105
 
91
106
  Validation rules:
92
107
 
@@ -100,7 +115,15 @@ Retry and abort behavior:
100
115
  - Caller-provided aborted `AbortSignal` is re-thrown as native `AbortError`
101
116
  - Internal timeout is mapped to `BsuirTimeoutError`
102
117
 
103
- `createBsuirClient()` throws regular `Error` if no `fetch` implementation is available.
118
+ `createBsuirClient()` throws `BsuirConfigurationError` if no `fetch` implementation is available.
119
+
120
+ ## Successful HTTP responses (body parsing)
121
+
122
+ For **2xx** responses the client reads the body as text, then applies `JSON.parse` when the payload is valid JSON:
123
+
124
+ - Valid JSON is returned even when `Content-Type` does **not** include `application/json` (mislabeled responses still parse).
125
+ - If `Content-Type` indicates **`application/json`** but the body is empty or not valid JSON, the client throws `BsuirApiError` (`Invalid JSON response payload`), same as for a truncated `{` payload.
126
+ - If the body is **empty** and the content type does **not** indicate JSON, the result is an empty string `""` (analogous to reading plain text). Typical IIS catalog JSON endpoints return a non-empty body.
104
127
 
105
128
  ## Raw vs normalized schedule response
106
129
 
@@ -142,6 +165,7 @@ npm run lint
142
165
  npm run lint:fix
143
166
  npm run check
144
167
  npm run build
168
+ npm run api:report
145
169
  ```
146
170
 
147
171
  `npm run build` uses [tsup](https://tsup.egoist.dev/) with [`experimentalDts`](https://tsup.egoist.dev/) so `.d.ts` output is produced via `@microsoft/api-extractor` rather than the legacy Rollup declaration path (which is awkward with TypeScript 6’s `baseUrl` deprecation). TypeScript’s handbook notes that [`paths` can be used without `baseUrl`](https://www.typescriptlang.org/docs/handbook/modules/reference.html) when you need path mapping.