@superblocksteam/sdk-api 2.0.103 → 2.0.104-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.
- package/README.md +58 -299
- package/dist/api/definition.js +1 -1
- package/dist/api/definition.js.map +1 -1
- package/dist/api/index.d.ts +0 -2
- package/dist/api/index.d.ts.map +1 -1
- package/dist/api/index.js +0 -2
- package/dist/api/index.js.map +1 -1
- package/dist/errors.d.ts +0 -44
- package/dist/errors.d.ts.map +1 -1
- package/dist/errors.js +0 -32
- package/dist/errors.js.map +1 -1
- package/dist/index.d.ts +5 -5
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5 -9
- package/dist/index.js.map +1 -1
- package/dist/integrations/anthropic/types.d.ts +3 -22
- package/dist/integrations/anthropic/types.d.ts.map +1 -1
- package/dist/integrations/athena/types.d.ts +2 -2
- package/dist/integrations/base/index.d.ts +1 -1
- package/dist/integrations/base/index.d.ts.map +1 -1
- package/dist/integrations/base/rest-api-integration-client.d.ts +4 -48
- package/dist/integrations/base/rest-api-integration-client.d.ts.map +1 -1
- package/dist/integrations/base/rest-api-integration-client.js +2 -110
- package/dist/integrations/base/rest-api-integration-client.js.map +1 -1
- package/dist/integrations/base/types.d.ts +1 -67
- package/dist/integrations/base/types.d.ts.map +1 -1
- package/dist/integrations/bigquery/types.d.ts +3 -3
- package/dist/integrations/databricks/types.d.ts +3 -3
- package/dist/integrations/documentation.test.d.ts +2 -0
- package/dist/integrations/documentation.test.d.ts.map +1 -0
- package/dist/integrations/documentation.test.js +83 -0
- package/dist/integrations/documentation.test.js.map +1 -0
- package/dist/integrations/index.d.ts +1 -1
- package/dist/integrations/index.d.ts.map +1 -1
- package/dist/integrations/index.js.map +1 -1
- package/dist/integrations/lakebase/types.d.ts +4 -4
- package/dist/integrations/mariadb/types.d.ts +2 -2
- package/dist/integrations/mssql/types.d.ts +2 -2
- package/dist/integrations/mysql/types.d.ts +4 -4
- package/dist/integrations/openai_v2/types.d.ts +4 -22
- package/dist/integrations/openai_v2/types.d.ts.map +1 -1
- package/dist/integrations/oracledb/types.d.ts +2 -2
- package/dist/integrations/registry.d.ts +0 -16
- package/dist/integrations/registry.d.ts.map +1 -1
- package/dist/integrations/registry.js +38 -38
- package/dist/integrations/registry.js.map +1 -1
- package/dist/integrations/registry.test.js +1 -3
- package/dist/integrations/registry.test.js.map +1 -1
- package/dist/integrations/restapiintegration/types.d.ts +2 -2
- package/dist/integrations/restapiintegration/types.d.ts.map +1 -1
- package/dist/integrations/snowflakecortex/client.d.ts +1 -2
- package/dist/integrations/snowflakecortex/client.d.ts.map +1 -1
- package/dist/integrations/snowflakecortex/client.js +1 -2
- package/dist/integrations/snowflakecortex/client.js.map +1 -1
- package/dist/integrations/snowflakecortex/types.d.ts +3 -4
- package/dist/integrations/snowflakecortex/types.d.ts.map +1 -1
- package/dist/runtime/index.d.ts +0 -3
- package/dist/runtime/index.d.ts.map +1 -1
- package/dist/runtime/index.js +1 -6
- package/dist/runtime/index.js.map +1 -1
- package/package.json +1 -1
- package/src/api/definition.ts +1 -1
- package/src/api/index.ts +0 -4
- package/src/errors.ts +0 -48
- package/src/index.ts +2 -28
- package/src/integrations/anthropic/README.md +5 -101
- package/src/integrations/anthropic/types.ts +3 -29
- package/src/integrations/athena/README.md +4 -4
- package/src/integrations/athena/types.ts +2 -2
- package/src/integrations/base/index.ts +0 -2
- package/src/integrations/base/rest-api-integration-client.ts +4 -153
- package/src/integrations/base/types.ts +3 -74
- package/src/integrations/bigquery/README.md +28 -3
- package/src/integrations/bigquery/types.ts +3 -3
- package/src/integrations/cohere/README.md +11 -11
- package/src/integrations/databricks/README.md +29 -4
- package/src/integrations/databricks/types.ts +3 -3
- package/src/integrations/documentation.test.ts +122 -0
- package/src/integrations/fireworks/README.md +43 -17
- package/src/integrations/googleanalytics/README.md +2 -2
- package/src/integrations/googledrive/README.md +2 -2
- package/src/integrations/groq/README.md +41 -34
- package/src/integrations/gsheets/README.md +2 -2
- package/src/integrations/index.ts +0 -1
- package/src/integrations/lakebase/types.ts +4 -4
- package/src/integrations/launchdarkly/README.md +2 -2
- package/src/integrations/mariadb/README.md +3 -3
- package/src/integrations/mariadb/types.ts +2 -2
- package/src/integrations/mistral/README.md +39 -13
- package/src/integrations/mssql/README.md +3 -3
- package/src/integrations/mssql/types.ts +2 -2
- package/src/integrations/mysql/README.md +4 -4
- package/src/integrations/mysql/types.ts +4 -4
- package/src/integrations/openai_v2/README.md +44 -116
- package/src/integrations/openai_v2/types.ts +4 -29
- package/src/integrations/oracledb/README.md +3 -3
- package/src/integrations/oracledb/types.ts +2 -2
- package/src/integrations/pagerduty/README.md +2 -2
- package/src/integrations/perplexity/README.md +2 -1
- package/src/integrations/registry.test.ts +1 -3
- package/src/integrations/registry.ts +38 -127
- package/src/integrations/restapiintegration/README.md +4 -43
- package/src/integrations/restapiintegration/types.ts +2 -8
- package/src/integrations/sendgrid/README.md +2 -2
- package/src/integrations/snowflakecortex/README.md +4 -53
- package/src/integrations/snowflakecortex/client.ts +2 -3
- package/src/integrations/snowflakecortex/types.ts +3 -11
- package/src/integrations/stabilityai/README.md +2 -2
- package/src/runtime/index.ts +1 -23
- package/dist/api/streaming.d.ts +0 -229
- package/dist/api/streaming.d.ts.map +0 -1
- package/dist/api/streaming.js +0 -107
- package/dist/api/streaming.js.map +0 -1
- package/dist/api/streaming.test.d.ts +0 -5
- package/dist/api/streaming.test.d.ts.map +0 -1
- package/dist/api/streaming.test.js +0 -364
- package/dist/api/streaming.test.js.map +0 -1
- package/dist/runtime/execute.d.ts +0 -128
- package/dist/runtime/execute.d.ts.map +0 -1
- package/dist/runtime/execute.js +0 -84
- package/dist/runtime/execute.js.map +0 -1
- package/dist/runtime/streaming-context.d.ts +0 -49
- package/dist/runtime/streaming-context.d.ts.map +0 -1
- package/dist/runtime/streaming-context.js +0 -71
- package/dist/runtime/streaming-context.js.map +0 -1
- package/dist/runtime/streaming-executor.d.ts +0 -159
- package/dist/runtime/streaming-executor.d.ts.map +0 -1
- package/dist/runtime/streaming-executor.js +0 -229
- package/dist/runtime/streaming-executor.js.map +0 -1
- package/src/api/streaming.test.ts +0 -433
- package/src/api/streaming.ts +0 -303
- package/src/runtime/execute.ts +0 -221
- package/src/runtime/streaming-context.ts +0 -164
- package/src/runtime/streaming-executor.ts +0 -367
|
@@ -6,6 +6,9 @@ import type { z } from "zod";
|
|
|
6
6
|
|
|
7
7
|
import type { TraceMetadata } from "../registry.js";
|
|
8
8
|
|
|
9
|
+
// Re-export for backwards compatibility
|
|
10
|
+
export type { TraceMetadata };
|
|
11
|
+
|
|
9
12
|
/**
|
|
10
13
|
* Options for making a generic REST API request.
|
|
11
14
|
*/
|
|
@@ -101,77 +104,3 @@ export interface SupportsApiRequest {
|
|
|
101
104
|
metadata?: TraceMetadata,
|
|
102
105
|
): Promise<TResponse>;
|
|
103
106
|
}
|
|
104
|
-
|
|
105
|
-
/**
|
|
106
|
-
* Schema configuration for streaming API request validation.
|
|
107
|
-
*/
|
|
108
|
-
export interface StreamApiRequestSchema<TBody = unknown, TChunk = unknown> {
|
|
109
|
-
/**
|
|
110
|
-
* Optional Zod schema for request body validation.
|
|
111
|
-
* Required if body is provided in options.
|
|
112
|
-
*/
|
|
113
|
-
body?: z.ZodSchema<TBody>;
|
|
114
|
-
|
|
115
|
-
/**
|
|
116
|
-
* Zod schema for validating each streamed chunk.
|
|
117
|
-
*
|
|
118
|
-
* Every chunk received from the stream is validated against this schema.
|
|
119
|
-
* Validation errors will terminate the stream.
|
|
120
|
-
*/
|
|
121
|
-
chunk: z.ZodSchema<TChunk>;
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
/**
|
|
125
|
-
* Interface for integration clients that support streaming API requests.
|
|
126
|
-
*
|
|
127
|
-
* Streaming API requests return an AsyncIterable of validated chunks,
|
|
128
|
-
* enabling real-time data streaming from LLMs and other sources.
|
|
129
|
-
*/
|
|
130
|
-
export interface SupportsStreamingApiRequest {
|
|
131
|
-
/**
|
|
132
|
-
* Execute a streaming API request with type-safe chunk validation.
|
|
133
|
-
*
|
|
134
|
-
* Returns an AsyncIterable that yields validated chunks as they arrive.
|
|
135
|
-
* Each chunk is validated against the provided schema before being yielded.
|
|
136
|
-
*
|
|
137
|
-
* @param options - Request configuration including method, path, params, and body
|
|
138
|
-
* @param schema - Zod schemas for request body and chunk validation (chunk schema REQUIRED)
|
|
139
|
-
* @param metadata - Optional trace metadata for observability (label, description)
|
|
140
|
-
* @returns AsyncIterable yielding validated chunks
|
|
141
|
-
*
|
|
142
|
-
* @example
|
|
143
|
-
* ```typescript
|
|
144
|
-
* const ChunkSchema = z.object({
|
|
145
|
-
* id: z.string(),
|
|
146
|
-
* choices: z.array(z.object({
|
|
147
|
-
* delta: z.object({
|
|
148
|
-
* content: z.string().optional(),
|
|
149
|
-
* }),
|
|
150
|
-
* })),
|
|
151
|
-
* });
|
|
152
|
-
*
|
|
153
|
-
* const stream = client.streamApiRequest(
|
|
154
|
-
* {
|
|
155
|
-
* method: 'POST',
|
|
156
|
-
* path: '/v1/chat/completions',
|
|
157
|
-
* body: {
|
|
158
|
-
* model: 'gpt-4',
|
|
159
|
-
* stream: true,
|
|
160
|
-
* messages: [{ role: 'user', content: 'Hello!' }],
|
|
161
|
-
* },
|
|
162
|
-
* },
|
|
163
|
-
* { chunk: ChunkSchema },
|
|
164
|
-
* { label: 'openai.chatCompletions', description: 'Stream chat completion' }
|
|
165
|
-
* );
|
|
166
|
-
*
|
|
167
|
-
* for await (const chunk of stream) {
|
|
168
|
-
* console.log(chunk.choices[0]?.delta?.content);
|
|
169
|
-
* }
|
|
170
|
-
* ```
|
|
171
|
-
*/
|
|
172
|
-
streamApiRequest<TBody, TChunk>(
|
|
173
|
-
options: ApiRequestOptions<TBody>,
|
|
174
|
-
schema: StreamApiRequestSchema<TBody, TChunk>,
|
|
175
|
-
metadata?: TraceMetadata,
|
|
176
|
-
): AsyncIterable<TChunk>;
|
|
177
|
-
}
|
|
@@ -40,7 +40,7 @@ export default api({
|
|
|
40
40
|
const events = await ctx.integrations.bigquery.query(
|
|
41
41
|
`SELECT event_id, event_name, user_id, timestamp
|
|
42
42
|
FROM \`project.dataset.events\`
|
|
43
|
-
WHERE event_name =
|
|
43
|
+
WHERE event_name = ?
|
|
44
44
|
LIMIT 100`,
|
|
45
45
|
EventSchema,
|
|
46
46
|
[event_name],
|
|
@@ -51,12 +51,16 @@ export default api({
|
|
|
51
51
|
});
|
|
52
52
|
```
|
|
53
53
|
|
|
54
|
+
The SDK currently binds BigQuery parameters from the positional `params` array.
|
|
55
|
+
Even though native BigQuery also supports named parameters like `@event_name`,
|
|
56
|
+
use `?` placeholders in SDK queries and pass values in array order.
|
|
57
|
+
|
|
54
58
|
### Executing INSERT, UPDATE, DELETE Statements
|
|
55
59
|
|
|
56
60
|
```typescript
|
|
57
61
|
// INSERT
|
|
58
62
|
await ctx.integrations.bigquery.execute(
|
|
59
|
-
"INSERT INTO `project.dataset.metrics` (name, value, timestamp) VALUES (
|
|
63
|
+
"INSERT INTO `project.dataset.metrics` (name, value, timestamp) VALUES (?, ?, CURRENT_TIMESTAMP())",
|
|
60
64
|
["cpu_usage", "75.5"],
|
|
61
65
|
);
|
|
62
66
|
```
|
|
@@ -116,6 +120,27 @@ All methods accept an optional `metadata` parameter as the last argument for dia
|
|
|
116
120
|
|
|
117
121
|
## Common Pitfalls
|
|
118
122
|
|
|
123
|
+
### SDK Parameters Are Positional
|
|
124
|
+
|
|
125
|
+
The SDK accepts an array of parameter values and binds them server-side in
|
|
126
|
+
order. When you need parameters, use `?` placeholders in the SQL text:
|
|
127
|
+
|
|
128
|
+
```typescript
|
|
129
|
+
// WRONG - Native BigQuery named parameter syntax is not the SDK contract
|
|
130
|
+
await ctx.integrations.bigquery.query(
|
|
131
|
+
"SELECT * FROM `project.dataset.events` WHERE event_name = @event_name",
|
|
132
|
+
EventSchema,
|
|
133
|
+
["signup"],
|
|
134
|
+
);
|
|
135
|
+
|
|
136
|
+
// CORRECT - Use positional params with ? placeholders
|
|
137
|
+
await ctx.integrations.bigquery.query(
|
|
138
|
+
"SELECT * FROM `project.dataset.events` WHERE event_name = ?",
|
|
139
|
+
EventSchema,
|
|
140
|
+
["signup"],
|
|
141
|
+
);
|
|
142
|
+
```
|
|
143
|
+
|
|
119
144
|
### Backtick Table References
|
|
120
145
|
|
|
121
146
|
BigQuery uses backticks for fully-qualified table names:
|
|
@@ -165,7 +190,7 @@ BigQuery charges by data scanned. Use partitions and column selection:
|
|
|
165
190
|
const query = `
|
|
166
191
|
SELECT event_id, event_name
|
|
167
192
|
FROM \`project.dataset.events\`
|
|
168
|
-
WHERE _PARTITIONDATE =
|
|
193
|
+
WHERE _PARTITIONDATE = ?
|
|
169
194
|
`;
|
|
170
195
|
```
|
|
171
196
|
|
|
@@ -25,7 +25,7 @@ import type { TraceMetadata } from "../registry.js";
|
|
|
25
25
|
* });
|
|
26
26
|
*
|
|
27
27
|
* const events = await bigquery.query(
|
|
28
|
-
* 'SELECT * FROM events WHERE date =
|
|
28
|
+
* 'SELECT * FROM events WHERE date = ?',
|
|
29
29
|
* EventSchema,
|
|
30
30
|
* ['2024-01-01']
|
|
31
31
|
* );
|
|
@@ -35,9 +35,9 @@ export interface BigQueryClient extends BaseIntegrationClient {
|
|
|
35
35
|
/**
|
|
36
36
|
* Execute a SQL query and validate results against a Zod schema.
|
|
37
37
|
*
|
|
38
|
-
* @param sql - SQL query string (use
|
|
38
|
+
* @param sql - SQL query string (use ? placeholders for parameters)
|
|
39
39
|
* @param schema - Zod schema to validate the query results
|
|
40
|
-
* @param params - Optional query parameters
|
|
40
|
+
* @param params - Optional query parameters, bound positionally from the provided array
|
|
41
41
|
* @returns Promise resolving to validated query results
|
|
42
42
|
*
|
|
43
43
|
* @throws {QueryValidationError} If results don't match schema
|
|
@@ -52,7 +52,7 @@ export default api({
|
|
|
52
52
|
const result = await ctx.integrations.cohere.apiRequest(
|
|
53
53
|
{
|
|
54
54
|
method: "POST",
|
|
55
|
-
path: "/
|
|
55
|
+
path: "/chat",
|
|
56
56
|
body: {
|
|
57
57
|
model: "command-r-plus",
|
|
58
58
|
message: message,
|
|
@@ -81,7 +81,7 @@ const EmbedResponseSchema = z.object({
|
|
|
81
81
|
const result = await ctx.integrations.cohere.apiRequest(
|
|
82
82
|
{
|
|
83
83
|
method: "POST",
|
|
84
|
-
path: "/
|
|
84
|
+
path: "/embed",
|
|
85
85
|
body: {
|
|
86
86
|
model: "embed-english-v3.0",
|
|
87
87
|
texts: ["Hello world", "How are you?"],
|
|
@@ -115,7 +115,7 @@ const ClassifyResponseSchema = z.object({
|
|
|
115
115
|
const result = await ctx.integrations.cohere.apiRequest(
|
|
116
116
|
{
|
|
117
117
|
method: "POST",
|
|
118
|
-
path: "/
|
|
118
|
+
path: "/classify",
|
|
119
119
|
body: {
|
|
120
120
|
model: "embed-english-v3.0",
|
|
121
121
|
inputs: ["This product is amazing!", "Terrible experience, never again"],
|
|
@@ -159,7 +159,7 @@ const documents = [
|
|
|
159
159
|
const result = await ctx.integrations.cohere.apiRequest(
|
|
160
160
|
{
|
|
161
161
|
method: "POST",
|
|
162
|
-
path: "/
|
|
162
|
+
path: "/rerank",
|
|
163
163
|
body: {
|
|
164
164
|
model: "rerank-english-v3.0",
|
|
165
165
|
query: "What is the capital of the United States?",
|
|
@@ -193,7 +193,7 @@ const GenerateResponseSchema = z.object({
|
|
|
193
193
|
const result = await ctx.integrations.cohere.apiRequest(
|
|
194
194
|
{
|
|
195
195
|
method: "POST",
|
|
196
|
-
path: "/
|
|
196
|
+
path: "/generate",
|
|
197
197
|
body: {
|
|
198
198
|
model: "command",
|
|
199
199
|
prompt: "Write a creative story about",
|
|
@@ -220,7 +220,7 @@ await cohere.embed({ ... });
|
|
|
220
220
|
|
|
221
221
|
// CORRECT - Use apiRequest
|
|
222
222
|
await ctx.integrations.cohere.apiRequest(
|
|
223
|
-
{ method: "POST", path: "/
|
|
223
|
+
{ method: "POST", path: "/chat", body: { ... } },
|
|
224
224
|
{ response: ChatResponseSchema }
|
|
225
225
|
);
|
|
226
226
|
```
|
|
@@ -234,7 +234,7 @@ When creating embeddings, specify the correct `input_type`:
|
|
|
234
234
|
const docEmbeddings = await ctx.integrations.cohere.apiRequest(
|
|
235
235
|
{
|
|
236
236
|
method: "POST",
|
|
237
|
-
path: "/
|
|
237
|
+
path: "/embed",
|
|
238
238
|
body: {
|
|
239
239
|
texts: documents,
|
|
240
240
|
input_type: "search_document", // For documents
|
|
@@ -247,7 +247,7 @@ const docEmbeddings = await ctx.integrations.cohere.apiRequest(
|
|
|
247
247
|
const queryEmbedding = await ctx.integrations.cohere.apiRequest(
|
|
248
248
|
{
|
|
249
249
|
method: "POST",
|
|
250
|
-
path: "/
|
|
250
|
+
path: "/embed",
|
|
251
251
|
body: {
|
|
252
252
|
texts: [query],
|
|
253
253
|
input_type: "search_query", // For queries
|
|
@@ -266,7 +266,7 @@ The classify endpoint requires labeled examples:
|
|
|
266
266
|
const result = await ctx.integrations.cohere.apiRequest(
|
|
267
267
|
{
|
|
268
268
|
method: "POST",
|
|
269
|
-
path: "/
|
|
269
|
+
path: "/classify",
|
|
270
270
|
body: {
|
|
271
271
|
inputs: ["Great product!"],
|
|
272
272
|
// Missing examples!
|
|
@@ -279,7 +279,7 @@ const result = await ctx.integrations.cohere.apiRequest(
|
|
|
279
279
|
const result = await ctx.integrations.cohere.apiRequest(
|
|
280
280
|
{
|
|
281
281
|
method: "POST",
|
|
282
|
-
path: "/
|
|
282
|
+
path: "/classify",
|
|
283
283
|
body: {
|
|
284
284
|
inputs: ["Great product!"],
|
|
285
285
|
examples: [
|
|
@@ -299,7 +299,7 @@ import { RestApiValidationError } from "@superblocksteam/sdk-api";
|
|
|
299
299
|
|
|
300
300
|
try {
|
|
301
301
|
const result = await ctx.integrations.cohere.apiRequest(
|
|
302
|
-
{ method: "POST", path: "/
|
|
302
|
+
{ method: "POST", path: "/chat", body: { ... } },
|
|
303
303
|
{ response: ChatResponseSchema }
|
|
304
304
|
);
|
|
305
305
|
} catch (error) {
|
|
@@ -38,7 +38,7 @@ export default api({
|
|
|
38
38
|
}),
|
|
39
39
|
async run(ctx, { date }) {
|
|
40
40
|
const data = await ctx.integrations.databricks.query(
|
|
41
|
-
"SELECT id, value, timestamp FROM data WHERE date =
|
|
41
|
+
"SELECT id, value, timestamp FROM data WHERE date = :PARAM_1",
|
|
42
42
|
DataSchema,
|
|
43
43
|
[date],
|
|
44
44
|
);
|
|
@@ -48,25 +48,29 @@ export default api({
|
|
|
48
48
|
});
|
|
49
49
|
```
|
|
50
50
|
|
|
51
|
+
The SDK accepts Databricks parameters as a positional `params` array, but the
|
|
52
|
+
SQL text should use `:PARAM_1`, `:PARAM_2`, and so on. The first array value
|
|
53
|
+
binds to `:PARAM_1`, the second binds to `:PARAM_2`, and so forth.
|
|
54
|
+
|
|
51
55
|
### Executing INSERT, UPDATE, DELETE Statements
|
|
52
56
|
|
|
53
57
|
```typescript
|
|
54
58
|
// INSERT
|
|
55
59
|
await ctx.integrations.databricks.execute(
|
|
56
|
-
"INSERT INTO metrics (name, value) VALUES (
|
|
60
|
+
"INSERT INTO metrics (name, value) VALUES (:PARAM_1, :PARAM_2)",
|
|
57
61
|
["cpu_usage", "75.5"],
|
|
58
62
|
);
|
|
59
63
|
|
|
60
64
|
// UPDATE
|
|
61
65
|
const updateResult = await ctx.integrations.databricks.execute(
|
|
62
|
-
"UPDATE metrics SET value =
|
|
66
|
+
"UPDATE metrics SET value = :PARAM_1 WHERE name = :PARAM_2",
|
|
63
67
|
["80.0", "cpu_usage"],
|
|
64
68
|
);
|
|
65
69
|
console.log(`Updated ${updateResult.rowCount} rows`);
|
|
66
70
|
|
|
67
71
|
// DELETE
|
|
68
72
|
const deleteResult = await ctx.integrations.databricks.execute(
|
|
69
|
-
"DELETE FROM metrics WHERE timestamp <
|
|
73
|
+
"DELETE FROM metrics WHERE timestamp < :PARAM_1",
|
|
70
74
|
["2024-01-01"],
|
|
71
75
|
);
|
|
72
76
|
console.log(`Deleted ${deleteResult.rowCount} rows`);
|
|
@@ -100,6 +104,27 @@ All methods accept an optional `metadata` parameter as the last argument for dia
|
|
|
100
104
|
|
|
101
105
|
## Common Pitfalls
|
|
102
106
|
|
|
107
|
+
### Parameter Placeholders Must Match the SDK Contract
|
|
108
|
+
|
|
109
|
+
Pass parameter values as an array, but write the SQL with `:PARAM_n`
|
|
110
|
+
placeholders:
|
|
111
|
+
|
|
112
|
+
```typescript
|
|
113
|
+
// WRONG - Positional question marks are not the placeholder syntax this SDK emits
|
|
114
|
+
await ctx.integrations.databricks.query(
|
|
115
|
+
"SELECT * FROM data WHERE date = ?",
|
|
116
|
+
DataSchema,
|
|
117
|
+
["2024-01-01"],
|
|
118
|
+
);
|
|
119
|
+
|
|
120
|
+
// CORRECT - Use Databricks placeholders with positional params
|
|
121
|
+
await ctx.integrations.databricks.query(
|
|
122
|
+
"SELECT * FROM data WHERE date = :PARAM_1",
|
|
123
|
+
DataSchema,
|
|
124
|
+
["2024-01-01"],
|
|
125
|
+
);
|
|
126
|
+
```
|
|
127
|
+
|
|
103
128
|
### BIGINT/LONG Values Returned as Strings
|
|
104
129
|
|
|
105
130
|
```typescript
|
|
@@ -25,7 +25,7 @@ import type { TraceMetadata } from "../registry.js";
|
|
|
25
25
|
* });
|
|
26
26
|
*
|
|
27
27
|
* const data = await databricks.query(
|
|
28
|
-
* 'SELECT * FROM data WHERE date =
|
|
28
|
+
* 'SELECT * FROM data WHERE date = :PARAM_1',
|
|
29
29
|
* DataSchema,
|
|
30
30
|
* ['2024-01-01']
|
|
31
31
|
* );
|
|
@@ -35,9 +35,9 @@ export interface DatabricksClient extends BaseIntegrationClient {
|
|
|
35
35
|
/**
|
|
36
36
|
* Execute a SQL query and validate results against a Zod schema.
|
|
37
37
|
*
|
|
38
|
-
* @param sql - SQL query string (use
|
|
38
|
+
* @param sql - SQL query string (use :PARAM_1, :PARAM_2, etc. for parameters)
|
|
39
39
|
* @param schema - Zod schema to validate the query results
|
|
40
|
-
* @param params - Optional query parameters
|
|
40
|
+
* @param params - Optional query parameters, bound positionally so the first value maps to :PARAM_1
|
|
41
41
|
* @returns Promise resolving to validated query results
|
|
42
42
|
*
|
|
43
43
|
* @throws {QueryValidationError} If results don't match schema
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
import { existsSync, readFileSync, readdirSync } from "node:fs";
|
|
2
|
+
import { dirname, resolve } from "node:path";
|
|
3
|
+
import { fileURLToPath } from "node:url";
|
|
4
|
+
|
|
5
|
+
import { describe, expect, it } from "vitest";
|
|
6
|
+
|
|
7
|
+
import { SUPPORTED_PLUGINS } from "./registry.js";
|
|
8
|
+
|
|
9
|
+
const TEST_DIR = dirname(fileURLToPath(import.meta.url));
|
|
10
|
+
|
|
11
|
+
type PlaceholderDocsCase = {
|
|
12
|
+
integrationId: string;
|
|
13
|
+
expectedPlaceholder: string;
|
|
14
|
+
rejectsPostgresStyle?: boolean;
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
const DOC_DIRECTORY_ALIASES = {
|
|
18
|
+
confluent: "kafka",
|
|
19
|
+
graphqlintegration: "graphql",
|
|
20
|
+
redpanda: "kafka",
|
|
21
|
+
} as const;
|
|
22
|
+
|
|
23
|
+
const DOC_DIRECTORY_EXCLUSIONS = new Set(["base"]);
|
|
24
|
+
|
|
25
|
+
function hasDocDirectoryAlias(
|
|
26
|
+
pluginId: string,
|
|
27
|
+
): pluginId is keyof typeof DOC_DIRECTORY_ALIASES {
|
|
28
|
+
return pluginId in DOC_DIRECTORY_ALIASES;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
const EXPECTED_DOC_DIRECTORIES = Array.from(
|
|
32
|
+
new Set(
|
|
33
|
+
Object.values(SUPPORTED_PLUGINS)
|
|
34
|
+
.map((pluginId) =>
|
|
35
|
+
hasDocDirectoryAlias(pluginId)
|
|
36
|
+
? DOC_DIRECTORY_ALIASES[pluginId]
|
|
37
|
+
: pluginId,
|
|
38
|
+
)
|
|
39
|
+
.filter((directory) => !DOC_DIRECTORY_EXCLUSIONS.has(directory)),
|
|
40
|
+
),
|
|
41
|
+
).sort();
|
|
42
|
+
|
|
43
|
+
const ACTUAL_DOC_DIRECTORIES = readdirSync(TEST_DIR, { withFileTypes: true })
|
|
44
|
+
.filter((entry) => entry.isDirectory())
|
|
45
|
+
.map((entry) => entry.name)
|
|
46
|
+
.filter((directory) => !DOC_DIRECTORY_EXCLUSIONS.has(directory))
|
|
47
|
+
.sort();
|
|
48
|
+
|
|
49
|
+
const PLACEHOLDER_DOC_CASES: PlaceholderDocsCase[] = [
|
|
50
|
+
{ integrationId: "athena", expectedPlaceholder: "?" },
|
|
51
|
+
{ integrationId: "bigquery", expectedPlaceholder: "?" },
|
|
52
|
+
{
|
|
53
|
+
integrationId: "cockroachdb",
|
|
54
|
+
expectedPlaceholder: "$1",
|
|
55
|
+
rejectsPostgresStyle: false,
|
|
56
|
+
},
|
|
57
|
+
{ integrationId: "databricks", expectedPlaceholder: ":PARAM_1" },
|
|
58
|
+
{ integrationId: "dynamodb", expectedPlaceholder: "?" },
|
|
59
|
+
{
|
|
60
|
+
integrationId: "lakebase",
|
|
61
|
+
expectedPlaceholder: "$1",
|
|
62
|
+
rejectsPostgresStyle: false,
|
|
63
|
+
},
|
|
64
|
+
{ integrationId: "mariadb", expectedPlaceholder: "?" },
|
|
65
|
+
{ integrationId: "mssql", expectedPlaceholder: "@PARAM_1" },
|
|
66
|
+
{ integrationId: "mysql", expectedPlaceholder: "?" },
|
|
67
|
+
{ integrationId: "oracledb", expectedPlaceholder: ":1" },
|
|
68
|
+
{
|
|
69
|
+
integrationId: "redshift",
|
|
70
|
+
expectedPlaceholder: "$1",
|
|
71
|
+
rejectsPostgresStyle: false,
|
|
72
|
+
},
|
|
73
|
+
{ integrationId: "snowflake", expectedPlaceholder: "?" },
|
|
74
|
+
{
|
|
75
|
+
integrationId: "snowflakepostgres",
|
|
76
|
+
expectedPlaceholder: "$1",
|
|
77
|
+
rejectsPostgresStyle: false,
|
|
78
|
+
},
|
|
79
|
+
];
|
|
80
|
+
|
|
81
|
+
function readIntegrationFile(integrationId: string, fileName: string): string {
|
|
82
|
+
return readFileSync(resolve(TEST_DIR, integrationId, fileName), "utf8");
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
describe("SQL integration documentation", () => {
|
|
86
|
+
it("documents every supported integration directory", () => {
|
|
87
|
+
expect(ACTUAL_DOC_DIRECTORIES).toEqual(EXPECTED_DOC_DIRECTORIES);
|
|
88
|
+
|
|
89
|
+
for (const integrationId of EXPECTED_DOC_DIRECTORIES) {
|
|
90
|
+
expect(existsSync(resolve(TEST_DIR, integrationId, "README.md"))).toBe(
|
|
91
|
+
true,
|
|
92
|
+
);
|
|
93
|
+
expect(existsSync(resolve(TEST_DIR, integrationId, "types.ts"))).toBe(
|
|
94
|
+
true,
|
|
95
|
+
);
|
|
96
|
+
}
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
it.each(PLACEHOLDER_DOC_CASES)(
|
|
100
|
+
"$integrationId README uses $expectedPlaceholder placeholders",
|
|
101
|
+
({ integrationId, expectedPlaceholder, rejectsPostgresStyle = true }) => {
|
|
102
|
+
const readme = readIntegrationFile(integrationId, "README.md");
|
|
103
|
+
|
|
104
|
+
expect(readme).toContain(expectedPlaceholder);
|
|
105
|
+
if (rejectsPostgresStyle) {
|
|
106
|
+
expect(readme).not.toMatch(/\$\d+/);
|
|
107
|
+
}
|
|
108
|
+
},
|
|
109
|
+
);
|
|
110
|
+
|
|
111
|
+
it.each(PLACEHOLDER_DOC_CASES)(
|
|
112
|
+
"$integrationId JSDoc uses $expectedPlaceholder placeholders",
|
|
113
|
+
({ integrationId, expectedPlaceholder, rejectsPostgresStyle = true }) => {
|
|
114
|
+
const typeDocs = readIntegrationFile(integrationId, "types.ts");
|
|
115
|
+
|
|
116
|
+
expect(typeDocs).toContain(expectedPlaceholder);
|
|
117
|
+
if (rejectsPostgresStyle) {
|
|
118
|
+
expect(typeDocs).not.toMatch(/\$\d+/);
|
|
119
|
+
}
|
|
120
|
+
},
|
|
121
|
+
);
|
|
122
|
+
});
|
|
@@ -10,7 +10,9 @@ Interact with Fireworks AI's fast inference platform for LLM chat completions an
|
|
|
10
10
|
|
|
11
11
|
## Usage
|
|
12
12
|
|
|
13
|
-
###
|
|
13
|
+
### Step 1: List Available Models
|
|
14
|
+
|
|
15
|
+
Model availability varies by account. Before making requests, validate which models are deployed on your account:
|
|
14
16
|
|
|
15
17
|
```typescript
|
|
16
18
|
import { api, z, fireworks } from "@superblocksteam/sdk-api";
|
|
@@ -18,6 +20,30 @@ import { api, z, fireworks } from "@superblocksteam/sdk-api";
|
|
|
18
20
|
// Integration ID from the integrations panel
|
|
19
21
|
const PROD_FIREWORKS = "a1b2c3d4-5678-90ab-cdef-fireworks001";
|
|
20
22
|
|
|
23
|
+
const ModelsResponseSchema = z.object({
|
|
24
|
+
data: z.array(
|
|
25
|
+
z.object({
|
|
26
|
+
id: z.string(),
|
|
27
|
+
object: z.string(),
|
|
28
|
+
}),
|
|
29
|
+
),
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
const models = await ctx.integrations.fireworks.apiRequest(
|
|
33
|
+
{
|
|
34
|
+
method: "GET",
|
|
35
|
+
path: "/v1/models",
|
|
36
|
+
},
|
|
37
|
+
{ response: ModelsResponseSchema },
|
|
38
|
+
);
|
|
39
|
+
|
|
40
|
+
// Use a model ID from the response in subsequent requests
|
|
41
|
+
const availableModelId = models.data[0]?.id;
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
### Chat Completion
|
|
45
|
+
|
|
46
|
+
```typescript
|
|
21
47
|
const ChatCompletionResponseSchema = z.object({
|
|
22
48
|
id: z.string(),
|
|
23
49
|
object: z.string(),
|
|
@@ -55,7 +81,7 @@ export default api({
|
|
|
55
81
|
const result = await ctx.integrations.fireworks.apiRequest(
|
|
56
82
|
{
|
|
57
83
|
method: "POST",
|
|
58
|
-
path: "/
|
|
84
|
+
path: "/v1/chat/completions",
|
|
59
85
|
body: {
|
|
60
86
|
model: "accounts/fireworks/models/llama-v3p1-70b-instruct",
|
|
61
87
|
messages: [{ role: "user", content: prompt }],
|
|
@@ -76,7 +102,7 @@ export default api({
|
|
|
76
102
|
const llama70b = await ctx.integrations.fireworks.apiRequest(
|
|
77
103
|
{
|
|
78
104
|
method: "POST",
|
|
79
|
-
path: "/
|
|
105
|
+
path: "/v1/chat/completions",
|
|
80
106
|
body: {
|
|
81
107
|
model: "accounts/fireworks/models/llama-v3p1-70b-instruct",
|
|
82
108
|
messages: [{ role: "user", content: "Complex task..." }],
|
|
@@ -89,7 +115,7 @@ const llama70b = await ctx.integrations.fireworks.apiRequest(
|
|
|
89
115
|
const llama8b = await ctx.integrations.fireworks.apiRequest(
|
|
90
116
|
{
|
|
91
117
|
method: "POST",
|
|
92
|
-
path: "/
|
|
118
|
+
path: "/v1/chat/completions",
|
|
93
119
|
body: {
|
|
94
120
|
model: "accounts/fireworks/models/llama-v3p1-8b-instruct",
|
|
95
121
|
messages: [{ role: "user", content: "Simple task..." }],
|
|
@@ -102,7 +128,7 @@ const llama8b = await ctx.integrations.fireworks.apiRequest(
|
|
|
102
128
|
const mixtral = await ctx.integrations.fireworks.apiRequest(
|
|
103
129
|
{
|
|
104
130
|
method: "POST",
|
|
105
|
-
path: "/
|
|
131
|
+
path: "/v1/chat/completions",
|
|
106
132
|
body: {
|
|
107
133
|
model: "accounts/fireworks/models/mixtral-8x7b-instruct",
|
|
108
134
|
messages: [{ role: "user", content: "..." }],
|
|
@@ -115,7 +141,7 @@ const mixtral = await ctx.integrations.fireworks.apiRequest(
|
|
|
115
141
|
const qwen = await ctx.integrations.fireworks.apiRequest(
|
|
116
142
|
{
|
|
117
143
|
method: "POST",
|
|
118
|
-
path: "/
|
|
144
|
+
path: "/v1/chat/completions",
|
|
119
145
|
body: {
|
|
120
146
|
model: "accounts/fireworks/models/qwen2p5-coder-32b-instruct",
|
|
121
147
|
messages: [{ role: "user", content: "Write code..." }],
|
|
@@ -147,7 +173,7 @@ const EmbeddingsResponseSchema = z.object({
|
|
|
147
173
|
const result = await ctx.integrations.fireworks.apiRequest(
|
|
148
174
|
{
|
|
149
175
|
method: "POST",
|
|
150
|
-
path: "/
|
|
176
|
+
path: "/v1/embeddings",
|
|
151
177
|
body: {
|
|
152
178
|
model: "accounts/fireworks/models/nomic-embed-text-v1.5",
|
|
153
179
|
input: ["Hello world", "How are you?"],
|
|
@@ -188,7 +214,7 @@ const FunctionCallResponseSchema = z.object({
|
|
|
188
214
|
const result = await ctx.integrations.fireworks.apiRequest(
|
|
189
215
|
{
|
|
190
216
|
method: "POST",
|
|
191
|
-
path: "/
|
|
217
|
+
path: "/v1/chat/completions",
|
|
192
218
|
body: {
|
|
193
219
|
model: "accounts/fireworks/models/firefunction-v2",
|
|
194
220
|
messages: [{ role: "user", content: "What's the weather in Paris?" }],
|
|
@@ -220,7 +246,7 @@ const result = await ctx.integrations.fireworks.apiRequest(
|
|
|
220
246
|
const result = await ctx.integrations.fireworks.apiRequest(
|
|
221
247
|
{
|
|
222
248
|
method: "POST",
|
|
223
|
-
path: "/
|
|
249
|
+
path: "/v1/chat/completions",
|
|
224
250
|
body: {
|
|
225
251
|
model: "accounts/fireworks/models/llama-v3p1-70b-instruct",
|
|
226
252
|
messages: [{ role: "user", content: "List 3 colors in JSON format" }],
|
|
@@ -239,7 +265,7 @@ const data = JSON.parse(result.choices[0]?.message.content ?? "{}");
|
|
|
239
265
|
const result = await ctx.integrations.fireworks.apiRequest(
|
|
240
266
|
{
|
|
241
267
|
method: "POST",
|
|
242
|
-
path: "/
|
|
268
|
+
path: "/v1/chat/completions",
|
|
243
269
|
body: {
|
|
244
270
|
model: "accounts/fireworks/models/llama-v3p1-70b-instruct",
|
|
245
271
|
messages: [{ role: "user", content: "Generate user data" }],
|
|
@@ -276,7 +302,7 @@ await fireworks.complete({ ... });
|
|
|
276
302
|
|
|
277
303
|
// CORRECT - Use apiRequest
|
|
278
304
|
await ctx.integrations.fireworks.apiRequest(
|
|
279
|
-
{ method: "POST", path: "/
|
|
305
|
+
{ method: "POST", path: "/v1/chat/completions", body: { ... } },
|
|
280
306
|
{ response: ChatCompletionResponseSchema }
|
|
281
307
|
);
|
|
282
308
|
```
|
|
@@ -301,18 +327,18 @@ const body = {
|
|
|
301
327
|
|
|
302
328
|
### API Path
|
|
303
329
|
|
|
304
|
-
|
|
330
|
+
The integration's base URL already includes `https://api.fireworks.ai/inference`, so paths should start with `/v1/`:
|
|
305
331
|
|
|
306
332
|
```typescript
|
|
307
|
-
// WRONG -
|
|
333
|
+
// WRONG - Duplicates the /inference prefix (base URL already includes it)
|
|
308
334
|
await ctx.integrations.fireworks.apiRequest(
|
|
309
|
-
{ method: "POST", path: "/v1/chat/completions", body: { ... } },
|
|
335
|
+
{ method: "POST", path: "/inference/v1/chat/completions", body: { ... } },
|
|
310
336
|
{ response: schema }
|
|
311
337
|
);
|
|
312
338
|
|
|
313
|
-
// CORRECT -
|
|
339
|
+
// CORRECT - Start with /v1/ (the integration prepends /inference automatically)
|
|
314
340
|
await ctx.integrations.fireworks.apiRequest(
|
|
315
|
-
{ method: "POST", path: "/
|
|
341
|
+
{ method: "POST", path: "/v1/chat/completions", body: { ... } },
|
|
316
342
|
{ response: schema }
|
|
317
343
|
);
|
|
318
344
|
```
|
|
@@ -347,7 +373,7 @@ import { RestApiValidationError } from "@superblocksteam/sdk-api";
|
|
|
347
373
|
|
|
348
374
|
try {
|
|
349
375
|
const result = await ctx.integrations.fireworks.apiRequest(
|
|
350
|
-
{ method: "POST", path: "/
|
|
376
|
+
{ method: "POST", path: "/v1/chat/completions", body: { ... } },
|
|
351
377
|
{ response: ChatCompletionResponseSchema }
|
|
352
378
|
);
|
|
353
379
|
} catch (error) {
|
|
@@ -13,7 +13,7 @@ Run reports, get real-time data, and interact with Google Analytics 4 properties
|
|
|
13
13
|
### Run a Report
|
|
14
14
|
|
|
15
15
|
```typescript
|
|
16
|
-
import { api, z,
|
|
16
|
+
import { api, z, googleAnalytics } from "@superblocksteam/sdk-api";
|
|
17
17
|
|
|
18
18
|
// Integration ID from the integrations panel
|
|
19
19
|
const PROD_GA4 = "a1b2c3d4-5678-90ab-cdef-ga4000000001";
|
|
@@ -46,7 +46,7 @@ const ReportResponseSchema = z.object({
|
|
|
46
46
|
|
|
47
47
|
export default api({
|
|
48
48
|
integrations: {
|
|
49
|
-
ga:
|
|
49
|
+
ga: googleAnalytics(PROD_GA4),
|
|
50
50
|
},
|
|
51
51
|
name: "GoogleAnalyticsExample",
|
|
52
52
|
input: z.object({
|
|
@@ -13,7 +13,7 @@ Upload, download, and manage files in Google Drive.
|
|
|
13
13
|
### List Files
|
|
14
14
|
|
|
15
15
|
```typescript
|
|
16
|
-
import { api, z,
|
|
16
|
+
import { api, z, googleDrive } from "@superblocksteam/sdk-api";
|
|
17
17
|
|
|
18
18
|
// Integration ID from the integrations panel
|
|
19
19
|
const PROD_DRIVE = "a1b2c3d4-5678-90ab-cdef-gdrive000001";
|
|
@@ -45,7 +45,7 @@ const ListFilesResponseSchema = z.object({
|
|
|
45
45
|
|
|
46
46
|
export default api({
|
|
47
47
|
integrations: {
|
|
48
|
-
drive:
|
|
48
|
+
drive: googleDrive(PROD_DRIVE),
|
|
49
49
|
},
|
|
50
50
|
name: "GoogleDriveExample",
|
|
51
51
|
input: z.object({
|