diff --git a/.changeset/red-lobsters-destroy.md b/.changeset/red-lobsters-destroy.md new file mode 100644 index 0000000..9bf5e97 --- /dev/null +++ b/.changeset/red-lobsters-destroy.md @@ -0,0 +1,5 @@ +--- +"classcharts-api": patch +--- + +Export types first diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile deleted file mode 100644 index 7f0043e..0000000 --- a/.devcontainer/Dockerfile +++ /dev/null @@ -1,16 +0,0 @@ -# See here for image contents: https://github.com/microsoft/vscode-dev-containers/tree/v0.209.6/containers/javascript-node/.devcontainer/base.Dockerfile - -# [Choice] Node.js version (use -bullseye variants on local arm64/Apple Silicon): 16, 14, 12, 16-bullseye, 14-bullseye, 12-bullseye, 16-buster, 14-buster, 12-buster -ARG VARIANT="16-bullseye" -FROM mcr.microsoft.com/vscode/devcontainers/javascript-node:0-${VARIANT} - -# [Optional] Uncomment this section to install additional OS packages. -# RUN apt-get update && export DEBIAN_FRONTEND=noninteractive \ -# && apt-get -y install --no-install-recommends - -# [Optional] Uncomment if you want to install an additional version of node using nvm -# ARG EXTRA_NODE_VERSION=10 -# RUN su node -c "source /usr/local/share/nvm/nvm.sh && nvm install ${EXTRA_NODE_VERSION}" - -# [Optional] Uncomment if you want to install more global node modules -RUN su node -c "npm install -g pnpm np" diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json deleted file mode 100644 index af46c9e..0000000 --- a/.devcontainer/devcontainer.json +++ /dev/null @@ -1,24 +0,0 @@ -// For format details, see https://aka.ms/devcontainer.json. For config options, see the README at: -// https://github.com/microsoft/vscode-dev-containers/tree/v0.209.6/containers/javascript-node -{ - "name": "Node.js", - "build": { - "dockerfile": "Dockerfile", - // Update 'VARIANT' to pick a Node version: 16, 14, 12. - // Append -bullseye or -buster to pin to an OS version. - // Use -bullseye variants on local arm64/Apple Silicon. - "args": { - "VARIANT": "16-bullseye" - } - }, - // Set *default* container specific settings.json values on container create. - "settings": {}, - // Add the IDs of extensions you want installed when the container is created. - "extensions": ["dbaeumer.vscode-eslint"], - // Use 'forwardPorts' to make a list of ports inside the container available locally. - // "forwardPorts": [], - // Use 'postCreateCommand' to run commands after the container is created. - "postCreateCommand": "pnpm install", - // Comment out connect as root instead. More info: https://aka.ms/vscode-remote/containers/non-root. - "remoteUser": "node" -} diff --git a/.eslintignore b/.eslintignore index 4462152..2e37f93 100644 --- a/.eslintignore +++ b/.eslintignore @@ -1,5 +1,5 @@ dist/ docs/ node_modules/ -.eslintrc.js +.eslintrc.cjs tsconfig.json \ No newline at end of file diff --git a/.eslintrc.js b/.eslintrc.cjs similarity index 100% rename from .eslintrc.js rename to .eslintrc.cjs diff --git a/.github/workflows/typedoc.yml b/.github/workflows/docs.yml similarity index 75% rename from .github/workflows/typedoc.yml rename to .github/workflows/docs.yml index eab1064..dc0f84e 100644 --- a/.github/workflows/typedoc.yml +++ b/.github/workflows/docs.yml @@ -1,4 +1,4 @@ -name: Typedoc +name: Docs on: push: @@ -19,21 +19,21 @@ jobs: - uses: pnpm/action-setup@v2 with: version: 8.2.0 - - name: Retrieve the cached "node_modules" directory (if present) + - name: Retrieve the cache uses: actions/cache@v3 id: node-cache with: path: node_modules key: node-modules-${{ runner.os }}-${{ hashFiles('pnpm-lock.yaml') }} - - name: Install dependencies (if the cached directory was not found) + - name: Install dependencies if: steps.node-cache.outputs.cache-hit != 'true' run: pnpm install - - name: Test to see if the project compiles + - name: Build run: pnpm run build - - name: Create the docs directory locally in CI + - name: Generate typedoc run: pnpm generateDocs - name: Deploy 🚀 diff --git a/.gitignore b/.gitignore index d09bd88..2b61141 100644 --- a/.gitignore +++ b/.gitignore @@ -118,6 +118,5 @@ dist .pnp.* tests/config.json -tests/sandbox.js -docs/ \ No newline at end of file +docs/typedoc \ No newline at end of file diff --git a/.prettierignore b/.prettierignore index 2c98acd..16ac6bc 100644 --- a/.prettierignore +++ b/.prettierignore @@ -1,6 +1,6 @@ -dist -docs -node_modules +dist/ +node_modules/ pnpm-lock.yaml .prettierrc.json -.eslint.js \ No newline at end of file +.eslint.js +CHANGELOG.md \ No newline at end of file diff --git a/.vscode/extensions.json b/.vscode/extensions.json index e7cd390..1d7ac85 100644 --- a/.vscode/extensions.json +++ b/.vscode/extensions.json @@ -1,7 +1,3 @@ { - "recommendations": [ - "dbaeumer.vscode-eslint", - "esbenp.prettier-vscode", - "EditorConfig.EditorConfig" - ] + "recommendations": ["dbaeumer.vscode-eslint", "esbenp.prettier-vscode"] } diff --git a/CHANGELOG.md b/CHANGELOG.md index 721936f..1d7abb6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,22 @@ # classcharts-api +## 2.3.0 + +### Minor Changes + +- 6552c28: Migrate to native fetch + +## 2.2.0 + +### Minor Changes + +- a3e078b: Throw more description JSON parsing errors + +### Patch Changes + +- 350878c: Fixed internal typing typo +- 451f800: Specify the required node version + ## 2.1.3 ### Patch Changes diff --git a/docs/.nojekyll b/docs/.nojekyll new file mode 100644 index 0000000..e69de29 diff --git a/docs/README.md b/docs/README.md new file mode 100644 index 0000000..4af083e --- /dev/null +++ b/docs/README.md @@ -0,0 +1,297 @@ +

