Comparing version 0.0.3 to 0.1.0
268
apisdk.js
@@ -1,147 +0,157 @@ | ||
void function() { | ||
/**/ void function() { | ||
// Supported methods | ||
var METHODS = [ 'GET', 'POST', 'PUT', 'DELETE', 'PATCH' ]; | ||
// UMD | ||
var umd = function(name, component) { | ||
switch(true) { | ||
// CommonJS | ||
case typeof module === 'object' && !!module.exports: | ||
module.exports = component; | ||
break; | ||
// AMD (Add a 'String' wrapper here to fuck webpack) | ||
case String(typeof define) === 'function' && !!define.amd: | ||
define(name, function() { return component; }); | ||
break; | ||
// Global | ||
default: | ||
/**/ try { /* Fuck IE8- */ | ||
/**/ if(typeof execScript === 'object') execScript('var ' + name); | ||
/**/ } catch(error) {} | ||
window[name] = component; | ||
} | ||
}; | ||
// Use to convert a API list to a tree struct | ||
var buildTree = function(list) { | ||
var root = {}; | ||
var i, j, temp, path, name; | ||
for(i = 0; i < list.length; i++) { | ||
temp = root; | ||
path = list[i].split(/\s+/).pop().slice(1).split('/'); | ||
for(j = 0; j < path.length; j++) { | ||
name = path[j].replace(/^(?:\{.*\}|:[\w-]*)$/, '_'); | ||
temp = temp[name] = Object(temp[name]); | ||
} | ||
// Internal Part class | ||
var Part = function(config) { | ||
if(config) this.config = config; | ||
}; | ||
// To convert a API list to a raw tree struct | ||
Part.listToRawTree = function(list) { | ||
var root = {}; | ||
var i, j, k, path, methods, name; | ||
for(i = 0; i < list.length; i++) { | ||
if(!/^(\S+)\s+\/(\S+)$/.test(list[i])) { | ||
throw new Error('What\'s the fucking api defintion "' + list[i] + '"?'); | ||
} | ||
return root; | ||
}; | ||
methods = RegExp.$1; | ||
path = RegExp.$2.split('/'); | ||
for(k = root, j = 0; j < path.length; j++) { | ||
// Supported formats: {xxx} [xxx] (xxx) <xxx> :xxx * | ||
name = path[j].replace(/^(?:\{.*\}|\[.*\]|\(.*\)|<.*>|:.*|\*)$/, '#rawSubTree'); | ||
k = k[name] = Object(k[name]); | ||
} | ||
methods = methods.replace(/.*\*.*/, 'GET,POST,PUT,DELETE,PATCH'); | ||
k['#methods'] = (k['#methods'] || []).concat(methods.match(/\w+/g)); | ||
} | ||
return root; | ||
}; | ||
// Convert callable to normal | ||
var resolveCallable = function(what) { | ||
if(typeof what !== 'function') return what; | ||
return resolveCallable(what()); | ||
}; | ||
// It's prototype is an array, every part of API path is an array item | ||
Part.prototype = []; | ||
// Convert any to string | ||
var resolveString = function(what, config) { | ||
return new config.promise(function(resolve) { | ||
if(typeof what === 'function') { | ||
resolveString(what(), config).then(function(e){ | ||
resolve(e); | ||
}); | ||
} else if(what && typeof what.then === 'function') { | ||
what.then(function(what) { | ||
resolveString(what, config).then(function(e) { | ||
resolve(e); | ||
}); | ||
}); | ||
} else { | ||
resolve(what + ''); | ||
} | ||
// Return the actual API path | ||
Part.prototype.getPath = function() { | ||
var that = this; | ||
var result = []; | ||
for(var i = 0; i < this.length; i++) { | ||
// Resolve function result | ||
result[i] = function callee(what) { | ||
if(typeof what !== 'function') return what; | ||
return callee(what()); | ||
}(this[i]); | ||
} | ||
if(this.config.promise) { | ||
return this.config.promise.all(result).then(function(path) { | ||
return that.wrapHost(path); | ||
}); | ||
}; | ||
} else { | ||
return this.wrapHost(result); | ||
} | ||
}; | ||
// Path node internal constructor | ||
var Node = function(name) { | ||
this.push(name); | ||
}; | ||
Node.prototype = []; | ||
Node.prototype.toString = function() { | ||
return Array.prototype.join.call(this, '/'); | ||
}; | ||
Node.prototype.getPath = function(config) { | ||
var result = []; | ||
for(var i = 0; i < this.length; i++) { | ||
result[i] = resolveCallable(this[i]); | ||
} | ||
if(config.promise) { | ||
return config.promise.all(result).then(function(path) { | ||
return path.join('/'); | ||
}); | ||
// Concat host to path | ||
Part.prototype.wrapHost = function(path) { | ||
var host = this.config.host; | ||
host = host == null ? '/api' : host + ''; | ||
if(host.charAt(host.length - 1) !== '/') host += '/'; | ||
host = host.replace(/^(?!\w+:\/\/)(?!\/)/, '/'); | ||
return host + path.join('/'); | ||
}; | ||
// Create child node that inherit from current node | ||
Part.prototype.createChild = function(name) { | ||
var Part = function() {}; | ||
Part.prototype = this; | ||
var node = new Part(); | ||
node.push(name); | ||
return node; | ||
}; | ||
// Create a callable HTTP method as property of current node | ||
Part.prototype.buildMethod = function(method) { | ||
var node = this; | ||
return function(data) { | ||
var what = node.getPath(); | ||
var launch = function(path) { | ||
return node.config.http({ method: method, url: path, data: data }); | ||
}; | ||
if(typeof what === 'string') { | ||
return launch(what); | ||
} else { | ||
return result.join('/'); | ||
return what.then(launch); | ||
} | ||
}; | ||
Node.prototype.createChild = function(name) { | ||
var Node = function() {}; | ||
Node.prototype = this; | ||
var node = new Node(); | ||
node.push(name); | ||
return node; | ||
}; | ||
// Load API path data into current node from a raw tree and return a handler | ||
Part.prototype.loadRawTree = function(rawTree) { | ||
var that = this; | ||
var rawSubTree = rawTree['#rawSubTree'] || {}; | ||
var methods = rawTree['#methods'] || []; | ||
var handler = function(name) { | ||
return handler[name] = that.createChild(name).loadRawTree(rawSubTree); | ||
}; | ||
Node.prototype.buildMethod = function(method, config) { | ||
var node = this; | ||
return function(data) { | ||
var what = node.getPath(config); | ||
var launch = function(path) { | ||
return config.http({ method: method, url: path, data: data }); | ||
}; | ||
if(typeof what === 'string') { | ||
return launch(what); | ||
} else { | ||
return what.then(launch); | ||
} | ||
}; | ||
}; | ||
// Tree walker | ||
var walker = function(subtree, node, config) { | ||
var chains = subtree._ || {}; | ||
var current = function(name) { | ||
return current[name] = walker(chains, node.createChild(name), config); | ||
}; | ||
for(var name in subtree) { | ||
if(!/^\w+$/.test(name)) continue; | ||
current[name] = walker(subtree[name], node.createChild(name), config); | ||
} | ||
for(var i in METHODS) { | ||
current[METHODS[i].toLowerCase()] = node.buildMethod(METHODS[i], config); | ||
} | ||
return current; | ||
for(var name in rawTree) { | ||
if(name.charAt(0) === '#') continue; | ||
handler[name] = this.createChild(name).loadRawTree(rawTree[name]); | ||
} | ||
for(var i = 0; i < methods.length; i++) { | ||
handler[methods[i].toLowerCase()] = this.buildMethod(methods[i]); | ||
} | ||
return handler; | ||
}; | ||
// Interface | ||
var APISDK = function(list, config) { | ||
config = Object(config); | ||
config.promise = config.promise || window.Promise; | ||
config.host = String(config.host || '/api'); | ||
// Check "http" service | ||
if(typeof config.http !== 'function') { | ||
warn('APISDK: You should provide a "http" service, otherwise no request can be launched.') | ||
config.http = function(params) { | ||
return { | ||
then: function(callback) { | ||
callback(params); | ||
return this; | ||
} | ||
}; | ||
}; | ||
} | ||
// Check "promise" service | ||
if(typeof config.promise !== 'function') { | ||
warn('APISDK: Strongly suggest to provide a "promise" service, otherwise the asynchronous parameter will not be supported.') | ||
} | ||
return walker(buildTree(list || []), new Node(config.host), config); | ||
}; | ||
// Send a warning | ||
var warn = function(message) { | ||
window.console && console.warn && console.warn(message); | ||
}; | ||
// Warning | ||
var warn = function(message) { | ||
window.console && console.warn && console.warn(message); | ||
}; | ||
// Match loaders | ||
if(this.define && this.define.amd) { | ||
// For AMD | ||
define('APISDK', function() { return APISDK; }); | ||
} else if(this.angular) { | ||
// For angular | ||
angular.module('APISDK', []).factory('APISDK', function() { return APISDK; }); | ||
} else { | ||
// For global | ||
new Function('return this')().APISDK = APISDK; | ||
// Interface | ||
var Apisdk = function(list, config) { | ||
config = Object(config); | ||
config.promise = config.promise || window.Promise; | ||
// Check "http" service | ||
if(typeof config.http !== 'function') { | ||
warn('Apisdk: You should provide a "http" service, otherwise no request can be launched.') | ||
config.http = function(params) { | ||
return { | ||
then: function(callback) { | ||
callback(params); | ||
return this; | ||
} | ||
}; | ||
}; | ||
} | ||
// Check "promise" service | ||
if(typeof config.promise !== 'function') { | ||
warn('Apisdk: Strongly suggest to provide a "promise" service, otherwise the asynchronous parameter will not be supported.') | ||
} | ||
return new Part(config).loadRawTree(Part.listToRawTree(list)); | ||
}; | ||
}(); | ||
umd('Apisdk', Apisdk); | ||
umd('APISDK', Apisdk); <!-- Discarded, to be compatible with old version | ||
/**/ }(); |
{ | ||
"name": "apisdk", | ||
"main": "apisdk.js", | ||
"version": "0.0.3", | ||
"version": "0.1.0", | ||
"authors": [ | ||
@@ -6,0 +6,0 @@ "YanagiEiichi <admin@web-tinker.com>" |
{ | ||
"name": "apisdk", | ||
"version": "0.0.3", | ||
"version": "0.1.0", | ||
"main": "apisdk.js", | ||
@@ -5,0 +5,0 @@ "directories": { |
@@ -10,5 +10,5 @@ # apisdk.js | ||
'POST /articles', | ||
'GET /articles/{article_id}', | ||
'PUT /articles/{article_id}', | ||
'DELETE /articles/{article_id}' | ||
'GET /articles/:id', | ||
'PUT /articles/:id', | ||
'DELETE /articles/:id' | ||
], { | ||
@@ -22,5 +22,5 @@ 'host': '/api', | ||
var article_id = 123; | ||
var id = 123; | ||
// { "method": "get", "url": "/api/articles/123", "data": { "token": 789 } } | ||
api.articles(article_id).get({ token: 789 }); | ||
api.articles(id).get({ token: 789 }); | ||
@@ -30,5 +30,5 @@ // Dynamic parameter is supported | ||
var nextArticle = api.articles(function() { return inc++; }); | ||
// { "method": "get", "url": "/api/articles/0", "data": null } | ||
// { method: "GET", url: "/api/articles/0", data: undefined } | ||
nextArticle.get(); | ||
// { "method": "get", "url": "/api/articles/1", "data": null } | ||
// { method: "GET", url: "/api/articles/1", data: undefined } | ||
nextArticle.get(); | ||
@@ -38,2 +38,3 @@ | ||
var asyncParam = new Promise(function(resolve){ setTimeout(resolve, 1000, 123); }); | ||
// The request will be launched after the promise resolved | ||
@@ -47,10 +48,10 @@ api.articles(asyncParam).get(); | ||
/** | ||
* GET /users/{user_id}/ | ||
* GET /users/{user_id}/orders | ||
* POST /users/{user_id}/orders | ||
* GET /users/{user_id}/orders/{order_id} | ||
* POST /users/{user_id}/orders/{order_id}/payment | ||
* POST /users/{user_id}/orders/{order_id}/rating | ||
* POST /users/{user_id}/orders/{order_id}/cancel | ||
* POST /users/{user_id}/orders/{order_id}/refunding | ||
* GET /users/:user_id/ | ||
* GET /users/:user_id/orders | ||
* POST /users/:user_id/orders | ||
* GET /users/:user_id/orders/:order_id | ||
* POST /users/:user_id/orders/:order_id/payment | ||
* POST /users/:user_id/orders/:order_id/rating | ||
* POST /users/:user_id/orders/:order_id/cancel | ||
* POST /users/:user_id/orders/:order_id/refunding | ||
**/ | ||
@@ -85,14 +86,2 @@ | ||
### Run Demo | ||
```bash | ||
git clone git@github.com:YanagiEiichi/apisdk | ||
cd apisdk/demo | ||
bower install | ||
cd .. | ||
python -m SimpleHTTPServer | ||
``` | ||
[http://localhost:8000/demo/](http://localhost:8000/demo/) | ||
### Install | ||
@@ -105,4 +94,3 @@ | ||
```html | ||
<script src="bower_components/apisdk/apisdk.js"></script> | ||
<script src="/bower_components/apisdk/apisdk.js"></script> | ||
``` | ||
@@ -17,4 +17,5 @@ { | ||
"dependencies": { | ||
"tester": "~0.0.11" | ||
"tester": "~0.0.12", | ||
"requirejs": "~2.1.20" | ||
} | ||
} |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
15255
16
182
90