@togglhq/cli 1.11.82 → 1.11.83
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/README.md +1 -1
- package/build/cli.js +1 -1
- package/build/index.js +1 -1
- package/build/{program-DZlKCm-L.js → program-CZaDiFSf.js} +125 -15
- package/build/program.js +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -282,7 +282,7 @@ Disable product analytics:
|
|
|
282
282
|
TOGGL_PRODUCT_ANALYTICS=off
|
|
283
283
|
```
|
|
284
284
|
|
|
285
|
-
|
|
285
|
+
Error reporting is on by default. It sends a redacted error category, the stack trace with package-relative file paths, the CLI, Node and OS versions, and sampled request timings without query strings. It never sends command arguments, output, exception text, your hostname, local paths, or your project's dependency list. Disable it with `TOGGL_SENTRY=off`, or send it to your own Sentry project with `TOGGL_SENTRY_DSN`.
|
|
286
286
|
|
|
287
287
|
## License
|
|
288
288
|
|
package/build/cli.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { a as CommanderError, i as shutdownCliTelemetry, n as captureCliException, r as initCliTelemetry, t as createProgram } from "./program-
|
|
2
|
+
import { a as CommanderError, i as shutdownCliTelemetry, n as captureCliException, r as initCliTelemetry, t as createProgram } from "./program-CZaDiFSf.js";
|
|
3
3
|
import { readFileSync } from "node:fs";
|
|
4
4
|
import { dirname, join } from "node:path";
|
|
5
5
|
import { fileURLToPath } from "node:url";
|
package/build/index.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { t as createProgram } from "./program-
|
|
1
|
+
import { t as createProgram } from "./program-CZaDiFSf.js";
|
|
2
2
|
export { createProgram };
|
|
@@ -12672,6 +12672,120 @@ function redactUnsafeSentryMessages(event) {
|
|
|
12672
12672
|
for (const value of event.exception?.values ?? []) if (!isSafeSentryMessage(value.value)) value.value = REDACTED_SENTRY_MESSAGE;
|
|
12673
12673
|
return event;
|
|
12674
12674
|
}
|
|
12675
|
+
/**
|
|
12676
|
+
* Shared Sentry setup for the public CLI and MCP packages. Reporting is on by
|
|
12677
|
+
* default there, so everything the SDK attaches on its own has to be safe to
|
|
12678
|
+
* send from any user's machine, not only the exception message. Both packages
|
|
12679
|
+
* build their `Sentry.init` options from here so the two cannot drift.
|
|
12680
|
+
*/
|
|
12681
|
+
function normalized(raw) {
|
|
12682
|
+
const value = raw?.trim();
|
|
12683
|
+
return value ? value.toLowerCase() : void 0;
|
|
12684
|
+
}
|
|
12685
|
+
function isOff(raw) {
|
|
12686
|
+
const value = normalized(raw);
|
|
12687
|
+
return value === "0" || value === "false" || value === "off" || value === "no";
|
|
12688
|
+
}
|
|
12689
|
+
function isOn(raw) {
|
|
12690
|
+
const value = normalized(raw);
|
|
12691
|
+
return value === "1" || value === "true" || value === "on" || value === "yes";
|
|
12692
|
+
}
|
|
12693
|
+
/**
|
|
12694
|
+
* Picks the DSN the public build reports to, or `undefined` when reporting is
|
|
12695
|
+
* off.
|
|
12696
|
+
*
|
|
12697
|
+
* `TOGGL_SENTRY_DSN` is the override. The generic `SENTRY_DSN` is what most Node
|
|
12698
|
+
* apps set, and the MCP loads the working directory's `.env`, so on its own it
|
|
12699
|
+
* must not redirect Toggl's errors into the user's project. It is still honoured
|
|
12700
|
+
* with an explicit `TOGGL_SENTRY=1`, the old opt-in, and `SENTRY_DSN=off` still
|
|
12701
|
+
* switches reporting off.
|
|
12702
|
+
*/
|
|
12703
|
+
function resolvePublicSentryDsn(builtIn, env = process.env) {
|
|
12704
|
+
if (isOff(env.TOGGL_SENTRY) || normalized(env.SENTRY_DSN) === "off") return void 0;
|
|
12705
|
+
const override = env.TOGGL_SENTRY_DSN?.trim();
|
|
12706
|
+
if (override) return override.toLowerCase() === "off" ? void 0 : override;
|
|
12707
|
+
const legacy = env.SENTRY_DSN?.trim();
|
|
12708
|
+
if (legacy && isOn(env.TOGGL_SENTRY)) return legacy;
|
|
12709
|
+
return builtIn;
|
|
12710
|
+
}
|
|
12711
|
+
/**
|
|
12712
|
+
* `/Users/jane/.npm/_npx/…/node_modules/@togglhq/mcp/build/cli.js` becomes
|
|
12713
|
+
* `@togglhq/mcp/build/cli.js`. A path outside `node_modules` keeps only its file
|
|
12714
|
+
* name, so no home directory or login leaves the machine.
|
|
12715
|
+
*/
|
|
12716
|
+
function toPackageRelativePath(path) {
|
|
12717
|
+
const unified = path.replace(/^file:\/\//, "").replaceAll("\\", "/");
|
|
12718
|
+
const at = unified.lastIndexOf("/node_modules/");
|
|
12719
|
+
if (at !== -1) return unified.slice(at + 14);
|
|
12720
|
+
if (!unified.includes("/")) return unified;
|
|
12721
|
+
return unified.slice(unified.lastIndexOf("/") + 1);
|
|
12722
|
+
}
|
|
12723
|
+
function scrubStacktrace(stacktrace) {
|
|
12724
|
+
for (const frame of stacktrace?.frames ?? []) {
|
|
12725
|
+
if (typeof frame.filename === "string") frame.filename = toPackageRelativePath(frame.filename);
|
|
12726
|
+
if (typeof frame.abs_path === "string") frame.abs_path = toPackageRelativePath(frame.abs_path);
|
|
12727
|
+
}
|
|
12728
|
+
}
|
|
12729
|
+
const QUERY_ATTRIBUTES = [
|
|
12730
|
+
"http.query",
|
|
12731
|
+
"url.query",
|
|
12732
|
+
"http.fragment",
|
|
12733
|
+
"url.fragment"
|
|
12734
|
+
];
|
|
12735
|
+
const URL_ATTRIBUTES = [
|
|
12736
|
+
"url.full",
|
|
12737
|
+
"http.url",
|
|
12738
|
+
"http.target",
|
|
12739
|
+
"url"
|
|
12740
|
+
];
|
|
12741
|
+
function stripQuery(value) {
|
|
12742
|
+
return value.replace(/[?#]\S*/, "");
|
|
12743
|
+
}
|
|
12744
|
+
function scrubSpan(span) {
|
|
12745
|
+
if (!span) return;
|
|
12746
|
+
if (typeof span.description === "string") span.description = stripQuery(span.description);
|
|
12747
|
+
const data = span.data;
|
|
12748
|
+
if (!data) return;
|
|
12749
|
+
for (const key of QUERY_ATTRIBUTES) delete data[key];
|
|
12750
|
+
for (const key of URL_ATTRIBUTES) {
|
|
12751
|
+
const value = data[key];
|
|
12752
|
+
if (typeof value === "string") data[key] = stripQuery(value);
|
|
12753
|
+
}
|
|
12754
|
+
}
|
|
12755
|
+
/**
|
|
12756
|
+
* Last word on every event the public build sends: messages reduced to fixed
|
|
12757
|
+
* categories, no hostname, no breadcrumbs, no dependency list, no request data,
|
|
12758
|
+
* package-relative stack paths, and no query strings on spans.
|
|
12759
|
+
*/
|
|
12760
|
+
function scrubPublicSentryEvent(event) {
|
|
12761
|
+
redactUnsafeSentryMessages(event);
|
|
12762
|
+
delete event.server_name;
|
|
12763
|
+
delete event.breadcrumbs;
|
|
12764
|
+
delete event.modules;
|
|
12765
|
+
delete event.request;
|
|
12766
|
+
for (const value of event.exception?.values ?? []) scrubStacktrace(value.stacktrace);
|
|
12767
|
+
for (const thread of event.threads?.values ?? []) scrubStacktrace(thread.stacktrace);
|
|
12768
|
+
for (const span of event.spans ?? []) scrubSpan(span);
|
|
12769
|
+
scrubSpan(event.contexts?.trace);
|
|
12770
|
+
return event;
|
|
12771
|
+
}
|
|
12772
|
+
/**
|
|
12773
|
+
* Privacy options shared by `initCliTelemetry` and `initPublicSentry`.
|
|
12774
|
+
*
|
|
12775
|
+
* `sendDefaultPii: false` leaves the hostname (`server_name`), console and fetch
|
|
12776
|
+
* breadcrumbs, absolute stack paths, the working directory's package.json
|
|
12777
|
+
* dependencies (`Modules`) and incoming request data in place. Console
|
|
12778
|
+
* breadcrumbs in the MCP include the workspace name it logs at startup.
|
|
12779
|
+
*/
|
|
12780
|
+
const PUBLIC_SENTRY_PRIVACY_OPTIONS = {
|
|
12781
|
+
sendDefaultPii: false,
|
|
12782
|
+
includeServerName: false,
|
|
12783
|
+
maxBreadcrumbs: 0,
|
|
12784
|
+
integrations: (defaults) => defaults.filter((integration) => integration.name !== "Modules"),
|
|
12785
|
+
beforeBreadcrumb: () => null,
|
|
12786
|
+
beforeSend: (event) => scrubPublicSentryEvent(event),
|
|
12787
|
+
beforeSendTransaction: (event) => scrubPublicSentryEvent(event)
|
|
12788
|
+
};
|
|
12675
12789
|
const DEFAULT_POSTHOG_HOST = "https://eu.i.posthog.com";
|
|
12676
12790
|
/**
|
|
12677
12791
|
* The shared Toggl **production** PostHog project — the same token the Track
|
|
@@ -27151,11 +27265,12 @@ async function runValidatedOperation(operation, options, deps) {
|
|
|
27151
27265
|
}
|
|
27152
27266
|
//#endregion
|
|
27153
27267
|
//#region src/telemetry.ts
|
|
27154
|
-
|
|
27155
|
-
|
|
27156
|
-
|
|
27157
|
-
|
|
27158
|
-
|
|
27268
|
+
/**
|
|
27269
|
+
* Public client DSN for the `toggl-cli` Sentry project. Safe to ship: it only
|
|
27270
|
+
* accepts events. The pack audit allowlists this exact value and still rejects
|
|
27271
|
+
* any other `ingest.sentry.io` DSN.
|
|
27272
|
+
*/
|
|
27273
|
+
const PUBLIC_SENTRY_DSN = "https://499edd257e0c64778932e6b7c7a0f8e9@o43910.ingest.us.sentry.io/4512156592046080";
|
|
27159
27274
|
let sentryEnabled = false;
|
|
27160
27275
|
let productAnalyticsEnabled = false;
|
|
27161
27276
|
let lastCommandError;
|
|
@@ -27165,23 +27280,18 @@ function initCliTelemetry(packageVersion) {
|
|
|
27165
27280
|
packageVersion,
|
|
27166
27281
|
distinctId: resolveProductAnalyticsDistinctId("cli")
|
|
27167
27282
|
});
|
|
27168
|
-
|
|
27169
|
-
|
|
27170
|
-
return;
|
|
27171
|
-
}
|
|
27172
|
-
const dsn = process.env.SENTRY_DSN;
|
|
27173
|
-
if (!dsn || dsn === "off") {
|
|
27174
|
-
console.error("[Telemetry] TOGGL_SENTRY is set but SENTRY_DSN is missing; Sentry left disabled");
|
|
27283
|
+
const dsn = resolvePublicSentryDsn(PUBLIC_SENTRY_DSN);
|
|
27284
|
+
if (!dsn) {
|
|
27175
27285
|
sentryEnabled = false;
|
|
27176
27286
|
return;
|
|
27177
27287
|
}
|
|
27178
27288
|
Sentry.init({
|
|
27179
27289
|
dsn,
|
|
27290
|
+
release: `@togglhq/cli@${packageVersion}`,
|
|
27180
27291
|
environment: process.env.NODE_ENV ?? "production",
|
|
27181
27292
|
tracesSampleRate: .1,
|
|
27182
|
-
sendDefaultPii: false,
|
|
27183
27293
|
enableLogs: false,
|
|
27184
|
-
|
|
27294
|
+
...PUBLIC_SENTRY_PRIVACY_OPTIONS
|
|
27185
27295
|
});
|
|
27186
27296
|
Sentry.setTag("cli.session.id", crypto.randomUUID());
|
|
27187
27297
|
sentryEnabled = true;
|
|
@@ -27804,4 +27914,4 @@ Common commands:
|
|
|
27804
27914
|
//#endregion
|
|
27805
27915
|
export { CommanderError as a, shutdownCliTelemetry as i, captureCliException as n, initCliTelemetry as r, createProgram as t };
|
|
27806
27916
|
|
|
27807
|
-
//# sourceMappingURL=program-
|
|
27917
|
+
//# sourceMappingURL=program-CZaDiFSf.js.map
|
package/build/program.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { t as createProgram } from "./program-
|
|
1
|
+
import { t as createProgram } from "./program-CZaDiFSf.js";
|
|
2
2
|
export { createProgram };
|