feat(aws): add DynamoDB Cloud Explorer#143
Conversation
|
| Filename | Overview |
|---|---|
| packages/api/src/adapter-aws/AwsDynamoDbAdapter.ts | New adapter: pagination, 10-item describe batching, 100-item scan cap, and wrapNumbers-based large-integer normalization are all implemented correctly and verified by tests. |
| packages/api/src/adapter-aws/AwsDynamoDbAdapter.test.ts | 250 lines of thorough tests covering pagination, concurrency batching, validation, error handling, type normalization for large integers, and scan limits — all exercising the real unmarshall path. |
| packages/api/src/cloud-spi/dynamodbSchema.ts | Schema defines table-name, partition-key, and optional sort-key fields with correct validation patterns; columns and capabilities align with the adapter's action set. |
| packages/api/src/cloud-spi/types.ts | Adds nosql to CloudServiceType and dynamodb-table to the resource type union, and introduces the NoSqlItem interface; all consistent with the existing type layout. |
| packages/api/src/routes/clouds.ts | New GET route for nosql items is correctly guarded by withRuntime; nosql is added to the isServiceType validator keeping other routes unaffected. |
| packages/api/src/service/CloudProxyService.ts | nosql service entry and listNoSqlItems dispatch added cleanly; optional-method guard prevents errors if a future adapter omits item listing. |
| packages/frontend/src/components/DynamoDbTableExplorer.tsx | New component: React Query integration with abort-signal support, runtimeReachable gate, table-change reset, and two-panel layout are all implemented correctly. |
| packages/frontend/src/components/DynamicResourceView.tsx | Adds DynamoDbTableExplorer behind an aws+nosql guard, and a create-label branch; narrow and correct. |
| packages/frontend/src/api/cloudProxyClient.ts | Adds listNoSqlItems client function with abort signal support; also removes the duplicate ServerlessInvokeResult interface definition. |
| packages/frontend/src/pages/CloudExplorerPage.tsx | nosql added to normalizeService, serviceLabel, and limitationCopy — all three previously exhaustive switch-equivalents are kept consistent. |
| packages/frontend/src/components/Layout.tsx | NoSQL nav entry added with correct icon and AWS-only availability gate. |
| packages/api/src/cloudProxy.ts | AwsDynamoDbAdapter registered alongside other AWS adapters using the account-scoped dynamodb client. |
| packages/frontend/src/api/api.ts | New nosql.items.list endpoint key and registry entry added correctly with matching path template. |
Sequence Diagram
%%{init: {'theme': 'neutral'}}%%
sequenceDiagram
participant B as Browser (React)
participant RQ as React Query
participant C as cloudProxyClient
participant H as Hono /clouds/:cloud
participant S as CloudProxyService
participant A as AwsDynamoDbAdapter
participant D as DynamoDB (:4566)
B->>RQ: useQuery(['nosql-items', cloud, tableName])
RQ->>C: listNoSqlItems(cloud, tableId, signal)
C->>H: GET /clouds/aws/services/nosql/resources/:id/items
H->>S: listNoSqlItems('aws', id)
S->>A: adapter.listNoSqlItems(id)
A->>D: DescribeTableCommand(id)
D-->>A: KeySchema
loop paginate up to 100 items
A->>D: "ScanCommand(Limit=remaining)"
D-->>A: Items + LastEvaluatedKey
end
A-->>A: unmarshall + normalizeDocument
A-->>S: NoSqlItem[]
S-->>H: NoSqlItem[]
H-->>C: 200 JSON
C-->>RQ: NoSqlItem[]
RQ-->>B: items (cached by [cloud, tableName])
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
sequenceDiagram
participant B as Browser (React)
participant RQ as React Query
participant C as cloudProxyClient
participant H as Hono /clouds/:cloud
participant S as CloudProxyService
participant A as AwsDynamoDbAdapter
participant D as DynamoDB (:4566)
B->>RQ: useQuery(['nosql-items', cloud, tableName])
RQ->>C: listNoSqlItems(cloud, tableId, signal)
C->>H: GET /clouds/aws/services/nosql/resources/:id/items
H->>S: listNoSqlItems('aws', id)
S->>A: adapter.listNoSqlItems(id)
A->>D: DescribeTableCommand(id)
D-->>A: KeySchema
loop paginate up to 100 items
A->>D: "ScanCommand(Limit=remaining)"
D-->>A: Items + LastEvaluatedKey
end
A-->>A: unmarshall + normalizeDocument
A-->>S: NoSqlItem[]
S-->>H: NoSqlItem[]
H-->>C: 200 JSON
C-->>RQ: NoSqlItem[]
RQ-->>B: items (cached by [cloud, tableName])
Reviews (3): Last reviewed commit: "fix(frontend): remove duplicate invoke t..." | Re-trigger Greptile
| <tr> | ||
| <th>Key</th> | ||
| <th>Contents</th> | ||
| </tr> | ||
| </thead> | ||
| <tbody> | ||
| {items.map((item) => ( | ||
| <tr key={item.id} className={selectedItemId === item.id ? 'selected' : ''}> |
There was a problem hiding this comment.
All returned rows are rendered into the DOM without virtualisation
items.map(...) renders every record as a <tr> synchronously. If the backend scan returns even a few thousand rows the browser will build a DOM of that size, causing noticeable jank when selecting or scrolling. Since the listNoSqlItems call has no server-side limit today, pairing a DOM cap or a virtual-scroll list here is worth considering once the backend adds pagination.
Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!
Summary
NoSQLcategory in Cloud Explorer navigation and routingValidation
pnpm lintpnpm type-checkpnpm test(170 tests)pnpm buildCloses #76