@zapier/zapier-sdk 0.8.3 → 0.10.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.
Files changed (222) hide show
  1. package/CHANGELOG.md +18 -0
  2. package/README.md +17 -40
  3. package/dist/api/client.d.ts.map +1 -1
  4. package/dist/api/client.js +14 -0
  5. package/dist/api/debug.d.ts +1 -0
  6. package/dist/api/debug.d.ts.map +1 -1
  7. package/dist/api/debug.js +42 -1
  8. package/dist/api/debug.test.d.ts +2 -0
  9. package/dist/api/debug.test.d.ts.map +1 -0
  10. package/dist/api/debug.test.js +59 -0
  11. package/dist/api/schemas.d.ts +451 -251
  12. package/dist/api/schemas.d.ts.map +1 -1
  13. package/dist/api/schemas.js +51 -29
  14. package/dist/index.cjs +1149 -751
  15. package/dist/index.d.mts +2359 -2161
  16. package/dist/index.d.ts +3 -5
  17. package/dist/index.d.ts.map +1 -1
  18. package/dist/index.js +2 -4
  19. package/dist/index.mjs +1143 -743
  20. package/dist/plugins/apps/index.d.ts +4 -0
  21. package/dist/plugins/apps/index.d.ts.map +1 -1
  22. package/dist/plugins/findFirstAuthentication/index.d.ts +1 -1
  23. package/dist/plugins/findFirstAuthentication/index.d.ts.map +1 -1
  24. package/dist/plugins/findFirstAuthentication/index.js +9 -1
  25. package/dist/plugins/findFirstAuthentication/index.test.js +3 -4
  26. package/dist/plugins/findFirstAuthentication/schemas.d.ts +5 -3
  27. package/dist/plugins/findFirstAuthentication/schemas.d.ts.map +1 -1
  28. package/dist/plugins/findUniqueAuthentication/index.d.ts.map +1 -1
  29. package/dist/plugins/findUniqueAuthentication/index.js +4 -0
  30. package/dist/plugins/findUniqueAuthentication/schemas.d.ts +5 -3
  31. package/dist/plugins/findUniqueAuthentication/schemas.d.ts.map +1 -1
  32. package/dist/plugins/getAction/index.d.ts.map +1 -1
  33. package/dist/plugins/getAction/index.js +10 -0
  34. package/dist/plugins/getAction/schemas.d.ts +5 -3
  35. package/dist/plugins/getAction/schemas.d.ts.map +1 -1
  36. package/dist/plugins/getApp/index.d.ts +2 -7
  37. package/dist/plugins/getApp/index.d.ts.map +1 -1
  38. package/dist/plugins/getApp/index.js +17 -9
  39. package/dist/plugins/getApp/index.test.js +3 -3
  40. package/dist/plugins/getApp/schemas.d.ts +3 -1
  41. package/dist/plugins/getApp/schemas.d.ts.map +1 -1
  42. package/dist/plugins/getApp/schemas.js +2 -4
  43. package/dist/plugins/getAuthentication/index.d.ts.map +1 -1
  44. package/dist/plugins/getAuthentication/index.js +8 -0
  45. package/dist/plugins/getAuthentication/index.test.js +1 -1
  46. package/dist/plugins/getProfile/index.d.ts.map +1 -1
  47. package/dist/plugins/getProfile/index.js +4 -0
  48. package/dist/plugins/getProfile/schemas.d.ts.map +1 -1
  49. package/dist/plugins/getProfile/schemas.js +4 -3
  50. package/dist/plugins/listActions/index.d.ts +2 -4
  51. package/dist/plugins/listActions/index.d.ts.map +1 -1
  52. package/dist/plugins/listActions/index.js +10 -1
  53. package/dist/plugins/listActions/index.test.js +4 -4
  54. package/dist/plugins/listActions/schemas.d.ts +5 -3
  55. package/dist/plugins/listActions/schemas.d.ts.map +1 -1
  56. package/dist/plugins/listActions/schemas.js +2 -4
  57. package/dist/plugins/listApps/index.d.ts +4 -7
  58. package/dist/plugins/listApps/index.d.ts.map +1 -1
  59. package/dist/plugins/listApps/index.js +37 -17
  60. package/dist/plugins/listApps/index.test.js +23 -3
  61. package/dist/plugins/listApps/schemas.d.ts.map +1 -1
  62. package/dist/plugins/listApps/schemas.js +3 -9
  63. package/dist/plugins/listAuthentications/index.d.ts +2 -4
  64. package/dist/plugins/listAuthentications/index.d.ts.map +1 -1
  65. package/dist/plugins/listAuthentications/index.js +12 -0
  66. package/dist/plugins/listAuthentications/index.test.js +39 -13
  67. package/dist/plugins/listAuthentications/schemas.d.ts +8 -3
  68. package/dist/plugins/listAuthentications/schemas.d.ts.map +1 -1
  69. package/dist/plugins/listAuthentications/schemas.js +4 -0
  70. package/dist/plugins/listInputFieldChoices/index.d.ts.map +1 -1
  71. package/dist/plugins/listInputFieldChoices/index.js +14 -2
  72. package/dist/plugins/listInputFieldChoices/schemas.d.ts +5 -3
  73. package/dist/plugins/listInputFieldChoices/schemas.d.ts.map +1 -1
  74. package/dist/plugins/listInputFieldChoices/schemas.js +10 -19
  75. package/dist/plugins/listInputFields/index.d.ts.map +1 -1
  76. package/dist/plugins/listInputFields/index.js +14 -2
  77. package/dist/plugins/listInputFields/index.test.js +5 -9
  78. package/dist/plugins/listInputFields/schemas.d.ts +5 -3
  79. package/dist/plugins/listInputFields/schemas.d.ts.map +1 -1
  80. package/dist/plugins/manifest/index.d.ts +25 -9
  81. package/dist/plugins/manifest/index.d.ts.map +1 -1
  82. package/dist/plugins/manifest/index.js +239 -67
  83. package/dist/plugins/manifest/index.test.js +426 -171
  84. package/dist/plugins/manifest/schemas.d.ts +5 -1
  85. package/dist/plugins/manifest/schemas.d.ts.map +1 -1
  86. package/dist/plugins/manifest/schemas.js +1 -0
  87. package/dist/plugins/registry/index.d.ts.map +1 -1
  88. package/dist/plugins/registry/index.js +8 -2
  89. package/dist/plugins/request/index.d.ts.map +1 -1
  90. package/dist/plugins/request/index.js +1 -0
  91. package/dist/plugins/runAction/index.d.ts.map +1 -1
  92. package/dist/plugins/runAction/index.js +12 -0
  93. package/dist/plugins/runAction/schemas.d.ts +5 -3
  94. package/dist/plugins/runAction/schemas.d.ts.map +1 -1
  95. package/dist/resolvers/actionKey.d.ts +13 -7
  96. package/dist/resolvers/actionKey.d.ts.map +1 -1
  97. package/dist/resolvers/actionType.d.ts +8 -7
  98. package/dist/resolvers/actionType.d.ts.map +1 -1
  99. package/dist/resolvers/appKey.d.ts +2 -6
  100. package/dist/resolvers/appKey.d.ts.map +1 -1
  101. package/dist/resolvers/authenticationId.d.ts +7 -7
  102. package/dist/resolvers/authenticationId.d.ts.map +1 -1
  103. package/dist/resolvers/authenticationId.js +16 -7
  104. package/dist/resolvers/index.d.ts +3 -35
  105. package/dist/resolvers/index.d.ts.map +1 -1
  106. package/dist/resolvers/index.js +4 -87
  107. package/dist/resolvers/inputFieldKey.d.ts +11 -0
  108. package/dist/resolvers/inputFieldKey.d.ts.map +1 -0
  109. package/dist/resolvers/inputFieldKey.js +23 -0
  110. package/dist/resolvers/inputs.d.ts +11 -6
  111. package/dist/resolvers/inputs.d.ts.map +1 -1
  112. package/dist/resolvers/inputs.js +17 -0
  113. package/dist/schemas/Action.d.ts +8 -8
  114. package/dist/schemas/Action.d.ts.map +1 -1
  115. package/dist/schemas/Action.js +8 -3
  116. package/dist/schemas/App.d.ts +183 -11
  117. package/dist/schemas/App.d.ts.map +1 -1
  118. package/dist/schemas/App.js +7 -9
  119. package/dist/schemas/Auth.d.ts +12 -12
  120. package/dist/schemas/Auth.js +1 -1
  121. package/dist/schemas/Field.d.ts +5 -98
  122. package/dist/schemas/Field.d.ts.map +1 -1
  123. package/dist/schemas/Field.js +24 -52
  124. package/dist/schemas/Run.d.ts +3 -0
  125. package/dist/schemas/Run.d.ts.map +1 -0
  126. package/dist/schemas/Run.js +31 -0
  127. package/dist/schemas/UserProfile.d.ts +11 -11
  128. package/dist/schemas/UserProfile.d.ts.map +1 -1
  129. package/dist/schemas/UserProfile.js +21 -7
  130. package/dist/sdk.d.ts +15 -14
  131. package/dist/sdk.d.ts.map +1 -1
  132. package/dist/sdk.js +1 -4
  133. package/dist/types/plugin.d.ts +6 -0
  134. package/dist/types/plugin.d.ts.map +1 -1
  135. package/dist/types/properties.d.ts +3 -1
  136. package/dist/types/properties.d.ts.map +1 -1
  137. package/dist/types/sdk.d.ts +11 -3
  138. package/dist/types/sdk.d.ts.map +1 -1
  139. package/dist/utils/domain-utils.d.ts +17 -16
  140. package/dist/utils/domain-utils.d.ts.map +1 -1
  141. package/dist/utils/domain-utils.js +53 -78
  142. package/dist/utils/domain-utils.test.js +157 -3
  143. package/dist/utils/file-utils.d.ts +4 -0
  144. package/dist/utils/file-utils.d.ts.map +1 -0
  145. package/dist/utils/file-utils.js +74 -0
  146. package/dist/utils/file-utils.test.d.ts +2 -0
  147. package/dist/utils/file-utils.test.d.ts.map +1 -0
  148. package/dist/utils/file-utils.test.js +51 -0
  149. package/dist/utils/schema-utils.d.ts +44 -21
  150. package/dist/utils/schema-utils.d.ts.map +1 -1
  151. package/dist/utils/schema-utils.js +17 -11
  152. package/package.json +1 -1
  153. package/src/api/client.ts +12 -0
  154. package/src/api/debug.test.ts +76 -0
  155. package/src/api/debug.ts +46 -2
  156. package/src/api/schemas.ts +51 -29
  157. package/src/index.ts +5 -6
  158. package/src/plugins/apps/index.ts +9 -2
  159. package/src/plugins/findFirstAuthentication/index.test.ts +8 -5
  160. package/src/plugins/findFirstAuthentication/index.ts +14 -2
  161. package/src/plugins/findUniqueAuthentication/index.ts +4 -0
  162. package/src/plugins/getAction/index.ts +14 -0
  163. package/src/plugins/getApp/index.test.ts +3 -3
  164. package/src/plugins/getApp/index.ts +20 -14
  165. package/src/plugins/getApp/schemas.ts +7 -12
  166. package/src/plugins/getAuthentication/index.test.ts +1 -1
  167. package/src/plugins/getAuthentication/index.ts +8 -0
  168. package/src/plugins/getProfile/index.ts +4 -0
  169. package/src/plugins/getProfile/schemas.ts +4 -6
  170. package/src/plugins/listActions/index.test.ts +8 -7
  171. package/src/plugins/listActions/index.ts +12 -3
  172. package/src/plugins/listActions/schemas.ts +20 -25
  173. package/src/plugins/listApps/index.test.ts +24 -3
  174. package/src/plugins/listApps/index.ts +50 -25
  175. package/src/plugins/listApps/schemas.ts +17 -26
  176. package/src/plugins/listAuthentications/index.test.ts +52 -15
  177. package/src/plugins/listAuthentications/index.ts +15 -2
  178. package/src/plugins/listAuthentications/schemas.ts +4 -0
  179. package/src/plugins/listInputFieldChoices/index.ts +21 -1
  180. package/src/plugins/listInputFieldChoices/schemas.ts +61 -76
  181. package/src/plugins/listInputFields/index.test.ts +5 -9
  182. package/src/plugins/listInputFields/index.ts +20 -2
  183. package/src/plugins/manifest/index.test.ts +503 -197
  184. package/src/plugins/manifest/index.ts +338 -82
  185. package/src/plugins/manifest/schemas.ts +9 -2
  186. package/src/plugins/registry/index.ts +8 -2
  187. package/src/plugins/request/index.ts +1 -0
  188. package/src/plugins/runAction/index.ts +18 -0
  189. package/src/resolvers/actionKey.ts +15 -13
  190. package/src/resolvers/actionType.ts +10 -12
  191. package/src/resolvers/appKey.ts +2 -6
  192. package/src/resolvers/authenticationId.ts +25 -19
  193. package/src/resolvers/index.ts +7 -113
  194. package/src/resolvers/inputFieldKey.ts +38 -0
  195. package/src/resolvers/inputs.ts +28 -10
  196. package/src/schemas/Action.ts +8 -3
  197. package/src/schemas/App.ts +7 -9
  198. package/src/schemas/Auth.ts +1 -1
  199. package/src/schemas/Field.ts +24 -57
  200. package/src/schemas/Run.ts +40 -0
  201. package/src/schemas/UserProfile.ts +24 -7
  202. package/src/sdk.ts +18 -12
  203. package/src/types/plugin.ts +8 -0
  204. package/src/types/sdk.ts +31 -21
  205. package/src/utils/domain-utils.test.ts +196 -2
  206. package/src/utils/domain-utils.ts +77 -102
  207. package/src/utils/file-utils.test.ts +73 -0
  208. package/src/utils/file-utils.ts +94 -0
  209. package/src/utils/schema-utils.ts +96 -44
  210. package/tsconfig.tsbuildinfo +1 -1
  211. package/dist/plugins/lockVersion/index.d.ts +0 -24
  212. package/dist/plugins/lockVersion/index.d.ts.map +0 -1
  213. package/dist/plugins/lockVersion/index.js +0 -72
  214. package/dist/plugins/lockVersion/index.test.d.ts +0 -2
  215. package/dist/plugins/lockVersion/index.test.d.ts.map +0 -1
  216. package/dist/plugins/lockVersion/index.test.js +0 -129
  217. package/dist/plugins/lockVersion/schemas.d.ts +0 -10
  218. package/dist/plugins/lockVersion/schemas.d.ts.map +0 -1
  219. package/dist/plugins/lockVersion/schemas.js +0 -6
  220. package/src/plugins/lockVersion/index.test.ts +0 -176
  221. package/src/plugins/lockVersion/index.ts +0 -112
  222. package/src/plugins/lockVersion/schemas.ts +0 -9
