Forums / Support / Halo API Support

haloapi.js: JavaScript Node.js Client

OP Der Flatulator6

JavaScript devs ahoy! This is a complete, statically typed (using TypeScript) client/binding for the Halo 5 beta API.
It's available as a Node JS module (on NPM). Functionality maps the endpoints from the API with a handful of extra convenience functions.

GitHub: https://github.com/DerFlatulator/haloapi
Node Package: https://www.npmjs.com/package/haloapi
Interactive Example: https://tonicdev.com/npm/haloapi
Usage documentation: http://haloapi.js.org/

If you use an IDE like Visual Studio Code/IntelliJ/WebStorm or Visual Studio, it should be possible to install the TypeScript definitions to get auto-completion and inline documentation, but this is still a work in progress. Proper instructions will come when this is feature complete.

Contributors welcome.
Is there any interest in this package being adapted to work both on a server, and in a web browser?

---
News: published to NPM! https://www.npmjs.com/package/haloapi
Installation is as simple as "npm install haloapi".
Will have to check this out on the weekend. Been trying to do a bit of a bodge job with AngularJS $http.get method, but with no luck and keep getting 401's!

Do you reckon it would be possible to use this binding and incorporate it into an Angular (or any other popular framework) ?
PSYCLONE23 wrote:
Will have to check this out on the weekend. Been trying to do a bit of a bodge job with AngularJS $http.get method, but with no luck and keep getting 401's!

Do you reckon it would be possible to use this binding and incorporate it into an Angular (or any other popular framework) ?
At the moment it's server-side only. However I was planning to adapt it to work in browsers as well. Two things would have to be changed:
    1. (If we're running in a browser) switch from the "request" NPM package to use jQuery.ajax or plain JS XML HTTP Requests.
    2. Concatenate all of the JS files in the js/ directory into one file "haloapi.js", and remove the require() calls.
I will probably do this in the coming days.
Have you given this a try with AWS Lambda yet DF? I'm debating which language to go with for my Lambda functions, so knowing this works with Lambda out of the box would steer me closer to node (despite my lack of experience). Especially since Lambda came out of the box with Node.js originally. And node comes with a lot of nice features. Then again, I just learned what Typescript was, so I may be WAY off in understanding where it can be used. JS is not my space. lol...
Have you given this a try with AWS Lambda yet DF? I'm debating which language to go with for my Lambda functions, so knowing this works with Lambda out of the box would steer me closer to node (despite my lack of experience). Especially since Lambda came out of the box with Node.js originally. And node comes with a lot of nice features. Then again, I just learned what Typescript was, so I may be WAY off in understanding where it can be used. JS is not my space. lol...
I haven't tested it with Lambda, but there's absolutely no reason why it shouldn't work. You can actually completely ignore the TypeScript part of the module if you want, the JS that TypeScript produces is just plain old JS.

There's a basic example you can play with, available on tonic, here.
Awesome that's what I assumed so I'll give it a shot DF when I start playing around with Lambda. The main key is that Lambda functions by nature need to be stateless as they can be dynamically placed on tons of instances and killed or re-used at various moments. I haven't dug deep into your solution, which is the main reason I asked.

Side note, good to see you again old friend. ;)
Awesome that's what I assumed so I'll give it a shot DF when I start playing around with Lambda. The main key is that Lambda functions by nature need to be stateless as they can be dynamically placed on tons of instances and killed or re-used at various moments. I haven't dug deep into your solution, which is the main reason I asked.

Side note, good to see you again old friend. ;)
There's nothing that should be considered stateful in the codebase. Nothing is cached, so nothing from 343's end is stored in the code in any stateful manner. If I implement burst reads or throttling, I'll be sure to keep it stateless. I basically avoid stateful programming at all costs anyway, too difficult to debug and not scalable.
Been working on getting my documentation generator up to scratch. Promising results!
Here's a preview:
Image 1. Image 2.

Note that it documents the response, alongside the actual wrapper's docs. This could be a general purpose, language agnostic interactive documentation source.

Will hopefully release in the next few days.

--------

Alongside the full traditional documentation, I've put together a quick-reference up-and-go guide.
https://derflatulator.github.io/haloapi.js/docco/haloapi.html

