From 901105434980794e21fd77a7492afe158a4d614b Mon Sep 17 00:00:00 2001 From: Max Hauser Date: Fri, 4 Aug 2023 12:33:27 +0200 Subject: [PATCH] optimize some types and trim read docker version string (#2375) * optimize some types and trim read docker version string * back to node timeout * specify adapter interval and timeout as return types for the according methods * fix some of the ugly path handling * path must be relative * Update tools.ts * correct type to match implementation and allow undefined to be passed to clear methods for convinience like for internal timeout methods * add undefined guard * adapter _logger is always defined --- packages/adapter/src/lib/adapter/adapter.ts | 85 +++++++++++---------- packages/common/src/lib/common/tools.ts | 34 +++------ packages/types-public/index.test-d.ts | 12 ++- 3 files changed, 66 insertions(+), 65 deletions(-) diff --git a/packages/adapter/src/lib/adapter/adapter.ts b/packages/adapter/src/lib/adapter/adapter.ts index 55a2d7a227..aa56193b69 100644 --- a/packages/adapter/src/lib/adapter/adapter.ts +++ b/packages/adapter/src/lib/adapter/adapter.ts @@ -1619,19 +1619,19 @@ export class AdapterClass extends EventEmitter { } // external signature - getUserID(username: string): Promise; + getUserID(username: string): Promise; /** * Return ID of given username * * @param username - name of the user */ - getUserID(username: unknown): Promise { + getUserID(username: unknown): Promise { Validator.assertString(username, 'username'); return this._getUserID({ username }); } - private async _getUserID(options: InternalGetUserIDOptions): Promise { + private async _getUserID(options: InternalGetUserIDOptions): Promise { if (!this.usernames[options.username]) { try { // did not find username, we should have a look in the cache @@ -2492,7 +2492,7 @@ export class AdapterClass extends EventEmitter { } // external signature - setTimeout(cb: TimeoutCallback, timeout: number, ...args: any[]): NodeJS.Timeout | void; + setTimeout(cb: TimeoutCallback, timeout: number, ...args: any[]): ioBroker.Timeout | undefined; /** * Same as setTimeout * but it clears the running timers on unload @@ -2503,7 +2503,7 @@ export class AdapterClass extends EventEmitter { * @param args - as many arguments as needed, which will be passed to setTimeout * @returns timer id */ - setTimeout(cb: unknown, timeout: unknown, ...args: unknown[]): NodeJS.Timeout | void { + setTimeout(cb: unknown, timeout: unknown, ...args: unknown[]): ioBroker.Timeout | undefined { if (typeof cb !== 'function') { this._logger.warn( `${this.namespaceLog} setTimeout expected callback to be of type "function", but got "${typeof cb}"` @@ -2529,10 +2529,10 @@ export class AdapterClass extends EventEmitter { ); this._timers.add(timer); - return timer; + return timer as unknown as ioBroker.Timeout; } - clearTimeout(timer: NodeJS.Timeout): void; + clearTimeout(timer: ioBroker.Timeout | undefined): void; /** * Same as clearTimeout @@ -2541,9 +2541,13 @@ export class AdapterClass extends EventEmitter { * @param timer - the timer object */ clearTimeout(timer: unknown): void { - // should we validate this? - clearTimeout(timer as any); - this._timers.delete(timer as any); + if (timer === undefined) { + return; + } + + // should we further validate this? + clearTimeout(timer as NodeJS.Timeout); + this._timers.delete(timer as NodeJS.Timeout); } // external signature @@ -2575,7 +2579,7 @@ export class AdapterClass extends EventEmitter { } // external signature - setInterval(cb: TimeoutCallback, timeout: number, ...args: any[]): NodeJS.Timeout | void; + setInterval(cb: TimeoutCallback, timeout: number, ...args: any[]): ioBroker.Interval | undefined; /** * Same as setInterval @@ -2587,7 +2591,7 @@ export class AdapterClass extends EventEmitter { * @param args - as many arguments as needed, which will be passed to setTimeout * @returns interval interval object */ - setInterval(cb: unknown, timeout: unknown, ...args: unknown[]): NodeJS.Timeout | void { + setInterval(cb: unknown, timeout: unknown, ...args: unknown[]): ioBroker.Interval | undefined { if (typeof cb !== 'function') { this._logger.error( `${this.namespaceLog} setInterval expected callback to be of type "function", but got "${typeof cb}"` @@ -2606,11 +2610,11 @@ export class AdapterClass extends EventEmitter { const id = setInterval(() => cb(...args), timeout); this._intervals.add(id); - return id; + return id as unknown as ioBroker.Interval; } // external signature - clearInterval(interval: NodeJS.Timeout): void; + clearInterval(interval: ioBroker.Interval | undefined): void; /** * Same as clearInterval @@ -2619,9 +2623,13 @@ export class AdapterClass extends EventEmitter { * @param interval - interval object */ clearInterval(interval: unknown): void { - // should we validate it is a valid interval? - clearInterval(interval as any); - this._intervals.delete(interval as any); + if (interval === undefined) { + return; + } + + // should we further validate it is a valid interval? + clearInterval(interval as NodeJS.Timeout); + this._intervals.delete(interval as NodeJS.Timeout); } setObject(id: string, obj: ioBroker.SettableObject, callback?: ioBroker.SetObjectCallback): Promise; @@ -2660,7 +2668,7 @@ export class AdapterClass extends EventEmitter { * } * ``` */ - setObject(id: unknown, obj: unknown, options: unknown, callback?: unknown): Promise { + setObject(id: unknown, obj: unknown, options: unknown, callback?: unknown): Promise | void { if (typeof options === 'function') { callback = options; options = null; @@ -7372,26 +7380,26 @@ export class AdapterClass extends EventEmitter { id: string | ioBroker.IdObject, state: ioBroker.State | ioBroker.StateValue | ioBroker.SettableState, callback?: T - ): T extends ioBroker.SetStateCallback ? Promise : ioBroker.SetStatePromise; + ): T extends ioBroker.SetStateCallback ? void : ioBroker.SetStatePromise; setState( id: string | ioBroker.IdObject, state: ioBroker.State | ioBroker.StateValue | ioBroker.SettableState, ack: boolean, callback?: T - ): T extends ioBroker.SetStateCallback ? Promise : ioBroker.SetStatePromise; + ): T extends ioBroker.SetStateCallback ? void : ioBroker.SetStatePromise; setState( id: string | ioBroker.IdObject, state: ioBroker.State | ioBroker.StateValue | ioBroker.SettableState, options?: Partial | null, callback?: T - ): T extends ioBroker.SetStateCallback ? Promise : ioBroker.SetStatePromise; + ): T extends ioBroker.SetStateCallback ? void : ioBroker.SetStatePromise; setState( id: string | ioBroker.IdObject, state: ioBroker.State | ioBroker.StateValue | ioBroker.SettableState, ack: boolean, options?: Partial | null, callback?: T - ): T extends ioBroker.SetStateCallback ? Promise : ioBroker.SetStatePromise; + ): T extends ioBroker.SetStateCallback ? void : ioBroker.SetStatePromise; /** * Writes value into states DB. @@ -7424,7 +7432,13 @@ export class AdapterClass extends EventEmitter { * } * ``` */ - setState(id: unknown, state: unknown, ack: unknown, options?: unknown, callback?: unknown): Promise { + setState( + id: unknown, + state: unknown, + ack: unknown, + options?: unknown, + callback?: unknown + ): Promise | void { if (typeof state === 'object' && typeof ack !== 'boolean') { callback = options; options = ack; @@ -10782,11 +10796,10 @@ export class AdapterClass extends EventEmitter { this._initializeTimeout = setTimeout(() => { this._initializeTimeout = null; if (this._config.isInstall) { - this._logger && this._logger.warn(`${this.namespaceLog} no connection to states DB. Terminating.`); + this._logger.warn(`${this.namespaceLog} no connection to states DB. Terminating.`); this.terminate(EXIT_CODES.NO_ERROR); } else { - this._logger && - this._logger.warn(`${this.namespaceLog} slow connection to states DB. Still waiting ...`); + this._logger.warn(`${this.namespaceLog} slow connection to states DB. Still waiting ...`); } }, this._config.states.connectTimeout || 2_000); @@ -10946,8 +10959,8 @@ export class AdapterClass extends EventEmitter { // If someone want to have log messages if (id.endsWith('.logging')) { const instance = id.substring(0, id.length - '.logging'.length); - this._logger && - this._logger.silly(`${this.namespaceLog} ${instance}: logging ${state ? state.val : false}`); + + this._logger.silly(`${this.namespaceLog} ${instance}: logging ${state ? state.val : false}`); this.logRedirect!(state ? !!state.val : false, instance); } else if (id === `log.system.adapter.${this.namespace}`) { this._options.logTransporter && this.processLog && this.processLog(state); @@ -11087,10 +11100,7 @@ export class AdapterClass extends EventEmitter { if (this.connected) { return; } // If reconnected in the meantime, do not terminate - this._logger && - this._logger.warn( - `${this.namespaceLog} Cannot connect/reconnect to states DB. Terminating` - ); + this._logger.warn(`${this.namespaceLog} Cannot connect/reconnect to states DB. Terminating`); this.terminate(EXIT_CODES.NO_ERROR); }, 5000); } @@ -11101,11 +11111,10 @@ export class AdapterClass extends EventEmitter { this._initializeTimeout = setTimeout(() => { this._initializeTimeout = null; if (this._config.isInstall) { - this._logger && this._logger.warn(`${this.namespaceLog} no connection to objects DB. Terminating`); + this._logger.warn(`${this.namespaceLog} no connection to objects DB. Terminating`); this.terminate(EXIT_CODES.NO_ERROR); } else { - this._logger && - this._logger.warn(`${this.namespaceLog} slow connection to objects DB. Still waiting ...`); + this._logger.warn(`${this.namespaceLog} slow connection to objects DB. Still waiting ...`); } }, this._config.objects.connectTimeout * 2); // Because we do not connect only anymore, give it a bit more time @@ -11158,10 +11167,8 @@ export class AdapterClass extends EventEmitter { if (this.connected) { return; } // If reconnected in the meantime, do not terminate - this._logger && - this._logger.warn( - `${this.namespaceLog} Cannot connect/reconnect to objects DB. Terminating` - ); + + this._logger.warn(`${this.namespaceLog} Cannot connect/reconnect to objects DB. Terminating`); this.terminate(EXIT_CODES.NO_ERROR); }, 4000); }, diff --git a/packages/common/src/lib/common/tools.ts b/packages/common/src/lib/common/tools.ts index cc463199e3..b0c65861dd 100644 --- a/packages/common/src/lib/common/tools.ts +++ b/packages/common/src/lib/common/tools.ts @@ -410,7 +410,7 @@ function getMac(callback: (e?: Error | null, mac?: string) => void): void { */ export function getDockerInformation(): DockerInformation { try { - const versionString = fs.readFileSync(OFFICIAL_DOCKER_FILE, { encoding: 'utf-8' }); + const versionString = fs.readFileSync(OFFICIAL_DOCKER_FILE, { encoding: 'utf-8' }).trim(); return { isDocker: true, isOfficial: true, officialVersion: versionString }; } catch { // ignore error @@ -2239,30 +2239,20 @@ export function getDefaultDataDir(): string { return './data/'; } - const _appName = appName.toLowerCase(); - - // if debugging with npm5 - if (fs.existsSync(`${__dirname}/../../../node_modules/${_appName}.js-controller`)) { - return `../${_appName}-data/`; - } else { - // If installed with npm - return `../../${_appName}-data/`; - } + return path.join('..', '..', `${appNameLowerCase}-data/`); } /** * Returns the path of the config file */ export function getConfigFileName(): string { - const _appName = appName.toLowerCase(); - // Allow overriding the config file location with an environment variable let envDataDir = process.env[`${appName.toUpperCase()}_DATA_DIR`]; if (envDataDir) { if (!path.isAbsolute(envDataDir)) { envDataDir = path.join(getControllerDir(), envDataDir); } - return path.join(envDataDir, `${_appName}.json`); + return path.join(envDataDir, `${appNameLowerCase}.json`); } let devConfigDir; @@ -2275,10 +2265,10 @@ export function getConfigFileName(): string { devConfigParts.splice(devConfigParts.length - 4, 4); devConfigDir = devConfigParts.join('/'); devConfigDir += '/controller'; // go inside controller dir - if (fs.existsSync(`${devConfigDir}/conf/${_appName}.json`)) { - return `${devConfigDir}/conf/${_appName}.json`; - } else if (fs.existsSync(`${devConfigDir}/data/${_appName}.json`)) { - return `${devConfigDir}/data/${_appName}.json`; + if (fs.existsSync(`${devConfigDir}/conf/${appNameLowerCase}.json`)) { + return `${devConfigDir}/conf/${appNameLowerCase}.json`; + } else if (fs.existsSync(`${devConfigDir}/data/${appNameLowerCase}.json`)) { + return `${devConfigDir}/data/${appNameLowerCase}.json`; } } @@ -2287,8 +2277,8 @@ export function getConfigFileName(): string { // if debugging with npm5 -> node_modules on e.g. /opt/node_modules if ( - fs.existsSync(`${__dirname}/../../../../../../../../node_modules/${_appName.toLowerCase()}.js-controller`) || - fs.existsSync(`${__dirname}/../../../../../../../../node_modules/${_appName}.js-controller`) + fs.existsSync(`${__dirname}/../../../../../../../../node_modules/${appNameLowerCase}.js-controller`) || + fs.existsSync(`${__dirname}/../../../../../../../../node_modules/${appName}.js-controller`) ) { // remove /node_modules/' + appName + '.js-controller/lib configParts.splice(configParts.length - 8, 8); @@ -2299,11 +2289,11 @@ export function getConfigFileName(): string { configDir = configParts.join('/'); } - if (!fs.existsSync(`${configDir}/${_appName}-data/${_appName}.json`) && devConfigDir) { - return `${devConfigDir}/data/${_appName}.json`; + if (!fs.existsSync(`${configDir}/${appNameLowerCase}-data/${appNameLowerCase}.json`) && devConfigDir) { + return `${devConfigDir}/data/${appNameLowerCase}.json`; } - return `${configDir}/${_appName}-data/${_appName}.json`; + return `${configDir}/${appNameLowerCase}-data/${appNameLowerCase}.json`; } /** diff --git a/packages/types-public/index.test-d.ts b/packages/types-public/index.test-d.ts index 996516d5b2..437ee86884 100644 --- a/packages/types-public/index.test-d.ts +++ b/packages/types-public/index.test-d.ts @@ -688,15 +688,19 @@ declare let enumObj: ioBroker.EnumObject; enumObj.common.members && enumObj.common.members.map(() => 1); // Adapter.clearTimeout and clearInterval are not compatible with the builtins -adapter.clearTimeout(adapter.setTimeout(() => {}, 10)!); -adapter.clearInterval(adapter.setInterval(() => {}, 10)!); +adapter.clearTimeout(adapter.setTimeout(() => {}, 10)); +adapter.clearInterval(adapter.setInterval(() => {}, 10)); +// @ts-expect-error +adapter.clearInterval(adapter.setTimeout(() => {}, 10)); +// @ts-expect-error +adapter.clearTimeout(adapter.setInterval(() => {}, 10)); // @ts-expect-error clearTimeout(adapter.setTimeout(() => {}, 10)); // @ts-expect-error clearInterval(adapter.setInterval(() => {}, 10)); -// todo types need to be implemented to not allow interchanging between nodejs and iob timers @ts-expect-error +// @ts-expect-error adapter.clearTimeout(setTimeout(() => {}, 10)); -// todo types need to be implemented to not allow interchanging between nodejs and iob timers @ts-expect-error +// @ts-expect-error adapter.clearInterval(setInterval(() => {}, 10)); // And they must not be switched // @ts-expect-error