If you would like to help test the xbrowser compatability of Soapi.js, you may run a suite of tests in your browser or on your device. Thumbs up/Thumbs down reports in comments along with the platform and browser would be greatly appreciated.

@code, maybe I'm going blind, but how do you retrieve just a question? I see AnswersById, but this is only valid for answers, not questions, and I'm not using VS so I can't see the intellisense hints, and I've scoured the soapi.generated.js file to try and find the parameter and maybe I'm just tired... sigh
– Mark HendersonJun 14 '10 at 1:03

@farseeker - I am finishing up the beta3 of soapi.cs and soapi.sl and getting that documentation generated. Then I will have to break out my old proof of concept javascript documentation generator, get it up to date and generate .chm and html docs for Soapi.JS as well. FWIW the method names are generated directly from the route path with a few formating conventions. With a little examination the pattern will become clear.
– Sky SandersJun 14 '10 at 1:33

Turns out I was just being dense. I was using singlar instead of plurar (getQuestionById instead of getQuestionsById)
– Mark HendersonJun 14 '10 at 2:02

@farseeker - the method names are not the prettiest, but as I intend all of the Soapi libraries to serve as solid core foundations upon which higher level libraries can be built I felt it would be best to generate all of the identifiers directly from the api specs. Once I have the core libraries up I will post examples of extending Soapi with lazy loaded object graphs. say, start with a Users, dot Questions will load questions if empty (Users.Questions.load/refresh are explicit directives) and so on throughout the object graph enabling fluent dot navigation across the entire api.
– Sky SandersJun 14 '10 at 2:30

I just realized that Soapi.JS is licensed under the GPL v2 only. That's generally fine, appreciated and your choice anyway, however: I'm currently in the prototyping phase regarding some larger projects and have to decide which components to build these upon. While I intend to open source most derived components too (hard to avoid with JS anyway ;) the assembled apps might not be for various reasons (think e.g. GAE/GWT here). Are you considering dual licensing Soapi.JS in the future, e.g. (ideally ;) with the MIT License like jQuery or (understandably) a commercial license option? Thanks much!
– Steffen OpelJul 1 '10 at 10:58

@steffen - thanks for bringing this up and adding some well researched context to your question. Yes, initially i released soapi dual licensed ala jquery. I don't know when/why this changed in my mind but it just seemed to propagate throughout without questioning it. I will make it clear that it is (again) dual licensed and that until the next release where this will be codified, feel free to amend any license notice accordingly with my blessing.
– Sky SandersJul 1 '10 at 13:57

1

@steffen - licensing has been updated here and in the package. thanks.
– Sky SandersJul 1 '10 at 14:35

1

@code poet - Awesome, thanks so much! It would have been a real pity not being able to built upon your excellent work, which isn't just extremely productive, but really opened new design options regarding my project architecture, very inspiring! So thanks again, I really hope there's something in it for all of us in the long run, aside from all the fun, anyway :)
– Steffen OpelJul 1 '10 at 19:34

1

I guess soapi.js is dead now? Someone should edit this to make that clear if so... And preferably suggest an alternative that works with API 2.2, if there is one. I can't seem to find any :-(
– foobarbecueFeb 10 '16 at 14:05

soapi.js vs soapi-vsdoc.js

While the -vsdoc.js is quite large, it is never served. It is, if you are using Visual Studio, used to provide intellisense services, otherwise you may either delete it or keep it around as reference.

The file that actually defines the domain types at runtime, soapi.js, is quite small, 9.5k packed, in that it only contains meta data that is used at 'compile' or more accurately parsing time to dynamically build the domain objects.

There is a slight performance hit to be taken when using new Function() when compared to inline code but I have not seen that to be an issue, especially when you are dealing with network requests. It is my observation that an app using Soapi.js will be network bound as opposed to CPU bound.

Soapi.JS is designed to be very simple to use. The only 'class' you will instantiate is RouteFactory.

RouteFactory

The RouteFactory requires 2 parameters:

targetSite (Required) - the full name of the API you wish to query. e.g. api.stackoverflow.com or http://api.stackoverflow.com

apiKey (Optional) - your application's registered apiKey. If you have no api key, API queries will be limited to 300 (or the latest limit) and requests will fail upon usage of that threshold. The JSONP mechanism provides no ability to access response headers and subsequently the x-rate-limit headers that provide usage metrics, so you will simply need to watch for timeouts and respond accordingly.

