FamilySearch Javascript SDK

Dallan Quass

Disclaimers

  • Not official - not an official FamilySearch project
  • Not supported - code is provided as-is
  • Not maintained - everything currently works...

Why an SDK?

thefixer@flickr
petesimon@flickr

6500 lines of code

6500 lines of code

What does it do?

REST API calls return JSON

==>

Javascript function calls return Javascript objects

Features

REST API calls can be made using single-line Javascript functions

Authentication is a single-line call

Access token can be saved in a cookie - notify on expiration

Sets headers, handles transient errors and throttling

Convenience functions to make it easy to process the response

Convenience functions return Javascript objects

Objects have single-line $save() and $delete() functions

You can extend object prototypes to include your own functions

Dependencies

Either jQuery or AngularJS

No other dependencies

Diversion



Promises

Are Awesome!

Mr. Java calls Miss REST about the party

Mr. Java: Miss REST, what time is the party?

Miss REST: I'll know in about an hour

Mr. Java: I'll hold

An hour goes by

Miss REST: The party is at 7pm

Mr. Java: Thanks!

Mr. Java plans for the party

Mr. Javascript texts Miss REST about the party

Mr. Javascript: Miss REST, would you text me back when you know the time of the party?

Miss REST: I promise I will

Mr. Javascript works on his family history

An hour goes by

Miss REST: The party is at 7pm

When Mr. Javascript is at a stopping spot in his family history, he plans for the party

Think of a Promise as a Single-Use Event Bus


var promise = REST.asyncFunction();

promise.then(function(response) {
   // do something with the response
});
            

function asyncFunction() {
   var deferred = $.Deferred();

   setTimeout(function() {
      deferred.resolve("Response");
   }, 60*1000);

   return deferred.promise();
}
            

Handling Rejection


var promise = REST.asyncFunction();

promise.then(function(response) {
   // do something with the response
}, function(errorResponse) {
   // handle the error
});
            

function asyncFunction() {
   var deferred = $.Deferred();

   setTimeout(function() {
      deferred.reject("Error");
   }, 60*1000);

   return deferred.promise();
}
            

Promises can be nested

Mr. Javascript: Miss REST, would you text me back when you know the time of the party?

Miss REST: I promise I will

Mr. Javascript works on his family history

Miss REST asks her friend Miss Party Planner to fulfill her promise to Mr. Javascript

Miss REST: Miss Party Planner, would you text Mr. Javascript when you know the time of the party?

Miss Party Planner: I promise I will

An hour goes by

Miss Party Planner: Mr. Javascript, The party is at 7pm

When Mr. Javascript is at a stopping spot in his family history, he plans for the party

Example


var promise = REST.asyncFunction();

promise.then(function(response) {
   // do something with the response
});
            

function asyncFunction() {
   return $http('first URL').then(function(firstResponse) {
      var secondURL = fn(firstResponse);
      return $http(secondURL);
   });
}
            

Promises can be aggregated

Mr. Javascript: Miss REST, would you let me know when you find out what Amy and Bill are wearing to the party?

Miss REST: I promise I will

Miss REST texts Amy and Bill asking them what they are wearing

Once Miss REST hears back from both Amy and Bill, she fulfills her promise to Mr. Javascript

Example


var promise = REST.asyncFunction();

promise.then(function(amyResponse, billResponse) {
   // do something with the responses
});
            

function asyncFunction() {
   var amyPromise = amyAsyncFunction();
   var billPromise = billAsyncFunction();
   return $.when(amyPromise, billPromise);
}
            

Enough Talk

Let's Code!

1. Initialize


FamilySearch.init({
   app_key: 'WCQY-7J1Q-GKVV-7DNM-SQ5M-9Q5H-JX3H-CMJK',
   environment: 'sandbox',
   auth_callback: 'http://localhost:9000/#!/auth',
   http_function: $http,
   deferred_function: $q.defer,
   timeout_function: $timeout,
   save_access_token: true,
   auto_expire: true,
   auto_signin: true
});
          

2. Authenticate


FamilySearch.getAccessToken().then(function() {
   // user is authenticated - OAuth dance is complete
});
          

3. Make API calls


FamilySearch.getCurrentUserPersonId()
   .then(function(id) {
      FamilySearch.getAncestry(id)
         .then(function(response) {
            var persons = response.getPersons();
            // do something with the Person objects
         });
   });
          

FamilySearch.Person.prototype.isMale = function() {
   return this.display.gender === 'Male';
};
          

Another Example


function createMemoryForPerson(file, person) {
  var fd = new FormData();
  fd.append('artifact', file);
  // create memory
  return FamilySearch.createMemory(fd).then(function(memoryId) {

    // read memory to get memory artifact URL (memory.about)
    return FamilySearch.getMemory(memoryId).then(function(response) {
      var memory = response.getMemory();

      // create a memory persona from the person's name and the memory artifact URL
      var memoryPersona =
            new FamilySearch.MemoryPersona(person.$getDisplayName(), memory.about);

      // add the memory persona to the memory
      return memory.$addMemoryPersona(memoryPersona).then(function(memoryPersonaRef) {

        // add the memory persona reference to the person
        return person.$addMemoryPersonaRef(memoryPersonaRef).then(function() {
          // success!
          return memory;
        });
      });
    });
  });
};
          

Plumbing & Porcelain

jmrodri@flickr
qmnonic@flickr

Plumbing


FamilySearch.get('/platform/memories/memories/'+
                  urlencode(memoryId))
   .then(function(response) {
      // process response
   });
          

Using the SDK

Contributing

Pull Requests Are Welcome!

Cool things about the build workflow

  • jsHint
  • Karma
  • Travis-CI
  • Grunt
  • grunt-ngdocs

RootsDev


RootsDev: loose organization of software engineers interested in creating software for family history.


  • github organization: github.com/rootsdev
  • a low-volume google group with often-interesting discussions


Please join us!
rootsdev.org

The End

Slides are at https://github.com/DallanQ/rootstech-2014-fs-js-sdk-slides