@superblocksteam/sdk-api 0.0.9 → 0.0.10

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 (40) hide show
  1. package/dist/index.d.ts +1 -1
  2. package/dist/index.d.ts.map +1 -1
  3. package/dist/index.js.map +1 -1
  4. package/dist/integrations/dynamodb/client.d.ts +6 -2
  5. package/dist/integrations/dynamodb/client.d.ts.map +1 -1
  6. package/dist/integrations/dynamodb/client.js +83 -10
  7. package/dist/integrations/dynamodb/client.js.map +1 -1
  8. package/dist/integrations/dynamodb/client.test.d.ts +8 -0
  9. package/dist/integrations/dynamodb/client.test.d.ts.map +1 -0
  10. package/dist/integrations/dynamodb/client.test.js +198 -0
  11. package/dist/integrations/dynamodb/client.test.js.map +1 -0
  12. package/dist/integrations/dynamodb/index.d.ts +1 -1
  13. package/dist/integrations/dynamodb/index.d.ts.map +1 -1
  14. package/dist/integrations/dynamodb/index.js.map +1 -1
  15. package/dist/integrations/dynamodb/types.d.ts +27 -1
  16. package/dist/integrations/dynamodb/types.d.ts.map +1 -1
  17. package/dist/integrations/index.d.ts +1 -1
  18. package/dist/integrations/index.d.ts.map +1 -1
  19. package/dist/integrations/index.js.map +1 -1
  20. package/package.json +1 -1
  21. package/src/index.ts +1 -0
  22. package/src/integrations/anthropic/README.md +7 -0
  23. package/src/integrations/bigquery/README.md +1 -0
  24. package/src/integrations/box/README.md +3 -0
  25. package/src/integrations/cohere/README.md +7 -0
  26. package/src/integrations/dynamodb/README.md +33 -12
  27. package/src/integrations/dynamodb/client.test.ts +254 -0
  28. package/src/integrations/dynamodb/client.ts +121 -16
  29. package/src/integrations/dynamodb/index.ts +5 -1
  30. package/src/integrations/dynamodb/types.ts +33 -1
  31. package/src/integrations/fireworks/README.md +7 -0
  32. package/src/integrations/gemini/README.md +8 -0
  33. package/src/integrations/groq/README.md +7 -0
  34. package/src/integrations/index.ts +1 -0
  35. package/src/integrations/mistral/README.md +7 -0
  36. package/src/integrations/openai_v2/README.md +7 -0
  37. package/src/integrations/perplexity/README.md +7 -0
  38. package/src/integrations/s3/README.md +1 -0
  39. package/src/integrations/snowflakecortex/README.md +8 -0
  40. package/src/integrations/stabilityai/README.md +7 -0
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/integrations/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/integrations/index.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@superblocksteam/sdk-api",
3
- "version": "0.0.9",
3
+ "version": "0.0.10",
4
4
  "description": "Superblocks SDK for TypeScript-based API definitions",
5
5
  "license": "Superblocks Community Software License",
