An ES module TypeScript consumer was given the CommonJS declarations in dist/types. With those,
`import alex2node from "alex2node"` compiled (module Node16) and then failed when Node loaded it: "The requested
module 'alex2node' does not provide an export named 'default'". The ES module build has named exports only.
tsconfig.esm.json now emits declarations next to dist/esm/*.js, under that directory's {"type": "module"}, and
"exports" selects per condition: import -> dist/esm/index.d.ts, require -> dist/types/index.d.ts. The default
import is now refused with TS1192; named imports are unchanged. "main", "module" and "types" are as before.
test/fixtures/types.mts holds the default import under @ts-expect-error, and a new test requires "types" before
"default" and a declaration for every built file. dist/: 25 files, 132,291 B -> 33 files, 155,647 B; the npm
tarball 25,125 B -> 25,837 B. npm test: 25 pass in 5.6 s.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@types/node was not declared. It was installed only because mqtt's @types/readable-stream and @types/ws depend on
"@types/node": "*", and it resolved to 26.6.2, so an API newer than the "engines" floor passed the type check and
the build depended on another package's dependency list.
@types/node ^18.19.130 is now a devDependency (undici-types follows, 8.9.0 -> 5.26.5). A call to
process.loadEnvFile() (Node 20.12) in src/ now fails with TS2339. npm run check passes, the fixture compile with
skipLibCheck off included, so mqtt's declarations hold against the Node 18 types.
First run on the floor: npm test passes 24/24 on Node 18.20.8 and 20.20.2 as well as 24.21.0. No change to src/ or
dist/.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Step 2 replaced uuid by crypto.randomUUID() at three call sites (AlexaStatusMessage, AlexaErrorResponse,
Device.sendSceneResponse) and only the first was asserted, in the ES module test. With the messageId dropped or set
to a constant in the other two, the suite still passed 22/22, and no test read an ErrorResponse at all.
New: an ErrorResponse compared whole against the documented shape (header, endpoint, payload, no context), and one
test that sends two directives each to a light, an unreachable light and a scene and requires six different
version 4 UUIDs. The Response, StateReport, scene and change report tests check the messageId too; the pattern
lives in the harness.
Checked in a scratch copy: a missing or constant messageId at each of the three sites now fails the suite (the
missing one in AlexaStatusMessage does not compile). No change to src/ or dist/. npm test: 24 pass in 5.5 s.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
"exports" gains "import" and "types" next to "require": import "alex2node" failed with
ERR_PACKAGE_PATH_NOT_EXPORTED. scripts/build.mjs compiles src/ to dist/cjs, dist/esm and dist/types in a staging
directory and swaps them in only when both compiler runs passed. "main" and "types" follow for resolvers that do
not read "exports". Target ES6 -> ES2020, "engines": node >= 18, relative imports carry ".js" for Node's ESM loader.
uuid gives way to crypto.randomUUID(); mqtt is the only runtime dependency left.
Tests load the package by name. New: both entry points, the modules the builds import, dist/ equal to a fresh
build, a round trip on the ES module build, and two compiled type fixtures in place of the .d.ts regexes.
22 tests pass in 5.7 s. dist/: 16 files, 79,711 B -> 25 files, 132,291 B; the npm tarball is 25,125 B.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
test/helpers/harness.js holds the aedes broker, the Alexa-side watcher, until() and the cleanups, plus directive(),
connected() and setup(), which the old file spelled out in each test. test/alex2node.test.js (194 lines, 8 tests)
becomes connection, discovery, directives, change-report and typings.
The 50-line round-trip test is cut at its topic boundaries and the duplicate-endpointId test no longer carries the
thermostat discovery check, so a failure names a case: 8 tests become 15, every 1.5.2 assertion kept. Four checks
are stricter: the "directive" event is compared whole, the StateReport is checked for its token and properties, the
Celsius conversion covers lowerSetpoint as well as temperature, and a duplicate endpointId is listed once.
No change to src/ or dist/. npm test: 15 pass in 0.9 s.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>