assistant-ui 0.0.115 → 0.0.117

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 (84) hide show
  1. package/dist/codemods/utils/createTransformer.d.ts +3 -4
  2. package/dist/codemods/utils/createTransformer.d.ts.map +1 -1
  3. package/dist/commands/add.d.ts +4 -4
  4. package/dist/commands/add.d.ts.map +1 -1
  5. package/dist/commands/add.js +8 -5
  6. package/dist/commands/add.js.map +1 -1
  7. package/dist/commands/agent.d.ts +1 -2
  8. package/dist/commands/agent.d.ts.map +1 -1
  9. package/dist/commands/create.d.ts +10 -11
  10. package/dist/commands/create.d.ts.map +1 -1
  11. package/dist/commands/create.js +26 -13
  12. package/dist/commands/create.js.map +1 -1
  13. package/dist/commands/doctor.d.ts +9 -10
  14. package/dist/commands/doctor.d.ts.map +1 -1
  15. package/dist/commands/info.d.ts +3 -3
  16. package/dist/commands/info.d.ts.map +1 -1
  17. package/dist/commands/info.js +0 -1
  18. package/dist/commands/info.js.map +1 -1
  19. package/dist/commands/init.d.ts +3 -4
  20. package/dist/commands/init.d.ts.map +1 -1
  21. package/dist/commands/init.js +2 -3
  22. package/dist/commands/init.js.map +1 -1
  23. package/dist/commands/mcp.d.ts +1 -2
  24. package/dist/commands/mcp.d.ts.map +1 -1
  25. package/dist/commands/mcp.js +0 -1
  26. package/dist/commands/mcp.js.map +1 -1
  27. package/dist/commands/update.d.ts +1 -2
  28. package/dist/commands/update.d.ts.map +1 -1
  29. package/dist/commands/upgrade.d.ts +3 -4
  30. package/dist/commands/upgrade.d.ts.map +1 -1
  31. package/dist/lib/agent-skill.d.ts +3 -4
  32. package/dist/lib/agent-skill.d.ts.map +1 -1
  33. package/dist/lib/create-project.d.ts +16 -11
  34. package/dist/lib/create-project.d.ts.map +1 -1
  35. package/dist/lib/create-project.js +27 -18
  36. package/dist/lib/create-project.js.map +1 -1
  37. package/dist/lib/handle-cli-error.d.ts +1 -2
  38. package/dist/lib/handle-cli-error.d.ts.map +1 -1
  39. package/dist/lib/install-ai-sdk-lib.d.ts +1 -2
  40. package/dist/lib/install-ai-sdk-lib.d.ts.map +1 -1
  41. package/dist/lib/install-edge-lib.d.ts +1 -2
  42. package/dist/lib/install-edge-lib.d.ts.map +1 -1
  43. package/dist/lib/run-spawn.d.ts +6 -7
  44. package/dist/lib/run-spawn.d.ts.map +1 -1
  45. package/dist/lib/transform-options.d.ts +1 -2
  46. package/dist/lib/transform-options.d.ts.map +1 -1
  47. package/dist/lib/transform.d.ts +4 -5
  48. package/dist/lib/transform.d.ts.map +1 -1
  49. package/dist/lib/upgrade.d.ts +1 -2
  50. package/dist/lib/upgrade.d.ts.map +1 -1
  51. package/dist/lib/utils/config.d.ts +4 -5
  52. package/dist/lib/utils/config.d.ts.map +1 -1
  53. package/dist/lib/utils/file-scanner.d.ts +4 -5
  54. package/dist/lib/utils/file-scanner.d.ts.map +1 -1
  55. package/dist/lib/utils/logger.d.ts +1 -2
  56. package/dist/lib/utils/logger.d.ts.map +1 -1
  57. package/dist/lib/utils/package-installer.d.ts +2 -3
  58. package/dist/lib/utils/package-installer.d.ts.map +1 -1
  59. package/dist/lib/utils/package-json.d.ts +1 -2
  60. package/dist/lib/utils/package-json.d.ts.map +1 -1
  61. package/dist/lib/utils/package-manager.d.ts +7 -8
  62. package/dist/lib/utils/package-manager.d.ts.map +1 -1
  63. package/dist/lib/utils/registry.d.ts +5 -4
  64. package/dist/lib/utils/registry.d.ts.map +1 -1
  65. package/dist/lib/utils/registry.js +13 -2
  66. package/dist/lib/utils/registry.js.map +1 -1
  67. package/dist/lib/utils/workspace.d.ts +2 -3
  68. package/dist/lib/utils/workspace.d.ts.map +1 -1
  69. package/dist/program.d.ts +1 -2
  70. package/dist/program.d.ts.map +1 -1
  71. package/dist/run.d.ts +1 -2
  72. package/dist/run.d.ts.map +1 -1
  73. package/package.json +8 -7
  74. package/plugin/skills/assistant-ui/SKILL.md +3 -3
  75. package/src/commands/add.ts +10 -3
  76. package/src/commands/create.ts +33 -8
  77. package/src/commands/info.ts +0 -1
  78. package/src/commands/init.ts +1 -2
  79. package/src/commands/mcp.ts +0 -3
  80. package/src/lib/create-project.ts +35 -20
  81. package/src/lib/run-spawn.test.ts +0 -1
  82. package/src/lib/utils/registry.test.ts +56 -0
  83. package/src/lib/utils/registry.ts +35 -0
  84. package/src/run.test.ts +1 -5
