react-doctor 0.9.13 → 0.9.14-dev.bcf8062

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.
Files changed (46) hide show
  1. package/dist/_react-doctor_require-typescript-DnwIzXJn.js +7 -0
  2. package/dist/{active-scan-abort-registry-DwG6tSPy.js → active-scan-abort-registry-B72ASBUh.js} +3 -3
  3. package/dist/build-section-divider-v7NN_cR8.js +80 -0
  4. package/dist/{ci-DqnZCnrL.js → ci-BnQkEEV1.js} +12 -12
  5. package/dist/cli.js +25 -26
  6. package/dist/constants-CKOk_Fa9.js +23 -0
  7. package/dist/{design-DqUidb1f.js → design-Du1rV5hV.js} +4 -4
  8. package/dist/{devtools-CC2PAZ85.js → devtools-DOdrAPkZ.js} +3 -3
  9. package/dist/duplicate-jsx-worker.d.ts +1 -0
  10. package/dist/duplicate-jsx-worker.js +636 -0
  11. package/dist/{exit-gracefully-CrpeIbra.js → exit-gracefully-D9ffPCDJ.js} +7 -7
  12. package/dist/{get-east-asian-width-Bv2TD3Xj.js → get-east-asian-width-CM5BOEC-.js} +3 -3
  13. package/dist/{handle-error-BEYYtsCl.js → handle-error-BWHTahSo.js} +5 -5
  14. package/dist/index.js +2329 -1616
  15. package/dist/{inspect-BjMaC5WV.js → inspect-fWFs2jtk.js} +25 -21
  16. package/dist/{install-DxLmASQ5.js → install-DWpPYvxU.js} +9 -9
  17. package/dist/{install-doctor-script-4EWviJL8.js → install-doctor-script-wNnu5y_f.js} +5 -5
  18. package/dist/{install-github-workflow-BPznUbbo.js → install-github-workflow-DsgMnbqe.js} +5 -5
  19. package/dist/{install-react-doctor-Baq9hjoF.js → install-react-doctor-hFwI2elO.js} +8 -8
  20. package/dist/{jsx-runtime-DvynQ_wu.js → jsx-runtime-DCJqkm-B.js} +7 -7
  21. package/dist/oxlint-worker.d.ts +1 -0
  22. package/dist/oxlint-worker.js +135 -0
  23. package/dist/{print-branded-header-DSB6i3kk.js → print-branded-header-BcXGdtml.js} +4 -4
  24. package/dist/project-analysis-worker.js +457 -470
  25. package/dist/{prompt-runtime-scan-url-BibDt9O1.js → prompt-runtime-scan-url-s4NKC5nM.js} +5 -5
  26. package/dist/{read-object-file-DfWpkle4.js → read-object-file-Be3X79OD.js} +4 -4
  27. package/dist/{record-metric-Cckscwg_.js → record-metric-D8ltm-Oh.js} +1823 -1059
  28. package/dist/{report-error-C1YnoRNl.js → report-error-5LSXHGJq.js} +7 -7
  29. package/dist/{report-workflow-result-IdGRoBFN.js → report-workflow-result-2aLf7RhF.js} +5 -5
  30. package/dist/{resolve-scope-Bb6fljxd.js → resolve-scope-BXJ4WEdf.js} +6 -6
  31. package/dist/{rules-BcFekwN4.js → rules-C71aHICA.js} +6 -6
  32. package/dist/{run-scan-app-CKHynQx8.js → run-scan-app-BqzvDO2G.js} +28 -22
  33. package/dist/{runtime-scan-7Y_mbqEa.js → runtime-scan-TcGr2CHS.js} +14 -14
  34. package/dist/{sanitize-runtime-url-DzyBLbi3.js → sanitize-runtime-url-LBQ4amZg.js} +5 -5
  35. package/dist/{scan-DQCwBx6p.js → scan-8j0aKndg.js} +9 -9
  36. package/dist/{semver-DFtnEmN-.js → semver-DlmXks31.js} +3 -3
  37. package/dist/{should-fail-scan-gate-BYPsKIde.js → should-fail-scan-gate-fjfa2sYx.js} +116 -72
  38. package/dist/{should-skip-prompts-CKkbB3rC.js → should-skip-prompts-BZZxI1vY.js} +4 -4
  39. package/dist/{should-use-tui-Crfoao-l.js → should-use-tui-C59qAiOG.js} +4 -4
  40. package/dist/{telemetry-runtime-DKJyjz9o.js → telemetry-runtime-CmlSXXfi.js} +153 -5
  41. package/dist/unwrap-typescript-expression-CbO_6kmC.js +14 -0
  42. package/dist/{version-CMkUAGmw.js → version-DRDcTlA9.js} +4 -4
  43. package/dist/{why-By3I6_Ex.js → why-DthVqP00.js} +4 -4
  44. package/dist/{with-run-span-DxFGyW7k.js → with-run-span-D4-folvM.js} +5 -5
  45. package/package.json +6 -6
  46. package/dist/build-section-divider-DELfSn3p.js +0 -216
