Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 13 additions & 3 deletions index.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,22 @@
*
* @module @cldmv/node-android-tv-remote/cjs
*/
"use strict";

const { createRequire } = require("module");
const requireESM = createRequire(__filename);
// index.cjs is a thin wrapper: it loads index.mjs through Node's synchronous require(esm).
// Node.js versions without require(esm) would fail with a bare ERR_REQUIRE_ESM, so fail
// early with a message that says what to do instead.
if (!process.features?.require_module) {
const error = new Error(
`@cldmv/node-android-tv-remote: require() needs Node.js ^20.19.0 or >=22.12.0 (this is ${process.version}). On older Node.js, load the package with import() instead.`
);
error.code = "ERR_REQUIRE_ESM";
throw error;
}

const { default: createRemote } = requireESM("./index.mjs");
const { default: createRemote, createAndroidTVRemote } = require("./index.mjs");

module.exports = createRemote;
module.exports.createRemote = createRemote;
module.exports.createAndroidTVRemote = createAndroidTVRemote;
module.exports.default = createRemote;
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 4 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@cldmv/node-android-tv-remote",
"version": "2.1.6",
"version": "2.1.7",
"description": "A Node.js library for controlling Android TV devices via ADB keycodes and text input.",
"type": "module",
"exports": {
Expand All @@ -14,9 +14,10 @@
"setup-device": "node scripts/setup-device.mjs",
"build": "echo 'βœ“ no build step'",
"build:ci": "echo 'βœ“ no build step'",
"test": "node tests/run-vitest.mjs",
"test": "node tests/run-vitest.mjs && npm run test:cjs",
"test:cjs": "node --test tests/cjs/entry.test.cjs",
"test:watch": "vitest --config .configs/vitest.config.mjs",
"coverage": "node tests/run-vitest.mjs --coverage-quiet",
"coverage": "node tests/run-vitest.mjs --coverage-quiet && npm run test:cjs",
"ci:coverage": "npm run coverage",
"lint": "eslint --config eslint.config.mjs .",
"lint:fix": "eslint --config eslint.config.mjs . --fix",
Expand Down
56 changes: 56 additions & 0 deletions tests/cjs/entry.test.cjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
/**
*
* @Project: @cldmv/node-android-tv-remote
* @Filename: /tests/cjs/entry.test.cjs
* @Date: 2026-10-03T00:00:00-07:00 (1791010800)
* @Author: Nate Corcoran <CLDMV>
* @Email: <Shinrai@users.noreply.github.com>
* -----
* @Last modified by: Nate Corcoran <CLDMV> (Shinrai@users.noreply.github.com)
* @Last modified time: 2026-10-03T10:37:08-07:00 (1791049028)
* -----
* @Copyright: Copyright (c) 2013-2026 Catalyzed Motivation Inc. All rights reserved.
*
*/

/**
* CommonJS entry tests. These run under Node's own test runner (`node --test`), not Vitest:
* Vitest loads files through its own module runner, so it cannot show whether a plain
* `require()` of the package works the way it does for a CommonJS consumer.
*/
"use strict";

const { test } = require("node:test");
const assert = require("node:assert/strict");
const { spawnSync } = require("node:child_process");
const path = require("node:path");

const repoRoot = path.resolve(__dirname, "../..");

test("require() returns the same createRemote object as import", async () => {
const createRemote = require("../../index.cjs");
const esm = await import("../../index.mjs");

// createRemote opens an ADB connection when called, so only identity/type is
// checked here - no sockets are opened in this test.
assert.equal(typeof createRemote, "function");
assert.equal(createRemote, esm.default);
assert.equal(createRemote.createRemote, esm.default);
assert.equal(createRemote.default, esm.default);
assert.equal(typeof createRemote.createAndroidTVRemote, "function");
assert.equal(createRemote.createAndroidTVRemote, esm.createAndroidTVRemote);
});

test("require() fails with a clear message where Node.js has no require(esm)", () => {
// --no-experimental-require-module turns require(esm) off, which is what Node.js
// versions before 20.19 / 22.12 look like to the entry.
const res = spawnSync(process.execPath, ["--no-experimental-require-module", "-e", "require('./index.cjs')"], {
cwd: repoRoot,
encoding: "utf8"
});

assert.notEqual(res.status, 0);
assert.match(res.stderr, /ERR_REQUIRE_ESM/);
assert.match(res.stderr, /require\(\) needs Node\.js \^20\.19\.0 or >=22\.12\.0/);
assert.match(res.stderr, /import\(\)/);
});
Loading