Howto use generated JavaScript ESI client in browser

Hi all,

I generated a javascript api-client using swagger. The /src folder of the generated client is cotaining a index.js, which provides access to constructors for public API classes.

Now, I’m trying to use it in my javascript project and want to run the API calls on browser-site.

Inside the index.js there is a comment which describes, how to use it:

  /**
   * An_OpenAPI_for_EVE_Online.<br>
   * The <code>index</code> module provides access to constructors for all the classes which comprise the public API.
   * <p>
   * An AMD (recommended!) or CommonJS application will generally do something equivalent to the following:
   * <pre>
   * var EveSwaggerInterface = require('index'); // See note below*.
   * var xxxSvc = new EveSwaggerInterface.XxxApi(); // Allocate the API class we're going to use.
   * var yyyModel = new EveSwaggerInterface.Yyy(); // Construct a model instance.
   * yyyModel.someProperty = 'someValue';
   * ...
   * var zzz = xxxSvc.doSomething(yyyModel); // Invoke the service.
   * ...
   * </pre>
   * <em>*NOTE: For a top-level AMD script, use require(['index'], function(){...})
   * and put the application logic within the callback function.</em>
   * </p>
   * <p>
   * A non-AMD browser application (discouraged) might do something like this:
   * <pre>
   * var xxxSvc = new EveSwaggerInterface.XxxApi(); // Allocate the API class we're going to use.
   * var yyy = new EveSwaggerInterface.Yyy(); // Construct a model instance.
   * yyyModel.someProperty = 'someValue';
   * ...
   * var zzz = xxxSvc.doSomething(yyyModel); // Invoke the service.
   * ...
   * </pre>
   * </p>

However, this will not work for me. If I try to access APIs/function I’ll get reference errors (not defined).

Here is an example how I’ll use it:

  //var EveSwaggerInterface = require('eve_swagger_interface'); // I'm not using NodeJs (as I'm on client-site)
  var api = new EveSwaggerInterface.AllianceApi() // how I should embed the API on client-site here, as I'm not using NodeJs
  
  var opts = { 
    'datasource': "tranquility", // {String} The server name you would like data from
    'ifNoneMatch': "ifNoneMatch_example", // {String} ETag from a previous request. A 304 will be returned if this matches the current ETag
  };
  
  var callback = function(error, data, response) {
    if (error) {
      console.error(error);
    } else {
      console.log('API called successfully. Returned data: ' + data);
    }
  };
  api.getAlliancesAllianceId(99000001, opts, callback);

In my html site I referenced the index.js of the API:

<script src="eve-esi-api/src/index.js"></script>

So, whats the right way to use a generated ESI client on browser site?

Thanks in advance.
BR
n2k

I don’t really understand what the specific issue is you are struggling with is. But I can say this from my own experience:

I would recommend reading the docs on SSO ( Single Sign On ): https://github.com/esi/esi-docs/blob/master/docs/sso/README.md

If you want to use SSO you cannot do that client-side only. Since you need to keep your clientSecret away from the client-side.

If you are developing from a browser you cannot use your localhost with this authentication flow, so you might consider using the so-called implicit flow ( which gets you a token that can’t be refreshed and expires after 20-mins ) for that.

As far as the library you seem to use is concerned, I don’t know. But you should try to read the documentation that belongs to it or contact the person who created it.

PS: What are you working on?

For pure browser, you don’t have to generate your own client unless you really want to. You can generate one on the fly, see: https://github.com/swagger-api/swagger-js
You can use this client while you’re working on getting auth to work. If you want more control, I find it’s easiest to invest the time and learn something like browserify (http://browserify.org/) which let’s you pull in the usually node.js packages, then build something you can pull into the browser. Eventually, you will almost certainly turn to webpack (or similar) if you’re building a full application.

For SSO with a pure browser client with refreshable tokens, things are a little more complicated but still doable thanks to recent updates. Start here: https://github.com/esi/esi-docs/blob/master/docs/sso/native_sso_flow.md and hit the slack channel if you have questions.

Good luck!

Thanks for the feedback.

@Vex_Munda the specific issue is how to use the api in a pure browser context (without using nodejs). I don’t know how to include the api as the function require is only available for nodejs backend applications.
Thanks for the SSO starting point. I will have a look.

PS: What are you working on?

At the moment I’m just playing around with the api. Later on I think about to create a production/industry tool.

@salacious_necrosis I want to use the generated api because I want to (re)use the already provided models and request methods.
I already had a first look into swagger-js. If you recommend it as a way to go then I will have a deeper look.

I also played around with browserify, before. I tested it with the source code which I mentioned in my starting post. In general it works.
But, I tried to encapsulate an api call into a function because I want to use it on demand (e.g. after pressing a button):

var myESI = myESI || {};

myESI.testAllianceId = function() {
  var EveSwaggerInterface = window.require('eve_swagger_interface'); // this should be declared outside. just a quick test here ;)
  var api = new EveSwaggerInterface.AllianceApi()
  
  var opts = { 
    'datasource': "tranquility", // {String} The server name you would like data from
    'ifNoneMatch': "ifNoneMatch_example", // {String} ETag from a previous request. A 304 will be returned if this matches the current ETag
  };
  
  var callback = function(error, data, response) {
    if (error) {
      console.error(error);
    } else {
      console.log('API called successfully. Returned data: ' + data);
    }
  };
  api.getAlliancesAllianceId(99000001, opts, callback);
};

browserify will generate the following source code:

(function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof require&&require,i=0;i<t.length;i++)o(t[i]);return o}return r})()({1:[function(require,module,exports){
var myESI = myESI || {};

myESI.testAllianceId = function() {
  var EveSwaggerInterface = window.require('eve_swagger_interface');
  var api = new EveSwaggerInterface.AllianceApi()
  
  var opts = { 
    'datasource': "tranquility", // {String} The server name you would like data from
    'ifNoneMatch': "ifNoneMatch_example", // {String} ETag from a previous request. A 304 will be returned if this matches the current ETag
  };
  
  var callback = function(error, data, response) {
    if (error) {
      console.error(error);
    } else {
      console.log('API called successfully. Returned data: ' + data);
    }
  };
  api.getAlliancesAllianceId(99000001, opts, callback);
};
},{}]},{},[1]);

In my app.js I want to call the function like this:

var app = app || {};

app.run = function() {

  // ...
  myESI.testAllianceId();
  // ...
}    

Trying to call the function myESI.testAllianceId will cause a “Uncaught TypeError: myESI.testAllianceId is not a function”.
I’m not so familiar with js but in the generated browserify source it looks like myESI.testAllianceId is wrapped within in another scope and therefore the function will not be found:

(function(){function r(e,n,t){function o(i,f){ // and so on...

    myESI.getAllianceTest = function() {
        // ...
    };

},}]},{},[1]);

I don’t know this syntax construct and so don’t know how to address definitions within such a scope.

I also tried to browserify the whole api index.js but with that I think I have the same issue :wink:

Thanks again.

n2k

To get browserify to do what you expect, you likely need to just export your function. Create a file like this (let’s say it’s called myfuncs.js):

var EveSwaggerInterface = require('eve_swagger_interface');
testAllianceId = function() { ... your function ... }
exports.testAllianceId = testAllianceId;

Then in your main code:

var myFuncs = require('./myfuncs.js');
myFuncs.testAllianceId(); // this should call your function

the magic is the exports which tells browserify (and, indeed, node.js) that you want to export a symbol.

Totally find to do all this with a generated client. I only suggested swagger-js as it’s easier when you’re just playing around.

Hi @salacious_necrosis

Today, I investigated in swagger-js and webpack. For me webpack subjectively feels “better” than browserify. I think I’ll go for webpack. I was able to get swagger-js running with example petstore api. Next step is to adapt it to ESI.

Now, I think I’m able to go on :slight_smile:

Thanks for your help.

BR
n2k

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.