@zapier/zapier-sdk 0.8.2 → 0.9.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 (104) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/README.md +10 -33
  3. package/dist/api/client.d.ts.map +1 -1
  4. package/dist/api/client.js +1 -2
  5. package/dist/api/polling.d.ts +36 -6
  6. package/dist/api/polling.d.ts.map +1 -1
  7. package/dist/api/polling.js +132 -28
  8. package/dist/api/polling.test.d.ts +2 -0
  9. package/dist/api/polling.test.d.ts.map +1 -0
  10. package/dist/api/polling.test.js +318 -0
  11. package/dist/api/types.d.ts +1 -2
  12. package/dist/api/types.d.ts.map +1 -1
  13. package/dist/index.cjs +489 -252
  14. package/dist/index.d.mts +182 -187
  15. package/dist/index.d.ts +1 -2
  16. package/dist/index.d.ts.map +1 -1
  17. package/dist/index.js +0 -1
  18. package/dist/index.mjs +486 -251
  19. package/dist/plugins/apps/index.d.ts +4 -0
  20. package/dist/plugins/apps/index.d.ts.map +1 -1
  21. package/dist/plugins/getApp/index.d.ts +2 -7
  22. package/dist/plugins/getApp/index.d.ts.map +1 -1
  23. package/dist/plugins/getApp/index.js +9 -9
  24. package/dist/plugins/getApp/index.test.js +1 -1
  25. package/dist/plugins/getAuthentication/index.test.js +1 -1
  26. package/dist/plugins/listActions/index.d.ts +2 -4
  27. package/dist/plugins/listActions/index.d.ts.map +1 -1
  28. package/dist/plugins/listActions/index.js +1 -1
  29. package/dist/plugins/listActions/index.test.js +4 -4
  30. package/dist/plugins/listApps/index.d.ts +4 -7
  31. package/dist/plugins/listApps/index.d.ts.map +1 -1
  32. package/dist/plugins/listApps/index.js +33 -17
  33. package/dist/plugins/listApps/index.test.js +22 -2
  34. package/dist/plugins/listAuthentications/index.d.ts +2 -4
  35. package/dist/plugins/listAuthentications/index.d.ts.map +1 -1
  36. package/dist/plugins/listAuthentications/index.js +4 -0
  37. package/dist/plugins/listAuthentications/index.test.js +39 -13
  38. package/dist/plugins/listAuthentications/schemas.d.ts +3 -0
  39. package/dist/plugins/listAuthentications/schemas.d.ts.map +1 -1
  40. package/dist/plugins/listAuthentications/schemas.js +4 -0
  41. package/dist/plugins/manifest/index.d.ts +25 -9
  42. package/dist/plugins/manifest/index.d.ts.map +1 -1
  43. package/dist/plugins/manifest/index.js +239 -67
  44. package/dist/plugins/manifest/index.test.js +426 -171
  45. package/dist/plugins/manifest/schemas.d.ts +5 -1
  46. package/dist/plugins/manifest/schemas.d.ts.map +1 -1
  47. package/dist/plugins/manifest/schemas.js +1 -0
  48. package/dist/sdk.d.ts +5 -11
  49. package/dist/sdk.d.ts.map +1 -1
  50. package/dist/sdk.js +1 -4
  51. package/dist/types/plugin.d.ts +1 -0
  52. package/dist/types/plugin.d.ts.map +1 -1
  53. package/dist/types/sdk.d.ts +6 -3
  54. package/dist/types/sdk.d.ts.map +1 -1
  55. package/dist/utils/domain-utils.d.ts +16 -0
  56. package/dist/utils/domain-utils.d.ts.map +1 -1
  57. package/dist/utils/domain-utils.js +46 -27
  58. package/dist/utils/domain-utils.test.js +157 -3
  59. package/dist/utils/file-utils.d.ts +4 -0
  60. package/dist/utils/file-utils.d.ts.map +1 -0
  61. package/dist/utils/file-utils.js +74 -0
  62. package/dist/utils/file-utils.test.d.ts +2 -0
  63. package/dist/utils/file-utils.test.d.ts.map +1 -0
  64. package/dist/utils/file-utils.test.js +51 -0
  65. package/package.json +1 -1
  66. package/src/api/client.ts +5 -4
  67. package/src/api/polling.test.ts +405 -0
  68. package/src/api/polling.ts +224 -44
  69. package/src/api/types.ts +1 -2
  70. package/src/index.ts +1 -1
  71. package/src/plugins/apps/index.ts +9 -2
  72. package/src/plugins/getApp/index.test.ts +1 -1
  73. package/src/plugins/getApp/index.ts +12 -14
  74. package/src/plugins/getAuthentication/index.test.ts +1 -1
  75. package/src/plugins/listActions/index.test.ts +8 -7
  76. package/src/plugins/listActions/index.ts +3 -3
  77. package/src/plugins/listApps/index.test.ts +23 -2
  78. package/src/plugins/listApps/index.ts +46 -25
  79. package/src/plugins/listAuthentications/index.test.ts +52 -15
  80. package/src/plugins/listAuthentications/index.ts +7 -2
  81. package/src/plugins/listAuthentications/schemas.ts +4 -0
  82. package/src/plugins/manifest/index.test.ts +503 -197
  83. package/src/plugins/manifest/index.ts +338 -82
  84. package/src/plugins/manifest/schemas.ts +9 -2
  85. package/src/sdk.ts +1 -5
  86. package/src/types/plugin.ts +3 -0
  87. package/src/types/sdk.ts +26 -21
  88. package/src/utils/domain-utils.test.ts +196 -2
  89. package/src/utils/domain-utils.ts +68 -35
  90. package/src/utils/file-utils.test.ts +73 -0
  91. package/src/utils/file-utils.ts +94 -0
  92. package/tsconfig.tsbuildinfo +1 -1
  93. package/dist/plugins/lockVersion/index.d.ts +0 -24
  94. package/dist/plugins/lockVersion/index.d.ts.map +0 -1
  95. package/dist/plugins/lockVersion/index.js +0 -72
  96. package/dist/plugins/lockVersion/index.test.d.ts +0 -2
  97. package/dist/plugins/lockVersion/index.test.d.ts.map +0 -1
  98. package/dist/plugins/lockVersion/index.test.js +0 -129
  99. package/dist/plugins/lockVersion/schemas.d.ts +0 -10
  100. package/dist/plugins/lockVersion/schemas.d.ts.map +0 -1
  101. package/dist/plugins/lockVersion/schemas.js +0 -6
  102. package/src/plugins/lockVersion/index.test.ts +0 -176
  103. package/src/plugins/lockVersion/index.ts +0 -112
  104. package/src/plugins/lockVersion/schemas.ts +0 -9
