@superblocksteam/sdk-api 2.0.159-next.0 → 2.0.160

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 (41) hide show
  1. package/README.md +0 -23
  2. package/dist/index.d.ts +1 -1
  3. package/dist/index.d.ts.map +1 -1
  4. package/dist/index.js.map +1 -1
  5. package/dist/integrations/dynamodb/client.d.ts +2 -6
  6. package/dist/integrations/dynamodb/client.d.ts.map +1 -1
  7. package/dist/integrations/dynamodb/client.js +10 -83
  8. package/dist/integrations/dynamodb/client.js.map +1 -1
  9. package/dist/integrations/dynamodb/index.d.ts +1 -1
  10. package/dist/integrations/dynamodb/index.d.ts.map +1 -1
  11. package/dist/integrations/dynamodb/index.js.map +1 -1
  12. package/dist/integrations/dynamodb/types.d.ts +1 -27
  13. package/dist/integrations/dynamodb/types.d.ts.map +1 -1
  14. package/dist/integrations/index.d.ts +1 -1
  15. package/dist/integrations/index.d.ts.map +1 -1
  16. package/dist/integrations/index.js.map +1 -1
  17. package/dist/runtime/context.d.ts +0 -6
  18. package/dist/runtime/context.d.ts.map +1 -1
  19. package/dist/runtime/context.js +1 -2
  20. package/dist/runtime/context.js.map +1 -1
  21. package/dist/runtime/executor.d.ts +0 -6
  22. package/dist/runtime/executor.d.ts.map +1 -1
  23. package/dist/runtime/executor.js +0 -1
  24. package/dist/runtime/executor.js.map +1 -1
  25. package/dist/types.d.ts +0 -10
  26. package/dist/types.d.ts.map +1 -1
  27. package/package.json +3 -3
  28. package/src/index.ts +0 -1
  29. package/src/integrations/dynamodb/README.md +12 -33
  30. package/src/integrations/dynamodb/client.ts +16 -121
  31. package/src/integrations/dynamodb/index.ts +1 -5
  32. package/src/integrations/dynamodb/types.ts +1 -33
  33. package/src/integrations/index.ts +0 -1
  34. package/src/runtime/context.ts +0 -9
  35. package/src/runtime/executor.ts +0 -8
  36. package/src/types.ts +0 -11
  37. package/dist/integrations/dynamodb/client.test.d.ts +0 -8
  38. package/dist/integrations/dynamodb/client.test.d.ts.map +0 -1
  39. package/dist/integrations/dynamodb/client.test.js +0 -198
  40. package/dist/integrations/dynamodb/client.test.js.map +0 -1
  41. package/src/integrations/dynamodb/client.test.ts +0 -254
@@ -12,7 +12,6 @@ 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 |
16
15
  | `queryTable(table, keyExpr, values, schema, names?, metadata?)` | Query by key condition |
17
16
  | `batchWriteItem(requestItems, metadata?)` | Batch write multiple items |
18
17
  | `listTables(schema, metadata?)` | List all tables |
@@ -134,41 +133,21 @@ await ctx.integrations.dynamodb.deleteItem("users", { id: { S: "user-123" } });
134
133
  ### Scan Table
135
134
 
136
135
  ```typescript
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
- });
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
+ );
145
141
 
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
- }
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
+ );
167
149
  ```
168
150
 
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
-
172
151
  ### Query Table by Key Condition
173
152
 