@@ -1,6 +1,6 @@
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]="dac9c107-44f1-590e-9084-db7490a258d5")}catch(e){}}();
3
- import { $t as layerObservability, Cr as messageFromUnknown, Jn as makeUnsafe, Rn as runPromise, Un as buildWithScope, Xn as void_, Xt as isReactDoctorError, Yt as isProjectDiscoveryError, _ as VERSION, br as isErrnoException, i as isTelemetryEnabled, kn as make, qn as close, z as CliInputError, zn as runSync } from "./record-metric-Cckscwg_.js";
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]="fe9fd3ac-1722-508e-b83e-d30968bc877b")}catch(e){}}();
3
+ import { Bn as runPromise, Gn as buildWithScope, N as SENTRY_FLUSH_TIMEOUT_MS, Qn as void_, Qt as isReactDoctorError, Vn as runSync, Xn as makeUnsafe, Yn as close, Zt as isProjectDiscoveryError, _ as VERSION, _n as scrubSensitivePaths, a as isEnvFlagEnabled, ar as messageFromUnknown, i as isTelemetryEnabled, jn as make, mt as anonymizeText, nr as isErrnoException, o as buildSentryScope, pt as anonymizeInPlace, tn as layerObservability, z as CliInputError } from "./record-metric-D8ltm-Oh.js";
4
4
  //#region src/cli/utils/is-environment-error.ts
