Skip to content

Commit

Permalink
refactor: test browser entry points, fix several tree-shaking issues (#…
Browse files Browse the repository at this point in the history
  • Loading branch information
AlCalzone authored Jan 28, 2025
1 parent 2b535cc commit b5919c7
Show file tree
Hide file tree
Showing 28 changed files with 445 additions and 95 deletions.
9 changes: 9 additions & 0 deletions eslint.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,15 @@ export default tseslint.config(
"@typescript-eslint/*": "off",
},
},
// Make sure that the browser barrel files are parsed with the correct conditions
{
files: ["packages/**/*.browser.ts", "packages/**/index_browser.ts"],
languageOptions: {
parserOptions: {
project: "tsconfig.browser.json",
},
},
},
// Enable rules from the local plugin for relevant files
{
files: ["packages/cc/src/**/*CC.ts"],
Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,7 @@
"clean": "yarn turbo run clean",
"build": "yarn turbo run build:turbo --",
"build:turbo": "yarn ts maintenance/build.ts",
"check:browser": "yarn workspace zwave-js exec tsc -p tsconfig.browser.json --pretty",
"watch": "yarn w build",
"test:ts": "vitest run",
"test": "yarn ts maintenance/test.mts",
Expand Down
16 changes: 15 additions & 1 deletion packages/cc/src/index_browser.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,22 @@
/* @forbiddenImports external */

export * from "./cc/index.js";
export * from "./lib/API.js";
export * from "./lib/CommandClass.js";
export * from "./lib/CommandClassDecorators.js";
export * from "./lib/EncapsulatingCommandClass.js";
export {
MGRPExtension,
MOSExtension,
MPANExtension,
SPANExtension,
Security2Extension,
extensionType,
getExtensionType,
getS2ExtensionConstructor,
} from "./lib/Security2/Extension.js";
export * from "./lib/Security2/shared.js";
export * from "./lib/SetValueResult.js";
// eslint-disable-next-line @zwave-js/no-forbidden-imports -- FIXME: This is actually wrong, but I need to get the release done
export { defaultCCValueOptions } from "./lib/Values.js";
export type {
CCValueOptions,
Expand Down
4 changes: 2 additions & 2 deletions packages/cc/src/lib/CommandClass.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,15 +43,15 @@ import {
isZWaveError,
parseCCId,
valueIdToString,
} from "@zwave-js/core";
} from "@zwave-js/core/safe";
import {
Bytes,
type JSONObject,
buffer2hex,
getEnumMemberName,
num2hex,
staticExtends,
} from "@zwave-js/shared";
} from "@zwave-js/shared/safe";
import { isArray } from "alcalzone-shared/typeguards";
import type { CCAPIHost, CCAPINode, ValueIDProperties } from "./API.js";
import {
Expand Down
10 changes: 5 additions & 5 deletions packages/cc/src/lib/CommandClassDecorators.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import {
type CommandClasses,
ZWaveError,
ZWaveErrorCodes,
} from "@zwave-js/core";
import {
createReflectionDecorator,
createReflectionDecoratorPair,
createValuelessReflectionDecorator,
} from "@zwave-js/core/reflection";
import {
type CommandClasses,
ZWaveError,
ZWaveErrorCodes,
} from "@zwave-js/core/safe";
import type { TypedClassDecorator } from "@zwave-js/shared";
import type { APIConstructor, CCAPI } from "./API.js";
import {
Expand Down
1 change: 1 addition & 0 deletions packages/config/src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import type { DeviceConfigIndexEntry } from "./devices/DeviceConfig.js";
const require = createRequire(import.meta.url);

/** The absolute path of the embedded configuration directory */
// FIXME: use import.meta.resolve after upgrading to node 20
export const configDir = path.resolve(
path.dirname(require.resolve("@zwave-js/config/package.json")),
"config",
Expand Down
1 change: 1 addition & 0 deletions packages/core/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@
],
"imports": {
"#crypto_primitives": {
"browser": "./build/esm/crypto/primitives/primitives.browser.js",
"@@dev": "./src/crypto/primitives/primitives.node.ts",
"require": "./build/cjs/crypto/primitives/primitives.node.js",
"node": "./build/esm/crypto/primitives/primitives.node.js",
Expand Down
1 change: 1 addition & 0 deletions packages/core/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ export * from "./reflection/decorators.js";
export * from "./registries/index.js";
export * from "./security/Manager.js";
export * from "./security/Manager2.js";
export * from "./security/Manager2Types.js";
export * from "./security/ctr_drbg.wrapper.js";
export * from "./test/assertZWaveError.js";
export type * from "./traits/index.js";
Expand Down
7 changes: 5 additions & 2 deletions packages/core/src/index_browser.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
/* @forbiddenImports external */
// FIXME: Find a way to make sure that the forbiddenImports lint uses the "browser" condition

// eslint-disable-next-line @zwave-js/no-forbidden-imports -- FIXME: The lint fails here
export * from "./crypto/index.browser.js";
export * from "./definitions/index.js";
export * from "./dsk/index.js";
export * from "./error/ZWaveError.js";
export * from "./fsm/FSM.js";
export * from "./log/shared_safe.js";
export * from "./qr/index.browser.js";
export * from "./registries/DeviceClasses.js";
Expand All @@ -14,11 +13,14 @@ export * from "./registries/Meters.js";
export * from "./registries/Notifications.js";
export * from "./registries/Scales.js";
export * from "./registries/Sensors.js";
export * from "./security/Manager2Types.js";
export type * from "./traits/index.js";
export type * from "./util/_Types.js";
export * from "./util/compareVersions.js";
export { deflateSync, gunzipSync } from "./util/compression.js";
export * from "./util/config.js";
export * from "./util/crc.js";
export * from "./util/date.js";
export * from "./util/graph.js";
export * from "./util/misc.js";
export * from "./values/Cache.js";
Expand All @@ -27,4 +29,5 @@ export * from "./values/Duration.js";
export * from "./values/Metadata.js";
export * from "./values/Primitive.js";
export * from "./values/Timeout.js";
export * from "./values/ValueDB.js";
export type * from "./values/_Types.js";
1 change: 1 addition & 0 deletions packages/core/src/index_safe.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,4 +26,5 @@ export * from "./values/Duration.js";
export * from "./values/Metadata.js";
export * from "./values/Primitive.js";
export * from "./values/Timeout.js";
export * from "./values/ValueDB.js";
export * from "./values/_Types.js";
79 changes: 9 additions & 70 deletions packages/core/src/security/Manager2.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,78 +27,17 @@ import { encryptAES128ECBAsync } from "../index_browser.js";
import { deflateSync } from "../util/compression.js";
import { highResTimestamp } from "../util/date.js";
import { encodeBitMask } from "../values/Primitive.js";
import {
MPANState,
type MPANTableEntry,
type MulticastGroup,
type NetworkKeys,
SPANState,
type SPANTableEntry,
type TempNetworkKeys,
} from "./Manager2Types.js";
import { CtrDRBG } from "./ctr_drbg.wrapper.js";

interface NetworkKeys {
pnk: Uint8Array;
keyCCM: Uint8Array;
keyMPAN: Uint8Array;
personalizationString: Uint8Array;
}

interface TempNetworkKeys {
keyCCM: Uint8Array;
personalizationString: Uint8Array;
}

export enum SPANState {
/** No entry exists */
None = 0,
/* The other node's receiver's entropy input is known but, but we didn't send it our sender's EI yet */
RemoteEI,
/* We've sent the other node our receiver's entropy input, but we didn't receive its sender's EI yet */
LocalEI,
/* An SPAN with the other node has been established */
SPAN,
}

export enum MPANState {
/** No entry exists */
None = 0,
/** The group is in use, but no MPAN was received yet, or it is out of sync */
OutOfSync,
/** An MPAN has been established */
MPAN,
}

export type SPANTableEntry =
| {
// We know the other node's receiver's entropy input, but we didn't send it our sender's EI yet
type: SPANState.RemoteEI;
receiverEI: Uint8Array;
}
| {
// We've sent the other node our receiver's entropy input, but we didn't receive its sender's EI yet
type: SPANState.LocalEI;
receiverEI: Uint8Array;
}
| {
// We've established an SPAN with the other node
type: SPANState.SPAN;
securityClass: SecurityClass;
rng: CtrDRBG;
/** The most recent generated SPAN */
currentSPAN?: {
nonce: Uint8Array;
expires: number;
};
};

export type MPANTableEntry =
| {
type: MPANState.OutOfSync;
}
| {
type: MPANState.MPAN;
currentMPAN: Uint8Array;
};

export interface MulticastGroup {
nodeIDs: readonly number[];
securityClass: S2SecurityClass;
sequenceNumber: number;
}

// How many sequence numbers are remembered for each node when checking for duplicates
const SINGLECAST_MAX_SEQ_NUMS = 1; // more than 1 will confuse the certification test tool :(
// How long a singlecast nonce used for encryption will be kept around to attempt decryption of in-flight messages
Expand Down
74 changes: 74 additions & 0 deletions packages/core/src/security/Manager2Types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
import {
type S2SecurityClass,
type SecurityClass,
} from "../definitions/SecurityClass.js";
import { type CtrDRBG } from "./ctr_drbg.wrapper.js";

export interface NetworkKeys {
pnk: Uint8Array;
keyCCM: Uint8Array;
keyMPAN: Uint8Array;
personalizationString: Uint8Array;
}
export interface TempNetworkKeys {
keyCCM: Uint8Array;
personalizationString: Uint8Array;
}

export enum SPANState {
/** No entry exists */
None = 0,
/* The other node's receiver's entropy input is known but, but we didn't send it our sender's EI yet */
RemoteEI,
/* We've sent the other node our receiver's entropy input, but we didn't receive its sender's EI yet */
LocalEI,
/* An SPAN with the other node has been established */
SPAN,
}

export enum MPANState {
/** No entry exists */
None = 0,
/** The group is in use, but no MPAN was received yet, or it is out of sync */
OutOfSync,
/** An MPAN has been established */
MPAN,
}

export type SPANTableEntry =
| {
// We know the other node's receiver's entropy input, but we didn't send it our sender's EI yet
type: SPANState.RemoteEI;
receiverEI: Uint8Array;
}
| {
// We've sent the other node our receiver's entropy input, but we didn't receive its sender's EI yet
type: SPANState.LocalEI;
receiverEI: Uint8Array;
}
| {
// We've established an SPAN with the other node
type: SPANState.SPAN;
securityClass: SecurityClass;
rng: CtrDRBG;
/** The most recent generated SPAN */
currentSPAN?: {
nonce: Uint8Array;
expires: number;
};
};

export type MPANTableEntry =
| {
type: MPANState.OutOfSync;
}
| {
type: MPANState.MPAN;
currentMPAN: Uint8Array;
};

export interface MulticastGroup {
nodeIDs: readonly number[];
securityClass: S2SecurityClass;
sequenceNumber: number;
}
2 changes: 1 addition & 1 deletion packages/core/src/util/compareVersions.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { padVersion } from "@zwave-js/shared";
import { padVersion } from "@zwave-js/shared/safe";
import semverGt from "semver/functions/gt.js";
import semverGte from "semver/functions/gte.js";
import semverLt from "semver/functions/lt.js";
Expand Down
10 changes: 8 additions & 2 deletions packages/core/src/util/date.ts
Original file line number Diff line number Diff line change
Expand Up @@ -104,8 +104,14 @@ export function getDSTInfo(now: Date = new Date()): DSTInfo {

/** Returns a timestamp with nano-second precision */
export function highResTimestamp(): number {
const [s, ns] = process.hrtime();
return s * 1e9 + ns;
if (process != undefined) {
const [s, ns] = process.hrtime();
return s * 1e9 + ns;
} else if (performance != undefined) {
return performance.now() * 1e6;
} else {
throw new Error("No high-resolution timer available");
}
}

export const timespan = Object.freeze({
Expand Down
3 changes: 1 addition & 2 deletions packages/core/src/util/firmware.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { getErrorMessage, isUint8Array } from "@zwave-js/shared";
import { Bytes } from "@zwave-js/shared/safe";
import { Bytes, getErrorMessage, isUint8Array } from "@zwave-js/shared/safe";
import { unzipSync } from "fflate";
import { decryptAES256CBC as decryptAES256CBCAsync } from "../crypto/operations.async.js";
import { decryptAES256CBC as decryptAES256CBCSync } from "../crypto/operations.sync.js";
Expand Down
2 changes: 1 addition & 1 deletion packages/core/src/values/ValueDB.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { TypedEventTarget } from "@zwave-js/shared";
import { type Database } from "@zwave-js/shared/bindings";
import { TypedEventTarget } from "@zwave-js/shared/safe";
import type { CommandClasses } from "../definitions/CommandClasses.js";
import {
ZWaveError,
Expand Down
Loading

0 comments on commit b5919c7

Please sign in to comment.