################ 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: .. code-block:: bash 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: .. code-block:: bash 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 :class:`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 :class:`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 :func:`MP.fn` method returns a :class:`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 :class:`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 :class:`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. :class:`Table` objects are, as stated earlier, created upon initialization of the library. They can be fetched from the :class:`MP` object by using the :func:`MP.prototype.table() ` method:: var Contacts = mp.table('Contacts'); Now that we have the ``Contacts`` table, we can create :class:`Record` objects from it by calling the :func:`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 :func:`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, :func:`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 :func:`MP.prototype.query() ` method, which returns a :class:`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 :class:`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 :func:`Query.prototype.first() ` method applies a ``limit(1)`` to the query before proceeding and returns a single :class:`Record` object; or, if no result is found, ``null``. :func:`Query.prototype.all() `, on the other hand, returns an array of :class:`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 :class:`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 });