@zapier/zapier-sdk-cli 0.13.9 → 0.13.10

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zapier/zapier-sdk-cli",
3
- "version": "0.13.9",
3
+ "version": "0.13.10",
4
4
  "description": "Command line interface for Zapier SDK",
5
5
  "main": "dist/index.cjs",
6
6
  "module": "dist/index.mjs",
@@ -44,8 +44,8 @@
44
44
  "typescript": "^5.8.3",
45
45
  "zod": "^3.25.67",
46
46
  "@zapier/zapier-sdk": "0.13.7",
47
- "@zapier/zapier-sdk-mcp": "0.3.20",
48
- "@zapier/zapier-sdk-cli-login": "0.3.3"
47
+ "@zapier/zapier-sdk-cli-login": "0.3.3",
48
+ "@zapier/zapier-sdk-mcp": "0.3.20"
49
49
  },
50
50
  "devDependencies": {
51
51
  "@types/express": "^5.0.3",
@@ -161,15 +161,6 @@ export const addPlugin: Plugin<
161
161
  if (successfulApps.length > 0) {
162
162
  console.log(`✅ Added ${successfulApps.length} app(s) to manifest`);
163
163
  }
164
-
165
- // Report any errors
166
- const allErrors = [...manifestResult.errors, ...typesResult.errors];
167
- if (allErrors.length > 0) {
168
- console.warn(`\n⚠️ ${allErrors.length} error(s) occurred:`);
169
- allErrors.forEach(({ appKey, error }) => {
170
- console.warn(` - ${appKey}: ${error}`);
171
- });
172
- }
173
164
  }, AddSchema);
174
165
 
175
166
  return {
@@ -7,7 +7,11 @@ import type {
7
7
  ManifestEntry,
8
8
  UpdateManifestEntryOptions,
9
9
  } from "@zapier/zapier-sdk";
10
- import { createSdk } from "@zapier/zapier-sdk";
10
+ import {
11
+ createSdk,
12
+ ZapierUnknownError,
13
+ ZapierValidationError,
14
+ } from "@zapier/zapier-sdk";
11
15
 
12
16
  const mockSlackApp: AppItem = {
13
17
  key: "SlackCLIAPI",
@@ -170,7 +174,6 @@ describe("buildManifest plugin", () => {
170
174
  // Should return manifest with entries
171
175
  expect(result.manifest).toBeDefined();
172
176
  expect(result.manifest?.apps).toBeDefined();
173
- expect(result.errors).toEqual([]);
174
177
  });
175
178
 
176
179
  it("should process apps and create manifest entries", async () => {
@@ -182,7 +185,6 @@ describe("buildManifest plugin", () => {
182
185
  });
183
186
 
184
187
  expect(result.manifest?.apps).toBeDefined();
185
- expect(result.errors).toEqual([]);
186
188
  });
187
189
 
188
190
  it("should return empty result when no apps found", async () => {
@@ -194,7 +196,6 @@ describe("buildManifest plugin", () => {
194
196
  });
195
197
 
196
198
  expect(result.manifest).toBeUndefined();
197
- expect(result.errors).toEqual([]);
198
199
  });
199
200
  });
200
201
 
@@ -252,7 +253,6 @@ describe("buildManifest plugin", () => {
252
253
  implementationName: "GmailCLIAPI",
253
254
  version: "2.5.0",
254
255
  });
255
- expect(result.errors).toEqual([]);
256
256
  });
257
257
 