@@ -2,6 +2,7 @@ import { Command } from "commander";
2
2
  import { logger } from "../lib/utils/logger";
3
3
  import { hasConfig } from "../lib/utils/config";
4
4
  import {
5
+ detectRegistryPlatform,
5
6
  getComponentsJsonStyle,
6
7
  resolveRegistryItemUrl,
7
8
  } from "../lib/utils/registry";
@@ -24,12 +25,13 @@ export function createAddComponentsPlan(params: {
24
25
  overwrite?: boolean;
25
26
  path?: string;
26
27
  style?: string;
28
+ platform?: "web" | "native";
27
29
  }): AddComponentsPlan {
28
30
  const componentsToAdd = params.components.map((c) => {
29
31
  if (!/^[a-zA-Z0-9-/]+$/.test(c)) {
30
32
  throw new Error(`Invalid component name: ${c}`);
31
33
  }
32
- return resolveRegistryItemUrl(c, params.style);
34
+ return resolveRegistryItemUrl(c, params.style, params.platform);
33
35
  });
34
36
 
35
37
  const [command, dlxArgs] = dlxCommand(params.packageManager);
@@ -61,21 +63,25 @@ export const add = new Command()
61
63
  .option("--use-yarn", "explicitly use yarn")
62
64
  .option("--use-bun", "explicitly use bun")
63
65
  .action(async (components: string[], opts) => {
66
+ const platform = detectRegistryPlatform(opts.cwd);
67
+
64
68
  // Check if project is initialized
65
69
  if (!hasConfig(opts.cwd)) {
66
70
  logger.warn(
67
- "It looks like you haven't initialized your project yet — defaulting to Base UI flavored components. Run 'assistant-ui init' first for a configured setup.",
71
+ `It looks like you haven't initialized your project yet. Defaulting to ${platform === "native" ? "the native component tree" : "Base UI flavored components"}. Run 'assistant-ui init' first for a configured setup.`,
68
72
  );
69
73
  logger.break();
70
74
  }
71
75
 
76
+ logger.info(`Using the ${platform} registry tree.`);
72
77
  logger.step(`Adding ${components.length} component(s)...`);
73
78
 
74
79
  const packageManager = await resolvePackageManagerForCwd(
75
80
  opts.cwd,
76
81
  resolvePackageManager(opts),
77
82
  );
78
- const style = getComponentsJsonStyle(opts.cwd);
83
+ const style =
84
+ platform === "web" ? getComponentsJsonStyle(opts.cwd) : undefined;
79
85
  const { command, args } = createAddComponentsPlan({
80
86
  components,
81
87
  packageManager,
@@ -83,6 +89,7 @@ export const add = new Command()
83
89
  overwrite: opts.overwrite,
84
90
  path: opts.path,
85
91
  ...(style === undefined ? {} : { style }),
92
+ platform,
86
93
  });
87
94
 
88
95
  try {
@@ -195,7 +195,7 @@ export const PROJECT_METADATA: ProjectMetadata[] = [
195
195
  description: "Expo / React Native",
196
196
  category: "example",
197
197
  path: "examples/with-expo",
198
- hasLocalComponents: true,
198
+ hasLocalComponents: false,
199
199
  },
200
200
  {
201
201
  name: "with-interactables",
@@ -282,8 +282,6 @@ export const PROJECT_METADATA: ProjectMetadata[] = [
282
282
  // Examples that exist in the monorepo but are intentionally excluded from the CLI:
283
283
  //
284
284
  // - waterfall: Still in development, not ready for production.
285
- // - with-cloud-standalone: For cloud without assistant-ui — not for the
286
- // assistant-ui CLI.
287
285
  // - with-store: In development, not ready for public use of the tap store.
288
286
  // - with-tap-runtime: In development, not ready for public use of the tap
289
287
  // store.
@@ -522,6 +520,12 @@ export const create = new Command()
522
520
  .option("--skip-install", "skip installing packages")
523
521
  .option("--skills", "add assistant-ui agent skills for AI coding assistants")
524
522
  .option("--no-skills", "skip adding assistant-ui agent skills")
523
+ .addOption(
524
+ new Option(
525
+ "--cwd <cwd>",
526
+ "the working directory. defaults to the current directory.",
527
+ ).hideHelp(),
528
+ )
525
529
  .addOption(
526
530
  new Option(
527
531
  "--debug-source-root <path>",
@@ -577,9 +581,13 @@ export const create = new Command()
577
581
  }
578
582
 
579
583
  // Check directory
580
- const absoluteProjectDir = path.resolve(resolvedProjectDirectory);
584
+ const absoluteProjectDir = path.resolve(
585
+ opts.cwd ?? process.cwd(),
586
+ resolvedProjectDirectory,
587
+ );
581
588
  const { display: displayProjectDir, cdCommand } =
582
589
  resolveProjectDirectoryGuidance({ absoluteProjectDir });
590
+ let projectDirExisted = true;
583
591
  try {
584
592
  const files = fs.readdirSync(absoluteProjectDir);
585
593
  if (files.length > 0) {
@@ -593,6 +601,7 @@ export const create = new Command()
593
601
  err instanceof Error ? (err as NodeJS.ErrnoException).code : undefined;
594
602
  if (code === "ENOENT") {
595
603
  // Directory doesn't exist — good, proceed
604
+ projectDirExisted = false;
596
605
  } else if (code === "ENOTDIR") {
597
606
  logger.error(
598
607
  `${displayProjectDir} already exists and is not a directory`,
@@ -640,11 +649,24 @@ export const create = new Command()
640
649
  );
641
650
 
642
651
  // Clean up partial project directory on unexpected exit (e.g. Ctrl+C)
652
+ const resetProjectDir = () => {
653
+ if (!projectDirExisted) {
654
+ fs.rmSync(absoluteProjectDir, { recursive: true, force: true });
655
+ return;
656
+ }
657
+ if (!fs.existsSync(absoluteProjectDir)) return;
658
+ for (const entry of fs.readdirSync(absoluteProjectDir)) {
659
+ fs.rmSync(path.join(absoluteProjectDir, entry), {
660
+ recursive: true,
661
+ force: true,
662
+ });
663
+ }
664
+ };
643
665
  let cleanupArmed = true;
644
666
  const cleanupOnExit = () => {
645
667
  if (!cleanupArmed) return;
646
668
  cleanupArmed = false;
647
- fs.rmSync(absoluteProjectDir, { recursive: true, force: true });
669
+ resetProjectDir();
648
670
  };
649
671
  const disarmCleanup = () => {
650
672
  cleanupArmed = false;
@@ -653,8 +675,8 @@ export const create = new Command()
653
675
  process.removeListener("SIGTERM", cleanupOnSignal);
654
676
  };
655
677
  // Node emits no "exit" when a signal kills the process. An in-flight
656
- // runSpawn forwards the signal itself, so the directory is removed on the
657
- // error path once the child is reaped rather than while it is still writing.
678
+ // runSpawn forwards the signal itself, so cleanup runs on the error path
679
+ // once the child is reaped rather than while it is still writing.
658
680
  const cleanupOnSignal = (signal: NodeJS.Signals) => {
659
681
  if (hasActiveSpawn()) return;
660
682
  cleanupOnExit();
@@ -698,7 +720,7 @@ export const create = new Command()
698
720
  ref &&
699
721
  !fs.existsSync(path.join(absoluteProjectDir, "package.json"))
700
722
  ) {
701
- fs.rmSync(absoluteProjectDir, { recursive: true, force: true });
723
+ resetProjectDir();
702
724
  logger.warn(
703
725
  "Template not found at release tag, downloading from HEAD",
704
726
  );
@@ -799,6 +821,9 @@ export const create = new Command()
799
821
  logger.info(` ${cdCommand}`);
800
822
  if (opts.skipInstall) {
801
823
  logger.info(` ${pm} install`);
824
+ if (transformResult.registryInstallCommand) {
825
+ logger.info(` ${transformResult.registryInstallCommand}`);
826
+ }
802
827
  }
803
828
  logger.info(` # Set up your environment variables in ${envFile}`);
804
829
  logger.info(` ${runCmd} ${devScript}`);
@@ -23,7 +23,6 @@ const ASSISTANT_UI_PACKAGES = [
23
23
  // Streaming & Cloud
24
24
  "assistant-stream",
25
25
  "assistant-cloud",
26
- "@assistant-ui/cloud-ai-sdk",
27
26
  // Adapters
28
27
  "@assistant-ui/eve",
29
28
  "@assistant-ui/ai-sdk",
@@ -83,8 +83,7 @@ export const init = new Command()
83
83
  logger.break();
84
84
  }
85
85
 
86
- const createArgs: string[] = [];
87
- if (projectDirectory) createArgs.push(targetDir);
86
+ const createArgs = projectDirectory ? [targetDir] : ["--cwd", cwd];
88
87
  if (presetUrl) createArgs.push("--preset", presetUrl);
89
88
  if (opts.useNpm) createArgs.push("--use-npm");
90
89
  if (opts.usePnpm) createArgs.push("--use-pnpm");
@@ -75,9 +75,6 @@ const MCP_CONFIGS: Record<
75
75
  if (process.platform === "win32") {
76
76
  return path.join(process.env.APPDATA || "", "Zed", "settings.json");
77
77
  }
78
- if (process.platform === "darwin") {
79
- return path.join(os.homedir(), ".zed", "settings.json");
80
- }
81
78
  return path.join(os.homedir(), ".config", "zed", "settings.json");
82
79
  },
83
80
  config: {
@@ -10,6 +10,10 @@ import { logger } from "./utils/logger";
10
10
  import { runSpawn, SpawnExitError, SpawnSignalError } from "./run-spawn";
11
11
  import { type PackageManagerName } from "./utils/package-manager";
12
12
  import { readProjectFiles } from "./utils/file-scanner";
13
+ import {
14
+ detectRegistryPlatform,
15
+ resolveRegistryItemUrl,
16
+ } from "./utils/registry";
13
17
 
14
18
  export function dlxCommand(pm: PackageManagerName): [string, string[]] {
15
19
  switch (pm) {
@@ -186,6 +190,7 @@ export async function scaffoldProject(
186
190
 
187
191
  export interface TransformResult {
188
192
  registryInstallFailure?: { retryCommand: string };
193
+ registryInstallCommand?: string;
189
194
  }
190
195
 
191
196
  export async function transformProject(
@@ -199,29 +204,23 @@ export async function transformProject(
199
204
  transformTsConfig(projectDir);
200
205
  transformCssFiles(projectDir);
201
206
 
202
- let assistantUI: string[] | undefined;
203
- let shadcnUI: string[] | undefined;
204
-
205
- if (!opts.hasLocalComponents) {
206
- const components = scanRequiredComponents(projectDir);
207
- assistantUI = components.assistantUI;
208
- shadcnUI = components.shadcnUI;
209
- }
207
+ const components = opts.hasLocalComponents
208
+ ? undefined
209
+ : resolveRegistryComponents(projectDir, scanRequiredComponents(projectDir));
210
210
 
211
211
  const pm = opts.packageManager;
212
- if (!opts.skipInstall) {
213
- logger.step("Installing dependencies...");
214
- await installDependencies(projectDir, pm);
212
+ if (opts.skipInstall) {
213
+ if (!components) return {};
214
+ const [cmd, dlxArgs] = dlxCommand(pm);
215
+ return {
216
+ registryInstallCommand: `${cmd} ${[...dlxArgs, "shadcn@latest", "add", ...components].join(" ")}`,
217
+ };
215
218
  }
216
219
 
217
- if (
218
- !opts.skipInstall &&
219
- !opts.hasLocalComponents &&
220
- shadcnUI &&
221
- assistantUI
222
- ) {
223
- const auiComponents = assistantUI.map((c) => `@assistant-ui/${c}`);
224
- const components = ["@assistant-ui/utils", ...shadcnUI, ...auiComponents];
220
+ logger.step("Installing dependencies...");
221
+ await installDependencies(projectDir, pm);
222
+
223
+ if (components) {
225
224
  logger.step(`Installing components: ${components.join(", ")}...`);
226
225
  const failure = await installShadcnRegistry(
227
226
  projectDir,
@@ -235,6 +234,22 @@ export async function transformProject(
235
234
  return {};
236
235
  }
237
236
 
237
+ function resolveRegistryComponents(
238
+ projectDir: string,
239
+ { assistantUI, shadcnUI }: RequiredComponents,
240
+ ): string[] {
241
+ if (detectRegistryPlatform(projectDir) === "native") {
242
+ return ["utils", ...shadcnUI, ...assistantUI].map((component) =>
243
+ resolveRegistryItemUrl(component, undefined, "native"),
244
+ );
245
+ }
246
+ return [
247
+ "@assistant-ui/utils",
248
+ ...shadcnUI,
249
+ ...assistantUI.map((component) => `@assistant-ui/${component}`),
250
+ ];
251
+ }
252
+
238
253
  function transformPackageJson(projectDir: string): void {
239
254
  const pkgPath = path.join(projectDir, "package.json");
240
255
  const pkg = JSON.parse(fs.readFileSync(pkgPath, "utf-8"));
@@ -543,7 +558,7 @@ export async function reconcileAssistantUIImportLayout(
543
558
  }
544
559
  }
545
560
 
546
- function scanRequiredComponents(projectDir: string): RequiredComponents {
561
+ export function scanRequiredComponents(projectDir: string): RequiredComponents {
547
562
  const assistantUIComponents = new Set<string>();
548
563
  const shadcnUIComponents = new Set<string>();
549
564
 
@@ -36,7 +36,6 @@ const trackSignal = (signal: NodeJS.Signals) => {
36
36
  describe("runSpawn", () => {
37
37
  afterEach(() => {
38
38
  vi.restoreAllMocks();
39
- vi.clearAllMocks();
40
39
  });
41
40
 
42
41
  it("forwards the first termination signal and cleans up listeners", async () => {
@@ -3,6 +3,7 @@ import * as os from "node:os";
3
3
  import * as path from "node:path";
4
4
  import { afterEach, beforeEach, describe, expect, it } from "vitest";
5
5
  import {
6
+ detectRegistryPlatform,
6
7
  getComponentsJsonStyle,
7
8
  resolveQuickStartRegistryUrl,
8
9
  resolveRegistryItemUrl,
@@ -61,6 +62,49 @@ describe("getComponentsJsonStyle", () => {
61
62
  });
62
63
  });
63
64
 
65
+ describe("detectRegistryPlatform", () => {
66
+ let cwd: string;
67
+
68
+ beforeEach(() => {
69
+ cwd = fs.mkdtempSync(path.join(os.tmpdir(), "assistant-ui-cli-"));
70
+ });
71
+
72
+ afterEach(() => {
73
+ fs.rmSync(cwd, { recursive: true, force: true });
74
+ });
75
+
76
+ it("detects react-native in dependencies", () => {
77
+ fs.writeFileSync(
78
+ path.join(cwd, "package.json"),
79
+ JSON.stringify({ dependencies: { "react-native": "0.86.3" } }),
80
+ );
81
+
82
+ expect(detectRegistryPlatform(cwd)).toBe("native");
83
+ });
84
+
85
+ it("detects react-native in devDependencies", () => {
86
+ fs.writeFileSync(
87
+ path.join(cwd, "package.json"),
88
+ JSON.stringify({ devDependencies: { "react-native": "0.86.3" } }),
89
+ );
90
+
91
+ expect(detectRegistryPlatform(cwd)).toBe("native");
92
+ });
93
+
94
+ it("uses web without react-native", () => {
95
+ fs.writeFileSync(
96
+ path.join(cwd, "package.json"),
97
+ JSON.stringify({ dependencies: { react: "19.2.3" } }),
98
+ );
99
+
100
+ expect(detectRegistryPlatform(cwd)).toBe("web");
101
+ });
102
+
103
+ it("uses web when package.json is missing", () => {
104
+ expect(detectRegistryPlatform(cwd)).toBe("web");
105
+ });
106
+ });
107
+
64
108
  describe("resolveQuickStartRegistryUrl", () => {
65
109
  it("uses the base quick start for base styles", () => {
66
110
  expect(resolveQuickStartRegistryUrl("base-nova")).toBe(
@@ -111,4 +155,16 @@ describe("resolveRegistryItemUrl", () => {
111
155
  "https://r.assistant-ui.com/styles/base-nova%3Fpreview%3D1/thread.json",
112
156
  );
113
157
  });
158
+
159
+ it("uses the native URL regardless of style", () => {
160
+ expect(resolveRegistryItemUrl("thread", "base-nova", "native")).toBe(
161
+ "https://r.assistant-ui.com/native/thread.json",
162
+ );
163
+ });
164
+
165
+ it("keeps shared items at the root URL on native", () => {
166
+ expect(resolveRegistryItemUrl("utils", undefined, "native")).toBe(
167
+ "https://r.assistant-ui.com/utils.json",
168
+ );
169
+ });
114
170
  });
@@ -2,6 +2,34 @@ import * as fs from "node:fs";
2
2
  import * as path from "node:path";
3
3
 
4
4
  const REGISTRY_BASE_URL = "https://r.assistant-ui.com";
5
+ export const SHARED_REGISTRY_ITEMS = new Set(["utils"]);
6
+
7
+ export function detectRegistryPlatform(cwd: string): "web" | "native" {
8
+ try {
9
+ const packageJsonPath = path.join(cwd, "package.json");
10
+ const packageJson = JSON.parse(
11
+ fs.readFileSync(packageJsonPath, "utf8"),
12
+ ) as {
13
+ dependencies?: unknown;
14
+ devDependencies?: unknown;
15
+ };
16
+ const dependencyGroups = [
17
+ packageJson.dependencies,
18
+ packageJson.devDependencies,
19
+ ];
20
+
21
+ return dependencyGroups.some(
22
+ (dependencies) =>
23
+ typeof dependencies === "object" &&
24
+ dependencies !== null &&
25
+ Object.hasOwn(dependencies, "react-native"),
26
+ )
27
+ ? "native"
28
+ : "web";
29
+ } catch {
30
+ return "web";
31
+ }
32
+ }
5
33
 
6
34
  export function getComponentsJsonStyle(cwd: string): string | undefined {
7
35
  try {
@@ -30,7 +58,14 @@ export function resolveQuickStartRegistryUrl(style?: string): string {
30
58
  export function resolveRegistryItemUrl(
31
59
  component: string,
32
60
  style?: string,
61
+ platform: "web" | "native" = "web",
33
62
  ): string {
63
+ if (platform === "native") {
64
+ return SHARED_REGISTRY_ITEMS.has(component)
65
+ ? `${REGISTRY_BASE_URL}/${encodeURIComponent(component)}.json`
66
+ : `${REGISTRY_BASE_URL}/native/${encodeURIComponent(component)}.json`;
67
+ }
68
+
34
69
  if (style === undefined) {
35
70
  return `${REGISTRY_BASE_URL}/base/${encodeURIComponent(component)}.json`;
36
71
  }
package/src/run.test.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { beforeEach, describe, expect, it, vi } from "vitest";
1
+ import { describe, expect, it, vi } from "vitest";
2
2
 
3
3
  const mocks = vi.hoisted(() => ({
4
4
  parseAsync: vi.fn(),
@@ -13,10 +13,6 @@ vi.mock("./program", () => ({
13
13
  import { runCli } from "./run";
14
14
 
15
15
  describe("runCli", () => {
16
- beforeEach(() => {
17
- vi.clearAllMocks();
18
- });
19
-
20
16
  it("awaits and propagates asynchronous command failures", async () => {
21
17
  const error = new Error("command failed");
22
18
  mocks.parseAsync.mockRejectedValue(error);