RouteFactory's raison d'être is to hold a reference to the target site and the api key and build Route objects via factory methods. NOTE: you do not have to, although you may, use the new keyword when instantiating a RouteFactory.

Request Caching

In the interest of application performance and to prevent inadvertent api 'abuse', Soapi.js includes an integrated request cache that stores the results of each unique request url for a default (and minimum) period of 60 seconds.

The caching duration may be increased for individual routes as per your application's needs.

e.g. perhaps your application requires that the stackauth site list be current to only 10 minutes you may set an increased cache duration as follows:

After a successful response, subsequent requests to /sites within the cache duration will be returned from the in-memory cache. Upon expiration of the cache duration, the data for the particular route is purged from memory and the next request will be forwarded to the API.

that's a deep and detailed work, good job. I promised to myself that i will study this bunch of great stuff soon :).
– systempuntooutJul 20 '10 at 6:44

@system - thanks dude, it is a labor of love/hate and I am pleased to be nearing a point when I can concentrate on bringing soapi.cs to the same level and then maybe actually finish my apps.
– Sky SandersJul 20 '10 at 7:49

Throttled Request Queue

The queue is integrated into the library and is transparent, requiring no additional coding or consideration.

The current default queue interval is 170ms.

This means that, with the request queue and request cache, you may make requests with impunity and without concern for 503 errors or API abuse and all requests.

Requests that are cached are not subject to queue delays.

The request queue throttle interval can be adjusted from the current default of 170ms via the static Soapi.RequestQueue object e.g.

Soapi.RequestQueue.setInterval(intervalInMS);

Care must be taken to self-control bursts so as to comply with throttling rates, otherwise unexpected behavior can, well.. be expected.

As a convenient side effect of implementing a request queue, throttled or otherwise, is the ability to provide feedback when your application is busy requesting data. This capability is implemented via global 'event' handlers and can easily facilitate UI blocking or manipulation e.g. ajax loading mask or other visual cues.

Paging Operations

The majority of operation against the API involve paging operations.

Most of the work and complexity of dealing with paged results have been encapsulated by the Route.GetPagedResponse() method.

Soapi.RouteFactory("api.stackoverflow.com", apiKey)
.Tags({ pagesize: 1 }) // contrived page size
.getPagedResponse(function success(aggregatedPages)
{
// when the paging operation completes, whether due to completion of
// paging or arbitrary termination in pageCallback, the aggregated data is
// returned to this, the success handler.
// should be the aggregated total of 10 pages of 1 item or simply 10
alert(aggregatedPages.items.length);
}, function failure(error)
{
// handle the error
}, function pageCallback(currentPage)
{
// you can handle the data page by page in this handler or
// aggregated in total in the success handler
// simply omit this function parameter if you want all
// pages returned to the success handler
// return true from this function to terminate paging operation
// and return currently aggregated data to success handler.
// we will report progress on the paging operation and constrain
// the paging operation to 10 pages
reportProgress(currentPage.page);
// return true to terminate operation
return currentPage.page == 10;
});

Visual Studio JavaScript Intellisense and Code Completion Support

This file, while of special interest to users of Visual Studio, contains complete documentation of the API, including all enumerated constant values and route parameter specifications.

For Visual Studio users: When using Soapi.JS in Visual Studio, the -vsdoc.js file simply needs to reside in the same directory as the soapi.js and soapi.generated.js files. Visual Studio will

If you are using Visual Studio 2008, you may need to apply the JavaScript Intellisense patch. The patch specifies X86, but I can assure you that the same patch is applicable to both x86 and x64.

Enums

As described in the Enumerated Constants post, soapi.js define enums that can help you write stronger code against the Soapi.JS library.

In addition to the interesting 'enum' construct provided by soapi, the soapi-vsdoc.js file enhances the value of the enum types by adding Visual Studio Intellisense and Code Completion via the use of XML Documentation Comments.

NOTE: The documentation is generated directly from the API, so it is assumed that the programmer will know that the 'semicolon-delimited string' description, in the context of Soapi.JS, describes, in the factory method call, a param array, and when setting parameters directly on the route, an array, which will be properly converted and encoded by getResponse.

The route's fields describe themselves:

NOTE: The documentation is generated directly from the API, so it is assumed that the programmer will know that the 'unix timestamp' description, in the context of Soapi.JS, describes a JavaScript Date, which will be properly converted and encoded by getResponse.

Convenience Constructors

When becoming acquainted with a new library, it is sometimes helpful to have code completion assistance and intellisense documentation for the objects returned from API calls.