6
6
  "files": [
package/src/index.ts CHANGED
@@ -251,6 +251,7 @@ export type { GraphQLClient } from "./integrations/graphql/index.js";
251
251
  export type {
252
252
  DynamoDBClient,
253
253
  DynamoDBAttributeValue,
254
+ DynamoDBScanOptions,
254
255
  } from "./integrations/dynamodb/index.js";
255
256
  export type { CosmosDBClient } from "./integrations/cosmosdb/index.js";
256
257
  export type {
@@ -247,6 +247,13 @@ All methods accept an optional `metadata` parameter as the last argument for dia
247
247
 
248
248
  ## Common Pitfalls
249
249
 
250
+ ### Streaming Is Not Supported
251
+
252
+ `apiRequest()` does not support streaming or Server-Sent Events. Do not set
253
+ `stream: true` — streaming responses fail schema validation. Every call
254
+ returns the complete response; if a UI needs real-time token streaming,
255
+ handle it at the frontend layer, not through the SDK.
256
+
250
257
  ### No Specialized Methods
251
258
 
252
259
  The Anthropic client only provides `apiRequest()`. There are no other specialized methods:
@@ -27,6 +27,7 @@ const EventSchema = z.object({
27
27
  });
28
28
 
29
29
  export default api({
30
+ name: "GetEventCounts",
30
31
  integrations: {
31
32
  bigquery: bigquery(PROD_BIGQUERY),
32
33
  },
@@ -57,6 +57,9 @@ const ListItemsResponseSchema = z.object({
57
57
 
58
58
  export default api({
59
59
  name: "BoxExample",
60
+ integrations: {
61
+ box: box(PROD_BOX),
62
+ },
60
63
  input: z.object({
61
64
  folderId: z.string().default("0"), // "0" is root folder
62
65
  limit: z.number().default(100),
@@ -211,6 +211,13 @@ All methods accept an optional `metadata` parameter as the last argument for dia
211
211
 
212
212
  ## Common Pitfalls
213
213
 
214
+ ### Streaming Is Not Supported
215
+
216
+ `apiRequest()` does not support streaming or Server-Sent Events. Do not set
217
+ `stream: true` — streaming responses fail schema validation. Every call
218
+ returns the complete response; if a UI needs real-time token streaming,
219
+ handle it at the frontend layer, not through the SDK.
220
+
214
221
  ### No Specialized Methods
215
222
 
216
223
  ```typescript
@@ -12,6 +12,7 @@ Execute operations against Amazon DynamoDB with full type safety and runtime val
12
12
  | `updateItem(table, key, expr, values, names?, metadata?)` | Update an existing item |
13
13
  | `deleteItem(table, key, metadata?)` | Delete an item by key |
14
14
  | `scan(table, schema, filter?, values?, names?, metadata?)` | Scan a table |
15
+ | `scan(table, schema, options, metadata?)` | Scan with pagination options |
15
16
  | `queryTable(table, keyExpr, values, schema, names?, metadata?)` | Query by key condition |
16
17
  | `batchWriteItem(requestItems, metadata?)` | Batch write multiple items |
17
18
  | `listTables(schema, metadata?)` | List all tables |
@@ -133,21 +134,41 @@ await ctx.integrations.dynamodb.deleteItem("users", { id: { S: "user-123" } });
133
134
  ### Scan Table
134
135
 
135
136
  ```typescript
136
- // Full scan
137
- const allUsers = await ctx.integrations.dynamodb.scan(
138
- "users",
139
- z.array(z.object({ id: z.string(), name: z.string() })),
140
- );
137
+ // DynamoDB Scan returns raw AttributeValue maps.
138
+ // import type { DynamoDBAttributeValue } from "@superblocksteam/sdk-api";
139
+ const AttributeValueSchema = z.custom<DynamoDBAttributeValue>();
140
+ const ItemSchema = z.record(AttributeValueSchema);
141
+ const ScanPageSchema = z.object({
142
+ Items: z.array(ItemSchema).optional(),
143
+ LastEvaluatedKey: z.record(AttributeValueSchema).optional(),
144
+ });
141
145
 
142
- // With filter expression
143
- const activeUsers = await ctx.integrations.dynamodb.scan(
144
- "users",
145
- z.array(z.object({ id: z.string(), name: z.string() })),
146
- "status = :s",
147
- { ":s": { S: "active" } },
148
- );
146
+ // Paginate past DynamoDB's 1 MB per-Scan limit. Bound the number of
147
+ // requests so throttling or an unexpectedly large table cannot consume
148
+ // the entire API execution timeout.
149
+ const MAX_PAGES = 100;
150
+ let exclusiveStartKey: Record<string, DynamoDBAttributeValue> | undefined;
151
+ const allItems: Array<Record<string, DynamoDBAttributeValue>> = [];
152
+ for (let pageNumber = 0; pageNumber < MAX_PAGES; pageNumber += 1) {
153
+ const page = await ctx.integrations.dynamodb.scan("users", ScanPageSchema, {
154
+ exclusiveStartKey,
155
+ filterExpression: "status = :s",
156
+ expressionAttributeValues: { ":s": { S: "active" } },
157
+ });
158
+ allItems.push(...(page.Items ?? []));
159
+ exclusiveStartKey = page.LastEvaluatedKey;
160
+ if (!exclusiveStartKey) {
161
+ break;
162
+ }
163
+ if (pageNumber === MAX_PAGES - 1) {
164
+ throw new Error(`Scan exceeded the ${MAX_PAGES}-page safety limit`);
165
+ }
166
+ }
149
167
  ```
150
168
 
169
+ Choose a page cap appropriate for the API timeout and provisioned read
170
+ capacity. For very large tables, process and persist pages incrementally.
171
+
151
172
  ### Query Table by Key Condition
152
173
 
153
174
  ```typescript
@@ -0,0 +1,254 @@
1
+ /**
2
+ * Unit tests for DynamoDB client request bodies.
3
+ *
4
+ * The orchestrator forwards `action` + JSON `body` to the AWS SDK, so these
5
+ * tests lock the wire params - especially ExclusiveStartKey pagination.
6
+ */
7
+
8
+ import { describe, it, expect, vi } from "vitest";
9
+ import { z } from "zod";
10
+
11
+ import type { IntegrationConfig } from "../types.js";
12
+ import { DynamoDBClientImpl } from "./client.js";
13
+
14
+ const TEST_CONFIG: IntegrationConfig = {
15
+ id: "dynamodb-test-id",
16
+ name: "Test DynamoDB",
17
+ pluginId: "dynamodb",
18
+ configuration: {},
19
+ };
20
+
21
+ const ItemsSchema = z.object({ Items: z.array(z.unknown()).optional() });
22
+
23
+ function createClient(mockResult: unknown = { Items: [] }) {
24
+ const executeQuery = vi.fn().mockResolvedValue(mockResult);
25
+ const client = new DynamoDBClientImpl(TEST_CONFIG, executeQuery);
26
+ return { client, executeQuery };
27
+ }
28
+
29
+ function parsedBody(executeQuery: ReturnType<typeof vi.fn>, callIndex = 0) {
30
+ const request = z
31
+ .object({ action: z.string(), body: z.string() })
32
+ .parse(executeQuery.mock.calls[callIndex]?.[0]);
33
+ return { action: request.action, body: JSON.parse(request.body) };
34
+ }
35
+
36
+ describe("DynamoDBClientImpl", () => {
37
+ describe("scan", () => {
38
+ it("omits ExclusiveStartKey on a positional scan", async () => {
39
+ const { client, executeQuery } = createClient();
40
+
41
+ await client.scan("retailers", ItemsSchema, "status = :s", {
42
+ ":s": { S: "active" },
43
+ });
44
+
45
+ expect(parsedBody(executeQuery)).toEqual({
46
+ action: "scan",
47
+ body: {
48
+ TableName: "retailers",
49
+ FilterExpression: "status = :s",
50
+ ExpressionAttributeValues: { ":s": { S: "active" } },
51
+ },
52
+ });
53
+ });
54
+
55
+ it("forwards ExclusiveStartKey from the options object", async () => {
56
+ const { client, executeQuery } = createClient();
57
+ const exclusiveStartKey = { id: { S: "retailer-18" } };
58
+
59
+ await client.scan("retailers", ItemsSchema, { exclusiveStartKey });
60
+
61
+ expect(parsedBody(executeQuery)).toEqual({
62
+ action: "scan",
63
+ body: {
64
+ TableName: "retailers",
65
+ ExclusiveStartKey: exclusiveStartKey,
66
+ },
67
+ });
68
+ });
69
+
70
+ it("treats an empty object as empty scan options", async () => {
71
+ const { client, executeQuery } = createClient();
72
+
73
+ await client.scan("retailers", ItemsSchema, {});
74
+
75
+ expect(parsedBody(executeQuery)).toEqual({
76
+ action: "scan",
77
+ body: { TableName: "retailers" },
78
+ });
79
+ });
80
+
81
+ it("rejects objects with unknown scan option keys", async () => {
82
+ const { client, executeQuery } = createClient();
83
+
84
+ await expect(
85
+ Reflect.apply(client.scan, client, [
86
+ "retailers",
87
+ ItemsSchema,
88
+ { label: "not scan options" },
89
+ ]),
90
+ ).rejects.toThrow("Invalid DynamoDB scan options: label");
91
+ expect(executeQuery).not.toHaveBeenCalled();
92
+ });
93
+
94
+ it("forwards pagination and parallel-scan options", async () => {
95
+ const { client, executeQuery } = createClient();
96
+
97
+ await client.scan(
98
+ "retailers",
99
+ ItemsSchema,
100
+ {
101
+ exclusiveStartKey: { id: { S: "page-2" } },
102
+ limit: 25,
103
+ projectionExpression: "id, name",
104
+ indexName: "gsi1",
105
+ segment: 0,
106
+ totalSegments: 4,
107
+ filterExpression: "#s = :s",
108
+ expressionAttributeNames: { "#s": "status" },
109
+ expressionAttributeValues: { ":s": { S: "active" } },
110
+ },
111
+ { label: "page retailers" },
112
+ );
113
+
114
+ expect(parsedBody(executeQuery)).toEqual({
115
+ action: "scan",
116
+ body: {
117
+ TableName: "retailers",
118
+ ExclusiveStartKey: { id: { S: "page-2" } },
119
+ Limit: 25,
120
+ ProjectionExpression: "id, name",
121
+ IndexName: "gsi1",
122
+ Segment: 0,
123
+ TotalSegments: 4,
124
+ FilterExpression: "#s = :s",
125
+ ExpressionAttributeNames: { "#s": "status" },
126
+ ExpressionAttributeValues: { ":s": { S: "active" } },
127
+ },
128
+ });
129
+ expect(executeQuery).toHaveBeenCalledWith(expect.anything(), undefined, {
130
+ label: "page retailers",
131
+ });
132
+ });
133
+
134
+ it("keeps positional names and metadata working together", async () => {
135
+ const { client, executeQuery } = createClient();
136
+
137
+ await client.scan(
138
+ "retailers",
139
+ ItemsSchema,
140
+ "#s = :s",
141
+ { ":s": { S: "active" } },
142
+ { "#s": "status" },
143
+ { label: "filtered scan" },
144
+ );
145
+
146
+ expect(parsedBody(executeQuery).body).toEqual({
147
+ TableName: "retailers",
148
+ FilterExpression: "#s = :s",
149
+ ExpressionAttributeValues: { ":s": { S: "active" } },
150
+ ExpressionAttributeNames: { "#s": "status" },
151
+ });
152
+ expect(executeQuery.mock.calls[0][2]).toEqual({ label: "filtered scan" });
153
+ });
154
+
155
+ it("keeps schemas that strip pagination cursors backward compatible", async () => {
156
+ const lastEvaluatedKey = {
157
+ id: { S: "retailer-18" },
158
+ version: { N: "2" },
159
+ };
160
+ const { client } = createClient({
161
+ Items: [{ id: { S: "retailer-1" } }],
162
+ LastEvaluatedKey: lastEvaluatedKey,
163
+ });
164
+
165
+ await expect(
166
+ client.scan("retailers", ItemsSchema, { limit: 25 }),
167
+ ).resolves.toEqual({
168
+ Items: [{ id: { S: "retailer-1" } }],
169
+ });
170
+ });
171
+
172
+ it("preserves mixed AttributeValue pagination cursors", async () => {
173
+ const lastEvaluatedKey = {
174
+ id: { S: "retailer-18" },
175
+ version: { N: "2" },
176
+ };
177
+ const PageSchema = z.object({
178
+ Items: z.array(z.unknown()).optional(),
179
+ LastEvaluatedKey: z.record(z.unknown()).optional(),
180
+ });
181
+ const { client } = createClient({
182
+ Items: [],
183
+ LastEvaluatedKey: lastEvaluatedKey,
184
+ });
185
+
186
+ const page = await client.scan("retailers", PageSchema, {});
187
+
188
+ expect(page.LastEvaluatedKey).toEqual(lastEvaluatedKey);
189
+ });
190
+
191
+ it("threads each returned pagination cursor into the next request", async () => {
192
+ const LastEvaluatedKeySchema = z.object({
193
+ id: z.object({ S: z.string() }),
194
+ });
195
+ const PageSchema = z.object({
196
+ Items: z.array(z.string()),
197
+ LastEvaluatedKey: LastEvaluatedKeySchema.optional(),
198
+ });
199
+ const lastEvaluatedKey = { id: { S: "retailer-1" } };
200
+ const executeQuery = vi
201
+ .fn()
202
+ .mockResolvedValueOnce({
203
+ Items: ["retailer-1"],
204
+ LastEvaluatedKey: lastEvaluatedKey,
205
+ })
206
+ .mockResolvedValueOnce({ Items: ["retailer-2"] });
207
+ const client = new DynamoDBClientImpl(TEST_CONFIG, executeQuery);
208
+
209
+ const items: string[] = [];
210
+ let exclusiveStartKey: z.infer<typeof LastEvaluatedKeySchema> | undefined;
211
+ do {
212
+ const page = await client.scan("retailers", PageSchema, {
213
+ exclusiveStartKey,
214
+ });
215
+ items.push(...page.Items);
216
+ exclusiveStartKey = page.LastEvaluatedKey;
217
+ } while (exclusiveStartKey);
218
+
219
+ expect(items).toEqual(["retailer-1", "retailer-2"]);
220
+ expect(executeQuery).toHaveBeenCalledTimes(2);
221
+ expect(parsedBody(executeQuery, 0).body).toEqual({
222
+ TableName: "retailers",
223
+ });
224
+ expect(parsedBody(executeQuery, 1).body).toEqual({
225
+ TableName: "retailers",
226
+ ExclusiveStartKey: lastEvaluatedKey,
227
+ });
228
+ });
229
+ });
230
+
231
+ describe("queryTable", () => {
232
+ it("treats a plain names map as ExpressionAttributeNames", async () => {
233
+ const { client, executeQuery } = createClient();
234
+
235
+ await client.queryTable(
236
+ "orders",
237
+ "#uid = :uid",
238
+ { ":uid": { S: "user-123" } },
239
+ ItemsSchema,
240
+ { "#uid": "userId" },
241
+ );
242
+
243
+ expect(parsedBody(executeQuery)).toEqual({
244
+ action: "query",
245
+ body: {
246
+ TableName: "orders",
247
+ KeyConditionExpression: "#uid = :uid",
248
+ ExpressionAttributeValues: { ":uid": { S: "user-123" } },
249
+ ExpressionAttributeNames: { "#uid": "userId" },
250
+ },
251
+ });
252
+ });
253
+ });
254
+ });
@@ -12,7 +12,23 @@ import { RestApiValidationError } from "../../errors.js";
12
12
  import { IntegrationError } from "../../runtime/errors.js";
13
13
  import type { QueryExecutor, TraceMetadata } from "../registry.js";
14
14
  import type { IntegrationConfig, IntegrationClientImpl } from "../types.js";
15
- import type { DynamoDBClient, DynamoDBAttributeValue } from "./types.js";
15
+ import type {
16
+ DynamoDBClient,
17
+ DynamoDBAttributeValue,
18
+ DynamoDBScanOptions,
19
+ } from "./types.js";
20
+
21
+ const DYNAMODB_SCAN_OPTION_KEYS = new Set<string>([
22
+ "filterExpression",
23
+ "expressionAttributeValues",
24
+ "expressionAttributeNames",
25
+ "exclusiveStartKey",
26
+ "limit",
27
+ "projectionExpression",
28
+ "indexName",
29
+ "segment",
30
+ "totalSegments",
31
+ ]);
16
32
 
17
33
  /**
18
34
  * Internal implementation of DynamoDBClient.
@@ -189,33 +205,120 @@ export class DynamoDBClientImpl
189
205
  return this.executeWithErrorHandling(request, "deleteItem", metadata);
190
206
  }
191
207
 
208
+ /** Copy optional AWS Scan fields onto the request body. */
209
+ private applyScanParams(
210
+ params: Record<string, unknown>,
211
+ options: DynamoDBScanOptions,
212
+ ): void {
213
+ if (options.filterExpression) {
214
+ params.FilterExpression = options.filterExpression;
215
+ }
216
+ if (
217
+ options.expressionAttributeValues &&
218
+ Object.keys(options.expressionAttributeValues).length > 0
219
+ ) {
220
+ params.ExpressionAttributeValues = options.expressionAttributeValues;
221
+ }
222
+ if (
223
+ options.expressionAttributeNames &&
224
+ Object.keys(options.expressionAttributeNames).length > 0
225
+ ) {
226
+ params.ExpressionAttributeNames = options.expressionAttributeNames;
227
+ }
228
+ if (options.exclusiveStartKey) {
229
+ params.ExclusiveStartKey = options.exclusiveStartKey;
230
+ }
231
+ if (options.limit !== undefined) {
232
+ params.Limit = options.limit;
233
+ }
234
+ if (options.projectionExpression) {
235
+ params.ProjectionExpression = options.projectionExpression;
236
+ }
237
+ if (options.indexName) {
238
+ params.IndexName = options.indexName;
239
+ }
240
+ if (options.segment !== undefined) {
241
+ params.Segment = options.segment;
242
+ }
243
+ if (options.totalSegments !== undefined) {
244
+ params.TotalSegments = options.totalSegments;
245
+ }
246
+ }
247
+
248
+ private isScanOptions(value: unknown): value is DynamoDBScanOptions {
249
+ return (
250
+ typeof value === "object" &&
251
+ value !== null &&
252
+ Object.keys(value).every((key) => DYNAMODB_SCAN_OPTION_KEYS.has(key))
253
+ );
254
+ }
255
+
256
+ private isTraceMetadata(value: unknown): value is TraceMetadata {
257
+ return (
258
+ typeof value === "object" &&
259
+ value !== null &&
260
+ Object.keys(value).every(
261
+ (key) => key === "label" || key === "description",
262
+ ) &&
263
+ Object.values(value).every(
264
+ (entry) => entry === undefined || typeof entry === "string",
265
+ )
266
+ );
267
+ }
268
+
192
269
  async scan<T>(
193
270
  table: string,
194
271
  schema: z.ZodSchema<T>,
195
- filterExpression?: string,
196
- expressionAttributeValues?: Record<string, DynamoDBAttributeValue>,
272
+ filterExpressionOrOptions?: string | DynamoDBScanOptions,
273
+ expressionAttributeValuesOrMetadata?:
274
+ | Record<string, DynamoDBAttributeValue>
275
+ | TraceMetadata,
197
276
  expressionAttributeNames?: Record<string, string>,
198
277
  metadata?: TraceMetadata,
199
278
  ): Promise<T> {
200
279
  const params: Record<string, unknown> = { TableName: table };
280
+ let resolvedMetadata = metadata;
281
+
282
+ if (
283
+ typeof filterExpressionOrOptions === "object" &&
284
+ filterExpressionOrOptions !== null
285
+ ) {
286
+ if (!this.isScanOptions(filterExpressionOrOptions)) {
287
+ throw new Error(
288
+ `Invalid DynamoDB scan options: ${Object.keys(filterExpressionOrOptions).join(", ")}`,
289
+ );
290
+ }
291
+ this.applyScanParams(params, filterExpressionOrOptions);
201
292
 
202
- if (filterExpression) {
203
- params.FilterExpression = filterExpression;
204
- }
205
-
206
- if (expressionAttributeValues) {
207
- params.ExpressionAttributeValues = expressionAttributeValues;
208
- }
209
-
210
- if (expressionAttributeNames) {
211
- params.ExpressionAttributeNames = expressionAttributeNames;
293
+ if (expressionAttributeValuesOrMetadata !== undefined) {
294
+ if (!this.isTraceMetadata(expressionAttributeValuesOrMetadata)) {
295
+ throw new Error("Invalid DynamoDB scan trace metadata");
296
+ }
297
+ resolvedMetadata = expressionAttributeValuesOrMetadata;
298
+ }
299
+ } else {
300
+ if (filterExpressionOrOptions) {
301
+ params.FilterExpression = filterExpressionOrOptions;
302
+ }
303
+ if (
304
+ expressionAttributeValuesOrMetadata &&
305
+ Object.keys(expressionAttributeValuesOrMetadata).length > 0
306
+ ) {
307
+ params.ExpressionAttributeValues = expressionAttributeValuesOrMetadata;
308
+ }
309
+ if (
310
+ expressionAttributeNames &&
311
+ Object.keys(expressionAttributeNames).length > 0
312
+ ) {
313
+ params.ExpressionAttributeNames = expressionAttributeNames;
314
+ }
212
315
  }
213
316
 
214
317
  const request = this.buildRequest("scan", params);
215
318
  const result = await this.executeWithErrorHandling(
216
319
  request,
217
320
  "scan",
218
- metadata,
321
+ resolvedMetadata,
219
322
  );
220
323
  return this.validateResult(result, schema, "scan");
221
324
  }
@@ -233,8 +336,10 @@ export class DynamoDBClientImpl
233
336
  KeyConditionExpression: keyConditionExpression,
234
337
  ExpressionAttributeValues: expressionAttributeValues,
235
338
  };
236
-
237
- if (expressionAttributeNames) {
339
+ if (
340
+ expressionAttributeNames &&
341
+ Object.keys(expressionAttributeNames).length > 0
342
+ ) {
238
343
  params.ExpressionAttributeNames = expressionAttributeNames;
239
344
  }
240
345
 
@@ -4,5 +4,9 @@
4
4
  * @module
5
5
  */
6
6
 
7
- export type { DynamoDBClient, DynamoDBAttributeValue } from "./types.js";
7
+ export type {
8
+ DynamoDBClient,
9
+ DynamoDBAttributeValue,
10
+ DynamoDBScanOptions,
11
+ } from "./types.js";
8
12
  export { DynamoDBClientImpl } from "./client.js";
@@ -37,6 +37,24 @@ export type DynamoDBAttributeValue =
37
37
  | { NS: string[] }
38
38
  | { BS: string[] };
39
39
 
40
+ /**
41
+ * Optional Scan parameters forwarded to the AWS SDK.
42
+ *
43
+ * Use `exclusiveStartKey` with `LastEvaluatedKey` from a previous page to
44
+ * continue past DynamoDB's 1 MB per-Scan limit.
45
+ */
46
+ export interface DynamoDBScanOptions {
47
+ filterExpression?: string;
48
+ expressionAttributeValues?: Record<string, DynamoDBAttributeValue>;
49
+ expressionAttributeNames?: Record<string, string>;
50
+ exclusiveStartKey?: Record<string, DynamoDBAttributeValue>;
51
+ limit?: number;
52
+ projectionExpression?: string;
53
+ indexName?: string;
54
+ segment?: number;
55
+ totalSegments?: number;
56
+ }
57
+
40
58
  /**
41
59
  * DynamoDB client for database operations.
42
60
  *
@@ -84,6 +102,11 @@ export type DynamoDBAttributeValue =
84
102
  * 'status = :s',
85
103
  * { ':s': { S: 'active' } }
86
104
  * );
105
+ *
106
+ * // Paginate past the 1 MB Scan limit
107
+ * const page = await ctx.integrations.db.scan('users', UsersSchema, {
108
+ * exclusiveStartKey: lastEvaluatedKey,
109
+ * });
87
110
  * ```
88
111
  */
89
112
  export interface DynamoDBClient extends BaseIntegrationClient {
@@ -122,7 +145,10 @@ export interface DynamoDBClient extends BaseIntegrationClient {
122
145
  ): Promise<T>;
123
146
 
124
147
  /**
125
- * Scan a DynamoDB table with optional filter.
148
+ * Scan a DynamoDB table.
149
+ *
150
+ * Prefer the options-object form when paginating (`exclusiveStartKey`) or
151
+ * when you need `limit`, `indexName`, or parallel scan segments.
126
152
  *
127
153
  * @param table - The table name
128
154
  * @param schema - Zod schema for validating the result
@@ -133,6 +159,12 @@ export interface DynamoDBClient extends BaseIntegrationClient {
133
159
  * @param metadata - Optional trace metadata for diagnostics
134
160
  * @returns The validated result
135
161
  */
162
+ scan<T>(
163
+ table: string,
164
+ schema: z.ZodSchema<T>,
165
+ options: DynamoDBScanOptions,
166
+ metadata?: TraceMetadata,
167
+ ): Promise<T>;
136
168
  scan<T>(
137
169
  table: string,
138
170
  schema: z.ZodSchema<T>,
@@ -293,6 +293,13 @@ All methods accept an optional `metadata` parameter as the last argument for dia
293
293
 
294
294
  ## Common Pitfalls
295
295
 
296
+ ### Streaming Is Not Supported
297
+
298
+ `apiRequest()` does not support streaming or Server-Sent Events. Do not set
299
+ `stream: true` — streaming responses fail schema validation. Every call
300
+ returns the complete response; if a UI needs real-time token streaming,
301
+ handle it at the frontend layer, not through the SDK.
302
+
296
303
  ### No Specialized Methods
297
304
 
298
305
  ```typescript
@@ -265,6 +265,14 @@ All methods accept an optional `metadata` parameter as the last argument for dia
265
265
 
266
266
  ## Common Pitfalls
267
267
 
268
+ ### Streaming Is Not Supported
269
+
270
+ `apiRequest()` does not support streaming or Server-Sent Events. Use
271
+ `:generateContent`, never `:streamGenerateContent` or `alt=sse` — streaming
272
+ responses fail schema validation. Every call returns the complete response;
273
+ if a UI needs real-time token streaming, handle it at the frontend layer,
274
+ not through the SDK.
275
+
268
276
  ### No Specialized Methods
269
277
 
270
278
  ```typescript