react-doctor 0.5.8-dev.970babc → 0.5.8-dev.99f2417

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/lsp.js CHANGED
@@ -6021,7 +6021,7 @@ const composePassthrough = /* @__PURE__ */ dual(2, (left, right) => (input) => {
6021
6021
  * @since 2.0.0
6022
6022
  */
6023
6023
  const Scheduler = /* @__PURE__ */ Reference("effect/Scheduler", { defaultValue: () => new MixedScheduler() });
6024
- const setImmediate = "setImmediate" in globalThis ? (f) => {
6024
+ const setImmediate$1 = "setImmediate" in globalThis ? (f) => {
6025
6025
  const timer = globalThis.setImmediate(f);
6026
6026
  return () => globalThis.clearImmediate(timer);
6027
6027
  } : (f) => {
@@ -6065,7 +6065,7 @@ var PriorityBuckets = class {
6065
6065
  var MixedScheduler = class {
6066
6066
  executionMode;
6067
6067
  setImmediate;
6068
- constructor(executionMode = "async", setImmediateFn = setImmediate) {
6068
+ constructor(executionMode = "async", setImmediateFn = setImmediate$1) {
6069
6069
  this.executionMode = executionMode;
6070
6070
  this.setImmediate = setImmediateFn;
6071
6071
  }
@@ -6090,7 +6090,7 @@ var MixedSchedulerDispatcher = class {
6090
6090
  tasks = /* @__PURE__ */ new PriorityBuckets();
6091
6091
  running = void 0;
6092
6092
  setImmediate;
6093
- constructor(setImmediateFn = setImmediate) {
6093
+ constructor(setImmediateFn = setImmediate$1) {
6094
6094
  this.setImmediate = setImmediateFn;
6095
6095
  }
6096
6096
  /**
@@ -33811,6 +33811,7 @@ const DEAD_CODE_PHASE_TIMEOUT_MS = 15e4;
33811
33811
  const LINT_PHASE_TIMEOUT_MS = 3e5;
33812
33812
  const SCAN_TOTAL_DEADLINE_MS = 9e5;
33813
33813
  const DEAD_CODE_WORKER_MAX_OLD_SPACE_MB = 8192;
33814
+ const DEAD_CODE_WORKER_MEM_BUDGET_BYTES = 2 * 1024 * 1024 * 1024;
33814
33815
  const DEAD_CODE_TIMEOUT_CEILING_MS = 6e5;
33815
33816
  const DEAD_CODE_PHASE_TIMEOUT_OVER_WORKER_MS = 3e4;
33816
33817
  const DEAD_CODE_OVERLAP_PARSE_SHARE = .4;
@@ -35053,6 +35054,7 @@ const collectStringSet = (values) => {
35053
35054
  if (!Array.isArray(values)) return /* @__PURE__ */ new Set();
35054
35055
  return new Set(values.filter((value) => typeof value === "string"));
35055
35056
  };
35057
+ const JSX_NO_UNDEF_IDENTIFIER_PATTERN = /^`([^`]+)`/;
35056
35058
  /**
35057
35059
  * Pre-compiles every stateful filter and returns a single
35058
35060
  * `apply(diagnostic)` closure that runs (in order):
@@ -35086,8 +35088,10 @@ const buildDiagnosticPipeline = (input) => {
35086
35088
  const compiledOverrides = compileIgnoreOverrides(userConfig);
35087
35089
  const textComponentNames = collectStringSet(userConfig?.textComponents);
35088
35090
  const rawTextWrapperComponentNames = collectStringSet(userConfig?.rawTextWrapperComponents);
35091
+ const runtimeGlobalNames = collectStringSet(userConfig?.runtimeGlobals);
35089
35092
  const hasTextComponents = textComponentNames.size > 0;
35090
35093
  const hasRawTextWrappers = rawTextWrapperComponentNames.size > 0;
35094
+ const hasRuntimeGlobals = runtimeGlobalNames.size > 0;
35091
35095
  const fileLinesCache = /* @__PURE__ */ new Map();
35092
35096
  const fileContextCache = /* @__PURE__ */ new Map();
35093
35097
  const libraryFileCache = /* @__PURE__ */ new Map();
@@ -35139,6 +35143,12 @@ const buildDiagnosticPipeline = (input) => {
35139
35143
  if (hasRawTextWrappers && isInsideStringOnlyWrapper(lines, diagnostic.line, diagnostic.column, rawTextWrapperComponentNames)) return true;
35140
35144
  return false;
35141
35145
  };
35146
+ const isJsxNoUndefSuppressedByConfig = (diagnostic) => {
35147
+ if (!hasRuntimeGlobals) return false;
35148
+ if (diagnostic.rule !== "jsx-no-undef") return false;
35149
+ const identifierMatch = JSX_NO_UNDEF_IDENTIFIER_PATTERN.exec(diagnostic.message);
35150
+ return identifierMatch !== null && runtimeGlobalNames.has(identifierMatch[1]);
35151
+ };
35142
35152
  return { apply: (diagnostic) => {
35143
35153
  if (shouldAutoSuppress(diagnostic)) return null;
35144
35154
  let current = diagnostic;
@@ -35163,6 +35173,7 @@ const buildDiagnosticPipeline = (input) => {
35163
35173
  if (isFileIgnoredByPatterns(current.filePath, rootDirectory, ignoredFilePatterns)) return null;
35164
35174
  if (isDiagnosticIgnoredByOverrides(current, rootDirectory, compiledOverrides)) return null;
35165
35175
  if (isRnRawTextSuppressedByConfig(current)) return null;
35176
+ if (isJsxNoUndefSuppressedByConfig(current)) return null;
35166
35177
  }
35167
35178
  if (respectInlineDisables && current.line > 0) {
35168
35179
  const lines = getFileLines(current.filePath);
@@ -35402,7 +35413,7 @@ const resolveScanConcurrency = (requested) => {
35402
35413
  if (!Number.isFinite(requested) || requested < 1) return 1;
35403
35414
  return Math.min(Math.floor(requested), 32);
35404
35415
  };
35405
- const readSystemFacts = () => ({
35416
+ const readSystemFacts$1 = () => ({
35406
35417
  availableCores: os.availableParallelism(),
35407
35418
  totalMemoryBytes: os.totalmem(),
35408
35419
  cgroupMemoryLimitBytes: readCgroupMemoryLimitBytes()
@@ -35423,7 +35434,7 @@ const readSystemFacts = () => ({
35423
35434
  * `facts` is injectable so tests exercise core-bound, memory-bound, cgroup-
35424
35435
  * limited, and ceiling cases without mocking `os` or the filesystem.
35425
35436
  */
35426
- const resolveAutoScanConcurrency = (facts = readSystemFacts()) => {
35437
+ const resolveAutoScanConcurrency = (facts = readSystemFacts$1()) => {
35427
35438
  const availableMemoryBytes = Math.min(facts.totalMemoryBytes, facts.cgroupMemoryLimitBytes ?? Number.POSITIVE_INFINITY);
35428
35439
  const memoryBoundedWorkers = Math.floor(availableMemoryBytes / PER_WORKER_MEM_BUDGET_BYTES);
35429
35440
  return resolveScanConcurrency(Math.min(facts.availableCores, memoryBoundedWorkers));
@@ -35618,6 +35629,7 @@ const STRING_ARRAY_FIELD_NAMES = [
35618
35629
  "projects",
35619
35630
  "textComponents",
35620
35631
  "rawTextWrapperComponents",
35632
+ "runtimeGlobals",
35621
35633
  "serverAuthFunctionNames"
35622
35634
  ];
35623
35635
  const SURFACE_CONTROL_FIELD_NAMES = [
@@ -36908,7 +36920,10 @@ const shouldEnableRule = (requires, tags, capabilities, ignoredTags, disabledBy)
36908
36920
  }
36909
36921
  return true;
36910
36922
  };
36911
- const checkSecurityScan = (rootDirectory, options = {}) => {
36923
+ const yieldToEventLoop = () => new Promise((resolve) => {
36924
+ setImmediate(resolve);
36925
+ });
36926
+ const createSecurityScanSession = (rootDirectory, options) => {
36912
36927
  const capabilities = options.project ? buildCapabilities(options.project) : /* @__PURE__ */ new Set();
36913
36928
  const ignoredTags = options.ignoredTags ?? /* @__PURE__ */ new Set();
36914
36929
  const enabledScanRules = REACT_DOCTOR_RULES.flatMap((entry) => {
@@ -36923,7 +36938,7 @@ const checkSecurityScan = (rootDirectory, options = {}) => {
36923
36938
  committedFilesOnly: rule.committedFilesOnly === true
36924
36939
  }];
36925
36940
  });
36926
- if (enabledScanRules.length === 0) return [];
36941
+ if (enabledScanRules.length === 0) return null;
36927
36942
  const diagnostics = [];
36928
36943
  const seen = /* @__PURE__ */ new Set();
36929
36944
  const gitIgnoredCache = /* @__PURE__ */ new Map();
@@ -36935,15 +36950,34 @@ const checkSecurityScan = (rootDirectory, options = {}) => {
36935
36950
  }
36936
36951
  return status === true;
36937
36952
  };
36938
- for (const file of collectSecurityScanFiles(rootDirectory)) for (const { entry, scan, committedFilesOnly } of enabledScanRules) for (const finding of scan(file)) {
36939
- if (committedFilesOnly && isFileGitIgnored(file)) continue;
36940
- const diagnostic = buildSecurityScanDiagnostic(finding, entry, file.relativePath);
36941
- const key = `${diagnostic.rule}:${diagnostic.filePath}:${diagnostic.line}:${diagnostic.column}:${diagnostic.message}`;
36942
- if (seen.has(key)) continue;
36943
- seen.add(key);
36944
- diagnostics.push(diagnostic);
36953
+ const scanFile = (file) => {
36954
+ for (const { entry, scan, committedFilesOnly } of enabledScanRules) for (const finding of scan(file)) {
36955
+ if (committedFilesOnly && isFileGitIgnored(file)) continue;
36956
+ const diagnostic = buildSecurityScanDiagnostic(finding, entry, file.relativePath);
36957
+ const key = `${diagnostic.rule}:${diagnostic.filePath}:${diagnostic.line}:${diagnostic.column}:${diagnostic.message}`;
36958
+ if (seen.has(key)) continue;
36959
+ seen.add(key);
36960
+ diagnostics.push(diagnostic);
36961
+ }
36962
+ };
36963
+ return {
36964
+ scanFile,
36965
+ diagnostics
36966
+ };
36967
+ };
36968
+ const checkSecurityScanCooperative = async (rootDirectory, options = {}) => {
36969
+ const session = createSecurityScanSession(rootDirectory, options);
36970
+ if (session === null) return [];
36971
+ let filesSinceYield = 0;
36972
+ for (const file of collectSecurityScanFiles(rootDirectory)) {
36973
+ session.scanFile(file);
36974
+ filesSinceYield += 1;
36975
+ if (filesSinceYield >= 16) {
36976
+ filesSinceYield = 0;
36977
+ await yieldToEventLoop();
36978
+ }
36945
36979
  }
36946
- return diagnostics;
36980
+ return session.diagnostics;
36947
36981
  };
36948
36982
  var import_picocolors = /* @__PURE__ */ __toESM((/* @__PURE__ */ __commonJSMin(((exports, module) => {
36949
36983
  let p = process || {}, argv = p.argv || [], env = p.env || {};
@@ -37160,6 +37194,74 @@ const collectDeadCodeIgnorePatterns = (rootDirectory) => {
37160
37194
  return [...seen].filter((pattern) => pattern.length > 0);
37161
37195
  };
37162
37196
  const collectDeadCodeEntryPatterns = (rootDirectory) => [...new Set(collectKnipPatterns(rootDirectory, "entry"))].filter((pattern) => pattern.length > 0);
37197
+ const readSystemFacts = () => ({
37198
+ availableCores: os.availableParallelism(),
37199
+ totalMemoryBytes: os.totalmem(),
37200
+ cgroupMemoryLimitBytes: readCgroupMemoryLimitBytes()
37201
+ });
37202
+ /**
37203
+ * How many real deslop dead-code child processes may run at once, across the
37204
+ * concurrent per-project `runInspect` fibers of one CLI run. The cap is the
37205
+ * smaller of the core count and the number of `DEAD_CODE_WORKER_MEM_BUDGET_BYTES`
37206
+ * workers that fit in available memory, floored at 1.
37207
+ *
37208
+ * On a roomy dev box / CI runner this resolves high enough that every
37209
+ * concurrently-scanned project still spawns its own worker (no serialization vs
37210
+ * the prior uncapped behavior); on a memory-constrained runner it collapses
37211
+ * toward 1, so the `withDeadCodeWorkerSlot` semaphore serializes the spawns
37212
+ * instead of oversubscribing memory with N simultaneous children — the global
37213
+ * cap the per-project spawn path lacked.
37214
+ *
37215
+ * Mirrors `resolveAutoScanConcurrency` (lint), but budgets memory per the
37216
+ * heavier dead-code worker. `facts` is injectable for tests.
37217
+ */
37218
+ const resolveDeadCodeConcurrency = (facts = readSystemFacts()) => {
37219
+ const availableMemoryBytes = Math.min(facts.totalMemoryBytes, facts.cgroupMemoryLimitBytes ?? Number.POSITIVE_INFINITY);
37220
+ const memoryBoundedWorkers = Math.floor(availableMemoryBytes / DEAD_CODE_WORKER_MEM_BUDGET_BYTES);
37221
+ return Math.max(1, Math.min(facts.availableCores, memoryBoundedWorkers));
37222
+ };
37223
+ let availableSlots = -1;
37224
+ const waiters = [];
37225
+ const releaseSlot = () => {
37226
+ const nextWaiter = waiters.shift();
37227
+ if (nextWaiter !== void 0) nextWaiter();
37228
+ else availableSlots += 1;
37229
+ };
37230
+ /**
37231
+ * Runs `task` once a dead-code worker slot is free, releasing the slot when the
37232
+ * task settles (success or failure). With a high cap (roomy machine) every
37233
+ * caller proceeds immediately; with a low cap (constrained runner) callers
37234
+ * queue and run as slots free.
37235
+ *
37236
+ * `abortSignal` short-circuits the WAIT: if it's already aborted, or fires while
37237
+ * this caller is queued, the call rejects without acquiring a slot or running
37238
+ * `task` — so a cancelled scan (e.g. lint failed) doesn't sit in the queue and
37239
+ * then spawn a child only to tear it down. A queued caller that aborts removes
37240
+ * its own waiter so a later release never hands a slot to a dead request.
37241
+ */
37242
+ const withDeadCodeWorkerSlot = async (task, abortSignal) => {
37243
+ if (abortSignal?.aborted) throw new Error("Dead-code worker aborted.");
37244
+ if (availableSlots < 0) availableSlots = resolveDeadCodeConcurrency();
37245
+ if (availableSlots > 0) availableSlots -= 1;
37246
+ else await new Promise((resolve, reject) => {
37247
+ const waiter = () => {
37248
+ abortSignal?.removeEventListener("abort", onAbort);
37249
+ resolve();
37250
+ };
37251
+ const onAbort = () => {
37252
+ const queuedIndex = waiters.indexOf(waiter);
37253
+ if (queuedIndex !== -1) waiters.splice(queuedIndex, 1);
37254
+ reject(/* @__PURE__ */ new Error("Dead-code worker aborted."));
37255
+ };
37256
+ waiters.push(waiter);
37257
+ abortSignal?.addEventListener("abort", onAbort, { once: true });
37258
+ });
37259
+ try {
37260
+ return await task();
37261
+ } finally {
37262
+ releaseSlot();
37263
+ }
37264
+ };
37163
37265
  /**
37164
37266
  * Resolves a path to its canonical, symlink-free form, falling back to
37165
37267
  * the input when it cannot be realpath'd (broken symlink, permission
@@ -37184,6 +37286,11 @@ const toCanonicalPath = (filePath) => {
37184
37286
  };
37185
37287
  const DEAD_CODE_PLUGIN = "deslop";
37186
37288
  const DEAD_CODE_CATEGORY = "Maintainability";
37289
+ const REACT_DOCTOR_TOOLCHAIN_PACKAGES = new Set([
37290
+ "react-doctor",
37291
+ "eslint-plugin-react-doctor",
37292
+ "oxlint-plugin-react-doctor"
37293
+ ]);
37187
37294
  const DEAD_CODE_WORKER_SCRIPT = `
37188
37295
  const inputChunks = [];
37189
37296
  process.stdin.on("data", (chunk) => inputChunks.push(chunk));
@@ -37450,14 +37557,17 @@ const checkDeadCode = async (options) => {
37450
37557
  if (!NFS.existsSync(Path.join(rootDirectory, "package.json"))) return [];
37451
37558
  const entryPatterns = collectDeadCodeEntryPatterns(rootDirectory);
37452
37559
  const ignorePatterns = collectDeadCodeIgnorePatterns(rootDirectory);
37453
- const result = parseDeadCodeWorkerResult(await runDeadCodeWorkerWithTimeout((options.createWorker ?? createDeadCodeWorker)({
37454
- rootDirectory,
37455
- entryPatterns,
37456
- tsConfigPath: resolveTsConfigPath(rootDirectory),
37457
- ignorePatterns,
37458
- deslopJsModuleSpecifier: options.deslopJsModuleSpecifier ?? import.meta.resolve("deslop-js"),
37459
- parseConcurrency: options.parseConcurrency
37460
- }), options.workerTimeoutMs ?? 12e4, options.abortSignal));
37560
+ const spawnAndRun = () => {
37561
+ return runDeadCodeWorkerWithTimeout((options.createWorker ?? createDeadCodeWorker)({
37562
+ rootDirectory,
37563
+ entryPatterns,
37564
+ tsConfigPath: resolveTsConfigPath(rootDirectory),
37565
+ ignorePatterns,
37566
+ deslopJsModuleSpecifier: options.deslopJsModuleSpecifier ?? import.meta.resolve("deslop-js"),
37567
+ parseConcurrency: options.parseConcurrency
37568
+ }), options.workerTimeoutMs ?? 12e4, options.abortSignal);
37569
+ };
37570
+ const result = parseDeadCodeWorkerResult(options.createWorker === void 0 ? await withDeadCodeWorkerSlot(spawnAndRun, options.abortSignal) : await spawnAndRun());
37461
37571
  const toRelative = (filePath) => toRelativeFilePath(rootDirectory, filePath);
37462
37572
  const diagnostics = [];
37463
37573
  for (const unusedFile of result.unusedFiles) diagnostics.push({
@@ -37486,6 +37596,7 @@ const checkDeadCode = async (options) => {
37486
37596
  });
37487
37597
  }
37488
37598
  for (const unusedDependency of result.unusedDependencies) {
37599
+ if (REACT_DOCTOR_TOOLCHAIN_PACKAGES.has(unusedDependency.name)) continue;
37489
37600
  const label = unusedDependency.isDevDependency ? "devDependency" : "dependency";
37490
37601
  diagnostics.push({
37491
37602
  filePath: "package.json",
@@ -40621,7 +40732,10 @@ const formatLintFailText = (reasonTag, nodeVersion) => {
40621
40732
  * diagnostics).
40622
40733
  * 2. beforeLint hook (e.g. CLI renders the project-detection block)
40623
40734
  * 3. environment checks (reduced-motion + pnpm hardening +
40624
- * expo/react-native + security scan), collected synchronously
40735
+ * expo/react-native), collected synchronously. The heavier
40736
+ * content-regex security scan is forked instead (like supply-chain
40737
+ * below) and joined before the concat, so its CPU overlaps lint
40738
+ * rather than blocking the event loop before it.
40625
40739
  * 4. The supply-chain check (Socket.dev) is forked onto a background
40626
40740
  * fiber so its ~100% network-bound time overlaps the ~100%
40627
40741
  * CPU/subprocess-bound lint pass below, collapsing two serial
@@ -40641,7 +40755,7 @@ const formatLintFailText = (reasonTag, nodeVersion) => {
40641
40755
  * order, so terminal output is identical either way; supply-chain
40642
40756
  * rides alongside without a spinner.
40643
40757
  * 6. Join the supply-chain fiber, then assemble the diagnostics in a
40644
- * FIXED order (env, supply-chain, lint, dead-code) so the output is
40758
+ * FIXED order (env, security-scan, supply-chain, lint, dead-code) so the output is
40645
40759
  * byte-identical regardless of which fiber settled first. The
40646
40760
  * viewer-permission fiber is joined later, during score-metadata
40647
40761
  * assembly (it feeds score metadata, not diagnostics). The per-element
@@ -40702,12 +40816,12 @@ const runInspect = (input, hooks = {}) => gen(function* () {
40702
40816
  ...checkPnpmHardening(scanDirectory),
40703
40817
  ...checkReactServerComponentsAdvisory(scanDirectory, project),
40704
40818
  ...checkExpoProject(scanDirectory, project),
40705
- ...checkReactNativeProject(scanDirectory, project),
40706
- ...checkSecurityScan(scanDirectory, {
40707
- project,
40708
- ignoredTags: input.ignoredTags
40709
- })
40819
+ ...checkReactNativeProject(scanDirectory, project)
40710
40820
  ])));
40821
+ const securityScanFiber = yield* forkChild(runCollect(applyPerElementPipeline(isDiffMode ? empty$4 : unwrap(promise(() => checkSecurityScanCooperative(scanDirectory, {
40822
+ project,
40823
+ ignoredTags: input.ignoredTags
40824
+ })).pipe(map$3((diagnostics) => fromIterable$1(diagnostics)))))).pipe(withSpan("SecurityScan.run")));
40711
40825
  const shouldRunSupplyChain = !isDiffMode || (input.supplyChainManifestChanged ?? false);
40712
40826
  const supplyChainOverlapTimeout = yield* SupplyChainOverlapTimeoutMs;
40713
40827
  const supplyChainFiber = yield* forkChild(shouldRunSupplyChain ? runCollect(applyPerElementPipeline(supplyChainService.run({
@@ -40843,9 +40957,11 @@ const runInspect = (input, hooks = {}) => gen(function* () {
40843
40957
  else yield* scanProgress.succeed(`Scanned ${scannedFilesLabel} in ${scanElapsedSeconds}s${workerCountSuffix}`);
40844
40958
  const supplyChainResult = yield* join(supplyChainFiber);
40845
40959
  const supplyChainCollected = supplyChainResult.diagnostics;
40960
+ const securityScanCollected = yield* join(securityScanFiber);
40846
40961
  yield* reporterService.finalize;
40847
40962
  const finalDiagnostics = sortDiagnosticsStable(assignFixGroups([
40848
40963
  ...envCollected,
40964
+ ...securityScanCollected,
40849
40965
  ...supplyChainCollected,
40850
40966
  ...lintCollected,
40851
40967
  ...deadCodeCollected
@@ -42947,7 +43063,9 @@ const METRIC = {
42947
43063
  lspSessionStarted: "lsp.session.started",
42948
43064
  lspScanCompleted: "lsp.scan.completed",
42949
43065
  lspScanDuration: "lsp.scan.duration",
42950
- lspScanDiagnostics: "lsp.scan.diagnostics"
43066
+ lspScanDiagnostics: "lsp.scan.diagnostics",
43067
+ aiTrainingWarningShown: "ai.training.warning_shown",
43068
+ jsonOutUsed: "json.out_used"
42951
43069
  };
42952
43070
  //#endregion
42953
43071
  //#region src/cli/utils/to-category-key.ts
@@ -43264,5 +43382,5 @@ const startLanguageServer = () => {
43264
43382
  };
43265
43383
  //#endregion
43266
43384
  export { startLanguageServer };
43267
- !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]="d12f3c5d-14fd-59ba-9d8a-7e3f589c88ad")}catch(e){}}();
43268
- //# debugId=d12f3c5d-14fd-59ba-9d8a-7e3f589c88ad
43385
+ !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]="0423aeac-9239-56af-8e8c-ada39e5172dd")}catch(e){}}();
43386
+ //# debugId=0423aeac-9239-56af-8e8c-ada39e5172dd
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-doctor",
3
- "version": "0.5.8-dev.970babc",
3
+ "version": "0.5.8-dev.99f2417",
4
4
  "description": "Your agent writes bad React. This catches it",
5
5
  "keywords": [
6
6
  "accessibility",
@@ -20,7 +20,7 @@
20
20
  "bugs": {
21
21
  "url": "https://github.com/millionco/react-doctor/issues"
22
22
  },
23
- "license": "MIT",
23
+ "license": "SEE LICENSE IN LICENSE",
24
24
  "author": "Million Software, Inc",
25
25
  "repository": {
26
26
  "type": "git",
@@ -34,7 +34,8 @@
34
34
  "bin/**",
35
35
  "dist/**/*.js",
36
36
  "dist/**/*.d.ts",
37
- "dist/skills/**"
37
+ "dist/skills/**",
38
+ "LICENSE"
38
39
  ],
39
40
  "type": "module",
40
41
  "sideEffects": false,
@@ -59,12 +60,12 @@
59
60
  "magicast": "^0.5.3",
60
61
  "oxlint": ">=1.66.0 <1.67.0",
61
62
  "prompts": "^2.4.2",
62
- "typescript": ">=5.0.4 <7",
63
+ "typescript": ">=5.0.4 <6",
63
64
  "vscode-languageserver": "^9.0.1",
64
65
  "vscode-languageserver-textdocument": "^1.0.12",
65
66
  "vscode-uri": "^3.1.0",
66
67
  "deslop-js": "0.5.8",
67
- "oxlint-plugin-react-doctor": "0.5.8-dev.970babc"
68
+ "oxlint-plugin-react-doctor": "0.5.8-dev.99f2417"
68
69
  },
69
70
  "devDependencies": {
70
71
  "@types/babel__code-frame": "^7.27.0",
@@ -72,9 +73,9 @@
72
73
  "@xterm/headless": "^6.0.0",
73
74
  "commander": "^14.0.3",
74
75
  "ora": "^9.4.0",
76
+ "@react-doctor/api": "0.5.8",
75
77
  "@react-doctor/core": "0.5.8",
76
- "@react-doctor/language-server": "0.5.8",
77
- "@react-doctor/api": "0.5.8"
78
+ "@react-doctor/language-server": "0.5.8"
78
79
  },
79
80
  "engines": {
80
81
  "node": "^20.19.0 || >=22.13.0"