@@ -28,9 +28,26 @@ const mockAppsResponse = {
28
28
  },
29
29
  };
30
30
 
31
+ const mockResolveAppKeys = vi
32
+ .fn()
33
+ .mockImplementation(async ({ appKeys }: { appKeys: string[] }) => {
34
+ // Mock implementation that returns resolved locators for the app keys
35
+ return appKeys.map((appKey) => ({
36
+ lookupAppKey: appKey,
37
+ implementationName: appKey, // For testing, use appKey as implementationName
38
+ slug: appKey.toLowerCase(),
39
+ version: undefined,
40
+ }));
41
+ });
42
+
31
43
  function createTestSdk() {
32
44
  return createSdk()
33
45
  .addPlugin(apiPlugin, { fetch: global.fetch })
46
+ .addPlugin(() => ({
47
+ context: {
48
+ resolveAppKeys: mockResolveAppKeys,
49
+ },
50
+ }))
34
51
  .addPlugin(listAppsPlugin as any);
35
52
  }
36
53
 
@@ -100,7 +117,11 @@ describe("listApps plugin", () => {
100
117
  expect((context.api as any).get).toHaveBeenCalledWith(
101
118
  "/api/v4/implementations-meta/lookup/",
102
119
  {
103
- searchParams: { latest_only: "true", limit: "100" },
120
+ searchParams: {
121
+ latest_only: "true",
122
+ limit: "100",
123
+ selected_apis: "",
124
+ },
104
125
  },
105
126
  );
106
127
  });
