From 6d007ad92337a8c2e290037280f41a421f349d43 Mon Sep 17 00:00:00 2001 From: jsteuer <jan.steuer.htw@gmail.com> Date: Wed, 18 Dec 2019 12:57:47 +0100 Subject: [PATCH] docs, runtime type checks for createStorageBasedApi --- src/Helpers.ts | 61 ++++++++++++++++++++++-------- 1 files changed, 44 insertions(+), 17 deletions(-) diff --git a/src/Helpers.ts b/src/Helpers.ts index a50e2a8..e0dccb0 100644 --- a/src/Helpers.ts +++ b/src/Helpers.ts @@ -9,9 +9,7 @@ /** * Bildet die MathCoach API nach, sodass diese auch Offline (ohne IDE) - * verfügbar ist. Aktuell wird eine Implementierung auf Basis des LocalStorage - * verwendet. Funktionen wie der Navigator sind nicht verfügbar. Alle API Aufrufe - * werden in der Browser-Console geloggt. + * verfügbar ist. (Siehe auch `createStorageBasedApi`). * * **Hinweis**: Wenn die echte MathCoach-API der IDE verfügbar ist, hat der Aufruf * dieser Funktion keinen Seiteneffekt. @@ -39,26 +37,48 @@ } /** - * Implementierung der MathCoach IDE API zu Testzwecken. + * Implementierung der MathCoach API zu Testzwecken. * - * Das Dateisystem wird durch den LocalStorage des Browsers (oder InMemory) implementiert. - * Einige Features der IDE (beispielsweise der Navigator) sind nicht verfügbar - * und führen keine Aktionen durch. Alle Aktionen werden in der Browser-Console - * geloggt. + * Das Dateisystem wird durch einen Storage implementiert. Einige Features der + * IDE (beispielsweise der Navigator) sind nicht verfügbar und führen keine Aktionen + * durch. Alle Aktionen werden in der Browser-Console geloggt. * * Anwendungsbeispiel * * import { Helpers } from "@mathcoach/ide-api"; * const _MC = Helpers.createStorageBasedApi(); * const contextFile = await _MC.ide.getContextFile() // use the api + * + * @param contextFileExtension Die Datei-Erweiterung der Kontext-Datei. Das Werkzeug sollte + * unabhängig davon implementiert sein, da der Administrator der MathCoach IDE unter + * Umständen auf eine Alternative ausweichen muss. + * @param storage Storage-Implementierung, die zum Speichern von Dateien verwendet werden + * soll. Standardmäßig wird der `LocalStorage` des Browsers verwendet + * bzw. falls nicht verfügbar der `InMemoryStorage`. + * */ - export function createStorageBasedApi(contextFileExtension: string = "dummy.json"): MathCoach.Api { + export function createStorageBasedApi( + contextFileExtension: string = "dummy.json", + storage: Storage = (typeof localStorage === "undefined") ? new InMemoryStorage() : localStorage + ): MathCoach.Api { const fileIdentifier = (file: MathCoach.File) => `mock-file://${file.owner}@${file.part}/${file.path}`; const traceMethod = (method: string, args?: any[]) => console.log(["[MC MOCK API]", " ", method, "(", (args ? args : [""]).join(","), ")"].join("")); - let storage: Storage = (typeof localStorage === "undefined") ? new InMemoryStorage() : localStorage; - class LocalStorageBasedApi implements MathCoach.Api { - - public ide: MathCoach.IdeApi = { + const runtimeCheck = (errorMessage: string, isInvalid: (param: any) => boolean) => { + return (paramName: string, value: any, optional: boolean = false) => { + if (!optional && (value === null || value === undefined)) { + throw new Error(`parameter '${paramName}' is null or undefined`); + } else { + if (isInvalid(value)) { + throw new Error(`parameter '${paramName}' is invalid: ${errorMessage}`); + } + } + } + } + const runtimeCheckString = runtimeCheck("not a string", v => typeof v !== "string"); + const runtimeCheckBoolean = runtimeCheck("not a boolean", v => typeof v !== "boolean"); + const runtimeCheckFile = runtimeCheck("not a valid file", v => !isFile(v)); + const api: MathCoach.Api = { + ide: { async getContextFile(): Promise<MathCoach.File> { traceMethod("MC.ide.getContextFile"); return { @@ -74,28 +94,35 @@ fs: { async readFile(file: MathCoach.File) { traceMethod("MC.ide.fs.readFile", [JSON.stringify(file)]); + runtimeCheckFile("file", file); return storage.getItem(fileIdentifier(file)) || ""; }, async writeFile(file: MathCoach.File, text: string) { traceMethod("MC.ide.fs.writeFile", [JSON.stringify(file), JSON.stringify(`...${text.length} chars...`)]); + runtimeCheckFile("file", file); + runtimeCheckString("text", text); return storage.setItem(fileIdentifier(file), text); } }, navigator: { async navigateTo(link: string, forceOpen?: boolean) { traceMethod("MC.ide.navigator.navigateTo", [JSON.stringify(link), JSON.stringify(forceOpen ? true : false)]); + runtimeCheckString("link", link); + runtimeCheckBoolean("forceOpen", forceOpen, true); }, async navigateToExercise(file: MathCoach.File, forceOpen?: boolean) { traceMethod("MC.ide.navigator.navigateToExercise", [JSON.stringify(file), JSON.stringify(forceOpen ? true : false)]); + runtimeCheckFile("file", file); + runtimeCheckBoolean("forceOpen", forceOpen, true); } } - }; - public async isReady(): Promise<boolean> { + }, + async isReady() { traceMethod("MC.isReady"); return true; } - } - return new LocalStorageBasedApi(); + }; + return api; } -- Gitblit v1.10.0-SNAPSHOT