@@ -1,30 +1,41 @@
1
- import { readFileSync } from "fs";
2
- import { resolve } from "path";
1
+ import { readFile, writeFile, resolve } from "../../utils/file-utils";
3
2
  import type {
4
- GetImplementation,
5
- GetManifestEntry,
6
3
  GetVersionedImplementationId,
7
4
  Manifest,
5
+ ManifestEntry,
8
6
  ManifestPluginOptionsSchema,
7
+ ResolveAppKeys,
9
8
  } from "./schemas";
10
- import { ManifestSchema } from "./schemas";
11
- import type { GetSdkType, Plugin } from "../../types/plugin";
9
+ import { ManifestSchema, DEFAULT_CONFIG_PATH } from "./schemas";
10
+ import type { Plugin } from "../../types/plugin";
12
11
  import type { z } from "zod";
13
12
  import type { ApiClient } from "../../api";
14
- import type { ListAppsPluginProvides } from "../listApps";
15
- import type { ImplementationsResponse } from "../../api/types";
13
+ import type { ImplementationsMetaResponse } from "../../api/types";
16
14
  import {
17
- normalizeImplementationToAppItem,
15
+ normalizeImplementationMetaToAppItem,
18
16
  splitVersionedKey,
17
+ isSnakeCasedSlug,
18
+ dashifySnakeCasedSlug,
19
+ toAppLocator,
20
+ type ResolvedAppLocator,
21
+ isResolvedAppLocator,
19
22
  } from "../../utils/domain-utils";
