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

[refactoring]: refactor some old functions in adapter and improve comments #2875

Open
wants to merge 11 commits into
base: master
Choose a base branch
from
182 changes: 92 additions & 90 deletions packages/adapter/src/lib/adapter/adapter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -161,14 +161,14 @@
/**
* Extend an object and create it if it might not exist
*
* @deprecated use `adapter.extendObject` without callback instead
* @deprecated use `adapter.extendObject` without a callback instead
*/
extendObjectAsync(
id: string,
objPart: ioBroker.PartialObject,
options?: ioBroker.ExtendObjectOptions
): ioBroker.SetObjectPromise;
/** Set capabilities of the given executable. Only works on Linux systems. */
/** Set the capabilities of the given executable. Only works on Linux systems. */
setExecutableCapabilities(
execPath: string,
capabilities: string[],
Expand All @@ -195,7 +195,7 @@
params: ioBroker.GetObjectViewParams | null | undefined,
options?: unknown
): ioBroker.GetObjectViewPromise<ioBroker.InferGetObjectViewItemType<Design, Search>>;
/** Returns a list of objects with id between params.startkey and params.endkey */
/** Returns a list of objects with id between `params.startkey` and `params.endkey` */
getObjectListAsync(
params: ioBroker.GetObjectListParams | null,
options?: { sorted?: boolean } | Record<string, any>
Expand Down Expand Up @@ -289,7 +289,7 @@
delStateAsync(id: string, options?: unknown): Promise<void>;
/** Deletes a state from the states DB, but not the associated object */
delForeignStateAsync(id: string, options?: unknown): Promise<void>;
/** Read all states of this adapter which match the given pattern */
/** Read all states of this adapter that match the given pattern */
getStatesAsync(pattern: string, options?: unknown): ioBroker.GetStatesPromise;
/** Read all states (which might not belong to this adapter) which match the given pattern */
getForeignStatesAsync(pattern: Pattern, options?: unknown): ioBroker.GetStatesPromise;
Expand Down Expand Up @@ -1336,7 +1336,7 @@
decrypt(secretVal: unknown, value?: unknown): string {
if (value === undefined) {
value = secretVal;
secretVal = this._systemSecret;
secretVal = this._systemSecret as string;
}

Validator.assertString(secretVal, 'secretVal');
Expand All @@ -1358,7 +1358,7 @@
encrypt(secretVal: unknown, value?: unknown): string {
if (value === undefined) {
value = secretVal;
secretVal = this._systemSecret;
secretVal = this._systemSecret as string;
}

Validator.assertString(secretVal, 'secretVal');
Expand Down Expand Up @@ -1606,7 +1606,7 @@
* ...
* }
* ```

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

View workflow job for this annotation

GitHub Actions / Eslint

Expected JSDoc block to be aligned
* @param featureName the name of the feature to check
* @returns true/false if the feature is in the list of supported features
*/
Expand Down Expand Up @@ -4538,33 +4538,31 @@
this.delForeignObject(id, options, callback);
}

private _deleteObjects(
private async _deleteObjects(
tasks: { id: string; [other: string]: any }[],
options: Record<string, any>,
cb?: () => void
): void | Promise<void> {
options: Record<string, any>
): Promise<void> {
if (!tasks || !tasks.length) {
return tools.maybeCallback(cb);
} else {
const task = tasks.shift();
this.#objects!.delObject(task!.id, options, async err => {
if (err) {
return tools.maybeCallbackWithError(cb, err);
}
if (task!.state) {
try {
await this.delForeignStateAsync(task!.id, options);
} catch (e) {
this._logger.warn(`${this.namespaceLog} Could not remove state of ${task!.id}: ${e.message}`);
}
}
return;
}
for (const task of tasks) {
try {
await this.#objects!.delObject(task!.id, options);
} catch (e) {
this._logger.warn(`${this.namespaceLog} Could not remove object ${task!.id}: ${e.message}`);
}
if (task!.state) {
try {
await tools.removeIdFromAllEnums(this.#objects, task!.id, this.enums);
await this.delForeignStateAsync(task!.id, options);
} catch (e) {
this._logger.warn(`${this.namespaceLog} Could not remove ${task!.id} from enums: ${e.message}`);
this._logger.warn(`${this.namespaceLog} Could not remove state of ${task!.id}: ${e.message}`);
}
setImmediate(() => this._deleteObjects(tasks, options, cb));
});
}
try {
await tools.removeIdFromAllEnums(this.#objects, task!.id, this.enums);
} catch (e) {
this._logger.warn(`${this.namespaceLog} Could not remove ${task!.id} from enums: ${e.message}`);
}
}
}

Expand Down Expand Up @@ -4631,15 +4629,15 @@

const selector = { startkey: `${id}.`, endkey: `${id}.\u9999` };
// read all underlying states
this.#objects!.getObjectList(selector, options, (err, res) => {
res &&
res.rows.forEach(
(item: ioBroker.GetObjectListItem<ioBroker.Object>) =>
!tasks.find(task => task.id === item.id) &&
(!item.value || !item.value.common || !item.value.common.dontDelete) && // exclude objects with dontDelete flag
tasks.push({ id: item.id, state: item.value && item.value.type === 'state' })
);
this._deleteObjects(tasks, options, callback);
this.#objects!.getObjectList(selector, options, async (err, res) => {
res?.rows.forEach(
(item: ioBroker.GetObjectListItem<ioBroker.Object>) =>
!tasks.find(task => task.id === item.id) &&
(!item.value || !item.value.common || !item.value.common.dontDelete) && // exclude objects with dontDelete flag
tasks.push({ id: item.id, state: item.value && item.value.type === 'state' })
);
await this._deleteObjects(tasks, options);
tools.maybeCallback(callback);
});
});
} else {
Expand Down Expand Up @@ -5139,11 +5137,11 @@
): void;

/**
* @param deviceName

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

View workflow job for this annotation

GitHub Actions / Eslint

Missing JSDoc @param "deviceName" description
* @param common

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

View workflow job for this annotation

GitHub Actions / Eslint

Missing JSDoc @param "common" description
* @param _native

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

View workflow job for this annotation

GitHub Actions / Eslint

Missing JSDoc @param "_native" description
* @param options

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

View workflow job for this annotation

GitHub Actions / Eslint

Missing JSDoc @param "options" description
* @param callback

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

View workflow job for this annotation

GitHub Actions / Eslint

Missing JSDoc @param "callback" description
* @deprecated use `this.extendObject` instead
*/
createDevice(deviceName: unknown, common: unknown, _native?: unknown, options?: unknown, callback?: unknown): any {
Expand Down Expand Up @@ -5234,10 +5232,10 @@
/**
* Name of channel must be in format "channel"
*
* @param parentDevice

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

View workflow job for this annotation

GitHub Actions / Eslint

Missing JSDoc @param "parentDevice" description
* @param channelName

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

View workflow job for this annotation

GitHub Actions / Eslint

Missing JSDoc @param "channelName" description
* @param roleOrCommon

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

View workflow job for this annotation

GitHub Actions / Eslint

Missing JSDoc @param "roleOrCommon" description
* @param _native

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

View workflow job for this annotation

GitHub Actions / Eslint

Missing JSDoc @param "_native" description
* @param options
* @param callback
* @deprecated use `this.extendObject` instead
Expand Down Expand Up @@ -7264,12 +7262,12 @@

/**
* Async version of sendTo
* As we have a special case (first arg can be error or result, we need to promisify manually)
* As we have a special case (first arg can be an error or result, we need to promisify manually)
*
* @param instanceName name of the instance where the message must be sent to. E.g. "pushover.0" or "system.adapter.pushover.0".
* @param command command name, like "send", "browse", "list". Command is depend on target adapter implementation.
* @param command command name, like "send", "browse", "list". Command is depending on target adapter implementation.
* @param message object that will be given as argument for request
* @param options optional options to define a timeout. This allows to get an error callback if no answer received in time (only if target is specific instance)
* @param options optional options to define a timeout. This allows getting an error callback if no answer received in time (only if target is a specific instance)
*/
sendToAsync(instanceName: unknown, command: unknown, message?: unknown, options?: unknown): any {
return new Promise((resolve, reject) => {
Expand Down Expand Up @@ -8684,7 +8682,7 @@
return tools.maybeCallbackWithError(callback, tools.ERRORS.ERROR_DB_CLOSED);
}

// read object for formatting - we ignore permissions on the target object and thus get it as admin user
// read an object for formatting - we ignore permissions on the target object and thus get it as an admin user
const targetObj = await this.#objects.getObject(targetId, {
...options,
user: SYSTEM_ADMIN_USER
Expand Down Expand Up @@ -8993,7 +8991,7 @@

if (id.startsWith(ALIAS_STARTS_WITH)) {
if (obj?.common?.alias?.id) {
// id can be string or can have attribute id.read
// id can be a string or can have attribute id.read
const aliasId = tools.isObject(obj.common.alias.id) ? obj.common.alias.id.read : obj.common.alias.id;

// validate here because we use objects/states db directly
Expand Down Expand Up @@ -9665,7 +9663,7 @@

if (!aliasDetails.source) {
await this.#states!.subscribe(sourceId);
// we ignore permissions on the source object and thus get it as admin user
// we ignore permissions on the source object and thus get it as an admin user
const sourceObj = await this.#objects!.getObject(sourceId, { user: SYSTEM_ADMIN_USER });

// if we have a common and the alias has not been removed in-between
Expand Down Expand Up @@ -11532,6 +11530,14 @@

this.adapterConfig = adapterConfig;

// Check that version in DB is the same as on disk
if ((adapterConfig as ioBroker.InstanceObject).common.version !== packJson.version) {
// TODO: think about to make upload automatically if a version on disk is newer than in DB. Now it is just hint in the log.
this._logger.warn(
`${this.namespaceLog} Version in DB is ${(adapterConfig as ioBroker.InstanceObject).common.version}, but this version is ${packJson.version}. Please synchronise the adapter with "iob upload ${(adapterConfig as ioBroker.InstanceObject).common.name}".`
);
}

this._utils = new Validator(
this.#objects,
this.#states,
Expand Down Expand Up @@ -11772,7 +11778,7 @@
}

private async _createInstancesObjects(instanceObj: ioBroker.InstanceObject): Promise<void> {
let objs: (IoPackageInstanceObject & { state?: unknown })[];
let objs: (IoPackageInstanceObject & { state?: ioBroker.StateValue })[];

if (instanceObj?.common && !('onlyWWW' in instanceObj.common) && instanceObj.common.mode !== 'once') {
objs = tools.getInstanceIndicatorObjects(this.namespace);
Expand All @@ -11782,7 +11788,7 @@

if (instanceObj && 'instanceObjects' in instanceObj) {
for (const instObj of instanceObj.instanceObjects) {
const obj: IoPackageInstanceObject & { state?: unknown } = instObj;
const obj: IoPackageInstanceObject & { state?: ioBroker.StateValue } = instObj;

const allowedTopLevelTypes: ioBroker.ObjectType[] = ['meta', 'device'];

Expand Down Expand Up @@ -11870,63 +11876,59 @@
});
}

return new Promise(resolve => {
this._extendObjects(objs, resolve);
});
}

private async _extendObjects(tasks: Record<string, any>, callback: () => void): Promise<void> {
if (!tasks || !tasks.length) {
return tools.maybeCallback(callback);
}
const task = tasks.shift();
const state = task.state;
if (state !== undefined) {
delete task.state;
}

try {
tools.validateGeneralObjectProperties(task, true);
await this._extendObjects(objs);
} catch (e) {
this._logger.error(`${this.namespaceLog} Object ${task._id} is invalid: ${e.message}`);
return tools.maybeCallbackWithError(callback, e);
}

if (!this.#objects) {
this._logger.info(
`${this.namespaceLog} extendObjects not processed because Objects database not connected.`
);
return tools.maybeCallbackWithError(callback, tools.ERRORS.ERROR_DB_CLOSED);
this._logger.error(`${this.namespaceLog} Cannot update objects: ${e}`);
}
}

// preserve attributes on instance creation
const options = { preserve: { common: ['name'], native: true } };

try {
await this.extendForeignObjectAsync(task._id, task, options);
} catch {
// ignore
private async _extendObjects(tasks: (IoPackageInstanceObject & { state?: ioBroker.StateValue })[]): Promise<void> {
if (!tasks || !tasks.length) {
return;
}
for (const task of tasks) {
const state = task.state;
if (state !== undefined) {
delete task.state;
}
try {
tools.validateGeneralObjectProperties(task, true);
} catch (e) {
this._logger.error(`${this.namespaceLog} Object ${task._id} is invalid: ${e.message}`);
throw e;
}

if (state !== undefined) {
if (!this.#states) {
if (!this.#objects) {
this._logger.info(
`${this.namespaceLog} extendObjects not processed because States database not connected.`
`${this.namespaceLog} extendObjects not processed because Objects database not connected.`
);
return tools.maybeCallbackWithError(callback, tools.ERRORS.ERROR_DB_CLOSED);
throw new Error(tools.ERRORS.ERROR_DB_CLOSED);
}
this.outputCount++;
this.#states.setState(
task._id,
{

// preserve attributes on instance creation
const options = { preserve: { common: ['name'], native: true } };

try {
await this.extendForeignObjectAsync(task._id, task, options);
} catch {
// ignore
}

if (state !== undefined) {
if (!this.#states) {
this._logger.info(
`${this.namespaceLog} extendObjects not processed because States database not connected.`
);
throw new Error(tools.ERRORS.ERROR_DB_CLOSED);
}
this.outputCount++;
await this.#states.setState(task._id, {
val: state,
from: `system.adapter.${this.namespace}`,
ack: true
},
() => setImmediate(() => this._extendObjects(tasks, callback))
);
} else {
setImmediate(() => this._extendObjects(tasks, callback));
});
}
}
}

Expand Down
Loading