By leveraging the vsdoc file and a special constructor function, we can build a 'casting' constructor that, if the object passed in is an instance of itself, simply return it, otherwise apply the object passed in to a new instance. This provides intellisense, code completion and method chaining via type inference.

The properties of the response type are enumerated:

The fact that users is an array is demonstrated by the type inference provided by Visual Studio.

Casting an element of the users array to Soapi.Domain.User results in the same effect.

While this added functionality may seem trivial, in a scenario where one is dealing with a new/beta/constantly shifting API, this type of assistance can be a great productivity boost. Especially on objects that have many many members and nested objects.

It is Visual Studio's type inference functionality, driven by the -vsdoc.js file, that enables complete intellisense code-completion throughout the compact, or 'fluent', example that is given at the head of the question to this answer.

Complete Route Listing

The RouteFactory's factory methods are consistently and intuitively named by convention to make banging out code without intellisense code completion as painless as possible.

Here is a complete list of the RouteFactory methods and the API equivalent. Starting to see a pattern? ;-)

Api Routes

AnswersById = /answers/{id}

AnswersByIdComments = /answers/{id}/comments

Badges = /badges

BadgesById = /badges/{id}

BadgesName = /badges/name

BadgesTags = /badges/tags

CommentsById = /comments/{id}

ErrorsById = /errors/{id}

PostsByIdComments = /posts/{id}/comments

Questions = /questions

QuestionsById = /questions/{id}

QuestionsByIdAnswers = /questions/{id}/answers

QuestionsByIdComments = /questions/{id}/comments

QuestionsByIdTimeline = /questions/{id}/timeline

QuestionsUnanswered = /questions/unanswered

RevisionsById = /revisions/{id}

RevisionsByIdByRevisionguid = /revisions/{id}/{revisionguid}

Search = /search

Stats = /stats

Tags = /tags

Users = /users

UsersById = /users/{id}

UsersByIdAnswers = /users/{id}/answers

UsersByIdBadges = /users/{id}/badges

UsersByIdComments = /users/{id}/comments

UsersByIdCommentsByToid = /users/{id}/comments/{toid}

UsersByIdFavorites = /users/{id}/favorites

UsersByIdMentioned = /users/{id}/mentioned

UsersByIdQuestions = /users/{id}/questions

UsersByIdReputation = /users/{id}/reputation

UsersByIdTags = /users/{id}/tags

UsersByIdTimeline = /users/{id}/timeline

UsersModerators = /users/moderators

StackAuth Routes

Sites = /sites

UsersByIdAssociated = /users/{id}/associated

NOTE: the stackauth methods/routes are available on every RouteFactory instance and are not tied to a particular target site. In fact, you may simply instantiate a RouteFactory with an empty string for target. This is useful in that you need to fetch /sites (Sites) in order to get an authoritive list of api_endpoint to use as target.

Packaging Soapi.js

The process of packaging Soapi.js for distribution may be of interest to users of Soapi.js as well as others interested in using Visual Studio to automate the build and packaging of JavaScript resources, including documentation.

There is currently no public means
of generating vs doc xml from POJO
code. I have an abandoned and
partially implemented project but
have not taken the time to revive
it for reasons that will become
clear.

The JsDoc format is far more
expressive than is the Xml Doc
format and better than mix those
concerns, I find it a much cleaner,
albeit labor intensive, approach to
use JsDoc Toolkit for generating
hard copy docs.

There are a few features that JsDoc Toolkit does not support, so there are some post processing that needs to be done.

update the build number in both the
doc file and the script

run JsDoc Toolkit to generate the
doc site from the vsdoc (jsdoc) file
into /build/docs

Date Handling

As of RC2, Soapi.js is Dates in, Dates out. No more dealing with unix timestamps.

This includes input parameters, todate, fromdate, min and max (when applicable) and all response object date properties e.g. creation_date is converted to a JavaScript date object before it is passed to your success function.

todate, fromdate may also be specified using string, e.g. "1 jun 2010 00:00:00".

min and max are special 'variant' parameters and when dates are appropriate you must explicitly set a Date object.

+1 for this extremely useful improvement! Dealing with Unix timestamps in an application layer is always annoying and a perfect job for a library/wrapper as such, much appreciated!
– Steffen OpelJul 3 '10 at 14:51

1

@steffen - if you would like to submit any other "i wish soapi did xxxx" as individual comments on the main question you just might see them in the next release.
– Sky SandersJul 3 '10 at 17:46

