@intercom/cli 0.7.0 → 0.8.1

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/CHANGELOG.md ADDED
@@ -0,0 +1,84 @@
1
+ # Changelog
2
+
3
+ All notable changes to the Intercom CLI are documented in this file.
4
+
5
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6
+ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
+
8
+ View it from the CLI with `intercom changelog`.
9
+
10
+ ## [0.8.1] - 2026-06-16
11
+
12
+ ### Fixed
13
+
14
+ - Show the server's actual error message on failed requests instead of a bare `HTTP <status>`. This covers Fin SDK endpoints like `fin workflows upload` and `fin procedures upload`, which report problems (e.g. `YAML syntax error`, `Invalid file content`, `File too large`) in a different format than the rest of the API. `--verbose` now also prints the response body on errors.
15
+ - `fin workflows enable` and `fin workflows disable` now send the workflow state as the name the server expects (`live`/`paused`) instead of an internal numeric value, which the upload endpoint rejected. Both commands work again.
16
+
17
+ ## [0.7.0] - 2026-06-10
18
+
19
+ ### Added
20
+
21
+ - `intercom changelog` command to view the CLI's release notes from the terminal
22
+ - `fin data-connectors versions <id>` to view a data connector's version history
23
+ - Auto-enable fin-sdk and retry when a fin command hits the gate (#102)
24
+
25
+ ### Changed
26
+
27
+ - `fin data-connectors list` now shows each connector's state
28
+ - `fin data-connectors get` now shows the full connector definition (method, URL, inputs, outputs)
29
+ - `fin data-connectors create` now takes `--name` and returns the URL to finish configuring the connector in the UI
30
+
31
+ ### Fixed
32
+
33
+ - Handle `login_verification` redirect in CLI sign-in (#99)
34
+
35
+ ## [0.6.0] - 2026-05-25
36
+
37
+ ### Added
38
+
39
+ - `fin workflows upload`, `fin workflows enable`, and `fin workflows disable` (#95)
40
+ - `fin monitor pull-flagged` and `fin conversation bulk-send` (#83)
41
+
42
+ ### Changed
43
+
44
+ - Strip internal fields from conversation responses (#97)
45
+
46
+ ### Fixed
47
+
48
+ - Target the correct workspace during bootstrap (#96)
49
+ - Parse `fin workflows get` output as YAML, not JSON (#90)
50
+
51
+ ## [0.5.0] - 2026-04-27
52
+
53
+ ### Added
54
+
55
+ - Emit a Claude Code plugin hint from `--help` and `auth login` (#91)
56
+
57
+ ## [0.4.0] - 2026-04-20
58
+
59
+ ### Added
60
+
61
+ - `articles search` subcommand (#85)
62
+ - `pricing` command to fetch live pricing information (#67)
63
+ - `fin guidance create` command (#69)
64
+ - `fin` as a binary alias for `intercom` (#66)
65
+ - `intercom config` command (#43)
66
+ - `auth list` and `auth switch` commands (#41)
67
+ - Global `--dry-run` / `-n` flag (#48)
68
+ - `--input` flag on the `api` command and search subcommands (#46)
69
+ - Color output and a `--wide` flag for tables (#44)
70
+ - 5xx retry with exponential backoff (#49)
71
+
72
+ ### Changed
73
+
74
+ - Strip article bodies from list/search by default (#86)
75
+ - Default messenger snippets to JWT authentication (#81)
76
+
77
+ ### Fixed
78
+
79
+ - Improve `setup` command reliability for greenfield workspaces (#64)
80
+
81
+ [0.7.0]: https://github.com/intercom/cli/releases/tag/v0.7.0
82
+ [0.6.0]: https://github.com/intercom/cli/releases/tag/v0.6.0
83
+ [0.5.0]: https://github.com/intercom/cli/releases/tag/v0.5.0
84
+ [0.4.0]: https://github.com/intercom/cli/releases/tag/v0.4.0
package/README.md CHANGED
@@ -73,6 +73,7 @@ intercom setup --company-name "Acme" --articles-from ./docs
73
73
  | `intercom setup` | Orchestrate full workspace setup |
74
74
  | `intercom config get\|set\|list` | Manage CLI configuration |
75
75
  | `intercom pricing` | Show current Intercom pricing |
76
+ | `intercom changelog` | Show the CLI's release notes / version history |
76
77
  | `intercom completion bash\|zsh\|fish` | Generate shell completions |
77
78
 
78
79
  ## Global Flags
@@ -141,11 +142,11 @@ intercom api /contacts --jq '.data[].email'
141
142
  ```bash
142
143
  git clone git@github.com:intercom/cli.git
143
144
  cd cli
144
- npm ci
145
- npm run build # Build to dist/
146
- npm test # Run tests (~5s)
147
- npm run lint # TypeScript typecheck
148
- npm run dev # Watch mode
145
+ pnpm install
146
+ pnpm build # Build to dist/
147
+ pnpm test # Run tests (~5s)
148
+ pnpm lint # TypeScript typecheck
149
+ pnpm dev # Watch mode
149
150
 
150
151
  # Try it locally
151
152
  export INTERCOM_TOKEN="<your-token>"
@@ -154,6 +155,35 @@ node dist/index.js me
154
155
 
155
156
  See [SETUP.md](SETUP.md) for full developer setup guide.
156
157
 
158
+ ## Releasing
159
+
160
+ Publishing `@intercom/cli` to npm runs through `.github/workflows/publish.yml`, which fires when a GitHub Release is published. It uses OIDC trusted publishing (GitHub Actions mints a short-lived token per run, so there is no long-lived `NPM_TOKEN`) and npm staged publishing, which holds every version behind a human 2FA approval before it becomes installable. The org-wide reference is the [Engineering Wiki: Release new npm package versions](https://coda.io/d/Engineering-Wiki_duvlW1VbQXK/Release-new-npm-package-versions_suK1gai4).
161
+
162
+ ### Prerequisites (one-time)
163
+
164
+ - **GitHub:** write access to this repo, to bump the version and create Releases.
165
+ - **npm:** to approve a staged release, log in to npmjs.com as `intercom-npm-publisher` (the package owner). Credentials are in the 1Password Engineering Vault.
166
+
167
+ ### Cut a stable release
168
+
169
+ 1. **Bump the version.** In a PR, set the new `version` in `package.json` and move the unreleased entries in `CHANGELOG.md` under a new `## [X.Y.Z] - YYYY-MM-DD` heading. Merge it to `main` — the workflow refuses any release that is not reachable from the default branch.
170
+ 2. **Create a GitHub Release.** From the [Releases page](https://github.com/intercom/cli/releases/new), add a tag `vX.Y.Z` that matches `package.json` exactly (the `v` prefix is required; the workflow asserts `tag == version`). Leave the release label as **None**. Publishing the Release creates the tag and triggers `publish.yml`.
171
+ 3. **Wait for the workflow.** It runs the tag and branch guards, builds, then runs `npm stage publish` over OIDC. When the Actions run is green, the version sits in npm's staged queue — uploaded but not yet installable.
172
+ 4. **Approve in npm.** Logged in as `intercom-npm-publisher`, open [Staged Packages](https://www.npmjs.com/settings/intercom-npm-publisher/staged-packages), review the version, and **Approve** with 2FA. A stable version publishes to the `latest` dist-tag and is then installable via `npm install -g @intercom/cli`.
173
+
174
+ ### Cut a prerelease
175
+
176
+ Same path and same approval gate; a prerelease lands on the `next` dist-tag instead of `latest`.
177
+
178
+ 1. Bump `package.json` to a version with a `-` suffix (e.g. `X.Y.Z-beta.1`) and merge to `main` via PR. Prereleases come from the default branch too.
179
+ 2. Create a GitHub Release tagged `vX.Y.Z-beta.1` from that commit (the tag must match the version) and tick **Set as a pre-release**.
180
+ 3. The workflow detects the `-` suffix and stages to the `next` tag, never `latest`.
181
+ 4. Approve the staged version with 2FA as above. Consumers opt in explicitly with `npm install -g @intercom/cli@next`; a plain install still resolves to stable `latest`.
182
+
183
+ ### Reject a staged release
184
+
185
+ If a staged version should not ship, choose **Reject** in Staged Packages and it is removed without publishing. Rejecting leaves the git tag and GitHub Release behind, so also delete the Release and tag from the GitHub Releases UI. The version can then be re-staged — only published versions are immutable.
186
+
157
187
  ## License
158
188
 
159
189
  MIT
package/dist/index.js CHANGED
@@ -61,6 +61,25 @@ async function fetchWithTimeout(url, init, options) {
61
61
 
62
62
  // src/api/client.ts
63
63
  var DEFAULT_BASE_URL = "https://api.intercom.io";
64
+ var MAX_RAW_ERROR_LEN = 500;
65
+ function extractApiError(body) {
66
+ if (!body || typeof body !== "object") return {};
67
+ const b = body;
68
+ if (Array.isArray(b.errors) && b.errors.length > 0) {
69
+ const first = b.errors[0];
70
+ return {
71
+ message: typeof first?.message === "string" ? first.message : void 0,
72
+ code: typeof first?.code === "string" ? first.code : void 0
73
+ };
74
+ }
75
+ if (typeof b.error === "string") return { message: b.error };
76
+ if (b.errors && typeof b.errors === "object") {
77
+ const msgs = Object.values(b.errors).flat().filter((m) => typeof m === "string");
78
+ if (msgs.length > 0) return { message: msgs.join("; ") };
79
+ }
80
+ if (typeof b.message === "string") return { message: b.message };
81
+ return {};
82
+ }
64
83
  var _dryRun = false;
65
84
  function setDryRun(enabled) {
66
85
  _dryRun = enabled;
@@ -189,9 +208,21 @@ var IntercomClient = class _IntercomClient {
189
208
  return response.json();
190
209
  }
191
210
  }
192
- const errorBody = await response.json().catch(() => ({}));
193
- const errorMsg = errorBody?.errors?.[0]?.message ?? `HTTP ${response.status}`;
194
- const errorCode = errorBody?.errors?.[0]?.code ?? "";
211
+ const rawBody = await response.text().catch(() => "");
212
+ if (this.verbose && rawBody) {
213
+ console.error(`< Body: ${rawBody}`);
214
+ }
215
+ let parsedBody;
216
+ try {
217
+ parsedBody = rawBody ? JSON.parse(rawBody) : void 0;
218
+ } catch {
219
+ parsedBody = void 0;
220
+ }
221
+ const extracted = extractApiError(parsedBody);
222
+ const trimmedBody = rawBody.trim();
223
+ const rawFallback = trimmedBody.length > MAX_RAW_ERROR_LEN ? `${trimmedBody.slice(0, MAX_RAW_ERROR_LEN)}\u2026` : trimmedBody;
224
+ const errorMsg = extracted.message ?? (rawFallback || `HTTP ${response.status}`);
225
+ const errorCode = extracted.code ?? "";
195
226
  if (response.status === 401) {
196
227
  throw new AuthError(
197
228
  `Authentication expired or invalid: ${errorMsg}. Run "intercom auth login" to re-authenticate.`
@@ -2545,9 +2576,13 @@ function registerProceduresCommand(fin) {
2545
2576
  }
2546
2577
 
2547
2578
  // src/commands/fin/data-connectors.ts
2579
+ function summarizeKeys(obj) {
2580
+ if (!obj) return "";
2581
+ return Object.keys(obj).join(", ");
2582
+ }
2548
2583
  function registerDataConnectorsCommand(fin) {
2549
2584
  const dataConnectors = fin.command("data-connectors").description("Manage Fin SDK data connectors");
2550
- dataConnectors.command("list").description("List data connectors from the Fin SDK manifest").option("--json", "Output as JSON").option("--verbose", "Show HTTP request/response details").action(async function() {
2585
+ dataConnectors.command("list").description("List data connectors from the Fin SDK manifest").option("--json", "Output as JSON").option("--jq <expr>", "Filter JSON output with jq expression").option("--verbose", "Show HTTP request/response details").action(async function() {
2551
2586
  const opts = this.optsWithGlobals();
2552
2587
  const client = await resolveClient(opts);
2553
2588
  const result = await client.get("/fin-sdk/manifest");
@@ -2559,33 +2594,38 @@ function registerDataConnectorsCommand(fin) {
2559
2594
  }
2560
2595
  const rows = items.map((item) => ({
2561
2596
  ID: String(item.id ?? ""),
2562
- NAME: String(item.name ?? "")
2597
+ NAME: String(item.name ?? ""),
2598
+ STATE: String(item.state ?? "")
2563
2599
  }));
2564
- return table({ columns: ["ID", "NAME"], rows });
2600
+ return table({ columns: ["ID", "NAME", "STATE"], rows });
2565
2601
  }, items);
2566
2602
  });
2567
- dataConnectors.command("create").description("Create a data connector").requiredOption("-f, --field <key=value>", "Field to set (e.g. name=<name>)", (v, acc) => [...acc, v], []).option("--json", "Output as JSON").option("--jq <expr>", "Filter JSON output with jq expression").option("--verbose", "Show HTTP request/response details").action(async function() {
2603
+ dataConnectors.command("create").description("Create a draft data connector (finish configuration in the UI)").requiredOption("--name <name>", "Name for the new data connector").option("--json", "Output as JSON").option("--jq <expr>", "Filter JSON output with jq expression").option("--verbose", "Show HTTP request/response details").addHelpText(
2604
+ "after",
2605
+ `
2606
+ The create endpoint only sets the name \u2014 it returns a web_url where you finish
2607
+ configuring the connector (request, inputs, outputs, auth) in the Intercom UI.
2608
+
2609
+ Example:
2610
+ $ intercom fin data-connectors create --name "Order lookup"`
2611
+ ).action(async function() {
2568
2612
  const opts = this.optsWithGlobals();
2569
2613
  const client = await resolveClient(opts);
2570
- const fields = opts.field ?? [];
2571
- const body = {};
2572
- for (const f of fields) {
2573
- const eq = f.indexOf("=");
2574
- if (eq === -1) throw new Error(`Invalid field format: ${f}. Expected key=value`);
2575
- body[f.slice(0, eq)] = f.slice(eq + 1);
2576
- }
2577
- const result = await client.post("/fin-sdk/data-connectors", body);
2614
+ const result = await client.post("/fin-sdk/data-connectors", {
2615
+ name: opts.name
2616
+ });
2578
2617
  render(
2579
2618
  result,
2580
2619
  opts,
2581
2620
  () => detail({
2582
- "ID": String(result.id ?? ""),
2583
- "Name": String(result.name ?? ""),
2584
- "Status": result.status != null ? String(result.status) : void 0
2621
+ ID: String(result.id ?? ""),
2622
+ Name: String(result.name ?? ""),
2623
+ "Web URL": result.web_url != null ? String(result.web_url) : void 0,
2624
+ "Next step": result.message != null ? String(result.message) : void 0
2585
2625
  })
2586
2626
  );
2587
2627
  });
2588
- dataConnectors.command("get <id>").description("Download a data connector by ID").option("--json", "Output as JSON").option("--jq <expr>", "Filter JSON output with jq expression").option("--verbose", "Show HTTP request/response details").action(async function(id) {
2628
+ dataConnectors.command("get <id>").description("Download a data connector's full definition by ID").option("--json", "Output as JSON").option("--jq <expr>", "Filter JSON output with jq expression").option("--verbose", "Show HTTP request/response details").action(async function(id) {
2589
2629
  const opts = this.optsWithGlobals();
2590
2630
  const client = await resolveClient(opts);
2591
2631
  const result = await client.get(`/fin-sdk/data-connectors/${id}/download`);
@@ -2593,11 +2633,36 @@ function registerDataConnectorsCommand(fin) {
2593
2633
  result,
2594
2634
  opts,
2595
2635
  () => detail({
2596
- "ID": String(result.id ?? ""),
2597
- "Name": String(result.name ?? "")
2636
+ ID: String(result.id ?? ""),
2637
+ Name: String(result.name ?? ""),
2638
+ State: result.state != null ? String(result.state) : void 0,
2639
+ Description: result.description != null ? String(result.description) : void 0,
2640
+ "Direct Fin usage": result.enable_direct_usage != null ? String(result.enable_direct_usage) : void 0,
2641
+ Method: result.request?.method != null ? String(result.request.method) : void 0,
2642
+ URL: result.request?.url != null ? String(result.request.url) : void 0,
2643
+ Inputs: summarizeKeys(result.inputs) || void 0,
2644
+ Outputs: summarizeKeys(result.outputs) || void 0
2598
2645
  })
2599
2646
  );
2600
2647
  });
2648
+ dataConnectors.command("versions <id>").description("List a data connector's server-side version history").option("--json", "Output as JSON").option("--jq <expr>", "Filter JSON output with jq expression").option("--verbose", "Show HTTP request/response details").action(async function(id) {
2649
+ const opts = this.optsWithGlobals();
2650
+ const client = await resolveClient(opts);
2651
+ const result = await client.get(`/fin-sdk/data-connectors/${id}/versions`);
2652
+ const items = result.versions ?? [];
2653
+ render(items, opts, () => {
2654
+ if (items.length === 0) {
2655
+ return "No versions found.";
2656
+ }
2657
+ const rows = items.map((v) => ({
2658
+ STATUS: String(v.status ?? ""),
2659
+ CREATED: String(v.created_at ?? ""),
2660
+ AUTHOR: String(v.author?.name ?? ""),
2661
+ NOTE: String(v.note ?? "")
2662
+ }));
2663
+ return table({ columns: ["STATUS", "CREATED", "AUTHOR", "NOTE"], rows });
2664
+ }, items);
2665
+ });
2601
2666
  }
2602
2667
 
2603
2668
  // src/commands/fin/guidance.ts
@@ -2708,8 +2773,8 @@ function registerAudiencesCommand(fin) {
2708
2773
  import { readFile as readFile3 } from "fs/promises";
2709
2774
  import { basename as basename2 } from "path";
2710
2775
  import { parse as parseYaml, stringify as stringifyYaml } from "yaml";
2711
- var STATE_LIVE = 1;
2712
- var STATE_PAUSED = 2;
2776
+ var STATE_LIVE = "live";
2777
+ var STATE_PAUSED = "paused";
2713
2778
  function registerWorkflowsCommand(fin) {
2714
2779
  const workflows = fin.command("workflows").description("Manage Fin SDK workflows");
2715
2780
  workflows.command("list").description("List Fin SDK workflows").option("--json", "Output as JSON").option("--verbose", "Show HTTP request/response details").action(async function() {
@@ -4127,6 +4192,104 @@ function registerConfigCommand(program) {
4127
4192
  });
4128
4193
  }
4129
4194
 
4195
+ // src/commands/changelog.ts
4196
+ import pc2 from "picocolors";
4197
+
4198
+ // src/changelog.ts
4199
+ import { readFileSync as readFileSync5 } from "fs";
4200
+ import { fileURLToPath } from "url";
4201
+ var RELEASE_RE = /^##\s+\[?([^\]]+?)\]?(?:\s+-\s+(.+))?$/;
4202
+ var SECTION_RE = /^###\s+(.+)$/;
4203
+ var ENTRY_RE = /^[-*]\s+(.+)$/;
4204
+ function parseChangelog(markdown) {
4205
+ const releases = [];
4206
+ let release = null;
4207
+ let section = null;
4208
+ for (const raw of markdown.split("\n")) {
4209
+ const line = raw.trimEnd();
4210
+ const releaseMatch = line.match(RELEASE_RE);
4211
+ if (releaseMatch) {
4212
+ release = { version: releaseMatch[1].trim(), date: releaseMatch[2]?.trim() ?? "", sections: [] };
4213
+ section = null;
4214
+ releases.push(release);
4215
+ continue;
4216
+ }
4217
+ if (!release) continue;
4218
+ const sectionMatch = line.match(SECTION_RE);
4219
+ if (sectionMatch) {
4220
+ section = { title: sectionMatch[1].trim(), entries: [] };
4221
+ release.sections.push(section);
4222
+ continue;
4223
+ }
4224
+ const entryMatch = line.match(ENTRY_RE);
4225
+ if (entryMatch && section) {
4226
+ section.entries.push(entryMatch[1].trim());
4227
+ }
4228
+ }
4229
+ return releases;
4230
+ }
4231
+ var cached;
4232
+ function loadChangelog() {
4233
+ if (cached) return cached;
4234
+ const path = fileURLToPath(new URL("../CHANGELOG.md", import.meta.url));
4235
+ cached = parseChangelog(readFileSync5(path, "utf8"));
4236
+ return cached;
4237
+ }
4238
+
4239
+ // src/commands/changelog.ts
4240
+ function normalizeVersion(v) {
4241
+ return v.replace(/^v/i, "");
4242
+ }
4243
+ function colorEnabled() {
4244
+ return !!process.stdout.isTTY && !process.env.NO_COLOR;
4245
+ }
4246
+ function renderHuman(releases) {
4247
+ const color = colorEnabled();
4248
+ const out = [];
4249
+ for (const release of releases) {
4250
+ const heading = release.date ? `${release.version} \u2014 ${release.date}` : release.version;
4251
+ out.push(color ? pc2.bold(heading) : heading);
4252
+ for (const section of release.sections) {
4253
+ out.push(` ${color ? pc2.dim(section.title) : section.title}`);
4254
+ for (const entry of section.entries) {
4255
+ out.push(` \u2022 ${entry}`);
4256
+ }
4257
+ }
4258
+ out.push("");
4259
+ }
4260
+ return out.join("\n").trimEnd();
4261
+ }
4262
+ function registerChangelogCommand(program) {
4263
+ program.command("changelog").description("Show the CLI's release notes / version history").argument("[version]", "Show a single version (e.g. 0.7.0)").option("-n, --limit <count>", "Show only the most recent <count> releases").option("--json", "Output as JSON").option("--jq <expr>", "Filter JSON output with jq expression").addHelpText(
4264
+ "after",
4265
+ `
4266
+ Examples:
4267
+ $ intercom changelog Show the full release history
4268
+ $ intercom changelog --limit 1 Show only the latest release
4269
+ $ intercom changelog 0.7.0 Show a specific version
4270
+ $ intercom changelog --json Machine-readable release history`
4271
+ ).action(async function(version) {
4272
+ const opts = this.optsWithGlobals();
4273
+ let releases = loadChangelog();
4274
+ if (version) {
4275
+ const wanted = normalizeVersion(version);
4276
+ const match = releases.find((r) => normalizeVersion(r.version) === wanted);
4277
+ if (!match) {
4278
+ const known = releases.map((r) => r.version).join(", ");
4279
+ throw new CLIError(`No changelog entry for version "${version}". Known versions: ${known}`);
4280
+ }
4281
+ releases = [match];
4282
+ } else if (opts.limit !== void 0) {
4283
+ const limit = parseInt(String(opts.limit), 10);
4284
+ if (isNaN(limit) || limit <= 0) {
4285
+ throw new CLIError("--limit must be a positive integer");
4286
+ }
4287
+ releases = releases.slice(0, limit);
4288
+ }
4289
+ render(releases, opts, () => renderHuman(releases), releases);
4290
+ });
4291
+ }
4292
+
4130
4293
  // src/index.ts
4131
4294
  function detectBinaryName() {
4132
4295
  const argv1 = process.argv[1] ?? "";
@@ -4171,6 +4334,7 @@ Environment: Set INTERCOM_TOKEN to skip login entirely.`;
4171
4334
  registerPricingCommand(program);
4172
4335
  registerCompletionCommand(program);
4173
4336
  registerConfigCommand(program);
4337
+ registerChangelogCommand(program);
4174
4338
  program.hook("preAction", (thisCommand, actionCommand) => {
4175
4339
  const rootOpts = thisCommand.opts();
4176
4340
  if (rootOpts.agent && rootOpts.human) {
package/package.json CHANGED
@@ -1,8 +1,9 @@
1
1
  {
2
2
  "name": "@intercom/cli",
3
- "version": "0.7.0",
3
+ "version": "0.8.1",
4
4
  "description": "CLI tool for managing Intercom workspaces",
5
5
  "type": "module",
6
+ "packageManager": "pnpm@10.23.0",
6
7
  "bin": {
7
8
  "intercom": "dist/index.js",
8
9
  "fin": "dist/index.js"
@@ -20,7 +21,8 @@
20
21
  },
21
22
  "files": [
22
23
  "dist",
23
- "!dist/**/*.map"
24
+ "!dist/**/*.map",
25
+ "CHANGELOG.md"
24
26
  ],
25
27
  "license": "MIT",
26
28
  "dependencies": {
@@ -39,5 +41,9 @@
39
41
  "tsup": "^8.5.1",
40
42
  "typescript": "^5.9.3",
41
43
  "vitest": "^4.1.0"
44
+ },
45
+ "pnpm": {
46
+ "overrides": {},
47
+ "onlyBuiltDependencies": []
42
48
  }
43
49
  }