174
153
  ```typescript
@@ -12,23 +12,7 @@ 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 {
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
- ]);
15
+ import type { DynamoDBClient, DynamoDBAttributeValue } from "./types.js";
32
16
 
33
17
  /**
34
18
  * Internal implementation of DynamoDBClient.
@@ -205,120 +189,33 @@ export class DynamoDBClientImpl
205
189
  return this.executeWithErrorHandling(request, "deleteItem", metadata);
206
190
  }
207
191
 
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
-
269
192
  async scan<T>(
270
193
  table: string,
271
194
  schema: z.ZodSchema<T>,
272
- filterExpressionOrOptions?: string | DynamoDBScanOptions,
273
- expressionAttributeValuesOrMetadata?:
274
- | Record<string, DynamoDBAttributeValue>
275
- | TraceMetadata,
195
+ filterExpression?: string,
196
+ expressionAttributeValues?: Record<string, DynamoDBAttributeValue>,
276
197
  expressionAttributeNames?: Record<string, string>,
277
198
  metadata?: TraceMetadata,
278
199
  ): Promise<T> {
279
200
  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);
292
201
 
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
- }
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;
315
212
  }
316
213
 
317
214
  const request = this.buildRequest("scan", params);
318
215
  const result = await this.executeWithErrorHandling(
319
216
  request,
320
217
  "scan",
321
- resolvedMetadata,
218
+ metadata,
322
219
  );
323
220
  return this.validateResult(result, schema, "scan");
324
221
  }
@@ -336,10 +233,8 @@ export class DynamoDBClientImpl
336
233
  KeyConditionExpression: keyConditionExpression,
337
234
  ExpressionAttributeValues: expressionAttributeValues,
338
235
  };
339
- if (
340
- expressionAttributeNames &&
341
- Object.keys(expressionAttributeNames).length > 0
342
- ) {
236
+
237
+ if (expressionAttributeNames) {
343
238
  params.ExpressionAttributeNames = expressionAttributeNames;
344
239
  }
345
240
 
@@ -4,9 +4,5 @@
4
4
  * @module
5
5
  */
6
6
 
7
- export type {
8
- DynamoDBClient,
9
- DynamoDBAttributeValue,
10
- DynamoDBScanOptions,
11
- } from "./types.js";
7
+ export type { DynamoDBClient, DynamoDBAttributeValue } from "./types.js";
12
8
  export { DynamoDBClientImpl } from "./client.js";
@@ -37,24 +37,6 @@ 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
-
58
40
  /**
59
41
  * DynamoDB client for database operations.
60
42
  *
@@ -102,11 +84,6 @@ export interface DynamoDBScanOptions {
102
84
  * 'status = :s',
103
85
  * { ':s': { S: 'active' } }
104
86
  * );
105
- *
106
- * // Paginate past the 1 MB Scan limit
107
- * const page = await ctx.integrations.db.scan('users', UsersSchema, {
108
- * exclusiveStartKey: lastEvaluatedKey,
109
- * });
110
87
  * ```
111
88
  */
