diff --git a/src/public/app/components/component.js b/src/public/app/components/component.ts similarity index 75% rename from src/public/app/components/component.js rename to src/public/app/components/component.ts index 0f614bcbf..4b2445526 100644 --- a/src/public/app/components/component.js +++ b/src/public/app/components/component.ts @@ -12,6 +12,11 @@ import utils from '../services/utils.js'; * event / command is executed in all components - by simply awaiting the `triggerEvent()`. */ export default class Component { + private componentId: string; + private children: Component[]; + private initialized: Promise | null; + private parent?: Component; + constructor() { this.componentId = `${this.sanitizedClassName}-${utils.randomString(8)}`; /** @type Component[] */ @@ -24,13 +29,12 @@ export default class Component { return this.constructor.name.replace(/[^A-Z0-9]/ig, "_"); } - setParent(parent) { - /** @type Component */ + setParent(parent: Component) { this.parent = parent; return this; } - child(...components) { + child(...components: Component[]) { for (const component of components) { component.setParent(this); @@ -40,12 +44,11 @@ export default class Component { return this; } - /** @returns {Promise} */ - handleEvent(name, data) { + handleEvent(name: string, data: unknown): Promise | null { try { const callMethodPromise = this.initialized - ? this.initialized.then(() => this.callMethod(this[`${name}Event`], data)) - : this.callMethod(this[`${name}Event`], data); + ? this.initialized.then(() => this.callMethod((this as any)[`${name}Event`], data)) + : this.callMethod((this as any)[`${name}Event`], data); const childrenPromise = this.handleEventInChildren(name, data); @@ -54,20 +57,18 @@ export default class Component { ? Promise.all([callMethodPromise, childrenPromise]) : (callMethodPromise || childrenPromise); } - catch (e) { + catch (e: any) { console.error(`Handling of event '${name}' failed in ${this.constructor.name} with error ${e.message} ${e.stack}`); return null; } } - /** @returns {Promise} */ - triggerEvent(name, data = {}) { - return this.parent.triggerEvent(name, data); + triggerEvent(name: string, data = {}): Promise | undefined { + return this.parent?.triggerEvent(name, data); } - /** @returns {Promise} */ - handleEventInChildren(name, data = {}) { + handleEventInChildren(name: string, data: unknown = {}) { const promises = []; for (const child of this.children) { @@ -82,19 +83,18 @@ export default class Component { return promises.length > 0 ? Promise.all(promises) : null; } - /** @returns {Promise<*>} */ - triggerCommand(name, data = {}) { - const fun = this[`${name}Command`]; + triggerCommand(name: string, data = {}): Promise | undefined { + const fun = (this as any)[`${name}Command`]; if (fun) { return this.callMethod(fun, data); } else { - return this.parent.triggerCommand(name, data); + return this.parent?.triggerCommand(name, data); } } - callMethod(fun, data) { + callMethod(fun: (arg: unknown) => Promise, data: unknown) { if (typeof fun !== 'function') { return; } diff --git a/src/public/app/services/utils.ts b/src/public/app/services/utils.ts index ef58b4a32..2370ee92b 100644 --- a/src/public/app/services/utils.ts +++ b/src/public/app/services/utils.ts @@ -301,7 +301,7 @@ function dynamicRequire(moduleName: string) { } } -function timeLimit(promise: Promise, limitMs: number, errorMessage: string) { +function timeLimit(promise: Promise, limitMs: number, errorMessage: string) { if (!promise || !promise.then) { // it's not actually a promise return promise; } @@ -309,7 +309,7 @@ function timeLimit(promise: Promise, limitMs: number, errorMessage: string // better stack trace if created outside of promise const error = new Error(errorMessage || `Process exceeded time limit ${limitMs}`); - return new Promise((res, rej) => { + return new Promise((res, rej) => { let resolved = false; promise.then(result => { diff --git a/src/public/app/types.d.ts b/src/public/app/types.d.ts index 62d507c80..5c344c38c 100644 --- a/src/public/app/types.d.ts +++ b/src/public/app/types.d.ts @@ -25,6 +25,7 @@ interface CustomGlobals { csrfToken: string; baseApiUrl: string; isProtectedSessionAvailable: boolean; + isDev: boolean; } type RequireMethod = (moduleName: string) => any;