Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[typing] Added types to adapter.ts #2922

Merged
merged 11 commits into from
Jan 9, 2025
4 changes: 3 additions & 1 deletion packages/adapter/src/lib/_Types.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
export interface AdapterOptions {

Check warning on line 1 in packages/adapter/src/lib/_Types.ts

View workflow job for this annotation

GitHub Actions / Eslint

Missing JSDoc comment
subscribesChange?: (

Check warning on line 2 in packages/adapter/src/lib/_Types.ts

View workflow job for this annotation

GitHub Actions / Eslint

Missing JSDoc comment
subs: Record<
string,
{
regex: RegExp;

Check warning on line 6 in packages/adapter/src/lib/_Types.ts

View workflow job for this annotation

GitHub Actions / Eslint

Missing JSDoc comment
}
>,
) => void;
Expand Down Expand Up @@ -70,10 +70,10 @@

type Invoice = 'free' | (string & {});

export interface SuitableLicense {

Check warning on line 73 in packages/adapter/src/lib/_Types.ts

View workflow job for this annotation

GitHub Actions / Eslint

Missing JSDoc comment
/** Name of the license type, not necessarily matching adapter */
product: string;
/** E-Mail of license owner */
/** E-Mail of a license owner */
email: string;
/** Unique id of this license */
id: string;
Expand All @@ -95,18 +95,18 @@
decoded: {
/** E-Mail of license owner */
email: string;
comment: string;

Check warning on line 98 in packages/adapter/src/lib/_Types.ts

View workflow job for this annotation

GitHub Actions / Eslint

Missing JSDoc comment
/** License type, eg private */
type: string;
/** Adapter name */
name: string;
/** Address of license owner */
address: {
Country: string;

Check warning on line 105 in packages/adapter/src/lib/_Types.ts

View workflow job for this annotation

GitHub Actions / Eslint

Missing JSDoc comment
Name: string;

Check warning on line 106 in packages/adapter/src/lib/_Types.ts

View workflow job for this annotation

GitHub Actions / Eslint

Missing JSDoc comment
AddressLine1: string;

Check warning on line 107 in packages/adapter/src/lib/_Types.ts

View workflow job for this annotation

GitHub Actions / Eslint

Missing JSDoc comment
AddressLine2: string;

Check warning on line 108 in packages/adapter/src/lib/_Types.ts

View workflow job for this annotation

GitHub Actions / Eslint

Missing JSDoc comment
ZIP: string;

Check warning on line 109 in packages/adapter/src/lib/_Types.ts

View workflow job for this annotation

GitHub Actions / Eslint

Missing JSDoc comment
City: string;
};
ltype: string;
Expand Down Expand Up @@ -149,6 +149,8 @@
accepted: boolean;
/** Optional heartbeat, if set, the client needs to re-subscribe every heartbeat interval */
heartbeat?: number;
/** Optional error if not accepted */
error?: string;
}

type UserInterfaceUnsubscribeInfoBaseObject = {
Expand Down
84 changes: 46 additions & 38 deletions packages/adapter/src/lib/adapter/adapter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,7 @@ import type {
} from '@/lib/_Types.js';
import { UserInterfaceMessagingController } from '@/lib/adapter/userInterfaceMessagingController.js';
import { SYSTEM_ADAPTER_PREFIX } from '@iobroker/js-controller-common-db/constants';
import { isLogLevel } from '@iobroker/js-controller-common-db/tools';

const controllerVersion = packJson.version;

Expand Down Expand Up @@ -609,6 +610,20 @@ export interface AdapterClass {
getStatesOfAsync(parentDevice: string, parentChannel: string, options?: unknown): Promise<ioBroker.StateObject[]>;
}

/**
* Contents of iobroker.json plus some internal variables
*/
interface InternalAdapterJsonConfig extends ioBroker.IoBrokerJson {
/** Is instance started with the `--install` flag */
isInstall?: boolean;
/** If logs must be printed to stdout */
consoleOutput?: boolean;
/** Start instance even if it disabled in config */
forceIfDisabled?: boolean;
/** Instance number */
instance?: number;
}

/**
* Adapter class
*
Expand All @@ -628,7 +643,7 @@ export class AdapterClass extends EventEmitter {
/** Objects DB constructor */
private Objects?: typeof ObjectsInRedisClient;
/** Contents of iobroker.json */
private readonly _config: Record<string, any>;
private readonly _config: InternalAdapterJsonConfig;
private readonly _options: AdapterOptions;
private readonly startedInCompactMode: boolean;
/** List of instances which want our logs */
Expand Down Expand Up @@ -700,7 +715,7 @@ export class AdapterClass extends EventEmitter {
private _initializeTimeout?: NodeJS.Timeout | null;
private inited?: boolean;
/** contents of iobroker.json if required via AdapterOptions */
systemConfig?: Record<string, any>;
systemConfig?: InternalAdapterJsonConfig;
/** the configured date format of system.config, only available if requested via AdapterOptions `useFormatDate` */
dateFormat?: any;
/** if float comma instead of dot is used, only available if requested via AdapterOptions `useFormatDate` */
Expand Down Expand Up @@ -778,7 +793,10 @@ export class AdapterClass extends EventEmitter {
this._options.config.log = this._config.log;
}

this._config = this._options.config || this._config;
// this used in tests
if (this._options.config) {
this._config = this._options.config as ioBroker.IoBrokerJson;
}
this.startedInCompactMode = !!this._options.compact;

const parsedArgs = yargs(process.argv.slice(2))
Expand Down Expand Up @@ -818,7 +836,7 @@ export class AdapterClass extends EventEmitter {
})
.parseSync();

if (parsedArgs.loglevel && ['info', 'debug', 'error', 'warn', 'silly'].includes(parsedArgs.loglevel)) {
if (parsedArgs.loglevel && isLogLevel(parsedArgs.loglevel)) {
this._config.log.level = parsedArgs.loglevel;
this.overwriteLogLevel = true;
}
Expand Down Expand Up @@ -861,11 +879,11 @@ export class AdapterClass extends EventEmitter {
}

const instance = parseInt(
this._options.compactInstance !== undefined
(this._options.compactInstance !== undefined
? this._options.compactInstance
: this._options.instance !== undefined
? this._options.instance
: this._config.instance || 0,
: this._config.instance || 0) as unknown as string,
10,
);

Expand Down Expand Up @@ -10506,15 +10524,15 @@ export class AdapterClass extends EventEmitter {
logs.push(`Actual Loglist - ${JSON.stringify(Array.from(this.logList))}`);

if (!this.#states) {
// if adapterState was destroyed, we can not continue
// if adapterState was destroyed, we cannot continue
return;
}

// Read current state of all log subscribers
// Read the current state of all log subscribers
this.#states.getKeys(`${SYSTEM_ADAPTER_PREFIX}*.logging`, (err, keys) => {
if (keys?.length) {
if (!this.#states) {
// if adapterState was destroyed, we can not continue
// if adapterState was destroyed, we cannot continue
return;
}

Expand Down Expand Up @@ -10560,7 +10578,7 @@ export class AdapterClass extends EventEmitter {
*/
private async _initLogging(): Promise<void> {
if (!this.#states) {
// if adapterState was destroyed, we can not continue
// if adapterState was destroyed, we cannot continue
return;
}

Expand All @@ -10583,13 +10601,13 @@ export class AdapterClass extends EventEmitter {
if (messages && !this._options.logTransporter) {
messages.push(info);

// do not let messages grow without limit
// do not let messages grow without a limit
if (messages.length > this._config.states.maxQueue) {
messages.splice(0, messages.length - this._config.states.maxQueue);
}
}
} else if (this.#states?.pushLog) {
// Send to all adapter, that required logs
// Send it to all adapters, that required logs
for (const instanceId of this.logList) {
this.#states.pushLog(instanceId, info);
}
Expand All @@ -10599,15 +10617,15 @@ export class AdapterClass extends EventEmitter {
const keys = await this.#states.getKeys(`${SYSTEM_ADAPTER_PREFIX}*.logging`);
if (keys?.length) {
if (!this.#states) {
// if adapterState was destroyed, we can not continue
// if adapterState was destroyed, we cannot continue
return;
}

const obj = await this.#states.getStates(keys);
if (obj) {
for (let i = 0; i < keys.length; i++) {
const objPart = obj[i];
// We can JSON.parse, but index is 16x faster
// We can JSON.parse, but the index is 16x faster
if (!objPart) {
continue;
}
Expand Down Expand Up @@ -10833,27 +10851,24 @@ export class AdapterClass extends EventEmitter {
if (id === `system.adapter.${this.namespace}.logLevel`) {
if (this._config && this._config.log && state && !state.ack) {
let currentLevel = this._config.log.level;
if (
state.val &&
state.val !== currentLevel &&
['silly', 'debug', 'info', 'warn', 'error'].includes(state.val as string)
) {
const newLogLevel = state.val as string;
if (state.val && state.val !== currentLevel && isLogLevel(newLogLevel)) {
this.overwriteLogLevel = true;
this._config.log.level = state.val;
this._config.log.level = newLogLevel;
for (const transport in this._logger.transports) {
if (!Object.prototype.hasOwnProperty.call(this._logger.transports, transport)) {
continue;
}
// set the loglevel on transport only if no loglevel was pinned in log config
// @ts-expect-error it is our own modification
if (!this._logger.transports[transport]._defaultConfigLoglevel) {
this._logger.transports[transport].level = state.val as string;
this._logger.transports[transport].level = newLogLevel;
}
}
this._logger.info(
`${this.namespaceLog} Loglevel changed from "${currentLevel}" to "${state.val}"`,
);
currentLevel = state.val;
currentLevel = newLogLevel;
} else if (state.val && state.val !== currentLevel) {
this._logger.info(`${this.namespaceLog} Got invalid loglevel "${state.val}", ignoring`);
}
Expand Down Expand Up @@ -10990,7 +11005,7 @@ export class AdapterClass extends EventEmitter {
} else if (!this._stopInProgress && this.adapterReady && this.aliases.has(id)) {
// If adapter is ready and for this ID exist some alias links
const alias = this.aliases.get(id)!;
/** Prevent multiple publishes if multiple pattern contain this alias id */
/** Prevent multiple publishes if multiple patterns contain this alias id */
const uniqueTargets = new Set<string>();

for (const target of alias.targets) {
Expand Down Expand Up @@ -11352,8 +11367,7 @@ export class AdapterClass extends EventEmitter {
!this._config.forceIfDisabled &&
!this._config.isInstall &&
!this.startedInCompactMode &&
killRes &&
killRes.from?.startsWith('system.host.') &&
killRes?.from?.startsWith('system.host.') &&
killRes.ack &&
!isNaN(killRes.val as any) &&
killRes.val !== process.pid
Expand All @@ -11362,13 +11376,7 @@ export class AdapterClass extends EventEmitter {
`${this.namespaceLog} ${this.namespace} invalid process id scenario ${killRes.val} vs. own ID ${process.pid}. Stopping`,
);
this.terminate(EXIT_CODES.ADAPTER_REQUESTED_TERMINATION);
} else if (
!this._config.isInstall &&
resAlive &&
resAlive.val === true &&
resAlive.ack &&
!this._config.forceIfDisabled
) {
} else if (!this._config.isInstall && resAlive?.val === true && resAlive.ack && !this._config.forceIfDisabled) {
this._logger.error(`${this.namespaceLog} ${this.namespace} already running`);
this.terminate(EXIT_CODES.ADAPTER_ALREADY_RUNNING);
} else {
Expand Down Expand Up @@ -11404,7 +11412,7 @@ export class AdapterClass extends EventEmitter {
this.pluginHandler.setDatabaseForPlugins(this.#objects, this.#states);
await this.pluginHandler.initPlugins(adapterConfig || {});
if (!this.#states || !this.#objects || this.terminated) {
// if adapterState was destroyed,we should not continue
// if adapterState was destroyed, we should not continue
return;
}

Expand Down Expand Up @@ -11639,7 +11647,7 @@ export class AdapterClass extends EventEmitter {
}in ${this.adapterDir}, node: ${process.version}, js-controller: ${controllerVersion}`,
);
this._config.system = this._config.system || {};
this._config.system.statisticsInterval = parseInt(this._config.system.statisticsInterval, 10) || 15_000;
this._config.system.statisticsInterval = Math.round(this._config.system.statisticsInterval) || 15_000;
if (!this._config.isInstall) {
this._reportInterval = setInterval(() => this._reportStatus(), this._config.system.statisticsInterval);
this._reportStatus();
Expand Down Expand Up @@ -11820,7 +11828,7 @@ export class AdapterClass extends EventEmitter {
}

if (!obj._id.startsWith(this.namespace)) {
// instanceObjects are normally defined without namespace prefix
// instanceObjects are normally defined without a namespace prefix
obj._id = obj._id === '' ? this.namespace : `${this.namespace}.${obj._id}`;
}

Expand Down Expand Up @@ -12060,13 +12068,13 @@ export class AdapterClass extends EventEmitter {
if (this._options.systemConfig) {
this.systemConfig = this._config;
// Workaround for an admin 5 issue which could lead to deleting the dataDir folder
// TODO: remove it as soon as all adapters are fixed which use systemConfig.dataDir
// TODO: 08.2022 FR remove it as soon as all adapters are fixed which use systemConfig.dataDir
if (!Object.prototype.hasOwnProperty.call(this.systemConfig, 'dataDir')) {
this.systemConfig.dataDir = tools.getDefaultDataDir();
}
}

if (this._config.states && this._config.states.type) {
if (this._config.states?.type) {
try {
this.States = (await import(`@iobroker/db-states-${this._config.states.type}`)).Client;
} catch (e) {
Expand All @@ -12076,7 +12084,7 @@ export class AdapterClass extends EventEmitter {
this.States = await getStatesConstructor();
}

if (this._config.objects && this._config.objects.type) {
if (this._config.objects?.type) {
try {
this.Objects = (await import(`@iobroker/db-objects-${this._config.objects.type}`)).Client;
} catch (e) {
Expand Down
9 changes: 9 additions & 0 deletions packages/common-db/src/lib/common/tools.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4024,6 +4024,15 @@ export async function getPids(): Promise<number[]> {
return pids;
}

/**
* Check if given string is a valid loglevel
*
* @param level level to validate
*/
export function isLogLevel(level: string): level is ioBroker.LogLevel {
return ['silly', 'debug', 'info', 'warn', 'error'].includes(level);
}

/**
* Get the controller pid
*
Expand Down
2 changes: 1 addition & 1 deletion packages/controller/conf/iobroker-dist.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@
"host": "127.0.0.1",
"port": 9001,
"noFileCache": false,
"maxQueue": 1000,
"connectTimeout": 5000,
"writeFileInterval": 5000,
"dataDir": "",
Expand Down Expand Up @@ -78,6 +77,7 @@
"connectTimeout": 5000,
"writeFileInterval": 30000,
"dataDir": "",
"maxQueue": 1000,
"options": {
"auth_pass": "",
"retry_max_delay": 5000,
Expand Down
13 changes: 5 additions & 8 deletions packages/controller/src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ import {
getDefaultNodeArgs,
type HostInfo,
isAdapterEsmModule,
isLogLevel,
} from '@iobroker/js-controller-common-db/tools';
import type { UpgradeArguments } from '@/lib/upgradeManager.js';
import { AdapterUpgradeManager } from '@/lib/adapterUpgradeManager.js';
Expand Down Expand Up @@ -570,11 +571,7 @@ function createStates(onConnect: () => void): void {
return;
}
let currentLevel = config.log.level;
if (
typeof state.val === 'string' &&
state.val !== currentLevel &&
['silly', 'debug', 'info', 'warn', 'error'].includes(state.val)
) {
if (typeof state.val === 'string' && state.val !== currentLevel && isLogLevel(state.val)) {
config.log.level = state.val;
for (const transport in logger.transports) {
if (
Expand Down Expand Up @@ -5281,17 +5278,17 @@ export async function init(compactGroupId?: number): Promise<void> {
States = await getStatesConstructor();
}

// Detect if outputs to console are forced. By default, they are disabled and redirected to log file
// Detect if outputs to console are forced. By default, they are disabled and redirected to the log file
if (
config.log.noStdout &&
process.argv &&
(process.argv.indexOf('--console') !== -1 || process.argv.indexOf('--logs') !== -1)
(process.argv.includes('--console') || process.argv.includes('--logs') || process.argv.includes('--debug'))
) {
config.log.noStdout = false;
}

// Detect if controller runs as a linux-daemon
if (process.argv.indexOf('start') !== -1 && !compactGroupController) {
if (process.argv.includes('start') && !compactGroupController) {
isDaemon = true;
config.log.noStdout = true;
}
Expand Down
1 change: 0 additions & 1 deletion packages/db-base/src/lib/inMemFileDB.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,6 @@ export interface ConnectionOptions {
/** array on sentinel */
port: number | number[];
options: Record<string, any>;
maxQueue?: number;
enhancedLogging?: boolean;
backup?: BackupOptions;
/** relative path to the data dir */
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -229,9 +229,6 @@ export class ObjectsInRedisClient {
const onChangeUser = this.settings.changeUser; // on change handler for User events
const onChangeFileUser = this.settings.changeFileUser; // on change handler for User file events

// limit max number of log entries in the list
this.settings.connection.maxQueue = this.settings.connection.maxQueue || 1_000;

this.settings.connection.options = this.settings.connection.options || {};
const retry_max_delay: number = this.settings.connection.options.retry_max_delay || 5_000;
const retry_max_count: number = this.settings.connection.options.retry_max_count || 19;
Expand Down
2 changes: 0 additions & 2 deletions packages/db-states-file/src/lib/states/statesInMemFileDB.js
Original file line number Diff line number Diff line change
Expand Up @@ -61,8 +61,6 @@ export class StatesInMemoryFileDB extends InMemoryFileDB {
this.log.silly(`${this.namespace} States DB uses file write interval of ${this.writeFileInterval} ms`);
}

//this.settings.connection.maxQueue = this.settings.connection.maxQueue || 1000;

// Reset expires, that are still in DB
this._expireAll();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -154,9 +154,6 @@ export class StateRedisClient {
let reconnectCounter = 0;
let errorLogged = false;

// limit max number of log entries in the list
this.settings.connection.maxQueue = this.settings.connection.maxQueue || 1000;

this.settings.connection.options = this.settings.connection.options || {};
const retry_max_delay = this.settings.connection.options.retry_max_delay || 5000;
const retry_max_count = this.settings.connection.options.retry_max_count || 19;
Expand Down
Loading
Loading