@code: Well, you have to admit that this page is quite large... and I figured it would take you all of 2 seconds to tell me.
– Nathan Osman♦Aug 11 '10 at 20:55

I am way ahead of you.. In any post that I make that contains help answers you will find an index of topics. You see, I was not too lazy to index so that you, my dear user, would not have to read every answer. or the bold header to every answer post. lmao.
– Sky SandersAug 11 '10 at 21:06

@code: Sorry, one more question - does Soapi.js take timezones into consideration?
– Nathan Osman♦Aug 14 '10 at 15:16

yes. to/from utc is handled by the lib. dates are relative to your local time.
– Sky SandersAug 14 '10 at 15:33

@code: Thanks - also, is there a way to get the original timestamp? (Not the JavaScript Date() object one.)
– Nathan Osman♦Aug 14 '10 at 17:34

@geo - Date.getTime() is UTC, so just take the local date that soapi gives you, call .getTime() and divide by 1000. e.g. originalTimestamp = question.creation_date.getTime()/1000;
– Sky SandersAug 16 '10 at 18:07

@code: Thanks! I updated StackCenter so that it now informs you of new comments that have been posted since your last visit.
– Nathan Osman♦Aug 16 '10 at 18:45

Soapi.js defines Route 'classes' for each and every route, or URL, in the Stack Overflow API.

A Route is primarily a 'class' off of which to hang the URL path and define the parameters for the URL. Specifying required 'id' parameters in the factory method call and the application of parameters via explicitly defined parameter objects or JSON literals will be covered later in this post.

A Route, once constructed via the factory methods on RouteFactory, may be re-used as often as desired.

Route exposes two functions

getResponse(success, error, timeout).

getPagedResponse(success, error, pageCallback, timeout).

Route.getResponse parameters:

success (required) - function(data) - data will be a JavaScript object (jsob) built from the response JSON as defined on the route's help-page.

pageCallback (optional) - function(data) - data will be a JavaScript object (jsob) built from the response JSON as defined on the route's help-page. You may examine this object to determine if you would like to terminate the paged request. Simply return true if you wish to terminate and receive the current aggregated results in your success function.

timeout (optional) - number - The default timeout value is 10,000, or 10 seconds. If this is not acceptable, simply provide a timeout value in ms.

Routes that require an id, typically a semi-colon delimited list of identifiers, the factory method will accept id values as a param array, e.g. (id1,id2,id3,...) and construct the 'vectorized, semi-colon delimited' string for you.

example:

var route = factory.UsersById(1,2,3,14, { pagesize: 5});

resulting in a URL resembling the following (URL-encoded, of course):

http://api.xxx.com/0.8/users/1;2;3;14&pagesize=5&key=myApiKey

The other parameters of the route may be supplied as an object literal in the factory method, as shown, explicitly set on the Route object itself or applied via the Route.applyParameters function with an object literal.

'semicolon-delimited' parameters, which can be set in the factory method call, can be set as a string, ('1;2;3'), a param array, (1,2,3) or an array, ([1,2,3]), and are properly encoded by getResponse.

'unix timestamp..' parameters are set as JavaScript Date and are properly converted and encoded by getResponse.

Setting parameters directly on the Route object will, I think, be of more interest to Visual Studio users who may take advantage of the intellisense and code completion provided by soapi.generated-vsdoc.js. This topic will be covered in detail in the Intellisense Support post.

Enumerated Constants, or enums, in Soapi.js

The advantages of using enums include the elimination of magic strings scattered about your codebase and the ability to update all references to an enum value in one location.

Typically, in a statically typed language, enums are readonly or immutable values. While this concept is alien to the dynamically typed JavaScript language the benefits of enums are not mitigated. You simply need to treat them as immutable and not assign values to them.

Soapi.js defines 'enums' for all of the 'choice' parameters and return types in the API. Using enums may seem like more work in that they are more verbose than using string constant but in reality they make your code more robust and much easier to read and maintain.

Users of Visual Studio will get extra benefit from the use of the defined enum types as they have the luxury of intellisense code completion, which will be covered in detail in the Intellisense Support post.

Does this work with the Express editions of Visual Studio?
– Nathan Osman♦Jun 12 '10 at 23:36

@George, intellisense you mean? sure, I don't see why not. Just pay attention to the Intellisense Support instructions and you should have no problems. Let me know in a comment under the Intellisense Support answer.
– Sky SandersJun 12 '10 at 23:45