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

refactor: replace Node.js Buffer with Uint8Array or portable replacement #7332

Merged
merged 12 commits into from
Oct 29, 2024
11 changes: 11 additions & 0 deletions eslint.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,17 @@ export default tseslint.config(
"unicorn/prefer-string-slice": "error",
"unicorn/prefer-string-starts-ends-with": "error",
"unicorn/prefer-string-replace-all": "error",

// Prefer our own Buffer implementation (compatible with native Uint8array)
// See https://sindresorhus.com/blog/goodbye-nodejs-buffer for the reason behind this
"no-restricted-globals": [
"error",
{
name: "Buffer",
message:
"Use Uint8Array or the Bytes implementation from @zwave-js/shared instead.",
},
],
},
},
// Disable unnecessarily strict rules for test files
Expand Down
5 changes: 3 additions & 2 deletions packages/cc/src/cc/AlarmSensorCC.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import type {
CCParsingContext,
GetValueDB,
} from "@zwave-js/host/safe";
import { Bytes } from "@zwave-js/shared/safe";
import { getEnumMemberName, isEnumMember, pick } from "@zwave-js/shared/safe";
import { validateArgs } from "@zwave-js/transformers";
import { CCAPI, PhysicalCCAPI } from "../lib/API";
Expand Down Expand Up @@ -449,8 +450,8 @@ export class AlarmSensorCCGet extends AlarmSensorCC {

public sensorType: AlarmSensorType;

public serialize(ctx: CCEncodingContext): Buffer {
this.payload = Buffer.from([this.sensorType]);
public serialize(ctx: CCEncodingContext): Bytes {
this.payload = Bytes.from([this.sensorType]);
return super.serialize(ctx);
}

Expand Down
25 changes: 13 additions & 12 deletions packages/cc/src/cc/AssociationCC.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import type {
GetDeviceConfig,
GetValueDB,
} from "@zwave-js/host/safe";
import { Bytes } from "@zwave-js/shared/safe";
import { validateArgs } from "@zwave-js/transformers";
import { distinct } from "alcalzone-shared/arrays";
import { CCAPI, PhysicalCCAPI } from "../lib/API";
Expand Down Expand Up @@ -539,8 +540,8 @@ export class AssociationCCSet extends AssociationCC {
public groupId: number;
public nodeIds: number[];

public serialize(ctx: CCEncodingContext): Buffer {
this.payload = Buffer.from([this.groupId, ...this.nodeIds]);
public serialize(ctx: CCEncodingContext): Bytes {
this.payload = Bytes.from([this.groupId, ...this.nodeIds]);
return super.serialize(ctx);
}

Expand Down Expand Up @@ -598,8 +599,8 @@ export class AssociationCCRemove extends AssociationCC {
public groupId?: number;
public nodeIds?: number[];

public serialize(ctx: CCEncodingContext): Buffer {
this.payload = Buffer.from([
public serialize(ctx: CCEncodingContext): Bytes {
this.payload = Bytes.from([
this.groupId || 0,
...(this.nodeIds || []),
]);
Expand Down Expand Up @@ -692,8 +693,8 @@ export class AssociationCCReport extends AssociationCC {
.reduce((prev, cur) => prev.concat(...cur), []);
}

public serialize(ctx: CCEncodingContext): Buffer {
this.payload = Buffer.from([
public serialize(ctx: CCEncodingContext): Bytes {
this.payload = Bytes.from([
this.groupId,
this.maxNodes,
this.reportsToFollow,
Expand Down Expand Up @@ -748,8 +749,8 @@ export class AssociationCCGet extends AssociationCC {

public groupId: number;

public serialize(ctx: CCEncodingContext): Buffer {
this.payload = Buffer.from([this.groupId]);
public serialize(ctx: CCEncodingContext): Bytes {
this.payload = Bytes.from([this.groupId]);
return super.serialize(ctx);
}

Expand Down Expand Up @@ -792,8 +793,8 @@ export class AssociationCCSupportedGroupingsReport extends AssociationCC {
@ccValue(AssociationCCValues.groupCount)
public groupCount: number;

public serialize(ctx: CCEncodingContext): Buffer {
this.payload = Buffer.from([this.groupCount]);
public serialize(ctx: CCEncodingContext): Bytes {
this.payload = Bytes.from([this.groupCount]);
return super.serialize(ctx);
}

Expand Down Expand Up @@ -839,8 +840,8 @@ export class AssociationCCSpecificGroupReport extends AssociationCC {

public group: number;

public serialize(ctx: CCEncodingContext): Buffer {
this.payload = Buffer.from([this.group]);
public serialize(ctx: CCEncodingContext): Bytes {
this.payload = Bytes.from([this.group]);
return super.serialize(ctx);
}

Expand Down
31 changes: 16 additions & 15 deletions packages/cc/src/cc/AssociationGroupInfoCC.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import type {
CCParsingContext,
GetValueDB,
} from "@zwave-js/host/safe";
import { Bytes } from "@zwave-js/shared/safe";
import { cpp2js, getEnumMemberName, num2hex } from "@zwave-js/shared/safe";
import { validateArgs } from "@zwave-js/transformers";
import { CCAPI, PhysicalCCAPI } from "../lib/API";
Expand Down Expand Up @@ -520,10 +521,10 @@ export class AssociationGroupInfoCCNameReport extends AssociationGroupInfoCC {
return true;
}

public serialize(ctx: CCEncodingContext): Buffer {
this.payload = Buffer.concat([
Buffer.from([this.groupId, this.name.length]),
Buffer.from(this.name, "utf8"),
public serialize(ctx: CCEncodingContext): Bytes {
this.payload = Bytes.concat([
Bytes.from([this.groupId, this.name.length]),
Bytes.from(this.name, "utf8"),
]);
return super.serialize(ctx);
}
Expand Down Expand Up @@ -569,8 +570,8 @@ export class AssociationGroupInfoCCNameGet extends AssociationGroupInfoCC {

public groupId: number;

public serialize(ctx: CCEncodingContext): Buffer {
this.payload = Buffer.from([this.groupId]);
public serialize(ctx: CCEncodingContext): Bytes {
this.payload = Bytes.from([this.groupId]);
return super.serialize(ctx);
}

Expand Down Expand Up @@ -663,8 +664,8 @@ export class AssociationGroupInfoCCInfoReport extends AssociationGroupInfoCC {
return true;
}

public serialize(ctx: CCEncodingContext): Buffer {
this.payload = Buffer.alloc(1 + this.groups.length * 7, 0);
public serialize(ctx: CCEncodingContext): Bytes {
this.payload = Bytes.alloc(1 + this.groups.length * 7, 0);

this.payload[0] = (this.isListMode ? 0b1000_0000 : 0)
| (this.hasDynamicInfo ? 0b0100_0000 : 0)
Expand All @@ -673,7 +674,7 @@ export class AssociationGroupInfoCCInfoReport extends AssociationGroupInfoCC {
for (let i = 0; i < this.groups.length; i++) {
const offset = 1 + i * 7;
this.payload[offset] = this.groups[i].groupId;
this.payload.writeUint16BE(this.groups[i].profile, offset + 2);
this.payload.writeUInt16BE(this.groups[i].profile, offset + 2);
// The remaining bytes are zero
}

Expand Down Expand Up @@ -754,11 +755,11 @@ export class AssociationGroupInfoCCInfoGet extends AssociationGroupInfoCC {
public listMode?: boolean;
public groupId?: number;

public serialize(ctx: CCEncodingContext): Buffer {
public serialize(ctx: CCEncodingContext): Bytes {
const isListMode = this.listMode === true;
const optionByte = (this.refreshCache ? 0b1000_0000 : 0)
| (isListMode ? 0b0100_0000 : 0);
this.payload = Buffer.from([
this.payload = Bytes.from([
optionByte,
isListMode ? 0 : this.groupId!,
]);
Expand Down Expand Up @@ -836,10 +837,10 @@ export class AssociationGroupInfoCCCommandListReport
)
public readonly commands: ReadonlyMap<CommandClasses, readonly number[]>;

public serialize(ctx: CCEncodingContext): Buffer {
public serialize(ctx: CCEncodingContext): Bytes {
// To make it easier to encode possible extended CCs, we first
// allocate as much space as we may need, then trim it again
this.payload = Buffer.allocUnsafe(2 + this.commands.size * 3);
this.payload = new Bytes(2 + this.commands.size * 3);
this.payload[0] = this.groupId;
let offset = 2;
for (const [ccId, commands] of this.commands) {
Expand Down Expand Up @@ -912,8 +913,8 @@ export class AssociationGroupInfoCCCommandListGet
public allowCache: boolean;
public groupId: number;

public serialize(ctx: CCEncodingContext): Buffer {
this.payload = Buffer.from([
public serialize(ctx: CCEncodingContext): Bytes {
this.payload = Bytes.from([
this.allowCache ? 0b1000_0000 : 0,
this.groupId,
]);
Expand Down
13 changes: 7 additions & 6 deletions packages/cc/src/cc/BarrierOperatorCC.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import type {
CCParsingContext,
GetValueDB,
} from "@zwave-js/host/safe";
import { Bytes } from "@zwave-js/shared/safe";
import {
getEnumMemberName,
isEnumMember,
Expand Down Expand Up @@ -571,8 +572,8 @@ export class BarrierOperatorCCSet extends BarrierOperatorCC {

public targetState: BarrierState.Open | BarrierState.Closed;

public serialize(ctx: CCEncodingContext): Buffer {
this.payload = Buffer.from([this.targetState]);
public serialize(ctx: CCEncodingContext): Bytes {
this.payload = Bytes.from([this.targetState]);
return super.serialize(ctx);
}

Expand Down Expand Up @@ -757,8 +758,8 @@ export class BarrierOperatorCCEventSignalingSet extends BarrierOperatorCC {
public subsystemType: SubsystemType;
public subsystemState: SubsystemState;

public serialize(ctx: CCEncodingContext): Buffer {
this.payload = Buffer.from([this.subsystemType, this.subsystemState]);
public serialize(ctx: CCEncodingContext): Bytes {
this.payload = Bytes.from([this.subsystemType, this.subsystemState]);
return super.serialize(ctx);
}

Expand Down Expand Up @@ -877,8 +878,8 @@ export class BarrierOperatorCCEventSignalingGet extends BarrierOperatorCC {

public subsystemType: SubsystemType;

public serialize(ctx: CCEncodingContext): Buffer {
this.payload = Buffer.from([this.subsystemType]);
public serialize(ctx: CCEncodingContext): Bytes {
this.payload = Bytes.from([this.subsystemType]);
return super.serialize(ctx);
}

Expand Down
9 changes: 5 additions & 4 deletions packages/cc/src/cc/BasicCC.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import type {
GetSupportedCCVersion,
GetValueDB,
} from "@zwave-js/host/safe";
import { Bytes } from "@zwave-js/shared/safe";
import { pick } from "@zwave-js/shared/safe";
import { validateArgs } from "@zwave-js/transformers";
import {
Expand Down Expand Up @@ -396,8 +397,8 @@ export class BasicCCSet extends BasicCC {

public targetValue: number;

public serialize(ctx: CCEncodingContext): Buffer {
this.payload = Buffer.from([this.targetValue]);
public serialize(ctx: CCEncodingContext): Bytes {
this.payload = Bytes.from([this.targetValue]);
return super.serialize(ctx);
}

Expand Down Expand Up @@ -506,8 +507,8 @@ export class BasicCCReport extends BasicCC {
return true;
}

public serialize(ctx: CCEncodingContext): Buffer {
this.payload = Buffer.from([
public serialize(ctx: CCEncodingContext): Bytes {
this.payload = Bytes.from([
this.currentValue ?? 0xfe,
this.targetValue ?? 0xfe,
(this.duration ?? Duration.unknown()).serializeReport(),
Expand Down
9 changes: 5 additions & 4 deletions packages/cc/src/cc/BatteryCC.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import type {
GetSupportedCCVersion,
GetValueDB,
} from "@zwave-js/host/safe";
import { Bytes } from "@zwave-js/shared/safe";
import { type AllOrNone, getEnumMemberName, pick } from "@zwave-js/shared/safe";
import {
CCAPI,
Expand Down Expand Up @@ -564,12 +565,12 @@ export class BatteryCCReport extends BatteryCC {
@ccValue(BatteryCCValues.lowTemperatureStatus)
public readonly lowTemperatureStatus: boolean | undefined;

public serialize(ctx: CCEncodingContext): Buffer {
this.payload = Buffer.from([this.isLow ? 0xff : this.level]);
public serialize(ctx: CCEncodingContext): Bytes {
this.payload = Bytes.from([this.isLow ? 0xff : this.level]);
if (this.chargingStatus != undefined) {
this.payload = Buffer.concat([
this.payload = Bytes.concat([
this.payload,
Buffer.from([
Bytes.from([
(this.chargingStatus << 6)
+ (this.rechargeable ? 0b0010_0000 : 0)
+ (this.backup ? 0b0001_0000 : 0)
Expand Down
11 changes: 6 additions & 5 deletions packages/cc/src/cc/BinarySensorCC.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import type {
CCParsingContext,
GetValueDB,
} from "@zwave-js/host/safe";
import { Bytes } from "@zwave-js/shared/safe";
import { getEnumMemberName, isEnumMember } from "@zwave-js/shared/safe";
import { validateArgs } from "@zwave-js/transformers";
import {
Expand Down Expand Up @@ -399,8 +400,8 @@ export class BinarySensorCCReport extends BinarySensorCC {
public type: BinarySensorType;
public value: boolean;

public serialize(ctx: CCEncodingContext): Buffer {
this.payload = Buffer.from([this.value ? 0xff : 0x00, this.type]);
public serialize(ctx: CCEncodingContext): Bytes {
this.payload = Bytes.from([this.value ? 0xff : 0x00, this.type]);
return super.serialize(ctx);
}

Expand Down Expand Up @@ -459,8 +460,8 @@ export class BinarySensorCCGet extends BinarySensorCC {

public sensorType: BinarySensorType | undefined;

public serialize(ctx: CCEncodingContext): Buffer {
this.payload = Buffer.from([this.sensorType ?? BinarySensorType.Any]);
public serialize(ctx: CCEncodingContext): Bytes {
this.payload = Bytes.from([this.sensorType ?? BinarySensorType.Any]);
return super.serialize(ctx);
}

Expand Down Expand Up @@ -516,7 +517,7 @@ export class BinarySensorCCSupportedReport extends BinarySensorCC {
@ccValue(BinarySensorCCValues.supportedSensorTypes)
public supportedSensorTypes: BinarySensorType[];

public serialize(ctx: CCEncodingContext): Buffer {
public serialize(ctx: CCEncodingContext): Bytes {
this.payload = encodeBitMask(
this.supportedSensorTypes.filter((t) => t !== BinarySensorType.Any),
undefined,
Expand Down
13 changes: 7 additions & 6 deletions packages/cc/src/cc/BinarySwitchCC.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import type {
CCParsingContext,
GetValueDB,
} from "@zwave-js/host/safe";
import { Bytes } from "@zwave-js/shared/safe";
import { validateArgs } from "@zwave-js/transformers";
import {
CCAPI,
Expand Down Expand Up @@ -339,8 +340,8 @@ export class BinarySwitchCCSet extends BinarySwitchCC {
public targetValue: boolean;
public duration: Duration | undefined;

public serialize(ctx: CCEncodingContext): Buffer {
this.payload = Buffer.from([
public serialize(ctx: CCEncodingContext): Bytes {
this.payload = Bytes.from([
this.targetValue ? 0xff : 0x00,
(this.duration ?? Duration.default()).serializeSet(),
]);
Expand Down Expand Up @@ -425,14 +426,14 @@ export class BinarySwitchCCReport extends BinarySwitchCC {
@ccValue(BinarySwitchCCValues.duration)
public readonly duration: Duration | undefined;

public serialize(ctx: CCEncodingContext): Buffer {
this.payload = Buffer.from([
public serialize(ctx: CCEncodingContext): Bytes {
this.payload = Bytes.from([
encodeMaybeBoolean(this.currentValue ?? UNKNOWN_STATE),
]);
if (this.targetValue !== undefined) {
this.payload = Buffer.concat([
this.payload = Bytes.concat([
this.payload,
Buffer.from([
Bytes.from([
encodeMaybeBoolean(this.targetValue),
(this.duration ?? Duration.default()).serializeReport(),
]),
Expand Down
Loading
Loading