@zapier/zapier-sdk 0.9.0 → 0.11.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 (187) hide show
  1. package/CHANGELOG.md +18 -0
  2. package/README.md +7 -7
  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 +968 -582
  15. package/dist/index.d.mts +2537 -2229
  16. package/dist/index.d.ts +2 -3
  17. package/dist/index.d.ts.map +1 -1
  18. package/dist/index.js +2 -3
  19. package/dist/index.mjs +966 -576
  20. package/dist/plugins/findFirstAuthentication/index.d.ts +1 -1
  21. package/dist/plugins/findFirstAuthentication/index.d.ts.map +1 -1
  22. package/dist/plugins/findFirstAuthentication/index.js +9 -1
  23. package/dist/plugins/findFirstAuthentication/index.test.js +3 -4
  24. package/dist/plugins/findFirstAuthentication/schemas.d.ts +5 -3
  25. package/dist/plugins/findFirstAuthentication/schemas.d.ts.map +1 -1
  26. package/dist/plugins/findUniqueAuthentication/index.d.ts.map +1 -1
  27. package/dist/plugins/findUniqueAuthentication/index.js +4 -0
  28. package/dist/plugins/findUniqueAuthentication/schemas.d.ts +5 -3
  29. package/dist/plugins/findUniqueAuthentication/schemas.d.ts.map +1 -1
  30. package/dist/plugins/getAction/index.d.ts.map +1 -1
  31. package/dist/plugins/getAction/index.js +10 -0
  32. package/dist/plugins/getAction/schemas.d.ts +5 -3
  33. package/dist/plugins/getAction/schemas.d.ts.map +1 -1
  34. package/dist/plugins/getApp/index.d.ts.map +1 -1
  35. package/dist/plugins/getApp/index.js +8 -0
  36. package/dist/plugins/getApp/index.test.js +2 -2
  37. package/dist/plugins/getApp/schemas.d.ts +3 -1
  38. package/dist/plugins/getApp/schemas.d.ts.map +1 -1
  39. package/dist/plugins/getApp/schemas.js +2 -4
  40. package/dist/plugins/getAuthentication/index.d.ts.map +1 -1
  41. package/dist/plugins/getAuthentication/index.js +8 -0
  42. package/dist/plugins/getProfile/index.d.ts.map +1 -1
  43. package/dist/plugins/getProfile/index.js +4 -0
  44. package/dist/plugins/getProfile/schemas.d.ts.map +1 -1
  45. package/dist/plugins/getProfile/schemas.js +4 -3
  46. package/dist/plugins/listActions/index.d.ts.map +1 -1
  47. package/dist/plugins/listActions/index.js +9 -0
  48. package/dist/plugins/listActions/schemas.d.ts +5 -3
  49. package/dist/plugins/listActions/schemas.d.ts.map +1 -1
  50. package/dist/plugins/listActions/schemas.js +2 -4
  51. package/dist/plugins/listApps/index.d.ts.map +1 -1
  52. package/dist/plugins/listApps/index.js +4 -0
  53. package/dist/plugins/listApps/index.test.js +1 -1
  54. package/dist/plugins/listApps/schemas.d.ts.map +1 -1
  55. package/dist/plugins/listApps/schemas.js +3 -9
  56. package/dist/plugins/listAuthentications/index.d.ts.map +1 -1
  57. package/dist/plugins/listAuthentications/index.js +8 -0
  58. package/dist/plugins/listAuthentications/schemas.d.ts +5 -3
  59. package/dist/plugins/listAuthentications/schemas.d.ts.map +1 -1
  60. package/dist/plugins/listInputFieldChoices/index.d.ts.map +1 -1
  61. package/dist/plugins/listInputFieldChoices/index.js +14 -2
  62. package/dist/plugins/listInputFieldChoices/schemas.d.ts +5 -3
  63. package/dist/plugins/listInputFieldChoices/schemas.d.ts.map +1 -1
  64. package/dist/plugins/listInputFieldChoices/schemas.js +10 -19
  65. package/dist/plugins/listInputFields/index.d.ts +4 -4
  66. package/dist/plugins/listInputFields/index.d.ts.map +1 -1
  67. package/dist/plugins/listInputFields/index.js +71 -5
  68. package/dist/plugins/listInputFields/index.test.js +5 -9
  69. package/dist/plugins/listInputFields/schemas.d.ts +8 -6
  70. package/dist/plugins/listInputFields/schemas.d.ts.map +1 -1
  71. package/dist/plugins/registry/index.d.ts.map +1 -1
  72. package/dist/plugins/registry/index.js +8 -2
  73. package/dist/plugins/request/index.d.ts.map +1 -1
  74. package/dist/plugins/request/index.js +1 -0
  75. package/dist/plugins/runAction/index.d.ts.map +1 -1
  76. package/dist/plugins/runAction/index.js +12 -0
  77. package/dist/plugins/runAction/schemas.d.ts +5 -3
  78. package/dist/plugins/runAction/schemas.d.ts.map +1 -1
  79. package/dist/resolvers/actionKey.d.ts +13 -7
  80. package/dist/resolvers/actionKey.d.ts.map +1 -1
  81. package/dist/resolvers/actionType.d.ts +8 -7
  82. package/dist/resolvers/actionType.d.ts.map +1 -1
  83. package/dist/resolvers/appKey.d.ts +2 -6
  84. package/dist/resolvers/appKey.d.ts.map +1 -1
  85. package/dist/resolvers/authenticationId.d.ts +7 -7
  86. package/dist/resolvers/authenticationId.d.ts.map +1 -1
  87. package/dist/resolvers/authenticationId.js +16 -7
  88. package/dist/resolvers/index.d.ts +3 -35
  89. package/dist/resolvers/index.d.ts.map +1 -1
  90. package/dist/resolvers/index.js +4 -87
  91. package/dist/resolvers/inputFieldKey.d.ts +11 -0
  92. package/dist/resolvers/inputFieldKey.d.ts.map +1 -0
  93. package/dist/resolvers/inputFieldKey.js +47 -0
  94. package/dist/resolvers/inputs.d.ts +13 -4
  95. package/dist/resolvers/inputs.d.ts.map +1 -1
  96. package/dist/resolvers/inputs.js +36 -0
  97. package/dist/schemas/Action.d.ts +8 -8
  98. package/dist/schemas/Action.d.ts.map +1 -1
  99. package/dist/schemas/Action.js +8 -3
  100. package/dist/schemas/App.d.ts +183 -11
  101. package/dist/schemas/App.d.ts.map +1 -1
  102. package/dist/schemas/App.js +7 -9
  103. package/dist/schemas/Auth.d.ts +12 -12
  104. package/dist/schemas/Auth.js +1 -1
  105. package/dist/schemas/Field.d.ts +112 -97
  106. package/dist/schemas/Field.d.ts.map +1 -1
  107. package/dist/schemas/Field.js +63 -52
  108. package/dist/schemas/Run.d.ts +3 -0
  109. package/dist/schemas/Run.d.ts.map +1 -0
  110. package/dist/schemas/Run.js +31 -0
  111. package/dist/schemas/UserProfile.d.ts +11 -11
  112. package/dist/schemas/UserProfile.d.ts.map +1 -1
  113. package/dist/schemas/UserProfile.js +21 -7
  114. package/dist/sdk.d.ts +11 -4
  115. package/dist/sdk.d.ts.map +1 -1
  116. package/dist/types/domain.d.ts +17 -1
  117. package/dist/types/domain.d.ts.map +1 -1
  118. package/dist/types/plugin.d.ts +5 -0
  119. package/dist/types/plugin.d.ts.map +1 -1
  120. package/dist/types/properties.d.ts +3 -1
  121. package/dist/types/properties.d.ts.map +1 -1
  122. package/dist/types/sdk.d.ts +5 -0
  123. package/dist/types/sdk.d.ts.map +1 -1
  124. package/dist/utils/domain-utils.d.ts +1 -16
  125. package/dist/utils/domain-utils.d.ts.map +1 -1
  126. package/dist/utils/domain-utils.js +7 -51
  127. package/dist/utils/schema-utils.d.ts +44 -21
  128. package/dist/utils/schema-utils.d.ts.map +1 -1
  129. package/dist/utils/schema-utils.js +17 -11
  130. package/dist/utils/string-utils.d.ts +12 -0
  131. package/dist/utils/string-utils.d.ts.map +1 -0
  132. package/dist/utils/string-utils.js +23 -0
  133. package/dist/utils/string-utils.test.d.ts +2 -0
  134. package/dist/utils/string-utils.test.d.ts.map +1 -0
  135. package/dist/utils/string-utils.test.js +36 -0
  136. package/package.json +1 -1
  137. package/src/api/client.ts +12 -0
  138. package/src/api/debug.test.ts +76 -0
  139. package/src/api/debug.ts +46 -2
  140. package/src/api/schemas.ts +51 -29
  141. package/src/index.ts +4 -5
  142. package/src/plugins/findFirstAuthentication/index.test.ts +8 -5
  143. package/src/plugins/findFirstAuthentication/index.ts +14 -2
  144. package/src/plugins/findUniqueAuthentication/index.ts +4 -0
  145. package/src/plugins/getAction/index.ts +14 -0
  146. package/src/plugins/getApp/index.test.ts +2 -2
  147. package/src/plugins/getApp/index.ts +8 -0
  148. package/src/plugins/getApp/schemas.ts +7 -12
  149. package/src/plugins/getAuthentication/index.ts +8 -0
  150. package/src/plugins/getProfile/index.ts +4 -0
  151. package/src/plugins/getProfile/schemas.ts +4 -6
  152. package/src/plugins/listActions/index.ts +9 -0
  153. package/src/plugins/listActions/schemas.ts +20 -25
  154. package/src/plugins/listApps/index.test.ts +1 -1
  155. package/src/plugins/listApps/index.ts +4 -0
  156. package/src/plugins/listApps/schemas.ts +17 -26
  157. package/src/plugins/listAuthentications/index.ts +8 -0
  158. package/src/plugins/listInputFieldChoices/index.ts +21 -1
  159. package/src/plugins/listInputFieldChoices/schemas.ts +61 -76
  160. package/src/plugins/listInputFields/index.test.ts +5 -9
  161. package/src/plugins/listInputFields/index.ts +89 -11
  162. package/src/plugins/listInputFields/schemas.ts +6 -3
  163. package/src/plugins/registry/index.ts +8 -2
  164. package/src/plugins/request/index.ts +1 -0
  165. package/src/plugins/runAction/index.ts +18 -0
  166. package/src/resolvers/actionKey.ts +15 -13
  167. package/src/resolvers/actionType.ts +10 -12
  168. package/src/resolvers/appKey.ts +2 -6
  169. package/src/resolvers/authenticationId.ts +25 -19
  170. package/src/resolvers/index.ts +7 -113
  171. package/src/resolvers/inputFieldKey.ts +70 -0
  172. package/src/resolvers/inputs.ts +51 -7
  173. package/src/schemas/Action.ts +8 -3
  174. package/src/schemas/App.ts +7 -9
  175. package/src/schemas/Auth.ts +1 -1
  176. package/src/schemas/Field.ts +97 -60
  177. package/src/schemas/Run.ts +40 -0
  178. package/src/schemas/UserProfile.ts +24 -7
  179. package/src/sdk.ts +17 -7
  180. package/src/types/domain.ts +24 -1
  181. package/src/types/plugin.ts +5 -0
  182. package/src/types/sdk.ts +5 -0
  183. package/src/utils/domain-utils.ts +9 -67
  184. package/src/utils/schema-utils.ts +96 -44
  185. package/src/utils/string-utils.test.ts +45 -0
  186. package/src/utils/string-utils.ts +26 -0
  187. package/tsconfig.tsbuildinfo +1 -1
@@ -0,0 +1,40 @@
1
+ import { z } from "zod";
2
+ import { withFormatter, type FormattedItem } from "../utils/schema-utils";
3
+
4
+ // Type guard to safely access object properties
5
+ function getStringProperty(obj: unknown, key: string): string | undefined {
6
+ if (typeof obj === "object" && obj !== null && key in obj) {
7
+ const value = (obj as Record<string, unknown>)[key];
8
+ return typeof value === "string" ? value : undefined;
9
+ }
10
+ return undefined;
11
+ }
12
+
13
+ // Formatter for action results - handles any data structure
14
+ function formatActionResult(item: unknown): FormattedItem {
15
+ // Try to extract common fields for structured display
16
+ const obj = typeof item === "object" && item !== null ? item : {};
17
+
18
+ // Try common title fields
19
+ const title =
20
+ getStringProperty(obj, "title") ||
21
+ getStringProperty(obj, "name") ||
22
+ getStringProperty(obj, "label") ||
23
+ getStringProperty(obj, "subject") ||
24
+ "Action Result";
25
+
26
+ return {
27
+ title,
28
+ id: getStringProperty(obj, "id"),
29
+ key: getStringProperty(obj, "key"),
30
+ description: getStringProperty(obj, "description"),
31
+ data: item, // Let formatJsonOutput handle the JSON rendering
32
+ details: [], // Not used when data is provided
33
+ };
34
+ }
35
+
36
+ // Flexible schema for action results - can be any object
37
+ export const ActionResultItemSchema = withFormatter(
38
+ z.unknown().describe("Action execution result"),
39
+ { format: formatActionResult },
40
+ );
@@ -15,21 +15,38 @@ export const UserProfileItemSchema = withFormatter(
15
15
  {
16
16
  format: (item) => {
17
17
  const details = [];
18
- details.push({ text: item.email, style: "dim" as const });
19
- if (item.timezone) {
18
+ if (
19
+ item == null ||
20
+ typeof item !== "object" ||
21
+ !("full_name" in item) ||
22
+ !("username" in item)
23
+ ) {
24
+ return {
25
+ title: "User Profile",
26
+ subtitle: "Malformatted result item",
27
+ details: [],
28
+ };
29
+ }
30
+
31
+ if ("email" in item) {
32
+ details.push({ text: item.email, style: "dim" as const });
33
+ }
34
+ if ("timezone" in item && item.timezone) {
20
35
  details.push({
21
36
  text: `Timezone: ${item.timezone}`,
22
37
  style: "accent" as const,
23
38
  });
24
39
  }
25
- details.push({
26
- text: `Member since: ${item.since_signup}`,
27
- style: "dim" as const,
28
- });
40
+ if ("since_signup" in item && item.since_signup) {
41
+ details.push({
42
+ text: `Member since: ${item.since_signup}`,
43
+ style: "dim" as const,
44
+ });
45
+ }
29
46
 
30
47
  return {
31
48
  title: item.full_name,
32
- subtitle: `@${item.username}`,
49
+ id: item.id.toString(),
33
50
  details,
34
51
  };
35
52
  },
package/src/sdk.ts CHANGED
@@ -9,6 +9,7 @@ import type {
9
9
  Sdk,
10
10
  Plugin,
11
11
  ExtractContextProperties,
12
+ ExtractSdkProperties,
12
13
  PluginProvides,
13
14
  PluginMeta,
14
15
  } from "./types/plugin";
@@ -41,12 +42,14 @@ export interface ZapierSdkOptions extends BaseSdkOptions {}
41
42
  // Create SDK that supports flat plugins - returns an SDK, not a builder
42
43
  export function createSdk<
43
44
  TCurrentSdk = {},
44
- TCurrentContext = { meta: Record<string, PluginMeta> },
45
+ TCurrentContext extends { meta: Record<string, PluginMeta> } = {
46
+ meta: Record<string, PluginMeta>;
47
+ },
45
48
  >(
46
49
  options: ZapierSdkOptions = {},
47
50
  initialSdk: TCurrentSdk = {} as TCurrentSdk,
48
51
  initialContext: TCurrentContext = { meta: {} } as TCurrentContext,
49
- ): Sdk<TCurrentSdk, TCurrentContext> {
52
+ ) {
50
53
  return {
51
54
  ...initialSdk,
52
55
  getContext: () => initialContext,
@@ -56,8 +59,11 @@ export function createSdk<
56
59
  TRequiresContext,
57
60
  TProvides
58
61
  >,
59
- addPluginOptions: any = {},
60
- ) {
62
+ addPluginOptions: Record<string, unknown> = {},
63
+ ): Sdk<
64
+ TCurrentSdk & ExtractSdkProperties<TProvides>,
65
+ TCurrentContext & NonNullable<ExtractContextProperties<TProvides>>
66
+ > {
61
67
  // Create SDK with getContext method for plugins to use
62
68
  const currentSdkWithContext = {
63
69
  ...initialSdk,
@@ -71,7 +77,7 @@ export function createSdk<
71
77
  ...initialContext,
72
78
  // Add the options that createSdk was called with to context
73
79
  options,
74
- },
80
+ } as TCurrentContext & { options: ZapierSdkOptions } & TRequiresContext,
75
81
  ...addPluginOptions,
76
82
  });
77
83
 
@@ -86,7 +92,8 @@ export function createSdk<
86
92
  let newContext = {
87
93
  ...initialContext,
88
94
  ...addPluginOptions,
89
- meta: (initialContext as any).meta || {},
95
+ meta:
96
+ (initialContext as { meta?: Record<string, PluginMeta> }).meta || {},
90
97
  } as TCurrentContext & NonNullable<ExtractContextProperties<TProvides>>;
91
98
 
92
99
  if (pluginContext) {
@@ -112,7 +119,10 @@ export function createSdk<
112
119
  }
113
120
 
114
121
  // Recursively create new SDK with updated properties
115
- return createSdk(options, newSdk, newContext) as any;
122
+ return createSdk(options, newSdk, newContext) as Sdk<
123
+ TCurrentSdk & ExtractSdkProperties<TProvides>,
124
+ TCurrentContext & NonNullable<ExtractContextProperties<TProvides>>
125
+ >;
116
126
  },
117
127
  };
118
128
  }
@@ -9,8 +9,13 @@ import type { z } from "zod";
9
9
  import type { AppItemSchema } from "../schemas/App";
10
10
  import type { AuthenticationItemSchema } from "../schemas/Auth";
11
11
  import type { ActionItemSchema } from "../schemas/Action";
12
- import type { InputFieldItemSchema } from "../schemas/Field";
12
+ import type {
13
+ InputFieldItemSchema,
14
+ InfoFieldItemSchema,
15
+ RootFieldItemSchema,
16
+ } from "../schemas/Field";
13
17
  import type { UserProfileItemSchema } from "../schemas/UserProfile";
18
+ import type { FieldsetItem } from "../schemas/Field";
14
19
 
15
20
  /**
16
21
  * Represents an app item returned by getApp and listApps functions
@@ -36,6 +41,24 @@ export type ActionItem = z.infer<typeof ActionItemSchema>;
36
41
  */
37
42
  export type InputFieldItem = z.infer<typeof InputFieldItemSchema>;
38
43
 
44
+ /**
45
+ * Represents an info field item (help text/copy) returned by listInputFields functions
46
+ * Inferred from InfoFieldItemSchema
47
+ */
48
+ export type InfoFieldItem = z.infer<typeof InfoFieldItemSchema>;
49
+
50
+ /**
51
+ * Represents a fieldset (group of fields) returned by listInputFields functions
52
+ * This is defined as an interface rather than inferred due to recursive nature
53
+ */
54
+ export type { FieldsetItem };
55
+
56
+ /**
57
+ * Represents a root field item (any field/fieldset type) returned by listInputFields
58
+ * Inferred from RootFieldItemSchema - use as RootFieldItem[]
59
+ */
60
+ export type RootFieldItem = z.infer<typeof RootFieldItemSchema>;
61
+
39
62
  /**
40
63
  * Represents a user profile item returned by getProfile function
41
64
  * Inferred from UserProfileItemSchema which extends the base UserProfile API schema
@@ -22,7 +22,12 @@ export interface PluginProvides extends Record<string, any> {
22
22
 
23
23
  export interface PluginMeta {
24
24
  categories: string[];
25
+ type?: "list" | "item";
26
+ itemType?: string;
27
+ returnType?: string;
25
28
  inputSchema: z.ZodSchema;
29
+ outputSchema?: z.ZodSchema;
30
+ resolvers?: Record<string, any>;
26
31
  [key: string]: any;
27
32
  }
28
33
 
package/src/types/sdk.ts CHANGED
@@ -57,8 +57,13 @@ import type { ManifestPluginProvides } from "../plugins/manifest";
57
57
  // Registry entry interface with proper types
58
58
  export interface FunctionRegistryEntry {
59
59
  name: string;
60
+ type?: "list" | "item";
61
+ itemType?: string;
62
+ returnType?: string;
60
63
  inputSchema: z.ZodSchema;
64
+ outputSchema?: z.ZodSchema;
61
65
  categories: string[];
66
+ resolvers?: Record<string, any>;
62
67
  }
63
68
 
64
69
  // Compose SDK functions from individual function interfaces
@@ -2,14 +2,7 @@
2
2
  * Domain utility functions for working with app identifiers and data normalization
3
3
  */