@@ -207,7 +228,7 @@ describe("listApps plugin", () => {
207
228
 
208
229
  expect(result.data[0]).toHaveProperty("title");
209
230
  expect(result.data[0]).toHaveProperty("key");
210
- expect(result.data[0]).toHaveProperty("current_implementation_id");
231
+ expect(result.data[0]).toHaveProperty("implementation_id");
211
232
  // Version is optional
212
233
  expect(result.data[0]).toHaveProperty("version");
213
234
  });
@@ -338,7 +359,7 @@ describe("listApps plugin", () => {
338
359
  expect.stringContaining("implementations-meta"),
339
360
  expect.objectContaining({
340
361
  searchParams: expect.objectContaining({
341
- selected_apis: "SlackCLIAPI,GitHubCLIAPI",
362
+ selected_apis: "SlackCLIAPI@latest,GitHubCLIAPI@latest",
342
363
  }),
343
364
  }),
344
365
  );
@@ -1,16 +1,20 @@
1
- import type { Plugin } from "../../types/plugin";
2
- import type { ApiClient } from "../../api/types";
1
+ import type { GetContextType, Plugin } from "../../types/plugin";
3
2
  import { createPaginatedFunction } from "../../utils/function-utils";
4
3
  import { ListAppsSchema } from "./schemas";
5
4
  import type { ListAppsOptions, ListAppsPage } from "./schemas";
6
5
  import type { AppItem } from "../../types/domain";
6
+ import { AppItemSchema } from "../../schemas/App";
7
+ import type { ResolvedAppLocator } from "../../utils/domain-utils";
7
8
  import {
8
- groupAppKeysByType,
9
9
  normalizeImplementationMetaToAppItem,
10
10
  splitVersionedKey,
11
+ toAppLocator,
12
+ toImplementationId,
11
13
  } from "../../utils/domain-utils";
12
14
  import { extractCursor } from "../../utils/function-utils";
13
15
  import type { ImplementationsMetaResponse } from "../../api/types";
16
+ import type { ManifestPluginProvides } from "../manifest";
17
+ import type { ApiPluginProvides } from "../api";
14
18
  // ListApps plugin provides interface - listApps goes directly to SDK root
15
19
  export interface ListAppsPluginProvides {
16
20
  listApps: (options?: ListAppsOptions) => Promise<{ data: AppItem[] }> &
@@ -26,10 +30,9 @@ export interface ListAppsPluginProvides {
26
30
  };
27
31
  }
28
32
 
29
- // Direct plugin function - takes options + sdk + context in one object
30
33
  export const listAppsPlugin: Plugin<
31
- {}, // no SDK dependencies
32
- { api: ApiClient }, // requires api in context
34
+ {},
35
+ GetContextType<ApiPluginProvides & ManifestPluginProvides>,
33
36
  ListAppsPluginProvides
34
37
  > = ({ context }) => {
35
38
  const listApps = createPaginatedFunction(async function listAppsPage(
@@ -38,9 +41,28 @@ export const listAppsPlugin: Plugin<
38
41
  const api = context.api;
39
42
  const opts = options;
40
43
 
41
- const appKeys = [...(opts.appKeys ?? [])].map(
42
- (key) => splitVersionedKey(key)[0],
43
- );
44
+ const appLocators = await context.resolveAppKeys({
45
+ appKeys: [...(opts.appKeys ?? [])],
46
+ });
47
+ const implementationNameToLocator: Record<string, ResolvedAppLocator[]> =
48
+ {};
49
+ for (const locator of appLocators) {
50
+ implementationNameToLocator[locator.implementationName] = [
51
+ ...(implementationNameToLocator[locator.implementationName] ?? []),
52
+ locator,
53
+ ];
54
+ }
55
+ const duplicatedLookupAppKeys = Object.keys(implementationNameToLocator)
56
+ .filter((key) => implementationNameToLocator[key].length > 1)
57
+ .map((key) => implementationNameToLocator[key])
58
+ .flat()
59
+ .map((locator) => locator.lookupAppKey);
60
+
61
+ if (duplicatedLookupAppKeys.length > 0) {
62
+ throw new Error(
63
+ `Duplicate lookup app keys found: ${duplicatedLookupAppKeys.join(", ")}`,
64
+ );
65
+ }
44
66
 
45
67
  if (opts.search) {
46
68
  const searchParams: Record<string, string> = {};
@@ -58,12 +80,18 @@ export const listAppsPlugin: Plugin<
58
80
  normalizeImplementationMetaToAppItem,
59
81
  );
60
82
 
61
- const appKeysSet = new Set(appKeys);
83
+ const implementationNameSet = new Set<string>(
84
+ appLocators.map((locator) => locator.implementationName),
85
+ );
62
86
 
63
87
  for (const implementation of implementations) {
64
- if (!appKeysSet.has(implementation.key)) {
65
- appKeysSet.add(implementation.key);
66
- appKeys.push(implementation.key);
88
+ const [implementationName] = splitVersionedKey(implementation.key);
89
+ if (!implementationNameSet.has(implementationName)) {
90
+ implementationNameSet.add(implementationName);
91
+ appLocators.push({
92
+ ...toAppLocator(implementation.key),
93
+ implementationName,
94
+ });
67
95
  }
68
96
  }
69
97
  }
@@ -74,23 +102,17 @@ export const listAppsPlugin: Plugin<
74
102
  searchParams.limit = opts.pageSize.toString();
75
103
  }
76
104
 
77
- searchParams.latest_only = "true";
105
+ if (appLocators.length === 0) {
106
+ searchParams.latest_only = "true";
107
+ }
78
108
 
79
109
  if (opts.cursor) {
80
110
  searchParams.offset = opts.cursor;
81
111
  }
82
112
 
83
- if (appKeys.length > 0) {
84
- const groupedAppKeys = groupAppKeysByType(appKeys);
85
-
86
- if (groupedAppKeys.selectedApi.length > 0) {
87
- searchParams.selected_apis = groupedAppKeys.selectedApi.join(",");
88
- }
89
-
90
- if (groupedAppKeys.slug.length > 0) {
91
- searchParams.slugs = groupedAppKeys.slug.join(",");
92
- }
93
- }
113
+ searchParams.selected_apis = appLocators
114
+ .map((locator) => toImplementationId(locator))
115
+ .join(",");
94
116
 
95
117
  const implementationsEnvelope: ImplementationsMetaResponse = await api.get(
96
118
  "/api/v4/implementations-meta/lookup/",
@@ -114,7 +136,10 @@ export const listAppsPlugin: Plugin<
114
136
  meta: {
115
137
  listApps: {
116
138
  categories: ["app"],
139
+ type: "list",
140
+ itemType: "App",
117
141
  inputSchema: ListAppsSchema,
142
+ outputSchema: AppItemSchema,
118
143
  },
119
144
  },
120
145
  },
@@ -2,8 +2,6 @@ import { z } from "zod";
2
2
  import type { AppItem } from "../../types/domain";
3
3
  import type { PaginatedSdkFunction } from "../../types/functions";
4
4
  import type { ZapierApiError, ZapierValidationError } from "../../types/errors";
5
- import { AppItemSchema } from "../../schemas/App";
6
- import { withOutputSchema } from "../../utils/schema-utils";
7
5
 
8
6
  // Union of all possible errors for listApps
9
7
  export type ListAppsError = ZapierApiError | ZapierValidationError;
@@ -15,30 +13,23 @@ export interface ListAppsPage {
15
13
  }
16
14
 
17
15
  // Pure Zod schema - no pagination metadata exposed
18
- export const ListAppsSchema = withOutputSchema(
19
- z
20
- .object({
21
- appKeys: z
22
- .array(z.string())
23
- .optional()
24
- .describe(
25
- "Filter apps by app keys (e.g., 'SlackCLIAPI' or slug like 'github')",
26
- ),
27
- search: z.string().optional().describe("Search for apps by name"),
28
- pageSize: z
29
- .number()
30
- .min(1)
31
- .optional()
32
- .describe("Number of apps per page"),
33
- maxItems: z
34
- .number()
35
- .min(1)
36
- .optional()
37
- .describe("Maximum total items to return across all pages"),
38
- })
39
- .describe("List all available apps with optional filtering"),
40
- AppItemSchema,
41
- );
16
+ export const ListAppsSchema = z
17
+ .object({
18
+ appKeys: z
19
+ .array(z.string())
20
+ .optional()
21
+ .describe(
22
+ "Filter apps by app keys (e.g., 'SlackCLIAPI' or slug like 'github')",
23
+ ),
24
+ search: z.string().optional().describe("Search for apps by name"),
25
+ pageSize: z.number().min(1).optional().describe("Number of apps per page"),
26
+ maxItems: z
27
+ .number()
28
+ .min(1)
29
+ .optional()
30
+ .describe("Maximum total items to return across all pages"),
31
+ })
32
+ .describe("List all available apps with optional filtering");
42
33
 
43
34
  // Type inferred from schema
44
35
  export type ListAppsOptions = z.infer<typeof ListAppsSchema>;
@@ -6,7 +6,6 @@ import {
6
6
  import { listAuthenticationsPlugin } from "./index";
7
7
  import { createSdk } from "../../sdk";
8
8
  import type { ApiClient } from "../../api";
9
- import type { AppItem } from "../../types/domain";
10
9
 
11
10
  const mockAuthenticationsResponse = {
12
11
  results: [
@@ -42,15 +41,6 @@ const mockAuthenticationsResponse = {
42
41
  previous: null,
43
42
  };
44
43
 
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",
52
- };
53
-
54
44
  describe("listAuthentications plugin", () => {
55
45
  let mockApiClient: ApiClient;
56
46
  let mockGetVersionedImplementationId: any;
@@ -72,15 +62,14 @@ describe("listAuthentications plugin", () => {
72
62
  },
73
63
  });
74
64
 
65
+ const mockResolveAppKeys = vi.fn().mockResolvedValue([]);
66
+
75
67
  const manifestPlugin = () => ({
76
68
  context: {
77
69
  manifest: null,
78
70
  getVersionedImplementationId: mockGetVersionedImplementationId,
79
- getManifestEntry: () => ({
80
- implementationName: "SlackCLIAPI",
81
- version: "1.21.1",
82
- }),
83
- getImplementation: vi.fn().mockResolvedValue(mockSlackApp),
71
+ resolveAppKeys: mockResolveAppKeys,
72
+ updateManifestEntry: vi.fn().mockResolvedValue(["test-key", {}]),
84
73
  },
85
74
  });
86
75
 
@@ -152,6 +141,21 @@ describe("listAuthentications plugin", () => {
152
141
  }).toThrow(ZapierValidationError);
153
142
  });
154
143
 
144
+ it("should throw validation error for invalid authenticationIds type", () => {
145
+ const sdk = createTestSdk();
146
+ expect(() => {
147
+ sdk.listAuthentications({
148
+ authenticationIds: "123" as any, // Should be array of strings
149
+ });
150
+ }).toThrow(ZapierValidationError);
151
+
152
+ expect(() => {
153
+ sdk.listAuthentications({
154
+ authenticationIds: [123] as any, // Should be array of strings, not numbers
155
+ });
156
+ }).toThrow(ZapierValidationError);
157
+ });
158
+
155
159
  it("should throw validation error for invalid pageSize", () => {
156
160
  const sdk = createTestSdk();
157
161
  expect(() => {
@@ -186,6 +190,7 @@ describe("listAuthentications plugin", () => {
186
190
  const sdk = createTestSdk();
187
191
  const result = await sdk.listAuthentications({
188
192
  appKey: "slack",
193
+ authenticationIds: ["123", "456"],
189
194
  search: "workspace",
190
195
  title: "My Slack Workspace",
191
196
  accountId: "acc_123",
@@ -336,6 +341,38 @@ describe("listAuthentications plugin", () => {
336
341
  }),
337
342
  );
338
343
  });
344
+
345
+ it("should pass authenticationIds as ids parameter to API", async () => {
346
+ const sdk = createTestSdk();
347
+ await sdk.listAuthentications({
348
+ authenticationIds: ["123", "456", "789"],
349
+ });
350
+
351
+ expect(mockApiClient.get).toHaveBeenCalledWith(
352
+ "/api/v4/authentications/",
353
+ expect.objectContaining({
354
+ searchParams: expect.objectContaining({
355
+ ids: "123,456,789",
356
+ }),
357
+ }),
358
+ );
359
+ });
360
+
361
+ it("should not include ids parameter when authenticationIds is empty", async () => {
362
+ const sdk = createTestSdk();
363
+ await sdk.listAuthentications({
364
+ authenticationIds: [],
365
+ });
366
+
367
+ expect(mockApiClient.get).toHaveBeenCalledWith(
368
+ "/api/v4/authentications/",
369
+ expect.objectContaining({
370
+ searchParams: expect.not.objectContaining({
371
+ ids: expect.anything(),
372
+ }),
373
+ }),
374
+ );
375
+ });
339
376
  });
340
377
 
341
378
  describe("pagination", () => {
@@ -18,6 +18,8 @@ import {
18
18
  } from "../../utils/function-utils";
19
19
  import type { GetVersionedImplementationId } from "../manifest/schemas";
20
20
  import type { ManifestPluginProvides } from "../manifest";
21
+ import { appKeyResolver } from "../../resolvers";
22
+ import { AuthenticationItemSchema } from "../../schemas/Auth";
21
23
 
22
24
  export interface ListAuthenticationsPluginProvides {
23
25
  listAuthentications: (options?: ListAuthenticationsOptions) => Promise<{
@@ -36,11 +38,11 @@ export interface ListAuthenticationsPluginProvides {
36
38
  }
37
39
 
38
40
  export const listAuthenticationsPlugin: Plugin<
39
- GetSdkType<ManifestPluginProvides>, // requires getApp in SDK
41
+ GetSdkType<ManifestPluginProvides>,
40
42
  {
41
43
  api: ApiClient;
42
44
  getVersionedImplementationId: GetVersionedImplementationId;
43
- }, // requires api in context
45
+ },
44
46
  ListAuthenticationsPluginProvides
45
47
  > = ({ context }) => {
46
48
  const listAuthentications = createPaginatedFunction(
@@ -64,6 +66,11 @@ export const listAuthenticationsPlugin: Plugin<
64
66
  }
65
67
  }
66
68
 
69
+ // Add authenticationIds as ids parameter if provided
70
+ if (options.authenticationIds && options.authenticationIds.length > 0) {
71
+ searchParams.ids = options.authenticationIds.join(",");
72
+ }
73
+
67
74
  // Add other query parameters if provided
68
75
  // Use title as search if no explicit search provided
69
76
  if (options.search) {
@@ -130,7 +137,13 @@ export const listAuthenticationsPlugin: Plugin<
130
137
  meta: {
131
138
  listAuthentications: {
132
139
  categories: ["authentication"],
140
+ type: "list",
141
+ itemType: "Authentication",
133
142
  inputSchema: ListAuthenticationsSchema,
143
+ outputSchema: AuthenticationItemSchema,
144
+ resolvers: {
145
+ appKey: appKeyResolver,
146
+ },
134
147
  },
135
148
  },
136
149
  },
@@ -16,6 +16,10 @@ export const ListAuthenticationsSchema = z
16
16
  appKey: AppKeyPropertySchema.optional().describe(
17
17
  "App key of authentications to list (e.g., 'SlackCLIAPI')",
18
18
  ),
19
+ authenticationIds: z
20
+ .array(z.string())
21
+ .optional()
22
+ .describe("List of authentication IDs to filter by"),
19
23
  search: z
20
24
  .string()
21
25
  .optional()
@@ -10,10 +10,19 @@ import {
10
10
  ListInputFieldChoicesSchema,
11
11
  type ListInputFieldChoicesOptions,
12
12
  type ListInputFieldChoicesPage,
13
+ InputFieldChoiceItemSchema,
13
14
  } from "./schemas";
14
15
  import { ZapierApiError } from "../../types/errors";
15
16
  import { createPaginatedFunction } from "../../utils/function-utils";
16
17
  import type { GetActionPluginProvides } from "../getAction";
18
+ import {
19
+ appKeyResolver,
20
+ actionTypeResolver,
21
+ actionKeyResolver,
22
+ authenticationIdResolver,
23
+ inputFieldKeyResolver,
24
+ inputsAllOptionalResolver,
25
+ } from "../../resolvers";
17
26
 
18
27
  // Transform NeedChoices to InputFieldChoiceItem
19
28
  function transformNeedChoicesToInputFieldChoiceItem(
@@ -116,7 +125,7 @@ export const listInputFieldChoicesPlugin: Plugin<
116
125
 
117
126
  // Handle pagination
118
127
  let nextCursor: string | undefined;
119
- if (choicesData.next_page !== undefined) {
128
+ if (choicesData.next_page != null) {
120
129
  nextCursor = choicesData.next_page.toString();
121
130
  } else if (choicesData.links?.next) {
122
131
  // Extract page from next URL for external actions
@@ -144,7 +153,18 @@ export const listInputFieldChoicesPlugin: Plugin<
144
153
  meta: {
145
154
  listInputFieldChoices: {
146
155
  categories: ["action"],
156
+ type: "list",
157
+ itemType: "InputFieldChoice",
147
158
  inputSchema: ListInputFieldChoicesSchema,
159
+ outputSchema: InputFieldChoiceItemSchema,
160
+ resolvers: {
161
+ appKey: appKeyResolver,
162
+ actionType: actionTypeResolver,
163
+ actionKey: actionKeyResolver,
164
+ authenticationId: authenticationIdResolver,
165
+ inputFieldKey: inputFieldKeyResolver,
166
+ inputs: inputsAllOptionalResolver,
167
+ },
148
168
  },
149
169
  },
150
170
  },
@@ -6,7 +6,8 @@ import {
6
6
  ActionKeyPropertySchema,
7
7
  InputsPropertySchema,
8
8
  } from "../../types/properties";
9
- import { withFormatter, withOutputSchema } from "../../utils/schema-utils";
9
+ import { withFormatter } from "../../utils/schema-utils";
10
+ import { NeedChoicesSchema } from "../../api/schemas";
10
11
  import type { PaginatedSdkFunction } from "../../types/functions";
11
12
  import type {
12
13
  ZapierConfigurationError,
@@ -21,46 +22,33 @@ import type {
21
22
  // Input Field Choice Item Schema
22
23
  // ============================================================================
23
24
 
24
- export const InputFieldChoiceItemSchema = withFormatter(
25
- z.object({
26
- key: z.string().optional().describe("Unique key/value for the choice"),
27
- label: z
28
- .string()
29
- .optional()
30
- .describe("Human readable label for the choice"),
31
- sample: z.string().optional().describe("Sample value for the choice"),
32
- value: z
33
- .string()
34
- .optional()
35
- .describe("Value to be submitted when selected"),
36
- }),
37
- {
38
- format: (item) => {
39
- const title = item.label || item.key || "Choice";
40
- const subtitle =
41
- item.label && item.key && item.label !== item.key
42
- ? `(${item.key})`
43
- : undefined;
44
- const details: Array<{
45
- text: string;
46
- style: "success" | "dim" | "normal" | "accent" | "warning";
47
- }> = [];
25
+ export const InputFieldChoiceItemSchema = withFormatter(NeedChoicesSchema, {
26
+ format: (item) => {
27
+ const title = item.label || item.key || "Choice";
28
+ const details: Array<{
29
+ text: string;
30
+ style: "success" | "dim" | "normal" | "accent" | "warning";
31
+ }> = [];
32
+
33
+ // Show key as detail if different from label
34
+ if (item.label && item.key && item.label !== item.key) {
35
+ details.push({ text: `Key: ${item.key}`, style: "dim" });
36
+ }
48
37
 
49
- if (item.sample && item.sample !== item.key) {
50
- details.push({ text: `Sample: ${item.sample}`, style: "dim" });
51
- }
52
- if (item.value && item.value !== item.key) {
53
- details.push({ text: `Value: ${item.value}`, style: "normal" });
54
- }
38
+ if (item.sample && item.sample !== item.key) {
39
+ details.push({ text: `Sample: ${item.sample}`, style: "dim" });
40
+ }
41
+ if (item.value && item.value !== item.key) {
42
+ details.push({ text: `Value: ${item.value}`, style: "normal" });
43
+ }
55
44
 
56
- return {
57
- title,
58
- subtitle,
59
- details,
60
- };
61
- },
45
+ return {
46
+ title,
47
+ key: item.key,
48
+ details,
49
+ };
62
50
  },
63
- );
51
+ });
64
52
 
65
53
  export type InputFieldChoiceItem = z.infer<typeof InputFieldChoiceItemSchema>;
66
54
 
@@ -68,47 +56,44 @@ export type InputFieldChoiceItem = z.infer<typeof InputFieldChoiceItemSchema>;
68
56
  // Plugin Schema Definition
69
57
  // ============================================================================
70
58
 
71
- export const ListInputFieldChoicesSchema = withOutputSchema(
72
- z
73
- .object({
74
- // Required action identification
75
- appKey: AppKeyPropertySchema,
76
- actionType: ActionTypePropertySchema,
77
- actionKey: ActionKeyPropertySchema,
59
+ export const ListInputFieldChoicesSchema = z
60
+ .object({
61
+ // Required action identification
62
+ appKey: AppKeyPropertySchema,
63
+ actionType: ActionTypePropertySchema,
64
+ actionKey: ActionKeyPropertySchema,
78
65
 
79
- // Input field specification
80
- inputFieldKey: z
81
- .string()
82
- .min(1)
83
- .describe("Input field key to get choices for."),
66
+ // Input field specification
67
+ inputFieldKey: z
68
+ .string()
69
+ .min(1)
70
+ .describe("Input field key to get choices for."),
84
71
 
85
- // Common parameters
86
- authenticationId: AuthenticationIdPropertySchema.nullable().optional(),
87
- inputs: InputsPropertySchema.optional().describe(
88
- "Current input values that may affect available choices",
89
- ),
90
- page: z
91
- .number()
92
- .int()
93
- .min(0)
94
- .optional()
95
- .describe("Page number for paginated results"),
72
+ // Common parameters
73
+ authenticationId: AuthenticationIdPropertySchema.nullable().optional(),
74
+ inputs: InputsPropertySchema.optional().describe(
75
+ "Current input values that may affect available choices",
76
+ ),
77
+ page: z
78
+ .number()
79
+ .int()
80
+ .min(0)
81
+ .optional()
82
+ .describe("Page number for paginated results"),
96
83
 
97
- // Pagination options (SDK-level)
98
- pageSize: z
99
- .number()
100
- .min(1)
101
- .optional()
102
- .describe("Number of choices per page"),
103
- maxItems: z
104
- .number()
105
- .min(1)
106
- .optional()
107
- .describe("Maximum total items to return across all pages"),
108
- })
109
- .describe("Get the available choices for a dynamic dropdown input field"),
110
- InputFieldChoiceItemSchema,
111
- );
84
+ // Pagination options (SDK-level)
85
+ pageSize: z
86
+ .number()
87
+ .min(1)
88
+ .optional()
89
+ .describe("Number of choices per page"),
90
+ maxItems: z
91
+ .number()
92
+ .min(1)
93
+ .optional()
94
+ .describe("Maximum total items to return across all pages"),
95
+ })
96
+ .describe("Get the available choices for a dynamic dropdown input field");
112
97
 
113
98
  // Type inferred from schema
114
99
  export type ListInputFieldChoicesOptions = z.infer<
@@ -217,7 +217,7 @@ describe("listInputFields plugin", () => {
217
217
  // Check message field transformation
218
218
  expect(result.data[0]).toEqual(
219
219
  expect.objectContaining({
220
- id: "message",
220
+ key: "message",
221
221
  title: "Message",
222
222
  description: "The message to send",
223
223
  is_required: true,
@@ -227,26 +227,22 @@ describe("listInputFields plugin", () => {
227
227
  }),
228
228
  );
229
229
 
230
- // Check channel field with choices (SELECT format)
230
+ // Check channel field with SELECT format
231
231
  expect(result.data[1]).toEqual(
232
232
  expect.objectContaining({
233
- id: "channel",
233
+ key: "channel",
234
234
  title: "Channel",
235
235
  description: "The channel to send to",
236
236
  is_required: true,
237
237
  value_type: "STRING",
238
238
  format: "SELECT",
239
- choices: [
240
- { value: "#general", label: "General", sample: "#general" },
241
- { value: "#random", label: "Random", sample: "#random" },
242
- ],
243
239
  }),
244
240
  );
245
241
 
246
242
  // Check array field
247
243
  expect(result.data[2]).toEqual(
248
244
  expect.objectContaining({
249
- id: "tags",
245
+ key: "tags",
250
246
  title: "Tags",
251
247
  description: "List of tags",
252
248
  value_type: "ARRAY",
@@ -405,7 +401,7 @@ describe("listInputFields plugin", () => {
405
401
  }
406
402
 
407
403
  expect(items).toHaveLength(3);
408
- expect(items[0].id).toBe("message");
404
+ expect(items[0].key).toBe("message");
409
405
  });
410
406
  });
411
407
  });