1
0
Fork 0
mirror of https://github.com/classchartsapi/classcharts-api-js.git synced 2026-05-14 19:59:37 +00:00

feat: massive overhaul

This commit is contained in:
James Cook 2023-04-07 13:47:08 +01:00
parent 22e21f9fcd
commit 24208c310e
10 changed files with 704 additions and 583 deletions

View file

@ -1,7 +1,7 @@
{ {
"name": "classcharts-api", "name": "classcharts-api",
"version": "1.6.0", "version": "1.6.0",
"description": "A javascript wrapper for getting information from the Classcharts API", "description": "A typescript wrapper for getting information from the Classcharts API",
"keywords": [ "keywords": [
"node", "node",
"typescript", "typescript",
@ -31,23 +31,20 @@
"dist/**" "dist/**"
], ],
"devDependencies": { "devDependencies": {
"@types/jest": "^29.2.3", "@types/jest": "^29.5.0",
"@types/node": "^18", "@types/node": "^18",
"@typescript-eslint/eslint-plugin": "^5.45.0", "@typescript-eslint/eslint-plugin": "^5.57.1",
"@typescript-eslint/parser": "^5.45.0", "@typescript-eslint/parser": "^5.57.1",
"eslint": "^8.28.0", "eslint": "^8.37.0",
"eslint-config-prettier": "^8.5.0", "eslint-config-prettier": "^8.8.0",
"jest": "^29.3.1", "jest": "^29.5.0",
"jest-extended": "^3.2.0", "jest-extended": "^3.2.4",
"prettier": "^2.8.0", "prettier": "^2.8.7",
"ts-jest": "^29.0.3", "ts-jest": "^29.1.0",
"typedoc": "^0.23.21", "typedoc": "^0.23.28",
"typescript": "^4.9.3" "typescript": "^5.0.3"
}, },
"types": "./dist/index.d.ts", "types": "./dist/index.d.ts",
"volta": {
"node": "18.12.1"
},
"exports": { "exports": {
".": { ".": {
"import": "./dist/index.js", "import": "./dist/index.js",

1009
pnpm-lock.yaml generated

File diff suppressed because it is too large Load diff

View file

@ -15,7 +15,6 @@ async function main() {
await client.login(); await client.login();
console.log( console.log(
await client.getBehaviour({ await client.getBehaviour({
displayDate: "due_date",
fromDate: "20/01/2000", fromDate: "20/01/2000",
toDate: "01/02/2000", toDate: "01/02/2000",
}) })

View file

@ -13,10 +13,9 @@ import type {
GetFullActivityOptions, GetFullActivityOptions,
GetHomeworkOptions, GetHomeworkOptions,
GetLessonsOptions, GetLessonsOptions,
Homework, GetStudentInfoResponse,
HomeworksResponse, HomeworksResponse,
LessonsResponse, LessonsResponse,
Student,
} from "./types"; } from "./types";
import { PING_INTERVAL } from "./consts"; import { PING_INTERVAL } from "./consts";
@ -25,7 +24,7 @@ import { PING_INTERVAL } from "./consts";
*/ */
export class ClasschartsClient { export class ClasschartsClient {
public studentId = 0; public studentId = 0;
public authCookies: Array<string> | undefined; public authCookies: Array<string>;
public sessionId = ""; public sessionId = "";
public lastPing = 0; public lastPing = 0;
protected API_BASE = ""; protected API_BASE = "";
@ -35,6 +34,7 @@ export class ClasschartsClient {
* @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 if its called as a parent or student
*/ */
constructor(API_BASE: string, axiosConfig?: AxiosRequestConfig) { constructor(API_BASE: string, axiosConfig?: AxiosRequestConfig) {
this.authCookies = [];
this.API_BASE = API_BASE; this.API_BASE = API_BASE;
this.axios = axios.create({ this.axios = axios.create({
...axiosConfig, ...axiosConfig,
@ -56,7 +56,7 @@ export class ClasschartsClient {
"Content-Type": "application/x-www-form-urlencoded", "Content-Type": "application/x-www-form-urlencoded",
}, },
}, },
{ includeMeta: true, revalidateToken: false } { revalidateToken: false }
); );
this.sessionId = pingData.meta.session_id; this.sessionId = pingData.meta.session_id;
this.lastPing = Date.now(); this.lastPing = Date.now();
@ -64,7 +64,7 @@ export class ClasschartsClient {
public async makeAuthedRequest( public async makeAuthedRequest(
path: string, path: string,
axiosOptions: Omit<AxiosRequestConfig, "path">, axiosOptions: Omit<AxiosRequestConfig, "path">,
options?: { includeMeta?: boolean; revalidateToken?: boolean } options?: { revalidateToken?: boolean }
) { ) {
if (!this.sessionId) throw new Error("No session ID"); if (!this.sessionId) throw new Error("No session ID");
if (!options) { if (!options) {
@ -92,23 +92,19 @@ export class ClasschartsClient {
if (responseJSON.success == 0) { if (responseJSON.success == 0) {
throw new Error(responseJSON.error); throw new Error(responseJSON.error);
} }
if (options?.includeMeta) { return responseJSON;
return responseJSON;
}
return responseJSON.data;
} }
/** /**
* Gets general information about the logged in student * Gets general information about the logged in student
* @returns Student object * @returns Student object
*/ */
async getStudentInfo(): Promise<Student> { async getStudentInfo(): Promise<GetStudentInfoResponse> {
const data = await this.makeAuthedRequest(this.API_BASE + "/ping", { const data = await this.makeAuthedRequest(this.API_BASE + "/ping", {
method: "POST", method: "POST",
data: "include_data=true", data: "include_data=true",
}); });
return data;
return data?.user;
} }
/** /**
* This function is only used for pagination, you likely want client.getFullActivity * This function is only used for pagination, you likely want client.getFullActivity
@ -134,8 +130,8 @@ export class ClasschartsClient {
*/ */
async getFullActivity( async getFullActivity(
options: GetFullActivityOptions options: GetFullActivityOptions
): Promise<ActivityResponse> { ): Promise<ActivityResponse["data"]> {
let data: ActivityResponse = []; let data: ActivityResponse["data"] = [];
let prevLast: number | undefined; let prevLast: number | undefined;
let gotData = true; let gotData = true;
while (gotData) { while (gotData) {
@ -146,7 +142,7 @@ export class ClasschartsClient {
if (prevLast) { if (prevLast) {
params.last_id = String(prevLast); params.last_id = String(prevLast);
} }
const fragment = await this.getActivity(params); const fragment = (await this.getActivity(params)).data;
if (!fragment || !fragment.length) { if (!fragment || !fragment.length) {
gotData = false; gotData = false;
} else { } else {
@ -179,30 +175,32 @@ export class ClasschartsClient {
* @param options GetHomeworkOptions * @param options GetHomeworkOptions
* @returns Array of homeworks * @returns Array of homeworks
*/ */
async listHomeworks( async getHomeworks(options?: GetHomeworkOptions): Promise<HomeworksResponse> {
options?: GetHomeworkOptions
): Promise<HomeworksResponse> {
const params = new URLSearchParams(); const params = new URLSearchParams();
if (options?.displayDate) if (options?.displayDate)
params.append("display_date", String(options?.displayDate)); params.append("display_date", String(options?.displayDate));
options?.fromDate && params.append("from", String(options?.fromDate));
options?.toDate && params.append("to", String(options?.toDate));
options?.from && params.append("from", String(options?.from)); options?.from && params.append("from", String(options?.from));
options?.to && params.append("to", String(options?.to)); options?.to && params.append("to", String(options?.to));
const data: Array<Homework> = await this.makeAuthedRequest( const data: HomeworksResponse = await this.makeAuthedRequest(
this.API_BASE + "/homeworks/" + this.studentId + "?" + params.toString(), this.API_BASE + "/homeworks/" + this.studentId + "?" + params.toString(),
{ {
method: "GET", method: "GET",
} }
); );
for (let i = 0; i < data.length; i++) { for (let i = 0; i < data.data.length; i++) {
data[i].description_raw = data[i].description; data.data[i].description_raw = data.data[i].description;
// homework.lesson.replace(/\\/g, '') // homework.lesson.replace(/\\/g, '')
data[i].description = data[i].description.replace(/(<([^>]+)>)/gi, ""); data.data[i].description = data.data[i].description.replace(
data[i].description = data[i].description.replace(/&nbsp;/g, ""); /(<([^>]+)>)/gi,
data[i].description = data[i].description.trim(); ""
);
data.data[i].description = data.data[i].description.replace(
/&nbsp;/g,
""
);
data.data[i].description = data.data[i].description.trim();
} }
return data; return data;
} }
@ -235,45 +233,55 @@ export class ClasschartsClient {
); );
} }
/** /**
* Lists the logged in student's announcements * Gets the logged in student's announcements
* @returns Array of announcements * @returns Array of announcements
*/ */
async listAnnouncements(): Promise<AnnouncementsResponse> { async getAnnouncements(): Promise<AnnouncementsResponse> {
return await this.makeAuthedRequest( return (
this.API_BASE + "/announcements/" + this.studentId, await this.makeAuthedRequest(
{ this.API_BASE + "/announcements/" + this.studentId,
method: "GET", {
} method: "GET",
); }
)
).data;
} }
/** /**
* Gets the logged in student's detentions * Gets the logged in student's detentions
* @returns Array of detentions * @returns Array of detentions
*/ */
async getDetentions(): Promise<DetentionsResponse> { async getDetentions(): Promise<DetentionsResponse> {
return await this.makeAuthedRequest( return (
this.API_BASE + "/detentions/" + this.studentId, await this.makeAuthedRequest(
{ this.API_BASE + "/detentions/" + this.studentId,
method: "GET", {
} method: "GET",
); }
)
).data;
} }
/** /**
* Gets the logged in student's attendance * Gets the logged in student's attendance
* @param options GetAttendanceOptions * @param options GetAttendanceOptions
* @returns Array of dates of attendance * @returns Array of dates of attendance
*/ */
async listAttendance( async getAttendance(
options?: GetAttendanceOptions options?: GetAttendanceOptions
): Promise<AttendanceResponse> { ): Promise<AttendanceResponse> {
const params = new URLSearchParams(); const params = new URLSearchParams();
options?.from && params.append("from", options?.from); options?.from && params.append("from", options?.from);
options?.to && params.append("to", options?.to); options?.to && params.append("to", options?.to);
return await this.makeAuthedRequest( return (
this.API_BASE + "/attendance/" + this.studentId + "?" + params.toString(), await this.makeAuthedRequest(
{ this.API_BASE +
method: "GET", "/attendance/" +
} this.studentId +
); "?" +
params.toString(),
{
method: "GET",
}
)
).data;
} }
} }

View file

@ -1,3 +1,2 @@
export * from "./parentClient"; export * from "./parentClient";
export * from "./studentClient"; export * from "./studentClient";
export * from "./types";

View file

@ -5,9 +5,9 @@ import { ClasschartsClient } from "./baseClient";
import { API_BASE_PARENT, BASE_URL } from "./consts"; import { API_BASE_PARENT, BASE_URL } from "./consts";
import { parseCookies } from "./utils"; import { parseCookies } from "./utils";
/** /**
* The base client * Parent Client
*/ */
export class ClasschartsParentClient extends ClasschartsClient { export class ParentClient extends ClasschartsClient {
private password = ""; private password = "";
private email = ""; private email = "";
// @ts-expect-error Init in .login // @ts-expect-error Init in .login
@ -52,7 +52,7 @@ export class ClasschartsParentClient extends ClasschartsClient {
throw new Error("Unauthenticated: Classcharts returned an error"); throw new Error("Unauthenticated: Classcharts returned an error");
const cookies = String(request.headers["set-cookie"]); const cookies = String(request.headers["set-cookie"]);
this.authCookies = cookies.split(";"); // this.authCookies = cookies.split(";");
const sessionCookies = parseCookies(cookies); const sessionCookies = parseCookies(cookies);
const sessionID = JSON.parse( const sessionID = JSON.parse(
String(sessionCookies["parent_session_credentials"]) String(sessionCookies["parent_session_credentials"])
@ -64,7 +64,7 @@ export class ClasschartsParentClient extends ClasschartsClient {
} }
/** /**
* Get Pupil details * Get Pupil details
* @returns an array fo 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> {
return this.makeAuthedRequest(this.API_BASE + "/pupils", { return this.makeAuthedRequest(this.API_BASE + "/pupils", {

View file

@ -3,10 +3,10 @@ import { API_BASE_STUDENT, BASE_URL } from "./consts";
import { ClasschartsClient } from "./baseClient"; import { ClasschartsClient } from "./baseClient";
import { parseCookies } from "./utils"; import { parseCookies } from "./utils";
/** /**
* The base client * Student Client
*/ */
export class ClasschartsStudentClient extends ClasschartsClient { export class StudentClient extends ClasschartsClient {
public studentCode = ""; public studentCode = "";
public dateOfBirth = ""; public dateOfBirth = "";
@ -57,6 +57,6 @@ export class ClasschartsStudentClient extends ClasschartsClient {
this.sessionId = sessionID.session_id; this.sessionId = sessionID.session_id;
await this.getNewSessionId(); await this.getNewSessionId();
const user = await this.getStudentInfo(); const user = await this.getStudentInfo();
this.studentId = user.id; this.studentId = user.data.user.id;
} }
} }

View file

@ -1,4 +1,11 @@
/* eslint-disable @typescript-eslint/no-explicit-any */ /* eslint-disable @typescript-eslint/no-explicit-any */
type ClassChartsResponse<T, E> = {
data: T;
meta: E;
error?: string;
success: number;
};
export interface Student { export interface Student {
id: number; id: number;
name: string; name: string;
@ -37,6 +44,18 @@ export interface Student {
survey_id: number | null; survey_id: number | null;
detention_alias_plural_uc: string; detention_alias_plural_uc: string;
} }
interface GetStudentInfoData {
user: Student;
}
interface GetStudentInfoMeta {
version: string;
}
export type GetStudentInfoResponse = ClassChartsResponse<
GetStudentInfoData,
GetStudentInfoMeta
>;
export interface GetBehaviourOptions { export interface GetBehaviourOptions {
/** /**
* From date, in format YYYY-MM-DD * From date, in format YYYY-MM-DD
@ -47,6 +66,7 @@ export interface GetBehaviourOptions {
*/ */
to?: string; to?: string;
} }
export interface BehaviourTimelinePoint { export interface BehaviourTimelinePoint {
positive: number; positive: number;
negative: number; negative: number;
@ -54,7 +74,7 @@ export interface BehaviourTimelinePoint {
start: string; start: string;
end: string; end: string;
} }
export interface BehaviourResponse { 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>;
@ -63,6 +83,16 @@ export interface BehaviourResponse {
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 {
start_date: string;
end_date: string;
step_size: string;
}
export type BehaviourResponse = ClassChartsResponse<
BehaviourResponseData,
BehaviourResponseMeta
>;
export interface GetActivityOptions { export interface GetActivityOptions {
/** /**
* From date, in format YYYY-MM-DD * From date, in format YYYY-MM-DD
@ -77,6 +107,7 @@ export interface GetActivityOptions {
*/ */
last_id?: string; last_id?: string;
} }
export interface ActivityPoint { export interface ActivityPoint {
id: number; id: number;
type: string; type: string;
@ -101,21 +132,25 @@ export interface ActivityPoint {
detention_location: string | null; detention_location: string | null;
detention_type: string | null; detention_type: string | null;
} }
export type ActivityResponse = Array<ActivityPoint>; type ActivityResponseData = Array<ActivityPoint>;
interface ActivityResponseMeta {
start_date: string;
end_date: string;
last_id: boolean;
step_size: string;
detention_alias_uc: string;
}
export type ActivityResponse = ClassChartsResponse<
ActivityResponseData,
ActivityResponseMeta
>;
export type DisplayDate = "due_date" | "issue_date"; export type DisplayDate = "due_date" | "issue_date";
export interface GetHomeworkOptions { export interface GetHomeworkOptions {
/** /**
* Way to sort homeworks * Way to sort homeworks
*/ */
displayDate?: DisplayDate; displayDate?: DisplayDate;
/**
* @deprecated Use "from" instead
*/
fromDate?: string;
/**
* @deprecated Use "to" instead
*/
toDate?: string;
/** /**
* From date, in format YYYY-MM-DD * From date, in format YYYY-MM-DD
*/ */
@ -161,7 +196,24 @@ export interface Homework {
validated_links: Array<any>; validated_links: Array<any>;
validated_attachments: Array<ValidatedHomeworkAttachment>; validated_attachments: Array<ValidatedHomeworkAttachment>;
} }
export type HomeworksResponse = Array<Homework>; type HomeworksResponseData = Array<Homework>;
interface HomeworksResponseMeta {
start_date: string;
end_date: string;
display_type: DisplayDate;
max_files_allowed: number;
allowed_file_types: string[];
this_week_due_count: number;
this_week_outstanding_count: number;
this_week_completed_count: number;
allow_attachments: boolean;
display_marks: boolean;
}
export type HomeworksResponse = ClassChartsResponse<
HomeworksResponseData,
HomeworksResponseMeta
>;
export interface GetLessonsOptions { export interface GetLessonsOptions {
/** /**
* Date to get lessons for, in format YYYY-MM-DD * Date to get lessons for, in format YYYY-MM-DD
@ -186,7 +238,24 @@ export interface Lesson {
pupil_note: string; pupil_note: string;
pupil_note_raw: string; pupil_note_raw: string;
} }
export type LessonsResponse = Array<Lesson>; type LessonsResponseData = Lesson[];
interface PeriodMeta {
number: string;
start_time: string;
end_time: string;
}
interface LessonsResponseMeta {
dates: string[];
timetable_dates: string[];
periods: PeriodMeta[];
start_time: string;
end_time: string;
}
export type LessonsResponse = ClassChartsResponse<
LessonsResponseData,
LessonsResponseMeta
>;
// Not sure what to call this // Not sure what to call this
export interface LessonPupilBehaviour { export interface LessonPupilBehaviour {
reason: string; reason: string;
@ -216,7 +285,12 @@ export interface Badge {
pupil_badges: Array<PupilEvent>; pupil_badges: Array<PupilEvent>;
icon_url: string; icon_url: string;
} }
export type BadgesResponse = Array<Badge>; type BadgesResponseData = Array<Badge>;
type BadgesResponseMeta = [];
export type BadgesResponse = ClassChartsResponse<
BadgesResponseData,
BadgesResponseMeta
>;
export interface Detention { export interface Detention {
id: number; id: number;
@ -257,6 +331,7 @@ export interface Detention {
name: string; name: string;
}; };
} }
// TODO: Update typings to include meta response. Currently not possible since I don't have access
export type DetentionsResponse = Array<Detention>; export type DetentionsResponse = Array<Detention>;
export interface Announcement { export interface Announcement {
@ -285,6 +360,7 @@ export interface Announcement {
pupil_consents: Array<any>; pupil_consents: Array<any>;
} }
// TODO: Update typings to include meta response. Currently not possible since I don't have access
export type AnnouncementsResponse = Array<Announcement>; export type AnnouncementsResponse = Array<Announcement>;
export interface Pupil extends Student { export interface Pupil extends Student {
@ -342,5 +418,5 @@ export interface AttendanceDate {
late_minutes: number; late_minutes: number;
}; };
} }
// TODO: Update typings to include meta response. Currently not possible since I don't have access
export type AttendanceResponse = Array<Record<string, AttendanceDate>>; export type AttendanceResponse = Record<string, AttendanceDate>[];

View file

@ -1,7 +1,7 @@
import { ClasschartsStudentClient } from "../src"; import { StudentClient } from "../src";
import { code, dob } from "./config.json"; import { code, dob } from "./config.json";
import "jest-extended"; import "jest-extended";
const client = new ClasschartsStudentClient(code, dob); const client = new StudentClient(code, dob);
jest.setTimeout(10000); jest.setTimeout(10000);
test("client logs in with correct credentials", () => { test("client logs in with correct credentials", () => {
@ -9,7 +9,7 @@ test("client logs in with correct credentials", () => {
}); });
test("client fails to login with incorrect credentials", () => { test("client fails to login with incorrect credentials", () => {
const fakeClient = new ClasschartsStudentClient("rewrew", "123"); const fakeClient = new StudentClient("rewrew", "123");
return expect(fakeClient.login()).rejects.toThrowError(); return expect(fakeClient.login()).rejects.toThrowError();
}); });
@ -18,7 +18,7 @@ test("client returns student data", () => {
}); });
test("client returns activity data", () => { test("client returns activity data", () => {
return expect(client.getActivity()).resolves.toBeArray(); return expect(client.getActivity()).resolves.toBeObject();
}); });
test("client returns full activity", () => { test("client returns full activity", () => {
@ -36,9 +36,9 @@ test("client returns behaviour data", () => {
}); });
test("client returns homework data", () => { test("client returns homework data", () => {
return expect(client.listHomeworks()).resolves.toBeArray(); return expect(client.getHomeworks()).resolves.toBeObject();
}); });
test("client returns badges", () => { test("client returns badges", () => {
expect(client.getBadges()).resolves.toBeArray(); expect(client.getBadges()).resolves.toBeObject();
}); });

View file

@ -30,7 +30,7 @@
// "typeRoots": [], /* Specify multiple folders that act like `./node_modules/@types`. */ // "typeRoots": [], /* Specify multiple folders that act like `./node_modules/@types`. */
// "types": [], /* Specify type package names to be included without being referenced in a source file. */ // "types": [], /* Specify type package names to be included without being referenced in a source file. */
// "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */ // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */
"resolveJsonModule": true, /* Enable importing .json files */ "resolveJsonModule": true, /* Enable importing .json files */
// "noResolve": true, /* Disallow `import`s, `require`s or `<reference>`s from expanding the number of files TypeScript should add to a project. */ // "noResolve": true, /* Disallow `import`s, `require`s or `<reference>`s from expanding the number of files TypeScript should add to a project. */
/* JavaScript Support */ /* JavaScript Support */
// "allowJs": true, /* Allow JavaScript files to be a part of your program. Use the `checkJS` option to get errors from these files. */ // "allowJs": true, /* Allow JavaScript files to be a part of your program. Use the `checkJS` option to get errors from these files. */
@ -40,7 +40,7 @@
"declaration": true /* Generate .d.ts files from TypeScript and JavaScript files in your project. */, "declaration": true /* Generate .d.ts files from TypeScript and JavaScript files in your project. */,
// "declarationMap": true, /* Create sourcemaps for d.ts files. */ // "declarationMap": true, /* Create sourcemaps for d.ts files. */
// "emitDeclarationOnly": true, /* Only output d.ts files and not JavaScript files. */ // "emitDeclarationOnly": true, /* Only output d.ts files and not JavaScript files. */
"sourceMap": true, /* Create source map files for emitted JavaScript files. */ "sourceMap": true, /* Create source map files for emitted JavaScript files. */
// "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If `declaration` is true, also designates a file that bundles all .d.ts output. */ // "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If `declaration` is true, also designates a file that bundles all .d.ts output. */
"outDir": "dist" /* Specify an output folder for all emitted files. */, "outDir": "dist" /* Specify an output folder for all emitted files. */,
// "removeComments": true, /* Disable emitting comments. */ // "removeComments": true, /* Disable emitting comments. */
@ -61,7 +61,7 @@
// "declarationDir": "./", /* Specify the output directory for generated declaration files. */ // "declarationDir": "./", /* Specify the output directory for generated declaration files. */
/* Interop Constraints */ /* Interop Constraints */
// "isolatedModules": true, /* Ensure that each file can be safely transpiled without relying on other imports. */ // "isolatedModules": true, /* Ensure that each file can be safely transpiled without relying on other imports. */
"allowSyntheticDefaultImports": true, /* Allow 'import x from y' when a module doesn't have a default export. */ "allowSyntheticDefaultImports": true, /* Allow 'import x from y' when a module doesn't have a default export. */
"esModuleInterop": true /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables `allowSyntheticDefaultImports` for type compatibility. */, "esModuleInterop": true /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables `allowSyntheticDefaultImports` for type compatibility. */,
// "preserveSymlinks": true, /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */ // "preserveSymlinks": true, /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */
"forceConsistentCasingInFileNames": true /* Ensure that casing is correct in imports. */, "forceConsistentCasingInFileNames": true /* Ensure that casing is correct in imports. */,
@ -89,5 +89,8 @@
// "skipDefaultLibCheck": true, /* Skip type checking .d.ts files that are included with TypeScript. */ // "skipDefaultLibCheck": true, /* Skip type checking .d.ts files that are included with TypeScript. */
// "skipLibCheck": true /* Skip type checking all .d.ts files. */ // "skipLibCheck": true /* Skip type checking all .d.ts files. */
}, },
"exclude": ["tests", "dist"] "exclude": [
"tests",
"dist"
]
} }