Skip to content

Commit 7f18183

Browse files
feat(unenv-preset): add native node:tty module support (#12023)
1 parent c58e81b commit 7f18183

File tree

6 files changed

+95
-61
lines changed

6 files changed

+95
-61
lines changed

.changeset/native-node-tty.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
---
2+
"@cloudflare/unenv-preset": minor
3+
---
4+
5+
Add support for native `node:tty` module from workerd when the `enable_nodejs_tty_module` compatibility flag is enabled.
6+
7+
This feature is currently experimental and requires `nodejs_compat`, `experimental`, and `enable_nodejs_tty_module` compatibility flags to be set.

packages/unenv-preset/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@
4949
},
5050
"peerDependencies": {
5151
"unenv": "2.0.0-rc.24",
52-
"workerd": "^1.20260115.0"
52+
"workerd": "^1.20260213.0"
5353
},
5454
"peerDependenciesMeta": {
5555
"workerd": {

packages/unenv-preset/src/preset.ts

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,7 @@ export function getCloudflarePreset({
8181
const replOverrides = getReplOverrides(compat);
8282
const processOverrides = getProcessOverrides(compat);
8383
const v8Overrides = getV8Overrides(compat);
84+
const ttyOverrides = getTtyOverrides(compat);
8485

8586
// "dynamic" as they depend on the compatibility date and flags
8687
const dynamicNativeModules = [
@@ -103,6 +104,7 @@ export function getCloudflarePreset({
103104
...replOverrides.nativeModules,
104105
...processOverrides.nativeModules,
105106
...v8Overrides.nativeModules,
107+
...ttyOverrides.nativeModules,
106108
];
107109

108110
// "dynamic" as they depend on the compatibility date and flags
@@ -125,6 +127,7 @@ export function getCloudflarePreset({
125127
...replOverrides.hybridModules,
126128
...processOverrides.hybridModules,
127129
...v8Overrides.hybridModules,
130+
...ttyOverrides.hybridModules,
128131
];
129132

130133
return {
@@ -939,3 +942,39 @@ function getV8Overrides({
939942
hybridModules: [],
940943
};
941944
}
945+
946+
/**
947+
* Returns the overrides for `node:tty` (unenv or workerd)
948+
*
949+
* The native tty implementation:
950+
* - is experimental and has no default enable date
951+
* - can be enabled with the "enable_nodejs_tty_module" flag
952+
* - can be disabled with the "disable_nodejs_tty_module" flag
953+
*/
954+
function getTtyOverrides({
955+
compatibilityFlags,
956+
}: {
957+
compatibilityDate: string;
958+
compatibilityFlags: string[];
959+
}): { nativeModules: string[]; hybridModules: string[] } {
960+
const disabledByFlag = compatibilityFlags.includes(
961+
"disable_nodejs_tty_module"
962+
);
963+
964+
const enabledByFlag =
965+
compatibilityFlags.includes("enable_nodejs_tty_module") &&
966+
compatibilityFlags.includes("experimental");
967+
968+
const enabled = enabledByFlag && !disabledByFlag;
969+
970+
// When enabled, use the native `tty` module from workerd
971+
return enabled
972+
? {
973+
nativeModules: ["tty"],
974+
hybridModules: [],
975+
}
976+
: {
977+
nativeModules: [],
978+
hybridModules: [],
979+
};
980+
}

packages/wrangler/e2e/unenv-preset/preset.test.ts

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -655,6 +655,27 @@ const localTestConfigs: TestConfig[] = [
655655
},
656656
},
657657
],
658+
// node:tty (experimental, no default enable date)
659+
[
660+
// TODO: add test for disabled by date (no date defined yet)
661+
// TODO: add test for enabled by date (no date defined yet)
662+
{
663+
name: "tty enabled by flag",
664+
compatibilityDate: "2024-09-23",
665+
compatibilityFlags: ["enable_nodejs_tty_module", "experimental"],
666+
expectRuntimeFlags: {
667+
enable_nodejs_tty_module: true,
668+
},
669+
},
670+
{
671+
name: "tty disabled by flag",
672+
compatibilityDate: "2024-09-23",
673+
compatibilityFlags: ["disable_nodejs_tty_module", "experimental"],
674+
expectRuntimeFlags: {
675+
enable_nodejs_tty_module: false,
676+
},
677+
},
678+
],
658679
].flat() as TestConfig[];
659680

660681
describe.each(localTestConfigs)(

packages/wrangler/e2e/unenv-preset/worker/index.ts

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -888,6 +888,31 @@ export const WorkerdTests: Record<string, () => void> = {
888888
});
889889
}
890890
},
891+
892+
async testTty() {
893+
const tty = await import("node:tty");
894+
895+
// Common exports (both unenv stub and native workerd)
896+
assertTypeOfProperties(tty, {
897+
isatty: "function",
898+
ReadStream: "function",
899+
WriteStream: "function",
900+
});
901+
902+
assertTypeOfProperties(tty.default, {
903+
isatty: "function",
904+
ReadStream: "function",
905+
WriteStream: "function",
906+
});
907+
908+
// isatty should return false (both unenv and workerd)
909+
assert.strictEqual(tty.isatty(0), false);
910+
assert.strictEqual(tty.isatty(1), false);
911+
assert.strictEqual(tty.isatty(2), false);
912+
913+
assert.doesNotThrow(() => new tty.ReadStream(0));
914+
assert.doesNotThrow(() => new tty.WriteStream(1));
915+
},
891916
};
892917

893918
/**

pnpm-lock.yaml

Lines changed: 2 additions & 60 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)