@zapier/zapier-sdk 0.5.1 → 0.6.0
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 +19 -0
- package/README.md +107 -83
- package/dist/api/index.d.ts +1 -1
- package/dist/api/index.d.ts.map +1 -1
- package/dist/api/schemas.d.ts +6 -6
- package/dist/api/types.d.ts +7 -7
- package/dist/api/types.d.ts.map +1 -1
- package/dist/index.cjs +343 -67
- package/dist/index.d.mts +416 -347
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +0 -1
- package/dist/index.mjs +343 -67
- package/dist/plugins/api/index.js +1 -1
- package/dist/plugins/apps/types.d.ts +1 -1
- package/dist/plugins/apps/types.d.ts.map +1 -1
- package/dist/plugins/findFirstAuthentication/index.d.ts.map +1 -1
- package/dist/plugins/findFirstAuthentication/index.js +1 -0
- package/dist/plugins/findUniqueAuthentication/index.d.ts.map +1 -1
- package/dist/plugins/findUniqueAuthentication/index.js +1 -0
- package/dist/plugins/getAction/index.d.ts.map +1 -1
- package/dist/plugins/getAction/index.js +1 -0
- package/dist/plugins/getAction/index.test.js +1 -1
- package/dist/plugins/getApp/index.d.ts +6 -3
- package/dist/plugins/getApp/index.d.ts.map +1 -1
- package/dist/plugins/getApp/index.js +8 -18
- package/dist/plugins/getApp/index.test.js +2 -0
- package/dist/plugins/getAuthentication/index.d.ts.map +1 -1
- package/dist/plugins/getAuthentication/index.js +1 -0
- package/dist/plugins/getAuthentication/index.test.js +12 -1
- package/dist/plugins/getProfile/index.d.ts.map +1 -1
- package/dist/plugins/getProfile/index.js +1 -0
- package/dist/plugins/listActions/index.d.ts +5 -3
- package/dist/plugins/listActions/index.d.ts.map +1 -1
- package/dist/plugins/listActions/index.js +6 -6
- package/dist/plugins/listActions/index.test.js +26 -74
- package/dist/plugins/listActions/schemas.d.ts +4 -4
- package/dist/plugins/listApps/index.d.ts.map +1 -1
- package/dist/plugins/listApps/index.js +1 -0
- package/dist/plugins/listApps/schemas.d.ts +2 -2
- package/dist/plugins/listAuthentications/index.d.ts +4 -2
- package/dist/plugins/listAuthentications/index.d.ts.map +1 -1
- package/dist/plugins/listAuthentications/index.js +9 -12
- package/dist/plugins/listAuthentications/index.test.js +33 -40
- package/dist/plugins/listAuthentications/schemas.d.ts +4 -4
- package/dist/plugins/listInputFields/index.d.ts +3 -1
- package/dist/plugins/listInputFields/index.d.ts.map +1 -1
- package/dist/plugins/listInputFields/index.js +5 -5
- package/dist/plugins/listInputFields/index.test.js +10 -8
- package/dist/plugins/listInputFields/schemas.d.ts +4 -4
- package/dist/plugins/lockVersion/index.d.ts +24 -0
- package/dist/plugins/lockVersion/index.d.ts.map +1 -0
- package/dist/plugins/lockVersion/index.js +72 -0
- package/dist/plugins/lockVersion/index.test.d.ts +2 -0
- package/dist/plugins/lockVersion/index.test.d.ts.map +1 -0
- package/dist/plugins/lockVersion/index.test.js +129 -0
- package/dist/plugins/lockVersion/schemas.d.ts +10 -0
- package/dist/plugins/lockVersion/schemas.d.ts.map +1 -0
- package/dist/plugins/lockVersion/schemas.js +6 -0
- package/dist/plugins/manifest/index.d.ts +24 -0
- package/dist/plugins/manifest/index.d.ts.map +1 -0
- package/dist/plugins/manifest/index.js +119 -0
- package/dist/plugins/manifest/index.test.d.ts +2 -0
- package/dist/plugins/manifest/index.test.d.ts.map +1 -0
- package/dist/plugins/manifest/index.test.js +331 -0
- package/dist/plugins/manifest/schemas.d.ts +64 -0
- package/dist/plugins/manifest/schemas.d.ts.map +1 -0
- package/dist/plugins/manifest/schemas.js +25 -0
- package/dist/plugins/registry/index.d.ts +9 -1
- package/dist/plugins/registry/index.d.ts.map +1 -1
- package/dist/plugins/registry/index.js +68 -3
- package/dist/plugins/request/index.d.ts.map +1 -1
- package/dist/plugins/request/index.js +1 -0
- package/dist/plugins/request/index.test.js +6 -1
- package/dist/plugins/request/schemas.d.ts +4 -4
- package/dist/plugins/runAction/index.d.ts +2 -0
- package/dist/plugins/runAction/index.d.ts.map +1 -1
- package/dist/plugins/runAction/index.js +5 -5
- package/dist/plugins/runAction/index.test.js +9 -8
- package/dist/plugins/runAction/schemas.d.ts +4 -4
- package/dist/schemas/Auth.d.ts +4 -4
- package/dist/schemas/Field.d.ts.map +1 -1
- package/dist/sdk.d.ts +3 -3
- package/dist/sdk.d.ts.map +1 -1
- package/dist/sdk.js +18 -7
- package/dist/sdk.test.js +1 -1
- package/dist/types/errors.d.ts +6 -6
- package/dist/types/errors.d.ts.map +1 -1
- package/dist/types/events.d.ts +1 -1
- package/dist/types/events.d.ts.map +1 -1
- package/dist/types/plugin.d.ts +10 -2
- package/dist/types/plugin.d.ts.map +1 -1
- package/dist/types/sdk.d.ts +13 -2
- package/dist/types/sdk.d.ts.map +1 -1
- package/dist/utils/validation.test.js +2 -1
- package/package.json +2 -2
- package/src/api/client.ts +3 -3
- package/src/api/index.ts +2 -0
- package/src/api/types.ts +15 -7
- package/src/index.ts +0 -2
- package/src/plugins/api/index.ts +1 -1
- package/src/plugins/apps/types.ts +1 -1
- package/src/plugins/findFirstAuthentication/index.ts +1 -0
- package/src/plugins/findUniqueAuthentication/index.ts +1 -0
- package/src/plugins/getAction/index.test.ts +1 -1
- package/src/plugins/getAction/index.ts +1 -0
- package/src/plugins/getApp/index.test.ts +2 -0
- package/src/plugins/getApp/index.ts +12 -24
- package/src/plugins/getAuthentication/index.test.ts +13 -3
- package/src/plugins/getAuthentication/index.ts +1 -0
- package/src/plugins/getProfile/index.ts +1 -0
- package/src/plugins/listActions/index.test.ts +30 -89
- package/src/plugins/listActions/index.ts +34 -27
- package/src/plugins/listApps/index.ts +1 -0
- package/src/plugins/listAuthentications/index.test.ts +38 -47
- package/src/plugins/listAuthentications/index.ts +21 -18
- package/src/plugins/listInputFields/index.test.ts +12 -9
- package/src/plugins/listInputFields/index.ts +10 -6
- package/src/plugins/lockVersion/index.test.ts +176 -0
- package/src/plugins/lockVersion/index.ts +112 -0
- package/src/plugins/lockVersion/schemas.ts +9 -0
- package/src/plugins/manifest/index.test.ts +439 -0
- package/src/plugins/manifest/index.ts +171 -0
- package/src/plugins/manifest/schemas.ts +53 -0
- package/src/plugins/registry/index.ts +89 -8
- package/src/plugins/request/index.test.ts +8 -4
- package/src/plugins/request/index.ts +1 -0
- package/src/plugins/runAction/index.test.ts +9 -8
- package/src/plugins/runAction/index.ts +18 -9
- package/src/schemas/Field.ts +5 -2
- package/src/sdk.test.ts +1 -1
- package/src/sdk.ts +22 -7
- package/src/types/errors.ts +9 -6
- package/src/types/events.ts +1 -1
- package/src/types/plugin.ts +14 -2
- package/src/types/sdk.ts +15 -1
- package/src/utils/validation.test.ts +2 -1
- package/tsconfig.tsbuildinfo +1 -1
|
@@ -4,8 +4,9 @@ import { GetAppSchema } from "./schemas";
|
|
|
4
4
|
import type { GetAppOptions } from "./schemas";
|
|
5
5
|
import type { AppItem } from "../../types/domain";
|
|
6
6
|
import { ZapierAppNotFoundError } from "../../types/errors";
|
|
7
|
-
import type { ListAppsPluginProvides } from "../listApps";
|
|
8
7
|
import type { GetSdkType } from "../../types/plugin";
|
|
8
|
+
import { GetImplementation } from "../manifest/schemas";
|
|
9
|
+
import { ManifestPluginProvides } from "../manifest";
|
|
9
10
|
|
|
10
11
|
// GetApp plugin provides interface - getApp goes directly to SDK root
|
|
11
12
|
export interface GetAppPluginProvides {
|
|
@@ -21,34 +22,20 @@ export interface GetAppPluginProvides {
|
|
|
21
22
|
|
|
22
23
|
// GetApp plugin depends on listApps SDK function
|
|
23
24
|
export const getAppPlugin: Plugin<
|
|
24
|
-
GetSdkType<
|
|
25
|
-
{}, //
|
|
25
|
+
GetSdkType<ManifestPluginProvides>, // depends on manifest plugin with getImplementation in context
|
|
26
|
+
{ getImplementation: GetImplementation }, //
|
|
26
27
|
GetAppPluginProvides
|
|
27
|
-
> = ({
|
|
28
|
+
> = ({ context }) => {
|
|
28
29
|
const getApp = createFunction(async function getApp(options: GetAppOptions) {
|
|
29
|
-
const
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
...options,
|
|
35
|
-
appKeys: [appKey],
|
|
36
|
-
})
|
|
37
|
-
.items();
|
|
38
|
-
|
|
39
|
-
// Get the first (and should be only) result
|
|
40
|
-
const apps = [];
|
|
41
|
-
for await (const app of appsIterator) {
|
|
42
|
-
apps.push(app);
|
|
43
|
-
break; // Only need the first result
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
if (apps.length === 0) {
|
|
47
|
-
throw new ZapierAppNotFoundError(appKey);
|
|
30
|
+
const app = await context.getImplementation(options.appKey);
|
|
31
|
+
if (!app) {
|
|
32
|
+
throw new ZapierAppNotFoundError("App not found", {
|
|
33
|
+
appKey: options.appKey,
|
|
34
|
+
});
|
|
48
35
|
}
|
|
49
36
|
|
|
50
37
|
return {
|
|
51
|
-
data:
|
|
38
|
+
data: app,
|
|
52
39
|
};
|
|
53
40
|
}, GetAppSchema);
|
|
54
41
|
|
|
@@ -58,6 +45,7 @@ export const getAppPlugin: Plugin<
|
|
|
58
45
|
context: {
|
|
59
46
|
meta: {
|
|
60
47
|
getApp: {
|
|
48
|
+
categories: ["app"],
|
|
61
49
|
inputSchema: GetAppSchema,
|
|
62
50
|
},
|
|
63
51
|
},
|
|
@@ -9,6 +9,8 @@ import { createSdk } from "../../sdk";
|
|
|
9
9
|
import type { ApiClient } from "../../api";
|
|
10
10
|
import type { GetAuthenticationOptions } from "./schemas";
|
|
11
11
|
import type { Authentication } from "../../api/types";
|
|
12
|
+
import { manifestPlugin } from "../manifest";
|
|
13
|
+
import { listAppsPlugin } from "../listApps";
|
|
12
14
|
|
|
13
15
|
const mockAuthenticationResponse: Authentication = {
|
|
14
16
|
id: 123,
|
|
@@ -34,10 +36,18 @@ describe("getAuthentication plugin", () => {
|
|
|
34
36
|
} as Partial<ApiClient> as ApiClient;
|
|
35
37
|
});
|
|
36
38
|
|
|
39
|
+
const apiPlugin = () => ({
|
|
40
|
+
context: {
|
|
41
|
+
api: mockApiClient,
|
|
42
|
+
},
|
|
43
|
+
});
|
|
44
|
+
|
|
37
45
|
function createTestSdk() {
|
|
38
|
-
return createSdk(
|
|
39
|
-
|
|
40
|
-
|
|
46
|
+
return createSdk()
|
|
47
|
+
.addPlugin(apiPlugin)
|
|
48
|
+
.addPlugin(listAppsPlugin)
|
|
49
|
+
.addPlugin(manifestPlugin)
|
|
50
|
+
.addPlugin(getAuthenticationPlugin);
|
|
41
51
|
}
|
|
42
52
|
|
|
43
53
|
describe("schema validation", () => {
|
|
@@ -8,19 +8,8 @@ import { listActionsPlugin } from "./index";
|
|
|
8
8
|
import { createSdk } from "../../sdk";
|
|
9
9
|
import type { ApiClient } from "../../api";
|
|
10
10
|
import type { ListActionsOptions } from "./schemas";
|
|
11
|
-
|
|
12
|
-
import {
|
|
13
|
-
|
|
14
|
-
const mockAppResponse = {
|
|
15
|
-
data: {
|
|
16
|
-
slug: "slack",
|
|
17
|
-
name: "Slack",
|
|
18
|
-
current_implementation_id: "SlackCLIAPI@1.20.0",
|
|
19
|
-
key: "slack",
|
|
20
|
-
title: "Slack",
|
|
21
|
-
hex_color: "#4A154B",
|
|
22
|
-
} as Partial<App> as App & { key: string; title: string; hex_color: string },
|
|
23
|
-
};
|
|
11
|
+
|
|
12
|
+
import { listAppsPlugin } from "../listApps";
|
|
24
13
|
|
|
25
14
|
const mockImplementationsResponse = {
|
|
26
15
|
results: [
|
|
@@ -66,7 +55,7 @@ const mockEmptyImplementationsResponse = {
|
|
|
66
55
|
|
|
67
56
|
describe("listActions plugin", () => {
|
|
68
57
|
let mockApiClient: ApiClient;
|
|
69
|
-
let
|
|
58
|
+
let mockGetVersionedImplementationId: any;
|
|
70
59
|
|
|
71
60
|
beforeEach(() => {
|
|
72
61
|
vi.clearAllMocks();
|
|
@@ -74,25 +63,31 @@ describe("listActions plugin", () => {
|
|
|
74
63
|
get: vi.fn().mockResolvedValue(mockImplementationsResponse),
|
|
75
64
|
} as Partial<ApiClient> as ApiClient;
|
|
76
65
|
|
|
77
|
-
|
|
66
|
+
mockGetVersionedImplementationId = vi
|
|
67
|
+
.fn()
|
|
68
|
+
.mockResolvedValue("SlackCLIAPI@1.21.1");
|
|
78
69
|
});
|
|
79
70
|
|
|
80
71
|
function createTestSdk() {
|
|
81
72
|
// Create a proper plugin chain with context dependencies
|
|
82
|
-
const mockGetAppPlugin = () => ({
|
|
83
|
-
getApp: mockGetApp,
|
|
84
|
-
context: {
|
|
85
|
-
meta: {
|
|
86
|
-
getApp: {
|
|
87
|
-
inputSchema: GetAppSchema,
|
|
88
|
-
},
|
|
89
|
-
},
|
|
90
|
-
},
|
|
91
|
-
});
|
|
92
73
|
|
|
93
74
|
// Build SDK with proper plugin composition, providing API in initial context
|
|
94
|
-
return createSdk(
|
|
95
|
-
.addPlugin(
|
|
75
|
+
return createSdk()
|
|
76
|
+
.addPlugin(() => ({
|
|
77
|
+
context: {
|
|
78
|
+
api: mockApiClient,
|
|
79
|
+
getVersionedImplementationId: mockGetVersionedImplementationId,
|
|
80
|
+
},
|
|
81
|
+
}))
|
|
82
|
+
.addPlugin(listAppsPlugin)
|
|
83
|
+
.addPlugin(() => ({
|
|
84
|
+
context: {
|
|
85
|
+
manifest: null,
|
|
86
|
+
getManifestEntry: () => null,
|
|
87
|
+
getVersionedImplementationId: mockGetVersionedImplementationId,
|
|
88
|
+
getImplementation: () => Promise.resolve(null),
|
|
89
|
+
},
|
|
90
|
+
}))
|
|
96
91
|
.addPlugin(listActionsPlugin);
|
|
97
92
|
}
|
|
98
93
|
|
|
@@ -401,9 +396,7 @@ describe("listActions plugin", () => {
|
|
|
401
396
|
const sdk = createTestSdk();
|
|
402
397
|
await sdk.listActions({ appKey: "slack" });
|
|
403
398
|
|
|
404
|
-
expect(
|
|
405
|
-
appKey: "slack",
|
|
406
|
-
});
|
|
399
|
+
expect(mockGetVersionedImplementationId).toHaveBeenCalledWith("slack");
|
|
407
400
|
});
|
|
408
401
|
|
|
409
402
|
it("should pass correct search parameters to implementations API", async () => {
|
|
@@ -416,7 +409,7 @@ describe("listActions plugin", () => {
|
|
|
416
409
|
searchParams: expect.objectContaining({
|
|
417
410
|
global: "true",
|
|
418
411
|
public_only: "true",
|
|
419
|
-
selected_apis: "SlackCLIAPI",
|
|
412
|
+
selected_apis: "SlackCLIAPI@1.21.1",
|
|
420
413
|
}),
|
|
421
414
|
}),
|
|
422
415
|
);
|
|
@@ -425,12 +418,7 @@ describe("listActions plugin", () => {
|
|
|
425
418
|
|
|
426
419
|
describe("error handling", () => {
|
|
427
420
|
it("should throw ZapierConfigurationError when app has no current_implementation_id", async () => {
|
|
428
|
-
|
|
429
|
-
data: {
|
|
430
|
-
...mockAppResponse.data,
|
|
431
|
-
current_implementation_id: undefined, // Missing implementation ID
|
|
432
|
-
},
|
|
433
|
-
});
|
|
421
|
+
mockGetVersionedImplementationId.mockResolvedValue(null);
|
|
434
422
|
|
|
435
423
|
const sdk = createTestSdk();
|
|
436
424
|
await expect(sdk.listActions({ appKey: "slack" })).rejects.toThrow(
|
|
@@ -439,12 +427,7 @@ describe("listActions plugin", () => {
|
|
|
439
427
|
});
|
|
440
428
|
|
|
441
429
|
it("should throw ZapierConfigurationError when current_implementation_id is empty", async () => {
|
|
442
|
-
|
|
443
|
-
data: {
|
|
444
|
-
...mockAppResponse.data,
|
|
445
|
-
current_implementation_id: "", // Empty implementation ID
|
|
446
|
-
},
|
|
447
|
-
});
|
|
430
|
+
mockGetVersionedImplementationId.mockResolvedValue("");
|
|
448
431
|
|
|
449
432
|
const sdk = createTestSdk();
|
|
450
433
|
await expect(sdk.listActions({ appKey: "slack" })).rejects.toThrow(
|
|
@@ -516,8 +499,10 @@ describe("listActions plugin", () => {
|
|
|
516
499
|
expect(result.data).toHaveLength(0);
|
|
517
500
|
});
|
|
518
501
|
|
|
519
|
-
it("should propagate
|
|
520
|
-
|
|
502
|
+
it("should propagate getVersionedImplementationId errors", async () => {
|
|
503
|
+
mockGetVersionedImplementationId.mockRejectedValue(
|
|
504
|
+
new Error("App not found"),
|
|
505
|
+
);
|
|
521
506
|
|
|
522
507
|
const sdk = createTestSdk();
|
|
523
508
|
await expect(sdk.listActions({ appKey: "nonexistent" })).rejects.toThrow(
|
|
@@ -526,50 +511,6 @@ describe("listActions plugin", () => {
|
|
|
526
511
|
});
|
|
527
512
|
});
|
|
528
513
|
|
|
529
|
-
describe("implementation ID extraction", () => {
|
|
530
|
-
it("should extract implementation name from versioned ID", async () => {
|
|
531
|
-
mockGetApp.mockResolvedValue({
|
|
532
|
-
data: {
|
|
533
|
-
...mockAppResponse.data,
|
|
534
|
-
current_implementation_id: "CustomAPIName@2.5.0",
|
|
535
|
-
},
|
|
536
|
-
});
|
|
537
|
-
|
|
538
|
-
const sdk = createTestSdk();
|
|
539
|
-
await sdk.listActions({ appKey: "slack" });
|
|
540
|
-
|
|
541
|
-
expect(mockApiClient.get).toHaveBeenCalledWith(
|
|
542
|
-
"/api/v4/implementations/",
|
|
543
|
-
expect.objectContaining({
|
|
544
|
-
searchParams: expect.objectContaining({
|
|
545
|
-
selected_apis: "CustomAPIName", // Extracted name without version
|
|
546
|
-
}),
|
|
547
|
-
}),
|
|
548
|
-
);
|
|
549
|
-
});
|
|
550
|
-
|
|
551
|
-
it("should handle implementation ID without version", async () => {
|
|
552
|
-
mockGetApp.mockResolvedValue({
|
|
553
|
-
data: {
|
|
554
|
-
...mockAppResponse.data,
|
|
555
|
-
current_implementation_id: "PlainAPIName",
|
|
556
|
-
},
|
|
557
|
-
});
|
|
558
|
-
|
|
559
|
-
const sdk = createTestSdk();
|
|
560
|
-
await sdk.listActions({ appKey: "slack" });
|
|
561
|
-
|
|
562
|
-
expect(mockApiClient.get).toHaveBeenCalledWith(
|
|
563
|
-
"/api/v4/implementations/",
|
|
564
|
-
expect.objectContaining({
|
|
565
|
-
searchParams: expect.objectContaining({
|
|
566
|
-
selected_apis: "PlainAPIName", // Used as-is
|
|
567
|
-
}),
|
|
568
|
-
}),
|
|
569
|
-
);
|
|
570
|
-
});
|
|
571
|
-
});
|
|
572
|
-
|
|
573
514
|
describe("context and metadata", () => {
|
|
574
515
|
it("should provide context with meta information", () => {
|
|
575
516
|
const sdk = createTestSdk();
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { Plugin, GetSdkType } from "../../types/plugin";
|
|
2
|
-
import type { ApiClient } from "../../api";
|
|
2
|
+
import type { ApiClient, Implementation } from "../../api";
|
|
3
3
|
import type { ActionItem } from "../../types/domain";
|
|
4
4
|
import { normalizeActionItem } from "../../utils/domain-utils";
|
|
5
5
|
import {
|
|
@@ -12,7 +12,8 @@ import {
|
|
|
12
12
|
ZapierAuthenticationError,
|
|
13
13
|
} from "../../types/errors";
|
|
14
14
|
import { createPaginatedFunction } from "../../utils/function-utils";
|
|
15
|
-
import
|
|
15
|
+
import { ManifestPluginProvides } from "../manifest";
|
|
16
|
+
import { GetVersionedImplementationId } from "../manifest/schemas";
|
|
16
17
|
|
|
17
18
|
export interface ListActionsPluginProvides {
|
|
18
19
|
listActions: (options?: ListActionsOptions) => Promise<{
|
|
@@ -31,20 +32,22 @@ export interface ListActionsPluginProvides {
|
|
|
31
32
|
}
|
|
32
33
|
|
|
33
34
|
export const listActionsPlugin: Plugin<
|
|
34
|
-
GetSdkType<
|
|
35
|
-
{
|
|
35
|
+
GetSdkType<ManifestPluginProvides>, // requires getApp in SDK
|
|
36
|
+
{
|
|
37
|
+
api: ApiClient;
|
|
38
|
+
getVersionedImplementationId: GetVersionedImplementationId;
|
|
39
|
+
}, // requires api and getVersionedImplementationId in context
|
|
36
40
|
ListActionsPluginProvides
|
|
37
|
-
> = ({
|
|
41
|
+
> = ({ context }) => {
|
|
38
42
|
const listActions = createPaginatedFunction(async function listActionsPage(
|
|
39
43
|
options: ListActionsOptions & { cursor?: string } & { pageSize: number },
|
|
40
44
|
): Promise<ListActionsPage> {
|
|
41
|
-
const { api } = context;
|
|
45
|
+
const { api, getVersionedImplementationId } = context;
|
|
42
46
|
|
|
43
47
|
// Use the getApp function from the SDK (dependency injection)
|
|
44
|
-
const
|
|
48
|
+
const selectedApi = await getVersionedImplementationId(options.appKey);
|
|
45
49
|
|
|
46
|
-
|
|
47
|
-
if (!implementationId) {
|
|
50
|
+
if (!selectedApi) {
|
|
48
51
|
throw new ZapierConfigurationError(
|
|
49
52
|
"No current_implementation_id found for app",
|
|
50
53
|
{ configType: "current_implementation_id" },
|
|
@@ -54,27 +57,30 @@ export const listActionsPlugin: Plugin<
|
|
|
54
57
|
const searchParams: Record<string, string> = {
|
|
55
58
|
global: "true",
|
|
56
59
|
public_only: "true",
|
|
57
|
-
selected_apis:
|
|
60
|
+
selected_apis: selectedApi,
|
|
58
61
|
};
|
|
59
62
|
|
|
60
|
-
const data = await api.get(
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
63
|
+
const data = await api.get<{ results: Implementation[] }>(
|
|
64
|
+
"/api/v4/implementations/",
|
|
65
|
+
{
|
|
66
|
+
searchParams,
|
|
67
|
+
customErrorHandler: ({ status }) => {
|
|
68
|
+
if (status === 401) {
|
|
69
|
+
return new ZapierAuthenticationError(
|
|
70
|
+
`Authentication failed. Your token may not have permission to access implementations or may be expired. (HTTP ${status})`,
|
|
71
|
+
{ statusCode: status },
|
|
72
|
+
);
|
|
73
|
+
}
|
|
74
|
+
if (status === 403) {
|
|
75
|
+
return new ZapierAuthenticationError(
|
|
76
|
+
`Access forbidden. Your token may not have the required scopes to list implementations. (HTTP ${status})`,
|
|
77
|
+
{ statusCode: status },
|
|
78
|
+
);
|
|
79
|
+
}
|
|
80
|
+
return undefined;
|
|
81
|
+
},
|
|
76
82
|
},
|
|
77
|
-
|
|
83
|
+
);
|
|
78
84
|
|
|
79
85
|
let allActions: ActionItem[] = [];
|
|
80
86
|
|
|
@@ -107,6 +113,7 @@ export const listActionsPlugin: Plugin<
|
|
|
107
113
|
context: {
|
|
108
114
|
meta: {
|
|
109
115
|
listActions: {
|
|
116
|
+
categories: ["action"],
|
|
110
117
|
inputSchema: ListActionsSchema,
|
|
111
118
|
},
|
|
112
119
|
},
|
|
@@ -6,7 +6,7 @@ import {
|
|
|
6
6
|
import { listAuthenticationsPlugin } from "./index";
|
|
7
7
|
import { createSdk } from "../../sdk";
|
|
8
8
|
import type { ApiClient } from "../../api";
|
|
9
|
-
import type {
|
|
9
|
+
import type { AppItem } from "../../types/domain";
|
|
10
10
|
|
|
11
11
|
const mockAuthenticationsResponse = {
|
|
12
12
|
results: [
|
|
@@ -42,29 +42,18 @@ const mockAuthenticationsResponse = {
|
|
|
42
42
|
previous: null,
|
|
43
43
|
};
|
|
44
44
|
|
|
45
|
-
const mockSlackApp = {
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
api_docs_url: "https://slack.com/api-docs",
|
|
53
|
-
app_profile_url: "https://slack.com",
|
|
54
|
-
banner: "https://slack.com/banner.png",
|
|
55
|
-
categories: [],
|
|
56
|
-
canonical_id: "slack",
|
|
57
|
-
zap_usage_count: 100,
|
|
58
|
-
zap_usage_count_last_updated: "2021-01-01",
|
|
59
|
-
zap_usage_count_last_updated_by: "user1",
|
|
60
|
-
zap_usage_count_last_updated_by_id: 123,
|
|
61
|
-
current_implementation_id: "SlackCLIAPI@1.21.1",
|
|
62
|
-
} as Partial<App> as App,
|
|
45
|
+
const mockSlackApp: AppItem = {
|
|
46
|
+
title: "Slack",
|
|
47
|
+
key: "SlackCLIAPI",
|
|
48
|
+
current_implementation_id: "SlackCLIAPI@1.21.1",
|
|
49
|
+
version: "1.21.1",
|
|
50
|
+
description: "Team communication platform",
|
|
51
|
+
slug: "slack",
|
|
63
52
|
};
|
|
64
53
|
|
|
65
54
|
describe("listAuthentications plugin", () => {
|
|
66
55
|
let mockApiClient: ApiClient;
|
|
67
|
-
let
|
|
56
|
+
let mockGetVersionedImplementationId: any;
|
|
68
57
|
|
|
69
58
|
beforeEach(() => {
|
|
70
59
|
vi.clearAllMocks();
|
|
@@ -72,14 +61,34 @@ describe("listAuthentications plugin", () => {
|
|
|
72
61
|
get: vi.fn().mockResolvedValue(mockAuthenticationsResponse),
|
|
73
62
|
} as Partial<ApiClient> as ApiClient;
|
|
74
63
|
|
|
75
|
-
|
|
64
|
+
mockGetVersionedImplementationId = vi
|
|
65
|
+
.fn()
|
|
66
|
+
.mockResolvedValue("SlackCLIAPI@1.21.1");
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
const apiPlugin = () => ({
|
|
70
|
+
context: {
|
|
71
|
+
api: mockApiClient,
|
|
72
|
+
},
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
const manifestPlugin = () => ({
|
|
76
|
+
context: {
|
|
77
|
+
manifest: null,
|
|
78
|
+
getVersionedImplementationId: mockGetVersionedImplementationId,
|
|
79
|
+
getManifestEntry: () => ({
|
|
80
|
+
implementationName: "SlackCLIAPI",
|
|
81
|
+
version: "1.21.1",
|
|
82
|
+
}),
|
|
83
|
+
getImplementation: vi.fn().mockResolvedValue(mockSlackApp),
|
|
84
|
+
},
|
|
76
85
|
});
|
|
77
86
|
|
|
78
87
|
function createTestSdk() {
|
|
79
|
-
return createSdk(
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
88
|
+
return createSdk()
|
|
89
|
+
.addPlugin(apiPlugin)
|
|
90
|
+
.addPlugin(manifestPlugin)
|
|
91
|
+
.addPlugin(listAuthenticationsPlugin);
|
|
83
92
|
}
|
|
84
93
|
|
|
85
94
|
describe("schema validation", () => {
|
|
@@ -129,7 +138,7 @@ describe("listAuthentications plugin", () => {
|
|
|
129
138
|
const sdk = createTestSdk();
|
|
130
139
|
expect(() => {
|
|
131
140
|
sdk.listAuthentications({
|
|
132
|
-
account_id: 123,
|
|
141
|
+
account_id: 123 as any,
|
|
133
142
|
});
|
|
134
143
|
}).toThrow(ZapierValidationError);
|
|
135
144
|
});
|
|
@@ -192,7 +201,7 @@ describe("listAuthentications plugin", () => {
|
|
|
192
201
|
describe("data mapping", () => {
|
|
193
202
|
it("should map is_stale to is_expired and marked_stale_at to expired_at", async () => {
|
|
194
203
|
const sdk = createTestSdk();
|
|
195
|
-
const result = await sdk.listAuthentications(
|
|
204
|
+
const result = await sdk.listAuthentications();
|
|
196
205
|
|
|
197
206
|
expect(result.data[0].is_expired).toBe("false");
|
|
198
207
|
expect(result.data[0].expired_at).toBe(null);
|
|
@@ -582,16 +591,7 @@ describe("listAuthentications plugin", () => {
|
|
|
582
591
|
|
|
583
592
|
describe("app key integration", () => {
|
|
584
593
|
it("should handle app without current_implementation_id", async () => {
|
|
585
|
-
|
|
586
|
-
data: {
|
|
587
|
-
id: 123,
|
|
588
|
-
key: "slack",
|
|
589
|
-
title: "Slack",
|
|
590
|
-
current_implementation_id: undefined,
|
|
591
|
-
} as Partial<App> as App,
|
|
592
|
-
};
|
|
593
|
-
|
|
594
|
-
mockGetApp.mockResolvedValue(appWithoutImplementation);
|
|
594
|
+
mockGetVersionedImplementationId.mockResolvedValue(null);
|
|
595
595
|
|
|
596
596
|
const sdk = createTestSdk();
|
|
597
597
|
await sdk.listAuthentications({ appKey: "slack" });
|
|
@@ -608,16 +608,7 @@ describe("listAuthentications plugin", () => {
|
|
|
608
608
|
});
|
|
609
609
|
|
|
610
610
|
it("should extract versionless API from versioned implementation ID", async () => {
|
|
611
|
-
|
|
612
|
-
data: {
|
|
613
|
-
id: 123,
|
|
614
|
-
key: "slack",
|
|
615
|
-
title: "Slack",
|
|
616
|
-
current_implementation_id: "SlackCLIAPI@2.1.3",
|
|
617
|
-
} as Partial<App> as App,
|
|
618
|
-
};
|
|
619
|
-
|
|
620
|
-
mockGetApp.mockResolvedValue(appWithVersionedApi);
|
|
611
|
+
mockGetVersionedImplementationId.mockResolvedValue("SlackCLIAPI@2.1.3");
|
|
621
612
|
|
|
622
613
|
const sdk = createTestSdk();
|
|
623
614
|
await sdk.listAuthentications({ appKey: "slack" });
|
|
@@ -7,13 +7,17 @@ import {
|
|
|
7
7
|
type ListAuthenticationsOptions,
|
|
8
8
|
type ListAuthenticationsPage,
|
|
9
9
|
} from "./schemas";
|
|
10
|
-
import {
|
|
10
|
+
import {
|
|
11
|
+
normalizeAuthenticationItem,
|
|
12
|
+
splitVersionedKey,
|
|
13
|
+
} from "../../utils/domain-utils";
|
|
11
14
|
import { ZapierAuthenticationError } from "../../types/errors";
|
|
12
15
|
import {
|
|
13
16
|
createPaginatedFunction,
|
|
14
17
|
extractCursor,
|
|
15
18
|
} from "../../utils/function-utils";
|
|
16
|
-
import
|
|
19
|
+
import { GetVersionedImplementationId } from "../manifest/schemas";
|
|
20
|
+
import { ManifestPluginProvides } from "../manifest";
|
|
17
21
|
|
|
18
22
|
export interface ListAuthenticationsPluginProvides {
|
|
19
23
|
listAuthentications: (options?: ListAuthenticationsOptions) => Promise<{
|
|
@@ -32,33 +36,31 @@ export interface ListAuthenticationsPluginProvides {
|
|
|
32
36
|
}
|
|
33
37
|
|
|
34
38
|
export const listAuthenticationsPlugin: Plugin<
|
|
35
|
-
GetSdkType<
|
|
36
|
-
{
|
|
39
|
+
GetSdkType<ManifestPluginProvides>, // requires getApp in SDK
|
|
40
|
+
{
|
|
41
|
+
api: ApiClient;
|
|
42
|
+
getVersionedImplementationId: GetVersionedImplementationId;
|
|
43
|
+
}, // requires api in context
|
|
37
44
|
ListAuthenticationsPluginProvides
|
|
38
|
-
> = ({
|
|
45
|
+
> = ({ context }) => {
|
|
39
46
|
const listAuthentications = createPaginatedFunction(
|
|
40
47
|
async function listAuthenticationsPage(
|
|
41
48
|
options: ListAuthenticationsOptions & { cursor?: string } & {
|
|
42
49
|
pageSize: number;
|
|
43
50
|
},
|
|
44
51
|
): Promise<ListAuthenticationsPage> {
|
|
45
|
-
const { api } = context;
|
|
46
|
-
|
|
52
|
+
const { api, getVersionedImplementationId } = context;
|
|
47
53
|
// Build search parameters
|
|
48
54
|
const searchParams: Record<string, string> = {};
|
|
49
55
|
|
|
50
56
|
// Handle appKey filtering by getting the selected_api first
|
|
51
57
|
if (options.appKey) {
|
|
52
|
-
const
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
// Use versionless_selected_api to find auths across all app versions
|
|
59
|
-
// Extract the base name without the version (e.g., "SlackCLIAPI" from "SlackCLIAPI@1.21.1")
|
|
60
|
-
const versionlessApi = selectedApi.split("@")[0];
|
|
61
|
-
searchParams.versionless_selected_api = versionlessApi;
|
|
58
|
+
const implementationId = await getVersionedImplementationId(
|
|
59
|
+
options.appKey,
|
|
60
|
+
);
|
|
61
|
+
if (implementationId) {
|
|
62
|
+
const [versionlessSelectedApi] = splitVersionedKey(implementationId);
|
|
63
|
+
searchParams.versionless_selected_api = versionlessSelectedApi;
|
|
62
64
|
}
|
|
63
65
|
}
|
|
64
66
|
|
|
@@ -81,7 +83,7 @@ export const listAuthenticationsPlugin: Plugin<
|
|
|
81
83
|
// Convert cursor back to offset for the API
|
|
82
84
|
searchParams.offset = options.cursor;
|
|
83
85
|
}
|
|
84
|
-
|
|
86
|
+
console.log({ searchParams });
|
|
85
87
|
const data: AuthenticationsResponse = await api.get(
|
|
86
88
|
"/api/v4/authentications/",
|
|
87
89
|
{
|
|
@@ -128,6 +130,7 @@ export const listAuthenticationsPlugin: Plugin<
|
|
|
128
130
|
context: {
|
|
129
131
|
meta: {
|
|
130
132
|
listAuthentications: {
|
|
133
|
+
categories: ["authentication"],
|
|
131
134
|
inputSchema: ListAuthenticationsSchema,
|
|
132
135
|
},
|
|
133
136
|
},
|
|
@@ -47,7 +47,7 @@ const mockNeedsResponse: NeedsResponse = {
|
|
|
47
47
|
|
|
48
48
|
describe("listInputFields plugin", () => {
|
|
49
49
|
let mockApiClient: ApiClient;
|
|
50
|
-
let
|
|
50
|
+
let mockGetVersionedImplementationId: any;
|
|
51
51
|
|
|
52
52
|
beforeEach(() => {
|
|
53
53
|
vi.clearAllMocks();
|
|
@@ -55,15 +55,20 @@ describe("listInputFields plugin", () => {
|
|
|
55
55
|
post: vi.fn().mockResolvedValue(mockNeedsResponse),
|
|
56
56
|
} as Partial<ApiClient> as ApiClient;
|
|
57
57
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
58
|
+
mockGetVersionedImplementationId = vi
|
|
59
|
+
.fn()
|
|
60
|
+
.mockResolvedValue("SlackCLIAPI@1.21.1");
|
|
61
61
|
});
|
|
62
62
|
|
|
63
63
|
function createTestSdk() {
|
|
64
64
|
return createSdk(
|
|
65
|
-
{
|
|
66
|
-
{
|
|
65
|
+
{},
|
|
66
|
+
{},
|
|
67
|
+
{
|
|
68
|
+
api: mockApiClient,
|
|
69
|
+
meta: {},
|
|
70
|
+
getVersionedImplementationId: mockGetVersionedImplementationId,
|
|
71
|
+
},
|
|
67
72
|
).addPlugin(listInputFieldsPlugin as any);
|
|
68
73
|
}
|
|
69
74
|
|
|
@@ -303,9 +308,7 @@ describe("listInputFields plugin", () => {
|
|
|
303
308
|
|
|
304
309
|
describe("error handling", () => {
|
|
305
310
|
it("should throw ZapierConfigurationError when app has no current_implementation_id", async () => {
|
|
306
|
-
|
|
307
|
-
data: { current_implementation_id: undefined },
|
|
308
|
-
});
|
|
311
|
+
mockGetVersionedImplementationId.mockResolvedValue(null);
|
|
309
312
|
|
|
310
313
|
const sdk = createTestSdk();
|
|
311
314
|
await expect(
|