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

Merge branch 'main' into main

This commit is contained in:
Veloi 2023-09-18 18:01:48 +01:00 committed by GitHub
commit 8b0ad3667d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
13 changed files with 113 additions and 41 deletions

5
.vscode/extensions.json vendored Normal file
View file

@ -0,0 +1,5 @@
{
"recommendations": [
"denoland.vscode-deno"
]
}

View file

@ -2,5 +2,8 @@
"tasks": {
"npm": "deno run -A scripts/build_npm.ts"
},
"exclude": ["npm"]
"exclude": ["npm"],
"imports": {
"~/": "./"
}
}

32
deno.lock generated
View file

@ -79,6 +79,38 @@
"https://deno.land/std@0.200.0/assert/unimplemented.ts": "d56fbeecb1f108331a380f72e3e010a1f161baa6956fd0f7cf3e095ae1a4c75a",
"https://deno.land/std@0.200.0/assert/unreachable.ts": "4600dc0baf7d9c15a7f7d234f00c23bca8f3eba8b140286aaca7aa998cf9a536",
"https://deno.land/std@0.200.0/fmt/colors.ts": "a7eecffdf3d1d54db890723b303847b6e0a1ab4b528ba6958b8f2e754cf1b3bc",
"https://deno.land/std@0.201.0/assert/_constants.ts": "8a9da298c26750b28b326b297316cdde860bc237533b07e1337c021379e6b2a9",
"https://deno.land/std@0.201.0/assert/_diff.ts": "1a3c044aedf77647d6cac86b798c6417603361b66b54c53331b312caeb447aea",
"https://deno.land/std@0.201.0/assert/_format.ts": "a69126e8a469009adf4cf2a50af889aca364c349797e63174884a52ff75cf4c7",
"https://deno.land/std@0.201.0/assert/assert.ts": "9a97dad6d98c238938e7540736b826440ad8c1c1e54430ca4c4e623e585607ee",
"https://deno.land/std@0.201.0/assert/assert_almost_equals.ts": "e15ca1f34d0d5e0afae63b3f5d975cbd18335a132e42b0c747d282f62ad2cd6c",
"https://deno.land/std@0.201.0/assert/assert_array_includes.ts": "6856d7f2c3544bc6e62fb4646dfefa3d1df5ff14744d1bca19f0cbaf3b0d66c9",
"https://deno.land/std@0.201.0/assert/assert_equals.ts": "d8ec8a22447fbaf2fc9d7c3ed2e66790fdb74beae3e482855d75782218d68227",
"https://deno.land/std@0.201.0/assert/assert_exists.ts": "407cb6b9fb23a835cd8d5ad804e2e2edbbbf3870e322d53f79e1c7a512e2efd7",
"https://deno.land/std@0.201.0/assert/assert_false.ts": "a9962749f4bf5844e3fa494257f1de73d69e4fe0e82c34d0099287552163a2dc",
"https://deno.land/std@0.201.0/assert/assert_greater.ts": "ae2158a2d19313bf675bf7251d31c6dc52973edb12ac64ac8fc7064152af3e63",
"https://deno.land/std@0.201.0/assert/assert_greater_or_equal.ts": "1439da5ebbe20855446cac50097ac78b9742abe8e9a43e7de1ce1426d556e89c",
"https://deno.land/std@0.201.0/assert/assert_instance_of.ts": "3aedb3d8186e120812d2b3a5dea66a6e42bf8c57a8bd927645770bd21eea554c",
"https://deno.land/std@0.201.0/assert/assert_is_error.ts": "c21113094a51a296ffaf036767d616a78a2ae5f9f7bbd464cd0197476498b94b",
"https://deno.land/std@0.201.0/assert/assert_less.ts": "aec695db57db42ec3e2b62e97e1e93db0063f5a6ec133326cc290ff4b71b47e4",
"https://deno.land/std@0.201.0/assert/assert_less_or_equal.ts": "5fa8b6a3ffa20fd0a05032fe7257bf985d207b85685fdbcd23651b70f928c848",
"https://deno.land/std@0.201.0/assert/assert_match.ts": "c4083f80600bc190309903c95e397a7c9257ff8b5ae5c7ef91e834704e672e9b",
"https://deno.land/std@0.201.0/assert/assert_not_equals.ts": "9f1acab95bd1f5fc9a1b17b8027d894509a745d91bac1718fdab51dc76831754",
"https://deno.land/std@0.201.0/assert/assert_not_instance_of.ts": "0c14d3dfd9ab7a5276ed8ed0b18c703d79a3d106102077ec437bfe7ed912bd22",
"https://deno.land/std@0.201.0/assert/assert_not_match.ts": "3796a5b0c57a1ce6c1c57883dd4286be13a26f715ea662318ab43a8491a13ab0",
"https://deno.land/std@0.201.0/assert/assert_not_strict_equals.ts": "ca6c6d645e95fbc873d25320efeb8c4c6089a9a5e09f92d7c1c4b6e935c2a6ad",
"https://deno.land/std@0.201.0/assert/assert_object_match.ts": "d8fc2867cfd92eeacf9cea621e10336b666de1874a6767b5ec48988838370b54",
"https://deno.land/std@0.201.0/assert/assert_rejects.ts": "45c59724de2701e3b1f67c391d6c71c392363635aad3f68a1b3408f9efca0057",
"https://deno.land/std@0.201.0/assert/assert_strict_equals.ts": "b1f538a7ea5f8348aeca261d4f9ca603127c665e0f2bbfeb91fa272787c87265",
"https://deno.land/std@0.201.0/assert/assert_string_includes.ts": "b821d39ebf5cb0200a348863c86d8c4c4b398e02012ce74ad15666fc4b631b0c",
"https://deno.land/std@0.201.0/assert/assert_throws.ts": "63784e951475cb7bdfd59878cd25a0931e18f6dc32a6077c454b2cd94f4f4bcd",
"https://deno.land/std@0.201.0/assert/assertion_error.ts": "4d0bde9b374dfbcbe8ac23f54f567b77024fb67dbb1906a852d67fe050d42f56",
"https://deno.land/std@0.201.0/assert/equal.ts": "9f1a46d5993966d2596c44e5858eec821859b45f783a5ee2f7a695dfc12d8ece",
"https://deno.land/std@0.201.0/assert/fail.ts": "c36353d7ae6e1f7933d45f8ea51e358c8c4b67d7e7502028598fe1fea062e278",
"https://deno.land/std@0.201.0/assert/mod.ts": "37c49a26aae2b254bbe25723434dc28cd7532e444cf0b481a97c045d110ec085",
"https://deno.land/std@0.201.0/assert/unimplemented.ts": "d56fbeecb1f108331a380f72e3e010a1f161baa6956fd0f7cf3e095ae1a4c75a",
"https://deno.land/std@0.201.0/assert/unreachable.ts": "4600dc0baf7d9c15a7f7d234f00c23bca8f3eba8b140286aaca7aa998cf9a536",
"https://deno.land/std@0.201.0/fmt/colors.ts": "87544aa2bc91087bb37f9c077970c85bfb041b48e4c37356129d7b450a415b6f",
"https://deno.land/x/code_block_writer@12.0.0/mod.ts": "2c3448060e47c9d08604c8f40dee34343f553f33edcdfebbf648442be33205e5",
"https://deno.land/x/code_block_writer@12.0.0/utils/string_utils.ts": "60cb4ec8bd335bf241ef785ccec51e809d576ff8e8d29da43d2273b69ce2a6ff",
"https://deno.land/x/deno_cache@0.5.2/auth_tokens.ts": "5d1d56474c54a9d152e44d43ea17c2e6a398dd1e9682c69811a313567c01ee1e",

