Writing Bindings


#1

Still have not got my head around a proper binding.

I want to write bindings for https://github.com/awslabs/aws-mobile-appsync-sdk-js to use it in Reason. Anyone feel like a pair programming session to grind it out together or teach me the proper way? It would be greatly appreciated.

Thank you.


#2

Have you seen this post? Posting there and sharing what you have so far in code may get you more help. I am pretty new to writing bindings as well. Good luck!


#3

I sure have not. Good looking out. Thank you @ben!


#4

@idkjs I don’t use AWS AppSync but this should work

[@bs.module "aws-appsync"] [@bs.new]
external makeAWSAppSyncClient :
  {
    .
    "url": Js.Nullable.t(string),
    "region": Js.Nullable.t(string),
    "auth":
      Js.Nullable.t(
        {
          .
          "type": string,
          "apiKey": string,
        },
      ),
  } =>
  'a =
  "AWSAppSyncClient";

let createAWSAppSyncClient = (~url=?, ~region=?, ~auth=?, ()) => {
  let appSyncClientOptions = {
    "url": Js.Nullable.fromOption(url),
    "region": Js.Nullable.fromOption(region),
    "auth": Js.Nullable.fromOption(auth),
  };
  makeAWSAppSyncClient(appSyncClientOptions);
};

#5

I only checked that it logged the instance of the client in the console


#6

@drejohnson you know where I’m going with this…reason-apollo. Anything that would stop this from working with that? I’m guessing we would just pass the created client to the ReasonApollo Provider. About to try.


#7

Yep, passing client to ReasonApollo should do it


#8

I dont think I have my syntax right here.

//AppSyncConfig.re
type config = {
  .
  "graphqlEndpoint": string,
  "region": string,
  "authenticationType": string,
  "apiKey": string,
};

let config = {
  "graphqlEndpoint": "https://h25cvu6lonfilcrryg7xo5fjne.appsync-api.eu-west-1.amazonaws.com/graphql",
  "region": "eu-west-1",
  "authenticationType": "API_KEY",
  "apiKey": "da2-2ajoq2qmsvgspdw6hljfdj2lb4",
};

Creating the client:

//Client.re
open AppSyncConfig;

let auth = {"type": config.authenticationType, "apiKey": config.apiKey};

let client =
  AWS.AppSync.createAWSAppSyncClient({
    "url": config.graphqlEndpoint,
    "region": config.region,
    "auth": auth,
  });

Seems like a basic misunderstanding on records here: Why is The record field authenticationType can't be found. when its clearly defined?

Error:

  /Users/prisc_000/code/APPSYNC/re-aws/src/aws/Client.re 4:28-45

  2 │ open AppSyncConfig;
  3 │
  4 │ let auth = {"type": config.authenticationType, "apiKey": config.apiKey}
      ;
  5 │
  6 │ let client =

  The record field authenticationType can't be found.

  If it's defined in another module or file, bring it into scope by:
  - Annotating it with said module name: let baby = {myModule.age: 3}
  - Or specifying its type: let baby: MyModule.person = {age: 3}

ninja: build stopped: subcommand failed.
>>>> Finish compiling(exit: 1)

The AppSync binding

/// AWS.re
module AppSync = {
  [@bs.module "aws-appsync"] [@bs.new]
  external makeAWSAppSyncClient :
    {
      .
      "url": Js.Nullable.t(string),
      "region": Js.Nullable.t(string),
      "auth":
        Js.Nullable.t(
          {
            .
            "type": string,
            "apiKey": string,
          },
        ),
    } =>
    'a =
    "AWSAppSyncClient";
  let createAWSAppSyncClient = (~url=?, ~region=?, ~auth=?, ()) => {
    let appSyncClientOptions = {
      "url": Js.Nullable.fromOption(url),
      "region": Js.Nullable.fromOption(region),
      "auth": Js.Nullable.fromOption(auth),
    };
    makeAWSAppSyncClient(appSyncClientOptions);
  };
};

#9

Because it’s an object not a record. Try config##authenticationType


#10

Your instantiation of the client should look like this

let client =
  createAWSAppSyncClient(
    ~url=config##graphqlEndpoint,
    ~region=config##region,
    ~auth={
      "type": config##authenticationType,
      "apiKey": config##apiKey,
    },
    (),
  );

#11

Record/Objects still tripping me up. Thank you @drejohnson


#12

Any ## and Js.t are deprecated in favor of bs.deriving abstract btw


#13

@chenglou do the docs reflect this yet?

So trying to apply bs.deriving abstract. This is what I have:

//AWS.re
module AppSyncConfig = {
  [@bs.deriving abstract]
  type auth = {
    type_: string,
    apiKey: string,
  };
  [@bs.deriving abstract]
  type t = {
    url: string,
    region: string,
    auth,
  };
  let make = t;
};

module AppSync = {
  [@bs.module "aws-appsync"] [@bs.new]
  external makeAWSAppSyncClient : AppSyncConfig.t => 'a = "AWSAppSyncClient";
  let createAWSAppSyncClient = (~url, ~region, ~auth, ()) => {
    let appSyncClientOptions = AppSyncConfig.t(~url, ~region, ~auth);
    makeAWSAppSyncClient(appSyncClientOptions);
  };
};

Then in Client.re

//Client.re
open AWS.AppSyncConfig;

let auth = auth(~type_="API_KEY", ~apiKey="da2-2ajoq2qmsvgspdw6hljfdj2lb4");

let config =
  AWS.AppSyncConfig.t(
    ~url=
      "https://h25cvu6lonfilcrryg7xo5fjne.appsync-api.eu-west-1.amazonaws.com/graphql",
    ~region="eu-west-1",
    ~auth,
    (),
  );

let client = AWS.AppSync.createAWSAppSyncClient(config, ());

Sidenote:
The reason I the auth variable is that I cant figure out the syntax for passing directly like this:

...
~auth=auth(~type_="API_KEY", ~apiKey="da2-2ajoq2qmsvgspdw6hljfdj2lb4"),

How do we do that?
End Sidenote


At any rate, running the above produced the following error which I am not understanding what it means and how to fix it:

  We've found a bug for you!
  /Users/prisc_000/code/APPSYNC/re-aws-events-demo/src/AWS/Client.re 3:24-32

  1 │ open AWS.AppSyncConfig;
  2 │
  3 │ let auth = auth(~type_="API_KEY", ~apiKey="da2-2ajoq2qmsvgspdw6hljfdj2l
      b4");
  4 │
  5 │ let config =

  The function applied to this argument has type
    AWS.AppSyncConfig.t => AWS.AppSyncConfig.auth
This argument cannot be applied with label ~type_

My understanding is that im defining auth as of type AppSyncConfig.auth which has the ~type_ and ~apiKey properties. So what does it mean that the argument can not be applied with label ~type_?

Thanks for the guidance?