Search code examples
dartdart-js-interop

converting a javascript object returned from a javascript API to a dart class


I'm trying to create a dart implementation of the auth0 javascript API using the js package from https://pub.dartlang.org/packages/js.

so I'm loading https://cdn.auth0.com/js/lock/10.0.0/lock.min.js in the index.html and I created the following auth0lock dart class:

@JS()
library auth0lock;

import 'package:js/js.dart';

@JS('Auth0Lock') 
class Auth0LockJS {
  external factory Auth0LockJS(String token, String domain, Object options);
  external on(String event, Function func);
  external show();
}

class Auth0Lock {
  Auth0LockJS auth0;
  Auth0Lock(String token, String domain, Object options) {
    this.auth0 = new Auth0LockJS(token,domain,options);
  }
  on(String event, Function func) {
    this.auth0.on(event,allowInterop(func));
  }
  show() {
    this.auth0.show();
  }
}

@anonymous
@JS()
class AuthResult {
 external factory AuthResult({
  String accessToken,
  String idToken,
  String idTokenPayload,
  String state
});
  external String get accessToken;
  external set accessToken(String v);
  external String get idToken;
  external set idToken(String v);
  external Object get idTokenPayload;
  external set idTokenPayload(Object v);
  external String get state;
  external set state(String v);
}

I'm writing an angular2-dart application so I created an authentication service that uses the auth0lock.dart file that I showed previously using the following code:

@Injectable()
class Auth {
    Auth0Lock lock;

    authenticatedEvent(AuthResult authResult) {
      print(authResult);
    }

    Auth() {
        this.lock = new Auth0Lock(configObj.auth0.apiKey, configObj.auth0.domain,{});
        this.lock.on("authenticated", authenticatedEvent);
    }
    updateProfileName(data) {
      var profile = data['profile'] != null ? data['profile'] : data;
      print(profile['name']);
    }

    authenticated() {
      return false;
    }

    login() {
       this.lock.show();
    }
}

now... everything actually works! I created in the auth_service.dart file a variable typed AuthLock named lock. I instance is with parameters, run the show() function, connect to the authenticated event and the function is fired with the authentication is completed.

I created a class AuthResult but it ignores it and I get a javascript object returned from the function handler.

I program the code using Intellij and execute with dartium. so when I place a breakpoint on the print(authResult);line in the auth_service.dart file, the debugger shows that the authResult Object contains 2 properties, JavaScript View of type Object and class of type JSObjectimpl. the Javascript View contains all the properties that are returned by this function handler.

how do I convert it to a regular class in dart ? obviously I created the AuthResult class wrong cause the function handler doesn't return this type. so what am I missing?

thanks!

update

inside the authenticatedEvent function I tried printing authResult.values, that produced the error that a class of type JSObjectImpl doesn't have that function. so the return object is type JSObjectImpl. the weird thing is that I have no idea where JSObjectImpl is defined so I removed the variable type of authResult and tried to use the variables inside directory with the following code:

authenticatedEvent(authResult) {
  var a = authResult.accessToken;
  print(a);
}

this works. why I can't find JSObjectImpl type in dart? any quick way to convert this to a dart class?

thanks


Solution

  • Perhaps you just need to remove @anonymous from AuthResult

    A simplified but complete and similar example

    index.html

    <!doctype html>
    <html>
      <head>
        <script>
          var Apple = function(type) {
            this.type = type;
            this.color = "red";
            this.getInfo2 = function() {
              return this.color + ' ' + this.type + ' apple';
            };
          };
    
          Apple.prototype.getInfo = function() {
            return this.color + ' ' + this.type + ' apple';
          };
    
          function callback(f) {
            console.log(f);
            f(new Apple('Golden Delicious'));
          }
        </script>
      </head>
      <body>
        <script type="application/dart" src="index.dart"></script>
        <script src="packages/browser/dart.js"></script>
      </body>
    </html>
    

    index.dart

    @JS()
    library typed_callback.web;
    
    import 'package:js/js.dart';
    
    @JS()
    class Apple {
      external String get type;
      external set type(String type);
      external String get color;
      external set color(String color);
      external String getInfo();
      external String getInfo2();
      external Apple(String type);
    }
    
    typedef void Callback(Apple a);
    
    @JS('callback')
    external void callback(Callback /* or just Function */ f);
    
    f(Apple apple) {
      print(apple.getInfo());
      print(apple); // prints the stringified JS object [object Object]
    }
    
    main() async {
      callback(allowInterop(f));
    }