@zapier/zapier-sdk 0.13.6 → 0.13.8

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 (155) hide show
  1. package/CHANGELOG.md +15 -0
  2. package/dist/api/client.d.ts.map +1 -1
  3. package/dist/api/client.js +5 -5
  4. package/dist/api/client.test.d.ts +2 -0
  5. package/dist/api/client.test.d.ts.map +1 -0
  6. package/dist/api/client.test.js +80 -0
  7. package/dist/api/index.d.ts +1 -0
  8. package/dist/api/index.d.ts.map +1 -1
  9. package/dist/api/index.js +3 -1
  10. package/dist/api/schemas.d.ts +20 -20
  11. package/dist/api/types.d.ts +2 -0
  12. package/dist/api/types.d.ts.map +1 -1
  13. package/dist/auth.d.ts +3 -0
  14. package/dist/auth.d.ts.map +1 -1
  15. package/dist/auth.test.d.ts +2 -0
  16. package/dist/auth.test.d.ts.map +1 -0
  17. package/dist/auth.test.js +102 -0
  18. package/dist/constants.d.ts +4 -4
  19. package/dist/constants.d.ts.map +1 -1
  20. package/dist/constants.js +4 -4
  21. package/dist/index.cjs +89 -21
  22. package/dist/index.d.mts +21 -1
  23. package/dist/index.d.ts +1 -0
  24. package/dist/index.d.ts.map +1 -1
  25. package/dist/index.js +2 -0
  26. package/dist/index.mjs +88 -22
  27. package/dist/plugins/api/index.d.ts.map +1 -1
  28. package/dist/plugins/api/index.js +4 -1
  29. package/dist/plugins/eventEmission/index.d.ts +2 -0
  30. package/dist/plugins/eventEmission/index.d.ts.map +1 -1
  31. package/dist/plugins/eventEmission/index.js +35 -9
  32. package/dist/plugins/eventEmission/index.test.js +100 -0
  33. package/dist/schemas/Action.d.ts +2 -2
  34. package/dist/schemas/Auth.d.ts +4 -4
  35. package/dist/schemas/Field.d.ts +10 -10
  36. package/dist/sdk.test.js +121 -1
  37. package/dist/types/sdk.d.ts +3 -0
  38. package/dist/types/sdk.d.ts.map +1 -1
  39. package/dist/utils/url-utils.d.ts +19 -0
  40. package/dist/utils/url-utils.d.ts.map +1 -0
  41. package/dist/utils/url-utils.js +62 -0
  42. package/dist/utils/url-utils.test.d.ts +2 -0
  43. package/dist/utils/url-utils.test.d.ts.map +1 -0
  44. package/dist/utils/url-utils.test.js +103 -0
  45. package/package.json +8 -3
  46. package/src/api/auth.ts +0 -28
  47. package/src/api/client.ts +0 -491
  48. package/src/api/debug.test.ts +0 -76
  49. package/src/api/debug.ts +0 -154
  50. package/src/api/index.ts +0 -90
  51. package/src/api/polling.test.ts +0 -405
  52. package/src/api/polling.ts +0 -253
  53. package/src/api/schemas.ts +0 -465
  54. package/src/api/types.ts +0 -152
  55. package/src/auth.ts +0 -72
  56. package/src/constants.ts +0 -16
  57. package/src/index.ts +0 -111
  58. package/src/plugins/api/index.ts +0 -43
  59. package/src/plugins/apps/index.ts +0 -203
  60. package/src/plugins/apps/schemas.ts +0 -64
  61. package/src/plugins/eventEmission/builders.ts +0 -115
  62. package/src/plugins/eventEmission/index.test.ts +0 -169
  63. package/src/plugins/eventEmission/index.ts +0 -294
  64. package/src/plugins/eventEmission/transport.test.ts +0 -214
  65. package/src/plugins/eventEmission/transport.ts +0 -135
  66. package/src/plugins/eventEmission/types.ts +0 -58
  67. package/src/plugins/eventEmission/utils.ts +0 -121
  68. package/src/plugins/fetch/index.ts +0 -83
  69. package/src/plugins/fetch/schemas.ts +0 -37
  70. package/src/plugins/findFirstAuthentication/index.test.ts +0 -209
  71. package/src/plugins/findFirstAuthentication/index.ts +0 -68
  72. package/src/plugins/findFirstAuthentication/schemas.ts +0 -47
  73. package/src/plugins/findUniqueAuthentication/index.test.ts +0 -197
  74. package/src/plugins/findUniqueAuthentication/index.ts +0 -77
  75. package/src/plugins/findUniqueAuthentication/schemas.ts +0 -49
  76. package/src/plugins/getAction/index.test.ts +0 -239
  77. package/src/plugins/getAction/index.ts +0 -75
  78. package/src/plugins/getAction/schemas.ts +0 -41
  79. package/src/plugins/getApp/index.test.ts +0 -181
  80. package/src/plugins/getApp/index.ts +0 -60
  81. package/src/plugins/getApp/schemas.ts +0 -33
  82. package/src/plugins/getAuthentication/index.test.ts +0 -294
  83. package/src/plugins/getAuthentication/index.ts +0 -95
  84. package/src/plugins/getAuthentication/schemas.ts +0 -38
  85. package/src/plugins/getProfile/index.ts +0 -60
  86. package/src/plugins/getProfile/schemas.ts +0 -24
  87. package/src/plugins/listActions/index.test.ts +0 -526
  88. package/src/plugins/listActions/index.ts +0 -132
  89. package/src/plugins/listActions/schemas.ts +0 -55
  90. package/src/plugins/listApps/index.test.ts +0 -378
  91. package/src/plugins/listApps/index.ts +0 -159
  92. package/src/plugins/listApps/schemas.ts +0 -41
  93. package/src/plugins/listAuthentications/index.test.ts +0 -739
  94. package/src/plugins/listAuthentications/index.ts +0 -152
  95. package/src/plugins/listAuthentications/schemas.ts +0 -77
  96. package/src/plugins/listInputFieldChoices/index.test.ts +0 -653
  97. package/src/plugins/listInputFieldChoices/index.ts +0 -173
  98. package/src/plugins/listInputFieldChoices/schemas.ts +0 -125
  99. package/src/plugins/listInputFields/index.test.ts +0 -439
  100. package/src/plugins/listInputFields/index.ts +0 -294
  101. package/src/plugins/listInputFields/schemas.ts +0 -68
  102. package/src/plugins/manifest/index.test.ts +0 -776
  103. package/src/plugins/manifest/index.ts +0 -461
  104. package/src/plugins/manifest/schemas.ts +0 -60
  105. package/src/plugins/registry/index.ts +0 -160
  106. package/src/plugins/request/index.test.ts +0 -333
  107. package/src/plugins/request/index.ts +0 -105
  108. package/src/plugins/request/schemas.ts +0 -69
  109. package/src/plugins/runAction/index.test.ts +0 -388
  110. package/src/plugins/runAction/index.ts +0 -215
  111. package/src/plugins/runAction/schemas.ts +0 -60
  112. package/src/resolvers/actionKey.ts +0 -37
  113. package/src/resolvers/actionType.ts +0 -34
  114. package/src/resolvers/appKey.ts +0 -7
  115. package/src/resolvers/authenticationId.ts +0 -54
  116. package/src/resolvers/index.ts +0 -11
  117. package/src/resolvers/inputFieldKey.ts +0 -70
  118. package/src/resolvers/inputs.ts +0 -69
  119. package/src/schemas/Action.ts +0 -52
  120. package/src/schemas/App.ts +0 -45
  121. package/src/schemas/Auth.ts +0 -59
  122. package/src/schemas/Field.ts +0 -169
  123. package/src/schemas/Run.ts +0 -40
  124. package/src/schemas/UserProfile.ts +0 -60
  125. package/src/sdk.test.ts +0 -212
  126. package/src/sdk.ts +0 -178
  127. package/src/types/domain.test.ts +0 -50
  128. package/src/types/domain.ts +0 -66
  129. package/src/types/errors.ts +0 -278
  130. package/src/types/events.ts +0 -43
  131. package/src/types/functions.ts +0 -28
  132. package/src/types/optional-zapier-sdk-cli-login.d.ts +0 -37
  133. package/src/types/plugin.ts +0 -125
  134. package/src/types/properties.ts +0 -80
  135. package/src/types/sdk.ts +0 -111
  136. package/src/types/telemetry-events.ts +0 -85
  137. package/src/utils/array-utils.test.ts +0 -131
  138. package/src/utils/array-utils.ts +0 -41
  139. package/src/utils/domain-utils.test.ts +0 -433
  140. package/src/utils/domain-utils.ts +0 -267
  141. package/src/utils/file-utils.test.ts +0 -73
  142. package/src/utils/file-utils.ts +0 -94
  143. package/src/utils/function-utils.test.ts +0 -141
  144. package/src/utils/function-utils.ts +0 -245
  145. package/src/utils/pagination-utils.test.ts +0 -620
  146. package/src/utils/pagination-utils.ts +0 -242
  147. package/src/utils/schema-utils.ts +0 -207
  148. package/src/utils/string-utils.test.ts +0 -45
  149. package/src/utils/string-utils.ts +0 -54
  150. package/src/utils/validation.test.ts +0 -51
  151. package/src/utils/validation.ts +0 -44
  152. package/tsconfig.build.json +0 -18
  153. package/tsconfig.json +0 -20
  154. package/tsconfig.tsbuildinfo +0 -1
  155. package/tsup.config.ts +0 -23
