Scoped modules for aws-sdk bindings


#1

Hi,

I’m starting to write some partial bindings for the aws-sdk and I’m already stuck!

The SDK for DynamoDb offers two APIs:

  • the DynamoDb class
  • the DynamoDb.DocumentClient class

(The difference between the two isn’t relevant to the question but relates to how you supply attribute values.)

In the first case I am able to write:

module DynamoDb = struct
    type t  [@@bs.deriving abstract]

    external create : unit -> t = 
        "DynamoDB" [@@bs.module "aws-sdk"] [@@bs.new] 
end

When used as:

let ddb = BsAwsSdk.DynamoDB.create()

this creates the correct JS fragment:

var AwsSdk = require("aws-sdk");
var db = new AwsSdk.DynamoDB();

However, I’m at a loss for what to write for the second. Given the following usage:

let client = BsAwsSdk.DynamoDB.DocumentClient.create()

I want to generate this JS:

var AwsSdk = require('aws-sdk');
var client = new AwsSdk.DynamoDB.DocumentClient();

I have tried both of the following:

module DynamoDb = struct
   module DocumentClient = struct
       type t  [@@bs.deriving abstract]
       
       external create : unit -> t = 
             "DynamoDB.DocumentClient" [@@bs.module "aws-sdk"] [@@bs.new] 
   end
end

and

module DynamoDb = struct
   module DocumentClient = struct
       type t  [@@bs.deriving abstract]
       
       external create : unit -> t = 
             "DocumentClient" [@@bs.module "aws-sdk.DynamoDb"] [@@bs.new] 
   end
end

But both are incorrect.

How should I write this in Bucklescript?

Thanks,

Michael


#2

You can apply the [@bs.scope] annotation here: https://bucklescript.github.io/docs/en/bind-to-global-values#global-modules (it’s not just for global modules, it can be used for imported stuff too).


#3

Thank you - this works! Given the following:

module DocumentClient = struct
  type t  [@@bs.deriving abstract]

  external create : unit -> t = 
    "DocumentClient" [@@bs.module "aws-sdk"] [@@bs.scope "DynamoDb"] [@@bs.new] 
end

When used, the generated JS looks like:

var client = new (AwsSdk.DynamoDb.DocumentClient)();

Cheers,

Michael


#4

Great. Btw you don’t need [@@bs.deriving abstract] for a fully abstract type. It’s only needed for when you’re describing a JavaScript type in terms of its fields to be able to create and access its objects. When you’re modelling a class with things like [@@bs.new], [@@bs.send] etc., you don’t need that.