Quickstart Guide

This guide is intended to get you up and rolling with the basics of the MPJS library. For a more thorough understanding of the library, how to use it, and how to extend it, you will often be referenced to the API portion of this documentation.

Installation

MPJS is an NPM package, but we it is not hosted in the general NPM repository. That means to install it, the best method is to (1) clone the mpjs repository, then (2) install the NPM package from that (now) local directory.

Cloning the GIT Repo

This is pretty straight forwards:

git clone gitosis@fun.blackpulp.com:mpjslib

Installing the NPM Module

Now that you have a copy of the library on your local system, you can install it easily to whatever node project you’re working on:

npm install --save /path/to/mpjslib

Connecting to MP

The first thing to know about the MPJS library is that every asynchronous operation returns a promise (using the Q library). Connecting is no different:

var mpjs = require('mpjs')
  , url = 'https://elcid.blackpulp.com/ministryplatform/public/api.asmx?wsdl'
  , guid = '[API GUID HERE]'
  , password = '[API PASSWORD HERE]';

mpjs.connect({
  url: url,
  guid: guid,
  password: password
}).then(function(mp) {
  console.log('yay, we are connected!');
}, function(e) {
  console.error("CRASH:", e)
}).done();

Upon connection, the success callback returns an MP() object, which is the central object we’ll use throughout our project/application to interact with the Ministry Platform system.

Executing Stored Procedures

One of the most common tasks when working with Ministry Platform as a developer is the execution of stored procs. The MPJS library makes this easy to do and even resolves the data types returned by the stored proc tables.

NOTE: Before I continue, I should probably note that from henceforth in this documentation, code examples are assumed to exist within the connect “success” call block (where the “mp” object is returned).

Here is an example of executing a commonly-used stored procedure:

mp.sp('api_Perimeter_CMS_FindMatchingContact').call({
  FirstName: 'Tim',
  LastName: 'Radke',
  EmailAddress: 'tim@blackpulp.com'
}).then(function(result) {
  // The result object has properties for each table returned
  result.Table   // => the table of matching contacts

  // Also important to note is that the result tables are arrays with a
  // special "first()" method, which is just an easy-to-type way of
  // accessing the first item in the table. Null is returned if the
  // result set is empty
  result.Table.first();

  // Or we can iterate over the table:
  for (var i = 0, item; (item = result.Table[i]); i++) {
    // Note that the "Contact_ID" field is an integer, not a string
    doThingsWithContactId(item.Contact_ID);

    // Also, datetime properties are converted to moment() objects:
    item.Date_of_Birth.format('MM/DD/YYYY');
  }

  // The result set also contains an array of returned table names:
  result.tableNames   // => In this case: ['Table']
}).done();

As you’ve probably noticed, mp.sp() is the method to use to initiate a stored procedure call. This method actually returns a “StoredProcedure” object, which has a call() method, amongst other things. For more information, check out the StoredProcedure() documentation.

Calling MP SOAP Functions

Every so often, we need to execute SOAP functions directly, such as calling AuthenticateUser. This can be done with ease with MPJS:

mp.fn('AuthenticateUser').call({
  UserName: 'bob',
  Password: 'bobspassword'
}).then(function(response) {
  // response contains all of the data that you'd expect from
  // AuthenticateUser:
  response.UserId;
  response.ContactID;
  response.CanImpersonate;
  response.UserGUID
  // etc, etc...
});

The MP.fn() method returns a APIFunction() object. I suggest you checkout that documentation for more information.

Creating and Interacting with Table Records

The MPJS library uses a special stored procedure on initialization to fetch the database schema information from Ministry Platform. Using this information, it constructs Table() objects for each table. These objects know all about the underlying database tables that they represent; they can even do basic validation on any Record() objects that are created from them.

What all this ultimately means is that the MPJS library can catch basic mistakes earlier, rather than later, and give you more information as to the nature of the error than the Ministry Platform SOAP library would give you.

Table() objects are, as stated earlier, created upon initialization of the library. They can be fetched from the MP() object by using the MP.prototype.table() method:

var Contacts = mp.table('Contacts');

Now that we have the Contacts table, we can create Record() objects from it by calling the Table.prototype.record() method:

var tim = Contacts.record();

Alternatively, we can specify some initialization data for this record:

var tim = Contacts.record({
  First_Name: 'Tim',
  Last_Name: 'Radke',
  Display_Name: 'Radke, Tim',
  Nickname: 'Timothy',
  Company: false
});

We can modify the data stored by the tim record two ways:

tim.update({
  First_Name: 'Timothy'
});

// or:

tim.First_Name = 'Timothy';

Records can be checked if they’re “new” by:

tim.isNew();   // => true in this case

NOTE: The Record.prototype.isNew() method simply checks if the primary key for the record is set or not. If it is, we assume the record is not new.

Saving Records

If we want to save the record to the database, we can simply do:

mp.save(tim).then(function(obj) {
  // Save successful!
  // Note that obj === tim.
}).done();

At times it is useful to save multiple records at a time. Because of JavaScript’s asynchronous nature, we can actually send off a bunch of requests all at once, then wait for the results. There are two ways of doing this. Since the MPJS library is promise-based, we could send a bunch of save() calls to q.all() encapsulated in an array:

q.all([mp.save(tim), mp.save(anotherRecord)]).then(function(responses) {
  // all done
});

However, MP.prototype.save() also allows passing an array of records to save, which effectively does the same as the above:

mp.save([tim, anotherRecord]).then(function(responses) {
  // all done
});

This is a pattern that is repeated throughout the MPJS library. Function calls, stored procedure calls, etc., can all be passed arrays instead of objects.

Fetching Arbitrary Records from the Database

Another stored procedure that the MPJS library uses (thanks, Ken!) allows us to fetch arbitrary records from arbitrary tables from the Ministry Platform database. This functionality is still in its infancy, so expect this section to change as the stored proc is tweaked in the future.

Fetching records is done via the MP.prototype.query() method, which returns a Query() object:

var query = mp.query('Contacts');

// or:

var query = mp.query(mp.table('Contacts'));

Query objects have several key methods for refining your search. Each one of them actually returns a new Query object with the requested modifications. For example:

var query = mp.query('Contacts')
  , query2 = query.orderBy('Contact_ID');

query === query2;   // false !!

The methods can be chained together to build the query that you’re after:

var query = mp.query('Form_Responses')
  .filterBy({Form_ID: 3})
  .orderBy('Form_Response_ID')
  .limit(25);

In case you’re wondering which methods exist for directing your query, check out the Query() documentation.

Now that we have built our query, we can execute it in one of two ways:

var formResponses = query.all();

// or:

var formResponse = query.first();

The Query.prototype.first() method applies a limit(1) to the query before proceeding and returns a single Record() object; or, if no result is found, null.

Query.prototype.all(), on the other hand, returns an array of Record() objects. This array has a special first() method, which will return the first record or null, if no results were found.

Because these calls return Record() objects, we can easily manipulate them and then save them back to the database:

formResponse.First_Name = 'Someone';
formResponse.Last_Name = 'Else';
mp.save(formResponse).then(function() {
  // all done
});