@superblocksteam/sdk-api 2.0.104 → 2.0.105-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 (163) hide show
  1. package/README.md +202 -86
  2. package/dist/api/definition.d.ts +11 -6
  3. package/dist/api/definition.d.ts.map +1 -1
  4. package/dist/api/definition.js +19 -12
  5. package/dist/api/definition.js.map +1 -1
  6. package/dist/api/definition.test.js +39 -15
  7. package/dist/api/definition.test.js.map +1 -1
  8. package/dist/errors.d.ts +1 -1
  9. package/dist/errors.js +1 -1
  10. package/dist/index.d.ts +10 -10
  11. package/dist/index.d.ts.map +1 -1
  12. package/dist/index.js +9 -5
  13. package/dist/index.js.map +1 -1
  14. package/dist/integrations/base/index.d.ts +2 -1
  15. package/dist/integrations/base/index.d.ts.map +1 -1
  16. package/dist/integrations/base/index.js +1 -0
  17. package/dist/integrations/base/index.js.map +1 -1
  18. package/dist/integrations/base/rest-api-client-base.d.ts +48 -0
  19. package/dist/integrations/base/rest-api-client-base.d.ts.map +1 -0
  20. package/dist/integrations/base/rest-api-client-base.js +98 -0
  21. package/dist/integrations/base/rest-api-client-base.js.map +1 -0
  22. package/dist/integrations/base/rest-api-integration-client.d.ts +10 -20
  23. package/dist/integrations/base/rest-api-integration-client.d.ts.map +1 -1
  24. package/dist/integrations/base/rest-api-integration-client.js +10 -65
  25. package/dist/integrations/base/rest-api-integration-client.js.map +1 -1
  26. package/dist/integrations/box/types.d.ts +1 -1
  27. package/dist/integrations/declarations.d.ts +5 -63
  28. package/dist/integrations/declarations.d.ts.map +1 -1
  29. package/dist/integrations/declarations.js +5 -59
  30. package/dist/integrations/declarations.js.map +1 -1
  31. package/dist/integrations/documentation.test.js +0 -2
  32. package/dist/integrations/documentation.test.js.map +1 -1
  33. package/dist/integrations/googledrive/types.d.ts +1 -1
  34. package/dist/integrations/index.d.ts +1 -9
  35. package/dist/integrations/index.d.ts.map +1 -1
  36. package/dist/integrations/index.js +1 -6
  37. package/dist/integrations/index.js.map +1 -1
  38. package/dist/integrations/registry.d.ts +1 -10
  39. package/dist/integrations/registry.d.ts.map +1 -1
  40. package/dist/integrations/registry.js +0 -25
  41. package/dist/integrations/registry.js.map +1 -1
  42. package/dist/integrations/slack/client.d.ts +13 -9
  43. package/dist/integrations/slack/client.d.ts.map +1 -1
  44. package/dist/integrations/slack/client.js +60 -8
  45. package/dist/integrations/slack/client.js.map +1 -1
  46. package/dist/integrations/slack/client.test.d.ts +11 -0
  47. package/dist/integrations/slack/client.test.d.ts.map +1 -0
  48. package/dist/integrations/slack/client.test.js +368 -0
  49. package/dist/integrations/slack/client.test.js.map +1 -0
  50. package/dist/integrations/slack/index.d.ts +2 -1
  51. package/dist/integrations/slack/index.d.ts.map +1 -1
  52. package/dist/integrations/slack/index.js +1 -0
  53. package/dist/integrations/slack/index.js.map +1 -1
  54. package/dist/integrations/slack/types.d.ts +127 -28
  55. package/dist/integrations/slack/types.d.ts.map +1 -1
  56. package/dist/integrations/slack/types.js +27 -1
  57. package/dist/integrations/slack/types.js.map +1 -1
  58. package/dist/integrations/snowflake/client.d.ts +2 -2
  59. package/dist/integrations/snowflake/client.js +2 -2
  60. package/dist/runtime/context.d.ts +1 -1
  61. package/dist/runtime/executor.d.ts +2 -2
  62. package/dist/types.d.ts +14 -5
  63. package/dist/types.d.ts.map +1 -1
  64. package/package.json +2 -2
  65. package/src/api/definition.test.ts +40 -15
  66. package/src/api/definition.ts +19 -12
  67. package/src/errors.ts +1 -1
  68. package/src/index.ts +13 -30
  69. package/src/integrations/asana/README.md +12 -12
  70. package/src/integrations/base/index.ts +2 -1
  71. package/src/integrations/base/rest-api-client-base.ts +134 -0
  72. package/src/integrations/base/rest-api-integration-client.ts +12 -89
  73. package/src/integrations/bitbucket/README.md +19 -19
  74. package/src/integrations/box/README.md +24 -24
  75. package/src/integrations/box/types.ts +1 -1
  76. package/src/integrations/circleci/README.md +18 -18
  77. package/src/integrations/declarations.ts +5 -91
  78. package/src/integrations/documentation.test.ts +0 -2
  79. package/src/integrations/googledrive/README.md +25 -22
  80. package/src/integrations/googledrive/types.ts +1 -1
  81. package/src/integrations/graphql/README.md +2 -2
  82. package/src/integrations/index.ts +0 -45
  83. package/src/integrations/registry.ts +1 -34
  84. package/src/integrations/salesforce/README.md +11 -9
  85. package/src/integrations/slack/README.md +62 -19
  86. package/src/integrations/slack/client.test.ts +553 -0
  87. package/src/integrations/slack/client.ts +92 -12
  88. package/src/integrations/slack/index.ts +6 -1
  89. package/src/integrations/slack/types.ts +142 -29
  90. package/src/integrations/snowflake/client.ts +2 -2
  91. package/src/integrations/zoom/README.md +15 -15
  92. package/src/runtime/context.ts +1 -1
  93. package/src/runtime/executor.ts +2 -2
  94. package/src/types.ts +14 -5
  95. package/dist/integrations/couchbase/client.d.ts +0 -36
  96. package/dist/integrations/couchbase/client.d.ts.map +0 -1
  97. package/dist/integrations/couchbase/client.js +0 -148
  98. package/dist/integrations/couchbase/client.js.map +0 -1
  99. package/dist/integrations/couchbase/index.d.ts +0 -8
  100. package/dist/integrations/couchbase/index.d.ts.map +0 -1
  101. package/dist/integrations/couchbase/index.js +0 -7
  102. package/dist/integrations/couchbase/index.js.map +0 -1
  103. package/dist/integrations/couchbase/types.d.ts +0 -100
  104. package/dist/integrations/couchbase/types.d.ts.map +0 -1
  105. package/dist/integrations/couchbase/types.js +0 -5
  106. package/dist/integrations/couchbase/types.js.map +0 -1
  107. package/dist/integrations/kafka/client.d.ts +0 -25
  108. package/dist/integrations/kafka/client.d.ts.map +0 -1
  109. package/dist/integrations/kafka/client.js +0 -124
  110. package/dist/integrations/kafka/client.js.map +0 -1
  111. package/dist/integrations/kafka/index.d.ts +0 -8
  112. package/dist/integrations/kafka/index.d.ts.map +0 -1
  113. package/dist/integrations/kafka/index.js +0 -7
  114. package/dist/integrations/kafka/index.js.map +0 -1
  115. package/dist/integrations/kafka/types.d.ts +0 -113
  116. package/dist/integrations/kafka/types.d.ts.map +0 -1
  117. package/dist/integrations/kafka/types.js +0 -5
  118. package/dist/integrations/kafka/types.js.map +0 -1
  119. package/dist/integrations/kinesis/client.d.ts +0 -31
  120. package/dist/integrations/kinesis/client.d.ts.map +0 -1
  121. package/dist/integrations/kinesis/client.js +0 -101
  122. package/dist/integrations/kinesis/client.js.map +0 -1
  123. package/dist/integrations/kinesis/index.d.ts +0 -8
  124. package/dist/integrations/kinesis/index.d.ts.map +0 -1
  125. package/dist/integrations/kinesis/index.js +0 -7
  126. package/dist/integrations/kinesis/index.js.map +0 -1
  127. package/dist/integrations/kinesis/types.d.ts +0 -97
  128. package/dist/integrations/kinesis/types.d.ts.map +0 -1
  129. package/dist/integrations/kinesis/types.js +0 -7
  130. package/dist/integrations/kinesis/types.js.map +0 -1
  131. package/dist/integrations/python/client.d.ts +0 -42
  132. package/dist/integrations/python/client.d.ts.map +0 -1
  133. package/dist/integrations/python/client.js +0 -89
  134. package/dist/integrations/python/client.js.map +0 -1
  135. package/dist/integrations/python/client.test.d.ts +0 -5
  136. package/dist/integrations/python/client.test.d.ts.map +0 -1
  137. package/dist/integrations/python/client.test.js +0 -214
  138. package/dist/integrations/python/client.test.js.map +0 -1
  139. package/dist/integrations/python/index.d.ts +0 -6
  140. package/dist/integrations/python/index.d.ts.map +0 -1
  141. package/dist/integrations/python/index.js +0 -5
  142. package/dist/integrations/python/index.js.map +0 -1
  143. package/dist/integrations/python/types.d.ts +0 -85
  144. package/dist/integrations/python/types.d.ts.map +0 -1
  145. package/dist/integrations/python/types.js +0 -5
  146. package/dist/integrations/python/types.js.map +0 -1
  147. package/src/integrations/couchbase/README.md +0 -138
  148. package/src/integrations/couchbase/client.ts +0 -225
  149. package/src/integrations/couchbase/index.ts +0 -8
  150. package/src/integrations/couchbase/types.ts +0 -126
  151. package/src/integrations/kafka/README.md +0 -144
  152. package/src/integrations/kafka/client.ts +0 -216
  153. package/src/integrations/kafka/index.ts +0 -14
  154. package/src/integrations/kafka/types.ts +0 -128
  155. package/src/integrations/kinesis/README.md +0 -153
  156. package/src/integrations/kinesis/client.ts +0 -146
  157. package/src/integrations/kinesis/index.ts +0 -14
  158. package/src/integrations/kinesis/types.ts +0 -114
  159. package/src/integrations/python/README.md +0 -566
  160. package/src/integrations/python/client.test.ts +0 -341
  161. package/src/integrations/python/client.ts +0 -136
  162. package/src/integrations/python/index.ts +0 -6
  163. package/src/integrations/python/types.ts +0 -92