23
+ import type { AppItem } from "../../types/domain";
24
+ import { extractCursor } from "../../utils/function-utils";
25
+ import { paginate } from "../../utils/pagination-utils";
26
+ import { toArrayFromAsync } from "../../utils/array-utils";
20
27
 
21
28
  export type ManifestPluginOptions = z.infer<typeof ManifestPluginOptionsSchema>;
22
29
 
23
30
  export interface ManifestPluginProvides {
24
31
  context: {
25
32
  getVersionedImplementationId: GetVersionedImplementationId;
26
- getManifestEntry: GetManifestEntry;
27
- getImplementation: GetImplementation;
33
+ resolveAppKeys: ResolveAppKeys;
34
+ updateManifestEntry: (
35
+ appKey: string,
36
+ entry: ManifestEntry,
37
+ configPath?: string,
38
+ ) => Promise<[string, ManifestEntry]>;
28
39
  };
29
40
  }
30
41
 
@@ -54,127 +65,372 @@ function parseManifestContent(
54
65
  }
55
66
 
56
67
  /**
57
- * Load manifest from a file path synchronously
58
- * Supports local files (Node.js only)
68
+ * Read manifest from a file path asynchronously
69
+ * Supports local files (Node.js) and browser environments (fallback to global filesystem)
59
70
  */
