bsuir-iis-api 0.1.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 +16 -0
- package/LICENSE +21 -0
- package/README.md +98 -0
- package/dist/index.d.ts +250 -0
- package/dist/index.js +405 -0
- package/dist/index.js.map +1 -0
- package/package.json +66 -0
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to this project are documented in this file.
|
|
4
|
+
|
|
5
|
+
The format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
6
|
+
and the project follows [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
|
+
|
|
8
|
+
## [0.1.0] - 2026-03-15
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
|
|
12
|
+
- Initial ESM-only TypeScript SDK implementation.
|
|
13
|
+
- Typed modules for schedules, catalogs, announcements, current week and last update.
|
|
14
|
+
- Retry/timeout-enabled HTTP client with typed errors.
|
|
15
|
+
- Unit and smoke tests with Vitest.
|
|
16
|
+
- CI, release and npm publishing scaffolding.
|
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 kotru21
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
# bsuir-iis-api
|
|
2
|
+
|
|
3
|
+
Type-safe ESM SDK for [BSUIR IIS API](https://iis.bsuir.by/api/v1) with support for Node.js and browser runtimes.
|
|
4
|
+
|
|
5
|
+
## Install
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install bsuir-iis-api
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Quick start
|
|
12
|
+
|
|
13
|
+
```ts
|
|
14
|
+
import { createBsuirClient } from "bsuir-iis-api";
|
|
15
|
+
|
|
16
|
+
const client = createBsuirClient();
|
|
17
|
+
|
|
18
|
+
const schedule = await client.schedule.getGroup("053503");
|
|
19
|
+
if ("lessons" in schedule) {
|
|
20
|
+
console.log(schedule.lessons.length);
|
|
21
|
+
}
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
## Client options
|
|
25
|
+
|
|
26
|
+
```ts
|
|
27
|
+
const client = createBsuirClient({
|
|
28
|
+
baseUrl: "https://iis.bsuir.by/api/v1",
|
|
29
|
+
timeoutMs: 10000,
|
|
30
|
+
retries: 2,
|
|
31
|
+
retryDelayMs: 300,
|
|
32
|
+
defaultRaw: false
|
|
33
|
+
});
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
- `fetch` can be passed for custom runtime/testing.
|
|
37
|
+
- `AbortSignal` is supported by all read methods.
|
|
38
|
+
|
|
39
|
+
## API
|
|
40
|
+
|
|
41
|
+
### Schedule
|
|
42
|
+
|
|
43
|
+
- `client.schedule.getGroup(groupNumber, options?)`
|
|
44
|
+
- `client.schedule.getEmployee(urlId, options?)`
|
|
45
|
+
- `client.schedule.getCurrentWeek(options?)`
|
|
46
|
+
- `client.schedule.getLastUpdateByGroup({ groupNumber } | { id }, options?)`
|
|
47
|
+
- `client.schedule.getLastUpdateByEmployee({ urlId } | { id }, options?)`
|
|
48
|
+
|
|
49
|
+
### Catalogs
|
|
50
|
+
|
|
51
|
+
- `client.groups.listAll(options?)`
|
|
52
|
+
- `client.employees.listAll(options?)`
|
|
53
|
+
- `client.faculties.listAll(options?)`
|
|
54
|
+
- `client.departments.listAll(options?)`
|
|
55
|
+
- `client.specialities.listAll(options?)`
|
|
56
|
+
- `client.auditories.listAll(options?)`
|
|
57
|
+
|
|
58
|
+
### Announcements
|
|
59
|
+
|
|
60
|
+
- `client.announcements.byEmployee(urlId, options?)`
|
|
61
|
+
- `client.announcements.byDepartment(id, options?)`
|
|
62
|
+
|
|
63
|
+
### Meta
|
|
64
|
+
|
|
65
|
+
- `client.currentWeek.get(options?)`
|
|
66
|
+
- `client.lastUpdate.byGroup({ groupNumber } | { id }, options?)`
|
|
67
|
+
- `client.lastUpdate.byEmployee({ urlId } | { id }, options?)`
|
|
68
|
+
|
|
69
|
+
## Errors
|
|
70
|
+
|
|
71
|
+
SDK throws typed errors:
|
|
72
|
+
|
|
73
|
+
- `BsuirApiError` for HTTP errors (contains `status`, `endpoint`, `body`)
|
|
74
|
+
- `BsuirNetworkError` for transport errors
|
|
75
|
+
- `BsuirTimeoutError` for timeouts
|
|
76
|
+
- `BsuirValidationError` for invalid input parameters
|
|
77
|
+
|
|
78
|
+
## Raw vs normalized schedule response
|
|
79
|
+
|
|
80
|
+
By default, schedule methods return normalized response with `lessons` array.
|
|
81
|
+
|
|
82
|
+
```ts
|
|
83
|
+
const raw = await client.schedule.getGroup("053503", { raw: true });
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
Use `defaultRaw: true` in `createBsuirClient` to change global behavior.
|
|
87
|
+
|
|
88
|
+
## Development
|
|
89
|
+
|
|
90
|
+
```bash
|
|
91
|
+
npm install
|
|
92
|
+
npm run check
|
|
93
|
+
npm run build
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
## License
|
|
97
|
+
|
|
98
|
+
MIT
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,250 @@
|
|
|
1
|
+
type QueryValue = string | number | boolean | null | undefined;
|
|
2
|
+
type QueryParams = Record<string, QueryValue>;
|
|
3
|
+
interface RequestOptions {
|
|
4
|
+
query?: QueryParams | undefined;
|
|
5
|
+
signal?: AbortSignal | undefined;
|
|
6
|
+
}
|
|
7
|
+
interface BsuirClientOptions {
|
|
8
|
+
baseUrl?: string;
|
|
9
|
+
fetch?: typeof globalThis.fetch;
|
|
10
|
+
timeoutMs?: number;
|
|
11
|
+
retries?: number;
|
|
12
|
+
retryDelayMs?: number;
|
|
13
|
+
userAgent?: string;
|
|
14
|
+
defaultRaw?: boolean;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
interface ReadOptions extends RequestOptions {
|
|
18
|
+
raw?: boolean;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
declare function createBsuirClient(options?: BsuirClientOptions): {
|
|
22
|
+
schedule: {
|
|
23
|
+
getGroup(groupNumber: string, options?: ReadOptions): Promise<ScheduleResponse | NormalizedScheduleResponse>;
|
|
24
|
+
getEmployee(urlId: string, options?: ReadOptions): Promise<ScheduleResponse | NormalizedScheduleResponse>;
|
|
25
|
+
getCurrentWeek(options?: ReadOptions): Promise<number>;
|
|
26
|
+
getLastUpdateByGroup(params: {
|
|
27
|
+
groupNumber: string;
|
|
28
|
+
} | {
|
|
29
|
+
id: number;
|
|
30
|
+
}, options?: ReadOptions): Promise<ApiDateResponse>;
|
|
31
|
+
getLastUpdateByEmployee(params: {
|
|
32
|
+
urlId: string;
|
|
33
|
+
} | {
|
|
34
|
+
id: number;
|
|
35
|
+
}, options?: ReadOptions): Promise<ApiDateResponse>;
|
|
36
|
+
};
|
|
37
|
+
groups: {
|
|
38
|
+
listAll(options?: ReadOptions): Promise<StudentGroupCatalogItem[]>;
|
|
39
|
+
};
|
|
40
|
+
employees: {
|
|
41
|
+
listAll(options?: ReadOptions): Promise<EmployeeCatalogItem[]>;
|
|
42
|
+
};
|
|
43
|
+
faculties: {
|
|
44
|
+
listAll(options?: ReadOptions): Promise<Faculty[]>;
|
|
45
|
+
};
|
|
46
|
+
departments: {
|
|
47
|
+
listAll(options?: ReadOptions): Promise<Department[]>;
|
|
48
|
+
};
|
|
49
|
+
specialities: {
|
|
50
|
+
listAll(options?: ReadOptions): Promise<Speciality[]>;
|
|
51
|
+
};
|
|
52
|
+
announcements: {
|
|
53
|
+
byEmployee(urlId: string, options?: ReadOptions): Promise<Announcement[]>;
|
|
54
|
+
byDepartment(id: number, options?: ReadOptions): Promise<Announcement[]>;
|
|
55
|
+
};
|
|
56
|
+
auditories: {
|
|
57
|
+
listAll(options?: ReadOptions): Promise<Auditory[]>;
|
|
58
|
+
};
|
|
59
|
+
lastUpdate: {
|
|
60
|
+
byGroup(params: {
|
|
61
|
+
groupNumber: string;
|
|
62
|
+
} | {
|
|
63
|
+
id: number;
|
|
64
|
+
}, options?: ReadOptions): Promise<ApiDateResponse>;
|
|
65
|
+
byEmployee(params: {
|
|
66
|
+
urlId: string;
|
|
67
|
+
} | {
|
|
68
|
+
id: number;
|
|
69
|
+
}, options?: ReadOptions): Promise<ApiDateResponse>;
|
|
70
|
+
};
|
|
71
|
+
currentWeek: {
|
|
72
|
+
get(options?: ReadOptions): Promise<number>;
|
|
73
|
+
};
|
|
74
|
+
};
|
|
75
|
+
type BsuirClient = ReturnType<typeof createBsuirClient>;
|
|
76
|
+
|
|
77
|
+
declare class BsuirApiError extends Error {
|
|
78
|
+
readonly status: number;
|
|
79
|
+
readonly endpoint: string;
|
|
80
|
+
readonly body: unknown;
|
|
81
|
+
constructor(message: string, status: number, endpoint: string, body: unknown);
|
|
82
|
+
}
|
|
83
|
+
declare class BsuirNetworkError extends Error {
|
|
84
|
+
readonly endpoint: string;
|
|
85
|
+
readonly causeError: unknown;
|
|
86
|
+
constructor(message: string, endpoint: string, causeError: unknown);
|
|
87
|
+
}
|
|
88
|
+
declare class BsuirTimeoutError extends Error {
|
|
89
|
+
readonly endpoint: string;
|
|
90
|
+
readonly timeoutMs: number;
|
|
91
|
+
constructor(message: string, endpoint: string, timeoutMs: number);
|
|
92
|
+
}
|
|
93
|
+
declare class BsuirValidationError extends Error {
|
|
94
|
+
constructor(message: string);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
type Weekday = "Понедельник" | "Вторник" | "Среда" | "Четверг" | "Пятница" | "Суббота";
|
|
98
|
+
interface ApiDateResponse {
|
|
99
|
+
lastUpdateDate: string;
|
|
100
|
+
}
|
|
101
|
+
interface StudentGroupShort {
|
|
102
|
+
id: number;
|
|
103
|
+
name: string;
|
|
104
|
+
}
|
|
105
|
+
type Maybe<T> = T | null;
|
|
106
|
+
|
|
107
|
+
interface Announcement {
|
|
108
|
+
id: number;
|
|
109
|
+
employee: string;
|
|
110
|
+
content: string;
|
|
111
|
+
date: string;
|
|
112
|
+
employeeDepartments: string[];
|
|
113
|
+
studentGroups: StudentGroupShort[];
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
interface Faculty {
|
|
117
|
+
id: number;
|
|
118
|
+
name: string;
|
|
119
|
+
abbrev: string;
|
|
120
|
+
}
|
|
121
|
+
interface Department {
|
|
122
|
+
id: number;
|
|
123
|
+
name: string;
|
|
124
|
+
abbrev: string;
|
|
125
|
+
}
|
|
126
|
+
interface EducationForm {
|
|
127
|
+
id: number;
|
|
128
|
+
name: string;
|
|
129
|
+
}
|
|
130
|
+
interface Speciality {
|
|
131
|
+
id: number;
|
|
132
|
+
name: string;
|
|
133
|
+
abbrev: string;
|
|
134
|
+
educationForm: EducationForm[];
|
|
135
|
+
facultyId: number;
|
|
136
|
+
code: string;
|
|
137
|
+
}
|
|
138
|
+
interface StudentGroupCatalogItem {
|
|
139
|
+
name: string;
|
|
140
|
+
facultyId: number;
|
|
141
|
+
facultyName?: string;
|
|
142
|
+
facultyAbbrev?: string;
|
|
143
|
+
specialityDepartmentEducationFormId: number;
|
|
144
|
+
specialityName: string;
|
|
145
|
+
specialityAbbrev?: string;
|
|
146
|
+
course: number;
|
|
147
|
+
id: number;
|
|
148
|
+
calendarId: string;
|
|
149
|
+
educationDegree?: number;
|
|
150
|
+
}
|
|
151
|
+
interface AuditoryType {
|
|
152
|
+
id: number;
|
|
153
|
+
name: string;
|
|
154
|
+
abbrev: string;
|
|
155
|
+
}
|
|
156
|
+
interface BuildingNumber {
|
|
157
|
+
id: number;
|
|
158
|
+
name: string;
|
|
159
|
+
}
|
|
160
|
+
interface AuditoryDepartment {
|
|
161
|
+
idDepartment: number;
|
|
162
|
+
abbrev: string;
|
|
163
|
+
name: string;
|
|
164
|
+
nameAndAbbrev: string;
|
|
165
|
+
}
|
|
166
|
+
interface Auditory {
|
|
167
|
+
id: number;
|
|
168
|
+
name: string;
|
|
169
|
+
note: string;
|
|
170
|
+
capacity: number | null;
|
|
171
|
+
auditoryType: AuditoryType;
|
|
172
|
+
buildingNumber: BuildingNumber;
|
|
173
|
+
department: AuditoryDepartment;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
interface Employee {
|
|
177
|
+
firstName: string;
|
|
178
|
+
lastName: string;
|
|
179
|
+
middleName: string;
|
|
180
|
+
degree: string;
|
|
181
|
+
degreeAbbrev?: string;
|
|
182
|
+
email: Maybe<string>;
|
|
183
|
+
rank: Maybe<string>;
|
|
184
|
+
photoLink: string;
|
|
185
|
+
calendarId: string;
|
|
186
|
+
id: number;
|
|
187
|
+
urlId: string;
|
|
188
|
+
jobPositions: Maybe<string[]>;
|
|
189
|
+
}
|
|
190
|
+
interface EmployeeCatalogItem {
|
|
191
|
+
firstName: string;
|
|
192
|
+
lastName: string;
|
|
193
|
+
middleName: string;
|
|
194
|
+
degree: string;
|
|
195
|
+
rank: string;
|
|
196
|
+
photoLink: string;
|
|
197
|
+
calendarId: string;
|
|
198
|
+
academicDepartment?: string[];
|
|
199
|
+
id: number;
|
|
200
|
+
urlId: string;
|
|
201
|
+
fio: string;
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
interface LessonStudentGroup {
|
|
205
|
+
specialityName: string;
|
|
206
|
+
specialityCode: string;
|
|
207
|
+
numberOfStudents: number;
|
|
208
|
+
name: string;
|
|
209
|
+
educationDegree: number;
|
|
210
|
+
}
|
|
211
|
+
interface ScheduleItem {
|
|
212
|
+
weekNumber: number[];
|
|
213
|
+
studentGroups: LessonStudentGroup[];
|
|
214
|
+
numSubgroup: number;
|
|
215
|
+
auditories: string[];
|
|
216
|
+
startLessonTime: string;
|
|
217
|
+
endLessonTime: string;
|
|
218
|
+
subject: string;
|
|
219
|
+
subjectFullName: string;
|
|
220
|
+
note: Maybe<string>;
|
|
221
|
+
lessonTypeAbbrev: string;
|
|
222
|
+
dateLesson: Maybe<string>;
|
|
223
|
+
startLessonDate: Maybe<string>;
|
|
224
|
+
endLessonDate: Maybe<string>;
|
|
225
|
+
announcement: boolean;
|
|
226
|
+
split: boolean;
|
|
227
|
+
employees: Maybe<Employee[]>;
|
|
228
|
+
}
|
|
229
|
+
type WeekScheduleMap = Partial<Record<Weekday, ScheduleItem[]>>;
|
|
230
|
+
interface ScheduleResponse {
|
|
231
|
+
employeeDto: Maybe<Employee>;
|
|
232
|
+
studentGroupDto: Maybe<StudentGroupCatalogItem>;
|
|
233
|
+
schedules: WeekScheduleMap;
|
|
234
|
+
exams: ScheduleItem[];
|
|
235
|
+
startDate: Maybe<string>;
|
|
236
|
+
endDate: Maybe<string>;
|
|
237
|
+
startExamsDate: Maybe<string>;
|
|
238
|
+
endExamsDate: Maybe<string>;
|
|
239
|
+
}
|
|
240
|
+
interface FlattenedScheduleItem extends ScheduleItem {
|
|
241
|
+
day: Weekday | null;
|
|
242
|
+
source: "schedules" | "exams";
|
|
243
|
+
}
|
|
244
|
+
interface NormalizedScheduleResponse extends Omit<ScheduleResponse, "schedules" | "exams"> {
|
|
245
|
+
schedules: WeekScheduleMap;
|
|
246
|
+
exams: ScheduleItem[];
|
|
247
|
+
lessons: FlattenedScheduleItem[];
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
export { type Announcement, type ApiDateResponse, type Auditory, type AuditoryDepartment, type AuditoryType, BsuirApiError, type BsuirClient, type BsuirClientOptions, BsuirNetworkError, BsuirTimeoutError, BsuirValidationError, type BuildingNumber, type Department, type EducationForm, type Employee, type EmployeeCatalogItem, type Faculty, type FlattenedScheduleItem, type LessonStudentGroup, type Maybe, type NormalizedScheduleResponse, type ScheduleItem, type ScheduleResponse, type Speciality, type StudentGroupCatalogItem, type StudentGroupShort, type WeekScheduleMap, type Weekday, createBsuirClient };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,405 @@
|
|
|
1
|
+
// src/client/errors.ts
|
|
2
|
+
var BsuirApiError = class extends Error {
|
|
3
|
+
status;
|
|
4
|
+
endpoint;
|
|
5
|
+
body;
|
|
6
|
+
constructor(message, status, endpoint, body) {
|
|
7
|
+
super(message);
|
|
8
|
+
this.name = "BsuirApiError";
|
|
9
|
+
this.status = status;
|
|
10
|
+
this.endpoint = endpoint;
|
|
11
|
+
this.body = body;
|
|
12
|
+
}
|
|
13
|
+
};
|
|
14
|
+
var BsuirNetworkError = class extends Error {
|
|
15
|
+
endpoint;
|
|
16
|
+
causeError;
|
|
17
|
+
constructor(message, endpoint, causeError) {
|
|
18
|
+
super(message);
|
|
19
|
+
this.name = "BsuirNetworkError";
|
|
20
|
+
this.endpoint = endpoint;
|
|
21
|
+
this.causeError = causeError;
|
|
22
|
+
}
|
|
23
|
+
};
|
|
24
|
+
var BsuirTimeoutError = class extends Error {
|
|
25
|
+
endpoint;
|
|
26
|
+
timeoutMs;
|
|
27
|
+
constructor(message, endpoint, timeoutMs) {
|
|
28
|
+
super(message);
|
|
29
|
+
this.name = "BsuirTimeoutError";
|
|
30
|
+
this.endpoint = endpoint;
|
|
31
|
+
this.timeoutMs = timeoutMs;
|
|
32
|
+
}
|
|
33
|
+
};
|
|
34
|
+
var BsuirValidationError = class extends Error {
|
|
35
|
+
constructor(message) {
|
|
36
|
+
super(message);
|
|
37
|
+
this.name = "BsuirValidationError";
|
|
38
|
+
}
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
// src/utils/guards.ts
|
|
42
|
+
function assertNonEmptyString(value, fieldName) {
|
|
43
|
+
if (!value || value.trim().length === 0) {
|
|
44
|
+
throw new BsuirValidationError(`'${fieldName}' must be a non-empty string`);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
function assertPositiveInt(value, fieldName) {
|
|
48
|
+
if (!Number.isInteger(value) || value <= 0) {
|
|
49
|
+
throw new BsuirValidationError(`'${fieldName}' must be a positive integer`);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
function isAbortError(error) {
|
|
53
|
+
return error instanceof DOMException && error.name === "AbortError";
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// src/client/http.ts
|
|
57
|
+
var RETRIABLE_STATUS_CODES = /* @__PURE__ */ new Set([429, 500, 502, 503, 504]);
|
|
58
|
+
function buildUrl(baseUrl, path, query) {
|
|
59
|
+
const normalizedBase = baseUrl.endsWith("/") ? baseUrl.slice(0, -1) : baseUrl;
|
|
60
|
+
const normalizedPath = path.startsWith("/") ? path : `/${path}`;
|
|
61
|
+
const url = new URL(`${normalizedBase}${normalizedPath}`);
|
|
62
|
+
if (query) {
|
|
63
|
+
for (const [key, value] of Object.entries(query)) {
|
|
64
|
+
if (value === void 0 || value === null) {
|
|
65
|
+
continue;
|
|
66
|
+
}
|
|
67
|
+
url.searchParams.set(key, String(value));
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
return url.toString();
|
|
71
|
+
}
|
|
72
|
+
function mergeSignals(signal, timeoutMs) {
|
|
73
|
+
if (typeof AbortSignal.any === "function") {
|
|
74
|
+
return AbortSignal.any([AbortSignal.timeout(timeoutMs), signal].filter(Boolean));
|
|
75
|
+
}
|
|
76
|
+
if (signal) {
|
|
77
|
+
return signal;
|
|
78
|
+
}
|
|
79
|
+
return AbortSignal.timeout(timeoutMs);
|
|
80
|
+
}
|
|
81
|
+
function sleep(ms) {
|
|
82
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
83
|
+
}
|
|
84
|
+
async function parseBody(response) {
|
|
85
|
+
const contentType = response.headers.get("content-type") ?? "";
|
|
86
|
+
if (!contentType.includes("application/json")) {
|
|
87
|
+
return response.text();
|
|
88
|
+
}
|
|
89
|
+
try {
|
|
90
|
+
return await response.json();
|
|
91
|
+
} catch {
|
|
92
|
+
throw new BsuirApiError("Invalid JSON response payload", response.status, response.url, null);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
async function requestJson(config, path, options = {}) {
|
|
96
|
+
const endpoint = buildUrl(config.baseUrl, path, options.query);
|
|
97
|
+
const requestSignal = mergeSignals(options.signal, config.timeoutMs);
|
|
98
|
+
const headers = new Headers({
|
|
99
|
+
Accept: "application/json"
|
|
100
|
+
});
|
|
101
|
+
if (config.userAgent) {
|
|
102
|
+
headers.set("User-Agent", config.userAgent);
|
|
103
|
+
}
|
|
104
|
+
for (let attempt = 0; attempt <= config.retries; attempt += 1) {
|
|
105
|
+
try {
|
|
106
|
+
const response = await config.fetchImpl(endpoint, {
|
|
107
|
+
method: "GET",
|
|
108
|
+
headers,
|
|
109
|
+
signal: requestSignal
|
|
110
|
+
});
|
|
111
|
+
if (!response.ok) {
|
|
112
|
+
const errorBody = await parseBody(response);
|
|
113
|
+
if (attempt < config.retries && RETRIABLE_STATUS_CODES.has(response.status)) {
|
|
114
|
+
await sleep(config.retryDelayMs * (attempt + 1));
|
|
115
|
+
continue;
|
|
116
|
+
}
|
|
117
|
+
throw new BsuirApiError(
|
|
118
|
+
`BSUIR API returned HTTP ${response.status} for ${path}`,
|
|
119
|
+
response.status,
|
|
120
|
+
endpoint,
|
|
121
|
+
errorBody
|
|
122
|
+
);
|
|
123
|
+
}
|
|
124
|
+
return await parseBody(response);
|
|
125
|
+
} catch (error) {
|
|
126
|
+
if (error instanceof BsuirApiError) {
|
|
127
|
+
throw error;
|
|
128
|
+
}
|
|
129
|
+
if (isAbortError(error)) {
|
|
130
|
+
if (options.signal?.aborted) {
|
|
131
|
+
throw error;
|
|
132
|
+
}
|
|
133
|
+
throw new BsuirTimeoutError(
|
|
134
|
+
`Request timed out after ${config.timeoutMs}ms: ${path}`,
|
|
135
|
+
endpoint,
|
|
136
|
+
config.timeoutMs
|
|
137
|
+
);
|
|
138
|
+
}
|
|
139
|
+
if (attempt < config.retries) {
|
|
140
|
+
await sleep(config.retryDelayMs * (attempt + 1));
|
|
141
|
+
continue;
|
|
142
|
+
}
|
|
143
|
+
throw new BsuirNetworkError(`Network error while requesting ${path}`, endpoint, error);
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
throw new BsuirNetworkError(`Network error while requesting ${path}`, endpoint, null);
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
// src/modules/announcements.ts
|
|
150
|
+
function createAnnouncementsModule(config) {
|
|
151
|
+
return {
|
|
152
|
+
async byEmployee(urlId, options = {}) {
|
|
153
|
+
assertNonEmptyString(urlId, "urlId");
|
|
154
|
+
return requestJson(config, "/announcements/employees", {
|
|
155
|
+
query: { "url-id": urlId },
|
|
156
|
+
signal: options.signal
|
|
157
|
+
});
|
|
158
|
+
},
|
|
159
|
+
async byDepartment(id, options = {}) {
|
|
160
|
+
assertPositiveInt(id, "id");
|
|
161
|
+
return requestJson(config, "/announcements/departments", {
|
|
162
|
+
query: { id },
|
|
163
|
+
signal: options.signal
|
|
164
|
+
});
|
|
165
|
+
}
|
|
166
|
+
};
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
// src/modules/auditories.ts
|
|
170
|
+
function createAuditoriesModule(config) {
|
|
171
|
+
return {
|
|
172
|
+
async listAll(options = {}) {
|
|
173
|
+
return requestJson(config, "/auditories", {
|
|
174
|
+
signal: options.signal
|
|
175
|
+
});
|
|
176
|
+
}
|
|
177
|
+
};
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
// src/modules/currentWeek.ts
|
|
181
|
+
function createCurrentWeekModule(config) {
|
|
182
|
+
return {
|
|
183
|
+
async get(options = {}) {
|
|
184
|
+
return requestJson(config, "/schedule/current-week", {
|
|
185
|
+
signal: options.signal
|
|
186
|
+
});
|
|
187
|
+
}
|
|
188
|
+
};
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
// src/modules/departments.ts
|
|
192
|
+
function createDepartmentsModule(config) {
|
|
193
|
+
return {
|
|
194
|
+
async listAll(options = {}) {
|
|
195
|
+
return requestJson(config, "/departments", {
|
|
196
|
+
signal: options.signal
|
|
197
|
+
});
|
|
198
|
+
}
|
|
199
|
+
};
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
// src/modules/employees.ts
|
|
203
|
+
function createEmployeesModule(config) {
|
|
204
|
+
return {
|
|
205
|
+
async listAll(options = {}) {
|
|
206
|
+
return requestJson(config, "/employees/all", {
|
|
207
|
+
signal: options.signal
|
|
208
|
+
});
|
|
209
|
+
}
|
|
210
|
+
};
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
// src/modules/faculties.ts
|
|
214
|
+
function createFacultiesModule(config) {
|
|
215
|
+
return {
|
|
216
|
+
async listAll(options = {}) {
|
|
217
|
+
return requestJson(config, "/faculties", {
|
|
218
|
+
signal: options.signal
|
|
219
|
+
});
|
|
220
|
+
}
|
|
221
|
+
};
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
// src/modules/groups.ts
|
|
225
|
+
function createGroupsModule(config) {
|
|
226
|
+
return {
|
|
227
|
+
async listAll(options = {}) {
|
|
228
|
+
return requestJson(config, "/student-groups", {
|
|
229
|
+
signal: options.signal
|
|
230
|
+
});
|
|
231
|
+
}
|
|
232
|
+
};
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
// src/modules/lastUpdate.ts
|
|
236
|
+
function createLastUpdateModule(config) {
|
|
237
|
+
return {
|
|
238
|
+
async byGroup(params, options = {}) {
|
|
239
|
+
let query;
|
|
240
|
+
if ("groupNumber" in params) {
|
|
241
|
+
assertNonEmptyString(params.groupNumber, "groupNumber");
|
|
242
|
+
query = { groupNumber: params.groupNumber };
|
|
243
|
+
} else {
|
|
244
|
+
assertPositiveInt(params.id, "id");
|
|
245
|
+
query = { id: params.id };
|
|
246
|
+
}
|
|
247
|
+
return requestJson(config, "/last-update-date/student-group", {
|
|
248
|
+
query,
|
|
249
|
+
signal: options.signal
|
|
250
|
+
});
|
|
251
|
+
},
|
|
252
|
+
async byEmployee(params, options = {}) {
|
|
253
|
+
let query;
|
|
254
|
+
if ("urlId" in params) {
|
|
255
|
+
assertNonEmptyString(params.urlId, "urlId");
|
|
256
|
+
query = { "url-id": params.urlId };
|
|
257
|
+
} else {
|
|
258
|
+
assertPositiveInt(params.id, "id");
|
|
259
|
+
query = { id: params.id };
|
|
260
|
+
}
|
|
261
|
+
return requestJson(config, "/last-update-date/employee", {
|
|
262
|
+
query,
|
|
263
|
+
signal: options.signal
|
|
264
|
+
});
|
|
265
|
+
}
|
|
266
|
+
};
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
// src/modules/schedule.ts
|
|
270
|
+
var WEEKDAYS = [
|
|
271
|
+
"\u041F\u043E\u043D\u0435\u0434\u0435\u043B\u044C\u043D\u0438\u043A",
|
|
272
|
+
"\u0412\u0442\u043E\u0440\u043D\u0438\u043A",
|
|
273
|
+
"\u0421\u0440\u0435\u0434\u0430",
|
|
274
|
+
"\u0427\u0435\u0442\u0432\u0435\u0440\u0433",
|
|
275
|
+
"\u041F\u044F\u0442\u043D\u0438\u0446\u0430",
|
|
276
|
+
"\u0421\u0443\u0431\u0431\u043E\u0442\u0430"
|
|
277
|
+
];
|
|
278
|
+
function normalizeSchedule(response) {
|
|
279
|
+
const lessons = [];
|
|
280
|
+
for (const day of WEEKDAYS) {
|
|
281
|
+
const dayItems = response.schedules[day] ?? [];
|
|
282
|
+
for (const item of dayItems) {
|
|
283
|
+
lessons.push({ ...item, day, source: "schedules" });
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
for (const exam of response.exams) {
|
|
287
|
+
lessons.push({
|
|
288
|
+
...exam,
|
|
289
|
+
day: null,
|
|
290
|
+
// Exams are not grouped by weekday in API response.
|
|
291
|
+
source: "exams"
|
|
292
|
+
});
|
|
293
|
+
}
|
|
294
|
+
return {
|
|
295
|
+
...response,
|
|
296
|
+
lessons
|
|
297
|
+
};
|
|
298
|
+
}
|
|
299
|
+
function createScheduleModule(config) {
|
|
300
|
+
return {
|
|
301
|
+
async getGroup(groupNumber, options = {}) {
|
|
302
|
+
assertNonEmptyString(groupNumber, "groupNumber");
|
|
303
|
+
const response = await requestJson(config, "/schedule", {
|
|
304
|
+
query: { studentGroup: groupNumber },
|
|
305
|
+
signal: options.signal
|
|
306
|
+
});
|
|
307
|
+
return options.raw ?? config.defaultRaw ? response : normalizeSchedule(response);
|
|
308
|
+
},
|
|
309
|
+
async getEmployee(urlId, options = {}) {
|
|
310
|
+
assertNonEmptyString(urlId, "urlId");
|
|
311
|
+
const response = await requestJson(config, `/employees/schedule/${urlId}`, {
|
|
312
|
+
signal: options.signal
|
|
313
|
+
});
|
|
314
|
+
return options.raw ?? config.defaultRaw ? response : normalizeSchedule(response);
|
|
315
|
+
},
|
|
316
|
+
async getCurrentWeek(options = {}) {
|
|
317
|
+
return requestJson(config, "/schedule/current-week", { signal: options.signal });
|
|
318
|
+
},
|
|
319
|
+
async getLastUpdateByGroup(params, options = {}) {
|
|
320
|
+
let query;
|
|
321
|
+
if ("groupNumber" in params) {
|
|
322
|
+
assertNonEmptyString(params.groupNumber, "groupNumber");
|
|
323
|
+
query = { groupNumber: params.groupNumber };
|
|
324
|
+
} else {
|
|
325
|
+
assertPositiveInt(params.id, "id");
|
|
326
|
+
query = { id: params.id };
|
|
327
|
+
}
|
|
328
|
+
return requestJson(config, "/last-update-date/student-group", {
|
|
329
|
+
query,
|
|
330
|
+
signal: options.signal
|
|
331
|
+
});
|
|
332
|
+
},
|
|
333
|
+
async getLastUpdateByEmployee(params, options = {}) {
|
|
334
|
+
let query;
|
|
335
|
+
if ("urlId" in params) {
|
|
336
|
+
assertNonEmptyString(params.urlId, "urlId");
|
|
337
|
+
query = { "url-id": params.urlId };
|
|
338
|
+
} else {
|
|
339
|
+
assertPositiveInt(params.id, "id");
|
|
340
|
+
query = { id: params.id };
|
|
341
|
+
}
|
|
342
|
+
return requestJson(config, "/last-update-date/employee", {
|
|
343
|
+
query,
|
|
344
|
+
signal: options.signal
|
|
345
|
+
});
|
|
346
|
+
}
|
|
347
|
+
};
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
// src/modules/specialities.ts
|
|
351
|
+
function createSpecialitiesModule(config) {
|
|
352
|
+
return {
|
|
353
|
+
async listAll(options = {}) {
|
|
354
|
+
return requestJson(config, "/specialities", {
|
|
355
|
+
signal: options.signal
|
|
356
|
+
});
|
|
357
|
+
}
|
|
358
|
+
};
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
// src/client/createClient.ts
|
|
362
|
+
var DEFAULT_BASE_URL = "https://iis.bsuir.by/api/v1";
|
|
363
|
+
function resolveFetch(customFetch) {
|
|
364
|
+
if (customFetch) {
|
|
365
|
+
return customFetch;
|
|
366
|
+
}
|
|
367
|
+
if (typeof globalThis.fetch !== "function") {
|
|
368
|
+
throw new Error("Global fetch is unavailable. Provide 'fetch' in createBsuirClient options.");
|
|
369
|
+
}
|
|
370
|
+
return globalThis.fetch;
|
|
371
|
+
}
|
|
372
|
+
function createInternalConfig(options = {}) {
|
|
373
|
+
return {
|
|
374
|
+
baseUrl: options.baseUrl ?? DEFAULT_BASE_URL,
|
|
375
|
+
fetchImpl: resolveFetch(options.fetch),
|
|
376
|
+
timeoutMs: options.timeoutMs ?? 1e4,
|
|
377
|
+
retries: options.retries ?? 1,
|
|
378
|
+
retryDelayMs: options.retryDelayMs ?? 300,
|
|
379
|
+
userAgent: options.userAgent,
|
|
380
|
+
defaultRaw: options.defaultRaw ?? false
|
|
381
|
+
};
|
|
382
|
+
}
|
|
383
|
+
function createBsuirClient(options = {}) {
|
|
384
|
+
const config = createInternalConfig(options);
|
|
385
|
+
return {
|
|
386
|
+
schedule: createScheduleModule(config),
|
|
387
|
+
groups: createGroupsModule(config),
|
|
388
|
+
employees: createEmployeesModule(config),
|
|
389
|
+
faculties: createFacultiesModule(config),
|
|
390
|
+
departments: createDepartmentsModule(config),
|
|
391
|
+
specialities: createSpecialitiesModule(config),
|
|
392
|
+
announcements: createAnnouncementsModule(config),
|
|
393
|
+
auditories: createAuditoriesModule(config),
|
|
394
|
+
lastUpdate: createLastUpdateModule(config),
|
|
395
|
+
currentWeek: createCurrentWeekModule(config)
|
|
396
|
+
};
|
|
397
|
+
}
|
|
398
|
+
export {
|
|
399
|
+
BsuirApiError,
|
|
400
|
+
BsuirNetworkError,
|
|
401
|
+
BsuirTimeoutError,
|
|
402
|
+
BsuirValidationError,
|
|
403
|
+
createBsuirClient
|
|
404
|
+
};
|
|
405
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/client/errors.ts","../src/utils/guards.ts","../src/client/http.ts","../src/modules/announcements.ts","../src/modules/auditories.ts","../src/modules/currentWeek.ts","../src/modules/departments.ts","../src/modules/employees.ts","../src/modules/faculties.ts","../src/modules/groups.ts","../src/modules/lastUpdate.ts","../src/modules/schedule.ts","../src/modules/specialities.ts","../src/client/createClient.ts"],"sourcesContent":["export class BsuirApiError extends Error {\r\n readonly status: number;\r\n readonly endpoint: string;\r\n readonly body: unknown;\r\n\r\n constructor(message: string, status: number, endpoint: string, body: unknown) {\r\n super(message);\r\n this.name = \"BsuirApiError\";\r\n this.status = status;\r\n this.endpoint = endpoint;\r\n this.body = body;\r\n }\r\n}\r\n\r\nexport class BsuirNetworkError extends Error {\r\n readonly endpoint: string;\r\n readonly causeError: unknown;\r\n\r\n constructor(message: string, endpoint: string, causeError: unknown) {\r\n super(message);\r\n this.name = \"BsuirNetworkError\";\r\n this.endpoint = endpoint;\r\n this.causeError = causeError;\r\n }\r\n}\r\n\r\nexport class BsuirTimeoutError extends Error {\r\n readonly endpoint: string;\r\n readonly timeoutMs: number;\r\n\r\n constructor(message: string, endpoint: string, timeoutMs: number) {\r\n super(message);\r\n this.name = \"BsuirTimeoutError\";\r\n this.endpoint = endpoint;\r\n this.timeoutMs = timeoutMs;\r\n }\r\n}\r\n\r\nexport class BsuirValidationError extends Error {\r\n constructor(message: string) {\r\n super(message);\r\n this.name = \"BsuirValidationError\";\r\n }\r\n}\r\n","import { BsuirValidationError } from \"../client/errors\";\r\n\r\nexport function assertNonEmptyString(value: string, fieldName: string): void {\r\n if (!value || value.trim().length === 0) {\r\n throw new BsuirValidationError(`'${fieldName}' must be a non-empty string`);\r\n }\r\n}\r\n\r\nexport function assertPositiveInt(value: number, fieldName: string): void {\r\n if (!Number.isInteger(value) || value <= 0) {\r\n throw new BsuirValidationError(`'${fieldName}' must be a positive integer`);\r\n }\r\n}\r\n\r\nexport function isAbortError(error: unknown): boolean {\r\n return error instanceof DOMException && error.name === \"AbortError\";\r\n}\r\n","import { BsuirApiError, BsuirNetworkError, BsuirTimeoutError } from \"./errors\";\r\nimport type { InternalClientConfig, QueryParams, RequestOptions } from \"./types\";\r\nimport { isAbortError } from \"../utils/guards\";\r\n\r\nconst RETRIABLE_STATUS_CODES = new Set([429, 500, 502, 503, 504]);\r\n\r\nfunction buildUrl(baseUrl: string, path: string, query?: QueryParams): string {\r\n const normalizedBase = baseUrl.endsWith(\"/\") ? baseUrl.slice(0, -1) : baseUrl;\r\n const normalizedPath = path.startsWith(\"/\") ? path : `/${path}`;\r\n const url = new URL(`${normalizedBase}${normalizedPath}`);\r\n\r\n if (query) {\r\n for (const [key, value] of Object.entries(query)) {\r\n if (value === undefined || value === null) {\r\n continue;\r\n }\r\n url.searchParams.set(key, String(value));\r\n }\r\n }\r\n\r\n return url.toString();\r\n}\r\n\r\nfunction mergeSignals(signal: AbortSignal | undefined, timeoutMs: number): AbortSignal {\r\n if (typeof AbortSignal.any === \"function\") {\r\n return AbortSignal.any([AbortSignal.timeout(timeoutMs), signal].filter(Boolean) as AbortSignal[]);\r\n }\r\n\r\n if (signal) {\r\n return signal;\r\n }\r\n\r\n return AbortSignal.timeout(timeoutMs);\r\n}\r\n\r\nfunction sleep(ms: number): Promise<void> {\r\n return new Promise((resolve) => setTimeout(resolve, ms));\r\n}\r\n\r\nasync function parseBody(response: Response): Promise<unknown> {\r\n const contentType = response.headers.get(\"content-type\") ?? \"\";\r\n if (!contentType.includes(\"application/json\")) {\r\n return response.text();\r\n }\r\n\r\n try {\r\n return await response.json();\r\n } catch {\r\n throw new BsuirApiError(\"Invalid JSON response payload\", response.status, response.url, null);\r\n }\r\n}\r\n\r\nexport async function requestJson<T>(\r\n config: InternalClientConfig,\r\n path: string,\r\n options: RequestOptions = {}\r\n): Promise<T> {\r\n const endpoint = buildUrl(config.baseUrl, path, options.query);\r\n const requestSignal = mergeSignals(options.signal, config.timeoutMs);\r\n const headers = new Headers({\r\n Accept: \"application/json\"\r\n });\r\n\r\n if (config.userAgent) {\r\n headers.set(\"User-Agent\", config.userAgent);\r\n }\r\n\r\n for (let attempt = 0; attempt <= config.retries; attempt += 1) {\r\n try {\r\n const response = await config.fetchImpl(endpoint, {\r\n method: \"GET\",\r\n headers,\r\n signal: requestSignal\r\n });\r\n\r\n if (!response.ok) {\r\n const errorBody = await parseBody(response);\r\n if (attempt < config.retries && RETRIABLE_STATUS_CODES.has(response.status)) {\r\n await sleep(config.retryDelayMs * (attempt + 1));\r\n continue;\r\n }\r\n throw new BsuirApiError(\r\n `BSUIR API returned HTTP ${response.status} for ${path}`,\r\n response.status,\r\n endpoint,\r\n errorBody\r\n );\r\n }\r\n\r\n return (await parseBody(response)) as T;\r\n } catch (error) {\r\n if (error instanceof BsuirApiError) {\r\n throw error;\r\n }\r\n\r\n if (isAbortError(error)) {\r\n if (options.signal?.aborted) {\r\n throw error;\r\n }\r\n throw new BsuirTimeoutError(\r\n `Request timed out after ${config.timeoutMs}ms: ${path}`,\r\n endpoint,\r\n config.timeoutMs\r\n );\r\n }\r\n\r\n if (attempt < config.retries) {\r\n await sleep(config.retryDelayMs * (attempt + 1));\r\n continue;\r\n }\r\n\r\n throw new BsuirNetworkError(`Network error while requesting ${path}`, endpoint, error);\r\n }\r\n }\r\n\r\n throw new BsuirNetworkError(`Network error while requesting ${path}`, endpoint, null);\r\n}\r\n","import type { InternalClientConfig } from \"../client/types\";\r\nimport { requestJson } from \"../client/http\";\r\nimport { assertNonEmptyString, assertPositiveInt } from \"../utils/guards\";\r\nimport type { Announcement } from \"../types/announcement\";\r\nimport type { ReadOptions } from \"./types\";\r\n\r\nexport function createAnnouncementsModule(config: InternalClientConfig) {\r\n return {\r\n async byEmployee(urlId: string, options: ReadOptions = {}): Promise<Announcement[]> {\r\n assertNonEmptyString(urlId, \"urlId\");\r\n return requestJson<Announcement[]>(config, \"/announcements/employees\", {\r\n query: { \"url-id\": urlId },\r\n signal: options.signal\r\n });\r\n },\r\n\r\n async byDepartment(id: number, options: ReadOptions = {}): Promise<Announcement[]> {\r\n assertPositiveInt(id, \"id\");\r\n return requestJson<Announcement[]>(config, \"/announcements/departments\", {\r\n query: { id },\r\n signal: options.signal\r\n });\r\n }\r\n };\r\n}\r\n","import type { InternalClientConfig } from \"../client/types\";\r\nimport { requestJson } from \"../client/http\";\r\nimport type { Auditory } from \"../types/catalog\";\r\nimport type { ReadOptions } from \"./types\";\r\n\r\nexport function createAuditoriesModule(config: InternalClientConfig) {\r\n return {\r\n async listAll(options: ReadOptions = {}): Promise<Auditory[]> {\r\n return requestJson<Auditory[]>(config, \"/auditories\", {\r\n signal: options.signal\r\n });\r\n }\r\n };\r\n}\r\n","import type { InternalClientConfig } from \"../client/types\";\r\nimport { requestJson } from \"../client/http\";\r\nimport type { ReadOptions } from \"./types\";\r\n\r\nexport function createCurrentWeekModule(config: InternalClientConfig) {\r\n return {\r\n async get(options: ReadOptions = {}): Promise<number> {\r\n return requestJson<number>(config, \"/schedule/current-week\", {\r\n signal: options.signal\r\n });\r\n }\r\n };\r\n}\r\n","import type { InternalClientConfig } from \"../client/types\";\r\nimport { requestJson } from \"../client/http\";\r\nimport type { Department } from \"../types/catalog\";\r\nimport type { ReadOptions } from \"./types\";\r\n\r\nexport function createDepartmentsModule(config: InternalClientConfig) {\r\n return {\r\n async listAll(options: ReadOptions = {}): Promise<Department[]> {\r\n return requestJson<Department[]>(config, \"/departments\", {\r\n signal: options.signal\r\n });\r\n }\r\n };\r\n}\r\n","import type { InternalClientConfig } from \"../client/types\";\r\nimport { requestJson } from \"../client/http\";\r\nimport type { EmployeeCatalogItem } from \"../types/employee\";\r\nimport type { ReadOptions } from \"./types\";\r\n\r\nexport function createEmployeesModule(config: InternalClientConfig) {\r\n return {\r\n async listAll(options: ReadOptions = {}): Promise<EmployeeCatalogItem[]> {\r\n return requestJson<EmployeeCatalogItem[]>(config, \"/employees/all\", {\r\n signal: options.signal\r\n });\r\n }\r\n };\r\n}\r\n","import type { InternalClientConfig } from \"../client/types\";\r\nimport { requestJson } from \"../client/http\";\r\nimport type { Faculty } from \"../types/catalog\";\r\nimport type { ReadOptions } from \"./types\";\r\n\r\nexport function createFacultiesModule(config: InternalClientConfig) {\r\n return {\r\n async listAll(options: ReadOptions = {}): Promise<Faculty[]> {\r\n return requestJson<Faculty[]>(config, \"/faculties\", {\r\n signal: options.signal\r\n });\r\n }\r\n };\r\n}\r\n","import type { InternalClientConfig } from \"../client/types\";\r\nimport { requestJson } from \"../client/http\";\r\nimport type { StudentGroupCatalogItem } from \"../types/catalog\";\r\nimport type { ReadOptions } from \"./types\";\r\n\r\nexport function createGroupsModule(config: InternalClientConfig) {\r\n return {\r\n async listAll(options: ReadOptions = {}): Promise<StudentGroupCatalogItem[]> {\r\n return requestJson<StudentGroupCatalogItem[]>(config, \"/student-groups\", {\r\n signal: options.signal\r\n });\r\n }\r\n };\r\n}\r\n","import type { InternalClientConfig } from \"../client/types\";\r\nimport { requestJson } from \"../client/http\";\r\nimport { assertNonEmptyString, assertPositiveInt } from \"../utils/guards\";\r\nimport type { ApiDateResponse } from \"../types/common\";\r\nimport type { ReadOptions } from \"./types\";\r\n\r\nexport function createLastUpdateModule(config: InternalClientConfig) {\r\n return {\r\n async byGroup(\r\n params: { groupNumber: string } | { id: number },\r\n options: ReadOptions = {}\r\n ): Promise<ApiDateResponse> {\r\n let query: Record<string, string | number>;\r\n if (\"groupNumber\" in params) {\r\n assertNonEmptyString(params.groupNumber, \"groupNumber\");\r\n query = { groupNumber: params.groupNumber };\r\n } else {\r\n assertPositiveInt(params.id, \"id\");\r\n query = { id: params.id };\r\n }\r\n\r\n return requestJson<ApiDateResponse>(config, \"/last-update-date/student-group\", {\r\n query,\r\n signal: options.signal\r\n });\r\n },\r\n\r\n async byEmployee(\r\n params: { urlId: string } | { id: number },\r\n options: ReadOptions = {}\r\n ): Promise<ApiDateResponse> {\r\n let query: Record<string, string | number>;\r\n if (\"urlId\" in params) {\r\n assertNonEmptyString(params.urlId, \"urlId\");\r\n query = { \"url-id\": params.urlId };\r\n } else {\r\n assertPositiveInt(params.id, \"id\");\r\n query = { id: params.id };\r\n }\r\n\r\n return requestJson<ApiDateResponse>(config, \"/last-update-date/employee\", {\r\n query,\r\n signal: options.signal\r\n });\r\n }\r\n };\r\n}\r\n","import type { InternalClientConfig } from \"../client/types\";\r\nimport { requestJson } from \"../client/http\";\r\nimport { assertNonEmptyString, assertPositiveInt } from \"../utils/guards\";\r\nimport type {\r\n FlattenedScheduleItem,\r\n NormalizedScheduleResponse,\r\n ScheduleResponse\r\n} from \"../types/schedule\";\r\nimport type { ApiDateResponse } from \"../types/common\";\r\nimport type { Weekday } from \"../types/common\";\r\nimport type { ReadOptions } from \"./types\";\r\n\r\nconst WEEKDAYS: Weekday[] = [\r\n \"Понедельник\",\r\n \"Вторник\",\r\n \"Среда\",\r\n \"Четверг\",\r\n \"Пятница\",\r\n \"Суббота\"\r\n];\r\n\r\nfunction normalizeSchedule(response: ScheduleResponse): NormalizedScheduleResponse {\r\n const lessons: FlattenedScheduleItem[] = [];\r\n for (const day of WEEKDAYS) {\r\n const dayItems = response.schedules[day] ?? [];\r\n for (const item of dayItems) {\r\n lessons.push({ ...item, day, source: \"schedules\" });\r\n }\r\n }\r\n\r\n for (const exam of response.exams) {\r\n lessons.push({\r\n ...exam,\r\n day: null,\r\n // Exams are not grouped by weekday in API response.\r\n source: \"exams\"\r\n });\r\n }\r\n\r\n return {\r\n ...response,\r\n lessons\r\n };\r\n}\r\n\r\nexport function createScheduleModule(config: InternalClientConfig) {\r\n return {\r\n async getGroup(\r\n groupNumber: string,\r\n options: ReadOptions = {}\r\n ): Promise<ScheduleResponse | NormalizedScheduleResponse> {\r\n assertNonEmptyString(groupNumber, \"groupNumber\");\r\n const response = await requestJson<ScheduleResponse>(config, \"/schedule\", {\r\n query: { studentGroup: groupNumber },\r\n signal: options.signal\r\n });\r\n return options.raw ?? config.defaultRaw ? response : normalizeSchedule(response);\r\n },\r\n\r\n async getEmployee(\r\n urlId: string,\r\n options: ReadOptions = {}\r\n ): Promise<ScheduleResponse | NormalizedScheduleResponse> {\r\n assertNonEmptyString(urlId, \"urlId\");\r\n const response = await requestJson<ScheduleResponse>(config, `/employees/schedule/${urlId}`, {\r\n signal: options.signal\r\n });\r\n return options.raw ?? config.defaultRaw ? response : normalizeSchedule(response);\r\n },\r\n\r\n async getCurrentWeek(options: ReadOptions = {}): Promise<number> {\r\n return requestJson<number>(config, \"/schedule/current-week\", { signal: options.signal });\r\n },\r\n\r\n async getLastUpdateByGroup(\r\n params: { groupNumber: string } | { id: number },\r\n options: ReadOptions = {}\r\n ): Promise<ApiDateResponse> {\r\n let query: Record<string, string | number>;\r\n if (\"groupNumber\" in params) {\r\n assertNonEmptyString(params.groupNumber, \"groupNumber\");\r\n query = { groupNumber: params.groupNumber };\r\n } else {\r\n assertPositiveInt(params.id, \"id\");\r\n query = { id: params.id };\r\n }\r\n return requestJson<ApiDateResponse>(config, \"/last-update-date/student-group\", {\r\n query,\r\n signal: options.signal\r\n });\r\n },\r\n\r\n async getLastUpdateByEmployee(\r\n params: { urlId: string } | { id: number },\r\n options: ReadOptions = {}\r\n ): Promise<ApiDateResponse> {\r\n let query: Record<string, string | number>;\r\n if (\"urlId\" in params) {\r\n assertNonEmptyString(params.urlId, \"urlId\");\r\n query = { \"url-id\": params.urlId };\r\n } else {\r\n assertPositiveInt(params.id, \"id\");\r\n query = { id: params.id };\r\n }\r\n return requestJson<ApiDateResponse>(config, \"/last-update-date/employee\", {\r\n query,\r\n signal: options.signal\r\n });\r\n }\r\n };\r\n}\r\n","import type { InternalClientConfig } from \"../client/types\";\r\nimport { requestJson } from \"../client/http\";\r\nimport type { Speciality } from \"../types/catalog\";\r\nimport type { ReadOptions } from \"./types\";\r\n\r\nexport function createSpecialitiesModule(config: InternalClientConfig) {\r\n return {\r\n async listAll(options: ReadOptions = {}): Promise<Speciality[]> {\r\n return requestJson<Speciality[]>(config, \"/specialities\", {\r\n signal: options.signal\r\n });\r\n }\r\n };\r\n}\r\n","import type { BsuirClientOptions, InternalClientConfig } from \"./types\";\r\nimport { createAnnouncementsModule } from \"../modules/announcements\";\r\nimport { createAuditoriesModule } from \"../modules/auditories\";\r\nimport { createCurrentWeekModule } from \"../modules/currentWeek\";\r\nimport { createDepartmentsModule } from \"../modules/departments\";\r\nimport { createEmployeesModule } from \"../modules/employees\";\r\nimport { createFacultiesModule } from \"../modules/faculties\";\r\nimport { createGroupsModule } from \"../modules/groups\";\r\nimport { createLastUpdateModule } from \"../modules/lastUpdate\";\r\nimport { createScheduleModule } from \"../modules/schedule\";\r\nimport { createSpecialitiesModule } from \"../modules/specialities\";\r\n\r\nconst DEFAULT_BASE_URL = \"https://iis.bsuir.by/api/v1\";\r\n\r\nfunction resolveFetch(customFetch?: typeof globalThis.fetch): typeof globalThis.fetch {\r\n if (customFetch) {\r\n return customFetch;\r\n }\r\n\r\n if (typeof globalThis.fetch !== \"function\") {\r\n throw new Error(\"Global fetch is unavailable. Provide 'fetch' in createBsuirClient options.\");\r\n }\r\n\r\n return globalThis.fetch;\r\n}\r\n\r\nfunction createInternalConfig(options: BsuirClientOptions = {}): InternalClientConfig {\r\n return {\r\n baseUrl: options.baseUrl ?? DEFAULT_BASE_URL,\r\n fetchImpl: resolveFetch(options.fetch),\r\n timeoutMs: options.timeoutMs ?? 10_000,\r\n retries: options.retries ?? 1,\r\n retryDelayMs: options.retryDelayMs ?? 300,\r\n userAgent: options.userAgent,\r\n defaultRaw: options.defaultRaw ?? false\r\n };\r\n}\r\n\r\nexport function createBsuirClient(options: BsuirClientOptions = {}) {\r\n const config = createInternalConfig(options);\r\n\r\n return {\r\n schedule: createScheduleModule(config),\r\n groups: createGroupsModule(config),\r\n employees: createEmployeesModule(config),\r\n faculties: createFacultiesModule(config),\r\n departments: createDepartmentsModule(config),\r\n specialities: createSpecialitiesModule(config),\r\n announcements: createAnnouncementsModule(config),\r\n auditories: createAuditoriesModule(config),\r\n lastUpdate: createLastUpdateModule(config),\r\n currentWeek: createCurrentWeekModule(config)\r\n };\r\n}\r\n\r\nexport type BsuirClient = ReturnType<typeof createBsuirClient>;\r\n"],"mappings":"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","names":[]}
|
package/package.json
ADDED
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "bsuir-iis-api",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Type-safe ESM SDK for BSUIR IIS API",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"author": "kotru21",
|
|
7
|
+
"license": "MIT",
|
|
8
|
+
"repository": {
|
|
9
|
+
"type": "git",
|
|
10
|
+
"url": "https://github.com/kotru21/bsuir-iis-api.git"
|
|
11
|
+
},
|
|
12
|
+
"homepage": "https://github.com/kotru21/bsuir-iis-api#readme",
|
|
13
|
+
"bugs": {
|
|
14
|
+
"url": "https://github.com/kotru21/bsuir-iis-api/issues"
|
|
15
|
+
},
|
|
16
|
+
"keywords": [
|
|
17
|
+
"bsuir",
|
|
18
|
+
"iis",
|
|
19
|
+
"schedule",
|
|
20
|
+
"api",
|
|
21
|
+
"sdk",
|
|
22
|
+
"typescript"
|
|
23
|
+
],
|
|
24
|
+
"engines": {
|
|
25
|
+
"node": ">=18"
|
|
26
|
+
},
|
|
27
|
+
"exports": {
|
|
28
|
+
".": {
|
|
29
|
+
"types": "./dist/index.d.ts",
|
|
30
|
+
"import": "./dist/index.js"
|
|
31
|
+
}
|
|
32
|
+
},
|
|
33
|
+
"main": "./dist/index.js",
|
|
34
|
+
"types": "./dist/index.d.ts",
|
|
35
|
+
"files": [
|
|
36
|
+
"dist",
|
|
37
|
+
"README.md",
|
|
38
|
+
"CHANGELOG.md",
|
|
39
|
+
"LICENSE"
|
|
40
|
+
],
|
|
41
|
+
"scripts": {
|
|
42
|
+
"build": "tsup",
|
|
43
|
+
"dev": "tsup --watch",
|
|
44
|
+
"typecheck": "tsc --noEmit",
|
|
45
|
+
"lint": "eslint .",
|
|
46
|
+
"test": "vitest run",
|
|
47
|
+
"test:coverage": "vitest run --coverage",
|
|
48
|
+
"check": "npm run lint && npm run typecheck && npm run test",
|
|
49
|
+
"release:dry": "npm pack --dry-run"
|
|
50
|
+
},
|
|
51
|
+
"devDependencies": {
|
|
52
|
+
"@changesets/cli": "^2.29.7",
|
|
53
|
+
"@eslint/js": "^9.38.0",
|
|
54
|
+
"@types/node": "^24.7.2",
|
|
55
|
+
"@typescript-eslint/eslint-plugin": "^8.46.1",
|
|
56
|
+
"@typescript-eslint/parser": "^8.46.1",
|
|
57
|
+
"@vitest/coverage-v8": "^3.2.4",
|
|
58
|
+
"eslint": "^9.38.0",
|
|
59
|
+
"eslint-config-prettier": "^10.1.8",
|
|
60
|
+
"globals": "^16.4.0",
|
|
61
|
+
"prettier": "^3.6.2",
|
|
62
|
+
"tsup": "^8.5.0",
|
|
63
|
+
"typescript": "^5.9.3",
|
|
64
|
+
"vitest": "^3.2.4"
|
|
65
|
+
}
|
|
66
|
+
}
|