+

ClassCharts API JS

+

+ A typescript wrapper for getting information from the Classcharts API +

+

+

+ Source +   â€¢   + Issues +   â€¢   + NPM +   â€¢   + Discord +   â€¢   + TypeDoc +   â€¢   + API Docs +

+ +# Introduction + +The ClassCharts API is a typescript wrapper around the ClassCharts API. It allows you to easily make requests to the ClassCharts API without having to worry about the underlying implementation of making requests. + +## Help + +For any help with the library, please join the [discord](https://discord.gg/DTcwugcgZ2) where you can ask questions and get help from the community. + +# Installation + +## Requirements + +- Node.js 18 or newer + +## NPM + +```bash +npm install classcharts-api # npm +``` + +```bash +yarn add classcharts-api # yarn +``` + +```bash +pnpm add classcharts-api # pnpm +``` + +# Logging In + +Before making any requests, you must login to the client. This will get you a session ID which will be used for all requests. + +## Student Client + +```typescript +import { StudentClient } from "classcharts-api"; + +// Date of birth MUST in the format DD/MM/YYYY +const client = new StudentClient("classchartsCode", "01/1/2000"); +await client.login(); +``` + +## Parent Client + +```typescript +import { ParentClient } from "classcharts-api"; + +const client = new ParentClient("username", "password"); +await client.login(); +``` + +# Universal Methods + +All the following methods can be used on both the student and parent client. Each example expects the client to be already logged in. + +## `.getStudentInfo` + +```typescript +const studentInfo = await client.getStudentInfo(); +console.log(studentInfo); +/** +{ + success: 1, + data: { + user: { + id: 2339528, + ... + } + }, + meta: { + session_id: '5vf2v7n5uk9jftrxaarrik39vk6yjm48', + ... + } +} +*/ +``` + +## `.getActivity` + +```typescript +// Dates must be in format YYYY-MM-DD +const activity = await client.getActivity({ + from: "2023-04-01", + to: "2023-05-10", + last_id: "12", +}); +console.log(activity); +``` + +## `.getFullActivity` + +```typescript +// Dates must be in format YYYY-MM-DD +const activity = await client.getFullActivity({ + from: "2023-04-01", + to: "2023-05-10", +}); +console.log(activity); +``` + +## `.getBehaviour` + +Gets behaviour for a given date range. + +```typescript +// Dates must be in format YYYY-MM-DD +const behaviour = await client.getBehaviour({ + from: "2023-04-01", + to: "2023-05-10", +}); +console.log(behaviour); + +/** +{ + "success": 1, + "data": { + "timeline": [ + { + "positive": 426, + ... + }, + ], + ... + "meta": { + "start_date": "2023-04-01T00:00:00+00:00", + ... + } +} +*/ +``` + +## `.getHomeworks` + +Gets homeworks for a given date range. + +```typescript +// Dates must be in format YYYY-MM-DD +const homeworks = await client.getHomeworks({ + from: "2023-04-01", + to: "2023-05-10", + displayDate: 'issue_date' // Can be 'due_date' or 'issue_date' +}); +console.log(homeworks); + +/** +{ + success: 1, + data: [ + { + lesson: '7A/Pe1', + ... + }, + ], + meta: { + start_date: '2023-04-01T00:00:00+00:00', + ... + } +} + +``` + +## `.getLessons` + +Gets lessons for a specific date. + +```typescript +// Dates must be in format YYYY-MM-DD +const lessons = await client.getLessons({ + date: "2023-04-01", +}); +console.log(lessons); + +/** +{ + "success": 1, + "data": [ + { + "teacher_name": "Mr J Doe", + ... + } + ... + ], + "meta": { + "dates": [ + "2023-05-04" + ], + ... + } +} +*/ +``` + +## `.getBadges` + +Gets all earned badges. + +```typescript +const badges = await client.getBadges(); +console.log(badges); + +/** +{ + success: 1, + data: [ + { + id: 123, + name: 'Big Badge', + ... + }, + ... + ], + meta: [] +} +*/ +``` + +## `.getAnnouncements` + +?> This method does not include `meta` in the response, since I do not have access to this endpoint to test it. If you have access to this endpoint, please open a PR to add the `meta` response. Thanks! + +Gets all announcements. + +```typescript +const announcements = await client.getAnnouncements(); +console.log(announcements); +``` + +## `.getDetentions` + +?> This method does not include `meta` in the response, since I do not have access to this endpoint to test it. If you have access to this endpoint, please open a PR to add the `meta` response. Thanks! + +Gets all detentions. + +```typescript +const detentions = await client.getDetentions(); +console.log(detentions); +``` + +## `.getAttendance` + +?> This method does not include `meta` in the response, since I do not have access to this endpoint to test it. If you have access to this endpoint, please open a PR to add the `meta` response. Thanks! + +Gets attendance. + +```typescript +const attendance = await client.getAttendance(); +console.log(attendance); +``` + +# Parent Specific Methods + +## `.getPupils` + +Gets a list of all pupils the parent has access to. + +```typescript +const pupils = await client.getPupils(); +console.log(pupils); +/** +[ + { + id: 123, + name: 'John Doe', + ... + }, + ... +] +*/ +``` + +## `.selectPupil` + +Selects a pupil to make subsequent requests for. + +```typescript +await client.selectPupil(123); +``` diff --git a/docs/index.html b/docs/index.html new file mode 100644 index 0000000..e005a08 --- /dev/null +++ b/docs/index.html @@ -0,0 +1,40 @@ + + + + + ClassCharts-API + + + + + + + +
+ + + + + + + + + diff --git a/package.json b/package.json index 28ce8a6..f956301 100644 --- a/package.json +++ b/package.json @@ -1,13 +1,13 @@ { "name": "classcharts-api", "type": "module", - "version": "2.1.3", + "version": "2.3.0", "license": "ISC", "author": { "name": "James Cook", "email": "james@jaminit.co.uk" }, - "description": "A Typescript wrapper for getting information from the Classcharts API", + "description": "A Typescript wrapper for getting information from the ClassCharts API", "keywords": [ "node", "typescript", @@ -28,9 +28,6 @@ "test": "jest", "release": "pnpm run build && changeset publish" }, - "dependencies": { - "ky-universal": "^0.11.0" - }, "devDependencies": { "@changesets/cli": "^2.26.1", "@types/jest": "^29.5.1", @@ -51,14 +48,17 @@ "types": "./dist/index.d.ts", "exports": { ".": { + "types": "./dist/index.d.ts", "import": "./dist/index.js", - "require": "./dist/index.js", - "types": "./dist/index.d.ts" + "require": "./dist/index.js" }, "./types": "./dist/index.d.ts", "./package.json": "./package.json" }, "files": [ "dist/**" - ] + ], + "engines": { + "node": ">=18" + } } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index b3d9f67..577c3d9 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -1,10 +1,5 @@ lockfileVersion: '6.0' -dependencies: - ky-universal: - specifier: ^0.11.0 - version: 0.11.0(ky@0.33.3) - devDependencies: '@changesets/cli': specifier: ^2.26.1 @@ -1200,13 +1195,6 @@ packages: eslint-visitor-keys: 3.4.0 dev: true - /abort-controller@3.0.0: - resolution: {integrity: sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==} - engines: {node: '>=6.5'} - dependencies: - event-target-shim: 5.0.1 - dev: false - /acorn-jsx@5.3.2(acorn@8.8.2): resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==} peerDependencies: @@ -1630,11 +1618,6 @@ packages: stream-transform: 2.1.3 dev: true - /data-uri-to-buffer@4.0.1: - resolution: {integrity: sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==} - engines: {node: '>= 12'} - dev: false - /debug@4.3.4: resolution: {integrity: sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==} engines: {node: '>=6.0'} @@ -1949,11 +1932,6 @@ packages: engines: {node: '>=0.10.0'} dev: true - /event-target-shim@5.0.1: - resolution: {integrity: sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==} - engines: {node: '>=6'} - dev: false - /execa@5.1.1: resolution: {integrity: sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==} engines: {node: '>=10'} @@ -2033,14 +2011,6 @@ packages: bser: 2.1.1 dev: true - /fetch-blob@3.2.0: - resolution: {integrity: sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==} - engines: {node: ^12.20 || >= 14.13} - dependencies: - node-domexception: 1.0.0 - web-streams-polyfill: 3.2.1 - dev: false - /file-entry-cache@6.0.1: resolution: {integrity: sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==} engines: {node: ^10.12.0 || >=12.0.0} @@ -2096,13 +2066,6 @@ packages: is-callable: 1.2.7 dev: true - /formdata-polyfill@4.0.10: - resolution: {integrity: sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==} - engines: {node: '>=12.20.0'} - dependencies: - fetch-blob: 3.2.0 - dev: false - /fs-extra@7.0.1: resolution: {integrity: sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==} engines: {node: '>=6 <7 || >=8'} @@ -3089,26 +3052,6 @@ packages: engines: {node: '>=6'} dev: true - /ky-universal@0.11.0(ky@0.33.3): - resolution: {integrity: sha512-65KyweaWvk+uKKkCrfAf+xqN2/epw1IJDtlyCPxYffFCMR8u1sp2U65NtWpnozYfZxQ6IUzIlvUcw+hQ82U2Xw==} - engines: {node: '>=14.16'} - peerDependencies: - ky: '>=0.31.4' - web-streams-polyfill: '>=3.2.1' - peerDependenciesMeta: - web-streams-polyfill: - optional: true - dependencies: - abort-controller: 3.0.0 - ky: 0.33.3 - node-fetch: 3.3.1 - dev: false - - /ky@0.33.3: - resolution: {integrity: sha512-CasD9OCEQSFIam2U8efFK81Yeg8vNMTBUqtMOHlrcWQHqUX3HeCl9Dr31u4toV7emlH8Mymk5+9p0lL6mKb/Xw==} - engines: {node: '>=14.16'} - dev: false - /leven@3.1.0: resolution: {integrity: sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==} engines: {node: '>=6'} @@ -3302,20 +3245,6 @@ packages: resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} dev: true - /node-domexception@1.0.0: - resolution: {integrity: sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==} - engines: {node: '>=10.5.0'} - dev: false - - /node-fetch@3.3.1: - resolution: {integrity: sha512-cRVc/kyto/7E5shrWca1Wsea4y6tL9iYJE5FBCius3JQfb/4P4I295PfhgbJQBLTx6lATE4z+wK0rPM4VS2uow==} - engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - dependencies: - data-uri-to-buffer: 4.0.1 - fetch-blob: 3.2.0 - formdata-polyfill: 4.0.10 - dev: false - /node-int64@0.4.0: resolution: {integrity: sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==} dev: true @@ -4191,11 +4120,6 @@ packages: defaults: 1.0.4 dev: true - /web-streams-polyfill@3.2.1: - resolution: {integrity: sha512-e0MO3wdXWKrLbL0DgGnUV7WHVuw9OUvL4hjgnPkIeEvESk74gAITi5G606JtZPp39cd8HA9VQzCIvA49LpPN5Q==} - engines: {node: '>= 8'} - dev: false - /which-boxed-primitive@1.0.2: resolution: {integrity: sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==} dependencies: diff --git a/readme.md b/readme.md index 522b4fe..53c505e 100644 --- a/readme.md +++ b/readme.md @@ -1,31 +1,23 @@ -# Classcharts API +