258
258
  it("should accumulate manifest entries across multiple apps", async () => {
@@ -426,85 +426,129 @@ describe("buildManifest plugin", () => {
426
426
  });
427
427
 
428
428
  describe("error handling", () => {
429
- it("should handle apps without version", async () => {
429
+ it("should throw ZapierUnknownError when createManifestEntry fails", async () => {
430
430
  const sdk = createTestSdk([mockAppWithoutVersion]);
431
431
 
432
- const result = await sdk.buildManifest({
433
- appKeys: ["broken"],
434
- skipWrite: true,
435
- });
432
+ await expect(
433
+ sdk.buildManifest({
434
+ appKeys: ["broken"],
435
+ skipWrite: true,
436
+ }),
437
+ ).rejects.toThrow(ZapierUnknownError);
438
+ });
436
439
 
437
- expect(result.errors).toHaveLength(1);
438
- expect(result.errors[0]).toEqual({
439
- appKey: "BrokenAPI",
440
- error: expect.stringContaining("Failed to process app"),
441
- });
440
+ it("should include app key in error message when processing fails", async () => {
441
+ const sdk = createTestSdk([mockAppWithoutVersion]);
442
+
443
+ await expect(
444
+ sdk.buildManifest({
445
+ appKeys: ["broken"],
446
+ skipWrite: true,
447
+ }),
448
+ ).rejects.toThrow(/Failed to process app BrokenAPI/);
442
449
  });
443
450
 
444
- it("should emit app_processing_error event on failure", async () => {
451
+ it("should emit app_processing_error event before throwing", async () => {
445
452
  const sdk = createTestSdk([mockAppWithoutVersion]);
446
453
  const onProgress = vi.fn();
447
454
 
448
- await sdk.buildManifest({
449
- appKeys: ["broken"],
450
- skipWrite: true,
451
- onProgress,
452
- });
455
+ await expect(
456
+ sdk.buildManifest({
457
+ appKeys: ["broken"],
458
+ skipWrite: true,
459
+ onProgress,
460
+ }),
461
+ ).rejects.toThrow();
453
462
 
454
463
  expect(onProgress).toHaveBeenCalledWith({
455
464
  type: "app_processing_error",
456
465
  appKey: "BrokenAPI",
457
- error: expect.stringContaining("Failed to process app"),
466
+ error: expect.stringContaining("Failed to process app BrokenAPI"),
458
467
  });
459
468
  });
460
469
 
461
- it("should continue processing other apps after error", async () => {
470
+ it("should throw immediately on first error and not continue processing", async () => {
462
471
  const sdk = createTestSdk([mockAppWithoutVersion, mockSlackApp]);
463
472
 
464
- const result = await sdk.buildManifest({
465
- appKeys: ["broken", "slack"],
466
- skipWrite: true,
467
- });
468
-
469
- // Should have one error
470
- expect(result.errors).toHaveLength(1);
471
- expect(result.errors[0].appKey).toBe("BrokenAPI");
473
+ await expect(
474
+ sdk.buildManifest({
475
+ appKeys: ["broken", "slack"],
476
+ skipWrite: true,
477
+ }),
478
+ ).rejects.toThrow(ZapierUnknownError);
472
479
 
473
- // Should still process successful app
474
- expect(result.manifest?.apps?.SlackCLIAPI).toBeDefined();
480
+ // updateManifestEntry should not be called since first app failed
481
+ expect(mockUpdateManifestEntry).not.toHaveBeenCalled();
475
482
  });
476
483
 
477
- it("should handle updateManifestEntry failure", async () => {
484
+ it("should throw ZapierUnknownError when updateManifestEntry fails", async () => {
478
485
  mockUpdateManifestEntry.mockRejectedValueOnce(new Error("Write failed"));
479
486
  const sdk = createTestSdk();
480
487
 
481
- const result = await sdk.buildManifest({
482
- appKeys: ["slack"],
483
- skipWrite: false,
484
- });
488
+ await expect(
489
+ sdk.buildManifest({
490
+ appKeys: ["slack"],
491
+ skipWrite: false,
492
+ }),
493
+ ).rejects.toThrow(ZapierUnknownError);
494
+ });
485
495
 
486
- expect(result.errors).toHaveLength(1);
487
- expect(result.errors[0]).toEqual({
488
- appKey: "SlackCLIAPI",
489
- error: "Failed to process app: Error: Write failed",
490
- });
496
+ it("should include original error as cause", async () => {
497
+ const originalError = new Error("Write failed");
498
+ mockUpdateManifestEntry.mockRejectedValueOnce(originalError);
499
+ const sdk = createTestSdk();
500
+
501
+ try {
502
+ await sdk.buildManifest({
503
+ appKeys: ["slack"],
504
+ skipWrite: false,
505
+ });
506
+ expect.fail("Should have thrown");
507
+ } catch (error) {
508
+ expect(error).toBeInstanceOf(ZapierUnknownError);
509
+ if (error instanceof ZapierUnknownError) {
510
+ expect(error.cause).toBe(originalError);
511
+ expect(error.message).toContain("Failed to process app SlackCLIAPI");
512
+ expect(error.message).toContain("Write failed");
513
+ }
514
+ }
515
+ });
516
+
517
+ it("should preserve ZapierValidationError if thrown from underlying code", async () => {
518
+ const validationError = new ZapierValidationError(
519
+ "Invalid manifest entry",
520
+ );
521
+ mockUpdateManifestEntry.mockRejectedValueOnce(validationError);
522
+ const sdk = createTestSdk();
523
+
524
+ await expect(
525
+ sdk.buildManifest({
526
+ appKeys: ["slack"],
527
+ skipWrite: false,
528
+ }),
529
+ ).rejects.toThrow(ZapierValidationError);
491
530
  });
492
531
 
493
- it("should accumulate multiple errors", async () => {
532
+ it("should stop processing after first app error", async () => {
494
533
  mockUpdateManifestEntry
495
534
  .mockRejectedValueOnce(new Error("First error"))
496
- .mockRejectedValueOnce(new Error("Second error"));
535
+ .mockResolvedValueOnce([
536
+ "GmailCLIAPI",
537
+ { implementationName: "GmailCLIAPI", version: "2.5.0" },
538
+ { apps: {} },
539
+ ]);
497
540
 
498
541
  const sdk = createTestSdk();
499
542
 
500
- const result = await sdk.buildManifest({
501
- appKeys: ["slack", "gmail"],
502
- skipWrite: false,
503
- });
543
+ await expect(
544
+ sdk.buildManifest({
545
+ appKeys: ["slack", "gmail"],
546
+ skipWrite: false,
547
+ }),
548
+ ).rejects.toThrow(ZapierUnknownError);
504
549
 
505
- expect(result.errors).toHaveLength(2);
506
- expect(result.errors[0].appKey).toBe("SlackCLIAPI");
507
- expect(result.errors[1].appKey).toBe("GmailCLIAPI");
550
+ // Should only call once (for first app that fails)
551
+ expect(mockUpdateManifestEntry).toHaveBeenCalledTimes(1);
508
552
  });
509
553
  });
510
554
 
@@ -574,7 +618,6 @@ describe("buildManifest plugin", () => {
574
618
  });
575
619
 
576
620
  expect(result.manifest).toBeUndefined();
577
- expect(result.errors).toEqual([]);
578
621
  });
579
622
 
580
623
  it("should not call updateManifestEntry when no apps found", async () => {
@@ -7,7 +7,11 @@ import type {
7
7
  AppItem,
8
8
  Manifest,
9
9
  } from "@zapier/zapier-sdk";
10
- import { createFunction } from "@zapier/zapier-sdk";
10
+ import {
11
+ createFunction,
12
+ ZapierValidationError,
13
+ ZapierUnknownError,
14
+ } from "@zapier/zapier-sdk";
11
15
  import {
12
16
  BuildManifestSchema,
13
17
  type BuildManifestOptions,
@@ -38,10 +42,6 @@ export const buildManifestPlugin: Plugin<
38
42
  ): Promise<BuildManifestResult> {
39
43
  const { appKeys, skipWrite = false, configPath, onProgress } = options;
40
44
 
41
- const result: BuildManifestResult = {
42
- errors: [],
43
- };
44
-
45
45
  // Get apps using listApps (which respects existing manifest for version locking)
46
46
  onProgress?.({ type: "apps_lookup_start", count: appKeys.length });
47
47
  const appsIterator = sdk.listApps({ appKeys }).items();
@@ -53,7 +53,7 @@ export const buildManifestPlugin: Plugin<
53
53
  onProgress?.({ type: "apps_lookup_complete", count: apps.length });
54
54
 
55
55
  if (apps.length === 0) {
56
- return result;
56
+ return {};
57
57
  }
58
58
 
59
59
  let updatedManifest: Manifest | undefined;
@@ -96,22 +96,25 @@ export const buildManifestPlugin: Plugin<
96
96
 
97
97
  onProgress?.({ type: "app_processing_complete", appKey: app.key });
98
98
  } catch (error) {
99
- const errorMessage = `Failed to process app: ${error}`;
100
- result.errors.push({
101
- appKey: app.key,
102
- error: errorMessage,
103
- });
99
+ const errorMessage = `Failed to process app ${app.key}: ${error instanceof Error ? error.message : String(error)}`;
100
+
104
101
  onProgress?.({
105
102
  type: "app_processing_error",
106
103
  appKey: app.key,
107
104
  error: errorMessage,
108
105
  });
106
+
107
+ if (error instanceof ZapierValidationError) {
108
+ throw error; // Preserve the specific error type
109
+ } else {
110
+ throw new ZapierUnknownError(errorMessage, {
111
+ cause: error, // Works for both Error and non-Error
112
+ });
113
+ }
109
114
  }
110
115
  }
111
116
 
112
- result.manifest = updatedManifest;
113
-
114
- return result;
117
+ return { manifest: updatedManifest };
115
118
  }, BuildManifestSchema);
116
119
 
117
120
  return {
@@ -52,8 +52,4 @@ export type ManifestBuildProgressEvent =
52
52
 
53
53
  export interface BuildManifestResult {
54
54
  manifest?: Manifest;
55
- errors: Array<{
56
- appKey: string;
57
- error: string;
58
- }>;
59
55
  }