@campusiq/sdk
Version:
Official JavaScript/TypeScript SDK for CampusIQ - A comprehensive school management system API
536 lines (524 loc) • 16.3 kB
JavaScript
;
class CampusIQError extends Error {
constructor(message, statusCode = 500, code = 'UNKNOWN_ERROR', requestId) {
super(message);
this.name = 'CampusIQError';
this.statusCode = statusCode;
this.code = code;
this.requestId = requestId;
// Maintains proper stack trace for where our error was thrown (only available on V8)
if (Error.captureStackTrace) {
Error.captureStackTrace(this, CampusIQError);
}
}
toJSON() {
return {
name: this.name,
message: this.message,
statusCode: this.statusCode,
code: this.code,
requestId: this.requestId,
stack: this.stack
};
}
static isNetworkError(error) {
return error instanceof CampusIQError && error.code === 'NETWORK_ERROR';
}
static isAuthenticationError(error) {
return error instanceof CampusIQError && error.statusCode === 401;
}
static isAuthorizationError(error) {
return error instanceof CampusIQError && error.statusCode === 403;
}
static isNotFoundError(error) {
return error instanceof CampusIQError && error.statusCode === 404;
}
static isRateLimitError(error) {
return error instanceof CampusIQError && error.statusCode === 429;
}
static isServerError(error) {
return error instanceof CampusIQError && error.statusCode >= 500;
}
}
class BaseResource {
constructor(client) {
this.client = client;
}
async requestGet(endpoint, params) {
try {
const url = new URL(`${this.client.baseURL}${endpoint}`);
if (params) {
Object.entries(params).forEach(([key, value]) => {
if (value !== undefined && value !== null) {
if (Array.isArray(value)) {
value.forEach(v => url.searchParams.append(key, String(v)));
}
else {
url.searchParams.append(key, String(value));
}
}
});
}
const response = await fetch(url.toString(), {
method: 'GET',
headers: {
'Authorization': `Bearer ${this.client.apiKey}`,
'X-School-ID': this.client.schoolId,
'Content-Type': 'application/json',
'User-Agent': `CampusIQ-SDK/${this.client.version}`,
},
});
if (!response.ok) {
const errorText = await response.text();
throw new CampusIQError(`HTTP ${response.status}: ${response.statusText}`, response.status, errorText);
}
return await response.json();
}
catch (error) {
if (error instanceof CampusIQError)
throw error;
throw new CampusIQError(`Request failed: ${error.message}`, 0, error.message);
}
}
async requestPost(endpoint, data) {
return this.sendRequest('POST', endpoint, data);
}
async requestPut(endpoint, data) {
return this.sendRequest('PUT', endpoint, data);
}
async requestPatch(endpoint, data) {
return this.sendRequest('PATCH', endpoint, data);
}
async requestDelete(endpoint) {
return this.sendRequest('DELETE', endpoint);
}
async sendRequest(method, endpoint, data) {
try {
const response = await fetch(`${this.client.baseURL}${endpoint}`, {
method,
headers: {
'Authorization': `Bearer ${this.client.apiKey}`,
'X-School-ID': this.client.schoolId,
'Content-Type': 'application/json',
'User-Agent': `CampusIQ-SDK/${this.client.version}`,
},
body: data ? JSON.stringify(data) : undefined,
});
if (!response.ok) {
const errorText = await response.text();
throw new CampusIQError(`HTTP ${response.status}: ${response.statusText}`, response.status, errorText);
}
return await response.json();
}
catch (error) {
if (error instanceof CampusIQError)
throw error;
throw new CampusIQError(`Request failed: ${error.message}`, 0, error.message);
}
}
}
class StudentsResource extends BaseResource {
/**
* List all students with optional filtering and pagination
*/
async list(filters) {
return super.requestGet('/students', filters);
}
/**
* Get a specific student by ID
*/
async get(studentId) {
return super.requestGet(`/students/${studentId}`);
}
/**
* Create a new student
*/
async create(data) {
return super.requestPost('/students', data);
}
/**
* Update an existing student
*/
async update(studentId, data) {
return super.requestPatch(`/students/${studentId}`, data);
}
/**
* Delete a student
*/
async delete(studentId) {
return super.requestDelete(`/students/${studentId}`);
}
/**
* Get student's enrollment history
*/
async getEnrollments(studentId, filters) {
return super.requestGet(`/students/${studentId}/enrollments`, filters);
}
/**
* Get student's grades
*/
async getGrades(studentId, filters) {
return super.requestGet(`/students/${studentId}/grades`, filters);
}
/**
* Get student's attendance records
*/
async getAttendance(studentId, filters) {
return super.requestGet(`/students/${studentId}/attendance`, filters);
}
/**
* Bulk create students
*/
async bulkCreate(students) {
return super.requestPost('/students/bulk', { students });
}
/**
* Search students by name or email
*/
async search(query, filters) {
return super.requestGet('/students/search', { q: query, ...filters });
}
}
class TeachersResource extends BaseResource {
/**
* List all teachers with optional filtering and pagination
*/
async list(filters) {
return super.requestGet('/teachers', filters);
}
/**
* Get a specific teacher by ID
*/
async get(teacherId) {
return super.requestGet(`/teachers/${teacherId}`);
}
/**
* Create a new teacher
*/
async create(data) {
return super.requestPost('/teachers', data);
}
/**
* Update an existing teacher
*/
async update(teacherId, data) {
return super.requestPatch(`/teachers/${teacherId}`, data);
}
/**
* Delete a teacher
*/
async delete(teacherId) {
return super.requestDelete(`/teachers/${teacherId}`);
}
/**
* Get teacher's courses
*/
async getCourses(teacherId, filters) {
return super.requestGet(`/teachers/${teacherId}/courses`, filters);
}
/**
* Get teacher's schedule
*/
async getSchedule(teacherId, filters) {
return super.requestGet(`/teachers/${teacherId}/schedule`, filters);
}
/**
* Search teachers by name, email, or department
*/
async search(query, filters) {
return super.requestGet('/teachers/search', { q: query, ...filters });
}
}
class CoursesResource extends BaseResource {
/**
* List all courses with optional filtering and pagination
*/
async list(filters) {
return super.requestGet('/courses', filters);
}
/**
* Get a specific course by ID
*/
async get(courseId) {
return super.requestGet(`/courses/${courseId}`);
}
/**
* Create a new course
*/
async create(data) {
return super.requestPost('/courses', data);
}
/**
* Update an existing course
*/
async update(courseId, data) {
return super.requestPatch(`/courses/${courseId}`, data);
}
/**
* Delete a course
*/
async delete(courseId) {
return super.requestDelete(`/courses/${courseId}`);
}
/**
* Get course enrollments
*/
async getEnrollments(courseId, filters) {
return super.requestGet(`/courses/${courseId}/enrollments`, filters);
}
/**
* Get course grades
*/
async getGrades(courseId, filters) {
return super.requestGet(`/courses/${courseId}/grades`, filters);
}
/**
* Get course attendance
*/
async getAttendance(courseId, filters) {
return super.requestGet(`/courses/${courseId}/attendance`, filters);
}
/**
* Search courses by name, code, or description
*/
async search(query, filters) {
return super.requestGet('/courses/search', { q: query, ...filters });
}
}
class EnrollmentsResource extends BaseResource {
/**
* List all enrollments with optional filtering and pagination
*/
async list(filters) {
return super.requestGet('/enrollments', filters);
}
/**
* Get a specific enrollment by ID
*/
async get(enrollmentId) {
return super.requestGet(`/enrollments/${enrollmentId}`);
}
/**
* Create a new enrollment
*/
async create(data) {
return super.requestPost('/enrollments', data);
}
/**
* Update an existing enrollment
*/
async update(enrollmentId, data) {
return super.requestPatch(`/enrollments/${enrollmentId}`, data);
}
/**
* Delete an enrollment
*/
async delete(enrollmentId) {
return super.requestDelete(`/enrollments/${enrollmentId}`);
}
/**
* Bulk enroll students in a course
*/
async bulkEnroll(courseId, studentIds, semester) {
return super.requestPost('/enrollments/bulk', {
courseId,
studentIds,
semester
});
}
/**
* Drop a student from a course
*/
async drop(enrollmentId, reason) {
return super.requestPatch(`/enrollments/${enrollmentId}/drop`, { reason });
}
/**
* Complete an enrollment (mark as completed)
*/
async complete(enrollmentId, finalGrade) {
return super.requestPatch(`/enrollments/${enrollmentId}/complete`, { finalGrade });
}
}
class GradesResource extends BaseResource {
/**
* List all grades with optional filtering and pagination
*/
async list(filters) {
return super.requestGet('/grades', filters);
}
/**
* Get a specific grade by ID
*/
async get(gradeId) {
return super.requestGet(`/grades/${gradeId}`);
}
/**
* Create a new grade
*/
async create(data) {
return super.requestPost('/grades', data);
}
/**
* Update an existing grade
*/
async update(gradeId, data) {
return super.requestPatch(`/grades/${gradeId}`, data);
}
/**
* Delete a grade
*/
async delete(gradeId) {
return super.requestDelete(`/grades/${gradeId}`);
}
/**
* Bulk create grades for multiple students
*/
async bulkCreate(grades) {
return super.requestPost('/grades/bulk', { grades });
}
/**
* Get grade statistics for a course
*/
async getCourseStats(courseId, filters) {
return super.requestGet(`/grades/stats/course/${courseId}`, filters);
}
/**
* Get grade statistics for a student
*/
async getStudentStats(studentId, filters) {
return super.requestGet(`/grades/stats/student/${studentId}`, filters);
}
}
class AttendanceResource extends BaseResource {
/**
* List all attendance records with optional filtering and pagination
*/
async list(filters) {
return super.requestGet('/attendance', filters);
}
/**
* Get a specific attendance record by ID
*/
async getAttendance(attendanceId) {
return super.requestGet(`/attendance/${attendanceId}`);
}
/**
* Create a new attendance record
*/
async createAttendance(data) {
return super.requestPost('/attendance', data);
}
/**
* Update an existing attendance record
*/
async updateAttendance(attendanceId, data) {
return super.requestPatch(`/attendance/${attendanceId}`, data);
}
/**
* Delete an attendance record
*/
async deleteAttendance(attendanceId) {
return super.requestDelete(`/attendance/${attendanceId}`);
}
/**
* Bulk create attendance records
*/
async bulkCreate(records) {
return super.requestPost('/attendance/bulk', { records });
}
/**
* Get attendance statistics for a student
*/
async getStudentStats(studentId, filters) {
return super.requestGet(`/attendance/student/${studentId}/stats`, filters);
}
/**
* Get attendance statistics for a course
*/
async getCourseStats(courseId, filters) {
return super.requestGet(`/attendance/course/${courseId}/stats`, filters);
}
/**
* Mark attendance for multiple students
*/
async markBulkAttendance(courseId, date, records) {
return super.requestPost(`/attendance/course/${courseId}/bulk`, { date, records });
}
}
class WebhooksResource extends BaseResource {
async list(filters) {
return this.requestGet('/webhooks', filters);
}
async get(webhookId) {
return this.requestGet(`/webhooks/${webhookId}`);
}
async create(data) {
return this.requestPost('/webhooks', data);
}
async update(webhookId, data) {
return this.requestPatch(`/webhooks/${webhookId}`, data);
}
async delete(webhookId) {
return this.requestDelete(`/webhooks/${webhookId}`);
}
async test(webhookId) {
return this.requestPost(`/webhooks/${webhookId}/test`, {});
}
async getLogs(webhookId, filters) {
return this.requestGet(`/webhooks/${webhookId}/logs`, filters);
}
verifySignature(payload, signature, secret) {
const crypto = require('crypto');
const expectedSignature = crypto
.createHmac('sha256', secret)
.update(payload)
.digest('hex');
return signature === `sha256=${expectedSignature}`;
}
}
class CampusIQClient {
constructor(config) {
this.version = '1.0.0';
if (!config.apiKey) {
throw new CampusIQError('API key is required', 400, 'MISSING_API_KEY');
}
if (!config.schoolId) {
throw new CampusIQError('School ID is required', 400, 'MISSING_SCHOOL_ID');
}
this.apiKey = config.apiKey;
this.schoolId = config.schoolId;
this.timeout = config.timeout || 30000;
this.debug = config.debug || false;
this.baseURL = config.baseURL ||
(config.environment === 'sandbox'
? 'https://sandbox-api.campusiq.edu/v1'
: 'https://api.campusiq.edu/v1');
// Initialize all resources
this.students = new StudentsResource(this);
this.teachers = new TeachersResource(this);
this.courses = new CoursesResource(this);
this.enrollments = new EnrollmentsResource(this);
this.grades = new GradesResource(this);
this.attendance = new AttendanceResource(this);
this.webhooks = new WebhooksResource(this);
}
static verifyWebhook(payload, signature, secret) {
const crypto = require('crypto');
const expectedSignature = crypto
.createHmac('sha256', secret)
.update(JSON.stringify(payload))
.digest('hex');
return signature === `sha256=${expectedSignature}`;
}
}
exports.AttendanceResource = AttendanceResource;
exports.BaseResource = BaseResource;
exports.CampusIQClient = CampusIQClient;
exports.CampusIQError = CampusIQError;
exports.CoursesResource = CoursesResource;
exports.EnrollmentsResource = EnrollmentsResource;
exports.GradesResource = GradesResource;
exports.StudentsResource = StudentsResource;
exports.TeachersResource = TeachersResource;
exports.WebhooksResource = WebhooksResource;
//# sourceMappingURL=index.cjs.js.map