From 8d896670504b246b9c826f8b32cd1fb465a7d25e Mon Sep 17 00:00:00 2001 From: Dominic Griesel Date: Wed, 16 Oct 2024 14:04:07 +0200 Subject: [PATCH] refactor: reorganize traits --- .../core/src/abstractions/ICommandClass.ts | 38 ------- .../core/src/abstractions/IZWaveEndpoint.ts | 69 ------------ packages/core/src/consts/Transmission.ts | 2 +- packages/core/src/index.ts | 7 +- packages/core/src/index_safe.ts | 8 +- packages/core/src/traits/CommandClasses.ts | 56 ++++++++++ packages/core/src/traits/Endpoints.ts | 21 ++++ .../IZWaveNode.ts => traits/Nodes.ts} | 48 ++------ packages/core/src/traits/SecurityManagers.ts | 12 ++ .../maintenance/src/codeshifts/moveImport.ts | 104 ++++++++++++++++++ packages/zwave-js/src/lib/node/Endpoint.ts | 4 +- packages/zwave-js/src/lib/node/Node.ts | 5 +- .../zwave-js/src/lib/node/VirtualEndpoint.ts | 8 +- packages/zwave-js/src/lib/node/VirtualNode.ts | 5 +- .../src/lib/node/mixins/50_Endpoints.ts | 7 +- 15 files changed, 217 insertions(+), 177 deletions(-) delete mode 100644 packages/core/src/abstractions/ICommandClass.ts delete mode 100644 packages/core/src/abstractions/IZWaveEndpoint.ts create mode 100644 packages/core/src/traits/CommandClasses.ts create mode 100644 packages/core/src/traits/Endpoints.ts rename packages/core/src/{abstractions/IZWaveNode.ts => traits/Nodes.ts} (60%) create mode 100644 packages/core/src/traits/SecurityManagers.ts create mode 100644 packages/maintenance/src/codeshifts/moveImport.ts diff --git a/packages/core/src/abstractions/ICommandClass.ts b/packages/core/src/abstractions/ICommandClass.ts deleted file mode 100644 index 867c409c1e59..000000000000 --- a/packages/core/src/abstractions/ICommandClass.ts +++ /dev/null @@ -1,38 +0,0 @@ -import type { CommandClasses } from "../capabilities/CommandClasses"; -import type { - MulticastDestination, - NODE_ID_BROADCAST, - NODE_ID_BROADCAST_LR, -} from "../consts"; -import { type SecurityManager } from "../security/Manager"; -import { type SecurityManager2 } from "../security/Manager2"; - -/** Allows accessing the security manager instances */ -export interface SecurityManagers { - /** Management of Security S0 keys and nonces */ - securityManager: SecurityManager | undefined; - /** Management of Security S2 keys and nonces (Z-Wave Classic) */ - securityManager2: SecurityManager2 | undefined; - /** Management of Security S2 keys and nonces (Z-Wave Long Range) */ - securityManagerLR: SecurityManager2 | undefined; -} - -/** A basic abstraction of a Z-Wave Command Class providing access to the relevant functionality */ -export interface CCId { - nodeId: number | MulticastDestination; - endpointIndex?: number; - ccId: CommandClasses; - ccCommand?: number; -} - -export type SinglecastCC = T & { - nodeId: number; -}; - -export type MulticastCC = T & { - nodeId: MulticastDestination; -}; - -export type BroadcastCC = T & { - nodeId: typeof NODE_ID_BROADCAST | typeof NODE_ID_BROADCAST_LR; -}; diff --git a/packages/core/src/abstractions/IZWaveEndpoint.ts b/packages/core/src/abstractions/IZWaveEndpoint.ts deleted file mode 100644 index d54716695d4f..000000000000 --- a/packages/core/src/abstractions/IZWaveEndpoint.ts +++ /dev/null @@ -1,69 +0,0 @@ -import type { - CommandClassInfo, - CommandClasses, -} from "../capabilities/CommandClasses"; -import type { MulticastDestination } from "../consts"; -import type { IVirtualNode, NodeId } from "./IZWaveNode"; - -/** Identifies an endpoint */ -export interface EndpointId { - readonly virtual: false; - readonly nodeId: number; - readonly index: number; -} - -/** Allows querying if a CC is supported and in which version */ -export interface SupportsCC { - supportsCC(cc: CommandClasses): boolean; - getCCVersion(cc: CommandClasses): number; -} - -/** Allows querying if a CC is controlled */ -export interface ControlsCC { - controlsCC(cc: CommandClasses): boolean; -} - -/** Allows querying if a CC is supported or controlled only securely */ -export interface IsCCSecure { - isCCSecure(cc: CommandClasses): boolean; -} - -/** Allows querying all implemented CCs and their information */ -export interface GetCCs { - getCCs(): Iterable<[ccId: CommandClasses, info: CommandClassInfo]>; -} - -/** Allows modifying the list of supported/controlled CCs */ -export interface ModifyCCs { - addCC(cc: CommandClasses, info: Partial): void; - removeCC(cc: CommandClasses): void; -} - -/** Allows accessing the parent node of the endpoint, if it exists */ -export interface GetEndpointNode { - tryGetNode(): T | undefined; -} - -/** A basic abstraction of a Z-Wave endpoint providing access to the relevant functionality */ -export interface IZWaveEndpoint - extends - EndpointId, - SupportsCC, - ControlsCC, - IsCCSecure, - ModifyCCs, - GetCCs, - GetEndpointNode -{} - -/** Identifies a virtual endpoint */ -export interface VirtualEndpointId { - readonly virtual: true; - readonly nodeId: number | MulticastDestination; - readonly index: number; -} - -/** A basic abstraction of an endpoint of a virtual node (multicast or broadcast) providing access to the relevant functionality */ -export interface IVirtualEndpoint extends VirtualEndpointId, SupportsCC { - readonly node: IVirtualNode; -} diff --git a/packages/core/src/consts/Transmission.ts b/packages/core/src/consts/Transmission.ts index fe6863fd625c..006dab8e9cab 100644 --- a/packages/core/src/consts/Transmission.ts +++ b/packages/core/src/consts/Transmission.ts @@ -1,8 +1,8 @@ import { num2hex } from "@zwave-js/shared/safe"; import { isObject } from "alcalzone-shared/typeguards"; -import type { CCId } from "../abstractions/ICommandClass"; import type { ProtocolDataRate } from "../capabilities/Protocols"; import { type SecurityClass } from "../security/SecurityClass"; +import type { CCId } from "../traits/CommandClasses"; import { Duration } from "../values/Duration"; /** The priority of messages, sorted from high (0) to low (>0) */ diff --git a/packages/core/src/index.ts b/packages/core/src/index.ts index 6afee8722c97..4fe19cbc112e 100644 --- a/packages/core/src/index.ts +++ b/packages/core/src/index.ts @@ -1,7 +1,4 @@ /* eslint-disable @typescript-eslint/consistent-type-exports */ -export * from "./abstractions/ICommandClass"; -export * from "./abstractions/IZWaveEndpoint"; -export * from "./abstractions/IZWaveNode"; export * from "./capabilities/CommandClasses"; export * from "./capabilities/ControllerCapabilities"; export * from "./capabilities/LibraryTypes"; @@ -30,6 +27,10 @@ export * from "./security/crypto"; export * from "./security/ctr_drbg"; export * from "./security/shared_safe"; export * from "./test/assertZWaveError"; +export * from "./traits/CommandClasses"; +export * from "./traits/Endpoints"; +export * from "./traits/Nodes"; +export * from "./traits/SecurityManagers"; export * from "./util/_Types"; export * from "./util/config"; export * from "./util/crc"; diff --git a/packages/core/src/index_safe.ts b/packages/core/src/index_safe.ts index c241edf8958f..7c15660e1ae8 100644 --- a/packages/core/src/index_safe.ts +++ b/packages/core/src/index_safe.ts @@ -1,9 +1,6 @@ /* eslint-disable @typescript-eslint/consistent-type-exports */ /* @forbiddenImports external */ -export * from "./abstractions/ICommandClass"; -export * from "./abstractions/IZWaveEndpoint"; -export * from "./abstractions/IZWaveNode"; export * from "./capabilities/CommandClasses"; export * from "./capabilities/ControllerCapabilities"; export * from "./capabilities/LibraryTypes"; @@ -24,6 +21,11 @@ export * from "./registries/Sensors"; export * from "./security/DSK"; export * from "./security/SecurityClass"; export * from "./security/shared_safe"; +export * from "./traits/CommandClasses"; +export * from "./traits/Endpoints"; +export * from "./traits/Endpoints"; +export * from "./traits/Nodes"; +export * from "./traits/SecurityManagers"; export * from "./util/_Types"; export * from "./util/config"; export * from "./util/crc"; diff --git a/packages/core/src/traits/CommandClasses.ts b/packages/core/src/traits/CommandClasses.ts new file mode 100644 index 000000000000..759567a2d7dc --- /dev/null +++ b/packages/core/src/traits/CommandClasses.ts @@ -0,0 +1,56 @@ +import type { + CommandClassInfo, + CommandClasses, +} from "../capabilities/CommandClasses"; +import type { + MulticastDestination, + NODE_ID_BROADCAST, + NODE_ID_BROADCAST_LR, +} from "../consts"; + +/** A basic abstraction of a Z-Wave Command Class providing access to the relevant functionality */ +export interface CCId { + nodeId: number | MulticastDestination; + endpointIndex?: number; + ccId: CommandClasses; + ccCommand?: number; +} + +export type SinglecastCC = T & { + nodeId: number; +}; + +export type MulticastCC = T & { + nodeId: MulticastDestination; +}; + +export type BroadcastCC = T & { + nodeId: typeof NODE_ID_BROADCAST | typeof NODE_ID_BROADCAST_LR; +}; + +/** Allows querying if a CC is supported and in which version */ +export interface SupportsCC { + supportsCC(cc: CommandClasses): boolean; + getCCVersion(cc: CommandClasses): number; +} + +/** Allows querying if a CC is controlled */ +export interface ControlsCC { + controlsCC(cc: CommandClasses): boolean; +} + +/** Allows querying if a CC is supported or controlled only securely */ +export interface IsCCSecure { + isCCSecure(cc: CommandClasses): boolean; +} + +/** Allows querying all implemented CCs and their information */ +export interface GetCCs { + getCCs(): Iterable<[ccId: CommandClasses, info: CommandClassInfo]>; +} + +/** Allows modifying the list of supported/controlled CCs */ +export interface ModifyCCs { + addCC(cc: CommandClasses, info: Partial): void; + removeCC(cc: CommandClasses): void; +} diff --git a/packages/core/src/traits/Endpoints.ts b/packages/core/src/traits/Endpoints.ts new file mode 100644 index 000000000000..0e42d1353b2a --- /dev/null +++ b/packages/core/src/traits/Endpoints.ts @@ -0,0 +1,21 @@ +import { type MulticastDestination } from "../consts/Transmission"; +import { type NodeId } from "./Nodes"; + +/** Identifies an endpoint */ +export interface EndpointId { + readonly virtual: false; + readonly nodeId: number; + readonly index: number; +} + +/** Identifies a virtual endpoint */ +export interface VirtualEndpointId { + readonly virtual: true; + readonly nodeId: number | MulticastDestination; + readonly index: number; +} + +/** Allows accessing the parent node of the endpoint, if it exists */ +export interface GetEndpointNode { + tryGetNode(): T | undefined; +} diff --git a/packages/core/src/abstractions/IZWaveNode.ts b/packages/core/src/traits/Nodes.ts similarity index 60% rename from packages/core/src/abstractions/IZWaveNode.ts rename to packages/core/src/traits/Nodes.ts index 70c393ab18c5..80b6fbbac7c3 100644 --- a/packages/core/src/abstractions/IZWaveNode.ts +++ b/packages/core/src/traits/Nodes.ts @@ -1,16 +1,7 @@ -import type { FLiRS } from "../capabilities/NodeInfo"; -import type { InterviewStage, NodeStatus } from "../consts"; -import type { - QuerySecurityClasses, - SetSecurityClass, -} from "../security/SecurityClass"; +import { type FLiRS } from "../capabilities/NodeInfo"; +import { type NodeStatus } from "../consts/NodeStatus"; import { type MaybeNotKnown } from "../values/Primitive"; -import type { - EndpointId, - IVirtualEndpoint, - IZWaveEndpoint, - VirtualEndpointId, -} from "./IZWaveEndpoint"; +import { type EndpointId, type VirtualEndpointId } from "./Endpoints"; /** Identifies a node */ export interface NodeId extends EndpointId { @@ -19,6 +10,10 @@ export interface NodeId extends EndpointId { // readonly index: number; } +export interface VirtualNodeId extends VirtualEndpointId { + readonly id: number | undefined; +} + /** Allows accessing a specific endpoint */ export interface GetEndpoint { getEndpoint(index: 0): T; @@ -51,35 +46,6 @@ export interface QueryNodeStatus { readonly status: NodeStatus; } -/** A basic abstraction of a Z-Wave node providing access to the relevant functionality */ -export interface IZWaveNode - extends - IZWaveEndpoint, - NodeId, - ListenBehavior, - QueryNodeStatus, - GetEndpoint, - GetAllEndpoints, - QuerySecurityClasses, - SetSecurityClass -{ - interviewStage: InterviewStage; -} - -export interface VirtualNodeId extends VirtualEndpointId { - readonly id: number | undefined; -} - export interface PhysicalNodes { readonly physicalNodes: readonly T[]; } - -/** A basic abstraction of a virtual node (multicast or broadcast) providing access to the relevant functionality */ -export interface IVirtualNode - extends - IVirtualEndpoint, - VirtualNodeId, - GetEndpoint, - PhysicalNodes -{ -} diff --git a/packages/core/src/traits/SecurityManagers.ts b/packages/core/src/traits/SecurityManagers.ts new file mode 100644 index 000000000000..c366240633e5 --- /dev/null +++ b/packages/core/src/traits/SecurityManagers.ts @@ -0,0 +1,12 @@ +import { type SecurityManager } from "../security/Manager"; +import { type SecurityManager2 } from "../security/Manager2"; + +/** Allows accessing the security manager instances */ +export interface SecurityManagers { + /** Management of Security S0 keys and nonces */ + securityManager: SecurityManager | undefined; + /** Management of Security S2 keys and nonces (Z-Wave Classic) */ + securityManager2: SecurityManager2 | undefined; + /** Management of Security S2 keys and nonces (Z-Wave Long Range) */ + securityManagerLR: SecurityManager2 | undefined; +} diff --git a/packages/maintenance/src/codeshifts/moveImport.ts b/packages/maintenance/src/codeshifts/moveImport.ts new file mode 100644 index 000000000000..5bfc1da315ca --- /dev/null +++ b/packages/maintenance/src/codeshifts/moveImport.ts @@ -0,0 +1,104 @@ +// Codemod to rename imports across the entire codebase. +// Run with jscodeshift: https://jscodeshift.com/run/cli/ +// options: +// from: the name of the import to rename +// to: the new name of the import +// typeOnly: whether to only rename type imports (optional, default false) + +// examples: https://github.com/wingy3181/jscodeshift-examples/tree/master/src/examples + +import { + type API, + type FileInfo, + type JSCodeshift, + type Options, + type Transform, +} from "jscodeshift"; + +const transform: Transform = ( + file: FileInfo, + api: API, + { + name, + from, + to, + }: Options, +) => { + if (!name || !to) { + throw new Error("Both 'name' and 'to' are required options"); + } + + const j: JSCodeshift = api.jscodeshift; + const root = j(file.source); + + const imp = root + .find( + j.ImportDeclaration, + from && { + source: { + type: "StringLiteral", + value: from, + }, + }, + ) + .find(j.ImportSpecifier, { + imported: { + name: name, + }, + }); + + if (imp.length !== 1) return file.source; + + const decl = imp.closest(j.ImportDeclaration); + + const isTypeOnly = (imp.at(0).nodes()[0] as any).importKind === "type" + || decl.at(0).nodes()[0].importKind === "type"; + + // Remove the found import from its parent + imp.remove(); + // And remove all empty imports + root + .find( + j.ImportDeclaration, + from && { + source: { + type: "StringLiteral", + value: from, + }, + }, + ).filter((path) => !path.value.specifiers?.length) + .remove(); + + // Try to find an existing import for the new specifier + const targetDecl = root + .find( + j.ImportDeclaration, + { + source: { + type: "StringLiteral", + value: to, + }, + ...(isTypeOnly ? { importKind: "type" } : {}), + }, + ); + + if (targetDecl.length === 1) { + targetDecl.at(0).get().node.specifiers.push( + j.importSpecifier(j.identifier(name)), + ); + } else { + // Create the new import specifier + root.find(j.Program).at(0).nodes()[0].body.unshift( + j.importDeclaration( + [j.importSpecifier(j.identifier(name))], + j.stringLiteral(to), + isTypeOnly ? "type" : "value", + ), + ); + } + + return root.toSource(); +}; + +export default transform; +export const parser = "ts"; diff --git a/packages/zwave-js/src/lib/node/Endpoint.ts b/packages/zwave-js/src/lib/node/Endpoint.ts index c9a052c7eb25..042c0c3910ef 100644 --- a/packages/zwave-js/src/lib/node/Endpoint.ts +++ b/packages/zwave-js/src/lib/node/Endpoint.ts @@ -15,7 +15,6 @@ import type { EndpointId, GetCCs, GetEndpointNode, - IZWaveEndpoint, IsCCSecure, MaybeNotKnown, ModifyCCs, @@ -54,8 +53,7 @@ export class Endpoint IsCCSecure, ModifyCCs, GetCCs, - GetEndpointNode, - IZWaveEndpoint + GetEndpointNode { public constructor( /** The id of the node this endpoint belongs to */ diff --git a/packages/zwave-js/src/lib/node/Node.ts b/packages/zwave-js/src/lib/node/Node.ts index c57a36aa8609..b23bf7b15cec 100644 --- a/packages/zwave-js/src/lib/node/Node.ts +++ b/packages/zwave-js/src/lib/node/Node.ts @@ -145,7 +145,6 @@ import { CommandClasses, Duration, EncapsulationFlags, - type IZWaveNode, type MaybeNotKnown, MessagePriority, NOT_KNOWN, @@ -287,9 +286,7 @@ export interface ZWaveNode * of its root endpoint (index 0) */ @Mixin([EventEmitter, NodeStatisticsHost]) -export class ZWaveNode extends ZWaveNodeMixins - implements QuerySecurityClasses, IZWaveNode -{ +export class ZWaveNode extends ZWaveNodeMixins implements QuerySecurityClasses { public constructor( id: number, driver: Driver, diff --git a/packages/zwave-js/src/lib/node/VirtualEndpoint.ts b/packages/zwave-js/src/lib/node/VirtualEndpoint.ts index bbb9aacc70ad..b965df0d6571 100644 --- a/packages/zwave-js/src/lib/node/VirtualEndpoint.ts +++ b/packages/zwave-js/src/lib/node/VirtualEndpoint.ts @@ -10,7 +10,6 @@ import { } from "@zwave-js/cc"; import { type CommandClasses, - type IVirtualEndpoint, type MulticastDestination, type SecurityClass, type SupportsCC, @@ -32,11 +31,9 @@ import { VirtualNode } from "./VirtualNode"; * * The endpoint's capabilities are determined by the capabilities of the individual nodes' endpoints. */ -export class VirtualEndpoint - implements VirtualEndpointId, SupportsCC, IVirtualEndpoint -{ +export class VirtualEndpoint implements VirtualEndpointId, SupportsCC { public constructor( - /** The virtual node this endpoint belongs to (or undefined if it set later) */ + /** The virtual node this endpoint belongs to */ node: VirtualNode | undefined, /** The driver instance this endpoint belongs to */ protected readonly driver: Driver, @@ -54,7 +51,6 @@ export class VirtualEndpoint public get node(): VirtualNode { return this._node; } - /** @internal */ protected setNode(node: VirtualNode): void { this._node = node; } diff --git a/packages/zwave-js/src/lib/node/VirtualNode.ts b/packages/zwave-js/src/lib/node/VirtualNode.ts index 65cf9ce86349..0a26c4590ae2 100644 --- a/packages/zwave-js/src/lib/node/VirtualNode.ts +++ b/packages/zwave-js/src/lib/node/VirtualNode.ts @@ -10,7 +10,6 @@ import { supervisionResultToSetValueResult, } from "@zwave-js/cc/safe"; import { - type IVirtualNode, SecurityClass, SupervisionStatus, type TranslatedValueID, @@ -59,7 +58,7 @@ function groupNodesBySecurityClass( return ret; } -export class VirtualNode extends VirtualEndpoint implements IVirtualNode { +export class VirtualNode extends VirtualEndpoint { public constructor( public readonly id: number | undefined, driver: Driver, @@ -179,7 +178,7 @@ export class VirtualNode extends VirtualEndpoint implements IVirtualNode { if (api.isSetValueOptimistic(valueId)) { // If the call did not throw, assume that the call was successful and remember the new value // for each node that was affected by this command - const affectedNodes = endpointInstance.node.physicalNodes + const affectedNodes = this.physicalNodes .filter((node) => node .getEndpoint(endpointInstance.index) diff --git a/packages/zwave-js/src/lib/node/mixins/50_Endpoints.ts b/packages/zwave-js/src/lib/node/mixins/50_Endpoints.ts index 0e29fe4716b4..1e0985293f26 100644 --- a/packages/zwave-js/src/lib/node/mixins/50_Endpoints.ts +++ b/packages/zwave-js/src/lib/node/mixins/50_Endpoints.ts @@ -3,7 +3,6 @@ import { type CommandClasses, type GetAllEndpoints, type GetEndpoint, - type IZWaveNode, type MaybeNotKnown, ZWaveError, ZWaveErrorCodes, @@ -42,11 +41,7 @@ export interface Endpoints { } export abstract class EndpointsMixin extends NodeValuesMixin - implements - Endpoints, - GetEndpoint, - GetAllEndpoints, - IZWaveNode + implements Endpoints, GetEndpoint, GetAllEndpoints { public get endpointCountIsDynamic(): MaybeNotKnown { return nodeUtils.endpointCountIsDynamic(this.driver, this.id);