@@ -1,461 +0,0 @@
1
- import { readFile, writeFile, resolve } from "../../utils/file-utils";
2
- import type {
3
- GetVersionedImplementationId,
4
- Manifest,
5
- ManifestEntry,
6
- ManifestPluginOptionsSchema,
7
- ResolveAppKeys,
8
- } from "./schemas";
9
- import { ManifestSchema, DEFAULT_CONFIG_PATH } from "./schemas";
10
- import type { Plugin } from "../../types/plugin";
11
- import type { z } from "zod";
12
- import type { ApiClient } from "../../api";
13
- import type { ImplementationsMetaResponse } from "../../api/types";
14
- import {
15
- normalizeImplementationMetaToAppItem,
16
- splitVersionedKey,
17
- isSnakeCasedSlug,
18
- dashifySnakeCasedSlug,
19
- toAppLocator,
20
- type ResolvedAppLocator,
21
- isResolvedAppLocator,
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";
27
-
28
- export type ManifestPluginOptions = z.infer<typeof ManifestPluginOptionsSchema>;
29
-
30
- export interface UpdateManifestEntryOptions {
31
- appKey: string;
32
- entry: ManifestEntry;
33
- configPath?: string;
34
- skipWrite?: boolean;
35
- manifest?: Manifest;
36
- }
37
-
38
- export interface ManifestPluginProvides {
39
- context: {
40
- getVersionedImplementationId: GetVersionedImplementationId;
41
- resolveAppKeys: ResolveAppKeys;
42
- updateManifestEntry: (
43
- options: UpdateManifestEntryOptions,
44
- ) => Promise<[string, ManifestEntry, Manifest]>;
45
- };
46
- }
47
-
48
- /**
49
- * Parse manifest content from a string
50
- */
51
- function parseManifestContent(
52
- content: string,
53
- source: string,
54
- ): Manifest | null {
55
- try {
56
- const parsed = JSON.parse(content);
57
-
58
- if (parsed?.apps && typeof parsed?.apps === "object") {
59
- const result = ManifestSchema.safeParse(parsed);
60
- if (result.success) {
61
- return result.data;
62
- }
63
- console.warn(`⚠️ Invalid manifest format in ${source}: ${result.error}`);
64
- }
65
-
66
- return null;
67
- } catch (error) {
68
- console.warn(`⚠️ Failed to parse manifest from ${source}:`, error);
69
- return null;
70
- }
71
- }
72
-
73
- /**
74
- * Read manifest from a file path asynchronously
75
- * Supports local files (Node.js) and browser environments (fallback to global filesystem)
76
- */
77
- export async function readManifestFromFile(
78
- filePath: string,
79
- ): Promise<Manifest | null> {
80
- try {
81
- // Resolve relative paths relative to current working directory
82
- const resolvedPath = await resolve(filePath);
83
- const content = await readFile(resolvedPath);
84
- return parseManifestContent(content, resolvedPath);
85
- } catch {
86
- console.warn(`⚠️ Failed to read manifest from ${filePath}`);
87
- return null;
88
- }
89
- }
90
-
91
- /**
92
- * Write manifest to a file path asynchronously
93
- * Supports local files (Node.js) and browser environments (fallback to global filesystem)
94
- */
95
- async function writeManifestToFile(
96
- manifest: Manifest,
97
- filePath: string,
98
- ): Promise<void> {
99
- const resolvedPath = await resolve(filePath);
100
- await writeFile(resolvedPath, JSON.stringify(manifest, null, 2));
101
- }
102
-
103
- /**
104
- * Get the preferred key for storing an app in the manifest
105
- * Extracted from plugin to make it easier to test
106
- */
107
- export async function getPreferredManifestEntryKey({
108
- appKey,
109
- api,
110
- }: {
111
- appKey: string;
112
- api: ApiClient;
113
- }): Promise<string> {
114
- const locator = toAppLocator(appKey);
115
-
116
- // If we have a slug, prefer it
117
- if (locator.slug) {
118
- return locator.slug;
119
- }
120
-
121
- // If we have implementation name, look up the latest to get the slug
122
- if (locator.implementationName) {
123
- try {
124
- // API call to get app metadata by implementation name using selected_apis parameter
125
- const implementationsEnvelope: ImplementationsMetaResponse =
126
- await api.get(`/api/v4/implementations-meta/lookup/`, {
127
- searchParams: {
128
- selected_apis: locator.implementationName,
129
- },
130
- });
131
-
132
- if (
133
- implementationsEnvelope.results.length > 0 &&
134
- implementationsEnvelope.results[0].slug
135
- ) {
136
- return implementationsEnvelope.results[0].slug;
137
- }
138
- } catch {
139
- // Fall back to implementation name if lookup fails
140
- }
141
-
142
- return locator.implementationName;
143
- }
144
-
145
- // Fall back to original key if we can't determine anything better
146
- return locator.lookupAppKey;
147
- }
148
-
149
- async function listAppsForSlugsPage({
150
- slugs,
151
- cursor,
152
- api,
153
- }: {
154
- slugs: string[];
155
- cursor?: string;
156
- api: ApiClient;
157
- }) {
158
- const searchParams: Record<string, string> = {};
159
-
160
- if (slugs.length > 0) {
161
- searchParams.slugs = slugs.join(",");
162
- }
163
-
164
- if (cursor) {
165
- searchParams.offset = cursor;
166
- }
167
-
168
- const implementationsEnvelope: ImplementationsMetaResponse = await api.get(
169
- "/api/v4/implementations-meta/lookup/",
170
- {
171
- searchParams,
172
- },
173
- );
174
-
175
- return {
176
- data: implementationsEnvelope.results.map(
177
- normalizeImplementationMetaToAppItem,
178
- ),
179
- nextCursor: extractCursor(implementationsEnvelope),
180
- };
181
- }
182
-
183
- /**
184
- * Find a manifest entry by any app key (implementation name, slug, etc.).
185
- */
186
- export function findManifestEntry({
187
- appKey,
188
- manifest,
189
- }: {
190
- appKey: string;
191
- manifest: Manifest;
192
- }): [string, ManifestEntry] | null {
193
- const [appKeyWithoutVersion] = splitVersionedKey(appKey);
194
-
195
- // Direct match by key
196
- if (manifest.apps[appKeyWithoutVersion]) {
197
- return [appKeyWithoutVersion, manifest.apps[appKeyWithoutVersion]];
198
- }
199
-
200
- // Handle snake-cased slugs (convert to dashed)
201
- if (isSnakeCasedSlug(appKey)) {
202
- const slug = dashifySnakeCasedSlug(appKey);
203
- if (manifest.apps[slug]) {
204
- return [slug, manifest.apps[slug]];
205
- }
206
- }
207
-
208
- // Search by implementation name in manifest values
209
- for (const [key, entry] of Object.entries(manifest.apps)) {
210
- if (entry.implementationName === appKeyWithoutVersion) {
211
- return [key, entry];
212
- }
213
- }
214
-
215
- // No match found
216
- return null;
217
- }
218
-
219
- /**
220
- * Turn any app keys (slugs, implementation names, etc.) into app locators, which are objects that will be guaranteed to
221
- * have implementation names. Note that this function will not actually guarantee that implementation names are valid!
222
- * 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
223
- * assume it's an implementation name that will be used for an API call.
224
- */
225
- async function resolveAppKeys({
226
- appKeys,
227
- api,
228
- manifest,
229
- }: {
230
- appKeys: string[];
231
- api: ApiClient;
232
- manifest: Manifest;
233
- }): Promise<ResolvedAppLocator[]> {
234
- // Step 1: Convert all app keys to locators
235
- const locators = appKeys.map(toAppLocator);
236
-
237
- // Step 2: Map to resolved/unresolved via manifest
238
- const locatorsWithManifest = locators.map((locator) => {
239
- const manifestEntryResult = findManifestEntry({
240
- appKey: locator.lookupAppKey,
241
- manifest,
242
- });
243
-
244
- if (manifestEntryResult) {
245
- const [, manifestEntry] = manifestEntryResult;
246
- // Use manifest entry to resolve implementation name
247
- const resolvedVersion = locator.version || manifestEntry.version;
248
-
249
- const resolvedLocator: ResolvedAppLocator = {
250
- ...locator,
251
- implementationName: manifestEntry.implementationName,
252
- version: resolvedVersion,
253
- };
254
-
255
- return resolvedLocator;
256
- }
257
-
258
- // If these have an implementationName, they're already resolved.
259
- return locator;
260
- });
261
-
262
- // Step 3: Separate resolved from unresolved
263
- const unresolvedLocators = locatorsWithManifest.filter(
264
- (locator) => !isResolvedAppLocator(locator),
265
- );
266
-
267
- // Step 4: Resolve slugs via API
268
- const slugsToResolve = unresolvedLocators
269
- .map((locator) => locator.slug)
270
- .filter((slug): slug is string => !!slug)
271
- .filter((slug, index, array) => array.indexOf(slug) === index); // dedupe
272
-
273
- if (slugsToResolve.length === 0) {
274
- return locatorsWithManifest.filter(isResolvedAppLocator);
275
- }
276
-
277
- const iterator = paginate(listAppsForSlugsPage, {
278
- slugs: slugsToResolve,
279
- api,
280
- });
281
-
282
- const pages = await toArrayFromAsync(iterator);
283
- const apps = pages.flatMap((page) => page.data);
284
-
285
- const slugToAppData = new Map<string, AppItem>();
286
- for (const app of apps) {
287
- if (app.slug) {
288
- slugToAppData.set(app.slug, app);
289
- }
290
- }
291
-
292
- const slugResolvedLocators = locatorsWithManifest.map((locator) => {
293
- if (isResolvedAppLocator(locator)) {
294
- return locator;
295
- }
296
- if (locator.slug) {
297
- const appData = slugToAppData.get(locator.slug);
298
- if (appData) {
299
- // After resolving from API, check if we have a manifest entry for this implementation name
300
- const manifestEntryByImplementationName = findManifestEntry({
301
- appKey: appData.key, // appData.key is the implementation name
302
- manifest,
303
- });
304
-
305
- let version = locator.version;
306
- if (!version) {
307
- // Prefer manifest version if available, otherwise use API version
308
- version = manifestEntryByImplementationName
309
- ? manifestEntryByImplementationName[1].version || appData.version
310
- : appData.version;
311
- }
312
-
313
- return {
314
- ...locator,
315
- implementationName: appData.key,
316
- version,
317
- };
318
- }
319
- }
320
- return locator;
321
- });
322
-
323
- // Return all resolved locators.
324
- return slugResolvedLocators.filter(isResolvedAppLocator);
325
- }
326
-
327
- export { DEFAULT_CONFIG_PATH } from "./schemas";
328
- export type { ManifestEntry, Manifest } from "./schemas";
329
-
330
- export const manifestPlugin: Plugin<
331
- {}, // no SDK dependencies
332
- { api: ApiClient },
333
- ManifestPluginProvides
334
- > = (params) => {
335
- const { context } = params;
336
- const { api, options } = context;
337
- const { manifestPath = DEFAULT_CONFIG_PATH, manifest } = options || {};
338
-
339
- let resolvedManifest: Manifest | undefined | null;
340
-
341
- async function resolveManifest(): Promise<Manifest | null> {
342
- // If manifest is provided directly, use it
343
- if (manifest) {
344
- return manifest;
345
- }
346
- // If manifestPath is provided, load from file
347
- if (manifestPath) {
348
- return await readManifestFromFile(manifestPath);
349
- }
350
- return null;
351
- }
352
-
353
- const getResolvedManifest = async (): Promise<Manifest | null> => {
354
- if (typeof resolvedManifest === "undefined") {
355
- resolvedManifest = (await resolveManifest()) ?? null;
356
- }
357
-
358
- return resolvedManifest;
359
- };
360
-
361
- const getVersionedImplementationId = async (appKey: string) => {
362
- const resolvedApps = await resolveAppKeys({
363
- appKeys: [appKey],
364
- api,
365
- manifest: (await getResolvedManifest()) ?? { apps: {} },
366
- });
367
-
368
- const resolvedApp = resolvedApps[0];
369
- if (!resolvedApp) return null;
370
-
371
- return `${resolvedApp.implementationName}@${resolvedApp.version || "latest"}`;
372
- };
373
-
374
- const updateManifestEntry = async (
375
- options: UpdateManifestEntryOptions,
376
- ): Promise<[string, ManifestEntry, Manifest]> => {
377
- const {
378
- appKey,
379
- entry,
380
- configPath = DEFAULT_CONFIG_PATH,
381
- skipWrite = false,
382
- manifest: inputManifest,
383
- } = options;
384
-
385
- // Use provided manifest or read from file
386
- const manifest = inputManifest ||
387
- (await readManifestFromFile(configPath)) || { apps: {} };
388
-
389
- // Try to find existing entry by direct key first
390
- let existingEntry = findManifestEntry({
391
- appKey,
392
- manifest,
393
- });
394
-
395
- // If not found directly, try to resolve the app key and search by implementation name
396
- if (!existingEntry) {
397
- try {
398
- const resolvedApps = await resolveAppKeys({
399
- appKeys: [appKey],
400
- api,
401
- manifest,
402
- });
403
-
404
- if (resolvedApps.length > 0) {
405
- const resolvedImplementationName = resolvedApps[0].implementationName;
406
- // Try to find entry using the resolved implementation name
407
- existingEntry = findManifestEntry({
408
- appKey: resolvedImplementationName,
409
- manifest,
410
- });
411
- }
412
- } catch {
413
- // If resolution fails, continue with original logic
414
- }
415
- }
416
-
417
- let manifestKey: string;
418
-
419
- if (existingEntry) {
420
- // Use existing key to maintain consistency with types files
421
- manifestKey = existingEntry[0];
422
- } else {
423
- // Get preferred key for new entries
424
- manifestKey = await getPreferredManifestEntryKey({
425
- appKey,
426
- api,
427
- });
428
- }
429
-
430
- const updatedManifest = {
431
- ...manifest,
432
- apps: {
433
- ...manifest.apps,
434
- [manifestKey]: entry,
435
- },
436
- };
437
-
438
- // Conditionally write to file
439
- if (!skipWrite) {
440
- await writeManifestToFile(updatedManifest, configPath);
441
-
442
- // Clear the cached manifest so it gets reloaded with the new data
443
- resolvedManifest = undefined;
444
- }
445
-
446
- return [manifestKey, entry, updatedManifest];
447
- };
448
-
449
- return {
450
- context: {
451
- getVersionedImplementationId,
452
- resolveAppKeys: async ({ appKeys }: { appKeys: string[] }) =>
453
- resolveAppKeys({
454
- appKeys,
455
- api,
456
- manifest: (await getResolvedManifest()) ?? { apps: {} },
457
- }),
458
- updateManifestEntry,
459
- },
460
- };
461
- };
@@ -1,60 +0,0 @@
1
- import { z } from "zod";
2
- import type { ResolvedAppLocator } from "../../utils/domain-utils";
3
- import type { AppItem } from "../../types/domain";
4
-
5
- export const DEFAULT_CONFIG_PATH = ".zapierrc" as const;
6
-
7
- export type ManifestEntry = {
8
- implementationName: string;
9
- version?: string;
10
- };
11
-
12
- export type GetVersionedImplementationId = (
13
- appKey: string,
14
- ) => Promise<string | null>;
15
-
16
- export type GetImplementation = (appKey: string) => Promise<AppItem | null>;
17
-
18
- export type Manifest = {
19
- apps: Record<string, ManifestEntry>;
20
- };
21
-
22
- export type ResolveAppKeys = ({
23
- appKeys,
24
- }: {
25
- appKeys: string[];
26
- }) => Promise<ResolvedAppLocator[]>;
27
-
28
- /**
29
- * Manifest schema for version locking
30
- * Maps app keys to their locked version information
31
- */
32
- export const ManifestSchema = z
33
- .object({
34
- apps: z.record(
35
- z.string(),
36
- z.object({
37
- implementationName: z
38
- .string()
39
- .describe(
40
- "Base implementation name without version (e.g., 'SlackCLIAPI')",
41
- ),
42
- version: z.string().describe("Version string (e.g., '1.21.1')"),
43
- }),
44
- ),
45
- })
46
- .describe("Manifest mapping app keys to version information");
47
-
48
- export const ManifestPluginOptionsSchema = z.object({
49
- manifestPath: z.string().optional().describe("Path to manifest file"),
50
- manifest: z
51
- .record(
52
- z.string(),
53
- z.object({
54
- implementationName: z.string(),
55
- version: z.string().optional(),
56
- }),
57
- )
58
- .optional()
59
- .describe("Direct manifest object"),
60
- });
@@ -1,160 +0,0 @@
1
- import type { Plugin } from "../../types/plugin";
2
- import type { FunctionRegistryEntry } from "../../types/sdk";
3
-
4
- export interface RegisterPluginFunctionOptions {}
5
-
6
- export interface RegistryPluginProvides {
7
- getRegistry: (options?: { package?: string }) => {
8
- functions: FunctionRegistryEntry[];
9
- categories: {
10
- key: string;
11
- title: string;
12
- titlePlural: string;
13
- functions: string[];
14
- }[];
15
- };
16
- }
17
-
18
- // Registry plugin requires no context but collects SDK metadata
19
- export const registryPlugin: Plugin<
20
- {}, // accepts any SDK shape
21
- {}, // requires no context
22
- RegistryPluginProvides
23
- > = ({ sdk, context }) => {
24
- const metaKeys = Object.keys(context.meta || {});
25
-
26
- const categoryDefinitions: Record<
27
- string,
28
- { title: string; titlePlural?: string }
29
- > = {
30
- account: {
31
- title: "Account",
32
- },
33
- app: {
34
- title: "App",
35
- titlePlural: "Apps",
36
- },
37
- authentication: {
38
- title: "Authentication",
39
- },
40
- action: {
41
- title: "Action",
42
- },
43
- http: {
44
- title: "HTTP Request",
45
- },
46
- utility: {
47
- title: "Utility",
48
- titlePlural: "Utilities",
49
- },
50
- other: {
51
- title: "Other",
52
- },
53
- };
54
-
55
- const functions = metaKeys
56
- .filter((key) => {
57
- const property = sdk[key as keyof typeof sdk];
58
- if (typeof property === "function") {
59
- return true;
60
- }
61
- const [rootKey] = key.split(".");
62
- const rootProperty = sdk[rootKey as keyof typeof sdk];
63
- if (typeof rootProperty === "object" && rootProperty !== null) {
64
- return true;
65
- }
66
- return false;
67
- })
68
- .map((key) => {
69
- const meta = context.meta[key];
70
- return {
71
- name: key,
72
- type: meta.type,
73
- itemType: meta.itemType,
74
- returnType: meta.returnType,
75
- inputSchema: meta.inputSchema,
76
- inputParameters: meta.inputParameters,
77
- outputSchema: meta.outputSchema,
78
- categories: meta.categories || [],
79
- resolvers: meta.resolvers,
80
- packages: meta.packages,
81
- };
82
- })
83
- .sort((a, b) => a.name.localeCompare(b.name));
84
-
85
- const knownCategories = Object.keys(categoryDefinitions);
86
-
87
- // Cache the entire registry result for each package
88
- const registryCache = new Map<
89
- string,
90
- { functions: FunctionRegistryEntry[]; categories: any[] }
91
- >();
92
-
93
- function getRegistry(options?: { package?: string }) {
94
- const packageFilter = options?.package;
95
- const cacheKey = packageFilter || "__all__";
96
-
97
- // Return cached result if available
98
- if (registryCache.has(cacheKey)) {
99
- return registryCache.get(cacheKey)!;
100
- }
101
-
102
- // Filter functions by package if specified
103
- const filteredFunctions = packageFilter
104
- ? functions.filter(
105
- (f) =>
106
- // Include if packages is undefined (belongs to all packages) or includes the specified package
107
- !f.packages || f.packages.includes(packageFilter),
108
- )
109
- : functions;
110
-
111
- // Build categories with filtered functions
112
- const filteredCategories = knownCategories
113
- .sort((a, b) => {
114
- // Keep "other" category last
115
- if (a === "other") return 1;
116
- if (b === "other") return -1;
117
- // Alphabetize by title, not key
118
- const titleA = categoryDefinitions[a].title;
119
- const titleB = categoryDefinitions[b].title;
120
- return titleA.localeCompare(titleB);
121
- })
122
- .map((categoryKey) => {
123
- // Find the functions that are in this category and match the package filter
124
- const categoryFunctions = filteredFunctions
125
- .filter(
126
- (f) =>
127
- f.categories.includes(categoryKey) ||
128
- // If the category is "other" and the function is not in any other category, include it
129
- (categoryKey === "other" &&
130
- !f.categories.some((c) => knownCategories.includes(c))),
131
- )
132
- .map((f) => f.name)
133
- .sort(); // Alphabetize functions within each category
134
-
135
- const definition = categoryDefinitions[categoryKey];
136
- const title = definition.title;
137
- return {
138
- key: categoryKey,
139
- title,
140
- titlePlural: definition.titlePlural ?? `${title}s`,
141
- functions: categoryFunctions,
142
- };
143
- })
144
- .filter((category) => category.functions.length > 0); // Only include categories with functions
145
-
146
- const result = {
147
- functions: filteredFunctions,
148
- categories: filteredCategories,
149
- };
150
-
151
- // Cache the result
152
- registryCache.set(cacheKey, result);
153
-
154
- return result;
155
- }
156
-
157
- return {
158
- getRegistry,
159
- };
160
- };