Built using docco, which is amazing.
Looking good man. I actually wanted to propose an idea to you. I was wondering if you would find it valuable to split off your tests and your documentation generation into a separate project that would essentially be a source of information on the API. Ideally the tests could be changed to verify the contract with a JSON schema check, and could eventually report when a change in Schema is detected. I was thinking about this the other day and as developer usage grows everyone can add their own contract tests to the project via pull request. It could be a central project for 343 to use to verify that their consumer contracts are affected as little as possible.

For example I'd write a test to confirm the start index usage I mentioned in my other thread. As that is an important feature for my needs. Potentially 343 could take this project and run it against a new update prior to release to verify what contracts are breaking and whether or not that is intentional and then they can communicate to devs what contracts are expected to break in the next update. Cuz right now there is no versioning or OPTIONS endpoint to work with so we need a layer of validation somewhere. This falls along the philosophy of Consumer Driven Contract Testing, which I think would be very valuable to 343 going forward if we provide it as a community.

Maybe this could be a whole separate project, in a separate language, but since you already have a set of tests verifying successful responses I figured I'd bring it up here first to see what you think.
Good ideas.

A note: TypeScript is never executed, it is a dev tool to have static typing (to avoid mistakes, better docs, less error prone, etc) but compiles to ordinary executable JavaScript. As a result it's not really possibly to test that a JSON object matches the typescript interface.

However, there is a better approach, json-schema. Basically, create one JSON file for each endpoint, which describes the "shape" of the response. You then validate the response with the schema. Easy!

Might start working on that in the next few days as I was already planning something similar. I'll host the schemas as a separate repository and use git submodules to pull it into my API client.

Would plug it straight into my test cases, which has CI set up here (most recent build).
Yep I'm aware of json-schema, which is why I mentioned "JSON schema check". We just have to build the schema. Do you know of a schema generator that can analyze a response, so we could start with a skeleton based on primitive json types? I'm in a rush or I'd search one out on my own. lol... Then we can add pattern matching later and any more validation that we would like for specific fields.

The separate project will be nice and we can create a thread for the Consumer Contracts project and encourage developers to add any contract tests that they would like to ensure that their contracts are at least recognized. We can't guarantee that 343 will adopt the use of the Consumer Contracts, but at the very least it will provide a source to discover when changes are made to the API. It may be valuable to setup nightly builds to check the contracts daily.
I've used jsonschema.net in the past, does the job but usually requires manual edits (though not really a fault of the software itself).

Here's a quick test for the spartan-ranks endpoint: https://gist.github.com/DerFlatulator/fbb83b855b15d35c689a.

Update: I'm giving this node package a try and it seems to produce better results.
Nice! I'll just file away the node module I started and use yours.
Update!

Added the new match events endpoint as of NPM module version 0.5.0.

Full documentation available at: http://haloapi.js.org/typedoc/index.html#_stats_.stats.events

Access using haloapi.stats.events(matchId)
the HaloAPI is awesome @DF! Great work. I can't wait to get up and running with it. Thanks for putting in so much effort, it really shows!

On a side note, just being proactive, I opened a GitHub issue (https://github.com/DerFlatulator/haloapi.js/issues/7) about the "Update to the Events API" from 343 Industries blog post this afternoon. I'll try to help with that tomorrow if you haven't close it out by then

Thanks again!
PSYCLONE23 wrote:
Will have to check this out on the weekend. Been trying to do a bit of a bodge job with AngularJS $http.get method, but with no luck and keep getting 401's!

Do you reckon it would be possible to use this binding and incorporate it into an Angular (or any other popular framework) ?
At the moment it's server-side only. However I was planning to adapt it to work in browsers as well. Two things would have to be changed:
    1. (If we're running in a browser) switch from the "request" NPM package to use jQuery.ajax or plain JS XML HTTP Requests.
    2. Concatenate all of the JS files in the js/ directory into one file "haloapi.js", and remove the require() calls.
I will probably do this in the coming days.
Is this still possible for you to do? I would be really interested in using a browser version. Thanks!
Is this still possible for you to do? I would be really interested in using a browser version. Thanks!
I changed my mind about this as it would leak developers' API keys. The trajectory that the NPM package took means that the cache functionality would also have to be re-written for indexDB or localStorage. I currently don't have plans to do this myself, but I would be open to reviewing a pull request if someone wants to give it a crack.

AMD target might work, too. Rather than concatenating the files.