Skip to content

Commit 801532b

Browse files
Copilotmrlubos
andcommitted
Move TTY detection logic to src with environment variable support
Co-authored-by: mrlubos <[email protected]>
1 parent 769269f commit 801532b

File tree

2 files changed

+129
-4
lines changed

2 files changed

+129
-4
lines changed

packages/openapi-ts/src/__tests__/interactive.test.ts

Lines changed: 109 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,16 @@
1-
import { describe, expect, it } from 'vitest';
1+
import { afterEach, describe, expect, it } from 'vitest';
22

3-
import { initConfigs } from '../config/init';
3+
import { detectInteractiveSession, initConfigs } from '../config/init';
44
import { mergeConfigs } from '../config/merge';
55

66
describe('interactive config', () => {
7-
it('should default to false when not provided', async () => {
7+
it('should use detectInteractiveSession when not provided', async () => {
88
const result = await initConfigs({
99
input: 'test.json',
1010
output: './test',
1111
});
1212

13+
// In test environment, TTY is typically not available, so it should be false
1314
expect(result.results[0].config.interactive).toBe(false);
1415
});
1516

@@ -67,3 +68,108 @@ describe('interactive config', () => {
6768
expect(mergedWithBug.interactive).toBe(true); // This was the bug - it overrode the file config
6869
});
6970
});
71+
72+
describe('detectInteractiveSession', () => {
73+
const originalEnv = process.env;
74+
const originalStdin = process.stdin;
75+
const originalStdout = process.stdout;
76+
77+
afterEach(() => {
78+
process.env = originalEnv;
79+
Object.defineProperty(process, 'stdin', { value: originalStdin });
80+
Object.defineProperty(process, 'stdout', { value: originalStdout });
81+
});
82+
83+
it('should return false when CI environment variable is set', () => {
84+
process.env = { ...originalEnv, CI: 'true' };
85+
Object.defineProperty(process.stdin, 'isTTY', {
86+
configurable: true,
87+
value: true,
88+
});
89+
Object.defineProperty(process.stdout, 'isTTY', {
90+
configurable: true,
91+
value: true,
92+
});
93+
94+
expect(detectInteractiveSession()).toBe(false);
95+
});
96+
97+
it('should return false when NO_INTERACTIVE environment variable is set', () => {
98+
process.env = { ...originalEnv, NO_INTERACTIVE: '1' };
99+
Object.defineProperty(process.stdin, 'isTTY', {
100+
configurable: true,
101+
value: true,
102+
});
103+
Object.defineProperty(process.stdout, 'isTTY', {
104+
configurable: true,
105+
value: true,
106+
});
107+
108+
expect(detectInteractiveSession()).toBe(false);
109+
});
110+
111+
it('should return false when NO_INTERACTION environment variable is set', () => {
112+
process.env = { ...originalEnv, NO_INTERACTION: '1' };
113+
Object.defineProperty(process.stdin, 'isTTY', {
114+
configurable: true,
115+
value: true,
116+
});
117+
Object.defineProperty(process.stdout, 'isTTY', {
118+
configurable: true,
119+
value: true,
120+
});
121+
122+
expect(detectInteractiveSession()).toBe(false);
123+
});
124+
125+
it('should return false when stdin is not TTY', () => {
126+
process.env = { ...originalEnv };
127+
delete process.env.CI;
128+
delete process.env.NO_INTERACTIVE;
129+
delete process.env.NO_INTERACTION;
130+
Object.defineProperty(process.stdin, 'isTTY', {
131+
configurable: true,
132+
value: false,
133+
});
134+
Object.defineProperty(process.stdout, 'isTTY', {
135+
configurable: true,
136+
value: true,
137+
});
138+
139+
expect(detectInteractiveSession()).toBe(false);
140+
});
141+
142+
it('should return false when stdout is not TTY', () => {
143+
process.env = { ...originalEnv };
144+
delete process.env.CI;
145+
delete process.env.NO_INTERACTIVE;
146+
delete process.env.NO_INTERACTION;
147+
Object.defineProperty(process.stdin, 'isTTY', {
148+
configurable: true,
149+
value: true,
150+
});
151+
Object.defineProperty(process.stdout, 'isTTY', {
152+
configurable: true,
153+
value: false,
154+
});
155+
156+
expect(detectInteractiveSession()).toBe(false);
157+
});
158+
159+
it('should return true when TTY is available and no blocking env vars are set', () => {
160+
process.env = { ...originalEnv };
161+
delete process.env.CI;
162+
delete process.env.NO_INTERACTIVE;
163+
delete process.env.NO_INTERACTION;
164+
Object.defineProperty(process.stdin, 'isTTY', {
165+
configurable: true,
166+
value: true,
167+
});
168+
Object.defineProperty(process.stdout, 'isTTY', {
169+
configurable: true,
170+
value: true,
171+
});
172+
173+
expect(detectInteractiveSession()).toBe(true);
174+
});
175+
});

packages/openapi-ts/src/config/init.ts

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,20 @@ import { getProjectDependencies } from './packages';
1313
import { getParser } from './parser';
1414
import { getPlugins } from './plugins';
1515

16+
/**
17+
* Detect if the current session is interactive based on TTY status and environment variables.
18+
* This is used as a fallback when the user doesn't explicitly set the interactive option.
19+
* @internal
20+
*/
21+
export const detectInteractiveSession = (): boolean =>
22+
!!(
23+
process.stdin.isTTY &&
24+
process.stdout.isTTY &&
25+
!process.env.CI &&
26+
!process.env.NO_INTERACTIVE &&
27+
!process.env.NO_INTERACTION
28+
);
29+
1630
/**
1731
* @internal
1832
*/
@@ -59,12 +73,17 @@ export const initConfigs = async (
5973
dryRun = false,
6074
experimentalParser = true,
6175
exportCore = true,
62-
interactive = false,
6376
name,
6477
request,
6578
useOptions = true,
6679
} = userConfig;
6780

81+
// Use environment-aware detection only when user doesn't explicitly set interactive
82+
const interactive =
83+
userConfig.interactive !== undefined
84+
? userConfig.interactive
85+
: detectInteractiveSession();
86+
6887
const errors: Array<Error> = [];
6988

7089
const logs = getLogs(userConfig);

0 commit comments

Comments
 (0)