-
-
Save 1fabiopereira/378ff5710cdee2e008577ffd0fb00a5c to your computer and use it in GitHub Desktop.
Rest API Adapter for Titanium Alloy
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* Rest API Adapter for Titanium Alloy | |
*/ | |
function S4() { | |
return ((1 + Math.random()) * 65536 | 0).toString(16).substring(1); | |
} | |
function guid() { | |
return S4() + S4() + "-" + S4() + "-" + S4() + "-" + S4() + "-" + S4() + S4() + S4(); | |
} | |
function InitAdapter(config) { | |
return {}; | |
} | |
function apiCall(_options, _callback) { | |
var xhr = Ti.Network.createHTTPClient({ | |
timeout : 5000 | |
}); | |
//Prepare the request | |
xhr.open(_options.type, _options.url); | |
xhr.onload = function() { | |
_callback({ | |
success: true, | |
status: xhr.status == 200 ? "ok" : xhr.status, | |
code: xhr.status, | |
responseText : xhr.responseText || null, | |
responseData : xhr.responseData || null | |
}); | |
}; | |
//Handle error | |
xhr.onerror = function(e) { | |
_callback({ | |
success: false, | |
status: "error", | |
code: xhr.status, | |
data: e.error, | |
responseText : xhr.responseText | |
}); | |
Ti.API.error('[REST API] apiCall ERROR: ' + xhr.responseText) | |
} | |
for (var header in _options.headers) { | |
xhr.setRequestHeader(header, _options.headers[header]); | |
} | |
if (_options.beforeSend) { | |
_options.beforeSend(xhr); | |
} | |
xhr.send(_options.data || null); | |
} | |
function Sync(method, model, opts) { | |
var DEBUG = model.config.debug; | |
var methodMap = { | |
'create' : 'POST', | |
'read' : 'GET', | |
'update' : 'PUT', | |
'delete' : 'DELETE' | |
}; | |
var type = methodMap[method]; | |
var params = _.extend({}, opts); | |
params.type = type; | |
//set default headers | |
params.headers = params.headers || {}; | |
// We need to ensure that we have a base url. | |
if (!params.url) { | |
params.url = (model.config.URL || model.url()); | |
if (!params.url) { | |
Ti.API.error("[REST API] ERROR: NO BASE URL"); | |
return; | |
} | |
} | |
// For older servers, emulate JSON by encoding the request into an HTML-form. | |
if (Alloy.Backbone.emulateJSON) { | |
params.contentType = 'application/x-www-form-urlencoded'; | |
params.processData = true; | |
params.data = params.data ? { | |
model : params.data | |
} : {}; | |
} | |
// For older servers, emulate HTTP by mimicking the HTTP method with `_method` | |
// And an `X-HTTP-Method-Override` header. | |
if (Alloy.Backbone.emulateHTTP) { | |
if (type === 'PUT' || type === 'DELETE') { | |
if (Alloy.Backbone.emulateJSON) | |
params.data._method = type; | |
params.type = 'POST'; | |
params.beforeSend = function(xhr) { | |
params.headers['X-HTTP-Method-Override'] = type | |
}; | |
} | |
} | |
//json data transfers | |
params.headers['Content-Type'] = 'application/json'; | |
if(DEBUG){ | |
Ti.API.debug("[REST API] REST METHOD: " + method); | |
} | |
switch(method) { | |
case 'delete' : | |
if (!model.id) { | |
params.error(null, "MISSING MODEL ID"); | |
Ti.API.error("[REST API] ERROR: MISSING MODEL ID"); | |
return; | |
} | |
params.url = params.url + '/' + model.id; | |
if(DEBUG){ | |
Ti.API.info("[REST API] options: "); | |
Ti.API.info(params); | |
} | |
apiCall(params, function(_response) { | |
if (_response.success) { | |
var data = JSON.parse(_response.responseText); | |
if(DEBUG){ | |
Ti.API.info("[REST API] server delete response: "); | |
Ti.API.debug(data) | |
} | |
params.success(null, _response.responseText); | |
model.trigger("fetch"); | |
// fire event | |
} else { | |
params.error(JSON.parse(_response.responseText), _response.responseText); | |
Ti.API.error('[REST API] DELETE ERROR: '); | |
Ti.API.error(_response); | |
} | |
}); | |
break; | |
case 'create' : | |
// convert to string for API call | |
params.data = JSON.stringify(model.toJSON()); | |
if(DEBUG){ | |
Ti.API.info("[REST API] options: "); | |
Ti.API.info(params); | |
} | |
apiCall(params, function(_response) { | |
if (_response.success) { | |
var data = JSON.parse(_response.responseText); | |
if(DEBUG){ | |
Ti.API.info("[REST API] server create response: "); | |
Ti.API.debug(data) | |
} | |
//Rest API should return a new model id. | |
if (data.id == undefined) { | |
data.id = guid(); | |
//if not - create one | |
} | |
params.success(data, JSON.stringify(data)); | |
model.trigger("fetch"); | |
// fire event | |
} else { | |
params.error(JSON.parse(_response.responseText), _response.responseText); | |
Ti.API.error('[REST API] CREATE ERROR: '); | |
Ti.API.error(_response); | |
} | |
}); | |
break; | |
case 'update' : | |
if (!model.id) { | |
params.error(null, "MISSING MODEL ID"); | |
Ti.API.error("[REST API] ERROR: MISSING MODEL ID"); | |
return; | |
} | |
// setup the url & data | |
params.url = params.url + '/' + model.id; | |
params.data = JSON.stringify(model.toJSON()); | |
if(DEBUG){ | |
Ti.API.info("[REST API] options: "); | |
Ti.API.info(params); | |
} | |
apiCall(params, function(_response) { | |
if (_response.success) { | |
var data = JSON.parse(_response.responseText); | |
if(DEBUG){ | |
Ti.API.info("[REST API] server update response: "); | |
Ti.API.debug(data) | |
} | |
params.success(data, JSON.stringify(data)); | |
model.trigger("fetch"); | |
} else { | |
params.error(JSON.parse(_response.responseText), _response.responseText); | |
Ti.API.error('[REST API] UPDATE ERROR: '); | |
Ti.API.error(_response); | |
} | |
}); | |
break; | |
case 'read': | |
if (model.id) { | |
params.url = params.url + '/' + model.id; | |
} | |
if (params.urlparams) { | |
params.url += "?" + encodeData(params.urlparams); | |
} | |
if(DEBUG){ | |
Ti.API.info("[REST API] options: "); | |
Ti.API.info(params); | |
} | |
apiCall(params, function(_response) { | |
if (_response.success) { | |
var data = JSON.parse(_response.responseText); | |
if(DEBUG){ | |
Ti.API.info("[REST API] server read response: "); | |
Ti.API.debug(data) | |
} | |
var values = []; | |
model.length = 0; | |
for (var i in data) { | |
var item = {}; | |
item = data[i]; | |
if (item.id == undefined) { | |
item.id = guid(); | |
} | |
values.push(item); | |
model.length++; | |
} | |
params.success((model.length === 1) ? values[0] : values, _response.responseText); | |
model.trigger("fetch"); | |
} else { | |
params.error(JSON.parse(_response.responseText), _response.responseText); | |
Ti.API.error('[REST API] READ ERROR: '); | |
Ti.API.error(_response); | |
} | |
}) | |
break; | |
} | |
}; | |
var encodeData = function(obj) { | |
var str = []; | |
for (var p in obj) | |
str.push(Ti.Network.encodeURIComponent(p) + "=" + Ti.Network.encodeURIComponent(obj[p])); | |
return str.join("&"); | |
} | |
//we need underscore | |
var _ = require("alloy/underscore")._; | |
//until this issue is fixed: https://jira.appcelerator.org/browse/TIMOB-11752 | |
var Alloy = require("alloy"), Backbone = Alloy.Backbone; | |
module.exports.sync = Sync; | |
module.exports.beforeModelCreate = function(config, name) { | |
config = config || {}; | |
InitAdapter(config); | |
return config; | |
}; | |
module.exports.afterModelCreate = function(Model, name) { | |
Model = Model || {}; | |
Model.prototype.config.Model = Model; | |
return Model; | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment