Last active
May 26, 2023 03:18
-
-
Save gabecoyne/da8d23d5c31be2d5aacbe6ed5b78ebd8 to your computer and use it in GitHub Desktop.
ActiveResource.js
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
/** | |
* @providesModule ActiveResource | |
**/ | |
'use strict'; | |
var _ = require('underscore'); | |
export default class ActiveResource { | |
static remote : object; // Remote | |
static base_route : string; // /api/v1/resource | |
// create instance - new AR(resource) | |
constructor(resource: object){ | |
this.attributes = resource; | |
// create attribute if not defined | |
_.each(resource, (v,k) => { if( !this[k] ) this[k] = v; }) | |
} | |
attr(key){ | |
return this.attributes[key]; | |
} | |
static all(callback?:() => [ActiveResource], params = {}){ | |
this.remote.get(this.base_route, params, (resources) => { | |
if(callback) callback(_.map(resources, (resource) => { return new this(resource) })); | |
}); | |
} | |
static find(id, callback?:() => ActiveResource, params = {}){ | |
this.remote.get(this.base_route+"/"+id, params, (resource) => { | |
if(callback) callback(new this(resource)) | |
}); | |
} | |
static create(params, callback?:() => ActiveResource){ | |
// TODO: update local instance | |
this.remote.post(this.base_route, params, (resource) => { | |
if(callback) callback(new this(resource)) | |
}); | |
} | |
// params must include id | |
static update(params, callback?:() => ActiveResource){ | |
if(!params.id) return; | |
// TODO: update local instance | |
this.remote.put(this.base_route+"/"+id, params, (resource) => { | |
if(callback) callback(new this(resource)) | |
}); | |
} | |
static save(callback?:() => ActiveResource){ | |
this.remote.put(this.base_route+"/"+this.attributes.id, this.attributes, (resource) => { | |
if(callback && resource && resource.id) callback(new this(resource)); | |
}); | |
} | |
static destroy(id, callback){ | |
this.remote.del(this.base_route+"/"+id, {}, (result) => { | |
if(callback) callback(result); | |
}); | |
} | |
// wrap response collection as instance objects | |
// resources/action.json | |
// we expect this to be some scope that returns a collection of resouces | |
static get(endpoint, params, callback){ | |
this.remote.get(this.base_route+endpoint, params, (resources) => { | |
if(callback) callback(_.map(resources, (resource) => { return new this(resource) })); | |
}); | |
} | |
// don't wrap response in new instances | |
static get_json(endpoint, params, callback){ | |
this.remote.get(this.base_route+endpoint, params, callback) | |
} | |
reload(callback){ | |
this.constructor.find(this.id, (resource) => { | |
_.extend(this.attributes, resource.attributes); | |
_.each(resource.attributes, (v,k) => { if(!_.isFunction(this[k])) this[k] = v; }); | |
if(callback) callback(this); | |
}) | |
} | |
set(key, val){ | |
this.attributes[key] = val; | |
if(!_.isFunction(this[key])) this[key] = val; | |
} | |
// we don't expect this to be this instance type | |
// /resources/:id/action.js | |
get(endpoint, params, callback){ | |
this.constructor.remote.get(this.constructor.base_route+endpoint, params, callback); | |
} | |
} |
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
import RemoteService from 'RemoteService'; | |
import ActiveResource from 'ActiveResource'; | |
var MyService = new RemoteService("https://myservice.com", { api_key: 'top-secret' }); | |
export default class MyResource extends ActiveResource { | |
static remote = MyService; | |
static base_route = '/api/v1/my_resources'; | |
// attribute getter overrides | |
// zero pad all ids | |
get id(){ | |
return _.lpad(this.attributes.id, 8, '0'); | |
} | |
} | |
MyResource.all((resource) => { | |
console.log(resource.id); // zero padded ids | |
}) | |
// crud api with attr getter overrides | |
var my_resource = MyResource.create({ title: 'new' }); | |
var my_resource = MyResource.find(my_resource.id); | |
my_resource.update({title: 'test'}); | |
my_resource.set('title', 'test2'); | |
my_resource.save(); | |
my_resource.destroy(); |
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
/** | |
* @providesModule RemoteService | |
**/ | |
'use strict'; | |
const _ = require('underscore'); | |
const SuperAgent = require('superagent'); | |
/** | |
* Usage: | |
* var MyService = new RemoteService("https://myservice.com/api/v1", { | |
* default_param: value | |
* }); | |
*/ | |
export default class RemoteService { | |
constructor(host:string, default_params:object){ | |
this.host = host; | |
this.default_params = default_params; | |
} | |
endpoint(path, host) { | |
return this.host+path; | |
}; | |
url(path){ | |
var u = this.host+path+"?"+this.obj_to_query(this.params()) | |
return u; | |
}; | |
obj_to_query(obj, key){ | |
return _.map(obj,(v,k) => { | |
if (_.isObject(v)) return this.obj_to_query(v, k); | |
if (key){ | |
return key + '[' + k + ']=' + encodeURIComponent(v); | |
} else { | |
return k + '=' + encodeURIComponent(v); | |
} | |
}).join('&'); | |
}; | |
params(values) { | |
return _.extend({}, this.default_params, values); | |
}; | |
this.get = async function(endpoint, params, success, error, host) { | |
params = this.params(params); | |
var uri = this.endpoint(endpoint, host); | |
// Handle nested params | |
_.each(params, (val, key) => { | |
if (typeof(val) === "object"){ | |
_.each(val, (v,k) => { params[key +"["+k+"]"] = v }) | |
delete params[key]; | |
} | |
}); | |
SuperAgent.get(uri) | |
.query(params) | |
.end((err, res) => { | |
this.on_response(endpoint, err, res, success, error); | |
}); | |
}; | |
this.post = async function(endpoint, params, success, error, host) { | |
params = this.params(params); | |
var uri = this.endpoint(endpoint, host); | |
SuperAgent.post(uri) | |
.set('Content-Type', 'application/json') | |
.send(JSON.stringify(params)) | |
.end((err, res) => { | |
this.on_response(endpoint, err, res, success, error); | |
}); | |
}, | |
this.put = async function(endpoint, params, success, error, host) { | |
params = this.params(params); | |
var uri = this.endpoint(endpoint, host); | |
SuperAgent.put(uri) | |
.set('Content-Type', 'application/json') | |
.send(params) | |
.end((err, res) => { | |
this.on_response(endpoint, err, res, success, error); | |
}); | |
}; | |
this.del = async function(endpoint, id, params, success, error, host) { | |
params = this.params(params); | |
var uri = this.endpoint(endpoint, host); | |
SuperAgent.del(`${uri}/${id}`) | |
.set('Content-Type', 'application/json') | |
.send(params) | |
.end((err, res) => { | |
this.on_response(endpoint, err, res, success, error); | |
}); | |
}; | |
this.on_response = async function(endpoint, err, res, success, error) { | |
var json = null; | |
if(err && error) error(err); | |
if(res) { | |
// TODO: check res.code == 200 | |
try { | |
var cleaned_string = JSONHelper.clean_string(res.text) | |
json = JSON.parse(cleaned_string); | |
} catch(e) { | |
if(error) error(e); | |
} | |
if(success) success(json); | |
} | |
}; | |
}; | |
module.exports = RemoteService; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment