@superblocksteam/sdk-api 2.0.101-next.0 → 2.0.101-next.1

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 (215) hide show
  1. package/README.md +47 -41
  2. package/dist/api/definition.d.ts +1 -1
  3. package/dist/api/definition.d.ts.map +1 -1
  4. package/dist/api/definition.js.map +1 -1
  5. package/dist/api/definition.test.js.map +1 -1
  6. package/dist/api/streaming.d.ts +1 -1
  7. package/dist/api/streaming.d.ts.map +1 -1
  8. package/dist/api/streaming.js.map +1 -1
  9. package/dist/api/streaming.test.js +2 -2
  10. package/dist/api/streaming.test.js.map +1 -1
  11. package/dist/integrations/athena/client.d.ts +1 -1
  12. package/dist/integrations/athena/client.d.ts.map +1 -1
  13. package/dist/integrations/athena/client.js.map +1 -1
  14. package/dist/integrations/athena/types.d.ts.map +1 -1
  15. package/dist/integrations/base/graphql-integration-client.d.ts +2 -2
  16. package/dist/integrations/base/graphql-integration-client.d.ts.map +1 -1
  17. package/dist/integrations/base/graphql-integration-client.js.map +1 -1
  18. package/dist/integrations/base/rest-api-integration-client.d.ts +3 -3
  19. package/dist/integrations/base/rest-api-integration-client.d.ts.map +1 -1
  20. package/dist/integrations/base/rest-api-integration-client.js.map +1 -1
  21. package/dist/integrations/base/types.d.ts.map +1 -1
  22. package/dist/integrations/bigquery/client.d.ts +1 -1
  23. package/dist/integrations/bigquery/client.d.ts.map +1 -1
  24. package/dist/integrations/bigquery/client.js.map +1 -1
  25. package/dist/integrations/bigquery/types.d.ts.map +1 -1
  26. package/dist/integrations/cockroachdb/client.d.ts +1 -1
  27. package/dist/integrations/cockroachdb/client.d.ts.map +1 -1
  28. package/dist/integrations/cockroachdb/client.js.map +1 -1
  29. package/dist/integrations/cockroachdb/types.d.ts.map +1 -1
  30. package/dist/integrations/cosmosdb/client.d.ts +1 -1
  31. package/dist/integrations/cosmosdb/client.d.ts.map +1 -1
  32. package/dist/integrations/cosmosdb/client.js.map +1 -1
  33. package/dist/integrations/cosmosdb/client.test.js.map +1 -1
  34. package/dist/integrations/cosmosdb/types.d.ts.map +1 -1
  35. package/dist/integrations/couchbase/client.d.ts +1 -1
  36. package/dist/integrations/couchbase/client.d.ts.map +1 -1
  37. package/dist/integrations/couchbase/client.js.map +1 -1
  38. package/dist/integrations/couchbase/types.d.ts.map +1 -1
  39. package/dist/integrations/databricks/client.d.ts +1 -1
  40. package/dist/integrations/databricks/client.d.ts.map +1 -1
  41. package/dist/integrations/databricks/client.js.map +1 -1
  42. package/dist/integrations/databricks/types.d.ts.map +1 -1
  43. package/dist/integrations/declarations.d.ts +36 -36
  44. package/dist/integrations/declarations.d.ts.map +1 -1
  45. package/dist/integrations/declarations.test.js.map +1 -1
  46. package/dist/integrations/dynamodb/client.d.ts +1 -1
  47. package/dist/integrations/dynamodb/client.d.ts.map +1 -1
  48. package/dist/integrations/dynamodb/client.js.map +1 -1
  49. package/dist/integrations/dynamodb/types.d.ts.map +1 -1
  50. package/dist/integrations/gcs/client.d.ts +1 -1
  51. package/dist/integrations/gcs/client.d.ts.map +1 -1
  52. package/dist/integrations/gcs/client.js.map +1 -1
  53. package/dist/integrations/gcs/types.d.ts.map +1 -1
  54. package/dist/integrations/graphql/types.d.ts +1 -1
  55. package/dist/integrations/graphql/types.d.ts.map +1 -1
  56. package/dist/integrations/gsheets/client.d.ts +1 -1
  57. package/dist/integrations/gsheets/client.d.ts.map +1 -1
  58. package/dist/integrations/gsheets/client.js.map +1 -1
  59. package/dist/integrations/gsheets/types.d.ts.map +1 -1
  60. package/dist/integrations/kafka/client.d.ts +1 -1
  61. package/dist/integrations/kafka/client.d.ts.map +1 -1
  62. package/dist/integrations/kafka/client.js.map +1 -1
  63. package/dist/integrations/kafka/types.d.ts.map +1 -1
  64. package/dist/integrations/kinesis/client.d.ts +1 -1
  65. package/dist/integrations/kinesis/client.d.ts.map +1 -1
  66. package/dist/integrations/kinesis/client.js.map +1 -1
  67. package/dist/integrations/lakebase/client.d.ts +1 -1
  68. package/dist/integrations/lakebase/client.d.ts.map +1 -1
  69. package/dist/integrations/lakebase/client.js.map +1 -1
  70. package/dist/integrations/lakebase/types.d.ts.map +1 -1
  71. package/dist/integrations/mariadb/client.d.ts +1 -1
  72. package/dist/integrations/mariadb/client.d.ts.map +1 -1
  73. package/dist/integrations/mariadb/client.js.map +1 -1
  74. package/dist/integrations/mariadb/types.d.ts.map +1 -1
  75. package/dist/integrations/mongodb/client.d.ts +1 -1
  76. package/dist/integrations/mongodb/client.d.ts.map +1 -1
  77. package/dist/integrations/mongodb/client.js.map +1 -1
  78. package/dist/integrations/mongodb/types.d.ts.map +1 -1
  79. package/dist/integrations/mssql/client.d.ts +1 -1
  80. package/dist/integrations/mssql/client.d.ts.map +1 -1
  81. package/dist/integrations/mssql/client.js.map +1 -1
  82. package/dist/integrations/mssql/types.d.ts.map +1 -1
  83. package/dist/integrations/mysql/client.d.ts +1 -1
  84. package/dist/integrations/mysql/client.d.ts.map +1 -1
  85. package/dist/integrations/mysql/client.js.map +1 -1
  86. package/dist/integrations/mysql/types.d.ts.map +1 -1
  87. package/dist/integrations/oracledb/client.d.ts +1 -1
  88. package/dist/integrations/oracledb/client.d.ts.map +1 -1
  89. package/dist/integrations/oracledb/client.js.map +1 -1
  90. package/dist/integrations/oracledb/types.d.ts.map +1 -1
  91. package/dist/integrations/postgres/client.d.ts +2 -2
  92. package/dist/integrations/postgres/client.d.ts.map +1 -1
  93. package/dist/integrations/postgres/client.js.map +1 -1
  94. package/dist/integrations/postgres/types.d.ts.map +1 -1
  95. package/dist/integrations/python/client.d.ts +2 -2
  96. package/dist/integrations/python/client.d.ts.map +1 -1
  97. package/dist/integrations/python/client.js.map +1 -1
  98. package/dist/integrations/python/client.test.js.map +1 -1
  99. package/dist/integrations/python/types.d.ts.map +1 -1
  100. package/dist/integrations/redis/client.d.ts +1 -1
  101. package/dist/integrations/redis/client.d.ts.map +1 -1
  102. package/dist/integrations/redis/client.js.map +1 -1
  103. package/dist/integrations/redis/types.d.ts.map +1 -1
  104. package/dist/integrations/redshift/client.d.ts +1 -1
  105. package/dist/integrations/redshift/client.d.ts.map +1 -1
  106. package/dist/integrations/redshift/client.js.map +1 -1
  107. package/dist/integrations/redshift/types.d.ts.map +1 -1
  108. package/dist/integrations/registry.d.ts.map +1 -1
  109. package/dist/integrations/registry.js +22 -22
  110. package/dist/integrations/registry.js.map +1 -1
  111. package/dist/integrations/registry.test.js.map +1 -1
  112. package/dist/integrations/s3/client.d.ts +1 -1
  113. package/dist/integrations/s3/client.d.ts.map +1 -1
  114. package/dist/integrations/s3/client.js.map +1 -1
  115. package/dist/integrations/s3/types.d.ts +3 -1
  116. package/dist/integrations/s3/types.d.ts.map +1 -1
  117. package/dist/integrations/salesforce/client.d.ts +1 -1
  118. package/dist/integrations/salesforce/client.d.ts.map +1 -1
  119. package/dist/integrations/salesforce/client.js.map +1 -1
  120. package/dist/integrations/salesforce/types.d.ts.map +1 -1
  121. package/dist/integrations/smtp/client.d.ts +1 -1
  122. package/dist/integrations/smtp/client.d.ts.map +1 -1
  123. package/dist/integrations/smtp/client.js.map +1 -1
  124. package/dist/integrations/snowflake/client.d.ts +1 -1
  125. package/dist/integrations/snowflake/client.d.ts.map +1 -1
  126. package/dist/integrations/snowflake/client.js.map +1 -1
  127. package/dist/integrations/snowflake/types.d.ts.map +1 -1
  128. package/dist/integrations/snowflakepostgres/client.d.ts +1 -1
  129. package/dist/integrations/snowflakepostgres/client.d.ts.map +1 -1
  130. package/dist/integrations/snowflakepostgres/client.js.map +1 -1
  131. package/dist/integrations/snowflakepostgres/types.d.ts.map +1 -1
  132. package/dist/runtime/context.d.ts +2 -2
  133. package/dist/runtime/context.d.ts.map +1 -1
  134. package/dist/runtime/context.js.map +1 -1
  135. package/dist/runtime/streaming-context.d.ts +2 -2
  136. package/dist/runtime/streaming-context.d.ts.map +1 -1
  137. package/dist/runtime/streaming-context.js.map +1 -1
  138. package/dist/runtime/streaming-executor.d.ts.map +1 -1
  139. package/dist/runtime/streaming-executor.js +1 -1
  140. package/dist/runtime/streaming-executor.js.map +1 -1
  141. package/dist/types.d.ts.map +1 -1
  142. package/package.json +1 -1
  143. package/src/api/definition.test.ts +1 -0
  144. package/src/api/definition.ts +1 -1
  145. package/src/api/streaming.test.ts +3 -2
  146. package/src/api/streaming.ts +2 -1
  147. package/src/integrations/athena/client.ts +5 -3
  148. package/src/integrations/athena/types.ts +1 -0
  149. package/src/integrations/base/graphql-integration-client.ts +3 -2
  150. package/src/integrations/base/rest-api-integration-client.ts +9 -7
  151. package/src/integrations/base/types.ts +1 -0
  152. package/src/integrations/bigquery/client.ts +5 -3
  153. package/src/integrations/bigquery/types.ts +1 -0
  154. package/src/integrations/cockroachdb/client.ts +5 -3
  155. package/src/integrations/cockroachdb/types.ts +1 -0
  156. package/src/integrations/cosmosdb/client.test.ts +2 -1
  157. package/src/integrations/cosmosdb/client.ts +5 -3
  158. package/src/integrations/cosmosdb/types.ts +1 -0
  159. package/src/integrations/couchbase/client.ts +3 -2
  160. package/src/integrations/couchbase/types.ts +1 -0
  161. package/src/integrations/databricks/client.ts +5 -3
  162. package/src/integrations/databricks/types.ts +1 -0
  163. package/src/integrations/declarations.test.ts +1 -0
  164. package/src/integrations/declarations.ts +36 -36
  165. package/src/integrations/dynamodb/client.ts +3 -2
  166. package/src/integrations/dynamodb/types.ts +1 -0
  167. package/src/integrations/gcs/client.ts +5 -3
  168. package/src/integrations/gcs/types.ts +1 -0
  169. package/src/integrations/graphql/types.ts +2 -1
  170. package/src/integrations/gsheets/client.ts +5 -3
  171. package/src/integrations/gsheets/types.ts +1 -0
  172. package/src/integrations/kafka/client.ts +3 -2
  173. package/src/integrations/kafka/types.ts +1 -0
  174. package/src/integrations/kinesis/client.ts +2 -2
  175. package/src/integrations/lakebase/README.md +242 -0
  176. package/src/integrations/lakebase/client.ts +6 -4
  177. package/src/integrations/lakebase/types.ts +1 -0
  178. package/src/integrations/mariadb/client.ts +5 -3
  179. package/src/integrations/mariadb/types.ts +1 -0
  180. package/src/integrations/mongodb/client.ts +5 -3
  181. package/src/integrations/mongodb/types.ts +1 -0
  182. package/src/integrations/mssql/client.ts +5 -3
  183. package/src/integrations/mssql/types.ts +1 -0
  184. package/src/integrations/mysql/client.ts +5 -3
  185. package/src/integrations/mysql/types.ts +1 -0
  186. package/src/integrations/oracledb/client.ts +5 -3
  187. package/src/integrations/oracledb/types.ts +1 -0
  188. package/src/integrations/postgres/client.ts +6 -4
  189. package/src/integrations/postgres/types.ts +1 -0
  190. package/src/integrations/python/client.test.ts +3 -2
  191. package/src/integrations/python/client.ts +5 -3
  192. package/src/integrations/python/types.ts +1 -0
  193. package/src/integrations/redis/client.ts +3 -2
  194. package/src/integrations/redis/types.ts +1 -0
  195. package/src/integrations/redshift/client.ts +5 -3
  196. package/src/integrations/redshift/types.ts +1 -0
  197. package/src/integrations/registry.test.ts +1 -0
  198. package/src/integrations/registry.ts +23 -23
  199. package/src/integrations/restapiintegration/README.md +359 -0
  200. package/src/integrations/s3/client.ts +5 -3
  201. package/src/integrations/s3/types.ts +4 -1
  202. package/src/integrations/salesforce/client.ts +3 -2
  203. package/src/integrations/salesforce/types.ts +1 -0
  204. package/src/integrations/smtp/README.md +220 -0
  205. package/src/integrations/smtp/client.ts +4 -2
  206. package/src/integrations/snowflake/client.ts +5 -3
  207. package/src/integrations/snowflake/types.ts +1 -0
  208. package/src/integrations/snowflakecortex/README.md +216 -0
  209. package/src/integrations/snowflakepostgres/README.md +233 -0
  210. package/src/integrations/snowflakepostgres/client.ts +1 -1
  211. package/src/integrations/snowflakepostgres/types.ts +1 -0
  212. package/src/runtime/context.ts +10 -10
  213. package/src/runtime/streaming-context.ts +10 -10
  214. package/src/runtime/streaming-executor.ts +4 -4
  215. package/src/types.ts +1 -0