5
5
  const ENVIRONMENT_ERROR_CODES = new Set([
6
6
  "EACCES",
@@ -144,6 +144,154 @@ const formatNpmCacheCorruptionError = (error) => {
144
144
  */
145
145
  const isExpectedUserError = (error) => error instanceof CliInputError || isProjectDiscoveryError(error) || isEnvironmentError(error) || isNpmCacheCorruptionError(error) || isReactDoctorError(error) && (error.reason._tag === "GitBaseBranchInvalid" || error.reason._tag === "GitBaseBranchMissing");
146
146
  //#endregion
147
+ //#region src/cli/utils/scrub-sentry-event.ts
148
+ /**
149
+ * Anonymizes a Sentry event (error or transaction) before it leaves the
150
+ * machine. Strips identity the SDK attaches automatically — the IP-bearing
151
+ * `user`, the `server_name`, and the device `name` (all hostnames) — drops
152
+ * captured local variables (unbounded, un-anonymizable user data), and scrubs
153
+ * home-directory paths + known secrets/emails from every remaining string:
154
+ * messages, stack frames, breadcrumbs, contexts/extra/tags, and span
155
+ * attributes (e.g. the `inspect.directory` path on the bridged `runInspect`
156
+ * span).
157
+ *
158
+ * Wired into both `beforeSend` and `beforeSendTransaction`. If scrubbing ever
159
+ * throws, the event is dropped (`null`) rather than risk sending un-anonymized
160
+ * data — telemetry is best-effort, privacy is not.
161
+ */
162
+ const scrubSentryEvent = (event) => {
163
+ try {
164
+ delete event.server_name;
165
+ delete event.user;
166
+ const device = event.contexts?.device;
167
+ if (device) delete device.name;
168
+ if (event.contexts) anonymizeInPlace(event.contexts);
169
+ if (event.extra) anonymizeInPlace(event.extra);
170
+ if (event.tags) anonymizeInPlace(event.tags);
171
+ if (typeof event.message === "string") event.message = anonymizeText(event.message);
172
+ for (const breadcrumb of event.breadcrumbs ?? []) {
173
+ if (typeof breadcrumb.message === "string") breadcrumb.message = anonymizeText(breadcrumb.message);
174
+ if (breadcrumb.data) anonymizeInPlace(breadcrumb.data);
175
+ }
176
+ for (const exception of event.exception?.values ?? []) {
177
+ if (typeof exception.value === "string") exception.value = anonymizeText(exception.value);
178
+ for (const frame of exception.stacktrace?.frames ?? []) {
179
+ delete frame.vars;
180
+ if (typeof frame.filename === "string") frame.filename = scrubSensitivePaths(frame.filename);
181
+ if (typeof frame.abs_path === "string") frame.abs_path = scrubSensitivePaths(frame.abs_path);
182
+ if (typeof frame.module === "string") frame.module = scrubSensitivePaths(frame.module);
183
+ }
184
+ }
185
+ for (const span of event.spans ?? []) {
186
+ if (typeof span.description === "string") span.description = anonymizeText(span.description);
187
+ if (span.data) anonymizeInPlace(span.data);
188
+ }
189
+ return event;
190
+ } catch {
191
+ return null;
192
+ }
193
+ };
194
+ //#endregion
195
+ //#region src/cli/utils/sentry-config.ts
196
+ /**
197
+ * Shared Sentry configuration resolution — release, environment, and tracing
198
+ * sample rate — derived from `VERSION` and the standard `SENTRY_*` env
199
+ * overrides. Lives apart from `instrument.ts` so this resolution remains
200
+ * independently testable.
201
+ */
202
+ /**
203
+ * A version is a "dev" build when it's the unbuilt placeholder (`0.0.0`) or
204
+ * carries a prerelease suffix (e.g. the `-dev.<sha>` snapshots published from
205
+ * CI). Everything else is a real, tagged release.
206
+ */
207
+ const isDevVersion = (version) => version === "0.0.0" || version.includes("-");
208
+ /**
209
+ * Sentry release identifier. `react-doctor@<version>` keeps it unique within
210
+ * the org and — crucially — matches the value `scripts/sentry-sourcemaps.mjs`
211
+ * uploads source-map artifacts under, so stack frames symbolicate. Honors the
212
+ * standard `SENTRY_RELEASE` override.
213
+ */
214
+ const resolveSentryRelease = () => process.env.SENTRY_RELEASE || `react-doctor@0.9.14-dev.bcf8062`;
215
+ /**
216
+ * Deployment environment shown in Sentry's environment filter. Defaults to
217
+ * `production` for tagged releases and `development` for dev/unbuilt versions,
218
+ * overridable via the standard `SENTRY_ENVIRONMENT` env var.
219
+ */
220
+ const resolveSentryEnvironment = () => process.env.SENTRY_ENVIRONMENT || (isDevVersion("0.9.14-dev.bcf8062") ? "development" : "production");
221
+ //#endregion
222
+ //#region src/instrument.ts
223
+ let sentryPromise = null;
224
+ /**
225
+ * Resolves the initialized Sentry SDK, or `null` when Sentry was never
226
+ * initialized (`--no-score`, tests, a missing DSN) or failed to load. Every
227
+ * Sentry consumer goes through here so the SDK's module graph (hundreds of
228
+ * `@sentry/*` + `@opentelemetry/*` files) is loaded off the CLI's critical
229
+ * startup path.
230
+ */
231
+ const getSentry = () => sentryPromise ?? Promise.resolve(null);
232
+ /**
233
+ * Flushes queued Sentry events (errors + transactions) before the CLI exits, so
234
+ * the success-path transaction is delivered. A no-op when Sentry was never
235
+ * initialized, and it swallows transport failures so telemetry can never mask
236
+ * the user's result.
237
+ */
238
+ const flushSentry = async () => {
239
+ const Sentry = await getSentry();
240
+ if (!Sentry?.isInitialized()) return;
241
+ try {
242
+ await Sentry.flush(SENTRY_FLUSH_TIMEOUT_MS);
243
+ } catch {}
244
+ };
245
+ const initializeSentryModule = (Sentry) => {
246
+ const { tags, contexts } = buildSentryScope();
247
+ try {
248
+ Sentry.init({
249
+ dsn: process.env.SENTRY_DSN || "https://f253d570240a59b8dbd77b7a548ef133@o4510226365743104.ingest.us.sentry.io/4511487817809920",
250
+ release: resolveSentryRelease(),
251
+ environment: resolveSentryEnvironment(),
252
+ sendDefaultPii: false,
253
+ tracesSampleRate: 0,
254
+ registerEsmLoaderHooks: false,
255
+ debug: isEnvFlagEnabled(process.env.SENTRY_DEBUG),
256
+ initialScope: {
257
+ tags,
258
+ contexts
259
+ },
260
+ beforeSend: (event, hint) => isExpectedUserError(hint.originalException) ? null : scrubSentryEvent(event)
261
+ });
262
+ } catch {}
263
+ return Sentry;
264
+ };
265
+ /**
266
+ * Initializes the Sentry Node SDK for CLI crash reporting. Invoked as the first
267
+ * statement of the CLI entry (`cli/index.ts`); the SDK is imported dynamically
268
+ * so its module graph loads in the background while the command starts, and the
269
+ * SDK's global `uncaughtException` / `unhandledRejection` handlers arm as soon
270
+ * as it lands. Consumers await `getSentry()` and so observe the initialized SDK.
271
+ *
272
+ * Performance tracing is off: spans are exported to Axiom instead (see
273
+ * `telemetry-runtime.ts`), and Effect has a single `Tracer` reference, so the
274
+ * two backends are mutually exclusive. Sentry keeps what it is good at —
275
+ * symbolicated stack traces, issue grouping, and a quotable event id — while
276
+ * crashes carry the Axiom trace id as a tag so an issue pivots into its trace.
277
+ *
278
+ * Exported as a function rather than a bare side-effecting import because the
279
+ * package declares `"sideEffects": false`, which lets the bundler tree-shake
280
+ * side-effect-only modules. An explicit call keeps the initialization in the
281
+ * published `dist/cli.js`.
282
+ *
283
+ * Scoped to the CLI application only — the programmatic `@react-doctor/api`
284
+ * library never initializes Sentry, so importing `diagnose()` into a consumer
285
+ * app can't hijack their telemetry.
286
+ *
287
+ * Configuration is environment-overridable for self-hosting and tuning:
288
+ * `SENTRY_DSN`, `SENTRY_ENVIRONMENT`, `SENTRY_RELEASE`, and `SENTRY_DEBUG`.
289
+ */
290
+ const initializeSentry = () => {
291
+ if (sentryPromise !== null || !isTelemetryEnabled()) return;
292
+ sentryPromise = import("@sentry/node").then(initializeSentryModule, () => null);
293
+ };
294
+ //#endregion
147
295
  //#region src/cli/utils/resolve-axiom-telemetry-options.ts
148
296
  /**
149
297
  * Resolves the credentials for first-party Axiom export, or `null` when this
@@ -245,7 +393,7 @@ const shutdownTelemetry = async () => {
245
393
  return pendingShutdown;
246
394
  };
247
395
  //#endregion
248
- export { isNpmCacheCorruptionError as a, formatNpmCacheCorruptionError as i, shutdownTelemetry as n, formatEnvironmentError as o, isExpectedUserError as r, isEnvironmentError as s, getTelemetryContext as t };
396
+ export { initializeSentry as a, isNpmCacheCorruptionError as c, getSentry as i, formatEnvironmentError as l, shutdownTelemetry as n, isExpectedUserError as o, flushSentry as r, formatNpmCacheCorruptionError as s, getTelemetryContext as t, isEnvironmentError as u };
249
397
 
250
- //# sourceMappingURL=telemetry-runtime-DKJyjz9o.js.map
251
- //# debugId=dac9c107-44f1-590e-9084-db7490a258d5
398
+ //# sourceMappingURL=telemetry-runtime-CmlSXXfi.js.map
399
+ //# debugId=fe9fd3ac-1722-508e-b83e-d30968bc877b
@@ -0,0 +1,14 @@
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]="3f276705-c59b-5820-9c67-3379b6bd67f5")}catch(e){}}();
3
+ import { t as _react_doctor_require_typescript_default } from "./_react-doctor_require-typescript-DnwIzXJn.js";
4
+ //#region ../core/src/utils/unwrap-typescript-expression.ts
5
+ const unwrapTypescriptExpression = (expression) => {
6
+ let currentExpression = expression;
7
+ while (_react_doctor_require_typescript_default.isParenthesizedExpression(currentExpression) || _react_doctor_require_typescript_default.isAsExpression(currentExpression) || _react_doctor_require_typescript_default.isSatisfiesExpression(currentExpression) || _react_doctor_require_typescript_default.isNonNullExpression(currentExpression) || _react_doctor_require_typescript_default.isTypeAssertionExpression(currentExpression)) currentExpression = currentExpression.expression;
8
+ return currentExpression;
9
+ };
10
+ //#endregion
11
+ export { unwrapTypescriptExpression as t };
12
+
13
+ //# sourceMappingURL=unwrap-typescript-expression-CbO_6kmC.js.map
14
+ //# debugId=3f276705-c59b-5820-9c67-3379b6bd67f5
@@ -1,6 +1,6 @@
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]="f4590472-0d55-592b-a812-7ba4c0c0beb0")}catch(e){}}();
3
- import { T as METRIC, _ as VERSION, t as recordCount } from "./record-metric-Cckscwg_.js";
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]="729a8ce2-93e0-5d5c-a2e3-5c54ca419d1c")}catch(e){}}();
3
+ import { T as METRIC, _ as VERSION, t as recordCount } from "./record-metric-D8ltm-Oh.js";
4
4
  //#region src/cli/commands/version.ts
5
5
  /**
6
6
  * oclif-style version line. 12-factor CLI Apps (#3, "What version am I
@@ -17,5 +17,5 @@ const versionAction = () => {
17
17
  //#endregion
18
18
  export { versionAction };
19
19
 
20
- //# sourceMappingURL=version-CMkUAGmw.js.map
21
- //# debugId=f4590472-0d55-592b-a812-7ba4c0c0beb0
20
+ //# sourceMappingURL=version-DRDcTlA9.js.map
21
+ //# debugId=729a8ce2-93e0-5d5c-a2e3-5c54ca419d1c
@@ -1,6 +1,6 @@
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]="e6bbeaeb-2371-57ec-a6ec-c59445174339")}catch(e){}}();
3
- import { t as inspectAction } from "./inspect-BjMaC5WV.js";
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]="599b7d13-6027-5233-99c3-51ba590f9644")}catch(e){}}();
3
+ import { t as inspectAction } from "./inspect-fWFs2jtk.js";
4
4
  //#region src/cli/commands/why.ts
5
5
  /**
6
6
  * `why <file:line>` — explains why a rule fired (or why a suppression didn't
@@ -17,5 +17,5 @@ const whyAction = async (location, options) => {
17
17
  //#endregion
18
18
  export { whyAction };
19
19
 
20
- //# sourceMappingURL=why-By3I6_Ex.js.map
21
- //# debugId=e6bbeaeb-2371-57ec-a6ec-c59445174339
20
+ //# sourceMappingURL=why-DthVqP00.js.map
21
+ //# debugId=599b7d13-6027-5233-99c3-51ba590f9644
@@ -1,7 +1,7 @@
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]="f0d00082-4926-5162-a9c8-d1ad3a7f6a66")}catch(e){}}();
3
- import { D as NANOSECONDS_PER_MILLISECOND, In as provideContext, Xn as void_, Yn as fail, c as setSentryProjectInfo, jn as makeSpan, o as buildSentryScope, r as toSpanAttributes, s as buildSentryProjectContext, zn as runSync } from "./record-metric-Cckscwg_.js";
4
- import { t as getTelemetryContext } from "./telemetry-runtime-DKJyjz9o.js";
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]="4c27c659-0022-52b6-bafa-461e7268b9f5")}catch(e){}}();
3
+ import { D as NANOSECONDS_PER_MILLISECOND, Nn as makeSpan, Qn as void_, Rn as provideContext, Vn as runSync, Zn as fail, c as setSentryProjectInfo, o as buildSentryScope, r as toSpanAttributes, s as buildSentryProjectContext } from "./record-metric-D8ltm-Oh.js";
4
+ import { t as getTelemetryContext } from "./telemetry-runtime-CmlSXXfi.js";
5
5
  import { i as setActiveRunTrace, r as recordRunTraceId } from "./active-run-trace-dlIZeEvb.js";
6
6
  //#region src/cli/utils/with-run-span.ts
7
7
  /**
@@ -106,5 +106,5 @@ const recordSentryProjectContext = (projectInfo, rootSpan, options = {}) => {
106
106
  //#endregion
107
107
  export { resetSentryRunState as n, withRunSpan as r, recordSentryProjectContext as t };
108
108
 
109
- //# sourceMappingURL=with-run-span-DxFGyW7k.js.map
110
- //# debugId=f0d00082-4926-5162-a9c8-d1ad3a7f6a66
109
+ //# sourceMappingURL=with-run-span-D4-folvM.js.map
110
+ //# debugId=4c27c659-0022-52b6-bafa-461e7268b9f5
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-doctor",
3
- "version": "0.9.13",
3
+ "version": "0.9.14-dev.bcf8062",
4
4
  "description": "Your agent writes bad React. This catches it",
5
5
  "keywords": [
6
6
  "accessibility",
@@ -60,15 +60,15 @@
60
60
  "is-unicode-supported": "^2.1.0",
61
61
  "jiti": "^2.7.0",
62
62
  "magicast": "^0.5.3",
63
- "oxc-parser": "^0.146.0",
63
+ "oxc-parser": "^0.148.0",
64
64
  "oxc-resolver": "^11.24.2",
65
- "oxlint": ">=1.79.0 <1.80.0",
65
+ "oxlint": ">=1.81.0 <1.82.0",
66
66
  "playwright-core": "^1.62.1",
67
67
  "prompts": "^2.4.2",
68
68
  "typescript": ">=5.0.4 <6",
69
69
  "yaml": "^2.9.0",
70
70
  "yoga-layout": "~3.2.1",
71
- "oxlint-plugin-react-doctor": "0.9.13"
71
+ "oxlint-plugin-react-doctor": "0.9.14-dev.bcf8062"
72
72
  },
73
73
  "devDependencies": {
74
74
  "@types/babel__code-frame": "^7.27.0",
@@ -81,8 +81,8 @@
81
81
  "ora": "^9.4.0",
82
82
  "react": "19.2.5",
83
83
  "react-devtools-core": "^7.0.1",
84
- "@react-doctor/api": "0.9.13",
85
- "@react-doctor/core": "0.9.13"
84
+ "@react-doctor/api": "0.9.14",
85
+ "@react-doctor/core": "0.9.14"
86
86
  },
87
87
  "engines": {
88
88
  "node": "^20.19.0 || >=22.13.0"
@@ -1,216 +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]="fc992092-cb60-5165-a621-058e9c73aa99")}catch(e){}}();
3
- import { Kt as highlighter, N as SENTRY_FLUSH_TIMEOUT_MS, a as isEnvFlagEnabled, er as CANONICAL_GITHUB_URL, ft as anonymizeInPlace, hn as scrubSensitivePaths, i as isTelemetryEnabled, o as buildSentryScope, or as DOCS_URL, pt as anonymizeText } from "./record-metric-Cckscwg_.js";
4
- import { r as isExpectedUserError } from "./telemetry-runtime-DKJyjz9o.js";
5
- import * as Sentry from "@sentry/node";
6
- //#region src/cli/utils/scrub-sentry-event.ts
7
- /**
8
- * Anonymizes a Sentry event (error or transaction) before it leaves the
9
- * machine. Strips identity the SDK attaches automatically — the IP-bearing
10
- * `user`, the `server_name`, and the device `name` (all hostnames) — drops
11
- * captured local variables (unbounded, un-anonymizable user data), and scrubs
12
- * home-directory paths + known secrets/emails from every remaining string:
13
- * messages, stack frames, breadcrumbs, contexts/extra/tags, and span
14
- * attributes (e.g. the `inspect.directory` path on the bridged `runInspect`
15
- * span).
16
- *
17
- * Wired into both `beforeSend` and `beforeSendTransaction`. If scrubbing ever
18
- * throws, the event is dropped (`null`) rather than risk sending un-anonymized
19
- * data — telemetry is best-effort, privacy is not.
20
- */
21
- const scrubSentryEvent = (event) => {
22
- try {
23
- delete event.server_name;
24
- delete event.user;
25
- const device = event.contexts?.device;
26
- if (device) delete device.name;
27
- if (event.contexts) anonymizeInPlace(event.contexts);
28
- if (event.extra) anonymizeInPlace(event.extra);
29
- if (event.tags) anonymizeInPlace(event.tags);
30
- if (typeof event.message === "string") event.message = anonymizeText(event.message);
31
- for (const breadcrumb of event.breadcrumbs ?? []) {
32
- if (typeof breadcrumb.message === "string") breadcrumb.message = anonymizeText(breadcrumb.message);
33
- if (breadcrumb.data) anonymizeInPlace(breadcrumb.data);
34
- }
35
- for (const exception of event.exception?.values ?? []) {
36
- if (typeof exception.value === "string") exception.value = anonymizeText(exception.value);
37
- for (const frame of exception.stacktrace?.frames ?? []) {
38
- delete frame.vars;
39
- if (typeof frame.filename === "string") frame.filename = scrubSensitivePaths(frame.filename);
40
- if (typeof frame.abs_path === "string") frame.abs_path = scrubSensitivePaths(frame.abs_path);
41
- if (typeof frame.module === "string") frame.module = scrubSensitivePaths(frame.module);
42
- }
43
- }
44
- for (const span of event.spans ?? []) {
45
- if (typeof span.description === "string") span.description = anonymizeText(span.description);
46
- if (span.data) anonymizeInPlace(span.data);
47
- }
48
- return event;
49
- } catch {
50
- return null;
51
- }
52
- };
53
- //#endregion
54
- //#region src/cli/utils/sentry-config.ts
55
- /**
56
- * Shared Sentry configuration resolution — release, environment, and tracing
57
- * sample rate — derived from `VERSION` and the standard `SENTRY_*` env
58
- * overrides. Lives apart from `instrument.ts` so this resolution remains
59
- * independently testable.
60
- */
61
- /**
62
- * A version is a "dev" build when it's the unbuilt placeholder (`0.0.0`) or
63
- * carries a prerelease suffix (e.g. the `-dev.<sha>` snapshots published from
64
- * CI). Everything else is a real, tagged release.
65
- */
66
- const isDevVersion = (version) => version === "0.0.0" || version.includes("-");
67
- /**
68
- * Sentry release identifier. `react-doctor@<version>` keeps it unique within
69
- * the org and — crucially — matches the value `scripts/sentry-sourcemaps.mjs`
70
- * uploads source-map artifacts under, so stack frames symbolicate. Honors the
71
- * standard `SENTRY_RELEASE` override.
72
- */
73
- const resolveSentryRelease = () => process.env.SENTRY_RELEASE || `react-doctor@0.9.13`;
74
- /**
75
- * Deployment environment shown in Sentry's environment filter. Defaults to
76
- * `production` for tagged releases and `development` for dev/unbuilt versions,
77
- * overridable via the standard `SENTRY_ENVIRONMENT` env var.
78
- */
79
- const resolveSentryEnvironment = () => process.env.SENTRY_ENVIRONMENT || (isDevVersion("0.9.13") ? "development" : "production");
80
- //#endregion
81
- //#region src/instrument.ts
82
- let isInitialized = false;
83
- /**
84
- * Flushes queued Sentry events (errors + transactions) before the CLI exits, so
85
- * the success-path transaction is delivered. A no-op when Sentry was never
86
- * initialized, and it swallows transport failures so telemetry can never mask
87
- * the user's result.
88
- */
89
- const flushSentry = async () => {
90
- if (!Sentry.isInitialized()) return;
91
- try {
92
- await Sentry.flush(SENTRY_FLUSH_TIMEOUT_MS);
93
- } catch {}
94
- };
95
- /**
96
- * Initializes the Sentry Node SDK for CLI crash reporting and performance
97
- * crash reporting. Invoked as the first statement of the CLI entry
98
- * (`cli/index.ts`) so the SDK's global `uncaughtException` /
99
- * `unhandledRejection` handlers are armed before any command runs.
100
- *
101
- * Performance tracing is off: spans are exported to Axiom instead (see
102
- * `telemetry-runtime.ts`), and Effect has a single `Tracer` reference, so the
103
- * two backends are mutually exclusive. Sentry keeps what it is good at —
104
- * symbolicated stack traces, issue grouping, and a quotable event id — while
105
- * crashes carry the Axiom trace id as a tag so an issue pivots into its trace.
106
- *
107
- * Exported as a function rather than a bare side-effecting import because the
108
- * package declares `"sideEffects": false`, which lets the bundler tree-shake
109
- * side-effect-only modules. An explicit call keeps the initialization in the
110
- * published `dist/cli.js`.
111
- *
112
- * Scoped to the CLI application only — the programmatic `@react-doctor/api`
113
- * library never initializes Sentry, so importing `diagnose()` into a consumer
114
- * app can't hijack their telemetry.
115
- *
116
- * Configuration is environment-overridable for self-hosting and tuning:
117
- * `SENTRY_DSN`, `SENTRY_ENVIRONMENT`, `SENTRY_RELEASE`, and `SENTRY_DEBUG`.
118
- */
119
- const initializeSentry = () => {
120
- if (isInitialized || !isTelemetryEnabled()) return;
121
- isInitialized = true;
122
- const { tags, contexts } = buildSentryScope();
123
- try {
124
- Sentry.init({
125
- dsn: process.env.SENTRY_DSN || "https://f253d570240a59b8dbd77b7a548ef133@o4510226365743104.ingest.us.sentry.io/4511487817809920",
126
- release: resolveSentryRelease(),
127
- environment: resolveSentryEnvironment(),
128
- sendDefaultPii: false,
129
- tracesSampleRate: 0,
130
- debug: isEnvFlagEnabled(process.env.SENTRY_DEBUG),
131
- initialScope: {
132
- tags,
133
- contexts
134
- },
135
- beforeSend: (event, hint) => isExpectedUserError(hint.originalException) ? null : scrubSentryEvent(event)
136
- });
137
- } catch {}
138
- };
139
- //#endregion
140
- //#region src/cli/utils/resolve-measure-width.ts
141
- const resolveClampedWidth = (input) => {
142
- const terminalColumns = process.stdout.columns;
143
- if (!terminalColumns || terminalColumns <= 0) return input.fullWidth;
144
- const availableColumns = terminalColumns - input.reservedColumns;
145
- return Math.max(input.minWidth, Math.min(input.fullWidth, availableColumns));
146
- };
147
- const resolveMeasureWidth = (reservedColumns = 0) => resolveClampedWidth({
148
- reservedColumns,
149
- fullWidth: 60,
150
- minWidth: 24
151
- });
152
- //#endregion
153
- //#region src/cli/utils/wrap-indented-text.ts
154
- const wrapLine = (lineText, width, breakLongWords) => {
155
- if (lineText.length <= width) return [lineText];
156
- const wrappedLines = [];
157
- let remainingText = lineText.trim();
158
- while (remainingText.length > width) {
159
- const candidateText = remainingText.slice(0, width);
160
- const breakIndex = candidateText.lastIndexOf(" ");
161
- if (breakIndex <= 0) {
162
- if (breakLongWords) {
163
- wrappedLines.push(candidateText);
164
- remainingText = remainingText.slice(width).trimStart();
165
- continue;
166
- }
167
- const nextSpace = remainingText.indexOf(" ");
168
- if (nextSpace === -1) break;
169
- wrappedLines.push(remainingText.slice(0, nextSpace));
170
- remainingText = remainingText.slice(nextSpace + 1).trimStart();
171
- continue;
172
- }
173
- wrappedLines.push(remainingText.slice(0, breakIndex));
174
- remainingText = remainingText.slice(breakIndex + 1).trimStart();
175
- }
176
- if (remainingText.length > 0) wrappedLines.push(remainingText);
177
- return wrappedLines;
178
- };
179
- /**
180
- * Greedy word-wrap to a character width, returning one string per line
181
- * (no indentation applied). Preserves existing `\n` boundaries.
182
- */
183
- const wrapTextToWidth = (text, width, options = {}) => {
184
- if (width <= 0) return text.split("\n");
185
- const breakLongWords = options.breakLongWords ?? true;
186
- return text.split("\n").flatMap((lineText) => wrapLine(lineText, width, breakLongWords));
187
- };
188
- //#endregion
189
- //#region src/cli/utils/build-footer-description-lines.ts
190
- const FOOTER_DESCRIPTION_INDENT = " ";
191
- const buildFooterDescriptionLines = (description) => {
192
- return wrapTextToWidth(description, resolveMeasureWidth(2)).map((line) => highlighter.dim(`${FOOTER_DESCRIPTION_INDENT}${line}`));
193
- };
194
- //#endregion
195
- //#region src/cli/utils/build-footer-link-lines.ts
196
- const buildFooterLinkLines = ({ shareUrl }) => [
197
- ...shareUrl === null ? [] : [
198
- ` ${highlighter.bold("Share:")} ${highlighter.info(shareUrl)}`,
199
- ...buildFooterDescriptionLines("Tell others how you did on socials"),
200
- ""
201
- ],
202
- ` ${highlighter.bold("Docs:")} ${highlighter.info(DOCS_URL)}`,
203
- ...buildFooterDescriptionLines("Learn more about fixing issues, setting up CI/CD, and configuring rules with a config file"),
204
- "",
205
- ` ${highlighter.bold("GitHub:")} ${highlighter.info(CANONICAL_GITHUB_URL)}`,
206
- ...buildFooterDescriptionLines("Report issues and star the repository!")
207
- ];
208
- //#endregion
209
- //#region src/cli/utils/build-section-divider.ts
210
- const DIVIDER_INDENT = " ";
211
- const buildSectionDivider = () => highlighter.dim(`${DIVIDER_INDENT}${"─".repeat(resolveMeasureWidth(2))}`);
212
- //#endregion
213
- export { initializeSentry as i, buildFooterLinkLines as n, flushSentry as r, buildSectionDivider as t };
214
-
215
- //# sourceMappingURL=build-section-divider-DELfSn3p.js.map
216
- //# debugId=fc992092-cb60-5165-a621-058e9c73aa99