Classcharts API JS

+
+Discord + npm + NPM + npm + node-current +
-A client for the classcharts API +

A typescript wrapper for getting information from the Classcharts API.

+ +# Links - [Documentation](https://classchartsapi.github.io/classcharts-api-js/) -- [API Documentation (with library examples)](https://classchartsapi.github.io/api-docs/#introduction) - [Discord](https://discord.gg/DTcwugcgZ2) -# Examples +# Contributing -Docs are very much a WIP, for any help with the library, please join the discord above +Contributions are welcome! There are lots of API endpoints which we simply do not have access to to implement, so if you have access to them, please consider contributing! If you have any questions, feel free to ask in the [discord](https://discord.gg/DTcwugcgZ2). -```typescript -import { StudentClient } from "classcharts-api"; -async function main() { - const client = new StudentClient("classchartsCode", "01/1/2000"); - await client.login(); - console.log( - await client.getBehaviour({ - fromDate: "20/01/2000", - toDate: "01/02/2000", - }) - ); - console.log(await client.getActivity()); - console.log(await client.getStudentInfo()); - console.log(await client.getActivity()); - console.log(await client.getActivity()); -} +# Help -main(); -``` +For any help with the library, please join the [discord](https://discord.gg/DTcwugcgZ2) where you can ask questions and get help from the community. diff --git a/src/core/baseClient.ts b/src/core/baseClient.ts index c9a56d9..6e62571 100644 --- a/src/core/baseClient.ts +++ b/src/core/baseClient.ts @@ -1,4 +1,3 @@ -import ky, { type Options as KyOptions } from "ky-universal"; import type { ActivityResponse, AnnouncementsResponse, @@ -44,13 +43,13 @@ export class BaseClient { */ public lastPing = 0; /** - * @property API_BASE Base API URL, this is different depending if its called as a parent or student + * @property API_BASE Base API URL, this is different depending on if its called as a parent or student * @internal */ protected API_BASE = ""; /** * - * @param API_BASE Base API URL, this is different depending if its called as a parent or student + * @param API_BASE Base API URL, this is different depending on if its called as a parent or student */ constructor(API_BASE: string) { this.authCookies = []; @@ -59,7 +58,7 @@ export class BaseClient { /** * Revalidates the session ID. * - * This is called automatically when the session ID is older than 3 minutes or when intially using the .login() method + * This is called automatically when the session ID is older than 3 minutes or when initially using the .login() method * @internal */ public async getNewSessionId() { @@ -77,7 +76,7 @@ export class BaseClient { this.lastPing = Date.now(); } /** - * Makes a request to the Classcharts API with the required authentication headers + * 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 @@ -89,7 +88,7 @@ export class BaseClient { */ public async makeAuthedRequest( path: string, - kyOptions: KyOptions, + fetchOptions: RequestInit, options?: { revalidateToken?: boolean } ) { if (!this.sessionId) throw new Error("No session ID"); @@ -100,24 +99,27 @@ export class BaseClient { options.revalidateToken = true; } const requestOptions = { - ...kyOptions, + ...fetchOptions, headers: { Cookie: this?.authCookies?.join(";") ?? [], Authorization: "Basic " + this.sessionId, - ...kyOptions.headers, + ...fetchOptions.headers, }, - credentials: undefined, - } satisfies KyOptions; + } satisfies RequestInit; if (options?.revalidateToken === true && this.lastPing) { if (Date.now() - this.lastPing + 5000 > PING_INTERVAL) { await this.getNewSessionId(); } } - const request = await ky(path, requestOptions); - const responseJSON = (await request.json()) as ClassChartsResponse< - unknown, - unknown - >; + const request = await fetch(path, requestOptions); + let responseJSON: ClassChartsResponse; + try { + responseJSON = await request.json(); + } catch (err) { + throw new Error( + "Error parsing JSON. Returned response: " + (await request.text()) + ); + } if (responseJSON.success == 0) { throw new Error(responseJSON.error); } diff --git a/src/core/parentClient.ts b/src/core/parentClient.ts index 67dff45..dad9fa5 100644 --- a/src/core/parentClient.ts +++ b/src/core/parentClient.ts @@ -1,4 +1,3 @@ -import ky from "ky-universal"; import type { GetPupilsResponse } from "../types.js"; import { BaseClient } from "./baseClient.js"; @@ -24,7 +23,7 @@ export class ParentClient extends BaseClient { } /** - * Authenticates with classcharts + * Authenticates with ClassCharts */ async login(): Promise { if (!this.email) throw new Error("Email not inputted"); @@ -33,11 +32,11 @@ export class ParentClient extends BaseClient { formData.append("email", this.email); formData.append("logintype", "existing"); formData.append("password", this.password); - formData.append("recaptcha-token", "no-token-avaliable"); + formData.append("recaptcha-token", "no-token-available"); const headers = new Headers({ "Content-Type": "application/x-www-form-urlencoded", }); - const response = await ky(BASE_URL + "/parent/login", { + const response = await fetch(BASE_URL + "/parent/login", { method: "POST", body: formData, headers: headers, @@ -45,7 +44,7 @@ export class ParentClient extends BaseClient { }); if (response.status != 302 || !response.headers.get("set-cookie")) throw new Error( - "Unauthenticated: Classcharts returned an error: " + + "Unauthenticated: ClassCharts returned an error: " + response.status + " " + response.statusText diff --git a/src/core/studentClient.ts b/src/core/studentClient.ts index 750c9b9..d8d6747 100644 --- a/src/core/studentClient.ts +++ b/src/core/studentClient.ts @@ -1,14 +1,13 @@ import { API_BASE_STUDENT, BASE_URL } from "../utils/consts.js"; import { BaseClient } from "./baseClient.js"; import { parseCookies } from "../utils/utils.js"; -import ky from "ky-universal"; /** * Student Client */ export class StudentClient extends BaseClient { /** - * @property studentCode Classcharts student code + * @property studentCode ClassCharts student code * @internal */ private studentCode = ""; @@ -20,7 +19,7 @@ export class StudentClient extends BaseClient { /** * - * @param studentCode Classcharts student code + * @param studentCode ClassCharts student code * @param dateOfBirth Student's date of birth */ constructor(studentCode: string, dateOfBirth?: string) { @@ -30,7 +29,7 @@ export class StudentClient extends BaseClient { } /** - * Authenticates with classcharts + * Authenticates with ClassCharts */ async login(): Promise { if (!this.studentCode) throw new Error("Student Code not inputted"); @@ -39,17 +38,16 @@ export class StudentClient extends BaseClient { formData.append("code", this.studentCode.toUpperCase()); formData.append("dob", this.dateOfBirth); formData.append("remember_me", "1"); - formData.append("recaptcha-token", "no-token-avaliable"); - const request = await ky(BASE_URL + "/student/login", { + formData.append("recaptcha-token", "no-token-available"); + const request = await fetch(BASE_URL + "/student/login", { method: "POST", body: formData, redirect: "manual", - throwHttpErrors: false, credentials: undefined, }); if (request.status != 302 || !request.headers.get("set-cookie")) { throw new Error( - "Unauthenticated: Classcharts returned an error: " + + "Unauthenticated: ClassCharts returned an error: " + request.status + " " + request.statusText diff --git a/src/types.ts b/src/types.ts index d6a005a..7712f31 100644 --- a/src/types.ts +++ b/src/types.ts @@ -4,9 +4,9 @@ * Helper type to define response from ClassCharts * @internal */ -export type ClassChartsResponse = { +export type ClassChartsResponse = { data: Data; - meta: Error; + meta: Meta; error?: string; success: number; }; diff --git a/tests/baseClient.test.ts b/tests/baseClient.test.ts index 0a0b145..189cb24 100644 --- a/tests/baseClient.test.ts +++ b/tests/baseClient.test.ts @@ -1,4 +1,6 @@ import { StudentClient } from "../src"; +// eslint-disable-next-line @typescript-eslint/ban-ts-comment +// @ts-ignore import { code, dob } from "./config.json"; import "jest-extended"; const client = new StudentClient(code, dob); diff --git a/tsconfig.json b/tsconfig.json index 346da08..8bc8621 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -16,7 +16,7 @@ "noUnusedLocals": true, "noUnusedParameters": true, "skipLibCheck": true, - "isolatedModules": true + "isolatedModules": true, }, "include": ["./src/**/*"] } diff --git a/typedoc.config.cjs b/typedoc.config.cjs index f1cac71..9ecd167 100644 --- a/typedoc.config.cjs +++ b/typedoc.config.cjs @@ -13,7 +13,7 @@ module.exports = { Github: "https://github.com/classchartsapi/classcharts-api-js", }, includeVersion: true, - out: "docs", + out: "docs/typedoc", sort: "required-first", umamiOptions: { src: "https://umami.jaminit.co.uk/script.js",