@mintlify/cli 4.0.1094 → 4.0.1096
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/__test__/analytics/format.test.ts +3 -0
- package/__test__/workflow.test.ts +2 -0
- package/bin/helpers.js +3 -0
- package/bin/init.js +5 -7
- package/bin/login.js +6 -1
- package/bin/telemetry/middleware.js +3 -1
- package/bin/telemetry/track.js +30 -2
- package/bin/tsconfig.build.tsbuildinfo +1 -1
- package/bin/workflow.js +2 -5
- package/package.json +2 -2
- package/src/helpers.tsx +6 -0
- package/src/init.tsx +6 -8
- package/src/login.tsx +7 -5
- package/src/telemetry/middleware.ts +3 -1
- package/src/telemetry/track.ts +35 -2
- package/src/workflow.tsx +2 -6
|
@@ -93,9 +93,12 @@ describe('resolveFormat', () => {
|
|
|
93
93
|
});
|
|
94
94
|
|
|
95
95
|
it('returns specified format', () => {
|
|
96
|
+
const prev = process.env.CLAUDECODE;
|
|
97
|
+
delete process.env.CLAUDECODE;
|
|
96
98
|
expect(resolveFormat({ format: 'plain' })).toBe('plain');
|
|
97
99
|
expect(resolveFormat({ format: 'json' })).toBe('json');
|
|
98
100
|
expect(resolveFormat({ format: 'graph' })).toBe('graph');
|
|
101
|
+
process.env.CLAUDECODE = prev;
|
|
99
102
|
});
|
|
100
103
|
|
|
101
104
|
it('defaults to plain', () => {
|
|
@@ -29,6 +29,8 @@ vi.mock('fs-extra', () => ({
|
|
|
29
29
|
|
|
30
30
|
vi.mock('../src/helpers.js', () => ({
|
|
31
31
|
CMD_EXEC_PATH: '/fake/project',
|
|
32
|
+
isAI: () =>
|
|
33
|
+
!process.stdin.isTTY || process.env.CLAUDECODE === '1' || process.env.TERM_PROGRAM === 'claude',
|
|
32
34
|
}));
|
|
33
35
|
|
|
34
36
|
const addLogSpy = vi.mocked(previewing.addLog);
|
package/bin/helpers.js
CHANGED
|
@@ -174,6 +174,9 @@ export const terminate = (code) => __awaiter(void 0, void 0, void 0, function* (
|
|
|
174
174
|
process.exit(code);
|
|
175
175
|
});
|
|
176
176
|
export const execAsync = promisify(exec);
|
|
177
|
+
export function isAI() {
|
|
178
|
+
return (!process.stdin.isTTY || process.env.CLAUDECODE === '1' || process.env.TERM_PROGRAM === 'claude');
|
|
179
|
+
}
|
|
177
180
|
export const detectPackageManager = (_a) => __awaiter(void 0, [_a], void 0, function* ({ packageName }) {
|
|
178
181
|
try {
|
|
179
182
|
const { stdout: packagePath } = yield execAsync(`which ${packageName}`);
|
package/bin/init.js
CHANGED
|
@@ -14,6 +14,7 @@ import { docsConfigSchema, validatePathWithinCwd } from '@mintlify/validation';
|
|
|
14
14
|
import AdmZip from 'adm-zip';
|
|
15
15
|
import fse from 'fs-extra';
|
|
16
16
|
import { Box, Text } from 'ink';
|
|
17
|
+
import { isAI } from './helpers.js';
|
|
17
18
|
const sendOnboardingMessage = (installDir) => {
|
|
18
19
|
addLogs(_jsx(Text, { bold: true, children: "Documentation Setup!" }), _jsx(Text, { children: "To see your docs run" }), _jsxs(Box, { children: [_jsx(Text, { color: "blue", children: "cd" }), _jsxs(Text, { children: [" ", installDir] })] }), _jsx(Text, { color: "blue", children: "mint dev" }));
|
|
19
20
|
};
|
|
@@ -24,9 +25,6 @@ export function init(installDir, force, theme, name) {
|
|
|
24
25
|
return __awaiter(this, void 0, void 0, function* () {
|
|
25
26
|
// Validate path is within current working directory to prevent path traversal
|
|
26
27
|
validatePathWithinCwd(installDir);
|
|
27
|
-
const isInteractive = process.stdin.isTTY;
|
|
28
|
-
const isClaudeCode = process.env.CLAUDECODE === '1';
|
|
29
|
-
const isAI = !isInteractive || isClaudeCode;
|
|
30
28
|
let selectedTheme = theme;
|
|
31
29
|
let projectName = name;
|
|
32
30
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
@@ -35,15 +33,15 @@ export function init(installDir, force, theme, name) {
|
|
|
35
33
|
});
|
|
36
34
|
const dirContents = yield fse.readdir(installDir).catch(() => []);
|
|
37
35
|
const contentsOccupied = dirContents.length > 0;
|
|
38
|
-
if ((!theme || !name) && isAI) {
|
|
36
|
+
if ((!theme || !name) && isAI()) {
|
|
39
37
|
sendUsageMessageForAI(installDir, contentsOccupied, themes);
|
|
40
38
|
return;
|
|
41
39
|
}
|
|
42
|
-
if (contentsOccupied && isAI && !force) {
|
|
40
|
+
if (contentsOccupied && isAI() && !force) {
|
|
43
41
|
sendUsageMessageForAI(installDir, contentsOccupied, themes);
|
|
44
42
|
return;
|
|
45
43
|
}
|
|
46
|
-
if (contentsOccupied && !isAI) {
|
|
44
|
+
if (contentsOccupied && !isAI()) {
|
|
47
45
|
const choice = yield select({
|
|
48
46
|
message: `Directory ${installDir} is not empty. What would you like to do?`,
|
|
49
47
|
choices: [
|
|
@@ -68,7 +66,7 @@ export function init(installDir, force, theme, name) {
|
|
|
68
66
|
validatePathWithinCwd(installDir, process.cwd());
|
|
69
67
|
}
|
|
70
68
|
}
|
|
71
|
-
if (!isAI && (!selectedTheme || !projectName)) {
|
|
69
|
+
if (!isAI() && (!selectedTheme || !projectName)) {
|
|
72
70
|
const defaultProject = projectName !== undefined ? projectName : installDir === '.' ? 'Mintlify' : installDir;
|
|
73
71
|
if (!projectName) {
|
|
74
72
|
projectName = yield input({
|
package/bin/login.js
CHANGED
|
@@ -17,6 +17,7 @@ import { calculatePKCECodeChallenge, randomNonce, randomPKCECodeVerifier, random
|
|
|
17
17
|
import { startCallbackServer } from './callbackServer.js';
|
|
18
18
|
import { DASHBOARD_URL, STYTCH_CLIENT_ID, TOKEN_ENDPOINT } from './constants.js';
|
|
19
19
|
import { storeCredentials } from './keyring.js';
|
|
20
|
+
import { trackLoginAttempt, trackLoginFailed, trackLoginSuccess } from './telemetry/track.js';
|
|
20
21
|
export function login() {
|
|
21
22
|
return __awaiter(this, void 0, void 0, function* () {
|
|
22
23
|
var _a, _b;
|
|
@@ -29,6 +30,7 @@ export function login() {
|
|
|
29
30
|
authorizeUrl.searchParams.set('state', state);
|
|
30
31
|
authorizeUrl.searchParams.set('code_challenge', codeChallenge);
|
|
31
32
|
const url = authorizeUrl.toString();
|
|
33
|
+
void trackLoginAttempt();
|
|
32
34
|
const { codePromise, close: closeServer } = yield startCallbackServer();
|
|
33
35
|
addLog(_jsxs(Box, { flexDirection: "column", gap: 1, paddingY: 1, children: [_jsxs(Text, { bold: true, children: [_jsx(Text, { color: "green", children: "\u25C6 " }), "A browser window will open for Mintlify authentication"] }), _jsxs(Box, { flexDirection: "column", paddingLeft: 3, gap: 1, children: [_jsx(Text, { dimColor: true, children: "If your browser doesn't open automatically, copy this URL:" }), _jsx(Text, { color: "cyan", children: url })] })] }));
|
|
34
36
|
open(url).catch(() => { });
|
|
@@ -69,11 +71,14 @@ export function login() {
|
|
|
69
71
|
});
|
|
70
72
|
const body = yield res.json().catch(() => ({}));
|
|
71
73
|
if (!res.ok) {
|
|
72
|
-
|
|
74
|
+
const reason = (_b = (_a = body.error_message) !== null && _a !== void 0 ? _a : body.error) !== null && _b !== void 0 ? _b : 'unknown error';
|
|
75
|
+
void trackLoginFailed(reason);
|
|
76
|
+
addLog(_jsxs(Text, { color: "red", children: ["\u2716 Login failed: ", reason] }));
|
|
73
77
|
return;
|
|
74
78
|
}
|
|
75
79
|
const token = body;
|
|
76
80
|
yield storeCredentials(token.access_token, token.refresh_token);
|
|
81
|
+
void trackLoginSuccess();
|
|
77
82
|
addLog(_jsx(Text, { color: "green", children: "\u2714 Logged in successfully." }));
|
|
78
83
|
});
|
|
79
84
|
}
|
|
@@ -7,6 +7,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
7
7
|
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
8
|
});
|
|
9
9
|
};
|
|
10
|
+
import { getConfigValue } from '../config.js';
|
|
10
11
|
import { getVersions } from '../helpers.js';
|
|
11
12
|
import { trackCommand } from './track.js';
|
|
12
13
|
const SCRAPE_SUBCOMMANDS = new Set(['page', 'site', 'openapi']);
|
|
@@ -32,7 +33,8 @@ export function createTelemetryMiddleware() {
|
|
|
32
33
|
tracked = true;
|
|
33
34
|
const sanitizedCommand = getSanitizedCommandForTelemetry(argv._);
|
|
34
35
|
const { cli: cliVersion } = getVersions();
|
|
35
|
-
|
|
36
|
+
const subdomain = getConfigValue('subdomain');
|
|
37
|
+
void trackCommand({ command: sanitizedCommand, cliVersion, subdomain });
|
|
36
38
|
}
|
|
37
39
|
});
|
|
38
40
|
};
|
package/bin/telemetry/track.js
CHANGED
|
@@ -10,7 +10,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
10
10
|
import os from 'os';
|
|
11
11
|
import { isTelemetryEnabled } from '../config.js';
|
|
12
12
|
import { TELEMETRY_ASYNC_TIMEOUT_MS } from '../constants.js';
|
|
13
|
-
import { getVersions } from '../helpers.js';
|
|
13
|
+
import { getVersions, isAI } from '../helpers.js';
|
|
14
14
|
import { getPostHogClient } from './client.js';
|
|
15
15
|
import { getDistinctId } from './distinctId.js';
|
|
16
16
|
function captureWithTimeout(event, properties) {
|
|
@@ -31,7 +31,7 @@ function captureWithTimeout(event, properties) {
|
|
|
31
31
|
});
|
|
32
32
|
}
|
|
33
33
|
export function trackCommand(_a) {
|
|
34
|
-
return __awaiter(this, arguments, void 0, function* ({ command, cliVersion }) {
|
|
34
|
+
return __awaiter(this, arguments, void 0, function* ({ command, cliVersion, subdomain, }) {
|
|
35
35
|
if (!isTelemetryEnabled())
|
|
36
36
|
return;
|
|
37
37
|
try {
|
|
@@ -41,11 +41,39 @@ export function trackCommand(_a) {
|
|
|
41
41
|
os: os.platform(),
|
|
42
42
|
arch: os.arch(),
|
|
43
43
|
node_version: process.version,
|
|
44
|
+
is_ai_agent: isAI(),
|
|
45
|
+
subdomain,
|
|
44
46
|
});
|
|
45
47
|
}
|
|
46
48
|
catch (_b) { }
|
|
47
49
|
});
|
|
48
50
|
}
|
|
51
|
+
function trackLoginEvent(event, extra) {
|
|
52
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
53
|
+
if (!isTelemetryEnabled())
|
|
54
|
+
return;
|
|
55
|
+
try {
|
|
56
|
+
const { cli: cliVersion } = getVersions();
|
|
57
|
+
yield captureWithTimeout(event, Object.assign(Object.assign({}, extra), { cli_version: cliVersion, os: os.platform(), arch: os.arch(), node_version: process.version }));
|
|
58
|
+
}
|
|
59
|
+
catch (_a) { }
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
export function trackLoginAttempt() {
|
|
63
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
64
|
+
return trackLoginEvent('cli.login.attempted');
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
export function trackLoginSuccess() {
|
|
68
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
69
|
+
return trackLoginEvent('cli.login.succeeded');
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
export function trackLoginFailed(reason) {
|
|
73
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
74
|
+
return trackLoginEvent('cli.login.failed', { reason });
|
|
75
|
+
});
|
|
76
|
+
}
|
|
49
77
|
export function trackTelemetryPreferenceChange(options) {
|
|
50
78
|
return __awaiter(this, void 0, void 0, function* () {
|
|
51
79
|
if (process.env.CLI_TEST_MODE === 'true')
|