1
0
Fork 0
mirror of https://github.com/classchartsapi/classcharts-api-js.git synced 2026-05-14 11:58:13 +00:00

feat: better documentation

This commit is contained in:
James Cook 2023-04-16 20:47:40 +01:00
parent 58c5dfa1e4
commit 3aa119a063
12 changed files with 141 additions and 44 deletions

4
.gitignore vendored
View file

@ -118,4 +118,6 @@ dist
.pnp.* .pnp.*
tests/config.json tests/config.json
tests/sandbox.js tests/sandbox.js
docs/

View file

@ -4,4 +4,4 @@
"esbenp.prettier-vscode", "esbenp.prettier-vscode",
"EditorConfig.EditorConfig" "EditorConfig.EditorConfig"
] ]
} }

View file

@ -19,7 +19,7 @@
"main": "./dist/index.js", "main": "./dist/index.js",
"scripts": { "scripts": {
"build": "tsc", "build": "tsc",
"generateDocs": "typedoc --entryPointStrategy expand ./src", "generateDocs": "typedoc --options typedoc.config.cjs",
"test": "jest", "test": "jest",
"prepublishOnly": "pnpm run build", "prepublishOnly": "pnpm run build",
"publishNow": "pnpx np --no-publish && npm publish" "publishNow": "pnpx np --no-publish && npm publish"

View file

@ -2,10 +2,12 @@
A client for the classcharts API A client for the classcharts API
* [Documentation](https://classchartsapi.github.io/classcharts-api-js/) - [Documentation](https://classchartsapi.github.io/classcharts-api-js/)
* [API Documentation (with library examples)](https://classchartsapi.github.io/api-docs/#introduction) - [API Documentation (with library examples)](https://classchartsapi.github.io/api-docs/#introduction)
* [Discord](https://discord.gg/DTcwugcgZ2) - [Discord](https://discord.gg/DTcwugcgZ2)
# Examples # Examples
Docs are very much a WIP, for any help with the library, please join the discord above Docs are very much a WIP, for any help with the library, please join the discord above
```typescript ```typescript

View file

@ -20,13 +20,31 @@ import type {
import { PING_INTERVAL } from "./consts.js"; import { PING_INTERVAL } from "./consts.js";
/** /**
* The base client * Shared client for both parent and student. This is not exported and should not be used directly
* @internal
*/ */
export class ClasschartsClient { export class BaseClient {
/**
* @property studentId Currently selected student ID
*/
public studentId = 0; public studentId = 0;
/**
* @internal
* @property authCookies Cookies used for authentication (set during login and can be empty)
*/
public authCookies: Array<string>; public authCookies: Array<string>;
/**
* @property sessionId Session ID used for authentication
*/
public sessionId = ""; public sessionId = "";
/**
* @property lastPing Last time the sessionId was updated
*/
public lastPing = 0; public lastPing = 0;
/**
* @property API_BASE Base API URL, this is different depending if its called as a parent or student
* @internal
*/
protected API_BASE = ""; protected API_BASE = "";
/** /**
* *
@ -36,6 +54,12 @@ export class ClasschartsClient {
this.authCookies = []; this.authCookies = [];
this.API_BASE = API_BASE; this.API_BASE = API_BASE;
} }
/**
* Revalidates the session ID.
*
* This is called automatically when the session ID is older than 3 minutes or when intially using the .login() method
* @internal
*/
public async getNewSessionId() { public async getNewSessionId() {
const pingFormData = new URLSearchParams(); const pingFormData = new URLSearchParams();
pingFormData.append("include_data", "true"); pingFormData.append("include_data", "true");
@ -50,6 +74,17 @@ export class ClasschartsClient {
this.sessionId = pingData.meta.session_id; this.sessionId = pingData.meta.session_id;
this.lastPing = Date.now(); this.lastPing = Date.now();
} }
/**
* Makes a request to the Classcharts API with the required authentication headers
*
* @param path Path to the API endpoint
* @param kyOptions Ky (fetch library) request options
* @param options
* @param options.revalidateToken Whether to revalidate the session ID if it is older than 3 minutes
*
* @returns Response
* @internal
*/
public async makeAuthedRequest( public async makeAuthedRequest(
path: string, path: string,
kyOptions: KyOptions, kyOptions: KyOptions,
@ -87,9 +122,8 @@ export class ClasschartsClient {
// eslint-disable-next-line @typescript-eslint/no-explicit-any // eslint-disable-next-line @typescript-eslint/no-explicit-any
return responseJSON as any; return responseJSON as any;
} }
/** /**
* Gets general information about the logged in student * Gets general information about the current student
* @returns Student object * @returns Student object
*/ */
async getStudentInfo(): Promise<GetStudentInfoResponse> { async getStudentInfo(): Promise<GetStudentInfoResponse> {
@ -102,9 +136,12 @@ export class ClasschartsClient {
return data; return data;
} }
/** /**
* Gets the current student's activity
*
* This function is only used for pagination, you likely want client.getFullActivity * This function is only used for pagination, you likely want client.getFullActivity
* @param options GetActivityOptions * @param options GetActivityOptions
* @returns Activity data * @returns Activity data
* @see getFullActivity
*/ */
async getActivity(options?: GetActivityOptions): Promise<ActivityResponse> { async getActivity(options?: GetActivityOptions): Promise<ActivityResponse> {
const params = new URLSearchParams(); const params = new URLSearchParams();
@ -119,9 +156,12 @@ export class ClasschartsClient {
); );
} }
/** /**
* Helper function for getActivity, returns all the data from the selected dates * Gets the current student's activity between two dates
*
* This function will automatically paginate through all the data returned by getActivity
* @param options GetFullActivityOptions * @param options GetFullActivityOptions
* @returns Activity Data * @returns Activity Data
* @see getActivity
*/ */
async getFullActivity( async getFullActivity(
options: GetFullActivityOptions options: GetFullActivityOptions
@ -148,7 +188,7 @@ export class ClasschartsClient {
return data; return data;
} }
/** /**
* Gets the logged in students behaviour points * Gets the current student's behaviour
* @param options GetBehaviourOptions * @param options GetBehaviourOptions
* @returns Array of behaviour points * @returns Array of behaviour points
*/ */
@ -166,7 +206,7 @@ export class ClasschartsClient {
); );
} }
/** /**
* Gets a list of the logged in student's homeworks * Gets the current student's homework
* @param options GetHomeworkOptions * @param options GetHomeworkOptions
* @returns Array of homeworks * @returns Array of homeworks
*/ */
@ -200,7 +240,7 @@ export class ClasschartsClient {
return data; return data;
} }
/** /**
* Gets the logged in student's lessons for a day * Gets the current student's lessons for a given date
* @param options GetLessonsOptions * @param options GetLessonsOptions
* @returns Array of lessons * @returns Array of lessons
*/ */
@ -216,7 +256,7 @@ export class ClasschartsClient {
); );
} }
/** /**
* Gets a list of the students badges * Gets the current student's earned badges
* @returns Array of badges * @returns Array of badges
*/ */
async getBadges(): Promise<BadgesResponse> { async getBadges(): Promise<BadgesResponse> {
@ -228,7 +268,7 @@ export class ClasschartsClient {
); );
} }
/** /**
* Gets the logged in student's announcements * Gets the current student's announcements
* @returns Array of announcements * @returns Array of announcements
*/ */
async getAnnouncements(): Promise<AnnouncementsResponse> { async getAnnouncements(): Promise<AnnouncementsResponse> {
@ -242,7 +282,7 @@ export class ClasschartsClient {
).data; ).data;
} }
/** /**
* Gets the logged in student's detentions * Gets the current student's detentions
* @returns Array of detentions * @returns Array of detentions
*/ */
async getDetentions(): Promise<DetentionsResponse> { async getDetentions(): Promise<DetentionsResponse> {
@ -256,7 +296,7 @@ export class ClasschartsClient {
).data; ).data;
} }
/** /**
* Gets the logged in student's attendance * Gets the current student's attendance
* @param options GetAttendanceOptions * @param options GetAttendanceOptions
* @returns Array of dates of attendance * @returns Array of dates of attendance
*/ */

View file

@ -1,2 +1,13 @@
export * from "./parentClient.js";
export * from "./studentClient.js"; export * from "./studentClient.js";
export * from "./parentClient.js";
export {
Student,
ActivityPoint,
BehaviourTimelinePoint,
Homework,
Lesson,
Badge,
Announcement,
Detention,
AttendanceDate,
} from "./types.js";

View file

@ -1,21 +1,21 @@
import ky from "ky-universal"; import ky from "ky-universal";
import type { GetPupilsResponse } from "./types.js"; import type { GetPupilsResponse } from "./types.js";
import { ClasschartsClient } from "./baseClient.js"; import { BaseClient } from "./baseClient.js";
import { API_BASE_PARENT, BASE_URL } from "./consts.js"; import { API_BASE_PARENT, BASE_URL } from "./consts.js";
import { parseCookies } from "./utils.js"; import { parseCookies } from "./utils.js";
/** /**
* Parent Client * Parent Client
*/ */
export class ParentClient extends ClasschartsClient { export class ParentClient extends BaseClient {
private password = ""; private password = "";
private email = ""; private email = "";
// @ts-expect-error Init in .login // @ts-expect-error Init in .login
public pupils: GetPupilsResponse; public pupils: GetPupilsResponse;
/** /**
* *
* @param email Parents email address * @param email Parent's email address
* @param password Parents password * @param password Parent's password
*/ */
constructor(email: string, password: string) { constructor(email: string, password: string) {
super(API_BASE_PARENT); super(API_BASE_PARENT);
@ -24,7 +24,7 @@ export class ParentClient extends ClasschartsClient {
} }
/** /**
* Logs the user in the client and authenticates with classcharts * Authenticates with classcharts
*/ */
async login(): Promise<void> { async login(): Promise<void> {
if (!this.email) throw new Error("Email not inputted"); if (!this.email) throw new Error("Email not inputted");
@ -63,7 +63,7 @@ export class ParentClient extends ClasschartsClient {
super.studentId = this.pupils[0].id; super.studentId = this.pupils[0].id;
} }
/** /**
* Get Pupil details * Get a list of pupils connected to this parent's account
* @returns an array of Pupils connected to this parent's account * @returns an array of Pupils connected to this parent's account
*/ */
async getPupils(): Promise<GetPupilsResponse> { async getPupils(): Promise<GetPupilsResponse> {
@ -73,7 +73,9 @@ export class ParentClient extends ClasschartsClient {
} }
/** /**
* Selects a pupil to be used with API requests * Selects a pupil to be used with API requests
* @param pupilId Pupil ID obtained from this.pupils or getPupils * @param pupilId Pupil ID obtained from this.pupils or getPupils()
*
* @see getPupils
*/ */
async selectPupil(pupilId: number): Promise<void> { async selectPupil(pupilId: number): Promise<void> {
if (!pupilId) throw new Error("No pupil ID specified"); if (!pupilId) throw new Error("No pupil ID specified");

View file

@ -1,14 +1,22 @@
import { API_BASE_STUDENT, BASE_URL } from "./consts.js"; import { API_BASE_STUDENT, BASE_URL } from "./consts.js";
import { ClasschartsClient } from "./baseClient.js"; import { BaseClient } from "./baseClient.js";
import { parseCookies } from "./utils.js"; import { parseCookies } from "./utils.js";
import ky from "ky-universal"; import ky from "ky-universal";
/** /**
* Student Client * Student Client
*/ */
export class StudentClient extends BaseClient {
export class StudentClient extends ClasschartsClient { /**
public studentCode = ""; * @property studentCode Classcharts student code
public dateOfBirth = ""; * @internal
*/
private studentCode = "";
/**
* @property dateOfBirth Student's date of birth
* @internal
*/
private dateOfBirth = "";
/** /**
* *
@ -22,7 +30,7 @@ export class StudentClient extends ClasschartsClient {
} }
/** /**
* Initialises the client and authenticates with classcharts * Authenticates with classcharts
*/ */
async login(): Promise<void> { async login(): Promise<void> {
if (!this.studentCode) throw new Error("Student Code not inputted"); if (!this.studentCode) throw new Error("Student Code not inputted");

View file

@ -1,4 +1,9 @@
/* eslint-disable @typescript-eslint/no-explicit-any */ /* eslint-disable @typescript-eslint/no-explicit-any */
/**
* Helper type to define response from classcharts
* @internal
*/
export type ClassChartsResponse<T, E> = { export type ClassChartsResponse<T, E> = {
data: T; data: T;
meta: E; meta: E;
@ -44,11 +49,11 @@ export interface Student {
survey_id: number | null; survey_id: number | null;
detention_alias_plural_uc: string; detention_alias_plural_uc: string;
} }
interface GetStudentInfoData { export interface GetStudentInfoData {
user: Student; user: Student;
} }
interface GetStudentInfoMeta { export interface GetStudentInfoMeta {
version: string; version: string;
} }
export type GetStudentInfoResponse = ClassChartsResponse< export type GetStudentInfoResponse = ClassChartsResponse<
@ -74,7 +79,7 @@ export interface BehaviourTimelinePoint {
start: string; start: string;
end: string; end: string;
} }
interface BehaviourResponseData { export interface BehaviourResponseData {
timeline: Array<BehaviourTimelinePoint>; timeline: Array<BehaviourTimelinePoint>;
positive_reasons: Record<string, number>; positive_reasons: Record<string, number>;
negative_reasons: Record<string, number>; negative_reasons: Record<string, number>;
@ -83,7 +88,7 @@ interface BehaviourResponseData {
other_positive_count: Array<Record<string, number>>; other_positive_count: Array<Record<string, number>>;
other_negative_count: Array<Record<string, number>>; other_negative_count: Array<Record<string, number>>;
} }
interface BehaviourResponseMeta { export interface BehaviourResponseMeta {
start_date: string; start_date: string;
end_date: string; end_date: string;
step_size: string; step_size: string;
@ -132,7 +137,7 @@ export interface ActivityPoint {
detention_location: string | null; detention_location: string | null;
detention_type: string | null; detention_type: string | null;
} }
type ActivityResponseData = Array<ActivityPoint>; export type ActivityResponseData = Array<ActivityPoint>;
interface ActivityResponseMeta { interface ActivityResponseMeta {
start_date: string; start_date: string;
end_date: string; end_date: string;
@ -149,6 +154,10 @@ export type DisplayDate = "due_date" | "issue_date";
export interface GetHomeworkOptions { export interface GetHomeworkOptions {
/** /**
* Way to sort homeworks * Way to sort homeworks
*
* Used to sort homeworks by when they are due or when they were issued
* @default "issue_date"
*
*/ */
displayDate?: DisplayDate; displayDate?: DisplayDate;
/** /**
@ -196,8 +205,8 @@ export interface Homework {
validated_links: Array<any>; validated_links: Array<any>;
validated_attachments: Array<ValidatedHomeworkAttachment>; validated_attachments: Array<ValidatedHomeworkAttachment>;
} }
type HomeworksResponseData = Array<Homework>; export type HomeworksResponseData = Array<Homework>;
interface HomeworksResponseMeta { export interface HomeworksResponseMeta {
start_date: string; start_date: string;
end_date: string; end_date: string;
display_type: DisplayDate; display_type: DisplayDate;
@ -238,13 +247,13 @@ export interface Lesson {
pupil_note: string; pupil_note: string;
pupil_note_raw: string; pupil_note_raw: string;
} }
type LessonsResponseData = Lesson[]; export type LessonsResponseData = Lesson[];
interface PeriodMeta { interface PeriodMeta {
number: string; number: string;
start_time: string; start_time: string;
end_time: string; end_time: string;
} }
interface LessonsResponseMeta { export interface LessonsResponseMeta {
dates: string[]; dates: string[];
timetable_dates: string[]; timetable_dates: string[];
periods: PeriodMeta[]; periods: PeriodMeta[];
@ -285,8 +294,8 @@ export interface Badge {
pupil_badges: Array<PupilEvent>; pupil_badges: Array<PupilEvent>;
icon_url: string; icon_url: string;
} }
type BadgesResponseData = Array<Badge>; export type BadgesResponseData = Array<Badge>;
type BadgesResponseMeta = []; export type BadgesResponseMeta = [];
export type BadgesResponse = ClassChartsResponse< export type BadgesResponse = ClassChartsResponse<
BadgesResponseData, BadgesResponseData,
BadgesResponseMeta BadgesResponseMeta

View file

@ -1,3 +1,9 @@
/**
* Parse cookies from string
* @param input Input string
* @returns Object of cookies
* @internal
*/
export function parseCookies(input: string) { export function parseCookies(input: string) {
const output: Record<string, unknown> = {}; const output: Record<string, unknown> = {};
const cookies = input.split(","); const cookies = input.split(",");

View file

@ -1,4 +1,4 @@
{ {
"code": "", "code": "",
"dob": "" "dob": ""
} }

17
typedoc.config.cjs Normal file
View file

@ -0,0 +1,17 @@
/** @type {import('typedoc').TypeDocOptions} */
module.exports = {
entryPointStrategy: "resolve",
entryPoints: [
"src/studentClient.ts",
"src/parentClient.ts",
"src/baseClient.ts",
"src/types.ts",
],
navigationLinks: {
Discord: "https://discord.gg/DTcwugcgZ2",
Github: "https://github.com/classchartsapi/classcharts-api-js",
},
includeVersion: true,
out: "docs",
sort: "required-first",
};