bsuir-iis-api 0.6.6 → 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,35 @@ 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
+
28
+ ## [0.6.7] - 2026-04-02
29
+
30
+ ### Changed
31
+
32
+ - Dev tooling: bumped TypeScript to 6.x, `@typescript-eslint/*` and `typescript-eslint` to ^8.58.0, `vitest` and `@vitest/coverage-v8` to ^4.1.2; added `@microsoft/api-extractor` for declaration emit; regenerated `package-lock.json`.
33
+ - Build: enable tsup [`experimentalDts`](https://tsup.egoist.dev/) (API Extractor) instead of the default DTS plugin so declaration builds work on TypeScript 6 without relying on deprecated `baseUrl` injection.
34
+ - Dev: npm [`overrides`](https://docs.npmjs.com/cli/v10/configuring-npm/package-json#overrides) pin transitive `lodash` to ^4.17.24 so `npm audit` stays clean with `@microsoft/api-extractor`.
35
+
36
+ ### Documentation
37
+
38
+ - README: note on `experimentalDts` / API Extractor and TypeScript [`paths` without `baseUrl`](https://www.typescriptlang.org/docs/handbook/modules/reference.html).
39
+
11
40
  ## [0.6.6] - 2026-03-23
12
41
 
13
42
  ### 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
 
@@ -144,6 +153,8 @@ npm run check
144
153
  npm run build
145
154
  ```
146
155
 
156
+ `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.
157
+
147
158
  Linting uses ESLint flat config with strict type-aware TypeScript rules for `src`,
148
159
  plus test-specific overrides for `test` and `vitest.config.ts`.
149
160
 
@@ -0,0 +1,591 @@
1
+ import { Options } from 'tsup';
2
+ import { UserConfig } from 'vite';
3
+
4
+ declare interface Announcement {
5
+ id: number;
6
+ employee: string;
7
+ content: string;
8
+ date: string;
9
+ employeeDepartments: string[];
10
+ studentGroups: StudentGroupShort[];
11
+ }
12
+ export { Announcement }
13
+ export { Announcement as Announcement_alias_1 }
14
+ export { Announcement as Announcement_alias_2 }
15
+
16
+ /** Payload from IIS legacy `last-update-date/*` endpoints (`schedule.getLastUpdateByGroup` / `getLastUpdateByEmployee`). */
17
+ declare interface ApiDateResponse {
18
+ lastUpdateDate: string;
19
+ }
20
+ export { ApiDateResponse }
21
+ export { ApiDateResponse as ApiDateResponse_alias_1 }
22
+ export { ApiDateResponse as ApiDateResponse_alias_2 }
23
+
24
+ export declare function assertEmployeeUrlId(value: unknown, fieldName?: string): asserts value is string;
25
+
26
+ export declare function assertGroupNumber(value: unknown, fieldName?: string): asserts value is string;
27
+
28
+ export declare function assertNonEmptyString(value: unknown, fieldName: string): asserts value is string;
29
+
30
+ export declare function assertPositiveInt(value: unknown, fieldName: string): asserts value is number;
31
+
32
+ declare interface Auditory {
33
+ id: number;
34
+ name: string;
35
+ note: string;
36
+ capacity: number | null;
37
+ auditoryType: AuditoryType;
38
+ buildingNumber: BuildingNumber;
39
+ department: AuditoryDepartment;
40
+ }
41
+ export { Auditory }
42
+ export { Auditory as Auditory_alias_1 }
43
+ export { Auditory as Auditory_alias_2 }
44
+
45
+ declare interface AuditoryDepartment {
46
+ idDepartment: number;
47
+ abbrev: string;
48
+ name: string;
49
+ nameAndAbbrev: string;
50
+ }
51
+ export { AuditoryDepartment }
52
+ export { AuditoryDepartment as AuditoryDepartment_alias_1 }
53
+ export { AuditoryDepartment as AuditoryDepartment_alias_2 }
54
+
55
+ declare interface AuditoryType {
56
+ id: number;
57
+ name: string;
58
+ abbrev: string;
59
+ }
60
+ export { AuditoryType }
61
+ export { AuditoryType as AuditoryType_alias_1 }
62
+ export { AuditoryType as AuditoryType_alias_2 }
63
+
64
+ declare class BsuirApiError extends Error {
65
+ readonly status: number;
66
+ readonly endpoint: string;
67
+ readonly body: unknown;
68
+ constructor(message: string, status: number, endpoint: string, body: unknown);
69
+ }
70
+ export { BsuirApiError }
71
+ export { BsuirApiError as BsuirApiError_alias_1 }
72
+
73
+ /**
74
+ * Public client contract returned by {@link createBsuirClient}.
75
+ */
76
+ declare type BsuirClient = ReturnType<typeof createBsuirClient>;
77
+ export { BsuirClient }
78
+ export { BsuirClient as BsuirClient_alias_1 }
79
+
80
+ /**
81
+ * Options accepted by {@link createBsuirClient}.
82
+ */
83
+ declare interface BsuirClientOptions {
84
+ baseUrl?: string;
85
+ fetch?: typeof globalThis.fetch;
86
+ /** Request timeout per attempt, in milliseconds. */
87
+ timeoutMs?: number;
88
+ /** Number of retry attempts for retriable GET failures. */
89
+ retries?: number;
90
+ /** Base retry delay before backoff, in milliseconds. */
91
+ retryDelayMs?: number;
92
+ /** Upper bound for retry delay, in milliseconds. */
93
+ retryMaxDelayMs?: number;
94
+ /** Enable jitter for retry backoff to avoid synchronized retries. */
95
+ retryJitter?: boolean;
96
+ /** Optional User-Agent header (used mainly in Node.js runtimes). */
97
+ userAgent?: string;
98
+ /** Force raw API payload for schedule endpoints by default. */
99
+ defaultRaw?: boolean;
100
+ }
101
+ export { BsuirClientOptions }
102
+ export { BsuirClientOptions as BsuirClientOptions_alias_1 }
103
+
104
+ declare class BsuirConfigurationError extends Error {
105
+ constructor(message: string);
106
+ }
107
+ export { BsuirConfigurationError }
108
+ export { BsuirConfigurationError as BsuirConfigurationError_alias_1 }
109
+
110
+ declare class BsuirNetworkError extends Error {
111
+ readonly endpoint: string;
112
+ readonly causeError: unknown;
113
+ constructor(message: string, endpoint: string, causeError: unknown);
114
+ }
115
+ export { BsuirNetworkError }
116
+ export { BsuirNetworkError as BsuirNetworkError_alias_1 }
117
+
118
+ declare class BsuirTimeoutError extends Error {
119
+ readonly endpoint: string;
120
+ readonly timeoutMs: number;
121
+ constructor(message: string, endpoint: string, timeoutMs: number);
122
+ }
123
+ export { BsuirTimeoutError }
124
+ export { BsuirTimeoutError as BsuirTimeoutError_alias_1 }
125
+
126
+ declare class BsuirValidationError extends Error {
127
+ constructor(message: string);
128
+ }
129
+ export { BsuirValidationError }
130
+ export { BsuirValidationError as BsuirValidationError_alias_1 }
131
+
132
+ declare interface BuildingNumber {
133
+ id: number;
134
+ name: string;
135
+ }
136
+ export { BuildingNumber }
137
+ export { BuildingNumber as BuildingNumber_alias_1 }
138
+ export { BuildingNumber as BuildingNumber_alias_2 }
139
+
140
+ export declare function createAnnouncementsModule(config: InternalClientConfig): {
141
+ /**
142
+ * Lists announcements for an employee. IIS may return HTTP `404` or `400` (no list / endpoint quirks); the SDK maps those to `[]`.
143
+ */
144
+ byEmployee(urlId: string, options?: ReadOptions): Promise<Announcement[]>;
145
+ /**
146
+ * Lists announcements for a department. IIS may return HTTP `404` or `400` (no list / endpoint quirks); the SDK maps those to `[]`.
147
+ */
148
+ byDepartment(id: number, options?: ReadOptions): Promise<Announcement[]>;
149
+ };
150
+
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
+ */
160
+ listAll(options?: ReadOptions): Promise<Auditory[]>;
161
+ };
162
+
163
+ /**
164
+ * Creates a configured BSUIR IIS API client.
165
+ */
166
+ declare function createBsuirClient(options?: BsuirClientOptions): {
167
+ schedule: {
168
+ getGroup: <TRaw extends boolean | undefined = undefined>(groupNumber: string, options?: ReadOptions & {
169
+ raw?: TRaw;
170
+ }) => Promise<TRaw extends true ? ScheduleResponse : NormalizedScheduleResponse>;
171
+ getEmployee: <TRaw extends boolean | undefined = undefined>(urlId: string, options?: ReadOptions & {
172
+ raw?: TRaw;
173
+ }) => Promise<TRaw extends true ? ScheduleResponse : NormalizedScheduleResponse>;
174
+ getGroupFiltered: (groupNumber: string, filter: ScheduleFilterOptions, options?: ReadOptions) => Promise<FlattenedScheduleItem[]>;
175
+ getEmployeeFiltered: (urlId: string, filter: ScheduleFilterOptions, options?: ReadOptions) => Promise<FlattenedScheduleItem[]>;
176
+ getGroupExams(groupNumber: string, options?: ReadOptions): Promise<FlattenedScheduleItem[]>;
177
+ getEmployeeExams(urlId: string, options?: ReadOptions): Promise<FlattenedScheduleItem[]>;
178
+ getGroupBySubgroup(groupNumber: string, subgroup: number, options?: ReadOptions): Promise<FlattenedScheduleItem[]>;
179
+ getEmployeeBySubgroup(urlId: string, subgroup: number, options?: ReadOptions): Promise<FlattenedScheduleItem[]>;
180
+ getCurrentWeek: (options?: ReadOptions) => Promise<number>;
181
+ getLastUpdateByGroup(params: {
182
+ groupNumber: string;
183
+ } | {
184
+ id: number;
185
+ }, options?: ReadOptions): Promise<ApiDateResponse>;
186
+ getLastUpdateByEmployee(params: {
187
+ urlId: string;
188
+ } | {
189
+ id: number;
190
+ }, options?: ReadOptions): Promise<ApiDateResponse>;
191
+ };
192
+ groups: {
193
+ listAll(options?: ReadOptions): Promise<StudentGroupCatalogItem[]>;
194
+ };
195
+ employees: {
196
+ listAll(options?: ReadOptions): Promise<EmployeeCatalogItem[]>;
197
+ };
198
+ faculties: {
199
+ listAll(options?: ReadOptions): Promise<Faculty[]>;
200
+ };
201
+ departments: {
202
+ listAll(options?: ReadOptions): Promise<Department[]>;
203
+ };
204
+ specialities: {
205
+ listAll(options?: ReadOptions): Promise<Speciality[]>;
206
+ };
207
+ announcements: {
208
+ byEmployee(urlId: string, options?: ReadOptions): Promise<Announcement[]>;
209
+ byDepartment(id: number, options?: ReadOptions): Promise<Announcement[]>;
210
+ };
211
+ auditories: {
212
+ listAll(options?: ReadOptions): Promise<Auditory[]>;
213
+ };
214
+ };
215
+ export { createBsuirClient }
216
+ export { createBsuirClient as createBsuirClient_alias_1 }
217
+
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
+ */
227
+ listAll(options?: ReadOptions): Promise<Department[]>;
228
+ };
229
+
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
+ */
239
+ listAll(options?: ReadOptions): Promise<EmployeeCatalogItem[]>;
240
+ };
241
+
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
+ */
251
+ listAll(options?: ReadOptions): Promise<Faculty[]>;
252
+ };
253
+
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
+ */
263
+ listAll(options?: ReadOptions): Promise<StudentGroupCatalogItem[]>;
264
+ };
265
+
266
+ export declare function createJsonResponse({ status, headers, body }: MockResponseInit): Response;
267
+
268
+ export declare function createScheduleModule(config: InternalClientConfig): {
269
+ getGroup: <TRaw extends boolean | undefined = undefined>(groupNumber: string, options?: ReadOptions & {
270
+ raw?: TRaw;
271
+ }) => Promise<TRaw extends true ? ScheduleResponse : NormalizedScheduleResponse>;
272
+ getEmployee: <TRaw extends boolean | undefined = undefined>(urlId: string, options?: ReadOptions & {
273
+ raw?: TRaw;
274
+ }) => Promise<TRaw extends true ? ScheduleResponse : NormalizedScheduleResponse>;
275
+ getGroupFiltered: (groupNumber: string, filter: ScheduleFilterOptions, options?: ReadOptions) => Promise<FlattenedScheduleItem[]>;
276
+ getEmployeeFiltered: (urlId: string, filter: ScheduleFilterOptions, options?: ReadOptions) => Promise<FlattenedScheduleItem[]>;
277
+ getGroupExams(groupNumber: string, options?: ReadOptions): Promise<FlattenedScheduleItem[]>;
278
+ getEmployeeExams(urlId: string, options?: ReadOptions): Promise<FlattenedScheduleItem[]>;
279
+ getGroupBySubgroup(groupNumber: string, subgroup: number, options?: ReadOptions): Promise<FlattenedScheduleItem[]>;
280
+ getEmployeeBySubgroup(urlId: string, subgroup: number, options?: ReadOptions): Promise<FlattenedScheduleItem[]>;
281
+ getCurrentWeek: (options?: ReadOptions) => Promise<number>;
282
+ /**
283
+ * Calls IIS `/last-update-date/student-group`. That route is legacy and unsupported on the server;
284
+ * it may return an error for newer group numbers (e.g. six-digit `524404`).
285
+ */
286
+ getLastUpdateByGroup(params: {
287
+ groupNumber: string;
288
+ } | {
289
+ id: number;
290
+ }, options?: ReadOptions): Promise<ApiDateResponse>;
291
+ /**
292
+ * Calls IIS `/last-update-date/employee`. That route is legacy and unsupported on the server; prefer
293
+ * not relying on it for critical cache logic.
294
+ */
295
+ getLastUpdateByEmployee(params: {
296
+ urlId: string;
297
+ } | {
298
+ id: number;
299
+ }, options?: ReadOptions): Promise<ApiDateResponse>;
300
+ };
301
+
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
+ */
311
+ listAll(options?: ReadOptions): Promise<Speciality[]>;
312
+ };
313
+
314
+ export declare const default_alias: Options | Options[] | ((overrideOptions: Options) => Options | Options[] | Promise<Options | Options[]>);
315
+
316
+ export declare const default_alias_1: UserConfig;
317
+
318
+ declare interface Department {
319
+ id: number;
320
+ name: string;
321
+ abbrev: string;
322
+ }
323
+ export { Department }
324
+ export { Department as Department_alias_1 }
325
+ export { Department as Department_alias_2 }
326
+
327
+ declare interface EducationForm {
328
+ id: number;
329
+ name: string;
330
+ }
331
+ export { EducationForm }
332
+ export { EducationForm as EducationForm_alias_1 }
333
+ export { EducationForm as EducationForm_alias_2 }
334
+
335
+ declare interface Employee {
336
+ firstName: string;
337
+ lastName: string;
338
+ middleName: string;
339
+ degree: string;
340
+ degreeAbbrev?: string;
341
+ email: Maybe<string>;
342
+ rank: Maybe<string>;
343
+ photoLink: string;
344
+ calendarId: string;
345
+ id: number;
346
+ urlId: string;
347
+ jobPositions: Maybe<string[]>;
348
+ }
349
+ export { Employee }
350
+ export { Employee as Employee_alias_1 }
351
+ export { Employee as Employee_alias_2 }
352
+
353
+ declare interface EmployeeCatalogItem {
354
+ firstName: string;
355
+ lastName: string;
356
+ middleName: string;
357
+ degree: string;
358
+ rank: string;
359
+ photoLink: string;
360
+ calendarId: string;
361
+ academicDepartment?: string[];
362
+ id: number;
363
+ urlId: string;
364
+ fio: string;
365
+ }
366
+ export { EmployeeCatalogItem }
367
+ export { EmployeeCatalogItem as EmployeeCatalogItem_alias_1 }
368
+ export { EmployeeCatalogItem as EmployeeCatalogItem_alias_2 }
369
+
370
+ declare interface Faculty {
371
+ id: number;
372
+ name: string;
373
+ abbrev: string;
374
+ }
375
+ export { Faculty }
376
+ export { Faculty as Faculty_alias_1 }
377
+ export { Faculty as Faculty_alias_2 }
378
+
379
+ declare type FlattenedLessonsByDay = Partial<Record<Weekday, FlattenedScheduleItem[]>>;
380
+ export { FlattenedLessonsByDay }
381
+ export { FlattenedLessonsByDay as FlattenedLessonsByDay_alias_1 }
382
+ export { FlattenedLessonsByDay as FlattenedLessonsByDay_alias_2 }
383
+
384
+ declare interface FlattenedScheduleItem extends ScheduleItem {
385
+ day: Weekday | null;
386
+ source: "schedules" | "exams";
387
+ }
388
+ export { FlattenedScheduleItem }
389
+ export { FlattenedScheduleItem as FlattenedScheduleItem_alias_1 }
390
+ export { FlattenedScheduleItem as FlattenedScheduleItem_alias_2 }
391
+
392
+ export declare interface InternalClientConfig {
393
+ baseUrl: string;
394
+ fetchImpl: typeof globalThis.fetch;
395
+ timeoutMs: number;
396
+ retries: number;
397
+ retryDelayMs: number;
398
+ retryMaxDelayMs: number;
399
+ retryJitter: boolean;
400
+ userAgent: string | undefined;
401
+ defaultRaw: boolean;
402
+ }
403
+
404
+ export declare function isAbortError(error: unknown): boolean;
405
+
406
+ declare interface LessonStudentGroup {
407
+ specialityName: string;
408
+ specialityCode: string;
409
+ numberOfStudents: number;
410
+ name: string;
411
+ educationDegree: number;
412
+ }
413
+ export { LessonStudentGroup }
414
+ export { LessonStudentGroup as LessonStudentGroup_alias_1 }
415
+ export { LessonStudentGroup as LessonStudentGroup_alias_2 }
416
+
417
+ declare type Maybe<T> = T | null;
418
+ export { Maybe }
419
+ export { Maybe as Maybe_alias_1 }
420
+ export { Maybe as Maybe_alias_2 }
421
+
422
+ /**
423
+ * Combines an optional caller {@link AbortSignal} with a per-attempt timeout.
424
+ * When `AbortSignal.any` exists at runtime, delegates to the platform implementation.
425
+ * Otherwise uses a manual merge so the timeout still applies alongside a caller signal.
426
+ */
427
+ export declare function mergeSignals(signal: AbortSignal | undefined, timeoutMs: number): AbortSignal;
428
+
429
+ /** Used when `AbortSignal.any` is unavailable; exposed for unit tests. */
430
+ export declare function mergeSignalsManual(signal: AbortSignal | undefined, timeoutMs: number): AbortSignal;
431
+
432
+ export declare function mockFetchSequence(responses: Array<Response | Error>): typeof globalThis.fetch;
433
+
434
+ export declare interface MockResponseInit {
435
+ status?: number;
436
+ headers?: HeadersInit;
437
+ body: unknown;
438
+ }
439
+
440
+ declare interface NormalizedScheduleResponse extends Omit<ScheduleResponse, "schedules" | "exams"> {
441
+ schedules: WeekScheduleMap;
442
+ exams: ScheduleItem[];
443
+ lessons: FlattenedScheduleItem[];
444
+ lessonsByDay: FlattenedLessonsByDay;
445
+ scheduleLessons: FlattenedScheduleItem[];
446
+ examLessons: FlattenedScheduleItem[];
447
+ }
448
+ export { NormalizedScheduleResponse }
449
+ export { NormalizedScheduleResponse as NormalizedScheduleResponse_alias_1 }
450
+ export { NormalizedScheduleResponse as NormalizedScheduleResponse_alias_2 }
451
+
452
+ /**
453
+ * Normalizes current week payload from API to a positive integer.
454
+ * API can return plain text (`"1\n"`) or number.
455
+ */
456
+ export declare function parseCurrentWeek(payload: unknown): number;
457
+
458
+ export declare function parseDdMmYyyy(value: string | null): Date | null;
459
+
460
+ export declare type QueryParams = Record<string, QueryValue>;
461
+
462
+ export declare type QueryValue = string | number | boolean | null | undefined;
463
+
464
+ /**
465
+ * Read options used by all module methods.
466
+ */
467
+ declare interface ReadOptions extends RequestOptions {
468
+ /**
469
+ * When true, return raw API payload where supported.
470
+ */
471
+ raw?: boolean;
472
+ }
473
+ export { ReadOptions }
474
+ export { ReadOptions as ReadOptions_alias_1 }
475
+
476
+ export declare function requestJson<T>(config: InternalClientConfig, path: string, options?: RequestOptions): Promise<T>;
477
+
478
+ /**
479
+ * Common request options shared by read-only API methods.
480
+ */
481
+ declare interface RequestOptions {
482
+ /**
483
+ * Query parameters appended to endpoint URL.
484
+ */
485
+ query?: QueryParams | undefined;
486
+ /**
487
+ * Optional signal to cancel request from the caller side.
488
+ */
489
+ signal?: AbortSignal | undefined;
490
+ }
491
+ export { RequestOptions }
492
+ export { RequestOptions as RequestOptions_alias_1 }
493
+
494
+ declare interface ScheduleFilterOptions {
495
+ source?: "schedules" | "exams";
496
+ weekday?: Weekday;
497
+ weekNumber?: number;
498
+ subgroup?: number;
499
+ lessonTypeAbbrev?: string | string[];
500
+ subjectQuery?: string;
501
+ employeeUrlId?: string;
502
+ auditory?: string;
503
+ }
504
+ export { ScheduleFilterOptions }
505
+ export { ScheduleFilterOptions as ScheduleFilterOptions_alias_1 }
506
+ export { ScheduleFilterOptions as ScheduleFilterOptions_alias_2 }
507
+
508
+ declare interface ScheduleItem {
509
+ weekNumber: number[] | null;
510
+ studentGroups: LessonStudentGroup[];
511
+ numSubgroup: number;
512
+ auditories: string[];
513
+ startLessonTime: string;
514
+ endLessonTime: string;
515
+ subject: string;
516
+ subjectFullName: string;
517
+ note: Maybe<string>;
518
+ lessonTypeAbbrev: string | null;
519
+ dateLesson: Maybe<string>;
520
+ startLessonDate: Maybe<string>;
521
+ endLessonDate: Maybe<string>;
522
+ announcement: boolean;
523
+ split: boolean;
524
+ employees: Maybe<Employee[]>;
525
+ }
526
+ export { ScheduleItem }
527
+ export { ScheduleItem as ScheduleItem_alias_1 }
528
+ export { ScheduleItem as ScheduleItem_alias_2 }
529
+
530
+ declare interface ScheduleResponse {
531
+ employeeDto: Maybe<Employee>;
532
+ studentGroupDto: Maybe<StudentGroupCatalogItem>;
533
+ schedules: WeekScheduleMap | null;
534
+ exams: ScheduleItem[] | null;
535
+ startDate: Maybe<string>;
536
+ endDate: Maybe<string>;
537
+ startExamsDate: Maybe<string>;
538
+ endExamsDate: Maybe<string>;
539
+ }
540
+ export { ScheduleResponse }
541
+ export { ScheduleResponse as ScheduleResponse_alias_1 }
542
+ export { ScheduleResponse as ScheduleResponse_alias_2 }
543
+
544
+ declare interface Speciality {
545
+ id: number;
546
+ name: string;
547
+ abbrev: string;
548
+ educationForm: EducationForm[];
549
+ facultyId: number;
550
+ code: string;
551
+ }
552
+ export { Speciality }
553
+ export { Speciality as Speciality_alias_1 }
554
+ export { Speciality as Speciality_alias_2 }
555
+
556
+ declare interface StudentGroupCatalogItem {
557
+ name: string;
558
+ facultyId: number;
559
+ facultyName?: string;
560
+ facultyAbbrev?: string;
561
+ specialityDepartmentEducationFormId: number;
562
+ specialityName: string;
563
+ specialityAbbrev?: string;
564
+ course: number;
565
+ id: number;
566
+ calendarId: string;
567
+ educationDegree?: number;
568
+ }
569
+ export { StudentGroupCatalogItem }
570
+ export { StudentGroupCatalogItem as StudentGroupCatalogItem_alias_1 }
571
+ export { StudentGroupCatalogItem as StudentGroupCatalogItem_alias_2 }
572
+
573
+ declare interface StudentGroupShort {
574
+ id: number;
575
+ name: string;
576
+ }
577
+ export { StudentGroupShort }
578
+ export { StudentGroupShort as StudentGroupShort_alias_1 }
579
+ export { StudentGroupShort as StudentGroupShort_alias_2 }
580
+
581
+ declare type Weekday = "Понедельник" | "Вторник" | "Среда" | "Четверг" | "Пятница" | "Суббота";
582
+ export { Weekday }
583
+ export { Weekday as Weekday_alias_1 }
584
+ export { Weekday as Weekday_alias_2 }
585
+
586
+ declare type WeekScheduleMap = Partial<Record<Weekday, ScheduleItem[]>>;
587
+ export { WeekScheduleMap }
588
+ export { WeekScheduleMap as WeekScheduleMap_alias_1 }
589
+ export { WeekScheduleMap as WeekScheduleMap_alias_2 }
590
+
591
+ export { }