bsuir-iis-api 0.6.7 → 0.7.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
@@ -8,6 +8,23 @@ This changelog is maintained manually and updated in release commits.
8
8
 
9
9
  ## [Unreleased]
10
10
 
11
+ ## [0.7.0] - 2026-04-19
12
+
13
+ ### Added
14
+
15
+ - `BsuirConfigurationError` when the runtime has no `fetch` and none was passed to `createBsuirClient({ fetch })`.
16
+
17
+ ### Changed
18
+
19
+ - 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 `""`.
20
+ - `package.json` `engines.node`: `>=20.0.0`. GitHub Actions **CI** runs on Node.js 20, 22, and 24 (`fail-fast: false`).
21
+
22
+ ### Documentation
23
+
24
+ - README: **Runtime requirements** (Node 20+ and CI), **Errors** (`BsuirConfigurationError`), **Successful HTTP responses (body parsing)**.
25
+ - JSDoc on catalog `listAll` methods (student groups, employees, faculties, departments, specialities, auditories), including caller abort / `AbortError` behavior.
26
+ - `.cursorrules` in the repository aligned with ESM-only build and the actual stack (Vitest, tsup, ESLint, native `fetch`).
27
+
11
28
  ## [0.6.7] - 2026-04-02
12
29
 
13
30
  ### Changed
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
 
@@ -87,6 +87,7 @@ SDK throws typed errors:
87
87
  - `BsuirNetworkError` for transport errors (contains `endpoint`, `causeError`, and standard `cause`)
88
88
  - `BsuirTimeoutError` for timeouts (contains `endpoint`, `timeoutMs`)
89
89
  - `BsuirValidationError` for invalid input parameters
90
+ - `BsuirConfigurationError` when the runtime has no `fetch` and none was passed to `createBsuirClient({ fetch })`
90
91
 
91
92
  Validation rules:
92
93
 
@@ -100,7 +101,15 @@ Retry and abort behavior:
100
101
  - Caller-provided aborted `AbortSignal` is re-thrown as native `AbortError`
101
102
  - Internal timeout is mapped to `BsuirTimeoutError`
102
103
 
103
- `createBsuirClient()` throws regular `Error` if no `fetch` implementation is available.
104
+ `createBsuirClient()` throws `BsuirConfigurationError` if no `fetch` implementation is available.
105
+
106
+ ## Successful HTTP responses (body parsing)
107
+
108
+ For **2xx** responses the client reads the body as text, then applies `JSON.parse` when the payload is valid JSON:
109
+
110
+ - Valid JSON is returned even when `Content-Type` does **not** include `application/json` (mislabeled responses still parse).
111
+ - 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.
112
+ - 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
113
 
105
114
  ## Raw vs normalized schedule response
106
115
 
@@ -101,6 +101,12 @@ declare interface BsuirClientOptions {
101
101
  export { BsuirClientOptions }
102
102
  export { BsuirClientOptions as BsuirClientOptions_alias_1 }
103
103
 
104
+ declare class BsuirConfigurationError extends Error {
105
+ constructor(message: string);
106
+ }
107
+ export { BsuirConfigurationError }
108
+ export { BsuirConfigurationError as BsuirConfigurationError_alias_1 }
109
+
104
110
  declare class BsuirNetworkError extends Error {
105
111
  readonly endpoint: string;
106
112
  readonly causeError: unknown;
@@ -143,6 +149,14 @@ export declare function createAnnouncementsModule(config: InternalClientConfig):
143
149
  };
144
150
 
145
151
  export declare function createAuditoriesModule(config: InternalClientConfig): {
152
+ /**
153
+ * Returns the full list of auditories from `/auditories`.
154
+ * If the caller aborts `options.signal`, the platform propagates `AbortError` (not wrapped by the SDK).
155
+ *
156
+ * @throws {BsuirApiError} When the API returns a non-success HTTP status
157
+ * @throws {BsuirNetworkError} On transport failures after retries
158
+ * @throws {BsuirTimeoutError} When the request exceeds `timeoutMs`
159
+ */
146
160
  listAll(options?: ReadOptions): Promise<Auditory[]>;
147
161
  };
148
162
 
@@ -202,18 +216,50 @@ export { createBsuirClient }
202
216
  export { createBsuirClient as createBsuirClient_alias_1 }
203
217
 
204
218
  export declare function createDepartmentsModule(config: InternalClientConfig): {
219
+ /**
220
+ * Returns the full list of departments from `/departments`.
221
+ * If the caller aborts `options.signal`, the platform propagates `AbortError` (not wrapped by the SDK).
222
+ *
223
+ * @throws {BsuirApiError} When the API returns a non-success HTTP status
224
+ * @throws {BsuirNetworkError} On transport failures after retries
225
+ * @throws {BsuirTimeoutError} When the request exceeds `timeoutMs`
226
+ */
205
227
  listAll(options?: ReadOptions): Promise<Department[]>;
206
228
  };
207
229
 
208
230
  export declare function createEmployeesModule(config: InternalClientConfig): {
231
+ /**
232
+ * Returns the full list of employees from `/employees/all`.
233
+ * If the caller aborts `options.signal`, the platform propagates `AbortError` (not wrapped by the SDK).
234
+ *
235
+ * @throws {BsuirApiError} When the API returns a non-success HTTP status
236
+ * @throws {BsuirNetworkError} On transport failures after retries
237
+ * @throws {BsuirTimeoutError} When the request exceeds `timeoutMs`
238
+ */
209
239
  listAll(options?: ReadOptions): Promise<EmployeeCatalogItem[]>;
210
240
  };
211
241
 
212
242
  export declare function createFacultiesModule(config: InternalClientConfig): {
243
+ /**
244
+ * Returns the full list of faculties from `/faculties`.
245
+ * If the caller aborts `options.signal`, the platform propagates `AbortError` (not wrapped by the SDK).
246
+ *
247
+ * @throws {BsuirApiError} When the API returns a non-success HTTP status
248
+ * @throws {BsuirNetworkError} On transport failures after retries
249
+ * @throws {BsuirTimeoutError} When the request exceeds `timeoutMs`
250
+ */
213
251
  listAll(options?: ReadOptions): Promise<Faculty[]>;
214
252
  };
215
253
 
216
254
  export declare function createGroupsModule(config: InternalClientConfig): {
255
+ /**
256
+ * Returns the full list of student groups from `/student-groups`.
257
+ * If the caller aborts `options.signal`, the platform propagates `AbortError` (not wrapped by the SDK).
258
+ *
259
+ * @throws {BsuirApiError} When the API returns a non-success HTTP status
260
+ * @throws {BsuirNetworkError} On transport failures after retries
261
+ * @throws {BsuirTimeoutError} When the request exceeds `timeoutMs`
262
+ */
217
263
  listAll(options?: ReadOptions): Promise<StudentGroupCatalogItem[]>;
218
264
  };
219
265
 
@@ -254,6 +300,14 @@ export declare function createScheduleModule(config: InternalClientConfig): {
254
300
  };
255
301
 
256
302
  export declare function createSpecialitiesModule(config: InternalClientConfig): {
303
+ /**
304
+ * Returns the full list of specialities from `/specialities`.
305
+ * If the caller aborts `options.signal`, the platform propagates `AbortError` (not wrapped by the SDK).
306
+ *
307
+ * @throws {BsuirApiError} When the API returns a non-success HTTP status
308
+ * @throws {BsuirNetworkError} On transport failures after retries
309
+ * @throws {BsuirTimeoutError} When the request exceeds `timeoutMs`
310
+ */
257
311
  listAll(options?: ReadOptions): Promise<Speciality[]>;
258
312
  };
259
313
 
package/dist/index.d.ts CHANGED
@@ -4,6 +4,7 @@ export { BsuirClientOptions } from './_tsup-dts-rollup.js';
4
4
  export { RequestOptions } from './_tsup-dts-rollup.js';
5
5
  export { ReadOptions } from './_tsup-dts-rollup.js';
6
6
  export { BsuirApiError } from './_tsup-dts-rollup.js';
7
+ export { BsuirConfigurationError } from './_tsup-dts-rollup.js';
7
8
  export { BsuirNetworkError } from './_tsup-dts-rollup.js';
8
9
  export { BsuirTimeoutError } from './_tsup-dts-rollup.js';
9
10
  export { BsuirValidationError } from './_tsup-dts-rollup.js';
package/dist/index.js CHANGED
@@ -44,6 +44,13 @@ var BsuirValidationError = class _BsuirValidationError extends Error {
44
44
  this.name = "BsuirValidationError";
45
45
  }
46
46
  };
47
+ var BsuirConfigurationError = class _BsuirConfigurationError extends Error {
48
+ constructor(message) {
49
+ super(message);
50
+ fixErrorPrototype(this, _BsuirConfigurationError.prototype);
51
+ this.name = "BsuirConfigurationError";
52
+ }
53
+ };
47
54
 
48
55
  // src/client/mergeSignals.ts
49
56
  var AbortSignalCtor = AbortSignal;
@@ -166,13 +173,21 @@ function getRetryDelayMs(config, attempt, retryAfterHeader) {
166
173
  }