@@ -1,114 +0,0 @@
1
- /**
2
- * Kinesis client types.
3
- *
4
- * Kinesis uses a dedicated plugin (not REST API) with PUT and GET operations.
5
- */
6
-
7
- import type { BaseIntegrationClient } from "../../types.js";
8
- import type { TraceMetadata } from "../registry.js";
9
-
10
- /**
11
- * Stream identifier type for Kinesis operations.
12
- */
13
- export type KinesisStreamIdentifier = "STREAM_NAME" | "STREAM_ARN";
14
-
15
- /**
16
- * Shard iterator type for Kinesis GET operations.
17
- */
18
- export type KinesisShardIteratorType =
19
- | "AT_SEQUENCE_NUMBER"
20
- | "AFTER_SEQUENCE_NUMBER"
21
- | "AT_TIMESTAMP"
22
- | "TRIM_HORIZON"
23
- | "LATEST";
24
-
25
- /**
26
- * Parameters for a Kinesis PUT operation.
27
- */
28
- export interface KinesisPutParams {
29
- /** The data payload (JSON string or raw string) */
30
- data: string;
31
- /** The partition key for the record */
32
- partitionKey: string;
33
- /** How to identify the stream */
34
- streamIdentifierType?: KinesisStreamIdentifier;
35
- /** Stream name (when streamIdentifierType is STREAM_NAME) */
36
- streamName?: string;
37
- /** Stream ARN (when streamIdentifierType is STREAM_ARN) */
38
- streamArn?: string;
39
- }
40
-
41
- /**
42
- * Parameters for a Kinesis GET operation.
43
- */
44
- export interface KinesisGetParams {
45
- /** The shard ID to read from */
46
- shardId: string;
47
- /** How to position the shard iterator */
48
- shardIteratorType: KinesisShardIteratorType;
49
- /** Maximum number of records to return */
50
- limit?: number;
51
- /** Polling cooldown in milliseconds */
52
- pollingCooldownMs?: number;
53
- /** Starting sequence number (for AT/AFTER_SEQUENCE_NUMBER) */
54
- startingSequenceNumber?: string;
55
- /** Timestamp (for AT_TIMESTAMP) */
56
- timestamp?: string;
57
- /** How to identify the stream */
58
- streamIdentifierType?: KinesisStreamIdentifier;
59
- /** Stream name (when streamIdentifierType is STREAM_NAME) */
60
- streamName?: string;
61
- /** Stream ARN (when streamIdentifierType is STREAM_ARN) */
62
- streamArn?: string;
63
- }
64
-
65
- /**
66
- * Kinesis client for Amazon Kinesis Data Streams.
67
- *
68
- * Provides methods for putting records to and getting records from Kinesis streams.
69
- *
70
- * @example
71
- * ```typescript
72
- * // Declare in api(): integrations: { kinesis: kinesis(INTEGRATION_ID) }
73
- * // In run(), access via ctx.integrations.kinesis
74
- *
75
- * // Put a record
76
- * await kinesis.putRecord({
77
- * data: JSON.stringify({ event: 'user_signup', userId: '123' }),
78
- * partitionKey: 'user-123',
79
- * streamName: 'user-events',
80
- * });
81
- *
82
- * // Get records from a shard
83
- * const records = await kinesis.getRecords({
84
- * shardId: 'shardId-000000000000',
85
- * shardIteratorType: 'LATEST',
86
- * streamName: 'user-events',
87
- * limit: 10,
88
- * });
89
- * ```
90
- */
91
- export interface KinesisClient extends BaseIntegrationClient {
92
- /**
93
- * Put a record to a Kinesis stream.
94
- *
95
- * @param params - PUT operation parameters
96
- * @returns The raw result from Kinesis (includes ShardId and SequenceNumber)
97
- */
98
- putRecord(
99
- params: KinesisPutParams,
100
- metadata?: TraceMetadata,
101
- ): Promise<unknown>;
102
-
103
- /**
104
- * Get records from a Kinesis stream shard.
105
- *
106
- * @param params - GET operation parameters
107
- * @param metadata - Optional trace metadata for diagnostics
108
- * @returns The raw result from Kinesis (includes Records array)
109
- */
110
- getRecords(
111
- params: KinesisGetParams,
112
- metadata?: TraceMetadata,
113
- ): Promise<unknown>;
114
- }
@@ -1,566 +0,0 @@
1
- # Python Client
2
-
3
- Execute Python scripts with type-safe inputs and outputs using the Superblocks SDK.
4
-
5
- ## Overview
6
-
7
- The Python client allows you to run Python code with:
8
-
9
- - Type-safe input bindings via `{{}}` syntax
10
- - Output validation using Zod schemas
11
- - Full Python 3 standard library support
12
- - Access to installed packages (requests, etc.)
13
-
14
- ## Basic Usage
15
-
16
- ```typescript
17
- import { api, z, python } from "@superblocksteam/sdk-api";
18
-
19
- // Integration ID from the integrations panel
20
- const PYTHON_RUNTIME = "a1b2c3d4-5678-90ab-cdef-python00001";
21
-
22
- export default api({
23
- name: "PythonExample",
24
- integrations: {
25
- runtime: python(PYTHON_RUNTIME),
26
- },
27
- input: z.object({
28
- userId: z.string(),
29
- }),
30
-
31
- output: z.object({
32
- greeting: z.string(),
33
- timestamp: z.number(),
34
- }),
35
-
36
- async run(ctx, { userId }) {
37
- const result = await ctx.integrations.runtime.run(
38
- `
39
- import time
40
-
41
- # userId is available as a direct Python variable
42
- current_time = int(time.time())
43
-
44
- # Return a dictionary matching your output schema
45
- return {
46
- "greeting": f"Hello user {userId}!",
47
- "timestamp": current_time
48
- }
49
- `,
50
- z.object({
51
- greeting: z.string(),
52
- timestamp: z.number(),
53
- }),
54
- {
55
- userId,
56
- },
57
- );
58
-
59
- return result;
60
- },
61
- });
62
- ```
63
-
64
- ## API Reference
65
-
66
- ### `ctx.integrations.<name>.run<T>(code, schema, bindings?, metadata?): Promise<T>`
67
-
68
- Executes Python code with validated output. Use the **key name** you declared in `integrations` (e.g. `ctx.integrations.runtime.run(...)` if you declared `runtime: python(...)`).
69
-
70
- **Parameters:**
71
-
72
- - `code` (string): Python script to execute. Bindings are automatically injected as Python variables.
73
- - `schema` (ZodSchema<T>): **Required** Zod schema for validating the return value.
74
- - `bindings` (Record<string, unknown>, optional): Key/value pairs that become Python variables in your code. Do not pass `TraceMetadata` here; use the `metadata` parameter instead.
75
- - `metadata` (TraceMetadata, optional): Trace metadata for diagnostics labeling (see [Trace Metadata](#trace-metadata)).
76
-
77
- **Returns:** Promise resolving to validated result matching the schema.
78
-
79
- **Throws:** `CodeExecutionError` if execution fails or validation fails.
80
-
81
- **Important:** Your Python code must use a `return` statement to return a value.
82
-
83
- > **Note:** Because `bindings` and `metadata` are both plain objects, take care not
84
- > to pass metadata as the third argument. If you need metadata but no bindings,
85
- > pass `undefined` for `bindings` explicitly:
86
- >
87
- > ```typescript
88
- > await ctx.integrations.runtime.run(code, schema, undefined, {
89
- > label: "My trace label",
90
- > });
91
- > ```
92
-
93
- ## Binding Syntax
94
-
95
- Bindings are passed as a map and automatically injected as Python variables. Reference them directly in your code by their key names:
96
-
97
- ```typescript
98
- // In your run(): use the key you declared in integrations (e.g. runtime: python(...))
99
- const result = await ctx.integrations.runtime.run(
100
- `
101
- # Bindings are available as direct Python variables
102
- # No {{}} syntax needed - just use the variable names directly
103
- return {
104
- "message": f"{userName} is {userAge} years old",
105
- "active": isActive
106
- }
107
- `,
108
- z.object({
109
- message: z.string(),
110
- active: z.boolean(),
111
- }),
112
- {
113
- userName: "Alice",
114
- userAge: 30,
115
- isActive: true,
116
- },
117
- );
118
- ```
119
-
120
- The SDK automatically injects bindings as Python variables before your code executes, making them available for immediate use.
121
-
122
- ## Examples
123
-
124
- ### Data Transformation
125
-
126
- Transform data from another step or API:
127
-
128
- ```typescript
129
- // Transform user data (use ctx.integrations.runtime if you declared runtime: python(...))
130
- const transformed = await ctx.integrations.runtime.run(
131
- `
132
- import json
133
-
134
- users = {{userList}}
135
-
136
- # Filter and transform
137
- active_users = [
138
- {
139
- "id": u["id"],
140
- "email": u["email"],
141
- "displayName": f"{u['firstName']} {u['lastName']}"
142
- }
143
- for u in users
144
- if u["status"] == "active"
145
- ]
146
-
147
- return {"users": active_users, "count": len(active_users)}
148
- `,
149
- z.object({
150
- users: z.array(
151
- z.object({
152
- id: z.string(),
153
- email: z.string(),
154
- displayName: z.string(),
155
- }),
156
- ),
157
- count: z.number(),
158
- }),
159
- {
160
- userList: await getUsersFromDatabase(),
161
- },
162
- );
163
- ```
164
-
165
- ### HTTP Requests with Requests Library
166
-
167
- Make HTTP requests using the `requests` library:
168
-
169
- ```typescript
170
- const apiData = await ctx.integrations.runtime.run(
171
- `
172
- import requests
173
-
174
- api_url = {{apiUrl}}
175
- api_key = {{apiKey}}
176
-
177
- response = requests.get(
178
- api_url,
179
- headers={"Authorization": f"Bearer {api_key}"}
180
- )
181
-
182
- data = response.json()
183
-
184
- return {
185
- "status": response.status_code,
186
- "data": data
187
- }
188
- `,
189
- z.object({
190
- status: z.number(),
191
- data: z.any(),
192
- }),
193
- {
194
- apiUrl: "https://api.example.com/data",
195
- apiKey: ctx.env.API_KEY,
196
- },
197
- );
198
- ```
199
-
200
- ### Complex Data Processing
201
-
202
- Process and aggregate data:
203
-
204
- ```typescript
205
- const stats = await ctx.integrations.runtime.run(
206
- `
207
- import statistics
208
-
209
- values = {{values}}
210
-
211
- return {
212
- "mean": statistics.mean(values),
213
- "median": statistics.median(values),
214
- "stdev": statistics.stdev(values),
215
- "min": min(values),
216
- "max": max(values)
217
- }
218
- `,
219
- z.object({
220
- mean: z.number(),
221
- median: z.number(),
222
- stdev: z.number(),
223
- min: z.number(),
224
- max: z.number(),
225
- }),
226
- {
227
- values: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10],
228
- },
229
- );
230
- ```
231
-
232
- ### Combining with Database Queries
233
-
234
- Use Python to process database results:
235
-
236
- ```typescript
237
- import { api, z, postgres, python } from "@superblocksteam/sdk-api";
238
-
239
- const PROD_POSTGRES = "a1b2c3d4-5678-90ab-cdef-postgres01";
240
- const PYTHON_RUNTIME = "a1b2c3d4-5678-90ab-cdef-python00001";
241
-
242
- export default api({
243
- name: "PythonExample",
244
- integrations: {
245
- db: postgres(PROD_POSTGRES),
246
- runtime: python(PYTHON_RUNTIME),
247
- },
248
- input: z.object({
249
- startDate: z.string(),
250
- endDate: z.string(),
251
- }),
252
-
253
- output: z.object({
254
- summary: z.string(),
255
- totalSales: z.number(),
256
- topProducts: z.array(z.string()),
257
- }),
258
-
259
- async run(ctx, { startDate, endDate }) {
260
- // Query database via ctx.integrations.db
261
- const sales = await ctx.integrations.db.query(
262
- `SELECT product_id, product_name, amount
263
- FROM sales
264
- WHERE sale_date BETWEEN $1 AND $2`,
265
- z.object({
266
- product_id: z.string(),
267
- product_name: z.string(),
268
- amount: z.number(),
269
- }),
270
- [startDate, endDate],
271
- );
272
-
273
- // Process with Python via ctx.integrations.runtime
274
- const analysis = await ctx.integrations.runtime.run(
275
- `
276
- sales_data = {{salesData}}
277
-
278
- # Group by product
279
- from collections import defaultdict
280
- product_totals = defaultdict(float)
281
-
282
- for sale in sales_data:
283
- product_totals[sale["product_name"]] += sale["amount"]
284
-
285
- # Get top products
286
- sorted_products = sorted(
287
- product_totals.items(),
288
- key=lambda x: x[1],
289
- reverse=True
290
- )
291
- top_5 = [p[0] for p in sorted_products[:5]]
292
-
293
- total = sum(product_totals.values())
294
-
295
- return {
296
- "summary": f"Analyzed {len(sales_data)} sales across {len(product_totals)} products",
297
- "totalSales": total,
298
- "topProducts": top_5
299
- }
300
- `,
301
- z.object({
302
- summary: z.string(),
303
- totalSales: z.number(),
304
- topProducts: z.array(z.string()),
305
- }),
306
- {
307
- salesData: sales,
308
- },
309
- );
310
-
311
- return analysis;
312
- },
313
- });
314
- ```
315
-
316
- ## Trace Metadata
317
-
318
- 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.
319
-
320
- ## Error Handling
321
-
322
- The client throws `CodeExecutionError` when execution or validation fails:
323
-
324
- ```typescript
325
- import { CodeExecutionError } from "@superblocksteam/sdk-api";
326
-
327
- try {
328
- const result = await ctx.integrations.runtime.run(
329
- `
330
- x = {{value}}
331
- return {"result": x * 2}
332
- `,
333
- z.object({ result: z.number() }),
334
- { value: 10 },
335
- );
336
- } catch (error) {
337
- if (error instanceof CodeExecutionError) {
338
- console.error("Python execution failed:", error.message);
339
-
340
- if (error.details?.zodError) {
341
- // Validation error - result didn't match schema
342
- console.error("Validation errors:", error.details.zodError.issues);
343
- console.error("Actual result:", error.details.result);
344
- } else if (error.details?.originalError) {
345
- // Runtime error in Python code
346
- console.error("Python error:", error.details.originalError);
347
- }
348
- }
349
- }
350
- ```
351
-
352
- ## Common Patterns
353
-
354
- ### Environment Variables
355
-
356
- Access environment variables in Python:
357
-
358
- ```typescript
359
- const result = await ctx.integrations.runtime.run(
360
- `
361
- # apiKey and environment are directly available as Python variables
362
- return {
363
- "configured": apiKey is not None,
364
- "environment": environment
365
- }
366
- `,
367
- z.object({
368
- configured: z.boolean(),
369
- environment: z.string(),
370
- }),
371
- {
372
- apiKey: ctx.env.API_KEY,
373
- environment: ctx.env.NODE_ENV,
374
- },
375
- );
376
- ```
377
-
378
- ### JSON Processing
379
-
380
- Work with JSON data:
381
-
382
- ```typescript
383
- const processed = await ctx.integrations.runtime.run(
384
- `
385
- import json
386
-
387
- json_str = {{jsonString}}
388
- data = json.loads(json_str)
389
-
390
- # Modify data
391
- data["processed"] = True
392
- data["timestamp"] = 1234567890
393
-
394
- return {"result": json.dumps(data)}
395
- `,
396
- z.object({
397
- result: z.string(),
398
- }),
399
- {
400
- jsonString: JSON.stringify({ foo: "bar" }),
401
- },
402
- );
403
- ```
404
-
405
- ## Best Practices
406
-
407
- ### 1. Keep Python Code Focused
408
-
409
- Python steps should perform data transformation and processing. Use integration clients for I/O operations:
410
-
411
- ✅ **Good:**
412
-
413
- ```typescript
414
- // Fetch data with integration client
415
- const data = await postgres.query(...);
416
-
417
- // Transform with Python
418
- const processed = await ctx.integrations.runtime.run(`...transform logic...`, schema, { data });
419
- ```
420
-
421
- ❌ **Avoid:**
422
-
423
- ```typescript
424
- // Don't make database connections in Python
425
- await ctx.integrations.runtime.run(
426
- `
427
- import psycopg2
428
- conn = psycopg2.connect(...) # Avoid this
429
- ...
430
- `,
431
- schema,
432
- );
433
- ```
434
-
435
- ### 2. Validate All Inputs and Outputs
436
-
437
- Always provide a schema to validate Python return values:
438
-
439
- ✅ **Good:**
440
-
441
- ```typescript
442
- const result = await ctx.integrations.runtime.run(
443
- code,
444
- z.object({
445
- value: z.number(),
446
- message: z.string(),
447
- }),
448
- bindings,
449
- );
450
- ```
451
-
452
- ❌ **Avoid:**
453
-
454
- ```typescript
455
- // Missing schema - no type safety!
456
- const result = await ctx.integrations.runtime.run(code, z.any(), bindings);
457
- ```
458
-
459
- ### 3. Use Meaningful Binding Names
460
-
461
- Choose clear binding names that match Python conventions:
462
-
463
- ✅ **Good:**
464
-
465
- ```typescript
466
- {
467
- user_id: "123",
468
- start_date: "2024-01-01",
469
- is_active: true
470
- }
471
- ```
472
-
473
- ❌ **Avoid:**
474
-
475
- ```typescript
476
- {
477
- userId: "123", // Mixing camelCase in Python
478
- StartDate: "...", // PascalCase doesn't fit Python
479
- }
480
- ```
481
-
482
- ### 4. Handle Errors Gracefully
483
-
484
- Use try/catch and check for specific error types:
485
-
486
- ```typescript
487
- try {
488
- const result = await ctx.integrations.runtime.run(code, schema, bindings);
489
- return result;
490
- } catch (error) {
491
- if (error instanceof CodeExecutionError) {
492
- ctx.log.error("Python execution failed", {
493
- code: error.details?.code,
494
- bindings: error.details?.bindings,
495
- });
496
- // Provide fallback or rethrow
497
- throw new Error("Data processing failed");
498
- }
499
- throw error;
500
- }
501
- ```
502
-
503
- ## Troubleshooting
504
-
505
- ### "Python execution result validation failed"
506
-
507
- The return value from your Python code doesn't match the provided schema.
508
-
509
- **Solution:** Check that your Python `return` statement matches the schema exactly:
510
-
511
- ```typescript
512
- // Schema expects
513
- z.object({ count: z.number(), items: z.array(z.string()) });
514
-
515
- // Python must return
516
- return { count: 5, items: ["a", "b", "c"] };
517
- ```
518
-
519
- ### "Python execution failed"
520
-
521
- The Python code had a runtime error.
522
-
523
- **Common causes:**
524
-
525
- - Syntax errors in Python code
526
- - Undefined variables or bindings
527
- - Import errors for unavailable packages
528
- - Division by zero or other runtime exceptions
529
-
530
- **Solution:** Test Python code snippets independently, check that all `{{}}` bindings are provided.
531
-
532
- ### Missing Binding Values
533
-
534
- If a binding is `undefined` or `null`, the orchestrator may handle it differently.
535
-
536
- **Solution:** Always provide explicit values for bindings:
537
-
538
- ```typescript
539
- // In your run function with destructured input:
540
- async run(ctx, { value, name }) {
541
- const result = await ctx.integrations.runtime.run(
542
- code,
543
- schema,
544
- {
545
- value: value ?? 0, // Provide default
546
- name: name || "Unknown"
547
- }
548
- );
549
- }
550
- ```
551
-
552
- ## Available Python Packages
553
-
554
- The Python runtime includes:
555
-
556
- - Python 3.x standard library
557
- - `requests` - HTTP library
558
- - Common data science packages (check with your Superblocks administrator for the full list)
559
-
560
- For specific package requirements, consult your Superblocks environment documentation.
561
-
562
- ## See Also
563
-
564
- - [API Reference](../../../README.md) - Main SDK documentation
565
- - [Error Handling](../../../README.md#error-handling) - Error types and handling strategies
566
- - [Best Practices](../../../README.md#best-practices) - General SDK best practices