112
89
  export interface DynamoDBClient extends BaseIntegrationClient {
@@ -145,10 +122,7 @@ export interface DynamoDBClient extends BaseIntegrationClient {
145
122
  ): Promise<T>;
146
123
 
147
124
  /**
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.
125
+ * Scan a DynamoDB table with optional filter.
152
126
  *
153
127
  * @param table - The table name
154
128
  * @param schema - Zod schema for validating the result
@@ -159,12 +133,6 @@ export interface DynamoDBClient extends BaseIntegrationClient {
159
133
  * @param metadata - Optional trace metadata for diagnostics
160
134
  * @returns The validated result
161
135
  */
162
- scan<T>(
163
- table: string,
164
- schema: z.ZodSchema<T>,
165
- options: DynamoDBScanOptions,
166
- metadata?: TraceMetadata,
167
- ): Promise<T>;
168
136
  scan<T>(
169
137
  table: string,
170
138
  schema: z.ZodSchema<T>,
@@ -363,7 +363,6 @@ export { MongoDBClientImpl } from "./mongodb/index.js";
363
363
  export type {
364
364
  DynamoDBClient,
365
365
  DynamoDBAttributeValue,
366
- DynamoDBScanOptions,
367
366
  } from "./dynamodb/index.js";
368
367
  export { DynamoDBClientImpl } from "./dynamodb/index.js";
369
368
 
@@ -57,13 +57,6 @@ export interface CreateContextOptions {
57
57
  /** Environment variables */
58
58
  env: Record<string, string>;
59
59
 
60
- /**
61
- * Server-resolved data tag key.
62
- *
63
- * Optional for compatibility with execution wrappers from older agents.
64
- */
65
- dataTag?: string;
66
-
67
60
  /** User information from JWT */
68
61
  user: ApiUser;
69
62
 
@@ -108,7 +101,6 @@ export function createApiContext(
108
101
  executeQuery,
109
102
  executionId,
110
103
  env,
111
- dataTag,
112
104
  user,
113
105
  logger,
114
106
  } = options;
@@ -180,7 +172,6 @@ export function createApiContext(
180
172
  >["integrations"],
181
173
  log,
182
174
  env: Object.freeze({ ...env }),
183
- dataTag,
184
175
  user,
185
176
  };
186
177
  }
@@ -36,13 +36,6 @@ export interface ExecuteApiRequest {
36
36
  /** Environment variables available to the API */
37
37
  env: Record<string, string>;
38
38
 
39
- /**
40
- * Server-resolved data tag key for this execution.
41
- *
42
- * Optional on the low-level request for compatibility with older runtimes.
43
- */
44
- dataTag?: string;
45
-
46
39
  /** User information extracted from the Superblocks JWT */
47
40
  user: ApiUser;
48
41
 
@@ -169,7 +162,6 @@ export async function executeApi<TInput = unknown, TOutput = unknown>(
169
162
  executeQuery: request.executeQuery,
170
163
  executionId: request.executionId,
171
164
  env: request.env,
172
- dataTag: request.dataTag,
173
165
  user: request.user,
174
166
  });
175
167
 
package/src/types.ts CHANGED
@@ -182,17 +182,6 @@ export interface ApiContext<
182
182
  /** Access to environment variables */
183
183
  readonly env: Readonly<Record<string, string>>;
184
184
 
185
- /**
186
- * Canonical key of the requested data tag validated for this execution.
187
- *
188
- * This identifies the integration configuration in use, not a user's
189
- * environment entitlement. It is supplied by the Superblocks runtime and
190
- * cannot be selected through API input. It is undefined when no data tag was
191
- * resolved or on runtimes that predate data-tag context support;
192
- * authorization checks must deny access in those cases.
193
- */
194
- readonly dataTag?: string;
195
-
196
185
  /** User information from the Superblocks JWT */
197
186
  readonly user: ApiUser;
198
187
  }
@@ -1,8 +0,0 @@
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
- export {};
8
- //# sourceMappingURL=client.test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"client.test.d.ts","sourceRoot":"","sources":["../../../src/integrations/dynamodb/client.test.ts"],"names":[],"mappings":"AAAA;;;;;GAKG"}
@@ -1,198 +0,0 @@
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
- import { describe, it, expect, vi } from "vitest";
8
- import { z } from "zod";
9
- import { DynamoDBClientImpl } from "./client.js";
10
- const TEST_CONFIG = {
11
- id: "dynamodb-test-id",
12
- name: "Test DynamoDB",
13
- pluginId: "dynamodb",
14
- configuration: {},
15
- };
16
- const ItemsSchema = z.object({ Items: z.array(z.unknown()).optional() });
17
- function createClient(mockResult = { Items: [] }) {
18
- const executeQuery = vi.fn().mockResolvedValue(mockResult);
19
- const client = new DynamoDBClientImpl(TEST_CONFIG, executeQuery);
20
- return { client, executeQuery };
21
- }
22
- function parsedBody(executeQuery, callIndex = 0) {
23
- const request = z
24
- .object({ action: z.string(), body: z.string() })
25
- .parse(executeQuery.mock.calls[callIndex]?.[0]);
26
- return { action: request.action, body: JSON.parse(request.body) };
27
- }
28
- describe("DynamoDBClientImpl", () => {
29
- describe("scan", () => {
30
- it("omits ExclusiveStartKey on a positional scan", async () => {
31
- const { client, executeQuery } = createClient();
32
- await client.scan("retailers", ItemsSchema, "status = :s", {
33
- ":s": { S: "active" },
34
- });
35
- expect(parsedBody(executeQuery)).toEqual({
36
- action: "scan",
37
- body: {
38
- TableName: "retailers",
39
- FilterExpression: "status = :s",
40
- ExpressionAttributeValues: { ":s": { S: "active" } },
41
- },
42
- });
43
- });
44
- it("forwards ExclusiveStartKey from the options object", async () => {
45
- const { client, executeQuery } = createClient();
46
- const exclusiveStartKey = { id: { S: "retailer-18" } };
47
- await client.scan("retailers", ItemsSchema, { exclusiveStartKey });
48
- expect(parsedBody(executeQuery)).toEqual({
49
- action: "scan",
50
- body: {
51
- TableName: "retailers",
52
- ExclusiveStartKey: exclusiveStartKey,
53
- },
54
- });
55
- });
56
- it("treats an empty object as empty scan options", async () => {
57
- const { client, executeQuery } = createClient();
58
- await client.scan("retailers", ItemsSchema, {});
59
- expect(parsedBody(executeQuery)).toEqual({
60
- action: "scan",
61
- body: { TableName: "retailers" },
62
- });
63
- });
64
- it("rejects objects with unknown scan option keys", async () => {
65
- const { client, executeQuery } = createClient();
66
- await expect(Reflect.apply(client.scan, client, [
67
- "retailers",
68
- ItemsSchema,
69
- { label: "not scan options" },
70
- ])).rejects.toThrow("Invalid DynamoDB scan options: label");
71
- expect(executeQuery).not.toHaveBeenCalled();
72
- });
73
- it("forwards pagination and parallel-scan options", async () => {
74
- const { client, executeQuery } = createClient();
75
- await client.scan("retailers", ItemsSchema, {
76
- exclusiveStartKey: { id: { S: "page-2" } },
77
- limit: 25,
78
- projectionExpression: "id, name",
79
- indexName: "gsi1",
80
- segment: 0,
81
- totalSegments: 4,
82
- filterExpression: "#s = :s",
83
- expressionAttributeNames: { "#s": "status" },
84
- expressionAttributeValues: { ":s": { S: "active" } },
85
- }, { label: "page retailers" });
86
- expect(parsedBody(executeQuery)).toEqual({
87
- action: "scan",
88
- body: {
89
- TableName: "retailers",
90
- ExclusiveStartKey: { id: { S: "page-2" } },
91
- Limit: 25,
92
- ProjectionExpression: "id, name",
93
- IndexName: "gsi1",
94
- Segment: 0,
95
- TotalSegments: 4,
96
- FilterExpression: "#s = :s",
97
- ExpressionAttributeNames: { "#s": "status" },
98
- ExpressionAttributeValues: { ":s": { S: "active" } },
99
- },
100
- });
101
- expect(executeQuery).toHaveBeenCalledWith(expect.anything(), undefined, {
102
- label: "page retailers",
103
- });
104
- });
105
- it("keeps positional names and metadata working together", async () => {
106
- const { client, executeQuery } = createClient();
107
- await client.scan("retailers", ItemsSchema, "#s = :s", { ":s": { S: "active" } }, { "#s": "status" }, { label: "filtered scan" });
108
- expect(parsedBody(executeQuery).body).toEqual({
109
- TableName: "retailers",
110
- FilterExpression: "#s = :s",
111
- ExpressionAttributeValues: { ":s": { S: "active" } },
112
- ExpressionAttributeNames: { "#s": "status" },
113
- });
114
- expect(executeQuery.mock.calls[0][2]).toEqual({ label: "filtered scan" });
115
- });
116
- it("keeps schemas that strip pagination cursors backward compatible", async () => {
117
- const lastEvaluatedKey = {
118
- id: { S: "retailer-18" },
119
- version: { N: "2" },
120
- };
121
- const { client } = createClient({
122
- Items: [{ id: { S: "retailer-1" } }],
123
- LastEvaluatedKey: lastEvaluatedKey,
124
- });
125
- await expect(client.scan("retailers", ItemsSchema, { limit: 25 })).resolves.toEqual({
126
- Items: [{ id: { S: "retailer-1" } }],
127
- });
128
- });
129
- it("preserves mixed AttributeValue pagination cursors", async () => {
130
- const lastEvaluatedKey = {
131
- id: { S: "retailer-18" },
132
- version: { N: "2" },
133
- };
134
- const PageSchema = z.object({
135
- Items: z.array(z.unknown()).optional(),
136
- LastEvaluatedKey: z.record(z.unknown()).optional(),
137
- });
138
- const { client } = createClient({
139
- Items: [],
140
- LastEvaluatedKey: lastEvaluatedKey,
141
- });
142
- const page = await client.scan("retailers", PageSchema, {});
143
- expect(page.LastEvaluatedKey).toEqual(lastEvaluatedKey);
144
- });
145
- it("threads each returned pagination cursor into the next request", async () => {
146
- const LastEvaluatedKeySchema = z.object({
147
- id: z.object({ S: z.string() }),
148
- });
149
- const PageSchema = z.object({
150
- Items: z.array(z.string()),
151
- LastEvaluatedKey: LastEvaluatedKeySchema.optional(),
152
- });
153
- const lastEvaluatedKey = { id: { S: "retailer-1" } };
154
- const executeQuery = vi
155
- .fn()
156
- .mockResolvedValueOnce({
157
- Items: ["retailer-1"],
158
- LastEvaluatedKey: lastEvaluatedKey,
159
- })
160
- .mockResolvedValueOnce({ Items: ["retailer-2"] });
161
- const client = new DynamoDBClientImpl(TEST_CONFIG, executeQuery);
162
- const items = [];
163
- let exclusiveStartKey;
164
- do {
165
- const page = await client.scan("retailers", PageSchema, {
166
- exclusiveStartKey,
167
- });
168
- items.push(...page.Items);
169
- exclusiveStartKey = page.LastEvaluatedKey;
170
- } while (exclusiveStartKey);
171
- expect(items).toEqual(["retailer-1", "retailer-2"]);
172
- expect(executeQuery).toHaveBeenCalledTimes(2);
173
- expect(parsedBody(executeQuery, 0).body).toEqual({
174
- TableName: "retailers",
175
- });
176
- expect(parsedBody(executeQuery, 1).body).toEqual({
177
- TableName: "retailers",
178
- ExclusiveStartKey: lastEvaluatedKey,
179
- });
180
- });
181
- });
182
- describe("queryTable", () => {
183
- it("treats a plain names map as ExpressionAttributeNames", async () => {
184
- const { client, executeQuery } = createClient();
185
- await client.queryTable("orders", "#uid = :uid", { ":uid": { S: "user-123" } }, ItemsSchema, { "#uid": "userId" });
186
- expect(parsedBody(executeQuery)).toEqual({
187
- action: "query",
188
- body: {
189
- TableName: "orders",
190
- KeyConditionExpression: "#uid = :uid",
191
- ExpressionAttributeValues: { ":uid": { S: "user-123" } },
192
- ExpressionAttributeNames: { "#uid": "userId" },
193
- },
194
- });
195
- });
196
- });
197
- });
198
- //# sourceMappingURL=client.test.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"client.test.js","sourceRoot":"","sources":["../../../src/integrations/dynamodb/client.test.ts"],"names":[],"mappings":"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"}