167
174
  async function parseBody(response) {
168
175
  const contentType = response.headers.get("content-type") ?? "";
169
- if (!contentType.includes("application/json")) {
170
- return response.text();
176
+ const declaredJson = contentType.includes("application/json");
177
+ const text = await response.text();
178
+ if (text.length === 0) {
179
+ if (declaredJson) {
180
+ throw new BsuirApiError("Invalid JSON response payload", response.status, response.url, null);
181
+ }
182
+ return "";
171
183
  }
172
184
  try {
173
- return await response.json();
185
+ return JSON.parse(text);
174
186
  } catch {
175
- throw new BsuirApiError("Invalid JSON response payload", response.status, response.url, null);
187
+ if (declaredJson) {
188
+ throw new BsuirApiError("Invalid JSON response payload", response.status, response.url, null);
189
+ }
190
+ return text;
176
191
  }
177
192
  }
178
193
  async function requestJson(config, path, options = {}) {
@@ -271,6 +286,14 @@ function createAnnouncementsModule(config) {
271
286
  // src/modules/auditories.ts
272
287
  function createAuditoriesModule(config) {
273
288
  return {
289
+ /**
290
+ * Returns the full list of auditories from `/auditories`.
291
+ * If the caller aborts `options.signal`, the platform propagates `AbortError` (not wrapped by the SDK).
292
+ *
293
+ * @throws {BsuirApiError} When the API returns a non-success HTTP status
294
+ * @throws {BsuirNetworkError} On transport failures after retries
295
+ * @throws {BsuirTimeoutError} When the request exceeds `timeoutMs`
296
+ */
274
297
  async listAll(options = {}) {
275
298
  return requestJson(config, "/auditories", {
276
299
  signal: options.signal
@@ -282,6 +305,14 @@ function createAuditoriesModule(config) {
282
305
  // src/modules/departments.ts
283
306
  function createDepartmentsModule(config) {
284
307
  return {
308
+ /**
309
+ * Returns the full list of departments from `/departments`.
310
+ * If the caller aborts `options.signal`, the platform propagates `AbortError` (not wrapped by the SDK).
311
+ *
312
+ * @throws {BsuirApiError} When the API returns a non-success HTTP status
313
+ * @throws {BsuirNetworkError} On transport failures after retries
314
+ * @throws {BsuirTimeoutError} When the request exceeds `timeoutMs`
315
+ */
285
316
  async listAll(options = {}) {
286
317
  return requestJson(config, "/departments", {
287
318
  signal: options.signal
@@ -293,6 +324,14 @@ function createDepartmentsModule(config) {
293
324
  // src/modules/employees.ts
294
325
  function createEmployeesModule(config) {
295
326
  return {
327
+ /**
328
+ * Returns the full list of employees from `/employees/all`.
329
+ * If the caller aborts `options.signal`, the platform propagates `AbortError` (not wrapped by the SDK).
330
+ *
331
+ * @throws {BsuirApiError} When the API returns a non-success HTTP status
332
+ * @throws {BsuirNetworkError} On transport failures after retries
333
+ * @throws {BsuirTimeoutError} When the request exceeds `timeoutMs`
334
+ */
296
335
  async listAll(options = {}) {
297
336
  return requestJson(config, "/employees/all", {
298
337
  signal: options.signal
@@ -304,6 +343,14 @@ function createEmployeesModule(config) {
304
343
  // src/modules/faculties.ts
305
344
  function createFacultiesModule(config) {
306
345
  return {
346
+ /**
347
+ * Returns the full list of faculties from `/faculties`.
348
+ * If the caller aborts `options.signal`, the platform propagates `AbortError` (not wrapped by the SDK).
349
+ *
350
+ * @throws {BsuirApiError} When the API returns a non-success HTTP status
351
+ * @throws {BsuirNetworkError} On transport failures after retries
352
+ * @throws {BsuirTimeoutError} When the request exceeds `timeoutMs`
353
+ */
307
354
  async listAll(options = {}) {
308
355
  return requestJson(config, "/faculties", {
309
356
  signal: options.signal
@@ -315,6 +362,14 @@ function createFacultiesModule(config) {
315
362
  // src/modules/groups.ts
316
363
  function createGroupsModule(config) {
317
364
  return {
365
+ /**
366
+ * Returns the full list of student groups from `/student-groups`.
367
+ * If the caller aborts `options.signal`, the platform propagates `AbortError` (not wrapped by the SDK).
368
+ *
369
+ * @throws {BsuirApiError} When the API returns a non-success HTTP status
370
+ * @throws {BsuirNetworkError} On transport failures after retries
371
+ * @throws {BsuirTimeoutError} When the request exceeds `timeoutMs`
372
+ */
318
373
  async listAll(options = {}) {
319
374
  return requestJson(config, "/student-groups", {
320
375
  signal: options.signal
@@ -548,6 +603,14 @@ function createScheduleModule(config) {
548
603
  // src/modules/specialities.ts
549
604
  function createSpecialitiesModule(config) {
550
605
  return {
606
+ /**
607
+ * Returns the full list of specialities from `/specialities`.
608
+ * If the caller aborts `options.signal`, the platform propagates `AbortError` (not wrapped by the SDK).
609
+ *
610
+ * @throws {BsuirApiError} When the API returns a non-success HTTP status
611
+ * @throws {BsuirNetworkError} On transport failures after retries
612
+ * @throws {BsuirTimeoutError} When the request exceeds `timeoutMs`
613
+ */
551
614
  async listAll(options = {}) {
552
615
  return requestJson(config, "/specialities", {
553
616
  signal: options.signal
@@ -563,7 +626,9 @@ function resolveFetch(customFetch) {
563
626
  return customFetch;
564
627
  }
565
628
  if (typeof globalThis.fetch !== "function") {
566
- throw new Error("Global fetch is unavailable. Provide 'fetch' in createBsuirClient options.");
629
+ throw new BsuirConfigurationError(
630
+ "Global fetch is unavailable. Provide 'fetch' in createBsuirClient options."
631
+ );
567
632
  }
568
633
  return globalThis.fetch;
569
634
  }
@@ -596,6 +661,7 @@ function createBsuirClient(options = {}) {
596
661
  }
597
662
  export {
598
663
  BsuirApiError,
664
+ BsuirConfigurationError,
599
665
  BsuirNetworkError,
600
666
  BsuirTimeoutError,
601
667
  BsuirValidationError,
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/client/errors.ts","../src/client/mergeSignals.ts","../src/utils/guards.ts","../src/client/http.ts","../src/modules/announcements.ts","../src/modules/auditories.ts","../src/modules/departments.ts","../src/modules/employees.ts","../src/modules/faculties.ts","../src/modules/groups.ts","../src/utils/week.ts","../src/modules/schedule.ts","../src/modules/specialities.ts","../src/client/createClient.ts"],"sourcesContent":["function fixErrorPrototype(instance: Error, prototype: object): void {\n Object.setPrototypeOf(instance, prototype);\n}\n\nexport class BsuirApiError extends Error {\n readonly status: number;\n readonly endpoint: string;\n readonly body: unknown;\n\n constructor(message: string, status: number, endpoint: string, body: unknown) {\n super(message);\n fixErrorPrototype(this, BsuirApiError.prototype);\n this.name = \"BsuirApiError\";\n this.status = status;\n this.endpoint = endpoint;\n this.body = body;\n }\n}\n\nexport class BsuirNetworkError extends Error {\n readonly endpoint: string;\n readonly causeError: unknown;\n\n constructor(message: string, endpoint: string, causeError: unknown) {\n super(message, { cause: causeError });\n fixErrorPrototype(this, BsuirNetworkError.prototype);\n this.name = \"BsuirNetworkError\";\n this.endpoint = endpoint;\n this.causeError = causeError;\n }\n}\n\nexport class BsuirTimeoutError extends Error {\n readonly endpoint: string;\n readonly timeoutMs: number;\n\n constructor(message: string, endpoint: string, timeoutMs: number) {\n super(message);\n fixErrorPrototype(this, BsuirTimeoutError.prototype);\n this.name = \"BsuirTimeoutError\";\n this.endpoint = endpoint;\n this.timeoutMs = timeoutMs;\n }\n}\n\nexport class BsuirValidationError extends Error {\n constructor(message: string) {\n super(message);\n fixErrorPrototype(this, BsuirValidationError.prototype);\n this.name = \"BsuirValidationError\";\n }\n}\n","type AbortSignalConstructor = typeof AbortSignal & {\n any?(signals: AbortSignal[]): AbortSignal;\n};\n\nconst AbortSignalCtor = AbortSignal as AbortSignalConstructor;\n\n/**\n * Combines an optional caller {@link AbortSignal} with a per-attempt timeout.\n * When `AbortSignal.any` exists at runtime, delegates to the platform implementation.\n * Otherwise uses a manual merge so the timeout still applies alongside a caller signal.\n */\nexport function mergeSignals(signal: AbortSignal | undefined, timeoutMs: number): AbortSignal {\n if (typeof AbortSignalCtor.any === \"function\") {\n const parts: AbortSignal[] = [AbortSignal.timeout(timeoutMs)];\n if (signal) {\n parts.push(signal);\n }\n return AbortSignalCtor.any(parts);\n }\n\n return mergeSignalsManual(signal, timeoutMs);\n}\n/** Used when `AbortSignal.any` is unavailable; exposed for unit tests. */\nexport function mergeSignalsManual(signal: AbortSignal | undefined, timeoutMs: number): AbortSignal {\n const combined = new AbortController();\n\n const onSignalAbort = (): void => {\n clearTimeout(timeoutId);\n combined.abort();\n };\n\n const timeoutId = setTimeout(() => {\n if (signal) {\n signal.removeEventListener(\"abort\", onSignalAbort);\n }\n combined.abort();\n }, timeoutMs);\n\n if (signal) {\n if (signal.aborted) {\n clearTimeout(timeoutId);\n combined.abort();\n } else {\n signal.addEventListener(\"abort\", onSignalAbort, { once: true });\n }\n }\n\n return combined.signal;\n}\n","import { BsuirValidationError } from \"../client/errors\";\n\nconst GROUP_NUMBER_PATTERN = /^\\d+$/;\nconst EMPLOYEE_URL_ID_PATTERN = /^[a-z0-9]+(?:-[a-z0-9]+)*$/i;\n\nexport function assertNonEmptyString(value: unknown, fieldName: string): asserts value is string {\n if (typeof value !== \"string\" || value.trim().length === 0) {\n throw new BsuirValidationError(`'${fieldName}' must be a non-empty string`);\n }\n}\n\nexport function assertPositiveInt(value: unknown, fieldName: string): asserts value is number {\n if (typeof value !== \"number\" || !Number.isInteger(value) || value <= 0) {\n throw new BsuirValidationError(`'${fieldName}' must be a positive integer`);\n }\n}\n\nexport function assertGroupNumber(value: unknown, fieldName = \"groupNumber\"): asserts value is string {\n assertNonEmptyString(value, fieldName);\n if (!GROUP_NUMBER_PATTERN.test(value)) {\n throw new BsuirValidationError(`'${fieldName}' must contain only digits`);\n }\n}\n\nexport function assertEmployeeUrlId(value: unknown, fieldName = \"urlId\"): asserts value is string {\n assertNonEmptyString(value, fieldName);\n if (!EMPLOYEE_URL_ID_PATTERN.test(value)) {\n throw new BsuirValidationError(\n `'${fieldName}' must be a valid slug (letters, digits, hyphen)`\n );\n }\n}\n\nexport function isAbortError(error: unknown): boolean {\n if (error instanceof DOMException && error.name === \"AbortError\") {\n return true;\n }\n\n if (typeof error === \"object\" && error !== null) {\n const maybeError = error as { name?: unknown; code?: unknown };\n return maybeError.name === \"AbortError\" || maybeError.code === \"ABORT_ERR\";\n }\n\n return false;\n}\n","import { BsuirApiError, BsuirNetworkError, BsuirTimeoutError } from \"./errors\";\nimport { mergeSignals } from \"./mergeSignals\";\nimport type { InternalClientConfig, QueryParams, RequestOptions } from \"./types\";\nimport { isAbortError } from \"../utils/guards\";\n\nconst RETRIABLE_STATUS_CODES = new Set([429, 500, 502, 503, 504]);\n\nfunction buildUrl(baseUrl: string, path: string, query?: QueryParams): string {\n const normalizedBase = baseUrl.endsWith(\"/\") ? baseUrl.slice(0, -1) : baseUrl;\n const normalizedPath = path.startsWith(\"/\") ? path : `/${path}`;\n const url = new URL(`${normalizedBase}${normalizedPath}`);\n\n if (query) {\n for (const [key, value] of Object.entries(query)) {\n if (value === undefined || value === null) {\n continue;\n }\n url.searchParams.set(key, String(value));\n }\n }\n\n return url.toString();\n}\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n\nfunction parseRetryAfterMs(retryAfter: string | null): number | null {\n if (!retryAfter) {\n return null;\n }\n\n const asSeconds = Number(retryAfter);\n if (!Number.isNaN(asSeconds)) {\n return Math.max(0, Math.floor(asSeconds * 1000));\n }\n\n const dateValue = Date.parse(retryAfter);\n if (!Number.isNaN(dateValue)) {\n return Math.max(0, dateValue - Date.now());\n }\n\n return null;\n}\n\nfunction getRetryDelayMs(\n config: InternalClientConfig,\n attempt: number,\n retryAfterHeader?: string | null\n): number {\n const retryAfterDelay = parseRetryAfterMs(retryAfterHeader ?? null);\n if (retryAfterDelay !== null) {\n return Math.min(retryAfterDelay, config.retryMaxDelayMs);\n }\n\n const exponent = Math.max(0, attempt);\n const baseDelay = Math.min(config.retryDelayMs * 2 ** exponent, config.retryMaxDelayMs);\n if (!config.retryJitter) {\n return baseDelay;\n }\n\n const jitterFactor = 0.75 + Math.random() * 0.5;\n return Math.floor(baseDelay * jitterFactor);\n}\n\nasync function parseBody(response: Response): Promise<unknown> {\n const contentType = response.headers.get(\"content-type\") ?? \"\";\n if (!contentType.includes(\"application/json\")) {\n return response.text();\n }\n\n try {\n return await response.json();\n } catch {\n throw new BsuirApiError(\"Invalid JSON response payload\", response.status, response.url, null);\n }\n}\n\nexport async function requestJson<T>(\n config: InternalClientConfig,\n path: string,\n options: RequestOptions = {}\n): Promise<T> {\n const endpoint = buildUrl(config.baseUrl, path, options.query);\n const headers = new Headers({\n Accept: \"application/json\"\n });\n\n if (config.userAgent) {\n headers.set(\"User-Agent\", config.userAgent);\n }\n\n for (let attempt = 0; attempt <= config.retries; attempt += 1) {\n const requestSignal = mergeSignals(options.signal, config.timeoutMs);\n try {\n const response = await config.fetchImpl(endpoint, {\n method: \"GET\",\n headers,\n signal: requestSignal\n });\n\n if (!response.ok) {\n const errorBody = await parseBody(response);\n if (attempt < config.retries && RETRIABLE_STATUS_CODES.has(response.status)) {\n const delayMs = getRetryDelayMs(config, attempt, response.headers.get(\"retry-after\"));\n await sleep(delayMs);\n continue;\n }\n throw new BsuirApiError(\n `BSUIR API returned HTTP ${String(response.status)} for ${path}`,\n response.status,\n endpoint,\n errorBody\n );\n }\n\n return (await parseBody(response)) as T;\n } catch (error) {\n if (error instanceof BsuirApiError) {\n throw error;\n }\n\n if (isAbortError(error)) {\n if (options.signal?.aborted) {\n throw error;\n }\n throw new BsuirTimeoutError(\n `Request timed out after ${String(config.timeoutMs)}ms: ${path}`,\n endpoint,\n config.timeoutMs\n );\n }\n\n if (attempt < config.retries) {\n const delayMs = getRetryDelayMs(config, attempt);\n await sleep(delayMs);\n continue;\n }\n\n throw new BsuirNetworkError(`Network error while requesting ${path}`, endpoint, error);\n }\n }\n\n throw new BsuirNetworkError(`Unexpected retry loop termination for ${path}`, endpoint, null);\n}\n","import { BsuirApiError } from \"../client/errors\";\nimport { requestJson } from \"../client/http\";\nimport type { InternalClientConfig } from \"../client/types\";\nimport type { Announcement } from \"../types/announcement\";\nimport { assertEmployeeUrlId, assertPositiveInt } from \"../utils/guards\";\nimport type { ReadOptions } from \"./types\";\n\nconst ANNOUNCEMENT_EMPTY_LIST_STATUSES = new Set<number>([404, 400]);\n\nasync function requestAnnouncementList(\n config: InternalClientConfig,\n path: string,\n options: ReadOptions & { query: Record<string, string | number> }\n): Promise<Announcement[]> {\n try {\n return await requestJson<Announcement[]>(config, path, options);\n } catch (error) {\n if (error instanceof BsuirApiError && ANNOUNCEMENT_EMPTY_LIST_STATUSES.has(error.status)) {\n return [];\n }\n throw error;\n }\n}\n\nexport function createAnnouncementsModule(config: InternalClientConfig) {\n return {\n /**\n * Lists announcements for an employee. IIS may return HTTP `404` or `400` (no list / endpoint quirks); the SDK maps those to `[]`.\n */\n async byEmployee(urlId: string, options: ReadOptions = {}): Promise<Announcement[]> {\n assertEmployeeUrlId(urlId, \"urlId\");\n return requestAnnouncementList(config, \"/announcements/employees\", {\n ...options,\n query: { \"url-id\": urlId }\n });\n },\n\n /**\n * Lists announcements for a department. IIS may return HTTP `404` or `400` (no list / endpoint quirks); the SDK maps those to `[]`.\n */\n async byDepartment(id: number, options: ReadOptions = {}): Promise<Announcement[]> {\n assertPositiveInt(id, \"id\");\n return requestAnnouncementList(config, \"/announcements/departments\", {\n ...options,\n query: { id }\n });\n }\n };\n}\n","import type { InternalClientConfig } from \"../client/types\";\nimport { requestJson } from \"../client/http\";\nimport type { Auditory } from \"../types/catalog\";\nimport type { ReadOptions } from \"./types\";\n\nexport function createAuditoriesModule(config: InternalClientConfig) {\n return {\n async listAll(options: ReadOptions = {}): Promise<Auditory[]> {\n return requestJson<Auditory[]>(config, \"/auditories\", {\n signal: options.signal\n });\n }\n };\n}\n","import type { InternalClientConfig } from \"../client/types\";\nimport { requestJson } from \"../client/http\";\nimport type { Department } from \"../types/catalog\";\nimport type { ReadOptions } from \"./types\";\n\nexport function createDepartmentsModule(config: InternalClientConfig) {\n return {\n async listAll(options: ReadOptions = {}): Promise<Department[]> {\n return requestJson<Department[]>(config, \"/departments\", {\n signal: options.signal\n });\n }\n };\n}\n","import type { InternalClientConfig } from \"../client/types\";\nimport { requestJson } from \"../client/http\";\nimport type { EmployeeCatalogItem } from \"../types/employee\";\nimport type { ReadOptions } from \"./types\";\n\nexport function createEmployeesModule(config: InternalClientConfig) {\n return {\n async listAll(options: ReadOptions = {}): Promise<EmployeeCatalogItem[]> {\n return requestJson<EmployeeCatalogItem[]>(config, \"/employees/all\", {\n signal: options.signal\n });\n }\n };\n}\n","import type { InternalClientConfig } from \"../client/types\";\nimport { requestJson } from \"../client/http\";\nimport type { Faculty } from \"../types/catalog\";\nimport type { ReadOptions } from \"./types\";\n\nexport function createFacultiesModule(config: InternalClientConfig) {\n return {\n async listAll(options: ReadOptions = {}): Promise<Faculty[]> {\n return requestJson<Faculty[]>(config, \"/faculties\", {\n signal: options.signal\n });\n }\n };\n}\n","import type { InternalClientConfig } from \"../client/types\";\nimport { requestJson } from \"../client/http\";\nimport type { StudentGroupCatalogItem } from \"../types/catalog\";\nimport type { ReadOptions } from \"./types\";\n\nexport function createGroupsModule(config: InternalClientConfig) {\n return {\n async listAll(options: ReadOptions = {}): Promise<StudentGroupCatalogItem[]> {\n return requestJson<StudentGroupCatalogItem[]>(config, \"/student-groups\", {\n signal: options.signal\n });\n }\n };\n}\n","import { BsuirValidationError } from \"../client/errors\";\nimport { assertPositiveInt } from \"./guards\";\n\n/**\n * Normalizes current week payload from API to a positive integer.\n * API can return plain text (`\"1\\n\"`) or number.\n */\nexport function parseCurrentWeek(payload: unknown): number {\n if (typeof payload === \"number\") {\n assertPositiveInt(payload, \"currentWeek\");\n return payload;\n }\n\n if (typeof payload === \"string\") {\n const normalized = payload.trim();\n if (normalized.length > 0) {\n const parsed = Number(normalized);\n if (Number.isInteger(parsed)) {\n assertPositiveInt(parsed, \"currentWeek\");\n return parsed;\n }\n }\n }\n\n if (typeof payload === \"object\" && payload !== null) {\n const record = payload as Record<string, unknown>;\n if (\"weekNumber\" in record) {\n return parseCurrentWeek(record.weekNumber);\n }\n if (\"currentWeek\" in record) {\n return parseCurrentWeek(record.currentWeek);\n }\n }\n\n throw new BsuirValidationError(\"'currentWeek' response payload must be a positive integer\");\n}\n","import type { InternalClientConfig } from \"../client/types\";\nimport { requestJson } from \"../client/http\";\nimport { assertEmployeeUrlId, assertGroupNumber, assertPositiveInt } from \"../utils/guards\";\nimport type {\n FlattenedLessonsByDay,\n FlattenedScheduleItem,\n NormalizedScheduleResponse,\n ScheduleFilterOptions,\n ScheduleItem,\n ScheduleResponse\n} from \"../types/schedule\";\nimport type { ApiDateResponse } from \"../types/common\";\nimport type { Weekday } from \"../types/common\";\nimport type { ReadOptions } from \"./types\";\nimport { parseCurrentWeek } from \"../utils/week\";\n\nconst WEEKDAYS: Weekday[] = [\n \"Понедельник\",\n \"Вторник\",\n \"Среда\",\n \"Четверг\",\n \"Пятница\",\n \"Суббота\"\n];\n\nfunction lessonAuditories(item: ScheduleItem): string[] {\n const { auditories } = item;\n return Array.isArray(auditories) ? auditories : [];\n}\n\nfunction normalizeSchedule(response: ScheduleResponse): NormalizedScheduleResponse {\n const lessons: FlattenedScheduleItem[] = [];\n const lessonsByDay: FlattenedLessonsByDay = {};\n const safeSchedules = response.schedules ?? {};\n const safeExams = response.exams ?? [];\n for (const day of WEEKDAYS) {\n const dayItems = safeSchedules[day] ?? [];\n const flattenedDayItems = dayItems.map((item) => ({\n ...item,\n auditories: lessonAuditories(item),\n day,\n source: \"schedules\" as const\n }));\n lessonsByDay[day] = flattenedDayItems;\n for (const item of dayItems) {\n lessons.push({\n ...item,\n auditories: lessonAuditories(item),\n day,\n source: \"schedules\"\n });\n }\n }\n\n for (const exam of safeExams) {\n lessons.push({\n ...exam,\n auditories: lessonAuditories(exam),\n day: null,\n // Exams are not grouped by weekday in API response.\n source: \"exams\"\n });\n }\n\n const scheduleLessons = lessons.filter((lesson) => lesson.source === \"schedules\");\n const examLessons = lessons.filter((lesson) => lesson.source === \"exams\");\n\n return {\n ...response,\n schedules: safeSchedules,\n exams: safeExams,\n lessons,\n lessonsByDay,\n scheduleLessons,\n examLessons\n };\n}\n\nfunction matchesFilter(item: FlattenedScheduleItem, filter: ScheduleFilterOptions): boolean {\n if (filter.source && item.source !== filter.source) {\n return false;\n }\n\n if (filter.weekday && item.day !== filter.weekday) {\n return false;\n }\n\n if (typeof filter.weekNumber === \"number\") {\n if (!Array.isArray(item.weekNumber) || !item.weekNumber.includes(filter.weekNumber)) {\n return false;\n }\n }\n\n if (typeof filter.subgroup === \"number\" && item.numSubgroup !== filter.subgroup) {\n return false;\n }\n\n if (filter.lessonTypeAbbrev) {\n const types = Array.isArray(filter.lessonTypeAbbrev)\n ? filter.lessonTypeAbbrev\n : [filter.lessonTypeAbbrev];\n if (!item.lessonTypeAbbrev || !types.includes(item.lessonTypeAbbrev)) {\n return false;\n }\n }\n\n if (filter.subjectQuery) {\n const query = filter.subjectQuery.toLowerCase();\n const haystack = `${item.subject} ${item.subjectFullName} ${item.note ?? \"\"}`.toLowerCase();\n if (!haystack.includes(query)) {\n return false;\n }\n }\n\n if (filter.employeeUrlId) {\n const employeeMatch = item.employees?.some((employee) => employee.urlId === filter.employeeUrlId);\n if (!employeeMatch) {\n return false;\n }\n }\n\n if (filter.auditory && !lessonAuditories(item).includes(filter.auditory)) {\n return false;\n }\n\n return true;\n}\n\nfunction filterLessons(\n response: NormalizedScheduleResponse,\n filter: ScheduleFilterOptions\n): FlattenedScheduleItem[] {\n return response.lessons.filter((item) => matchesFilter(item, filter));\n}\n\nexport function createScheduleModule(config: InternalClientConfig) {\n /**\n * Returns schedule for a student group.\n * By default returns normalized payload, unless `raw: true` is passed.\n */\n async function getGroup<TRaw extends boolean | undefined = undefined>(\n groupNumber: string,\n options: ReadOptions & { raw?: TRaw } = {}\n ): Promise<TRaw extends true ? ScheduleResponse : NormalizedScheduleResponse> {\n assertGroupNumber(groupNumber, \"groupNumber\");\n const response = await requestJson<ScheduleResponse>(config, \"/schedule\", {\n query: { studentGroup: groupNumber },\n signal: options.signal\n });\n const result = options.raw ?? config.defaultRaw ? response : normalizeSchedule(response);\n return result as TRaw extends true ? ScheduleResponse : NormalizedScheduleResponse;\n }\n\n /**\n * Returns schedule for an employee.\n * By default returns normalized payload, unless `raw: true` is passed.\n */\n async function getEmployee<TRaw extends boolean | undefined = undefined>(\n urlId: string,\n options: ReadOptions & { raw?: TRaw } = {}\n ): Promise<TRaw extends true ? ScheduleResponse : NormalizedScheduleResponse> {\n assertEmployeeUrlId(urlId, \"urlId\");\n const response = await requestJson<ScheduleResponse>(\n config,\n `/employees/schedule/${encodeURIComponent(urlId)}`,\n {\n signal: options.signal\n }\n );\n const result = options.raw ?? config.defaultRaw ? response : normalizeSchedule(response);\n return result as TRaw extends true ? ScheduleResponse : NormalizedScheduleResponse;\n }\n\n /**\n * Returns filtered schedule items for a group from normalized schedule payload.\n */\n async function getGroupFiltered(\n groupNumber: string,\n filter: ScheduleFilterOptions,\n options: ReadOptions = {}\n ): Promise<FlattenedScheduleItem[]> {\n const normalized = await getGroup(groupNumber, { ...options, raw: false });\n return filterLessons(normalized, filter);\n }\n\n /**\n * Returns filtered schedule items for an employee from normalized schedule payload.\n */\n async function getEmployeeFiltered(\n urlId: string,\n filter: ScheduleFilterOptions,\n options: ReadOptions = {}\n ): Promise<FlattenedScheduleItem[]> {\n const normalized = await getEmployee(urlId, { ...options, raw: false });\n return filterLessons(normalized, filter);\n }\n\n async function getCurrentWeek(options: ReadOptions = {}): Promise<number> {\n const payload = await requestJson<unknown>(config, \"/schedule/current-week\", {\n signal: options.signal\n });\n return parseCurrentWeek(payload);\n }\n\n return {\n getGroup,\n getEmployee,\n getGroupFiltered,\n getEmployeeFiltered,\n\n async getGroupExams(groupNumber: string, options: ReadOptions = {}): Promise<FlattenedScheduleItem[]> {\n return getGroupFiltered(groupNumber, { source: \"exams\" }, options);\n },\n\n async getEmployeeExams(urlId: string, options: ReadOptions = {}): Promise<FlattenedScheduleItem[]> {\n return getEmployeeFiltered(urlId, { source: \"exams\" }, options);\n },\n\n async getGroupBySubgroup(\n groupNumber: string,\n subgroup: number,\n options: ReadOptions = {}\n ): Promise<FlattenedScheduleItem[]> {\n assertPositiveInt(subgroup, \"subgroup\");\n return getGroupFiltered(groupNumber, { source: \"schedules\", subgroup }, options);\n },\n\n async getEmployeeBySubgroup(\n urlId: string,\n subgroup: number,\n options: ReadOptions = {}\n ): Promise<FlattenedScheduleItem[]> {\n assertPositiveInt(subgroup, \"subgroup\");\n return getEmployeeFiltered(urlId, { source: \"schedules\", subgroup }, options);\n },\n\n getCurrentWeek,\n\n /**\n * Calls IIS `/last-update-date/student-group`. That route is legacy and unsupported on the server;\n * it may return an error for newer group numbers (e.g. six-digit `524404`).\n */\n async getLastUpdateByGroup(\n params: { groupNumber: string } | { id: number },\n options: ReadOptions = {}\n ): Promise<ApiDateResponse> {\n let query: Record<string, string | number>;\n if (\"groupNumber\" in params) {\n assertGroupNumber(params.groupNumber, \"groupNumber\");\n query = { groupNumber: params.groupNumber };\n } else {\n assertPositiveInt(params.id, \"id\");\n query = { id: params.id };\n }\n return requestJson<ApiDateResponse>(config, \"/last-update-date/student-group\", {\n query,\n signal: options.signal\n });\n },\n\n /**\n * Calls IIS `/last-update-date/employee`. That route is legacy and unsupported on the server; prefer\n * not relying on it for critical cache logic.\n */\n async getLastUpdateByEmployee(\n params: { urlId: string } | { id: number },\n options: ReadOptions = {}\n ): Promise<ApiDateResponse> {\n let query: Record<string, string | number>;\n if (\"urlId\" in params) {\n assertEmployeeUrlId(params.urlId, \"urlId\");\n query = { \"url-id\": params.urlId };\n } else {\n assertPositiveInt(params.id, \"id\");\n query = { id: params.id };\n }\n return requestJson<ApiDateResponse>(config, \"/last-update-date/employee\", {\n query,\n signal: options.signal\n });\n }\n };\n}\n","import type { InternalClientConfig } from \"../client/types\";\nimport { requestJson } from \"../client/http\";\nimport type { Speciality } from \"../types/catalog\";\nimport type { ReadOptions } from \"./types\";\n\nexport function createSpecialitiesModule(config: InternalClientConfig) {\n return {\n async listAll(options: ReadOptions = {}): Promise<Speciality[]> {\n return requestJson<Speciality[]>(config, \"/specialities\", {\n signal: options.signal\n });\n }\n };\n}\n","import type { BsuirClientOptions, InternalClientConfig } from \"./types\";\nimport { createAnnouncementsModule } from \"../modules/announcements\";\nimport { createAuditoriesModule } from \"../modules/auditories\";\nimport { createDepartmentsModule } from \"../modules/departments\";\nimport { createEmployeesModule } from \"../modules/employees\";\nimport { createFacultiesModule } from \"../modules/faculties\";\nimport { createGroupsModule } from \"../modules/groups\";\nimport { createScheduleModule } from \"../modules/schedule\";\nimport { createSpecialitiesModule } from \"../modules/specialities\";\n\nconst DEFAULT_BASE_URL = \"https://iis.bsuir.by/api/v1\";\n\nfunction resolveFetch(customFetch?: typeof globalThis.fetch): typeof globalThis.fetch {\n if (customFetch) {\n return customFetch;\n }\n\n if (typeof globalThis.fetch !== \"function\") {\n throw new Error(\"Global fetch is unavailable. Provide 'fetch' in createBsuirClient options.\");\n }\n\n return globalThis.fetch;\n}\n\nfunction createInternalConfig(options: BsuirClientOptions = {}): InternalClientConfig {\n return {\n baseUrl: options.baseUrl ?? DEFAULT_BASE_URL,\n fetchImpl: resolveFetch(options.fetch),\n timeoutMs: options.timeoutMs ?? 10_000,\n retries: options.retries ?? 1,\n retryDelayMs: options.retryDelayMs ?? 300,\n retryMaxDelayMs: options.retryMaxDelayMs ?? 3_000,\n retryJitter: options.retryJitter ?? true,\n userAgent: options.userAgent,\n defaultRaw: options.defaultRaw ?? false\n };\n}\n\n/**\n * Creates a configured BSUIR IIS API client.\n */\nexport function createBsuirClient(options: BsuirClientOptions = {}) {\n const config = createInternalConfig(options);\n const schedule = createScheduleModule(config);\n\n return {\n schedule,\n groups: createGroupsModule(config),\n employees: createEmployeesModule(config),\n faculties: createFacultiesModule(config),\n departments: createDepartmentsModule(config),\n specialities: createSpecialitiesModule(config),\n announcements: createAnnouncementsModule(config),\n auditories: createAuditoriesModule(config)\n };\n}\n\n/**\n * Public client contract returned by {@link createBsuirClient}.\n */\nexport type BsuirClient = ReturnType<typeof createBsuirClient>;\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/client/errors.ts","../src/client/mergeSignals.ts","../src/utils/guards.ts","../src/client/http.ts","../src/modules/announcements.ts","../src/modules/auditories.ts","../src/modules/departments.ts","../src/modules/employees.ts","../src/modules/faculties.ts","../src/modules/groups.ts","../src/utils/week.ts","../src/modules/schedule.ts","../src/modules/specialities.ts","../src/client/createClient.ts"],"sourcesContent":["function fixErrorPrototype(instance: Error, prototype: object): void {\n Object.setPrototypeOf(instance, prototype);\n}\n\nexport class BsuirApiError extends Error {\n readonly status: number;\n readonly endpoint: string;\n readonly body: unknown;\n\n constructor(message: string, status: number, endpoint: string, body: unknown) {\n super(message);\n fixErrorPrototype(this, BsuirApiError.prototype);\n this.name = \"BsuirApiError\";\n this.status = status;\n this.endpoint = endpoint;\n this.body = body;\n }\n}\n\nexport class BsuirNetworkError extends Error {\n readonly endpoint: string;\n readonly causeError: unknown;\n\n constructor(message: string, endpoint: string, causeError: unknown) {\n super(message, { cause: causeError });\n fixErrorPrototype(this, BsuirNetworkError.prototype);\n this.name = \"BsuirNetworkError\";\n this.endpoint = endpoint;\n this.causeError = causeError;\n }\n}\n\nexport class BsuirTimeoutError extends Error {\n readonly endpoint: string;\n readonly timeoutMs: number;\n\n constructor(message: string, endpoint: string, timeoutMs: number) {\n super(message);\n fixErrorPrototype(this, BsuirTimeoutError.prototype);\n this.name = \"BsuirTimeoutError\";\n this.endpoint = endpoint;\n this.timeoutMs = timeoutMs;\n }\n}\n\nexport class BsuirValidationError extends Error {\n constructor(message: string) {\n super(message);\n fixErrorPrototype(this, BsuirValidationError.prototype);\n this.name = \"BsuirValidationError\";\n }\n}\n\nexport class BsuirConfigurationError extends Error {\n constructor(message: string) {\n super(message);\n fixErrorPrototype(this, BsuirConfigurationError.prototype);\n this.name = \"BsuirConfigurationError\";\n }\n}\n","type AbortSignalConstructor = typeof AbortSignal & {\n any?(signals: AbortSignal[]): AbortSignal;\n};\n\nconst AbortSignalCtor = AbortSignal as AbortSignalConstructor;\n\n/**\n * Combines an optional caller {@link AbortSignal} with a per-attempt timeout.\n * When `AbortSignal.any` exists at runtime, delegates to the platform implementation.\n * Otherwise uses a manual merge so the timeout still applies alongside a caller signal.\n */\nexport function mergeSignals(signal: AbortSignal | undefined, timeoutMs: number): AbortSignal {\n if (typeof AbortSignalCtor.any === \"function\") {\n const parts: AbortSignal[] = [AbortSignal.timeout(timeoutMs)];\n if (signal) {\n parts.push(signal);\n }\n return AbortSignalCtor.any(parts);\n }\n\n return mergeSignalsManual(signal, timeoutMs);\n}\n/** Used when `AbortSignal.any` is unavailable; exposed for unit tests. */\nexport function mergeSignalsManual(signal: AbortSignal | undefined, timeoutMs: number): AbortSignal {\n const combined = new AbortController();\n\n const onSignalAbort = (): void => {\n clearTimeout(timeoutId);\n combined.abort();\n };\n\n const timeoutId = setTimeout(() => {\n if (signal) {\n signal.removeEventListener(\"abort\", onSignalAbort);\n }\n combined.abort();\n }, timeoutMs);\n\n if (signal) {\n if (signal.aborted) {\n clearTimeout(timeoutId);\n combined.abort();\n } else {\n signal.addEventListener(\"abort\", onSignalAbort, { once: true });\n }\n }\n\n return combined.signal;\n}\n","import { BsuirValidationError } from \"../client/errors\";\n\nconst GROUP_NUMBER_PATTERN = /^\\d+$/;\nconst EMPLOYEE_URL_ID_PATTERN = /^[a-z0-9]+(?:-[a-z0-9]+)*$/i;\n\nexport function assertNonEmptyString(value: unknown, fieldName: string): asserts value is string {\n if (typeof value !== \"string\" || value.trim().length === 0) {\n throw new BsuirValidationError(`'${fieldName}' must be a non-empty string`);\n }\n}\n\nexport function assertPositiveInt(value: unknown, fieldName: string): asserts value is number {\n if (typeof value !== \"number\" || !Number.isInteger(value) || value <= 0) {\n throw new BsuirValidationError(`'${fieldName}' must be a positive integer`);\n }\n}\n\nexport function assertGroupNumber(value: unknown, fieldName = \"groupNumber\"): asserts value is string {\n assertNonEmptyString(value, fieldName);\n if (!GROUP_NUMBER_PATTERN.test(value)) {\n throw new BsuirValidationError(`'${fieldName}' must contain only digits`);\n }\n}\n\nexport function assertEmployeeUrlId(value: unknown, fieldName = \"urlId\"): asserts value is string {\n assertNonEmptyString(value, fieldName);\n if (!EMPLOYEE_URL_ID_PATTERN.test(value)) {\n throw new BsuirValidationError(\n `'${fieldName}' must be a valid slug (letters, digits, hyphen)`\n );\n }\n}\n\nexport function isAbortError(error: unknown): boolean {\n if (error instanceof DOMException && error.name === \"AbortError\") {\n return true;\n }\n\n if (typeof error === \"object\" && error !== null) {\n const maybeError = error as { name?: unknown; code?: unknown };\n return maybeError.name === \"AbortError\" || maybeError.code === \"ABORT_ERR\";\n }\n\n return false;\n}\n","import { BsuirApiError, BsuirNetworkError, BsuirTimeoutError } from \"./errors\";\nimport { mergeSignals } from \"./mergeSignals\";\nimport type { InternalClientConfig, QueryParams, RequestOptions } from \"./types\";\nimport { isAbortError } from \"../utils/guards\";\n\nconst RETRIABLE_STATUS_CODES = new Set([429, 500, 502, 503, 504]);\n\nfunction buildUrl(baseUrl: string, path: string, query?: QueryParams): string {\n const normalizedBase = baseUrl.endsWith(\"/\") ? baseUrl.slice(0, -1) : baseUrl;\n const normalizedPath = path.startsWith(\"/\") ? path : `/${path}`;\n const url = new URL(`${normalizedBase}${normalizedPath}`);\n\n if (query) {\n for (const [key, value] of Object.entries(query)) {\n if (value === undefined || value === null) {\n continue;\n }\n url.searchParams.set(key, String(value));\n }\n }\n\n return url.toString();\n}\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n\nfunction parseRetryAfterMs(retryAfter: string | null): number | null {\n if (!retryAfter) {\n return null;\n }\n\n const asSeconds = Number(retryAfter);\n if (!Number.isNaN(asSeconds)) {\n return Math.max(0, Math.floor(asSeconds * 1000));\n }\n\n const dateValue = Date.parse(retryAfter);\n if (!Number.isNaN(dateValue)) {\n return Math.max(0, dateValue - Date.now());\n }\n\n return null;\n}\n\nfunction getRetryDelayMs(\n config: InternalClientConfig,\n attempt: number,\n retryAfterHeader?: string | null\n): number {\n const retryAfterDelay = parseRetryAfterMs(retryAfterHeader ?? null);\n if (retryAfterDelay !== null) {\n return Math.min(retryAfterDelay, config.retryMaxDelayMs);\n }\n\n const exponent = Math.max(0, attempt);\n const baseDelay = Math.min(config.retryDelayMs * 2 ** exponent, config.retryMaxDelayMs);\n if (!config.retryJitter) {\n return baseDelay;\n }\n\n const jitterFactor = 0.75 + Math.random() * 0.5;\n return Math.floor(baseDelay * jitterFactor);\n}\n\nasync function parseBody(response: Response): Promise<unknown> {\n const contentType = response.headers.get(\"content-type\") ?? \"\";\n const declaredJson = contentType.includes(\"application/json\");\n const text = await response.text();\n if (text.length === 0) {\n if (declaredJson) {\n throw new BsuirApiError(\"Invalid JSON response payload\", response.status, response.url, null);\n }\n return \"\";\n }\n try {\n return JSON.parse(text) as unknown;\n } catch {\n if (declaredJson) {\n throw new BsuirApiError(\"Invalid JSON response payload\", response.status, response.url, null);\n }\n return text;\n }\n}\n\nexport async function requestJson<T>(\n config: InternalClientConfig,\n path: string,\n options: RequestOptions = {}\n): Promise<T> {\n const endpoint = buildUrl(config.baseUrl, path, options.query);\n const headers = new Headers({\n Accept: \"application/json\"\n });\n\n if (config.userAgent) {\n headers.set(\"User-Agent\", config.userAgent);\n }\n\n for (let attempt = 0; attempt <= config.retries; attempt += 1) {\n const requestSignal = mergeSignals(options.signal, config.timeoutMs);\n try {\n const response = await config.fetchImpl(endpoint, {\n method: \"GET\",\n headers,\n signal: requestSignal\n });\n\n if (!response.ok) {\n const errorBody = await parseBody(response);\n if (attempt < config.retries && RETRIABLE_STATUS_CODES.has(response.status)) {\n const delayMs = getRetryDelayMs(config, attempt, response.headers.get(\"retry-after\"));\n await sleep(delayMs);\n continue;\n }\n throw new BsuirApiError(\n `BSUIR API returned HTTP ${String(response.status)} for ${path}`,\n response.status,\n endpoint,\n errorBody\n );\n }\n\n return (await parseBody(response)) as T;\n } catch (error) {\n if (error instanceof BsuirApiError) {\n throw error;\n }\n\n if (isAbortError(error)) {\n if (options.signal?.aborted) {\n throw error;\n }\n throw new BsuirTimeoutError(\n `Request timed out after ${String(config.timeoutMs)}ms: ${path}`,\n endpoint,\n config.timeoutMs\n );\n }\n\n if (attempt < config.retries) {\n const delayMs = getRetryDelayMs(config, attempt);\n await sleep(delayMs);\n continue;\n }\n\n throw new BsuirNetworkError(`Network error while requesting ${path}`, endpoint, error);\n }\n }\n\n throw new BsuirNetworkError(`Unexpected retry loop termination for ${path}`, endpoint, null);\n}\n","import { BsuirApiError } from \"../client/errors\";\nimport { requestJson } from \"../client/http\";\nimport type { InternalClientConfig } from \"../client/types\";\nimport type { Announcement } from \"../types/announcement\";\nimport { assertEmployeeUrlId, assertPositiveInt } from \"../utils/guards\";\nimport type { ReadOptions } from \"./types\";\n\nconst ANNOUNCEMENT_EMPTY_LIST_STATUSES = new Set<number>([404, 400]);\n\nasync function requestAnnouncementList(\n config: InternalClientConfig,\n path: string,\n options: ReadOptions & { query: Record<string, string | number> }\n): Promise<Announcement[]> {\n try {\n return await requestJson<Announcement[]>(config, path, options);\n } catch (error) {\n if (error instanceof BsuirApiError && ANNOUNCEMENT_EMPTY_LIST_STATUSES.has(error.status)) {\n return [];\n }\n throw error;\n }\n}\n\nexport function createAnnouncementsModule(config: InternalClientConfig) {\n return {\n /**\n * Lists announcements for an employee. IIS may return HTTP `404` or `400` (no list / endpoint quirks); the SDK maps those to `[]`.\n */\n async byEmployee(urlId: string, options: ReadOptions = {}): Promise<Announcement[]> {\n assertEmployeeUrlId(urlId, \"urlId\");\n return requestAnnouncementList(config, \"/announcements/employees\", {\n ...options,\n query: { \"url-id\": urlId }\n });\n },\n\n /**\n * Lists announcements for a department. IIS may return HTTP `404` or `400` (no list / endpoint quirks); the SDK maps those to `[]`.\n */\n async byDepartment(id: number, options: ReadOptions = {}): Promise<Announcement[]> {\n assertPositiveInt(id, \"id\");\n return requestAnnouncementList(config, \"/announcements/departments\", {\n ...options,\n query: { id }\n });\n }\n };\n}\n","import type { InternalClientConfig } from \"../client/types\";\nimport { requestJson } from \"../client/http\";\nimport type { Auditory } from \"../types/catalog\";\nimport type { ReadOptions } from \"./types\";\n\nexport function createAuditoriesModule(config: InternalClientConfig) {\n return {\n /**\n * Returns the full list of auditories from `/auditories`.\n * If the caller aborts `options.signal`, the platform propagates `AbortError` (not wrapped by the SDK).\n *\n * @throws {BsuirApiError} When the API returns a non-success HTTP status\n * @throws {BsuirNetworkError} On transport failures after retries\n * @throws {BsuirTimeoutError} When the request exceeds `timeoutMs`\n */\n async listAll(options: ReadOptions = {}): Promise<Auditory[]> {\n return requestJson<Auditory[]>(config, \"/auditories\", {\n signal: options.signal\n });\n }\n };\n}\n","import type { InternalClientConfig } from \"../client/types\";\nimport { requestJson } from \"../client/http\";\nimport type { Department } from \"../types/catalog\";\nimport type { ReadOptions } from \"./types\";\n\nexport function createDepartmentsModule(config: InternalClientConfig) {\n return {\n /**\n * Returns the full list of departments from `/departments`.\n * If the caller aborts `options.signal`, the platform propagates `AbortError` (not wrapped by the SDK).\n *\n * @throws {BsuirApiError} When the API returns a non-success HTTP status\n * @throws {BsuirNetworkError} On transport failures after retries\n * @throws {BsuirTimeoutError} When the request exceeds `timeoutMs`\n */\n async listAll(options: ReadOptions = {}): Promise<Department[]> {\n return requestJson<Department[]>(config, \"/departments\", {\n signal: options.signal\n });\n }\n };\n}\n","import type { InternalClientConfig } from \"../client/types\";\nimport { requestJson } from \"../client/http\";\nimport type { EmployeeCatalogItem } from \"../types/employee\";\nimport type { ReadOptions } from \"./types\";\n\nexport function createEmployeesModule(config: InternalClientConfig) {\n return {\n /**\n * Returns the full list of employees from `/employees/all`.\n * If the caller aborts `options.signal`, the platform propagates `AbortError` (not wrapped by the SDK).\n *\n * @throws {BsuirApiError} When the API returns a non-success HTTP status\n * @throws {BsuirNetworkError} On transport failures after retries\n * @throws {BsuirTimeoutError} When the request exceeds `timeoutMs`\n */\n async listAll(options: ReadOptions = {}): Promise<EmployeeCatalogItem[]> {\n return requestJson<EmployeeCatalogItem[]>(config, \"/employees/all\", {\n signal: options.signal\n });\n }\n };\n}\n","import type { InternalClientConfig } from \"../client/types\";\nimport { requestJson } from \"../client/http\";\nimport type { Faculty } from \"../types/catalog\";\nimport type { ReadOptions } from \"./types\";\n\nexport function createFacultiesModule(config: InternalClientConfig) {\n return {\n /**\n * Returns the full list of faculties from `/faculties`.\n * If the caller aborts `options.signal`, the platform propagates `AbortError` (not wrapped by the SDK).\n *\n * @throws {BsuirApiError} When the API returns a non-success HTTP status\n * @throws {BsuirNetworkError} On transport failures after retries\n * @throws {BsuirTimeoutError} When the request exceeds `timeoutMs`\n */\n async listAll(options: ReadOptions = {}): Promise<Faculty[]> {\n return requestJson<Faculty[]>(config, \"/faculties\", {\n signal: options.signal\n });\n }\n };\n}\n","import type { InternalClientConfig } from \"../client/types\";\nimport { requestJson } from \"../client/http\";\nimport type { StudentGroupCatalogItem } from \"../types/catalog\";\nimport type { ReadOptions } from \"./types\";\n\nexport function createGroupsModule(config: InternalClientConfig) {\n return {\n /**\n * Returns the full list of student groups from `/student-groups`.\n * If the caller aborts `options.signal`, the platform propagates `AbortError` (not wrapped by the SDK).\n *\n * @throws {BsuirApiError} When the API returns a non-success HTTP status\n * @throws {BsuirNetworkError} On transport failures after retries\n * @throws {BsuirTimeoutError} When the request exceeds `timeoutMs`\n */\n async listAll(options: ReadOptions = {}): Promise<StudentGroupCatalogItem[]> {\n return requestJson<StudentGroupCatalogItem[]>(config, \"/student-groups\", {\n signal: options.signal\n });\n }\n };\n}\n","import { BsuirValidationError } from \"../client/errors\";\nimport { assertPositiveInt } from \"./guards\";\n\n/**\n * Normalizes current week payload from API to a positive integer.\n * API can return plain text (`\"1\\n\"`) or number.\n */\nexport function parseCurrentWeek(payload: unknown): number {\n if (typeof payload === \"number\") {\n assertPositiveInt(payload, \"currentWeek\");\n return payload;\n }\n\n if (typeof payload === \"string\") {\n const normalized = payload.trim();\n if (normalized.length > 0) {\n const parsed = Number(normalized);\n if (Number.isInteger(parsed)) {\n assertPositiveInt(parsed, \"currentWeek\");\n return parsed;\n }\n }\n }\n\n if (typeof payload === \"object\" && payload !== null) {\n const record = payload as Record<string, unknown>;\n if (\"weekNumber\" in record) {\n return parseCurrentWeek(record.weekNumber);\n }\n if (\"currentWeek\" in record) {\n return parseCurrentWeek(record.currentWeek);\n }\n }\n\n throw new BsuirValidationError(\"'currentWeek' response payload must be a positive integer\");\n}\n","import type { InternalClientConfig } from \"../client/types\";\nimport { requestJson } from \"../client/http\";\nimport { assertEmployeeUrlId, assertGroupNumber, assertPositiveInt } from \"../utils/guards\";\nimport type {\n FlattenedLessonsByDay,\n FlattenedScheduleItem,\n NormalizedScheduleResponse,\n ScheduleFilterOptions,\n ScheduleItem,\n ScheduleResponse\n} from \"../types/schedule\";\nimport type { ApiDateResponse } from \"../types/common\";\nimport type { Weekday } from \"../types/common\";\nimport type { ReadOptions } from \"./types\";\nimport { parseCurrentWeek } from \"../utils/week\";\n\nconst WEEKDAYS: Weekday[] = [\n \"Понедельник\",\n \"Вторник\",\n \"Среда\",\n \"Четверг\",\n \"Пятница\",\n \"Суббота\"\n];\n\nfunction lessonAuditories(item: ScheduleItem): string[] {\n const { auditories } = item;\n return Array.isArray(auditories) ? auditories : [];\n}\n\nfunction normalizeSchedule(response: ScheduleResponse): NormalizedScheduleResponse {\n const lessons: FlattenedScheduleItem[] = [];\n const lessonsByDay: FlattenedLessonsByDay = {};\n const safeSchedules = response.schedules ?? {};\n const safeExams = response.exams ?? [];\n for (const day of WEEKDAYS) {\n const dayItems = safeSchedules[day] ?? [];\n const flattenedDayItems = dayItems.map((item) => ({\n ...item,\n auditories: lessonAuditories(item),\n day,\n source: \"schedules\" as const\n }));\n lessonsByDay[day] = flattenedDayItems;\n for (const item of dayItems) {\n lessons.push({\n ...item,\n auditories: lessonAuditories(item),\n day,\n source: \"schedules\"\n });\n }\n }\n\n for (const exam of safeExams) {\n lessons.push({\n ...exam,\n auditories: lessonAuditories(exam),\n day: null,\n // Exams are not grouped by weekday in API response.\n source: \"exams\"\n });\n }\n\n const scheduleLessons = lessons.filter((lesson) => lesson.source === \"schedules\");\n const examLessons = lessons.filter((lesson) => lesson.source === \"exams\");\n\n return {\n ...response,\n schedules: safeSchedules,\n exams: safeExams,\n lessons,\n lessonsByDay,\n scheduleLessons,\n examLessons\n };\n}\n\nfunction matchesFilter(item: FlattenedScheduleItem, filter: ScheduleFilterOptions): boolean {\n if (filter.source && item.source !== filter.source) {\n return false;\n }\n\n if (filter.weekday && item.day !== filter.weekday) {\n return false;\n }\n\n if (typeof filter.weekNumber === \"number\") {\n if (!Array.isArray(item.weekNumber) || !item.weekNumber.includes(filter.weekNumber)) {\n return false;\n }\n }\n\n if (typeof filter.subgroup === \"number\" && item.numSubgroup !== filter.subgroup) {\n return false;\n }\n\n if (filter.lessonTypeAbbrev) {\n const types = Array.isArray(filter.lessonTypeAbbrev)\n ? filter.lessonTypeAbbrev\n : [filter.lessonTypeAbbrev];\n if (!item.lessonTypeAbbrev || !types.includes(item.lessonTypeAbbrev)) {\n return false;\n }\n }\n\n if (filter.subjectQuery) {\n const query = filter.subjectQuery.toLowerCase();\n const haystack = `${item.subject} ${item.subjectFullName} ${item.note ?? \"\"}`.toLowerCase();\n if (!haystack.includes(query)) {\n return false;\n }\n }\n\n if (filter.employeeUrlId) {\n const employeeMatch = item.employees?.some((employee) => employee.urlId === filter.employeeUrlId);\n if (!employeeMatch) {\n return false;\n }\n }\n\n if (filter.auditory && !lessonAuditories(item).includes(filter.auditory)) {\n return false;\n }\n\n return true;\n}\n\nfunction filterLessons(\n response: NormalizedScheduleResponse,\n filter: ScheduleFilterOptions\n): FlattenedScheduleItem[] {\n return response.lessons.filter((item) => matchesFilter(item, filter));\n}\n\nexport function createScheduleModule(config: InternalClientConfig) {\n /**\n * Returns schedule for a student group.\n * By default returns normalized payload, unless `raw: true` is passed.\n */\n async function getGroup<TRaw extends boolean | undefined = undefined>(\n groupNumber: string,\n options: ReadOptions & { raw?: TRaw } = {}\n ): Promise<TRaw extends true ? ScheduleResponse : NormalizedScheduleResponse> {\n assertGroupNumber(groupNumber, \"groupNumber\");\n const response = await requestJson<ScheduleResponse>(config, \"/schedule\", {\n query: { studentGroup: groupNumber },\n signal: options.signal\n });\n const result = options.raw ?? config.defaultRaw ? response : normalizeSchedule(response);\n return result as TRaw extends true ? ScheduleResponse : NormalizedScheduleResponse;\n }\n\n /**\n * Returns schedule for an employee.\n * By default returns normalized payload, unless `raw: true` is passed.\n */\n async function getEmployee<TRaw extends boolean | undefined = undefined>(\n urlId: string,\n options: ReadOptions & { raw?: TRaw } = {}\n ): Promise<TRaw extends true ? ScheduleResponse : NormalizedScheduleResponse> {\n assertEmployeeUrlId(urlId, \"urlId\");\n const response = await requestJson<ScheduleResponse>(\n config,\n `/employees/schedule/${encodeURIComponent(urlId)}`,\n {\n signal: options.signal\n }\n );\n const result = options.raw ?? config.defaultRaw ? response : normalizeSchedule(response);\n return result as TRaw extends true ? ScheduleResponse : NormalizedScheduleResponse;\n }\n\n /**\n * Returns filtered schedule items for a group from normalized schedule payload.\n */\n async function getGroupFiltered(\n groupNumber: string,\n filter: ScheduleFilterOptions,\n options: ReadOptions = {}\n ): Promise<FlattenedScheduleItem[]> {\n const normalized = await getGroup(groupNumber, { ...options, raw: false });\n return filterLessons(normalized, filter);\n }\n\n /**\n * Returns filtered schedule items for an employee from normalized schedule payload.\n */\n async function getEmployeeFiltered(\n urlId: string,\n filter: ScheduleFilterOptions,\n options: ReadOptions = {}\n ): Promise<FlattenedScheduleItem[]> {\n const normalized = await getEmployee(urlId, { ...options, raw: false });\n return filterLessons(normalized, filter);\n }\n\n async function getCurrentWeek(options: ReadOptions = {}): Promise<number> {\n const payload = await requestJson<unknown>(config, \"/schedule/current-week\", {\n signal: options.signal\n });\n return parseCurrentWeek(payload);\n }\n\n return {\n getGroup,\n getEmployee,\n getGroupFiltered,\n getEmployeeFiltered,\n\n async getGroupExams(groupNumber: string, options: ReadOptions = {}): Promise<FlattenedScheduleItem[]> {\n return getGroupFiltered(groupNumber, { source: \"exams\" }, options);\n },\n\n async getEmployeeExams(urlId: string, options: ReadOptions = {}): Promise<FlattenedScheduleItem[]> {\n return getEmployeeFiltered(urlId, { source: \"exams\" }, options);\n },\n\n async getGroupBySubgroup(\n groupNumber: string,\n subgroup: number,\n options: ReadOptions = {}\n ): Promise<FlattenedScheduleItem[]> {\n assertPositiveInt(subgroup, \"subgroup\");\n return getGroupFiltered(groupNumber, { source: \"schedules\", subgroup }, options);\n },\n\n async getEmployeeBySubgroup(\n urlId: string,\n subgroup: number,\n options: ReadOptions = {}\n ): Promise<FlattenedScheduleItem[]> {\n assertPositiveInt(subgroup, \"subgroup\");\n return getEmployeeFiltered(urlId, { source: \"schedules\", subgroup }, options);\n },\n\n getCurrentWeek,\n\n /**\n * Calls IIS `/last-update-date/student-group`. That route is legacy and unsupported on the server;\n * it may return an error for newer group numbers (e.g. six-digit `524404`).\n */\n async getLastUpdateByGroup(\n params: { groupNumber: string } | { id: number },\n options: ReadOptions = {}\n ): Promise<ApiDateResponse> {\n let query: Record<string, string | number>;\n if (\"groupNumber\" in params) {\n assertGroupNumber(params.groupNumber, \"groupNumber\");\n query = { groupNumber: params.groupNumber };\n } else {\n assertPositiveInt(params.id, \"id\");\n query = { id: params.id };\n }\n return requestJson<ApiDateResponse>(config, \"/last-update-date/student-group\", {\n query,\n signal: options.signal\n });\n },\n\n /**\n * Calls IIS `/last-update-date/employee`. That route is legacy and unsupported on the server; prefer\n * not relying on it for critical cache logic.\n */\n async getLastUpdateByEmployee(\n params: { urlId: string } | { id: number },\n options: ReadOptions = {}\n ): Promise<ApiDateResponse> {\n let query: Record<string, string | number>;\n if (\"urlId\" in params) {\n assertEmployeeUrlId(params.urlId, \"urlId\");\n query = { \"url-id\": params.urlId };\n } else {\n assertPositiveInt(params.id, \"id\");\n query = { id: params.id };\n }\n return requestJson<ApiDateResponse>(config, \"/last-update-date/employee\", {\n query,\n signal: options.signal\n });\n }\n };\n}\n","import type { InternalClientConfig } from \"../client/types\";\nimport { requestJson } from \"../client/http\";\nimport type { Speciality } from \"../types/catalog\";\nimport type { ReadOptions } from \"./types\";\n\nexport function createSpecialitiesModule(config: InternalClientConfig) {\n return {\n /**\n * Returns the full list of specialities from `/specialities`.\n * If the caller aborts `options.signal`, the platform propagates `AbortError` (not wrapped by the SDK).\n *\n * @throws {BsuirApiError} When the API returns a non-success HTTP status\n * @throws {BsuirNetworkError} On transport failures after retries\n * @throws {BsuirTimeoutError} When the request exceeds `timeoutMs`\n */\n async listAll(options: ReadOptions = {}): Promise<Speciality[]> {\n return requestJson<Speciality[]>(config, \"/specialities\", {\n signal: options.signal\n });\n }\n };\n}\n","import { BsuirConfigurationError } from \"./errors\";\nimport type { BsuirClientOptions, InternalClientConfig } from \"./types\";\nimport { createAnnouncementsModule } from \"../modules/announcements\";\nimport { createAuditoriesModule } from \"../modules/auditories\";\nimport { createDepartmentsModule } from \"../modules/departments\";\nimport { createEmployeesModule } from \"../modules/employees\";\nimport { createFacultiesModule } from \"../modules/faculties\";\nimport { createGroupsModule } from \"../modules/groups\";\nimport { createScheduleModule } from \"../modules/schedule\";\nimport { createSpecialitiesModule } from \"../modules/specialities\";\n\nconst DEFAULT_BASE_URL = \"https://iis.bsuir.by/api/v1\";\n\nfunction resolveFetch(customFetch?: typeof globalThis.fetch): typeof globalThis.fetch {\n if (customFetch) {\n return customFetch;\n }\n\n if (typeof globalThis.fetch !== \"function\") {\n throw new BsuirConfigurationError(\n \"Global fetch is unavailable. Provide 'fetch' in createBsuirClient options.\"\n );\n }\n\n return globalThis.fetch;\n}\n\nfunction createInternalConfig(options: BsuirClientOptions = {}): InternalClientConfig {\n return {\n baseUrl: options.baseUrl ?? DEFAULT_BASE_URL,\n fetchImpl: resolveFetch(options.fetch),\n timeoutMs: options.timeoutMs ?? 10_000,\n retries: options.retries ?? 1,\n retryDelayMs: options.retryDelayMs ?? 300,\n retryMaxDelayMs: options.retryMaxDelayMs ?? 3_000,\n retryJitter: options.retryJitter ?? true,\n userAgent: options.userAgent,\n defaultRaw: options.defaultRaw ?? false\n };\n}\n\n/**\n * Creates a configured BSUIR IIS API client.\n */\nexport function createBsuirClient(options: BsuirClientOptions = {}) {\n const config = createInternalConfig(options);\n const schedule = createScheduleModule(config);\n\n return {\n schedule,\n groups: createGroupsModule(config),\n employees: createEmployeesModule(config),\n faculties: createFacultiesModule(config),\n departments: createDepartmentsModule(config),\n specialities: createSpecialitiesModule(config),\n announcements: createAnnouncementsModule(config),\n auditories: createAuditoriesModule(config)\n };\n}\n\n/**\n * Public client contract returned by {@link createBsuirClient}.\n */\nexport type BsuirClient = ReturnType<typeof createBsuirClient>;\n"],"mappings":"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","names":[]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "bsuir-iis-api",
3
- "version": "0.6.7",
3
+ "version": "0.7.0",
4
4
  "description": "Type-safe ESM SDK for BSUIR IIS API",
5
5
  "type": "module",
6
6
  "author": "kotru21",
@@ -22,7 +22,7 @@
22
22
  "typescript"
23
23
  ],
24
24
  "engines": {
25
- "node": ">=24"
25
+ "node": ">=20.0.0"
26
26
  },
27
27
  "exports": {
28
28
  ".": {