react-doctor 0.9.7-dev.13138a4 → 0.9.7
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/dist/cli.js +10780 -96
- package/dist/{devtools-DPRVRu3S.js → devtools-BQATi33M.js} +3 -3
- package/dist/{record-metric-CtlQma6P.js → exit-gracefully-BJRsqdaK.js} +11954 -6251
- package/dist/index.d.ts +4082 -4704
- package/dist/index.js +4386 -6069
- package/dist/lsp.js +4510 -6181
- package/dist/{run-scan-app-Drlqxtzl.js → run-scan-app-DawD5rhU.js} +29 -36
- package/package.json +3 -2
- package/dist/build-section-divider-QykRnrlR.js +0 -312
- package/dist/ci-BvGqcDKc.js +0 -7501
- package/dist/design-SGX69YQq.js +0 -14
- package/dist/exit-gracefully-CddufLS0.js +0 -47
- package/dist/inspect-DBJtHure.js +0 -1443
- package/dist/install-doctor-script-DxrteuEw.js +0 -3251
- package/dist/install-ffJ108LC.js +0 -32
- package/dist/install-github-workflow-BP6t3YBA.js +0 -267
- package/dist/install-react-doctor-BhfvyNZB.js +0 -1154
- package/dist/print-branded-header-Cw5AlicW.js +0 -22
- package/dist/read-object-file-ITGVjFKp.js +0 -24
- package/dist/report-error-DUoFKR7d.js +0 -158
- package/dist/report-workflow-result-D3GCowCN.js +0 -279
- package/dist/resolve-scope-gy72JH3h.js +0 -339
- package/dist/rules-6-d19pN1.js +0 -581
- package/dist/scan-C3Io41Dq.js +0 -53
- package/dist/should-fail-scan-gate-DImKUuu-.js +0 -3075
- package/dist/should-skip-prompts-CbIIaU8b.js +0 -10
- package/dist/unref-stdin-B5RnVeLa.js +0 -120
- package/dist/version-BFKBxkKV.js +0 -21
- package/dist/why-DO4CTn-R.js +0 -21
package/dist/install-ffJ108LC.js
DELETED
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
|
|
2
|
-
!function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="da236116-fa98-5814-9d4e-dcc2503a7045")}catch(e){}}();
|
|
3
|
-
import { Yn as runSync, t as recordCount, y as METRIC } from "./record-metric-CtlQma6P.js";
|
|
4
|
-
import { o as isExpectedUserError } from "./unref-stdin-B5RnVeLa.js";
|
|
5
|
-
import { n as handleError, r as handleUserError, t as reportErrorToSentry } from "./report-error-DUoFKR7d.js";
|
|
6
|
-
import { t as printBrandedHeader } from "./print-branded-header-Cw5AlicW.js";
|
|
7
|
-
import { n as runInstallReactDoctor } from "./install-react-doctor-BhfvyNZB.js";
|
|
8
|
-
//#region src/cli/commands/install.ts
|
|
9
|
-
const installAction = async (options, command) => {
|
|
10
|
-
recordCount(METRIC.cliInvoked, 1, { command: "install" });
|
|
11
|
-
runSync(printBrandedHeader);
|
|
12
|
-
try {
|
|
13
|
-
const parentOptions = command?.parent?.opts?.();
|
|
14
|
-
await runInstallReactDoctor({
|
|
15
|
-
yes: options.yes ?? parentOptions?.yes,
|
|
16
|
-
dryRun: options.dryRun,
|
|
17
|
-
agentHooks: options.agentHooks,
|
|
18
|
-
projectRoot: options.cwd ?? process.cwd()
|
|
19
|
-
});
|
|
20
|
-
} catch (error) {
|
|
21
|
-
if (isExpectedUserError(error)) {
|
|
22
|
-
handleUserError(error);
|
|
23
|
-
return;
|
|
24
|
-
}
|
|
25
|
-
handleError(error, { sentryEventId: await reportErrorToSentry(error) });
|
|
26
|
-
}
|
|
27
|
-
};
|
|
28
|
-
//#endregion
|
|
29
|
-
export { installAction };
|
|
30
|
-
|
|
31
|
-
//# sourceMappingURL=install-ffJ108LC.js.map
|
|
32
|
-
//# debugId=da236116-fa98-5814-9d4e-dcc2503a7045
|
|
@@ -1,267 +0,0 @@
|
|
|
1
|
-
|
|
2
|
-
!function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="1f395a85-8fa9-5c73-af2c-14352d85877d")}catch(e){}}();
|
|
3
|
-
import { v as GH_DEFAULT_BRANCH_PROBE_TIMEOUT_MS } from "./record-metric-CtlQma6P.js";
|
|
4
|
-
import { t as unrefStdin } from "./unref-stdin-B5RnVeLa.js";
|
|
5
|
-
import { L as cliLogger } from "./install-doctor-script-DxrteuEw.js";
|
|
6
|
-
import { createRequire } from "node:module";
|
|
7
|
-
import { execFile } from "node:child_process";
|
|
8
|
-
import * as path$1 from "node:path";
|
|
9
|
-
import * as fs$1 from "node:fs";
|
|
10
|
-
import { promisify } from "node:util";
|
|
11
|
-
import basePrompts from "prompts";
|
|
12
|
-
//#region src/cli/utils/run-command.ts
|
|
13
|
-
const execFileAsync = promisify(execFile);
|
|
14
|
-
const runCommand = async (command, args, cwd, timeoutMs) => {
|
|
15
|
-
try {
|
|
16
|
-
const { stdout, stderr } = await execFileAsync(command, [...args], {
|
|
17
|
-
cwd,
|
|
18
|
-
encoding: "utf8",
|
|
19
|
-
timeout: timeoutMs
|
|
20
|
-
});
|
|
21
|
-
return {
|
|
22
|
-
success: true,
|
|
23
|
-
stdout: stdout.trim(),
|
|
24
|
-
stderr: stderr.trim()
|
|
25
|
-
};
|
|
26
|
-
} catch (error) {
|
|
27
|
-
const failure = error;
|
|
28
|
-
return {
|
|
29
|
-
success: false,
|
|
30
|
-
stdout: (failure.stdout ?? "").trim(),
|
|
31
|
-
stderr: (failure.stderr ?? "").trim()
|
|
32
|
-
};
|
|
33
|
-
}
|
|
34
|
-
};
|
|
35
|
-
//#endregion
|
|
36
|
-
//#region src/cli/utils/detect-default-branch.ts
|
|
37
|
-
const detectDefaultBranch = async (cwd, run = runCommand) => {
|
|
38
|
-
const repoView = await run("gh", [
|
|
39
|
-
"repo",
|
|
40
|
-
"view",
|
|
41
|
-
"--json",
|
|
42
|
-
"defaultBranchRef",
|
|
43
|
-
"--jq",
|
|
44
|
-
".defaultBranchRef.name"
|
|
45
|
-
], cwd, GH_DEFAULT_BRANCH_PROBE_TIMEOUT_MS);
|
|
46
|
-
if (repoView.success && repoView.stdout !== "" && repoView.stdout !== "null") return repoView.stdout;
|
|
47
|
-
const symRef = await run("git", ["symbolic-ref", "refs/remotes/origin/HEAD"], cwd);
|
|
48
|
-
if (symRef.success) {
|
|
49
|
-
const branchMatch = symRef.stdout.match(/refs\/remotes\/origin\/(.+)$/);
|
|
50
|
-
if (branchMatch) return branchMatch[1];
|
|
51
|
-
}
|
|
52
|
-
if ((await run("git", [
|
|
53
|
-
"rev-parse",
|
|
54
|
-
"--verify",
|
|
55
|
-
"origin/main"
|
|
56
|
-
], cwd)).success) return "main";
|
|
57
|
-
if ((await run("git", [
|
|
58
|
-
"rev-parse",
|
|
59
|
-
"--verify",
|
|
60
|
-
"origin/master"
|
|
61
|
-
], cwd)).success) return "master";
|
|
62
|
-
return null;
|
|
63
|
-
};
|
|
64
|
-
//#endregion
|
|
65
|
-
//#region src/cli/utils/is-command-available.ts
|
|
66
|
-
const isWindows = process.platform === "win32";
|
|
67
|
-
const candidateFileNames = (command) => {
|
|
68
|
-
if (!isWindows || path$1.extname(command)) return [command];
|
|
69
|
-
return [command, ...(process.env.PATHEXT ?? ".COM;.EXE;.BAT;.CMD").split(";").map((extension) => extension.trim()).filter(Boolean).map((extension) => `${command}${extension}`)];
|
|
70
|
-
};
|
|
71
|
-
const isCommandAvailable = (command) => {
|
|
72
|
-
const pathDirectories = (process.env.PATH ?? "").split(path$1.delimiter).filter(Boolean);
|
|
73
|
-
for (const directory of pathDirectories) for (const fileName of candidateFileNames(command)) {
|
|
74
|
-
const binaryPath = path$1.join(directory, fileName);
|
|
75
|
-
try {
|
|
76
|
-
if (!fs$1.statSync(binaryPath).isFile()) continue;
|
|
77
|
-
if (!isWindows) fs$1.accessSync(binaryPath, fs$1.constants.X_OK);
|
|
78
|
-
return true;
|
|
79
|
-
} catch {}
|
|
80
|
-
}
|
|
81
|
-
return false;
|
|
82
|
-
};
|
|
83
|
-
//#endregion
|
|
84
|
-
//#region src/cli/utils/should-auto-select-current-choice.ts
|
|
85
|
-
const shouldAutoSelectCurrentChoice = (choiceStates, cursor) => {
|
|
86
|
-
if (choiceStates.some((choiceState) => choiceState.selected)) return false;
|
|
87
|
-
const currentChoice = choiceStates[cursor];
|
|
88
|
-
return Boolean(currentChoice) && !currentChoice.disabled;
|
|
89
|
-
};
|
|
90
|
-
//#endregion
|
|
91
|
-
//#region src/cli/utils/should-select-all-choices.ts
|
|
92
|
-
const shouldSelectAllChoices = (choiceStates) => {
|
|
93
|
-
return choiceStates.filter((choiceState) => !choiceState.disabled).some((choiceState) => choiceState.selected !== true);
|
|
94
|
-
};
|
|
95
|
-
//#endregion
|
|
96
|
-
//#region src/cli/utils/prompts.ts
|
|
97
|
-
const require = createRequire(import.meta.url);
|
|
98
|
-
const PROMPTS_MULTISELECT_MODULE_PATH = "prompts/lib/elements/multiselect";
|
|
99
|
-
let didPatchMultiselectToggleAll = false;
|
|
100
|
-
let didPatchMultiselectSubmit = false;
|
|
101
|
-
const onCancel = () => {
|
|
102
|
-
cliLogger.break();
|
|
103
|
-
cliLogger.log("Cancelled.");
|
|
104
|
-
cliLogger.break();
|
|
105
|
-
process.exit(0);
|
|
106
|
-
};
|
|
107
|
-
const patchMultiselectToggleAll = () => {
|
|
108
|
-
if (didPatchMultiselectToggleAll) return;
|
|
109
|
-
didPatchMultiselectToggleAll = true;
|
|
110
|
-
const multiselectPromptConstructor = require(PROMPTS_MULTISELECT_MODULE_PATH);
|
|
111
|
-
multiselectPromptConstructor.prototype.toggleAll = function() {
|
|
112
|
-
const isCurrentChoiceDisabled = Boolean(this.value[this.cursor]?.disabled);
|
|
113
|
-
if (this.maxChoices !== void 0 || isCurrentChoiceDisabled) {
|
|
114
|
-
this.bell();
|
|
115
|
-
return;
|
|
116
|
-
}
|
|
117
|
-
const shouldSelectAllEnabledChoices = shouldSelectAllChoices(this.value);
|
|
118
|
-
for (const choiceState of this.value) {
|
|
119
|
-
if (choiceState.disabled) continue;
|
|
120
|
-
choiceState.selected = shouldSelectAllEnabledChoices;
|
|
121
|
-
}
|
|
122
|
-
this.render();
|
|
123
|
-
};
|
|
124
|
-
};
|
|
125
|
-
const patchMultiselectSubmit = () => {
|
|
126
|
-
if (didPatchMultiselectSubmit) return;
|
|
127
|
-
didPatchMultiselectSubmit = true;
|
|
128
|
-
const multiselectPromptConstructor = require(PROMPTS_MULTISELECT_MODULE_PATH);
|
|
129
|
-
const originalSubmit = multiselectPromptConstructor.prototype.submit;
|
|
130
|
-
multiselectPromptConstructor.prototype.submit = function() {
|
|
131
|
-
if (shouldAutoSelectCurrentChoice(this.value, this.cursor)) this.value[this.cursor].selected = true;
|
|
132
|
-
originalSubmit.call(this);
|
|
133
|
-
};
|
|
134
|
-
};
|
|
135
|
-
const prompts = (questions, options = {}) => {
|
|
136
|
-
patchMultiselectToggleAll();
|
|
137
|
-
patchMultiselectSubmit();
|
|
138
|
-
return basePrompts(questions, { onCancel: options.onCancel ?? onCancel }).finally(unrefStdin);
|
|
139
|
-
};
|
|
140
|
-
//#endregion
|
|
141
|
-
//#region src/cli/utils/install-github-workflow.ts
|
|
142
|
-
const buildWorkflowContent = (defaultBranch, actionRef = "v2") => `# React Doctor — finds security, performance, correctness, accessibility,
|
|
143
|
-
# bundle-size, and architecture issues in React codebases.
|
|
144
|
-
#
|
|
145
|
-
# Docs: https://www.react.doctor/ci
|
|
146
|
-
# Source: https://github.com/millionco/react-doctor
|
|
147
|
-
|
|
148
|
-
name: React Doctor
|
|
149
|
-
|
|
150
|
-
on:
|
|
151
|
-
# Scans the PR's changed files and posts a sticky summary comment listing only the new issues introduced relative to the merge base of the target branch.
|
|
152
|
-
pull_request:
|
|
153
|
-
types: [opened, synchronize, reopened, ready_for_review]
|
|
154
|
-
# Scans \`${defaultBranch}\` on every push to track the health-score trend and catch regressions that slipped past PR review.
|
|
155
|
-
push:
|
|
156
|
-
branches: ["${defaultBranch}"]
|
|
157
|
-
|
|
158
|
-
permissions:
|
|
159
|
-
contents: read
|
|
160
|
-
pull-requests: write
|
|
161
|
-
issues: write
|
|
162
|
-
statuses: write
|
|
163
|
-
|
|
164
|
-
# Cancels any in-flight scan for the same PR (or branch, on push) the moment a new commit arrives, so reviewers only ever see the latest run.
|
|
165
|
-
concurrency:
|
|
166
|
-
group: react-doctor-\${{ github.event.pull_request.number || github.ref }}
|
|
167
|
-
cancel-in-progress: true
|
|
168
|
-
|
|
169
|
-
jobs:
|
|
170
|
-
react-doctor:
|
|
171
|
-
runs-on: ubuntu-latest
|
|
172
|
-
steps:
|
|
173
|
-
# fetch-depth: 0 gives React Doctor the full git history it needs to find the merge base with the target branch. Without it a shallow checkout has no merge base, so PR runs can't compare against the base and fall back to reporting every issue in the changed files (pre-existing ones included) instead of only the ones the PR introduced.
|
|
174
|
-
- uses: actions/checkout@v5
|
|
175
|
-
with:
|
|
176
|
-
fetch-depth: 0
|
|
177
|
-
|
|
178
|
-
- uses: millionco/react-doctor@${actionRef}
|
|
179
|
-
# Advisory by default: React Doctor reports findings on every PR — a
|
|
180
|
-
# sticky summary comment, inline review comments, and a commit status
|
|
181
|
-
# with the health score — but never fails the check, so it won't red-X
|
|
182
|
-
# a teammate's PR on day one. When your team trusts the signal, graduate
|
|
183
|
-
# the gate: uncomment the block below and set blocking to "error" (fail
|
|
184
|
-
# on new error-severity findings) or "warning" (fail on any finding).
|
|
185
|
-
# Full reference: https://www.react.doctor/ci
|
|
186
|
-
# with:
|
|
187
|
-
# blocking: error # Gate level: "none" (advisory, the default) | "warning" | "error"
|
|
188
|
-
# scope: full # On PRs, scan the whole project instead of just changed files
|
|
189
|
-
# comment: false # Disable the sticky PR summary comment
|
|
190
|
-
# review-comments: false # Disable inline review comments on changed lines
|
|
191
|
-
# commit-status: false # Disable the commit status (score + counts, links to the run)
|
|
192
|
-
# version: "0.4.0" # Pin to a specific react-doctor version instead of "latest"
|
|
193
|
-
# directory: apps/web # Scan a sub-directory (default: ".")
|
|
194
|
-
# project: "web,admin" # In a monorepo, scan specific workspace project(s)
|
|
195
|
-
`;
|
|
196
|
-
const getReactDoctorWorkflowPath = (projectRoot) => path$1.join(projectRoot, ".github", "workflows", "react-doctor.yml");
|
|
197
|
-
const isReactDoctorWorkflowInstalled = (projectRoot) => fs$1.existsSync(getReactDoctorWorkflowPath(projectRoot));
|
|
198
|
-
const V1_FLOATING_ACTION_REF = String.raw`millionco/react-doctor@v1(?![\w.])`;
|
|
199
|
-
const V2_FLOATING_ACTION_REF = "millionco/react-doctor@v2";
|
|
200
|
-
const readReactDoctorWorkflow = (projectRoot) => {
|
|
201
|
-
const workflowPath = getReactDoctorWorkflowPath(projectRoot);
|
|
202
|
-
try {
|
|
203
|
-
return {
|
|
204
|
-
workflowPath,
|
|
205
|
-
content: fs$1.readFileSync(workflowPath, "utf8")
|
|
206
|
-
};
|
|
207
|
-
} catch {
|
|
208
|
-
return null;
|
|
209
|
-
}
|
|
210
|
-
};
|
|
211
|
-
const workflowUsesV1Action = (content) => new RegExp(V1_FLOATING_ACTION_REF).test(content);
|
|
212
|
-
const upgradeWorkflowActionToV2 = (content) => {
|
|
213
|
-
const upgraded = content.replace(new RegExp(V1_FLOATING_ACTION_REF, "g"), V2_FLOATING_ACTION_REF);
|
|
214
|
-
return {
|
|
215
|
-
content: upgraded,
|
|
216
|
-
changed: upgraded !== content
|
|
217
|
-
};
|
|
218
|
-
};
|
|
219
|
-
const installReactDoctorWorkflow = (projectRoot, defaultBranch = "main") => {
|
|
220
|
-
const workflowPath = getReactDoctorWorkflowPath(projectRoot);
|
|
221
|
-
if (fs$1.existsSync(workflowPath)) return {
|
|
222
|
-
status: "exists",
|
|
223
|
-
workflowPath
|
|
224
|
-
};
|
|
225
|
-
try {
|
|
226
|
-
fs$1.mkdirSync(path$1.dirname(workflowPath), { recursive: true });
|
|
227
|
-
fs$1.writeFileSync(workflowPath, buildWorkflowContent(defaultBranch));
|
|
228
|
-
return {
|
|
229
|
-
status: "created",
|
|
230
|
-
workflowPath
|
|
231
|
-
};
|
|
232
|
-
} catch {
|
|
233
|
-
return {
|
|
234
|
-
status: "failed",
|
|
235
|
-
workflowPath
|
|
236
|
-
};
|
|
237
|
-
}
|
|
238
|
-
};
|
|
239
|
-
const upgradeReactDoctorWorkflowInPlace = (projectRoot) => {
|
|
240
|
-
const workflow = readReactDoctorWorkflow(projectRoot);
|
|
241
|
-
if (!workflow) return {
|
|
242
|
-
status: "not-needed",
|
|
243
|
-
workflowPath: getReactDoctorWorkflowPath(projectRoot)
|
|
244
|
-
};
|
|
245
|
-
const { content, changed } = upgradeWorkflowActionToV2(workflow.content);
|
|
246
|
-
if (!changed) return {
|
|
247
|
-
status: "not-needed",
|
|
248
|
-
workflowPath: workflow.workflowPath
|
|
249
|
-
};
|
|
250
|
-
try {
|
|
251
|
-
fs$1.writeFileSync(workflow.workflowPath, content);
|
|
252
|
-
return {
|
|
253
|
-
status: "upgraded",
|
|
254
|
-
workflowPath: workflow.workflowPath
|
|
255
|
-
};
|
|
256
|
-
} catch {
|
|
257
|
-
return {
|
|
258
|
-
status: "failed",
|
|
259
|
-
workflowPath: workflow.workflowPath
|
|
260
|
-
};
|
|
261
|
-
}
|
|
262
|
-
};
|
|
263
|
-
//#endregion
|
|
264
|
-
export { readReactDoctorWorkflow as a, workflowUsesV1Action as c, detectDefaultBranch as d, runCommand as f, isReactDoctorWorkflowInstalled as i, prompts as l, getReactDoctorWorkflowPath as n, upgradeReactDoctorWorkflowInPlace as o, installReactDoctorWorkflow as r, upgradeWorkflowActionToV2 as s, buildWorkflowContent as t, isCommandAvailable as u };
|
|
265
|
-
|
|
266
|
-
//# sourceMappingURL=install-github-workflow-BP6t3YBA.js.map
|
|
267
|
-
//# debugId=1f395a85-8fa9-5c73-af2c-14352d85877d
|