react-doctor 0.7.9-dev.1a30f2c → 0.7.9-dev.21043e0
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 +79 -29
- package/dist/index.js +76 -9
- package/dist/lsp.js +76 -26
- package/package.json +4 -4
package/dist/cli.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
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]="
|
|
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]="6f05eada-46fe-5b24-92d8-15fa92a38b00")}catch(e){}}();
|
|
3
3
|
import { createRequire } from "node:module";
|
|
4
4
|
import * as NodeChildProcess from "node:child_process";
|
|
5
5
|
import { execFile, execFileSync, spawn, spawnSync } from "node:child_process";
|
|
@@ -36252,6 +36252,53 @@ const SUPPLY_CHAIN_OVERLAP_TIMEOUT_MS = 9e4;
|
|
|
36252
36252
|
const SUPPLY_CHAIN_CACHE_TTL_MS = 864e5;
|
|
36253
36253
|
const SUPPLY_CHAIN_CACHE_SUBDIR = "supply-chain";
|
|
36254
36254
|
const SUPPLY_CHAIN_IGNORED_PACKAGES = new Set(["next"]);
|
|
36255
|
+
const lastSourceMappingUrl = (fileContent) => {
|
|
36256
|
+
const lastReference = [...fileContent.matchAll(/\/\/# sourceMappingURL=(\S+)/g)].at(-1);
|
|
36257
|
+
return lastReference ? lastReference[1] : null;
|
|
36258
|
+
};
|
|
36259
|
+
const mapTargetsSource = (mapContent, input) => {
|
|
36260
|
+
const parsedMap = JSON.parse(mapContent);
|
|
36261
|
+
if (typeof parsedMap !== "object" || parsedMap === null) return false;
|
|
36262
|
+
const { file, sources } = parsedMap;
|
|
36263
|
+
if (file !== input.expectedFile) return false;
|
|
36264
|
+
if (!Array.isArray(sources) || sources.length !== 1 || typeof sources[0] !== "string") return false;
|
|
36265
|
+
return Path.posix.normalize(Path.posix.join(input.mapDirectory, sources[0])) === input.sourcePath;
|
|
36266
|
+
};
|
|
36267
|
+
const quartetProvesEmit = (stem, sourcePath, readFileText) => {
|
|
36268
|
+
try {
|
|
36269
|
+
const emitBaseName = Path.posix.basename(stem);
|
|
36270
|
+
const mapDirectory = Path.posix.dirname(stem);
|
|
36271
|
+
return lastSourceMappingUrl(readFileText(`${stem}.js`)) === `${emitBaseName}.js.map` && lastSourceMappingUrl(readFileText(`${stem}.d.ts`)) === `${emitBaseName}.d.ts.map` && mapTargetsSource(readFileText(`${stem}.js.map`), {
|
|
36272
|
+
expectedFile: `${emitBaseName}.js`,
|
|
36273
|
+
mapDirectory,
|
|
36274
|
+
sourcePath
|
|
36275
|
+
}) && mapTargetsSource(readFileText(`${stem}.d.ts.map`), {
|
|
36276
|
+
expectedFile: `${emitBaseName}.d.ts`,
|
|
36277
|
+
mapDirectory,
|
|
36278
|
+
sourcePath
|
|
36279
|
+
});
|
|
36280
|
+
} catch {
|
|
36281
|
+
return false;
|
|
36282
|
+
}
|
|
36283
|
+
};
|
|
36284
|
+
const collectTypeScriptEmitDuplicateJsPaths = (input) => {
|
|
36285
|
+
const untracked = new Set(input.untrackedPaths);
|
|
36286
|
+
const duplicateJsPaths = /* @__PURE__ */ new Set();
|
|
36287
|
+
for (const jsPath of untracked) {
|
|
36288
|
+
if (!jsPath.endsWith(".js")) continue;
|
|
36289
|
+
const stem = jsPath.slice(0, -3);
|
|
36290
|
+
if (![
|
|
36291
|
+
jsPath,
|
|
36292
|
+
`${stem}.js.map`,
|
|
36293
|
+
`${stem}.d.ts`,
|
|
36294
|
+
`${stem}.d.ts.map`
|
|
36295
|
+
].every((emitPath) => untracked.has(emitPath) && !input.trackedPaths.has(emitPath))) continue;
|
|
36296
|
+
const sourcePath = [`${stem}.ts`, `${stem}.tsx`].find((candidatePath) => input.trackedPaths.has(candidatePath));
|
|
36297
|
+
if (!sourcePath) continue;
|
|
36298
|
+
if (quartetProvesEmit(stem, sourcePath, input.readFileText)) duplicateJsPaths.add(jsPath);
|
|
36299
|
+
}
|
|
36300
|
+
return duplicateJsPaths;
|
|
36301
|
+
};
|
|
36255
36302
|
const isIgnoredDirectoryName = (directoryName) => IGNORED_DIRECTORIES.has(directoryName) || directoryName.startsWith(".") && !SCANNED_DOT_DIRECTORIES.has(directoryName);
|
|
36256
36303
|
const hasIgnoredPathSegment = (relativePath) => relativePath.split(/[/\\]/).slice(0, -1).some((segment) => isIgnoredDirectoryName(segment));
|
|
36257
36304
|
const isLintableSourceFile = (filePath) => SOURCE_FILE_PATTERN.test(filePath) && !GENERATED_BUNDLE_FILE_PATTERN.test(filePath) && !GENERATED_SOURCE_DIRECTORY_PATTERN.test(filePath);
|
|
@@ -36319,20 +36366,29 @@ const collectSizedSourceFiles = (rootDirectory, relativePaths) => {
|
|
|
36319
36366
|
}
|
|
36320
36367
|
return entries;
|
|
36321
36368
|
};
|
|
36322
|
-
const
|
|
36369
|
+
const gitLsFiles = (rootDirectory, flags) => {
|
|
36323
36370
|
const result = spawnSync("git", [
|
|
36324
36371
|
"ls-files",
|
|
36325
36372
|
"-z",
|
|
36326
|
-
|
|
36327
|
-
"--others",
|
|
36328
|
-
"--exclude-standard"
|
|
36373
|
+
...flags
|
|
36329
36374
|
], {
|
|
36330
36375
|
cwd: rootDirectory,
|
|
36331
36376
|
encoding: "utf-8",
|
|
36332
36377
|
maxBuffer: GIT_LS_FILES_MAX_BUFFER_BYTES
|
|
36333
36378
|
});
|
|
36334
36379
|
if (result.error || result.status !== 0) return null;
|
|
36335
|
-
return result.stdout.split("\0").filter((filePath) => filePath.length > 0
|
|
36380
|
+
return result.stdout.split("\0").filter((filePath) => filePath.length > 0);
|
|
36381
|
+
};
|
|
36382
|
+
const listSourceFilesViaGit = (rootDirectory) => {
|
|
36383
|
+
const trackedPaths = gitLsFiles(rootDirectory, ["--cached"]);
|
|
36384
|
+
const untrackedPaths = gitLsFiles(rootDirectory, ["--others", "--exclude-standard"]);
|
|
36385
|
+
if (trackedPaths === null || untrackedPaths === null) return null;
|
|
36386
|
+
const emitDuplicateJsPaths = collectTypeScriptEmitDuplicateJsPaths({
|
|
36387
|
+
trackedPaths: new Set(trackedPaths),
|
|
36388
|
+
untrackedPaths,
|
|
36389
|
+
readFileText: (relativePath) => NFS.readFileSync(Path.resolve(rootDirectory, relativePath), "utf-8")
|
|
36390
|
+
});
|
|
36391
|
+
return [...trackedPaths, ...untrackedPaths].filter((filePath) => isLintableSourceFile(filePath) && !hasIgnoredPathSegment(filePath) && !emitDuplicateJsPaths.has(filePath));
|
|
36336
36392
|
};
|
|
36337
36393
|
const listSourceFilesViaFilesystem = (rootDirectory) => {
|
|
36338
36394
|
const filePaths = [];
|
|
@@ -45276,6 +45332,14 @@ var Reporter = class Reporter extends Service()("react-doctor/Reporter") {
|
|
|
45276
45332
|
});
|
|
45277
45333
|
}));
|
|
45278
45334
|
};
|
|
45335
|
+
const HOME_DIRECTORY = os.homedir();
|
|
45336
|
+
const USER_HOME_PATTERNS = [/[A-Za-z]:[\\/]Users[\\/][^\\/]+/gi, /(?:\/Users\/|\/home\/)[^/\\]+/gi];
|
|
45337
|
+
const scrubSensitivePaths = (text) => {
|
|
45338
|
+
let scrubbed = text;
|
|
45339
|
+
if (HOME_DIRECTORY.length > 1) scrubbed = scrubbed.split(HOME_DIRECTORY).join("~");
|
|
45340
|
+
for (const pattern of USER_HOME_PATTERNS) scrubbed = scrubbed.replace(pattern, "~");
|
|
45341
|
+
return scrubbed;
|
|
45342
|
+
};
|
|
45279
45343
|
const ScoreApiResponseSchema = Struct({
|
|
45280
45344
|
score: Number$1,
|
|
45281
45345
|
label: String$1,
|
|
@@ -45290,7 +45354,10 @@ const ScoreApiResponseSchema = Struct({
|
|
|
45290
45354
|
})))
|
|
45291
45355
|
});
|
|
45292
45356
|
const parseScoreResult = (value) => getOrNull(decodeUnknownOption(ScoreApiResponseSchema)(value));
|
|
45293
|
-
const
|
|
45357
|
+
const sanitizeScoreDiagnostics = (diagnostics) => diagnostics.map(({ filePath, fileContext: _fileContext, fixGroupId: _fixGroupId, ...rest }) => ({
|
|
45358
|
+
...rest,
|
|
45359
|
+
filePath: redactSensitiveText(scrubSensitivePaths(filePath))
|
|
45360
|
+
}));
|
|
45294
45361
|
const isAbortError = (error) => error instanceof Error && (error.name === "AbortError" || error.name === "TimeoutError");
|
|
45295
45362
|
const describeFailure = (error) => {
|
|
45296
45363
|
if (isAbortError(error)) return `timed out after ${FETCH_TIMEOUT_MS / 1e3}s`;
|
|
@@ -45303,7 +45370,7 @@ const calculateScore = async (diagnostics, options = {}) => {
|
|
|
45303
45370
|
const requestUrl = options.isCi ? `${SCORE_API_URL}?ci=1` : SCORE_API_URL;
|
|
45304
45371
|
try {
|
|
45305
45372
|
const compressedBody = gzipSync(JSON.stringify({
|
|
45306
|
-
diagnostics:
|
|
45373
|
+
diagnostics: sanitizeScoreDiagnostics(diagnostics),
|
|
45307
45374
|
...options.metadata?.repo ? { repo: options.metadata.repo } : {},
|
|
45308
45375
|
...options.metadata?.sha ? { sha: options.metadata.sha } : {},
|
|
45309
45376
|
...options.metadata?.framework ? { framework: options.metadata.framework } : {},
|
|
@@ -47148,7 +47215,7 @@ const makeNoopConsole = () => ({
|
|
|
47148
47215
|
});
|
|
47149
47216
|
//#endregion
|
|
47150
47217
|
//#region src/cli/utils/version.ts
|
|
47151
|
-
const VERSION = "0.7.9-dev.
|
|
47218
|
+
const VERSION = "0.7.9-dev.21043e0";
|
|
47152
47219
|
//#endregion
|
|
47153
47220
|
//#region src/cli/utils/json-mode.ts
|
|
47154
47221
|
let context = null;
|
|
@@ -47234,23 +47301,6 @@ const getRunId = () => {
|
|
|
47234
47301
|
return cachedRunId;
|
|
47235
47302
|
};
|
|
47236
47303
|
//#endregion
|
|
47237
|
-
//#region src/cli/utils/scrub-sensitive-text.ts
|
|
47238
|
-
const HOME_DIRECTORY = os.homedir();
|
|
47239
|
-
const USER_HOME_PATTERNS = [/[A-Za-z]:[\\/]Users[\\/][^\\/]+/gi, /(?:\/Users\/|\/home\/)[^/\\]+/gi];
|
|
47240
|
-
/**
|
|
47241
|
-
* Replaces the user's home directory (and generic `/Users|/home|C:\Users\<name>`
|
|
47242
|
-
* roots) with `~` so absolute paths can't be tied back to an individual. Keeps
|
|
47243
|
-
* the path's relative structure intact, which stays useful for debugging while
|
|
47244
|
-
* dropping the personally-identifying prefix. Idempotent — re-running on an
|
|
47245
|
-
* already-scrubbed `~/...` path is a no-op.
|
|
47246
|
-
*/
|
|
47247
|
-
const scrubSensitivePaths = (text) => {
|
|
47248
|
-
let scrubbed = text;
|
|
47249
|
-
if (HOME_DIRECTORY.length > 1) scrubbed = scrubbed.split(HOME_DIRECTORY).join("~");
|
|
47250
|
-
for (const pattern of USER_HOME_PATTERNS) scrubbed = scrubbed.replace(pattern, "~");
|
|
47251
|
-
return scrubbed;
|
|
47252
|
-
};
|
|
47253
|
-
//#endregion
|
|
47254
47304
|
//#region src/cli/utils/build-run-context.ts
|
|
47255
47305
|
const ROOT_SUBCOMMANDS = new Set(["install", "setup"]);
|
|
47256
47306
|
const detectInvokedVia = () => {
|
|
@@ -47517,13 +47567,13 @@ const isDevVersion = (version) => version === "0.0.0" || version.includes("-");
|
|
|
47517
47567
|
* uploads source-map artifacts under, so stack frames symbolicate. Honors the
|
|
47518
47568
|
* standard `SENTRY_RELEASE` override.
|
|
47519
47569
|
*/
|
|
47520
|
-
const resolveSentryRelease = () => process.env.SENTRY_RELEASE || `react-doctor@0.7.9-dev.
|
|
47570
|
+
const resolveSentryRelease = () => process.env.SENTRY_RELEASE || `react-doctor@0.7.9-dev.21043e0`;
|
|
47521
47571
|
/**
|
|
47522
47572
|
* Deployment environment shown in Sentry's environment filter. Defaults to
|
|
47523
47573
|
* `production` for tagged releases and `development` for dev/unbuilt versions,
|
|
47524
47574
|
* overridable via the standard `SENTRY_ENVIRONMENT` env var.
|
|
47525
47575
|
*/
|
|
47526
|
-
const resolveSentryEnvironment = () => process.env.SENTRY_ENVIRONMENT || (isDevVersion("0.7.9-dev.
|
|
47576
|
+
const resolveSentryEnvironment = () => process.env.SENTRY_ENVIRONMENT || (isDevVersion("0.7.9-dev.21043e0") ? "development" : "production");
|
|
47527
47577
|
/**
|
|
47528
47578
|
* Performance-tracing sample rate in `[0, 1]`. Reads `SENTRY_TRACES_SAMPLE_RATE`
|
|
47529
47579
|
* (set to `0` to disable tracing) and falls back to
|
|
@@ -65801,4 +65851,4 @@ Promise.resolve().then(() => assertNoRemovedFlags(process.argv)).then(() => prog
|
|
|
65801
65851
|
export {};
|
|
65802
65852
|
|
|
65803
65853
|
//# sourceMappingURL=cli.js.map
|
|
65804
|
-
//# debugId=
|
|
65854
|
+
//# debugId=6f05eada-46fe-5b24-92d8-15fa92a38b00
|
package/dist/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
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]="
|
|
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]="28287c1c-b7b6-53b8-9e72-7d28d4f3ca45")}catch(e){}}();
|
|
3
3
|
import { r as __toESM$1, t as __commonJSMin$1 } from "./chunk-N93fKeF6.js";
|
|
4
4
|
import { createRequire } from "node:module";
|
|
5
5
|
import reactDoctorPlugin, { ALL_REACT_DOCTOR_RULE_KEYS, CROSS_FILE_DEPENDENCY_COLLECTORS, CROSS_FILE_RULE_IDS, FRAMEWORK_SPECIFIC_RULE_KEYS, FRAMEWORK_TOKENS, MOTION_LIBRARY_PACKAGES, REACT_COMPILER_RULES, REACT_DOCTOR_RULES, classifySecurityScanFile, collectCrossFileDependencyProbes, resetManifestCaches, shouldReadSecurityScanContent } from "oxlint-plugin-react-doctor";
|
|
@@ -33050,6 +33050,53 @@ const SUPPLY_CHAIN_OVERLAP_TIMEOUT_MS = 9e4;
|
|
|
33050
33050
|
const SUPPLY_CHAIN_CACHE_TTL_MS = 864e5;
|
|
33051
33051
|
const SUPPLY_CHAIN_CACHE_SUBDIR = "supply-chain";
|
|
33052
33052
|
const SUPPLY_CHAIN_IGNORED_PACKAGES = new Set(["next"]);
|
|
33053
|
+
const lastSourceMappingUrl = (fileContent) => {
|
|
33054
|
+
const lastReference = [...fileContent.matchAll(/\/\/# sourceMappingURL=(\S+)/g)].at(-1);
|
|
33055
|
+
return lastReference ? lastReference[1] : null;
|
|
33056
|
+
};
|
|
33057
|
+
const mapTargetsSource = (mapContent, input) => {
|
|
33058
|
+
const parsedMap = JSON.parse(mapContent);
|
|
33059
|
+
if (typeof parsedMap !== "object" || parsedMap === null) return false;
|
|
33060
|
+
const { file, sources } = parsedMap;
|
|
33061
|
+
if (file !== input.expectedFile) return false;
|
|
33062
|
+
if (!Array.isArray(sources) || sources.length !== 1 || typeof sources[0] !== "string") return false;
|
|
33063
|
+
return Path.posix.normalize(Path.posix.join(input.mapDirectory, sources[0])) === input.sourcePath;
|
|
33064
|
+
};
|
|
33065
|
+
const quartetProvesEmit = (stem, sourcePath, readFileText) => {
|
|
33066
|
+
try {
|
|
33067
|
+
const emitBaseName = Path.posix.basename(stem);
|
|
33068
|
+
const mapDirectory = Path.posix.dirname(stem);
|
|
33069
|
+
return lastSourceMappingUrl(readFileText(`${stem}.js`)) === `${emitBaseName}.js.map` && lastSourceMappingUrl(readFileText(`${stem}.d.ts`)) === `${emitBaseName}.d.ts.map` && mapTargetsSource(readFileText(`${stem}.js.map`), {
|
|
33070
|
+
expectedFile: `${emitBaseName}.js`,
|
|
33071
|
+
mapDirectory,
|
|
33072
|
+
sourcePath
|
|
33073
|
+
}) && mapTargetsSource(readFileText(`${stem}.d.ts.map`), {
|
|
33074
|
+
expectedFile: `${emitBaseName}.d.ts`,
|
|
33075
|
+
mapDirectory,
|
|
33076
|
+
sourcePath
|
|
33077
|
+
});
|
|
33078
|
+
} catch {
|
|
33079
|
+
return false;
|
|
33080
|
+
}
|
|
33081
|
+
};
|
|
33082
|
+
const collectTypeScriptEmitDuplicateJsPaths = (input) => {
|
|
33083
|
+
const untracked = new Set(input.untrackedPaths);
|
|
33084
|
+
const duplicateJsPaths = /* @__PURE__ */ new Set();
|
|
33085
|
+
for (const jsPath of untracked) {
|
|
33086
|
+
if (!jsPath.endsWith(".js")) continue;
|
|
33087
|
+
const stem = jsPath.slice(0, -3);
|
|
33088
|
+
if (![
|
|
33089
|
+
jsPath,
|
|
33090
|
+
`${stem}.js.map`,
|
|
33091
|
+
`${stem}.d.ts`,
|
|
33092
|
+
`${stem}.d.ts.map`
|
|
33093
|
+
].every((emitPath) => untracked.has(emitPath) && !input.trackedPaths.has(emitPath))) continue;
|
|
33094
|
+
const sourcePath = [`${stem}.ts`, `${stem}.tsx`].find((candidatePath) => input.trackedPaths.has(candidatePath));
|
|
33095
|
+
if (!sourcePath) continue;
|
|
33096
|
+
if (quartetProvesEmit(stem, sourcePath, input.readFileText)) duplicateJsPaths.add(jsPath);
|
|
33097
|
+
}
|
|
33098
|
+
return duplicateJsPaths;
|
|
33099
|
+
};
|
|
33053
33100
|
const isIgnoredDirectoryName = (directoryName) => IGNORED_DIRECTORIES.has(directoryName) || directoryName.startsWith(".") && !SCANNED_DOT_DIRECTORIES.has(directoryName);
|
|
33054
33101
|
const hasIgnoredPathSegment = (relativePath) => relativePath.split(/[/\\]/).slice(0, -1).some((segment) => isIgnoredDirectoryName(segment));
|
|
33055
33102
|
const isLintableSourceFile = (filePath) => SOURCE_FILE_PATTERN.test(filePath) && !GENERATED_BUNDLE_FILE_PATTERN.test(filePath) && !GENERATED_SOURCE_DIRECTORY_PATTERN.test(filePath);
|
|
@@ -33120,20 +33167,29 @@ const collectSizedSourceFiles = (rootDirectory, relativePaths) => {
|
|
|
33120
33167
|
}
|
|
33121
33168
|
return entries;
|
|
33122
33169
|
};
|
|
33123
|
-
const
|
|
33170
|
+
const gitLsFiles = (rootDirectory, flags) => {
|
|
33124
33171
|
const result = spawnSync("git", [
|
|
33125
33172
|
"ls-files",
|
|
33126
33173
|
"-z",
|
|
33127
|
-
|
|
33128
|
-
"--others",
|
|
33129
|
-
"--exclude-standard"
|
|
33174
|
+
...flags
|
|
33130
33175
|
], {
|
|
33131
33176
|
cwd: rootDirectory,
|
|
33132
33177
|
encoding: "utf-8",
|
|
33133
33178
|
maxBuffer: GIT_LS_FILES_MAX_BUFFER_BYTES
|
|
33134
33179
|
});
|
|
33135
33180
|
if (result.error || result.status !== 0) return null;
|
|
33136
|
-
return result.stdout.split("\0").filter((filePath) => filePath.length > 0
|
|
33181
|
+
return result.stdout.split("\0").filter((filePath) => filePath.length > 0);
|
|
33182
|
+
};
|
|
33183
|
+
const listSourceFilesViaGit = (rootDirectory) => {
|
|
33184
|
+
const trackedPaths = gitLsFiles(rootDirectory, ["--cached"]);
|
|
33185
|
+
const untrackedPaths = gitLsFiles(rootDirectory, ["--others", "--exclude-standard"]);
|
|
33186
|
+
if (trackedPaths === null || untrackedPaths === null) return null;
|
|
33187
|
+
const emitDuplicateJsPaths = collectTypeScriptEmitDuplicateJsPaths({
|
|
33188
|
+
trackedPaths: new Set(trackedPaths),
|
|
33189
|
+
untrackedPaths,
|
|
33190
|
+
readFileText: (relativePath) => NFS.readFileSync(Path.resolve(rootDirectory, relativePath), "utf-8")
|
|
33191
|
+
});
|
|
33192
|
+
return [...trackedPaths, ...untrackedPaths].filter((filePath) => isLintableSourceFile(filePath) && !hasIgnoredPathSegment(filePath) && !emitDuplicateJsPaths.has(filePath));
|
|
33137
33193
|
};
|
|
33138
33194
|
const listSourceFilesViaFilesystem = (rootDirectory) => {
|
|
33139
33195
|
const filePaths = [];
|
|
@@ -42032,6 +42088,14 @@ var Reporter = class Reporter extends Service()("react-doctor/Reporter") {
|
|
|
42032
42088
|
});
|
|
42033
42089
|
}));
|
|
42034
42090
|
};
|
|
42091
|
+
const HOME_DIRECTORY = os.homedir();
|
|
42092
|
+
const USER_HOME_PATTERNS = [/[A-Za-z]:[\\/]Users[\\/][^\\/]+/gi, /(?:\/Users\/|\/home\/)[^/\\]+/gi];
|
|
42093
|
+
const scrubSensitivePaths = (text) => {
|
|
42094
|
+
let scrubbed = text;
|
|
42095
|
+
if (HOME_DIRECTORY.length > 1) scrubbed = scrubbed.split(HOME_DIRECTORY).join("~");
|
|
42096
|
+
for (const pattern of USER_HOME_PATTERNS) scrubbed = scrubbed.replace(pattern, "~");
|
|
42097
|
+
return scrubbed;
|
|
42098
|
+
};
|
|
42035
42099
|
const ScoreApiResponseSchema = Struct({
|
|
42036
42100
|
score: Number$1,
|
|
42037
42101
|
label: String$1,
|
|
@@ -42046,7 +42110,10 @@ const ScoreApiResponseSchema = Struct({
|
|
|
42046
42110
|
})))
|
|
42047
42111
|
});
|
|
42048
42112
|
const parseScoreResult = (value) => getOrNull(decodeUnknownOption(ScoreApiResponseSchema)(value));
|
|
42049
|
-
const
|
|
42113
|
+
const sanitizeScoreDiagnostics = (diagnostics) => diagnostics.map(({ filePath, fileContext: _fileContext, fixGroupId: _fixGroupId, ...rest }) => ({
|
|
42114
|
+
...rest,
|
|
42115
|
+
filePath: redactSensitiveText(scrubSensitivePaths(filePath))
|
|
42116
|
+
}));
|
|
42050
42117
|
const isAbortError = (error) => error instanceof Error && (error.name === "AbortError" || error.name === "TimeoutError");
|
|
42051
42118
|
const describeFailure = (error) => {
|
|
42052
42119
|
if (isAbortError(error)) return `timed out after ${FETCH_TIMEOUT_MS / 1e3}s`;
|
|
@@ -42059,7 +42126,7 @@ const calculateScore = async (diagnostics, options = {}) => {
|
|
|
42059
42126
|
const requestUrl = options.isCi ? `${SCORE_API_URL}?ci=1` : SCORE_API_URL;
|
|
42060
42127
|
try {
|
|
42061
42128
|
const compressedBody = gzipSync(JSON.stringify({
|
|
42062
|
-
diagnostics:
|
|
42129
|
+
diagnostics: sanitizeScoreDiagnostics(diagnostics),
|
|
42063
42130
|
...options.metadata?.repo ? { repo: options.metadata.repo } : {},
|
|
42064
42131
|
...options.metadata?.sha ? { sha: options.metadata.sha } : {},
|
|
42065
42132
|
...options.metadata?.framework ? { framework: options.metadata.framework } : {},
|
|
@@ -43652,4 +43719,4 @@ const toJsonReport = (result, options) => buildJsonReport({
|
|
|
43652
43719
|
export { AmbiguousProjectError, NoReactDependencyError, NotADirectoryError, PackageJsonNotFoundError, ProjectNotFoundError, ReactDoctorError, buildJsonReport, buildJsonReportError, clearCaches, defineConfig, diagnose, filterSourceFiles, getDiffInfo, hasReactRuntime, isProjectDiscoveryError, isReactDoctorError, summarizeDiagnostics, toJsonReport };
|
|
43653
43720
|
|
|
43654
43721
|
//# sourceMappingURL=index.js.map
|
|
43655
|
-
//# debugId=
|
|
43722
|
+
//# debugId=28287c1c-b7b6-53b8-9e72-7d28d4f3ca45
|
package/dist/lsp.js
CHANGED
|
@@ -33102,6 +33102,53 @@ const SUPPLY_CHAIN_OVERLAP_TIMEOUT_MS = 9e4;
|
|
|
33102
33102
|
const SUPPLY_CHAIN_CACHE_TTL_MS = 864e5;
|
|
33103
33103
|
const SUPPLY_CHAIN_CACHE_SUBDIR = "supply-chain";
|
|
33104
33104
|
const SUPPLY_CHAIN_IGNORED_PACKAGES = new Set(["next"]);
|
|
33105
|
+
const lastSourceMappingUrl = (fileContent) => {
|
|
33106
|
+
const lastReference = [...fileContent.matchAll(/\/\/# sourceMappingURL=(\S+)/g)].at(-1);
|
|
33107
|
+
return lastReference ? lastReference[1] : null;
|
|
33108
|
+
};
|
|
33109
|
+
const mapTargetsSource = (mapContent, input) => {
|
|
33110
|
+
const parsedMap = JSON.parse(mapContent);
|
|
33111
|
+
if (typeof parsedMap !== "object" || parsedMap === null) return false;
|
|
33112
|
+
const { file, sources } = parsedMap;
|
|
33113
|
+
if (file !== input.expectedFile) return false;
|
|
33114
|
+
if (!Array.isArray(sources) || sources.length !== 1 || typeof sources[0] !== "string") return false;
|
|
33115
|
+
return Path.posix.normalize(Path.posix.join(input.mapDirectory, sources[0])) === input.sourcePath;
|
|
33116
|
+
};
|
|
33117
|
+
const quartetProvesEmit = (stem, sourcePath, readFileText) => {
|
|
33118
|
+
try {
|
|
33119
|
+
const emitBaseName = Path.posix.basename(stem);
|
|
33120
|
+
const mapDirectory = Path.posix.dirname(stem);
|
|
33121
|
+
return lastSourceMappingUrl(readFileText(`${stem}.js`)) === `${emitBaseName}.js.map` && lastSourceMappingUrl(readFileText(`${stem}.d.ts`)) === `${emitBaseName}.d.ts.map` && mapTargetsSource(readFileText(`${stem}.js.map`), {
|
|
33122
|
+
expectedFile: `${emitBaseName}.js`,
|
|
33123
|
+
mapDirectory,
|
|
33124
|
+
sourcePath
|
|
33125
|
+
}) && mapTargetsSource(readFileText(`${stem}.d.ts.map`), {
|
|
33126
|
+
expectedFile: `${emitBaseName}.d.ts`,
|
|
33127
|
+
mapDirectory,
|
|
33128
|
+
sourcePath
|
|
33129
|
+
});
|
|
33130
|
+
} catch {
|
|
33131
|
+
return false;
|
|
33132
|
+
}
|
|
33133
|
+
};
|
|
33134
|
+
const collectTypeScriptEmitDuplicateJsPaths = (input) => {
|
|
33135
|
+
const untracked = new Set(input.untrackedPaths);
|
|
33136
|
+
const duplicateJsPaths = /* @__PURE__ */ new Set();
|
|
33137
|
+
for (const jsPath of untracked) {
|
|
33138
|
+
if (!jsPath.endsWith(".js")) continue;
|
|
33139
|
+
const stem = jsPath.slice(0, -3);
|
|
33140
|
+
if (![
|
|
33141
|
+
jsPath,
|
|
33142
|
+
`${stem}.js.map`,
|
|
33143
|
+
`${stem}.d.ts`,
|
|
33144
|
+
`${stem}.d.ts.map`
|
|
33145
|
+
].every((emitPath) => untracked.has(emitPath) && !input.trackedPaths.has(emitPath))) continue;
|
|
33146
|
+
const sourcePath = [`${stem}.ts`, `${stem}.tsx`].find((candidatePath) => input.trackedPaths.has(candidatePath));
|
|
33147
|
+
if (!sourcePath) continue;
|
|
33148
|
+
if (quartetProvesEmit(stem, sourcePath, input.readFileText)) duplicateJsPaths.add(jsPath);
|
|
33149
|
+
}
|
|
33150
|
+
return duplicateJsPaths;
|
|
33151
|
+
};
|
|
33105
33152
|
const isIgnoredDirectoryName = (directoryName) => IGNORED_DIRECTORIES.has(directoryName) || directoryName.startsWith(".") && !SCANNED_DOT_DIRECTORIES.has(directoryName);
|
|
33106
33153
|
const hasIgnoredPathSegment = (relativePath) => relativePath.split(/[/\\]/).slice(0, -1).some((segment) => isIgnoredDirectoryName(segment));
|
|
33107
33154
|
const isLintableSourceFile = (filePath) => SOURCE_FILE_PATTERN.test(filePath) && !GENERATED_BUNDLE_FILE_PATTERN.test(filePath) && !GENERATED_SOURCE_DIRECTORY_PATTERN.test(filePath);
|
|
@@ -33172,20 +33219,29 @@ const collectSizedSourceFiles = (rootDirectory, relativePaths) => {
|
|
|
33172
33219
|
}
|
|
33173
33220
|
return entries;
|
|
33174
33221
|
};
|
|
33175
|
-
const
|
|
33222
|
+
const gitLsFiles = (rootDirectory, flags) => {
|
|
33176
33223
|
const result = spawnSync("git", [
|
|
33177
33224
|
"ls-files",
|
|
33178
33225
|
"-z",
|
|
33179
|
-
|
|
33180
|
-
"--others",
|
|
33181
|
-
"--exclude-standard"
|
|
33226
|
+
...flags
|
|
33182
33227
|
], {
|
|
33183
33228
|
cwd: rootDirectory,
|
|
33184
33229
|
encoding: "utf-8",
|
|
33185
33230
|
maxBuffer: GIT_LS_FILES_MAX_BUFFER_BYTES
|
|
33186
33231
|
});
|
|
33187
33232
|
if (result.error || result.status !== 0) return null;
|
|
33188
|
-
return result.stdout.split("\0").filter((filePath) => filePath.length > 0
|
|
33233
|
+
return result.stdout.split("\0").filter((filePath) => filePath.length > 0);
|
|
33234
|
+
};
|
|
33235
|
+
const listSourceFilesViaGit = (rootDirectory) => {
|
|
33236
|
+
const trackedPaths = gitLsFiles(rootDirectory, ["--cached"]);
|
|
33237
|
+
const untrackedPaths = gitLsFiles(rootDirectory, ["--others", "--exclude-standard"]);
|
|
33238
|
+
if (trackedPaths === null || untrackedPaths === null) return null;
|
|
33239
|
+
const emitDuplicateJsPaths = collectTypeScriptEmitDuplicateJsPaths({
|
|
33240
|
+
trackedPaths: new Set(trackedPaths),
|
|
33241
|
+
untrackedPaths,
|
|
33242
|
+
readFileText: (relativePath) => NFS.readFileSync(Path.resolve(rootDirectory, relativePath), "utf-8")
|
|
33243
|
+
});
|
|
33244
|
+
return [...trackedPaths, ...untrackedPaths].filter((filePath) => isLintableSourceFile(filePath) && !hasIgnoredPathSegment(filePath) && !emitDuplicateJsPaths.has(filePath));
|
|
33189
33245
|
};
|
|
33190
33246
|
const listSourceFilesViaFilesystem = (rootDirectory) => {
|
|
33191
33247
|
const filePaths = [];
|
|
@@ -42010,6 +42066,14 @@ var Reporter = class Reporter extends Service()("react-doctor/Reporter") {
|
|
|
42010
42066
|
});
|
|
42011
42067
|
}));
|
|
42012
42068
|
};
|
|
42069
|
+
const HOME_DIRECTORY = os.homedir();
|
|
42070
|
+
const USER_HOME_PATTERNS = [/[A-Za-z]:[\\/]Users[\\/][^\\/]+/gi, /(?:\/Users\/|\/home\/)[^/\\]+/gi];
|
|
42071
|
+
const scrubSensitivePaths = (text) => {
|
|
42072
|
+
let scrubbed = text;
|
|
42073
|
+
if (HOME_DIRECTORY.length > 1) scrubbed = scrubbed.split(HOME_DIRECTORY).join("~");
|
|
42074
|
+
for (const pattern of USER_HOME_PATTERNS) scrubbed = scrubbed.replace(pattern, "~");
|
|
42075
|
+
return scrubbed;
|
|
42076
|
+
};
|
|
42013
42077
|
const ScoreApiResponseSchema = Struct({
|
|
42014
42078
|
score: Number$1,
|
|
42015
42079
|
label: String$1,
|
|
@@ -42024,7 +42088,10 @@ const ScoreApiResponseSchema = Struct({
|
|
|
42024
42088
|
})))
|
|
42025
42089
|
});
|
|
42026
42090
|
const parseScoreResult = (value) => getOrNull(decodeUnknownOption(ScoreApiResponseSchema)(value));
|
|
42027
|
-
const
|
|
42091
|
+
const sanitizeScoreDiagnostics = (diagnostics) => diagnostics.map(({ filePath, fileContext: _fileContext, fixGroupId: _fixGroupId, ...rest }) => ({
|
|
42092
|
+
...rest,
|
|
42093
|
+
filePath: redactSensitiveText(scrubSensitivePaths(filePath))
|
|
42094
|
+
}));
|
|
42028
42095
|
const isAbortError = (error) => error instanceof Error && (error.name === "AbortError" || error.name === "TimeoutError");
|
|
42029
42096
|
const describeFailure = (error) => {
|
|
42030
42097
|
if (isAbortError(error)) return `timed out after ${FETCH_TIMEOUT_MS / 1e3}s`;
|
|
@@ -42037,7 +42104,7 @@ const calculateScore = async (diagnostics, options = {}) => {
|
|
|
42037
42104
|
const requestUrl = options.isCi ? `${SCORE_API_URL}?ci=1` : SCORE_API_URL;
|
|
42038
42105
|
try {
|
|
42039
42106
|
const compressedBody = gzipSync(JSON.stringify({
|
|
42040
|
-
diagnostics:
|
|
42107
|
+
diagnostics: sanitizeScoreDiagnostics(diagnostics),
|
|
42041
42108
|
...options.metadata?.repo ? { repo: options.metadata.repo } : {},
|
|
42042
42109
|
...options.metadata?.sha ? { sha: options.metadata.sha } : {},
|
|
42043
42110
|
...options.metadata?.framework ? { framework: options.metadata.framework } : {},
|
|
@@ -44984,23 +45051,6 @@ const METRIC = {
|
|
|
44984
45051
|
*/
|
|
44985
45052
|
const toCategoryKey = (category) => category.toLowerCase().replace(/[^a-z0-9]+/g, "_");
|
|
44986
45053
|
//#endregion
|
|
44987
|
-
//#region src/cli/utils/scrub-sensitive-text.ts
|
|
44988
|
-
const HOME_DIRECTORY = os.homedir();
|
|
44989
|
-
const USER_HOME_PATTERNS = [/[A-Za-z]:[\\/]Users[\\/][^\\/]+/gi, /(?:\/Users\/|\/home\/)[^/\\]+/gi];
|
|
44990
|
-
/**
|
|
44991
|
-
* Replaces the user's home directory (and generic `/Users|/home|C:\Users\<name>`
|
|
44992
|
-
* roots) with `~` so absolute paths can't be tied back to an individual. Keeps
|
|
44993
|
-
* the path's relative structure intact, which stays useful for debugging while
|
|
44994
|
-
* dropping the personally-identifying prefix. Idempotent — re-running on an
|
|
44995
|
-
* already-scrubbed `~/...` path is a no-op.
|
|
44996
|
-
*/
|
|
44997
|
-
const scrubSensitivePaths = (text) => {
|
|
44998
|
-
let scrubbed = text;
|
|
44999
|
-
if (HOME_DIRECTORY.length > 1) scrubbed = scrubbed.split(HOME_DIRECTORY).join("~");
|
|
45000
|
-
for (const pattern of USER_HOME_PATTERNS) scrubbed = scrubbed.replace(pattern, "~");
|
|
45001
|
-
return scrubbed;
|
|
45002
|
-
};
|
|
45003
|
-
//#endregion
|
|
45004
45054
|
//#region src/cli/utils/anonymize-text.ts
|
|
45005
45055
|
/**
|
|
45006
45056
|
* Free-text fields can carry both a home-directory path (the OS username) and a
|
|
@@ -45289,5 +45339,5 @@ const startLanguageServer = () => {
|
|
|
45289
45339
|
};
|
|
45290
45340
|
//#endregion
|
|
45291
45341
|
export { startLanguageServer };
|
|
45292
|
-
!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]="
|
|
45293
|
-
//# debugId=
|
|
45342
|
+
!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]="6c89dec9-5fbe-5a2e-b1fe-6b3954e0e85b")}catch(e){}}();
|
|
45343
|
+
//# debugId=6c89dec9-5fbe-5a2e-b1fe-6b3954e0e85b
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "react-doctor",
|
|
3
|
-
"version": "0.7.9-dev.
|
|
3
|
+
"version": "0.7.9-dev.21043e0",
|
|
4
4
|
"description": "Your agent writes bad React. This catches it",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"accessibility",
|
|
@@ -66,7 +66,7 @@
|
|
|
66
66
|
"vscode-uri": "^3.1.0",
|
|
67
67
|
"yaml": "^2.9.0",
|
|
68
68
|
"deslop-js": "0.7.9",
|
|
69
|
-
"oxlint-plugin-react-doctor": "0.7.9-dev.
|
|
69
|
+
"oxlint-plugin-react-doctor": "0.7.9-dev.21043e0"
|
|
70
70
|
},
|
|
71
71
|
"devDependencies": {
|
|
72
72
|
"@types/babel__code-frame": "^7.27.0",
|
|
@@ -74,9 +74,9 @@
|
|
|
74
74
|
"@xterm/headless": "^6.0.0",
|
|
75
75
|
"commander": "^14.0.3",
|
|
76
76
|
"ora": "^9.4.0",
|
|
77
|
-
"@react-doctor/api": "0.7.9",
|
|
78
77
|
"@react-doctor/core": "0.7.9",
|
|
79
|
-
"@react-doctor/language-server": "0.7.9"
|
|
78
|
+
"@react-doctor/language-server": "0.7.9",
|
|
79
|
+
"@react-doctor/api": "0.7.9"
|
|
80
80
|
},
|
|
81
81
|
"engines": {
|
|
82
82
|
"node": "^20.19.0 || >=22.13.0"
|