Possible to have NativeModule with function that returns a NativeModule?

I’m trying to create a NativeModule to integrate with native 3rd party SDKs. The library is a client to connect to a backend and perform CRUD operations. I’d like to make the NativeModule javascript APIs look similar to the native Android/iOS APIs.

Android API:

ThirdPartyClient client = new ThirdPartyClient (param1);
BackendTable table = client.getTable(tableName);
JsonElement obj = table.get(someObjectId);

My plan for Javascript API:

var ThirdParty = require('ThirdPartyModule');
var client = ThirdParty.ThirdPartyClient(param1); // client is an instance of an object with functions that wrap native sdk functions for ThirdPartyClient
var table = client.getTable(tableName); // table is an instance of an object with functions and properties that wrap native sdk functions for BackendTable
var obj = table.get(someObjectId); // obj is a json object

What is the proper way to accomplish something like this? Are there any examples I can look to for this?

I was thinking that I could accomplish this by creating a ThirdPartyModule.uno and ThirdPartyClientModule.uno like below:

public class ThirdPartyModule: NativeModule
{
  static readonly ThirdPartyModule _instance;

  public ThirdPartyModule()
  {
    if (_instance != null)
    {
      return;
    }

    _instance = this;
    Resource.SetGlobalKey(_instance, "ThirdPartyModule");
    AddMember(new NativeFunction("ThirdPartyClient", (NativeCallback)ThirdPartyClientModule));
  }

  ThirdPartyClientModule ThirdPartyClient(Context c, object[] args)
  {
    return new ThirdPartyClientModule ((string)args[0]);
  }
}
public class ThirdPartyClientModule: NativeModule
{
  readonly ThirdPartyClient _client; // Uno class wrapping native SDK
  public ThirdPartyClientModule(string param1)
  {
    _client = new ThirdPartyClient(param1);

    AddMember(new NativeFunction("getTable", (NativeCallback)GetTable));
  }

  ThirdPartyTableModule GetTable(Context c, object[] args)
  {
    return new ThirdPartyTableModule(_client.getTable((string)args[0]));
  }
}

But I get “Unhandled type in V8 marshaller: ThirdPartyClientModule:ThirdPartyClientModule” errors. So I’m thinking that instead of returning the NativeModule classes, I should be returning a Fuse.Scripting.Object. But I can’t figure out how to add methods to Fuse.Scripting.Objects, that would then be accessible to Javascript.

Hi Mitch,

you could take a look at how this is solved in Fuse.RMStore and Fuse.Billing.Android, both IAP libraries for the different target platforms. They wrap some native code and make a number of things accessible to JS.

You need to first get past the errors you’re getting, supposedly because you’re trying to return something other than an object (yeah, you have to return objects to JS). Then we could take it from there and you could ask more specific questions.

What would I do if I were you, is - write a little JavaScript module that works with the JavaScript types you need - objects, with attached methods specifically. Then that little library could call into your Uno code and execute whatever it needs at a given point.

Hope this helps!

So after trying many different things and thinking about this more, my question can be better worded as such:

Is it possible for functions of a NativeModule to return a Scripting.Object that has methods that can be called from Javascript? Or is the Scripting.Object strictly a JSON object, only containing data?

I see that the Scripting.Object class has a CallMethod function, but I can’t find any examples of its use.

I didn’t find an answer to my question, but I was able to get around the problem.

Luckily the third part service that I was writing the native module for also has a javascript sdk. So I wrote a native module wrapper around the android/iOS sdks to get an auth token, and initialize the javascript sdk with said token, and I’m able to use the javascript sdk to query the backend.

This is probably not the best way to do this, but I understood how to use the native sdks, so I thought it’d be easier to rely on them to get the token rather than reimplement the whole OAuth flow.

For examples of usage of the Scripting.Object’s CallMethod method you could try checking out the tests https://github.com/fusetools/fuselibs-public/blob/c9c448b1ea69c2d99e6eba28098cd6b0b9ca04ef/Source/Fuse.Scripting/Tests/Scripting.uno#L77

It’s certainly not pretty but until we have more comprehensive documentation this could be a good place to see a lot of things being used.

Here is an example of a module (WebSocket) that can instantiate multiple modules.

var WSC = require('FuseJS/WebSocketClient'); // this is a NativeModule
var client = new WSC("<url>"); // this return a NativeModule

I do this by inheriting NativeFunctionModule that I created in the same file (that module could actually be refactored to something generally accessible).

Was this what you meant in the original question?

Thanks Anders, that is exactly what I was wondering in my original question!