sam-goodwin / typesafe-dynamodb

TypeSafe type definitions for the AWS DynamoDB API
Apache License 2.0
205 stars 11 forks source link

v3 client runtime errors #33

Closed bok-at-built closed 2 years ago

bok-at-built commented 2 years ago

Hey @sam-goodwin, I'm still investigating, but I cannot get typesafe-dynamodb to work -- my tsc is happy but the code produces a runtime error when it tries to marshall the data:

    TypeError: Cannot read properties of undefined (reading '0')

      at Object.<anonymous>.AttributeValue.visit (node_modules/@aws-sdk/client-dynamodb/dist-cjs/models/models_0.js:1319:40)
      at serializeAws_json1_0AttributeValue (node_modules/@aws-sdk/client-dynamodb/dist-cjs/protocols/Aws_json1_0.js:3134:38)
      at node_modules/@aws-sdk/client-dynamodb/dist-cjs/protocols/Aws_json1_0.js:3746:20
          at Array.reduce (<anonymous>)
      at serializeAws_json1_0Key (node_modules/@aws-sdk/client-dynamodb/dist-cjs/protocols/Aws_json1_0.js:3740:34)
      at serializeAws_json1_0GetItemInput (node_modules/@aws-sdk/client-dynamodb/dist-cjs/protocols/Aws_json1_0.js:3646:69)
      at serializeAws_json1_0GetItemCommand (node_modules/@aws-sdk/client-dynamodb/dist-cjs/protocols/Aws_json1_0.js:276:27)
      at serialize (node_modules/@aws-sdk/client-dynamodb/dist-cjs/commands/GetItemCommand.js:30:69)
      at node_modules/@aws-sdk/middleware-serde/dist-cjs/serializerMiddleware.js:5:27
      at node_modules/@aws-sdk/middleware-logger/dist-cjs/loggerMiddleware.js:6:28

This can be easily reproduced if you try to invoke one of the functions in test/v3-document-client.test.ts against a locally running db (no need to create the tables since the request fails to serialize before it's sent out; you can basically just move a get call from foo into the dummy test case). I suspect it has something to do with a mismatched JsonFormat and/or a version mismatch in one of the aws dependencies.

Again, I'm still investigating, but I figured you may be able to quickly diagnose the issue since you're much more familiar with these libraries than I am.

bok-at-built commented 2 years ago

@sam-goodwin quick update here:

It looks likeTypeSafe${operationName}Command's underlying ${operationName}Command types from @aws-sdk/client-dynamodb are expecting marshalled inputs but are given the javascript objects. As an example, here is a hacky patch for Key serialization in TypeSafeGetItemCommand:

// src/get-item-command.ts
import { marshall } from "@aws-sdk/util-dynamodb";

...

export function TypeSafeGetItemCommand<
  Item extends object,
  PartitionKey extends keyof Item,
  RangeKey extends keyof Item | undefined,
  Format extends JsonFormat = JsonFormat.Default
>(): new <
  Key extends TableKey<Item, PartitionKey, RangeKey, Format>,
  AttributesToGet extends keyof Item | undefined,
  ProjectionExpression extends string | undefined
>(
  input: GetItemInput<
    Item,
    PartitionKey,
    RangeKey,
    Key,
    AttributesToGet,
    ProjectionExpression,
    Format
  >
) => GetItemCommand<
  Item,
  PartitionKey,
  RangeKey,
  Key,
  AttributesToGet,
  ProjectionExpression,
  Format
> {
  class __GetItemCommand extends _GetItemCommand {
    constructor(params: ConstructorParameters<typeof _GetItemCommand>[0]) {
      super({
        ...params,
        Key: marshall(params.Key)
      })
    }
  }
  return __GetItemCommand as any
}
sam-goodwin commented 2 years ago

Thanks for reporting the error and for investigating. Going to take a deeper look tomorrow now that I have some time. Hopefully should be a quick fix.

sam-goodwin commented 2 years ago

Looks like the problem is that we're using the GetItemCommand from @aws-sdk/client-dynamodb instead of GetCommand from @aws-sdk/lib-dynamodb. The former is for AttributeValues and the latter is for Documents.

See: https://docs.aws.amazon.com/sdk-for-javascript/v3/developer-guide/dynamodb-example-dynamodb-utilities.html