This repository has been archived by the owner on Apr 4, 2022. It is now read-only.
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Imported Kinto.js api module to its own package.
- Loading branch information
0 parents
commit 87c681c
Showing
16 changed files
with
1,677 additions
and
0 deletions.
There are no files selected for viewing
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
{ | ||
"env": { | ||
"development": { | ||
"presets": ["es2015"] | ||
} | ||
} | ||
} |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
{ | ||
"parser": "babel-eslint", | ||
"rules": { | ||
"comma-dangle": 0, | ||
"curly": 2, | ||
"indent": [2, 2], | ||
"linebreak-style": [2, "unix"], | ||
"no-console": 0, | ||
"no-unused-vars": [2, {"vars": "all", "args": "none"}], | ||
"no-var": 2, | ||
"prefer-const": 1, | ||
"quotes": [2, "double"], | ||
"semi": [2, "always"] | ||
}, | ||
"env": { | ||
"es6": true, | ||
"browser": true, | ||
"node": true | ||
}, | ||
"extends": "eslint:recommended", | ||
"root": true | ||
} |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
/.venv | ||
/dist | ||
/lib | ||
/npm-debug.log | ||
/coverage | ||
/esdoc | ||
/node_modules |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
/.venv | ||
/src |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
language: | ||
- node_js | ||
- python | ||
node_js: | ||
- "4" | ||
python: | ||
- "2.7" | ||
before_install: | ||
- export PATH=$HOME/.local/bin:$PATH | ||
- pip install --user `whoami` virtualenv | ||
- virtualenv .env | ||
- .env/bin/pip install kinto==1.11.0 | ||
- export KINTO_PSERVE_EXECUTABLE=.env/bin/pserve | ||
env: | ||
- ACTION=test | ||
- ACTION="run lint" | ||
- ACTION="run dist" # ensures building dist files doesn't break | ||
- ACTION="run build-demo" # ensures building the demo doesn't break | ||
script: | ||
- npm $ACTION | ||
after_script: | ||
- npm run report-coverage |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
Copyright 2015 - Mozilla Foundation | ||
|
||
Licensed under the Apache License, Version 2.0 (the "License"); | ||
you may not use this file except in compliance with the License. | ||
You may obtain a copy of the License at | ||
|
||
http://www.apache.org/licenses/LICENSE-2.0 | ||
|
||
Unless required by applicable law or agreed to in writing, software | ||
distributed under the License is distributed on an "AS IS" BASIS, | ||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
See the License for the specific language governing permissions and | ||
limitations under the License. |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
{ | ||
"source": "./src", | ||
"destination": "./esdoc", | ||
"test": { | ||
"type": "mocha", | ||
"source": "./test" | ||
}, | ||
"plugins": [ | ||
{ | ||
"name": "esdoc-importpath-plugin", | ||
"option": { | ||
"replaces": [ | ||
{"from": "^src", "to": "lib"} | ||
] | ||
} | ||
}, | ||
{ | ||
"name": "esdoc-es7-plugin" | ||
} | ||
] | ||
} |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
{ | ||
"name": "kinto-api.js", | ||
"version": "0.0.1", | ||
"description": "JavaScript HTTP client for the Kinto API.", | ||
"main": "lib/index.js", | ||
"scripts": { | ||
"build": "babel -d lib/ src/", | ||
"dist": "mkdir -p dist && rm -f dist/*.* && npm run dist-dev && npm run dist-prod && npm run dist-noshim", | ||
"dist-dev": "browserify -s KintoApi -d -e src/index.js -o dist/kinto-api.js-$npm_package_version.js -t [ babelify --sourceMapRelative . ]", | ||
"dist-noshim": "browserify -s KintoApi -g uglifyify --ignore isomorphic-fetch --ignore babel-polyfill -e src/index.js -o dist/kinto-api.js-$npm_package_version.noshim.js -t [ babelify --sourceMapRelative . ]", | ||
"dist-prod": "browserify -s KintoApi -g uglifyify -e src/index.js -o dist/kinto-api.js-$npm_package_version.min.js -t [ babelify --sourceMapRelative . ]", | ||
"report-coverage": "npm run test-cover && ./node_modules/coveralls/bin/coveralls.js < ./coverage/lcov.info", | ||
"tdd": "babel-node node_modules/.bin/_mocha --watch 'test/**/*_test.js'", | ||
"test": "npm run lint && npm run test-nocover", | ||
"test-cover": "babel-node node_modules/.bin/babel-istanbul cover --report text $npm_package_config_ISTANBUL_OPTS node_modules/.bin/_mocha -- 'test/**/*_test.js'", | ||
"test-cover-html": "babel-node node_modules/.bin/babel-istanbul cover --report html $npm_package_config_ISTANBUL_OPTS node_modules/.bin/_mocha -- 'test/**/*_test.js' && open coverage/index.html", | ||
"test-nocover": "babel-node node_modules/.bin/_mocha 'test/**/*_test.js'", | ||
"lint": "eslint src test" | ||
}, | ||
"repository": { | ||
"type": "git", | ||
"url": "git+https://github.com/Kinto/kinto-api.js.git" | ||
}, | ||
"keywords": [ | ||
"kinto", | ||
"http", | ||
"client", | ||
"api" | ||
], | ||
"author": "Mozilla <storage-team@mozilla.com>", | ||
"license": "Apache-2.0", | ||
"bugs": { | ||
"url": "https://github.com/Kinto/kinto-api.js/issues" | ||
}, | ||
"homepage": "https://github.com/Kinto/kinto-api.js#readme", | ||
"dependencies": { | ||
"isomorphic-fetch": "^2.2.1" | ||
}, | ||
"devDependencies": { | ||
"babel": "^6.3.26", | ||
"babel-cli": "^6.4.5", | ||
"babel-core": "^6.3.26", | ||
"babel-eslint": "^5.0.0-beta6", | ||
"babel-istanbul": "^0.6.0", | ||
"babel-loader": "^6.2.0", | ||
"babel-plugin-transform-es2015-modules-commonjs": "^6.4.0", | ||
"babel-polyfill": "^6.3.14", | ||
"babel-preset-es2015": "^6.3.13", | ||
"babelify": "^7.2.0", | ||
"browserify": "^13.0.0", | ||
"chai": "^3.4.1", | ||
"chai-as-promised": "^5.0.0", | ||
"coveralls": "^2.11.6", | ||
"esdoc": "^0.4.0", | ||
"esdoc-es7-plugin": "0.0.3", | ||
"esdoc-importpath-plugin": "0.0.1", | ||
"eslint": "^1.2.0", | ||
"mocha": "^2.3.4", | ||
"sinon": "^1.17.2", | ||
"uglifyify": "^3.0.1" | ||
} | ||
} |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
/** | ||
* Kinto server error code descriptors. | ||
* @type {Object} | ||
*/ | ||
export default { | ||
104: "Missing Authorization Token", | ||
105: "Invalid Authorization Token", | ||
106: "Request body was not valid JSON", | ||
107: "Invalid request parameter", | ||
108: "Missing request parameter", | ||
109: "Invalid posted data", | ||
110: "Invalid Token / id", | ||
111: "Missing Token / id", | ||
112: "Content-Length header was not provided", | ||
113: "Request body too large", | ||
114: "Resource was modified meanwhile", | ||
115: "Method not allowed on this end point", | ||
116: "Requested version not available on this server", | ||
117: "Client has sent too many requests", | ||
121: "Resource access is forbidden for this user", | ||
122: "Another resource violates constraint", | ||
201: "Service Temporary unavailable due to high load", | ||
202: "Service deprecated", | ||
999: "Internal Server Error", | ||
}; |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,173 @@ | ||
"use strict"; | ||
|
||
import ERROR_CODES from "./errors.js"; | ||
|
||
/** | ||
* Enhanced HTTP client for the Kinto protocol. | ||
*/ | ||
export default class HTTP { | ||
/** | ||
* Default HTTP request headers applied to each outgoing request. | ||
* | ||
* @type {Object} | ||
*/ | ||
static get DEFAULT_REQUEST_HEADERS() { | ||
return { | ||
"Accept": "application/json", | ||
"Content-Type": "application/json", | ||
}; | ||
} | ||
|
||
/** | ||
* Default options. | ||
* | ||
* @type {Object} | ||
*/ | ||
static get defaultOptions() { | ||
return {timeout: 5000, requestMode: "cors"}; | ||
} | ||
|
||
/** | ||
* Constructor. | ||
* | ||
* Options: | ||
* - {Number} timeout The request timeout in ms (default: `5000`). | ||
* - {String} requestMode The HTTP request mode (default: `"cors"`). | ||
* | ||
* @param {EventEmitter} events The event handler. | ||
* @param {Object} options The options object. | ||
*/ | ||
constructor(events, options={}) { | ||
// public properties | ||
/** | ||
* The event emitter instance. | ||
* @type {EventEmitter} | ||
*/ | ||
if (!events) { | ||
throw new Error("No events handler provided"); | ||
} | ||
this.events = events; | ||
|
||
options = Object.assign({}, HTTP.defaultOptions, options); | ||
|
||
/** | ||
* The request mode. | ||
* @see https://fetch.spec.whatwg.org/#requestmode | ||
* @type {String} | ||
*/ | ||
this.requestMode = options.requestMode; | ||
|
||
/** | ||
* The request timeout. | ||
* @type {Number} | ||
*/ | ||
this.timeout = options.timeout; | ||
} | ||
|
||
/** | ||
* Performs an HTTP request to the Kinto server. | ||
* | ||
* Options: | ||
* - `{Object} headers` The request headers object (default: {}) | ||
* | ||
* Resolves with an objet containing the following HTTP response properties: | ||
* - `{Number} status` The HTTP status code. | ||
* - `{Object} json` The JSON response body. | ||
* - `{Headers} headers` The response headers object; see the ES6 fetch() spec. | ||
* | ||
* @param {String} url The URL. | ||
* @param {Object} options The fetch() options object. | ||
* @return {Promise} | ||
*/ | ||
request(url, options={headers:{}}) { | ||
let response, status, statusText, headers, _timeoutId, hasTimedout; | ||
// Ensure default request headers are always set | ||
options.headers = Object.assign({}, HTTP.DEFAULT_REQUEST_HEADERS, options.headers); | ||
options.mode = this.requestMode; | ||
return new Promise((resolve, reject) => { | ||
_timeoutId = setTimeout(() => { | ||
hasTimedout = true; | ||
reject(new Error("Request timeout.")); | ||
}, this.timeout); | ||
fetch(url, options) .then(res => { | ||
if (!hasTimedout) { | ||
clearTimeout(_timeoutId); | ||
resolve(res); | ||
} | ||
}).catch(err => { | ||
if (!hasTimedout) { | ||
clearTimeout(_timeoutId); | ||
reject(err); | ||
} | ||
}); | ||
}) | ||
.then(res => { | ||
response = res; | ||
headers = res.headers; | ||
status = res.status; | ||
statusText = res.statusText; | ||
this._checkForDeprecationHeader(headers); | ||
this._checkForBackoffHeader(status, headers); | ||
return res.text(); | ||
}) | ||
// Check if we have a body; if so parse it as JSON. | ||
.then(text => { | ||
if (text.length === 0) { | ||
return null; | ||
} | ||
// Note: we can't consume the response body twice. | ||
return JSON.parse(text); | ||
}) | ||
.catch(err => { | ||
const error = new Error(`HTTP ${status || 0}; ${err}`); | ||
error.response = response; | ||
error.stack = err.stack; | ||
throw error; | ||
}) | ||
.then(json => { | ||
if (json && status >= 400) { | ||
let message = `HTTP ${status}; `; | ||
if (json.errno && json.errno in ERROR_CODES) { | ||
message += ERROR_CODES[json.errno]; | ||
if (json.message) { | ||
message += `: ${json.message}`; | ||
} | ||
} else { | ||
message += statusText || ""; | ||
} | ||
const error = new Error(message.trim()); | ||
error.response = response; | ||
error.data = json; | ||
throw error; | ||
} | ||
return {status, json, headers}; | ||
}); | ||
} | ||
|
||
_checkForDeprecationHeader(headers) { | ||
const alertHeader = headers.get("Alert"); | ||
if (!alertHeader) { | ||
return; | ||
} | ||
let alert; | ||
try { | ||
alert = JSON.parse(alertHeader); | ||
} catch(err) { | ||
console.warn("Unable to parse Alert header message", alertHeader); | ||
return; | ||
} | ||
console.warn(alert.message, alert.url); | ||
this.events.emit("deprecated", alert); | ||
} | ||
|
||
_checkForBackoffHeader(status, headers) { | ||
let backoffMs; | ||
const backoffSeconds = parseInt(headers.get("Backoff"), 10); | ||
if (backoffSeconds > 0) { | ||
backoffMs = (new Date().getTime()) + (backoffSeconds * 1000); | ||
} else { | ||
backoffMs = 0; | ||
} | ||
this.events.emit("backoff", backoffMs); | ||
} | ||
} |
Oops, something went wrong.