5
deps_dev.ts Normal file
View file

@ -0,0 +1,5 @@
export {
assertEquals,
assertExists,
assertRejects,
} from "https://deno.land/std@0.201.0/assert/mod.ts";

View file

@ -4,7 +4,10 @@
<meta charset="UTF-8" />
<title>ClassCharts-API</title>
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
<!-- <meta name="description" content="Description"> -->
<meta
name="description"
content="Documentation for classcharts-api javascript package. A library for interacting with the ClassCharts API."
/>
<meta
name="viewport"
content="width=device-width, initial-scale=1.0, minimum-scale=1.0"
@ -13,12 +16,6 @@
rel="stylesheet"
href="//cdn.jsdelivr.net/npm/docsify@4/lib/themes/vue.css"
/>
<script
async
src="https://umami.jaminit.co.uk/script.js"
data-website-id="3f01674a-5c63-47a2-962b-43d0c62c7c6c"
data-domains="classchartsapi.github.io"
></script>
</head>
<body>
<div id="app"></div>

4
mod.ts
View file

@ -1,2 +1,2 @@
export * from "./src/core/studentClient.ts";
export * from "./src/core/parentClient.ts";
export * from "~/src/core/studentClient.ts";
export * from "~/src/core/parentClient.ts";

View file

@ -1,3 +1,4 @@
// This dependancy cannot be moved to dev_deps.ts since dnt complains about a top-level await
import { build, emptyDir } from "https://deno.land/x/dnt@0.38.1/mod.ts";
if (!Deno.args[0]) throw new Error("No version specified");
@ -13,6 +14,7 @@ await build({
path: "./src/types.ts",
}],
outDir: "./npm",
importMap: "./deno.jsonc",
shims: {
deno: true,
},
@ -22,13 +24,12 @@ await build({
},
typeCheck: "both",
package: {
// package.json properties
name: "classcharts-api",
version: String(Deno.args[0]).replace("v", ""),
author: {
name: "James Cook",
email: "james@jaminit.co.uk",
},
version: Deno.args[0],
description:
"A Typescript wrapper for getting information from the ClassCharts API",
license: "ISC",
@ -47,7 +48,6 @@ await build({
sideEffects: false,
},
postBuild() {
// steps to run after building and before running the tests
Deno.copyFileSync("LICENSE", "npm/LICENSE");
Deno.copyFileSync("README.md", "npm/README.md");
},

View file

@ -17,7 +17,7 @@ import type {
LessonsResponse,
PupilFieldsResponse,
} from "../types.ts";
import { PING_INTERVAL } from "../utils/consts.ts";
import { PING_INTERVAL } from "~/src/utils/consts.ts";
/**
* Shared client for both parent and student. This is not exported and should not be used directly
@ -105,7 +105,8 @@ export class BaseClient {
}
}
const request = await fetch(path, requestOptions);
let responseJSON: ClassChartsResponse<unknown, unknown>;
// deno-lint-ignore no-explicit-any
let responseJSON: ClassChartsResponse<any, any>;
try {
responseJSON = await request.json();
} catch {
@ -116,8 +117,7 @@ export class BaseClient {
if (responseJSON.success == 0) {
throw new Error(responseJSON.error);
}
// deno-lint-ignore no-explicit-any
return responseJSON as unknown as any;
return responseJSON;
}
/**
* Gets general information about the current student

View file

@ -1,8 +1,8 @@
import type { GetPupilsResponse } from "../types.ts";
import { BaseClient } from "./baseClient.ts";
import { API_BASE_PARENT, BASE_URL } from "../utils/consts.ts";
import { parseCookies } from "../utils/utils.ts";
import { BaseClient } from "~/src/core/baseClient.ts";
import { API_BASE_PARENT, BASE_URL } from "~/src/utils/consts.ts";
import { parseCookies } from "~/src/utils/utils.ts";
/**
* Parent Client
*/
@ -26,6 +26,7 @@ export class ParentClient extends BaseClient {
*/
async login(): Promise<void> {
if (!this.email) throw new Error("Email not provided");
if (!this.password) throw new Error("Password not provided");
const formData = new URLSearchParams();
formData.append("_method", "POST");
formData.append("email", this.email);
@ -39,14 +40,12 @@ export class ParentClient extends BaseClient {
method: "POST",
body: formData,
headers: headers,
credentials: undefined,
redirect: "manual",
});
if (response.status != 302 || !response.headers.has("set-cookie")) {
await response.body?.cancel(); // Make deno tests happy by closing the body, unsure whether this is needed for the actual library
throw new Error(
"Unauthenticated: ClassCharts returned an error: " +
response.status +
" " +
response.statusText,
"Unauthenticated: ClassCharts didn't return authentication cookies",
);
}
@ -56,19 +55,20 @@ export class ParentClient extends BaseClient {
const sessionID = JSON.parse(
String(sessionCookies["parent_session_credentials"]),
);
super.sessionId = sessionID.session_id;
this.sessionId = sessionID.session_id;
this.pupils = await this.getPupils();
if (!this.pupils) throw new Error("Account has no pupils attached");
super.studentId = this.pupils[0].id;
this.studentId = this.pupils[0].id;
}
/**
* Get a list of pupils connected to this parent's account
* @returns an array of Pupils connected to this parent's account
*/
async getPupils(): Promise<GetPupilsResponse> {
return await super.makeAuthedRequest(super.API_BASE + "/pupils", {
const response = await this.makeAuthedRequest(this.API_BASE + "/pupils", {
method: "GET",
});
return response.data;
}
/**
* Selects a pupil to be used with API requests
@ -82,7 +82,7 @@ export class ParentClient extends BaseClient {
for (let i = 0; i < pupils.length; i++) {
const pupil = pupils[i];
if (pupil.id == pupilId) {
super.studentId = pupil.id;
this.studentId = pupil.id;
return;
}
}

View file

@ -0,0 +1,35 @@
import { assertRejects } from "~/deps_dev.ts";
import { ParentClient } from "~/src/core/parentClient.ts";
Deno.test("Throws when no email is provided", async () => {
const client = new ParentClient("", "password");
await assertRejects(
async () => {
await client.login();
},
Error,
"Email not provided",
);
});
Deno.test("Throws when no password is provided", async () => {
const client = new ParentClient("email", "");
await assertRejects(
async () => {
await client.login();
},
Error,
"Password not provided",
);
});
Deno.test("Throws with invalid username and password", async () => {
const client = new ParentClient("invalid", "invalid");
await assertRejects(
async () => {
await client.login();
},
Error,
"Unauthenticated: ClassCharts didn't return authentication cookies",
);
});

View file

@ -1,7 +1,7 @@
import { API_BASE_STUDENT, BASE_URL } from "../utils/consts.ts";
import { BaseClient } from "./baseClient.ts";
import { parseCookies } from "../utils/utils.ts";
import { RewardPurchaseResponse, RewardsResponse } from "../types.ts"
import { API_BASE_STUDENT, BASE_URL } from "~/src/utils/consts.ts";
import { BaseClient } from "~/src/core/baseClient.ts";
import { parseCookies } from "~/src/utils/utils.ts";
import { RewardPurchaseResponse, RewardsResponse } from "~/src/types.ts"
/**
* Student Client

View file

@ -1,6 +1,5 @@
import { assertRejects } from "https://deno.land/std@0.200.0/assert/mod.ts";
import { StudentClient } from "./studentClient.ts";
import { assertRejects } from "~/deps_dev.ts";
import { StudentClient } from "~/src/core/studentClient.ts";
Deno.test("Throws when no student code is provided", async () => {
const client = new StudentClient("");

View file

@ -1,8 +1,4 @@
import {
assertEquals,
assertExists,
} from "https://deno.land/std@0.200.0/assert/mod.ts";
import { assertEquals, assertExists } from "~/deps_dev.ts";
import { parseCookies } from "./utils.ts";
Deno.test("Parses simple cookie", () => {
const cookie =