@@ -0,0 +1,359 @@
1
+ # REST API Integration Client
2
+
3
+ Make HTTP requests to any REST API configured with a base URL and authentication in the integrations page.
4
+
5
+ This is the generic REST API Integration plugin. Unlike named integrations (Slack, GitHub, etc.) which target a specific service, this plugin works with **any** HTTP API you configure as an integration.
6
+
7
+ ## Methods
8
+
9
+ | Method | Description |
10
+ | ---------------------------------------------- | ------------------------------------------------ |
11
+ | `apiRequest(options, schema, metadata?)` | Make any HTTP request with schema validation |
12
+ | `streamApiRequest(options, schema, metadata?)` | Stream responses with real-time chunk validation |
13
+
14
+ ## Usage
15
+
16
+ ### Basic GET Request
17
+
18
+ ```typescript
19
+ import { api, z, restApiIntegration } from "@superblocksteam/sdk-api";
20
+
21
+ // Integration ID from the integrations panel
22
+ const MY_API = "a1b2c3d4-5678-90ab-cdef-111111111111";
23
+
24
+ const UsersResponseSchema = z.object({
25
+ users: z.array(
26
+ z.object({
27
+ id: z.string(),
28
+ name: z.string(),
29
+ email: z.string(),
30
+ }),
31
+ ),
32
+ });
33
+
34
+ export default api({
35
+ name: "FetchUsers",
36
+ integrations: {
37
+ myApi: restApiIntegration(MY_API),
38
+ },
39
+ input: z.object({}),
40
+ output: z.object({
41
+ users: z.array(
42
+ z.object({ id: z.string(), name: z.string(), email: z.string() }),
43
+ ),
44
+ }),
45
+ async run(ctx) {
46
+ const result = await ctx.integrations.myApi.apiRequest(
47
+ {
48
+ method: "GET",
49
+ path: "/users",
50
+ params: { limit: 50 },
51
+ },
52
+ { response: UsersResponseSchema },
53
+ );
54
+
55
+ return { users: result.users };
56
+ },
57
+ });
58
+ ```
59
+
60
+ ### POST Request with Body
61
+
62
+ ```typescript
63
+ const CreateRecordSchema = z.object({
64
+ id: z.string(),
65
+ created_at: z.string(),
66
+ });
67
+
68
+ const record = await ctx.integrations.myApi.apiRequest(
69
+ {
70
+ method: "POST",
71
+ path: "/records",
72
+ body: {
73
+ title: "New Record",
74
+ description: "Created via Superblocks",
75
+ tags: ["automated"],
76
+ },
77
+ headers: {
78
+ "Content-Type": "application/json",
79
+ },
80
+ },
81
+ { response: CreateRecordSchema },
82
+ );
83
+
84
+ console.log(`Created record: ${record.id}`);
85
+ ```
86
+
87
+ ### PATCH/PUT Request
88
+
89
+ ```typescript
90
+ const UpdateResponseSchema = z.object({
91
+ id: z.string(),
92
+ updated_at: z.string(),
93
+ });
94
+
95
+ await ctx.integrations.myApi.apiRequest(
96
+ {
97
+ method: "PATCH",
98
+ path: `/records/${recordId}`,
99
+ body: {
100
+ title: "Updated Title",
101
+ status: "published",
102
+ },
103
+ headers: {
104
+ "Content-Type": "application/json",
105
+ },
106
+ },
107
+ { response: UpdateResponseSchema },
108
+ );
109
+ ```
110
+
111
+ ### DELETE Request
112
+
113
+ ```typescript
114
+ await ctx.integrations.myApi.apiRequest(
115
+ {
116
+ method: "DELETE",
117
+ path: `/records/${recordId}`,
118
+ },
119
+ { response: z.object({}).passthrough() },
120
+ );
121
+ ```
122
+
123
+ ### Search with Query Parameters
124
+
125
+ ```typescript
126
+ const SearchResponseSchema = z.object({
127
+ items: z.array(
128
+ z.object({
129
+ id: z.string(),
130
+ title: z.string(),
131
+ score: z.number().optional(),
132
+ }),
133
+ ),
134
+ total: z.number(),
135
+ });
136
+
137
+ const results = await ctx.integrations.myApi.apiRequest(
138
+ {
139
+ method: "GET",
140
+ path: "/search",
141
+ params: {
142
+ q: "my query",
143
+ page: 1,
144
+ per_page: 25,
145
+ },
146
+ },
147
+ { response: SearchResponseSchema },
148
+ );
149
+
150
+ console.log(`Found ${results.total} results`);
151
+ ```
152
+
153
+ ### Using Multiple Integrations
154
+
155
+ You can use multiple REST API Integrations in a single API, each targeting a different service:
156
+
157
+ ```typescript
158
+ import { api, z, restApiIntegration, postgres } from "@superblocksteam/sdk-api";
159
+
160
+ const EXTERNAL_API = "a1b2c3d4-5678-90ab-cdef-111111111111";
161
+ const INTERNAL_API = "e5f6a7b8-9012-34cd-ef56-222222222222";
162
+ const MY_DB = "c3d4e5f6-7890-12ab-cdef-333333333333";
163
+
164
+ export default api({
165
+ name: "SyncData",
166
+ integrations: {
167
+ externalApi: restApiIntegration(EXTERNAL_API),
168
+ internalApi: restApiIntegration(INTERNAL_API),
169
+ db: postgres(MY_DB),
170
+ },
171
+ input: z.object({ query: z.string() }),
172
+ output: z.object({ synced: z.number() }),
173
+ async run(ctx, { query }) {
174
+ // Fetch from external API
175
+ const external = await ctx.integrations.externalApi.apiRequest(
176
+ { method: "GET", path: "/data", params: { q: query } },
177
+ { response: z.object({ items: z.array(z.unknown()) }) },
178
+ );
179
+
180
+ // Push to internal API
181
+ await ctx.integrations.internalApi.apiRequest(
182
+ { method: "POST", path: "/import", body: { items: external.items } },
183
+ { response: z.object({ imported: z.number() }) },
184
+ );
185
+
186
+ return { synced: external.items.length };
187
+ },
188
+ });
189
+ ```
190
+
191
+ ### Streaming Responses
192
+
193
+ For APIs that return streaming data (e.g., Server-Sent Events), use `streamApiRequest()`:
194
+
195
+ ```typescript
196
+ import { streamingApi, z, restApiIntegration } from "@superblocksteam/sdk-api";
197
+
198
+ const MY_API = "a1b2c3d4-5678-90ab-cdef-111111111111";
199
+
200
+ const StreamChunkSchema = z.object({
201
+ id: z.string(),
202
+ data: z.string(),
203
+ });
204
+
205
+ export default streamingApi({
206
+ integrations: {
207
+ myApi: restApiIntegration(MY_API),
208
+ },
209
+ input: z.object({ prompt: z.string() }),
210
+ chunk: z.object({ text: z.string() }),
211
+
212
+ async *run(ctx, { prompt }) {
213
+ const stream = ctx.integrations.myApi.streamApiRequest(
214
+ {
215
+ method: "POST",
216
+ path: "/stream",
217
+ body: { prompt },
218
+ },
219
+ { chunk: StreamChunkSchema },
220
+ );
221
+
222
+ for await (const chunk of stream) {
223
+ yield { text: chunk.data };
224
+ }
225
+ },
226
+ });
227
+ ```
228
+
229
+ ## Trace Metadata
230
+
231
+ All methods accept an optional `metadata` parameter as the last argument for diagnostics labeling. See the [root SDK README](../../../README.md#trace-metadata) for details.
232
+
233
+ ```typescript
234
+ const result = await ctx.integrations.myApi.apiRequest(
235
+ { method: "GET", path: "/users" },
236
+ { response: UsersResponseSchema },
237
+ { label: "myApi.getUsers", description: "Fetch all active users" },
238
+ );
239
+ ```
240
+
241
+ ## Common Pitfalls
242
+
243
+ ### No `.request()` Method
244
+
245
+ The only public methods are `apiRequest()` and `streamApiRequest()`. There is no `.request()` method:
246
+
247
+ ```typescript
248
+ // WRONG - .request() does not exist
249
+ await ctx.integrations.myApi.request({
250
+ method: "GET",
251
+ path: "/users",
252
+ });
253
+
254
+ // CORRECT - Use apiRequest with a response schema
255
+ await ctx.integrations.myApi.apiRequest(
256
+ { method: "GET", path: "/users" },
257
+ { response: UsersResponseSchema },
258
+ );
259
+ ```
260
+
261
+ ### Response Schema is Required
262
+
263
+ `apiRequest()` requires a response schema for type safety:
264
+
265
+ ```typescript
266
+ // WRONG - Missing response schema
267
+ const result = await ctx.integrations.myApi.apiRequest({
268
+ method: "GET",
269
+ path: "/users",
270
+ });
271
+
272
+ // CORRECT - Provide a response schema
273
+ const result = await ctx.integrations.myApi.apiRequest(
274
+ { method: "GET", path: "/users" },
275
+ { response: z.object({ users: z.array(z.unknown()) }) },
276
+ );
277
+ ```
278
+
279
+ ### Use `body` Instead of `JSON.stringify`
280
+
281
+ The `body` field is automatically serialized. Do not stringify it manually:
282
+
283
+ ```typescript
284
+ // WRONG - Manual stringify
285
+ await ctx.integrations.myApi.apiRequest(
286
+ {
287
+ method: "POST",
288
+ path: "/records",
289
+ body: JSON.stringify({ title: "New" }),
290
+ },
291
+ { response: ResponseSchema },
292
+ );
293
+
294
+ // CORRECT - Pass object directly
295
+ await ctx.integrations.myApi.apiRequest(
296
+ {
297
+ method: "POST",
298
+ path: "/records",
299
+ body: { title: "New" },
300
+ },
301
+ { response: ResponseSchema },
302
+ );
303
+ ```
304
+
305
+ ### Use `params` for Query Parameters
306
+
307
+ Query parameters go in the `params` field, not in the URL path:
308
+
309
+ ```typescript
310
+ // WRONG - Query params in path
311
+ await ctx.integrations.myApi.apiRequest(
312
+ { method: "GET", path: "/search?q=hello&limit=10" },
313
+ { response: ResponseSchema },
314
+ );
315
+
316
+ // CORRECT - Use params field
317
+ await ctx.integrations.myApi.apiRequest(
318
+ {
319
+ method: "GET",
320
+ path: "/search",
321
+ params: { q: "hello", limit: 10 },
322
+ },
323
+ { response: ResponseSchema },
324
+ );
325
+ ```
326
+
327
+ ### Use `.passthrough()` for Flexible Schemas
328
+
329
+ When the response contains fields you don't need to validate, use `.passthrough()`:
330
+
331
+ ```typescript
332
+ // Strict schema - will reject unknown fields
333
+ const StrictSchema = z.object({ id: z.string() });
334
+
335
+ // Flexible schema - allows additional fields
336
+ const FlexibleSchema = z.object({ id: z.string() }).passthrough();
337
+
338
+ // For dynamic responses
339
+ const GenericSchema = z.record(z.unknown());
340
+ ```
341
+
342
+ ## Error Handling
343
+
344
+ ```typescript
345
+ import { RestApiValidationError } from "@superblocksteam/sdk-api";
346
+
347
+ try {
348
+ const result = await ctx.integrations.myApi.apiRequest(
349
+ { method: "GET", path: "/users" },
350
+ { response: UsersResponseSchema },
351
+ );
352
+ } catch (error) {
353
+ if (error instanceof RestApiValidationError) {
354
+ // Response didn't match the schema
355
+ console.error("Validation failed:", error.details.zodError);
356
+ console.error("Actual response:", error.details.data);
357
+ }
358
+ }
359
+ ```
@@ -4,13 +4,15 @@
4
4
  * Uses the native S3 plugin type from @superblocksteam/types.
5
5
  */
6
6
 
7
- import type { z } from "zod";
8
7
  import type { PartialMessage } from "@bufbuild/protobuf";
8
+ import type { z } from "zod";
9
+
9
10
  import type { Plugin as S3Plugin } from "@superblocksteam/types/dist/src/plugins/s3/v1/plugin_pb";
10
- import type { IntegrationConfig, IntegrationClientImpl } from "../types.js";
11
- import type { QueryExecutor, TraceMetadata } from "../registry.js";
11
+
12
12
  import { RestApiValidationError } from "../../errors.js";
13
13
  import { IntegrationError } from "../../runtime/errors.js";
14
+ import type { QueryExecutor, TraceMetadata } from "../registry.js";
15
+ import type { IntegrationConfig, IntegrationClientImpl } from "../types.js";
14
16
  import type {
15
17
  S3Client,
16
18
  S3Action,
@@ -3,6 +3,7 @@
3
3
  */
4
4
 
5
5
  import type { z } from "zod";
6
+
6
7
  import type { BaseIntegrationClient } from "../../types.js";
7
8
  import type { TraceMetadata } from "../registry.js";
8
9
 
@@ -129,7 +130,9 @@ export interface S3Client extends BaseIntegrationClient {
129
130
  *
130
131
  * @param bucket - Bucket name
131
132
  * @param path - Object key/path
132
- * @param body - File content (base64 or text)
133
+ * @param body - String content stored verbatim (no base64 decoding is performed).
134
+ * Suitable for plain text, JSON, or CSV. For binary files (PDF, DOCX, images),
135
+ * use {@link S3Client.uploadMultipleObjects | uploadMultipleObjects} with file references instead.
133
136
  * @param metadata - Optional trace metadata for diagnostics
134
137
  */
135
138
  uploadObject(
@@ -6,10 +6,11 @@
6
6
  */
7
7
 
8
8
  import type { z } from "zod";
9
- import type { IntegrationConfig, IntegrationClientImpl } from "../types.js";
10
- import type { QueryExecutor, TraceMetadata } from "../registry.js";
9
+
11
10
  import { QueryValidationError, RestApiValidationError } from "../../errors.js";
12
11
  import { IntegrationError } from "../../runtime/errors.js";
12
+ import type { QueryExecutor, TraceMetadata } from "../registry.js";
13
+ import type { IntegrationConfig, IntegrationClientImpl } from "../types.js";
13
14
  import { describeType } from "../utils.js";
14
15
  import type { SalesforceClient } from "./types.js";
15
16
 
@@ -3,6 +3,7 @@
3
3
  */
4
4
 
5
5
  import type { z } from "zod";
6
+
6
7
  import type { BaseIntegrationClient } from "../../types.js";
7
8
  import type { TraceMetadata } from "../registry.js";
8
9
 
@@ -0,0 +1,220 @@
1
+ # SMTP Client
2
+
3
+ Send emails via SMTP with support for HTML content, CC/BCC, reply-to, and attachments.
4
+
5
+ ## Methods
6
+
7
+ | Method | Description |
8
+ | -------------------------- | ---------------------- |
9
+ | `send(options, metadata?)` | Send an email via SMTP |
10
+
11
+ ## Usage
12
+
13
+ ### Send a Simple Email
14
+
15
+ ```typescript
16
+ import { api, z, smtp } from "@superblocksteam/sdk-api";
17
+
18
+ // Integration ID from the integrations panel
19
+ const MAILER = "a1b2c3d4-5678-90ab-cdef-111111111111";
20
+
21
+ export default api({
22
+ name: "SendEmail",
23
+ integrations: {
24
+ mailer: smtp(MAILER),
25
+ },
26
+ input: z.object({
27
+ to: z.string(),
28
+ subject: z.string(),
29
+ body: z.string(),
30
+ }),
31
+ output: z.object({ success: z.boolean() }),
32
+
33
+ async run(ctx, { to, subject, body }) {
34
+ await ctx.integrations.mailer.send({
35
+ from: "noreply@example.com",
36
+ to,
37
+ subject,
38
+ body,
39
+ });
40
+
41
+ return { success: true };
42
+ },
43
+ });
44
+ ```
45
+
46
+ ### Send HTML Email
47
+
48
+ ```typescript
49
+ await ctx.integrations.mailer.send({
50
+ from: "noreply@example.com",
51
+ to: "user@example.com",
52
+ subject: "Welcome!",
53
+ body: "<h1>Welcome!</h1><p>Thank you for signing up.</p>",
54
+ });
55
+ ```
56
+
57
+ ### Send with CC and BCC
58
+
59
+ ```typescript
60
+ await ctx.integrations.mailer.send({
61
+ from: "noreply@example.com",
62
+ to: "user@example.com",
63
+ subject: "Team Update",
64
+ body: "Hello team!",
65
+ cc: "manager@example.com,lead@example.com",
66
+ bcc: "archive@example.com",
67
+ replyTo: "support@example.com",
68
+ });
69
+ ```
70
+
71
+ ### Send to Multiple Recipients
72
+
73
+ Use comma-separated email addresses:
74
+
75
+ ```typescript
76
+ await ctx.integrations.mailer.send({
77
+ from: "noreply@example.com",
78
+ to: "user1@example.com,user2@example.com,user3@example.com",
79
+ subject: "Announcement",
80
+ body: "<p>Important update for the team.</p>",
81
+ });
82
+ ```
83
+
84
+ ### Send with Attachments
85
+
86
+ Attachments are passed as a JSON string containing an array of objects with `content` (base64-encoded), `name` (filename), and `type` (MIME type):
87
+
88
+ ```typescript
89
+ const attachments = JSON.stringify([
90
+ {
91
+ content: base64EncodedPdf, // Base64-encoded file content
92
+ name: "report.pdf",
93
+ type: "application/pdf",
94
+ },
95
+ {
96
+ content: base64EncodedCsv,
97
+ name: "data.csv",
98
+ type: "text/csv",
99
+ },
100
+ ]);
101
+
102
+ await ctx.integrations.mailer.send({
103
+ from: "reports@example.com",
104
+ to: "user@example.com",
105
+ subject: "Your Report",
106
+ body: "<p>Please find the attached report.</p>",
107
+ attachments,
108
+ });
109
+ ```
110
+
111
+ ## Trace Metadata
112
+
113
+ The `send` method accepts an optional `metadata` parameter as the last argument for diagnostics labeling:
114
+
115
+ ```typescript
116
+ await ctx.integrations.mailer.send(
117
+ {
118
+ from: "noreply@example.com",
119
+ to: "user@example.com",
120
+ subject: "Welcome",
121
+ body: "Hello!",
122
+ },
123
+ { label: "Send welcome email" },
124
+ );
125
+ ```
126
+
127
+ When `includeDiagnostics` is enabled, `label` and `description` appear in the trace view. See the [root SDK README](../../../README.md#trace-metadata) for details.
128
+
129
+ ## Send Options Reference
130
+
131
+ | Option | Type | Required | Description |
132
+ | ------------- | -------- | -------- | --------------------------------------------- |
133
+ | `from` | `string` | Yes | Sender email address |
134
+ | `to` | `string` | Yes | Recipient(s), comma-separated for multiple |
135
+ | `subject` | `string` | Yes | Email subject line |
136
+ | `body` | `string` | Yes | Email body (HTML or plain text) |
137
+ | `cc` | `string` | No | CC recipient(s), comma-separated |
138
+ | `bcc` | `string` | No | BCC recipient(s), comma-separated |
139
+ | `replyTo` | `string` | No | Reply-to email address |
140
+ | `attachments` | `string` | No | JSON array of `{content, name, type}` objects |
141
+
142
+ ## Common Pitfalls
143
+
144
+ ### Use the `send` Method, Not `apiRequest`
145
+
146
+ Unlike most integrations, SMTP has a dedicated `send()` method:
147
+
148
+ ```typescript
149
+ // WRONG - apiRequest does not exist on SmtpClient
150
+ await ctx.integrations.mailer.apiRequest({ ... });
151
+
152
+ // CORRECT - Use send()
153
+ await ctx.integrations.mailer.send({
154
+ from: "noreply@example.com",
155
+ to: "user@example.com",
156
+ subject: "Hello",
157
+ body: "World",
158
+ });
159
+ ```
160
+
161
+ ### Attachments Must Be a JSON String
162
+
163
+ ```typescript
164
+ // WRONG - Passing an array directly
165
+ await ctx.integrations.mailer.send({
166
+ from: "noreply@example.com",
167
+ to: "user@example.com",
168
+ subject: "Report",
169
+ body: "See attached",
170
+ attachments: [{ content: "...", name: "file.pdf", type: "application/pdf" }],
171
+ });
172
+
173
+ // CORRECT - JSON.stringify the array
174
+ await ctx.integrations.mailer.send({
175
+ from: "noreply@example.com",
176
+ to: "user@example.com",
177
+ subject: "Report",
178
+ body: "See attached",
179
+ attachments: JSON.stringify([
180
+ { content: "...", name: "file.pdf", type: "application/pdf" },
181
+ ]),
182
+ });
183
+ ```
184
+
185
+ ### Multiple Recipients Use Comma Separation
186
+
187
+ ```typescript
188
+ // WRONG - Array of recipients
189
+ await ctx.integrations.mailer.send({
190
+ to: ["user1@example.com", "user2@example.com"],
191
+ // ...
192
+ });
193
+
194
+ // CORRECT - Comma-separated string
195
+ await ctx.integrations.mailer.send({
196
+ to: "user1@example.com,user2@example.com",
197
+ // ...
198
+ });
199
+ ```
200
+
201
+ ## Error Handling
202
+
203
+ ```typescript
204
+ import { IntegrationError } from "@superblocksteam/sdk-api";
205
+
206
+ try {
207
+ await ctx.integrations.mailer.send({
208
+ from: "noreply@example.com",
209
+ to: "user@example.com",
210
+ subject: "Test",
211
+ body: "Hello",
212
+ });
213
+ } catch (error) {
214
+ if (error instanceof IntegrationError) {
215
+ console.error(
216
+ `SMTP error in ${error.integrationName}.${error.method}: ${error.message}`,
217
+ );
218
+ }
219
+ }
220
+ ```
@@ -6,10 +6,12 @@
6
6
  */
7
7
 
8
8
  import type { PartialMessage } from "@bufbuild/protobuf";
9
+
9
10
  import type { Plugin as SmtpPlugin } from "@superblocksteam/types/dist/src/plugins/smtp/v1/plugin_pb";
10
- import type { IntegrationConfig, IntegrationClientImpl } from "../types.js";
11
- import type { QueryExecutor, TraceMetadata } from "../registry.js";
11
+
12
12
  import { IntegrationError } from "../../runtime/errors.js";
13
+ import type { QueryExecutor, TraceMetadata } from "../registry.js";
14
+ import type { IntegrationConfig, IntegrationClientImpl } from "../types.js";
13
15
  import type { SmtpClient, SmtpSendOptions } from "./types.js";
14
16
 
15
17
  /**
@@ -5,13 +5,15 @@
5
5
  * runtime validation using Zod schemas.
6
6
  */
7
7
 
8
- import type { z } from "zod";
9
8
  import type { PartialMessage } from "@bufbuild/protobuf";
9
+ import type { z } from "zod";
10
+
10
11
  import type { Plugin as SnowflakePlugin } from "@superblocksteam/types/dist/src/plugins/snowflake/v1/plugin_pb";
11
- import type { IntegrationConfig, IntegrationClientImpl } from "../types.js";
12
- import type { QueryExecutor, TraceMetadata } from "../registry.js";
12
+
13
13
  import { QueryValidationError } from "../../errors.js";
14
14
  import { IntegrationError } from "../../runtime/errors.js";
15
+ import type { QueryExecutor, TraceMetadata } from "../registry.js";
16
+ import type { IntegrationConfig, IntegrationClientImpl } from "../types.js";
15
17
  import { describeType } from "../utils.js";
16
18
  import type { SnowflakeClient } from "./types.js";
17
19
 
@@ -5,6 +5,7 @@
5
5
  */
6
6
 
7
7
  import type { z } from "zod";
8
+
8
9
  import type { BaseIntegrationClient } from "../../types";
9
10
  import type { TraceMetadata } from "../registry.js";
10
11