60
- export function loadManifestFromFile(filePath: string): Manifest | null {
71
+ export async function readManifestFromFile(
72
+ filePath: string,
73
+ ): Promise<Manifest | null> {
61
74
  try {
62
75
  // Resolve relative paths relative to current working directory
63
- const resolvedPath = resolve(filePath);
64
- const content = readFileSync(resolvedPath, "utf8");
76
+ const resolvedPath = await resolve(filePath);
77
+ const content = await readFile(resolvedPath);
65
78
  return parseManifestContent(content, resolvedPath);
66
79
  } catch {
67
- console.warn(`⚠️ Failed to load manifest from ${filePath}`);
80
+ console.warn(`⚠️ Failed to read manifest from ${filePath}`);
68
81
  return null;
69
82
  }
70
83
  }
71
84
 
72
- const emitWarning = (appKey: string) => {
73
- console.warn(
74
- `\n${"⚠️".padEnd(3)} ${"WARNING".padEnd(8)} No manifest version found for '${appKey}'`,
75
- );
76
- console.warn(
77
- ` ${"↳".padEnd(3)} Using a manifest ensures version locking and prevents unexpected behavior due to version changes.`,
85
+ /**
86
+ * Write manifest to a file path asynchronously
87
+ * Supports local files (Node.js) and browser environments (fallback to global filesystem)
88
+ */
89
+ async function writeManifestToFile(
90
+ manifest: Manifest,
91
+ filePath: string,
92
+ ): Promise<void> {
93
+ const resolvedPath = await resolve(filePath);
94
+ await writeFile(resolvedPath, JSON.stringify(manifest, null, 2));
95
+ }
96
+
97
+ /**
98
+ * Get the preferred key for storing an app in the manifest
99
+ * Extracted from plugin to make it easier to test
100
+ */
101
+ export async function getPreferredManifestEntryKey({
102
+ appKey,
103
+ api,
104
+ }: {
105
+ appKey: string;
106
+ api: ApiClient;
107
+ }): Promise<string> {
108
+ const locator = toAppLocator(appKey);
109
+
110
+ // If we have a slug, prefer it
111
+ if (locator.slug) {
112
+ return locator.slug;
113
+ }
114
+
115
+ // If we have implementation name, look up the latest to get the slug
116
+ if (locator.implementationName) {
117
+ try {
118
+ // API call to get app metadata by implementation name using selected_apis parameter
119
+ const implementationsEnvelope: ImplementationsMetaResponse =
120
+ await api.get(`/api/v4/implementations-meta/lookup/`, {
121
+ searchParams: {
122
+ selected_apis: locator.implementationName,
123
+ },
124
+ });
125
+
126
+ if (
127
+ implementationsEnvelope.results.length > 0 &&
128
+ implementationsEnvelope.results[0].slug
129
+ ) {
130
+ return implementationsEnvelope.results[0].slug;
131
+ }
132
+ } catch {
133
+ // Fall back to implementation name if lookup fails
134
+ }
135
+
136
+ return locator.implementationName;
137
+ }
138
+
139
+ // Fall back to original key if we can't determine anything better
140
+ return locator.lookupAppKey;
141
+ }
142
+
143
+ async function listAppsForSlugsPage({
144
+ slugs,
145
+ cursor,
146
+ api,
147
+ }: {
148
+ slugs: string[];
149
+ cursor?: string;
150
+ api: ApiClient;
151
+ }) {
152
+ const searchParams: Record<string, string> = {};
153
+
154
+ if (slugs.length > 0) {
155
+ searchParams.slugs = slugs.join(",");
156
+ }
157
+
158
+ if (cursor) {
159
+ searchParams.offset = cursor;
160
+ }
161
+
162
+ const implementationsEnvelope: ImplementationsMetaResponse = await api.get(
163
+ "/api/v4/implementations-meta/lookup/",
164
+ {
165
+ searchParams,
166
+ },
78
167
  );
79
- console.warn(
80
- ` ${"↳".padEnd(3)} Generate/update the manifest with: \`zapier-sdk lock-version ${appKey}\`\n`,
168
+
169
+ return {
170
+ data: implementationsEnvelope.results.map(
171
+ normalizeImplementationMetaToAppItem,
172
+ ),
173
+ nextCursor: extractCursor(implementationsEnvelope),
174
+ };
175
+ }
176
+
177
+ /**
178
+ * Find a manifest entry by any app key (implementation name, slug, etc.).
179
+ */
180
+ export function findManifestEntry({
181
+ appKey,
182
+ manifest,
183
+ }: {
184
+ appKey: string;
185
+ manifest: Manifest;
186
+ }): [string, ManifestEntry] | null {
187
+ const [appKeyWithoutVersion] = splitVersionedKey(appKey);
188
+
189
+ // Direct match by key
190
+ if (manifest.apps[appKeyWithoutVersion]) {
191
+ return [appKeyWithoutVersion, manifest.apps[appKeyWithoutVersion]];
192
+ }
193
+
194
+ // Handle snake-cased slugs (convert to dashed)
195
+ if (isSnakeCasedSlug(appKey)) {
196
+ const slug = dashifySnakeCasedSlug(appKey);
197
+ if (manifest.apps[slug]) {
198
+ return [slug, manifest.apps[slug]];
199
+ }
200
+ }
201
+
202
+ // Search by implementation name in manifest values
203
+ for (const [key, entry] of Object.entries(manifest.apps)) {
204
+ if (entry.implementationName === appKeyWithoutVersion) {
205
+ return [key, entry];
206
+ }
207
+ }
208
+
209
+ // No match found
210
+ return null;
211
+ }
212
+
213
+ /**
214
+ * Turn any app keys (slugs, implementation names, etc.) into app locators, which are objects that will be guaranteed to
215
+ * have implementation names. Note that this function will not actually guarantee that implementation names are valid!
216
+ * It will attempt to find the app key in the manifest, or if it's a slug, actually do an API call, or otherwise just
217
+ * assume it's an implementation name that will be used for an API call.
218
+ */
219
+ async function resolveAppKeys({
220
+ appKeys,
221
+ api,
222
+ manifest,
223
+ }: {
224
+ appKeys: string[];
225
+ api: ApiClient;
226
+ manifest: Manifest;
227
+ }): Promise<ResolvedAppLocator[]> {
228
+ // Step 1: Convert all app keys to locators
229
+ const locators = appKeys.map(toAppLocator);
230
+
231
+ // Step 2: Map to resolved/unresolved via manifest
232
+ const locatorsWithManifest = locators.map((locator) => {
233
+ const manifestEntryResult = findManifestEntry({
234
+ appKey: locator.lookupAppKey,
235
+ manifest,
236
+ });
237
+
238
+ if (manifestEntryResult) {
239
+ const [, manifestEntry] = manifestEntryResult;
240
+ // Use manifest entry to resolve implementation name
241
+ const resolvedVersion = locator.version || manifestEntry.version;
242
+
243
+ const resolvedLocator: ResolvedAppLocator = {
244
+ ...locator,
245
+ implementationName: manifestEntry.implementationName,
246
+ version: resolvedVersion,
247
+ };
248
+
249
+ return resolvedLocator;
250
+ }
251
+
252
+ // If these have an implementationName, they're already resolved.
253
+ return locator;
254
+ });
255
+
256
+ // Step 3: Separate resolved from unresolved
257
+ const unresolvedLocators = locatorsWithManifest.filter(
258
+ (locator) => !isResolvedAppLocator(locator),
81
259
  );
82
- };
260
+
261
+ // Step 4: Resolve slugs via API
262
+ const slugsToResolve = unresolvedLocators
263
+ .map((locator) => locator.slug)
264
+ .filter((slug): slug is string => !!slug)
265
+ .filter((slug, index, array) => array.indexOf(slug) === index); // dedupe
266
+
267
+ if (slugsToResolve.length === 0) {
268
+ return locatorsWithManifest.filter(isResolvedAppLocator);
269
+ }
270
+
271
+ const iterator = paginate(listAppsForSlugsPage, {
272
+ slugs: slugsToResolve,
273
+ api,
274
+ });
275
+
276
+ const pages = await toArrayFromAsync(iterator);
277
+ const apps = pages.flatMap((page) => page.data);
278
+
279
+ const slugToAppData = new Map<string, AppItem>();
280
+ for (const app of apps) {
281
+ if (app.slug) {
282
+ slugToAppData.set(app.slug, app);
283
+ }
284
+ }
285
+
286
+ const slugResolvedLocators = locatorsWithManifest.map((locator) => {
287
+ if (isResolvedAppLocator(locator)) {
288
+ return locator;
289
+ }
290
+ if (locator.slug) {
291
+ const appData = slugToAppData.get(locator.slug);
292
+ if (appData) {
293
+ // After resolving from API, check if we have a manifest entry for this implementation name
294
+ const manifestEntryByImplementationName = findManifestEntry({
295
+ appKey: appData.key, // appData.key is the implementation name
296
+ manifest,
297
+ });
298
+
299
+ let version = locator.version;
300
+ if (!version) {
301
+ // Prefer manifest version if available, otherwise use API version
302
+ version = manifestEntryByImplementationName
303
+ ? manifestEntryByImplementationName[1].version || appData.version
304
+ : appData.version;
305
+ }
306
+
307
+ return {
308
+ ...locator,
309
+ implementationName: appData.key,
310
+ version,
311
+ };
312
+ }
313
+ }
314
+ return locator;
315
+ });
316
+
317
+ // Return all resolved locators.
318
+ return slugResolvedLocators.filter(isResolvedAppLocator);
319
+ }
320
+
321
+ export { DEFAULT_CONFIG_PATH } from "./schemas";
83
322
 
84
323
  export const manifestPlugin: Plugin<
85
- GetSdkType<ListAppsPluginProvides>,
324
+ {}, // no SDK dependencies
86
325
  { api: ApiClient },
87
326
  ManifestPluginProvides
88
327
  > = (params) => {
89
- const { sdk, context } = params;
328
+ const { context } = params;
90
329
  const { api, options } = context;
91
- const { manifestPath = ".zapierrc", manifest } = options || {};
330
+ const { manifestPath = DEFAULT_CONFIG_PATH, manifest } = options || {};
92
331
 
93
332
  let resolvedManifest: Manifest | undefined | null;
94
333
 
95
- function resolveManifest() {
334
+ async function resolveManifest(): Promise<Manifest | null> {
96
335
  // If manifest is provided directly, use it
97
336
  if (manifest) {
98
337
  return manifest;
99
338
  }
100
339
  // If manifestPath is provided, load from file
101
340
  if (manifestPath) {
102
- return loadManifestFromFile(manifestPath);
341
+ return await readManifestFromFile(manifestPath);
103
342
  }
104
343
  return null;
105
344
  }
106
345
 
107
- const getResolvedManifest = () => {
346
+ const getResolvedManifest = async (): Promise<Manifest | null> => {
108
347
  if (typeof resolvedManifest === "undefined") {
109
- resolvedManifest = resolveManifest() ?? null;
348
+ resolvedManifest = (await resolveManifest()) ?? null;
110
349
  }
111
350
 
112
351
  return resolvedManifest;
113
352
  };
114
353
 
115
- const getManifestEntry = (appKey: string) => {
116
- return getResolvedManifest()?.apps?.[appKey] || null;
354
+ const getVersionedImplementationId = async (appKey: string) => {
355
+ const resolvedApps = await resolveAppKeys({
356
+ appKeys: [appKey],
357
+ api,
358
+ manifest: (await getResolvedManifest()) ?? { apps: {} },
359
+ });
360
+
361
+ const resolvedApp = resolvedApps[0];
362
+ if (!resolvedApp) return null;
363
+
364
+ return `${resolvedApp.implementationName}@${resolvedApp.version || "latest"}`;
117
365
  };
118
366
 
119
- const getImplementation = async (appKey: string) => {
120
- let selectedApi = null;
121
- const manifestImplementation = getResolvedManifest()?.apps?.[appKey];
122
- const [versionlessAppKey, version] = splitVersionedKey(appKey);
123
-
124
- // Use versioned app key if provided
125
- if (version) {
126
- selectedApi = `${versionlessAppKey}@${version}`;
127
- // Otherwise, use manifest entry if available
128
- } else if (manifestImplementation) {
129
- selectedApi = `${manifestImplementation.implementationName}@${manifestImplementation.version || "latest"}`;
130
- }
367
+ const updateManifestEntry = async (
368
+ appKey: string,
369
+ entry: ManifestEntry,
370
+ configPath: string = DEFAULT_CONFIG_PATH,
371
+ ): Promise<[string, ManifestEntry]> => {
372
+ const manifest = (await readManifestFromFile(configPath)) || { apps: {} };
131
373
 
132
- if (selectedApi) {
133
- const searchParams = {
134
- selected_apis: selectedApi,
135
- };
136
- const implementationData: ImplementationsResponse = await api.get(
137
- "/api/v4/implementations/",
138
- {
139
- searchParams,
140
- },
141
- );
142
- const implementationResults = implementationData.results[0];
143
- if (!implementationResults) return null;
144
- return normalizeImplementationToAppItem(implementationResults);
145
- }
146
- emitWarning(appKey);
374
+ // Try to find existing entry by direct key first
375
+ let existingEntry = findManifestEntry({
376
+ appKey,
377
+ manifest,
378
+ });
147
379
 
148
- const appsIterator = sdk.listApps({ appKeys: [appKey] }).items();
380
+ // If not found directly, try to resolve the app key and search by implementation name
381
+ if (!existingEntry) {
382
+ try {
383
+ const resolvedApps = await resolveAppKeys({
384
+ appKeys: [appKey],
385
+ api,
386
+ manifest,
387
+ });
149
388
 
150
- const apps = [];
151
- for await (const app of appsIterator) {
152
- apps.push(app);
153
- break; // Only need the first result
389
+ if (resolvedApps.length > 0) {
390
+ const resolvedImplementationName = resolvedApps[0].implementationName;
391
+ // Try to find entry using the resolved implementation name
392
+ existingEntry = findManifestEntry({
393
+ appKey: resolvedImplementationName,
394
+ manifest,
395
+ });
396
+ }
397
+ } catch {
398
+ // If resolution fails, continue with original logic
399
+ }
154
400
  }
155
401
 
156
- if (apps.length === 0) {
157
- return null;
158
- }
159
- const app = apps[0];
160
- return app;
161
- };
402
+ let manifestKey: string;
162
403
 
163
- const getVersionedImplementationId = async (appKey: string) => {
164
- const manifestEntry = getManifestEntry(appKey);
165
- if (manifestEntry) {
166
- return `${manifestEntry.implementationName}@${manifestEntry.version || "latest"}`;
404
+ if (existingEntry) {
405
+ // Use existing key to maintain consistency with types files
406
+ manifestKey = existingEntry[0];
407
+ } else {
408
+ // Get preferred key for new entries
409
+ manifestKey = await getPreferredManifestEntryKey({
410
+ appKey,
411
+ api,
412
+ });
167
413
  }
168
- const implementation = await getImplementation(appKey);
169
- if (!implementation) return null;
170
- return implementation.current_implementation_id;
414
+
415
+ manifest.apps[manifestKey] = entry;
416
+ await writeManifestToFile(manifest, configPath);
417
+
418
+ // Clear the cached manifest so it gets reloaded with the new data
419
+ resolvedManifest = undefined;
420
+
421
+ return [manifestKey, entry];
171
422
  };
172
423
 
173
424
  return {
174
425
  context: {
175
426
  getVersionedImplementationId,
176
- getManifestEntry,
177
- getImplementation,
427
+ resolveAppKeys: async ({ appKeys }: { appKeys: string[] }) =>
428
+ resolveAppKeys({
429
+ appKeys,
430
+ api,
431
+ manifest: (await getResolvedManifest()) ?? { apps: {} },
432
+ }),
433
+ updateManifestEntry,
178
434
  },
179
435
  };
180
436
  };
@@ -1,13 +1,14 @@
1
1
  import { z } from "zod";
2
+ import type { ResolvedAppLocator } from "../../utils/domain-utils";
2
3
  import type { AppItem } from "../../types/domain";
3
4
 
5
+ export const DEFAULT_CONFIG_PATH = ".zapierrc" as const;
6
+
4
7
  export type ManifestEntry = {
5
8
  implementationName: string;
6
9
  version?: string;
7
10
  };
8
11
 
9
- export type GetManifestEntry = (appKey: string) => ManifestEntry | null;
10
-
11
12
  export type GetVersionedImplementationId = (
12
13
  appKey: string,
13
14
  ) => Promise<string | null>;
@@ -18,6 +19,12 @@ export type Manifest = {
18
19
  apps: Record<string, ManifestEntry>;
19
20
  };
20
21
 
22
+ export type ResolveAppKeys = ({
23
+ appKeys,
24
+ }: {
25
+ appKeys: string[];
26
+ }) => Promise<ResolvedAppLocator[]>;
27
+
21
28
  /**
22
29
  * Manifest schema for version locking
23
30
  * Maps app keys to their locked version information
package/src/sdk.ts CHANGED
@@ -32,7 +32,6 @@ import { listInputFieldsPlugin } from "./plugins/listInputFields";
32
32
  import { listInputFieldChoicesPlugin } from "./plugins/listInputFieldChoices";
33
33
  import { requestPlugin } from "./plugins/request";
34
34
  import { manifestPlugin } from "./plugins/manifest";
35
- import { lockVersionPlugin } from "./plugins/lockVersion";
36
35
 
37
36
  // Full SDK interface with plugins applied
38
37
  // Note: ZapierSdk is now defined as ReturnType<typeof createZapierSdk> at the bottom of this file
@@ -125,10 +124,10 @@ export function createZapierSdkWithoutRegistry(options: ZapierSdkOptions = {}) {
125
124
  .addPlugin(apiPlugin)
126
125
 
127
126
  // Manifest plugin (provides version locking context)
127
+ .addPlugin(manifestPlugin)
128
128
 
129
129
  // Apps/actions/fields
130
130
  .addPlugin(listAppsPlugin)
131
- .addPlugin(manifestPlugin)
132
131
  .addPlugin(getAppPlugin)
133
132
  .addPlugin(listActionsPlugin)
134
133
  .addPlugin(getActionPlugin)
@@ -138,9 +137,6 @@ export function createZapierSdkWithoutRegistry(options: ZapierSdkOptions = {}) {
138
137
  // Run action
139
138
  .addPlugin(runActionPlugin)
140
139
 
141
- // Version locking
142
- .addPlugin(lockVersionPlugin)
143
-
144
140
  // Authentications
145
141
  .addPlugin(listAuthenticationsPlugin)
146
142
  .addPlugin(getAuthenticationPlugin)
@@ -41,6 +41,9 @@ export type GetSdkType<TPluginProvides extends PluginProvides> =
41
41
  getContext(): NonNullable<ExtractContextProperties<TPluginProvides>>;
42
42
  };
43
43
 
44
+ export type GetContextType<TPluginProvides extends PluginProvides> =
45
+ NonNullable<ExtractContextProperties<TPluginProvides>>;
46
+
44
47
  // Helper type for standard plugin options with SDK dependency and meta context
45
48
  export type PluginOptions<TSdk = {}, TContext = {}> = {
46
49
  sdk: TSdk;
package/src/types/sdk.ts CHANGED
@@ -29,12 +29,12 @@ import type { GetAuthenticationSdkFunction } from "../plugins/getAuthentication/
29
29
  import type { FindFirstAuthenticationSdkFunction } from "../plugins/findFirstAuthentication/schemas";
30
30
  import type { FindUniqueAuthenticationSdkFunction } from "../plugins/findUniqueAuthentication/schemas";
31
31
  import type { RelayRequestSdkFunction } from "../plugins/request/schemas";
32
- import type { LockVersionPluginProvides } from "../plugins/lockVersion";
33
32
 
34
33
  import type { z } from "zod";
35
34
  import type { RegistryPluginProvides } from "../plugins/registry";
36
35
  import type { GetProfilePluginProvides } from "../plugins/getProfile";
37
- import type { AppsPluginProvides } from "../plugins/apps";
36
+ import type { AppsPluginProvides, ZapierSdkApps } from "../plugins/apps";
37
+ import type { ActionProxy } from "../plugins/apps/types";
38
38
  import type { FetchPluginProvides } from "../plugins/fetch";
39
39
  import type { ListAppsPluginProvides } from "../plugins/listApps";
40
40
  import type { GetAppPluginProvides } from "../plugins/getApp";
@@ -46,6 +46,7 @@ import type { GetAuthenticationPluginProvides } from "../plugins/getAuthenticati
46
46
  import type { FindFirstAuthenticationPluginProvides } from "../plugins/findFirstAuthentication";
47
47
  import type { FindUniqueAuthenticationPluginProvides } from "../plugins/findUniqueAuthentication";
48
48
  import type { ListInputFieldsPluginProvides } from "../plugins/listInputFields";
49
+ import type { ListInputFieldChoicesPluginProvides } from "../plugins/listInputFieldChoices";
49
50
  import type { RequestPluginProvides } from "../plugins/request";
50
51
  import type { GetSdkType } from "./plugin";
51
52
  import type { ManifestPluginProvides } from "../plugins/manifest";
@@ -78,22 +79,26 @@ export interface ZapierSdkFunctions
78
79
  // Note: ZapierSdk type removed - use ReturnType<typeof createZapierSdk> instead
79
80
  // This ensures the type matches exactly what the builder produces
80
81
 
81
- export type ZapierSdk = GetSdkType<
82
- RegistryPluginProvides &
83
- FetchPluginProvides &
84
- AppsPluginProvides &
85
- ListAppsPluginProvides &
86
- ManifestPluginProvides &
87
- GetAppPluginProvides &
88
- ListActionsPluginProvides &
89
- GetActionPluginProvides &
90
- RunActionPluginProvides &
91
- LockVersionPluginProvides &
92
- ListAuthenticationsPluginProvides &
93
- GetAuthenticationPluginProvides &
94
- FindFirstAuthenticationPluginProvides &
95
- FindUniqueAuthenticationPluginProvides &
96
- ListInputFieldsPluginProvides &
97
- RequestPluginProvides &
98
- GetProfilePluginProvides
99
- >;
82
+ export interface ZapierSdk
83
+ extends GetSdkType<
84
+ RegistryPluginProvides &
85
+ FetchPluginProvides &
86
+ AppsPluginProvides &
87
+ ListAppsPluginProvides &
88
+ ManifestPluginProvides &
89
+ GetAppPluginProvides &
90
+ ListActionsPluginProvides &
91
+ GetActionPluginProvides &
92
+ RunActionPluginProvides &
93
+ ListAuthenticationsPluginProvides &
94
+ GetAuthenticationPluginProvides &
95
+ FindFirstAuthenticationPluginProvides &
96
+ FindUniqueAuthenticationPluginProvides &
97
+ ListInputFieldsPluginProvides &
98
+ ListInputFieldChoicesPluginProvides &
99
+ RequestPluginProvides &
100
+ GetProfilePluginProvides
101
+ > {
102
+ // Override apps property to intersect ActionProxy with our typed apps
103
+ apps: ActionProxy & ZapierSdkApps;
104
+ }