4
4
 
5
- import type {
6
- Action,
7
- App,
8
- Authentication,
9
- Implementation,
10
- ImplementationMeta,
11
- Service,
12
- } from "../api/types";
5
+ import type { Action, Authentication, ImplementationMeta } from "../api/types";
13
6
  import type { ActionItem, AppItem, AuthenticationItem } from "../types/domain";
14
7
 
15
8
  /**
@@ -34,48 +27,6 @@ export function splitVersionedKey(
34
27
  return [versionedKey, undefined];
35
28
  }
36
29
 
37
- /**
38
- * Converts an API App to an AppItem with normalized field names
39
- *
40
- * @param app - Raw App from API
41
- * @returns Normalized AppItem
42
- */
43
- export function normalizeAppItem(app: App): AppItem {
44
- // Extract API name and version from current_implementation_id
45
- const [apiName, appVersion] = app.current_implementation_id
46
- ? splitVersionedKey(app.current_implementation_id)
47
- : [app.current_implementation_id || "", undefined];
48
-
49
- return {
50
- title: app.name,
51
- key: app.slug || apiName,
52
- current_implementation_id: app.current_implementation_id || "",
53
- version: appVersion, // Extract version separately
54
- };
55
- }
56
-
57
- /**
58
- * Converts an Implementation to an AppItem with normalized field names
59
- *
60
- * @param implementation - Raw Implementation from API
61
- * @returns Normalized AppItem
62
- */
63
- export function normalizeImplementationToAppItem(
64
- implementation: Implementation,
65
- ): AppItem {
66
- // Extract API name and version from selected_api
67
- const [selectedApi, appVersion] = implementation.selected_api
68
- ? splitVersionedKey(implementation.selected_api)
69
- : [implementation.selected_api || "", undefined];
70
-
71
- return {
72
- title: implementation.name || selectedApi,
73
- key: selectedApi,
74
- current_implementation_id: implementation.selected_api || "",
75
- version: appVersion, // Extract version separately
76
- };
77
- }
78
-
79
30
  /**
80
31
  * Converts a lightweight ImplementationMeta to a slimmed AppItem
81
32
  *
@@ -88,26 +39,17 @@ export function normalizeImplementationMetaToAppItem(
88
39
  // Extract API name and version from the implementation ID
89
40
  const [selectedApi, appVersion] = splitVersionedKey(implementationMeta.id);
90
41
 
91
- return {
92
- title: implementationMeta.name,
93
- key: selectedApi,
94
- current_implementation_id: implementationMeta.id, // Keep the full versioned ID
95
- version: appVersion, // Extract version separately
96
- slug: implementationMeta.slug,
97
- };
98
- }
99
-
100
- export function normalizeServiceToAppItem(service: Service): AppItem {
101
- const [selectedApi, appVersion] = service.current_implementation_id
102
- ? splitVersionedKey(service.current_implementation_id)
103
- : ["", undefined];
42
+ // Destructure to exclude id and name before spreading
43
+ const { id, name, ...restOfImplementationMeta } = implementationMeta;
104
44
 
105
45
  return {
106
- title: service.name,
46
+ // Pass through all ImplementationMeta fields except id and name
47
+ ...restOfImplementationMeta,
48
+ // Transform key fields
49
+ title: name,
107
50
  key: selectedApi,
108
- current_implementation_id: service.current_implementation_id,
109
- version: appVersion,
110
- description: service.description,
51
+ implementation_id: id, // Keep the full versioned ID
52
+ version: appVersion, // Extract version separately
111
53
  };
112
54
  }
113
55
 
@@ -1,4 +1,6 @@
1
1
  import { z } from "zod";
2
+ import type { ZapierSdk } from "../types/sdk";
3
+ import type { InputFieldItem } from "../schemas/Field";
2
4
 
3
5
  // ============================================================================
4
6
  // Format Metadata Types
@@ -6,92 +8,121 @@ import { z } from "zod";
6
8
 
7
9
  export interface FormattedItem {
8
10
  title: string;
9
- subtitle?: string;
11
+ id?: string;
12
+ key?: string;
13
+ description?: string;
14
+ data?: unknown; // Optional: if provided, CLI will use formatJsonOutput instead of details
10
15
  details: Array<{
11
16
  text: string;
12
17
  style: "normal" | "dim" | "accent" | "warning" | "success";
13
18
  }>;
14
19
  }
15
20
 
16
- export interface FormatMetadata {
17
- format: (item: any) => FormattedItem;
21
+ export interface FormatMetadata<TItem = unknown> {
22
+ format: (item: TItem) => FormattedItem;
18
23
  }
19
24
 
20
25
  // Helper function to add format metadata to schemas
21
26
  export function withFormatter<T extends z.ZodType>(
22
27
  schema: T,
23
- formatMeta: FormatMetadata,
28
+ formatMeta: FormatMetadata<z.infer<T>>,
24
29
  ): T {
25
30
  // Store format metadata on the schema definition
26
- (schema._def as any).formatMeta = formatMeta;
27
- return schema;
31
+ Object.assign(schema._def, {
32
+ formatMeta: formatMeta,
33
+ });
34
+ return schema as T & {
35
+ _def: T["_def"] & { formatMeta: FormatMetadata<z.infer<T>> };
36
+ };
28
37
  }
29
38
 
30
- // Helper function to get format metadata from a schema
31
- export function getFormatMetadata(
32
- schema: z.ZodType,
33
- ): FormatMetadata | undefined {
34
- return (schema._def as any).formatMeta;
39
+ // Helper function to get output schema from an input schema
40
+ export function getOutputSchema(inputSchema: z.ZodType): z.ZodType | undefined {
41
+ return (inputSchema._def as { outputSchema?: z.ZodType }).outputSchema;
35
42
  }
36
43
 
37
44
  // Helper function to link input schemas to output schemas
38
45
  export function withOutputSchema<T extends z.ZodType>(
39
46
  inputSchema: T,
40
47
  outputSchema: z.ZodType,
41
- ): T {
48
+ ): T & {
49
+ _def: T["_def"] & { outputSchema: z.ZodType };
50
+ } {
42
51
  // Store output schema reference on the input schema
43
- (inputSchema._def as any).outputSchema = outputSchema;
44
- return inputSchema;
45
- }
46
-
47
- // Helper function to get output schema from an input schema
48
- export function getOutputSchema(inputSchema: z.ZodType): z.ZodType | undefined {
49
- return (inputSchema._def as any).outputSchema;
52
+ Object.assign(inputSchema._def, {
53
+ outputSchema,
54
+ });
55
+ return inputSchema as T & {
56
+ _def: T["_def"] & { outputSchema: z.ZodType };
57
+ };
50
58
  }
51
59
 
52
60
  // ============================================================================
53
61
  // Resolution Metadata Types
54
62
  // ============================================================================
55
63
 
56
- export interface StaticResolver {
64
+ export interface PromptConfig {
65
+ type: "list";
66
+ name: string;
67
+ message: string;
68
+ choices: Array<{
69
+ name: string;
70
+ value: unknown;
71
+ }>;
72
+ }
73
+
74
+ export interface Resolver {
75
+ type: string;
76
+ depends?: readonly string[] | string[]; // Parameters this resolver depends on
77
+ }
78
+
79
+ export interface StaticResolver extends Resolver {
57
80
  type: "static";
58
81
  inputType?: "text" | "password" | "email";
59
82
  placeholder?: string;
60
83
  }
61
84
 
62
- export interface DynamicResolver {
85
+ export interface DynamicResolver<
86
+ TItem = unknown,
87
+ TParams = Record<string, unknown>,
88
+ > extends Resolver {
63
89
  type: "dynamic";
64
- fetch: (sdk: any, resolvedParams: any) => Promise<any[]>; // Function to fetch data using SDK
65
- prompt: (items: any[], params: any) => any;
66
- depends?: string[]; // Parameters this resolver depends on
90
+ fetch: (sdk: ZapierSdk, resolvedParams: TParams) => Promise<TItem[]>; // Function to fetch data using SDK
91
+ prompt: (items: TItem[], params: TParams) => PromptConfig;
67
92
  }
68
93
 
69
- export interface FieldsResolver {
94
+ export interface FieldsResolver<TParams = Record<string, unknown>>
95
+ extends Resolver {
70
96
  type: "fields";
71
- fetch: (sdk: any, resolvedParams: any) => Promise<any[]>; // Function to fetch fields using SDK
72
- depends?: string[]; // Parameters this resolver depends on
97
+ fetch: (sdk: ZapierSdk, resolvedParams: TParams) => Promise<InputFieldItem[]>; // Function to fetch fields using SDK
73
98
  }
74
99
 
75
- export type ResolverMetadata =
76
- | StaticResolver
77
- | DynamicResolver
78
- | FieldsResolver;
100
+ export type ResolverMetadata<
101
+ TItem = unknown,
102
+ TParams = Record<string, unknown>,
103
+ > = StaticResolver | DynamicResolver<TItem, TParams> | FieldsResolver<TParams>;
79
104
 
80
105
  // Wrapper interface for resolver metadata to allow future extensibility
81
- export interface ResolverConfig {
82
- resolver: ResolverMetadata;
106
+ export interface ResolverConfig<
107
+ TItem = unknown,
108
+ TParams = Record<string, unknown>,
109
+ > {
110
+ resolver: ResolverMetadata<TItem, TParams>;
83
111
  // Future metadata types can be added here:
84
112
  // validation?: ValidationMetadata;
85
113
  // display?: DisplayMetadata;
86
114
  }
87
115
 
88
116
  // Helper function to add resolver metadata to schemas
89
- export function withResolver<T extends z.ZodType>(
90
- schema: T,
91
- config: ResolverConfig,
92
- ): T {
117
+ export function withResolver<
118
+ T extends z.ZodType,
119
+ TItem = unknown,
120
+ TParams = Record<string, unknown>,
121
+ >(schema: T, config: ResolverConfig<TItem, TParams>): T {
93
122
  // Store resolver metadata on the schema definition
94
- (schema._def as any).resolverMeta = config;
123
+ (
124
+ schema._def as { resolverMeta?: ResolverConfig<TItem, TParams> }
125
+ ).resolverMeta = config;
95
126
  return schema;
96
127
  }
97
128
 
@@ -104,7 +135,7 @@ export function getSchemaDescription(schema: z.ZodSchema): string | undefined {
104
135
  }
105
136
 
106
137
  export function getFieldDescriptions(
107
- schema: z.ZodObject<any>,
138
+ schema: z.ZodObject<z.ZodRawShape>,
108
139
  ): Record<string, string> {
109
140
  const descriptions: Record<string, string> = {};
110
141
  const shape = schema.shape;
@@ -123,20 +154,41 @@ export function getFieldDescriptions(
123
154
  // ============================================================================
124
155
 
125
156
  export interface PositionalMetadata {
126
- positional: true;
157
+ positionalMeta: {
158
+ positional: true;
159
+ };
127
160
  }
128
161
 
129
162
  // Helper function to mark a parameter as positional for CLI
130
- export function withPositional<T extends z.ZodType>(schema: T): T {
163
+ export function withPositional<T extends z.ZodType>(
164
+ schema: T,
165
+ ): T & {
166
+ _def: T["_def"] & PositionalMetadata;
167
+ } {
131
168
  // Store positional metadata on the schema definition
132
- (schema._def as any).positionalMeta = { positional: true };
133
- return schema;
169
+ Object.assign(schema._def, {
170
+ positionalMeta: { positional: true },
171
+ } satisfies PositionalMetadata);
172
+ return schema as T & {
173
+ _def: T["_def"] & PositionalMetadata;
174
+ };
175
+ }
176
+
177
+ function schemaHasPositionalMeta<T extends z.ZodType>(
178
+ schema: T,
179
+ ): schema is T & {
180
+ _def: T["_def"] & PositionalMetadata;
181
+ } {
182
+ return "positionalMeta" in schema._def;
134
183
  }
135
184
 
136
185
  // Helper function to check if a parameter should be positional
137
186
  export function isPositional(schema: z.ZodType): boolean {
138
187
  // Check the current schema first
139
- if ((schema._def as any).positionalMeta?.positional) {
188
+ if (
189
+ schemaHasPositionalMeta(schema) &&
190
+ schema._def.positionalMeta?.positional
191
+ ) {
140
192
  return true;
141
193
  }
142
194
 
@@ -0,0 +1,45 @@
1
+ import { describe, it, expect } from "vitest";
2
+ import { toTitleCase } from "./string-utils";
3
+
4
+ describe("toTitleCase", () => {
5
+ it("converts snake_case to title case", () => {
6
+ expect(toTitleCase("first_name")).toBe("First Name");
7
+ expect(toTitleCase("sender_settings")).toBe("Sender Settings");
8
+ expect(toTitleCase("api_key_config")).toBe("Api Key Config");
9
+ });
10
+
11
+ it("converts camelCase to title case", () => {
12
+ expect(toTitleCase("firstName")).toBe("First Name");
13
+ expect(toTitleCase("senderSettings")).toBe("Sender Settings");
14
+ expect(toTitleCase("apiKeyConfig")).toBe("Api Key Config");
15
+ });
16
+
17
+ it("converts kebab-case to title case", () => {
18
+ expect(toTitleCase("first-name")).toBe("First Name");
19
+ expect(toTitleCase("sender-settings")).toBe("Sender Settings");
20
+ expect(toTitleCase("api-key-config")).toBe("Api Key Config");
21
+ });
22
+
23
+ it("handles mixed formats", () => {
24
+ expect(toTitleCase("first_name-value")).toBe("First Name Value");
25
+ expect(toTitleCase("sender_settings-config")).toBe(
26
+ "Sender Settings Config",
27
+ );
28
+ });
29
+
30
+ it("handles single words", () => {
31
+ expect(toTitleCase("name")).toBe("Name");
32
+ expect(toTitleCase("settings")).toBe("Settings");
33
+ });
34
+
35
+ it("handles multiple spaces and trims", () => {
36
+ expect(toTitleCase(" first name ")).toBe("First Name");
37
+ expect(toTitleCase("sender__settings")).toBe("Sender Settings");
38
+ });
39
+
40
+ it("handles empty and edge cases", () => {
41
+ expect(toTitleCase("")).toBe("");
42
+ expect(toTitleCase("a")).toBe("A");
43
+ expect(toTitleCase("_")).toBe("");
44
+ });
45
+ });
@@ -0,0 +1,26 @@
1
+ /**
2
+ * String utility functions for the Zapier SDK
3
+ */
4
+
5
+ /**
6
+ * Converts a string to title case, handling various input formats:
7
+ * - camelCase: "firstName" → "First Name"
8
+ * - snake_case: "first_name" → "First Name"
9
+ * - kebab-case: "first-name" → "First Name"
10
+ * - mixed formats: "first_name-value" → "First Name Value"
11
+ */
12
+ export function toTitleCase(input: string): string {
13
+ return (
14
+ input
15
+ // insert a space before capital letters (handles camelCase)
16
+ .replace(/([a-z0-9])([A-Z])/g, "$1 $2")
17
+ // replace delimiters (underscore, dash, multiple spaces) with single space
18
+ .replace(/[_\-]+/g, " ")
19
+ .replace(/\s+/g, " ")
20
+ .trim()
21
+ // split and capitalize each word
22
+ .split(" ")
23
+ .map((word) => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase())
24
+ .join(" ")
25
+ );
26
+ }