From 97dc29d94164ec2fd8f82291c9ace1a2d412e170 Mon Sep 17 00:00:00 2001 From: Jordan Wallet Date: Mon, 2 Apr 2018 13:42:26 -0700 Subject: [PATCH 1/9] Draft of XMLHttpRequest support, package out of date --- src/infrastructure/BaseService.js | 6 +++++- src/infrastructure/RequestHelper.js | 19 ++++++++++++------- src/infrastructure/XMLHttpRequester.js | 12 ++++++++++++ 3 files changed, 29 insertions(+), 8 deletions(-) create mode 100644 src/infrastructure/XMLHttpRequester.js diff --git a/src/infrastructure/BaseService.js b/src/infrastructure/BaseService.js index cdbf78cc..7b4d28a7 100644 --- a/src/infrastructure/BaseService.js +++ b/src/infrastructure/BaseService.js @@ -1,9 +1,13 @@ import URLJoin from 'url-join'; +import Request from 'request-promise'; +import XMLHttpRequester from './XMLHttpRequester'; class BaseModel { - constructor({ url = 'https://gitlab.com', token, oauthToken }) { + constructor({ url = 'https://gitlab.com', token, oauthToken, useXMLHttpRequest = false }) { this.url = URLJoin(url, 'api', 'v4'); this.headers = {}; + this.requester = useXMLHttpRequest ? XMLHttpRequester : Request; + this.useXMLHttpRequest = useXMLHttpRequest; if (oauthToken) { this.headers.Authorization = `Bearer ${oauthToken}`; diff --git a/src/infrastructure/RequestHelper.js b/src/infrastructure/RequestHelper.js index 5fee2a0e..2dccdcee 100644 --- a/src/infrastructure/RequestHelper.js +++ b/src/infrastructure/RequestHelper.js @@ -1,12 +1,12 @@ -import Request from 'request-promise'; import Humps from 'humps'; import LinkParser from 'parse-link-header'; +import QS from 'qs'; import URLJoin from 'url-join'; function defaultRequest( url, endpoint, - { headers, body, qs, formData, resolveWithFullResponse = false }, + { headers, body, qs, formData, resolveWithFullResponse = false, useXMLHttpRequest }, ) { const params = { url: URLJoin(url, endpoint), @@ -15,7 +15,12 @@ function defaultRequest( }; if (body) params.body = Humps.decamelizeKeys(body); - if (qs) params.qs = Humps.decamelizeKeys(qs); + if (qs) { + if (useXMLHttpRequest) { + // The xhr package doesn't have a way of passing in a qs object until v3 + params.url = URLJoin(params.url, `?${QS.stringify(qs)}`); + } else params.qs = Humps.decamelizeKeys(qs); + } if (formData) params.formData = formData; params.resolveWithFullResponse = resolveWithFullResponse; @@ -25,7 +30,7 @@ function defaultRequest( class RequestHelper { static async get(service, endpoint, options = {}) { - const response = await Request.get(defaultRequest(service.url, endpoint, { + const response = await service.requester.get(defaultRequest(service.url, endpoint, { headers: service.headers, qs: options, resolveWithFullResponse: true, @@ -48,21 +53,21 @@ class RequestHelper { static post(service, endpoint, options = {}, form = false) { const body = form ? 'fromData' : 'body'; - return Request.post(defaultRequest(service.url, endpoint, { + return service.requester.post(defaultRequest(service.url, endpoint, { headers: service.headers, [body]: options, })); } static put(service, endpoint, options = {}) { - return Request.put(defaultRequest(service.url, endpoint, { + return service.requester.put(defaultRequest(service.url, endpoint, { headers: service.headers, body: options, })); } static delete(service, endpoint, options = {}) { - return Request.delete(defaultRequest(service.url, endpoint, { + return service.requester.delete(defaultRequest(service.url, endpoint, { headers: service.headers, qs: options, })); diff --git a/src/infrastructure/XMLHttpRequester.js b/src/infrastructure/XMLHttpRequester.js new file mode 100644 index 00000000..385cc3bd --- /dev/null +++ b/src/infrastructure/XMLHttpRequester.js @@ -0,0 +1,12 @@ +import { promisify as Promisify } from 'util'; +import XHR from 'xhr'; + +const XMLHttpRequester = Promisify(XHR); +XMLHttpRequester.del = Promisify(XHR.del); +XMLHttpRequester.get = Promisify(XHR.get); +XMLHttpRequester.head = Promisify(XHR.head); +XMLHttpRequester.patch = Promisify(XHR.patch); +XMLHttpRequester.post = Promisify(XHR.post); +XMLHttpRequester.put = Promisify(XHR.put); + +export default XMLHttpRequester; From f05610479d61ea717bef22cd97c1388236ccd088 Mon Sep 17 00:00:00 2001 From: Jordan Wallet Date: Mon, 2 Apr 2018 15:44:46 -0700 Subject: [PATCH 2/9] Make compatible with Node 7, update package.json (but not package-lock) --- package.json | 5 ++++- src/infrastructure/XMLHttpRequester.js | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index a6a83d59..24d0660e 100644 --- a/package.json +++ b/package.json @@ -46,8 +46,11 @@ "humps": "^2.0.1", "lodash.pick": "^4.4.0", "parse-link-header": "^1.0.1", + "qs": "^6.5.1", "request": "^2.85.0", "request-promise": "^4.2.2", - "url-join": "^4.0.0" + "url-join": "^4.0.0", + "util.promisify": "^1.0.0", + "xhr": "^2.4.1" } } diff --git a/src/infrastructure/XMLHttpRequester.js b/src/infrastructure/XMLHttpRequester.js index 385cc3bd..be88f258 100644 --- a/src/infrastructure/XMLHttpRequester.js +++ b/src/infrastructure/XMLHttpRequester.js @@ -1,4 +1,4 @@ -import { promisify as Promisify } from 'util'; +import Promisify from 'util.promisify'; import XHR from 'xhr'; const XMLHttpRequester = Promisify(XHR); From 05b524f5acb4b69146e11c5fc3b0051154bd99d9 Mon Sep 17 00:00:00 2001 From: Jordan Wallet Date: Tue, 3 Apr 2018 11:56:53 -0700 Subject: [PATCH 3/9] Fix useXMLHttpRequest passing --- src/infrastructure/RequestHelper.js | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/infrastructure/RequestHelper.js b/src/infrastructure/RequestHelper.js index 2dccdcee..c91e205f 100644 --- a/src/infrastructure/RequestHelper.js +++ b/src/infrastructure/RequestHelper.js @@ -4,9 +4,9 @@ import QS from 'qs'; import URLJoin from 'url-join'; function defaultRequest( - url, + { url, useXMLHttpRequest }, endpoint, - { headers, body, qs, formData, resolveWithFullResponse = false, useXMLHttpRequest }, + { headers, body, qs, formData, resolveWithFullResponse = false }, ) { const params = { url: URLJoin(url, endpoint), @@ -30,7 +30,7 @@ function defaultRequest( class RequestHelper { static async get(service, endpoint, options = {}) { - const response = await service.requester.get(defaultRequest(service.url, endpoint, { + const response = await service.requester.get(defaultRequest(service, endpoint, { headers: service.headers, qs: options, resolveWithFullResponse: true, @@ -53,21 +53,21 @@ class RequestHelper { static post(service, endpoint, options = {}, form = false) { const body = form ? 'fromData' : 'body'; - return service.requester.post(defaultRequest(service.url, endpoint, { + return service.requester.post(defaultRequest(service, endpoint, { headers: service.headers, [body]: options, })); } static put(service, endpoint, options = {}) { - return service.requester.put(defaultRequest(service.url, endpoint, { + return service.requester.put(defaultRequest(service, endpoint, { headers: service.headers, body: options, })); } static delete(service, endpoint, options = {}) { - return service.requester.delete(defaultRequest(service.url, endpoint, { + return service.requester.delete(defaultRequest(service, endpoint, { headers: service.headers, qs: options, })); From 51d62966c8e0a30a48e328d85411f87e33161a2f Mon Sep 17 00:00:00 2001 From: Jake Krammer Date: Tue, 3 Apr 2018 12:15:40 -0700 Subject: [PATCH 4/9] Update package-lock.json --- package-lock.json | 106 ++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 89 insertions(+), 17 deletions(-) diff --git a/package-lock.json b/package-lock.json index a8fe2f0f..19d5e8f1 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1315,7 +1315,6 @@ "version": "1.1.2", "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.2.tgz", "integrity": "sha1-g6c/L+pWmJj7c3GTyPhzyvbUXJQ=", - "dev": true, "requires": { "foreach": "2.0.5", "object-keys": "1.0.11" @@ -1350,6 +1349,11 @@ "esutils": "2.0.2" } }, + "dom-walk": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/dom-walk/-/dom-walk-0.1.1.tgz", + "integrity": "sha1-ZyIm3HTI95mtNTB9+TaroRrNYBg=" + }, "ecc-jsbn": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz", @@ -1387,7 +1391,6 @@ "version": "1.7.0", "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.7.0.tgz", "integrity": "sha1-363ndOAb/Nl/lhgCmMRJyGI/uUw=", - "dev": true, "requires": { "es-to-primitive": "1.1.1", "function-bind": "1.1.0", @@ -1399,7 +1402,6 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.1.1.tgz", "integrity": "sha1-RTVSSKiJeQNLZ5Lhm7gfK3l13Q0=", - "dev": true, "requires": { "is-callable": "1.1.3", "is-date-object": "1.0.1", @@ -1856,6 +1858,14 @@ "write": "0.2.1" } }, + "for-each": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.2.tgz", + "integrity": "sha1-LEBFC5NI6X8oEyJZO6lnBLmr1NQ=", + "requires": { + "is-function": "1.0.1" + } + }, "for-in": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", @@ -1874,8 +1884,7 @@ "foreach": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/foreach/-/foreach-2.0.5.tgz", - "integrity": "sha1-C+4AUBiusmDQo6865ljdATbsG5k=", - "dev": true + "integrity": "sha1-C+4AUBiusmDQo6865ljdATbsG5k=" }, "forever-agent": { "version": "0.6.1", @@ -2811,8 +2820,7 @@ "function-bind": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.0.tgz", - "integrity": "sha1-FhdnFMgBeY5Ojyz391KUZ7tKV3E=", - "dev": true + "integrity": "sha1-FhdnFMgBeY5Ojyz391KUZ7tKV3E=" }, "functional-red-black-tree": { "version": "1.0.1", @@ -2861,6 +2869,15 @@ "is-glob": "2.0.1" } }, + "global": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/global/-/global-4.3.2.tgz", + "integrity": "sha1-52mJJopsdMOJCLEwWxD8DjlOnQ8=", + "requires": { + "min-document": "2.19.0", + "process": "0.5.2" + } + }, "globby": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/globby/-/globby-5.0.0.tgz", @@ -2899,7 +2916,6 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/has/-/has-1.0.1.tgz", "integrity": "sha1-hGFzP1OLCDfJNh45qauelwTcLyg=", - "dev": true, "requires": { "function-bind": "1.1.0" } @@ -3055,14 +3071,12 @@ "is-callable": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.3.tgz", - "integrity": "sha1-hut1OSgF3cM69xySoO7fdO52BLI=", - "dev": true + "integrity": "sha1-hut1OSgF3cM69xySoO7fdO52BLI=" }, "is-date-object": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.1.tgz", - "integrity": "sha1-mqIOtq7rv/d/vTPnTKAbM1gdOhY=", - "dev": true + "integrity": "sha1-mqIOtq7rv/d/vTPnTKAbM1gdOhY=" }, "is-dotfile": { "version": "1.0.3", @@ -3097,6 +3111,11 @@ "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", "dev": true }, + "is-function": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-function/-/is-function-1.0.1.tgz", + "integrity": "sha1-Es+5i2W1fdPRk6MSH19uL0N2ArU=" + }, "is-glob": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", @@ -3167,7 +3186,6 @@ "version": "1.0.4", "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.4.tgz", "integrity": "sha1-VRdIm1RwkbCTDglWVM7SXul+lJE=", - "dev": true, "requires": { "has": "1.0.1" } @@ -3187,8 +3205,7 @@ "is-symbol": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.1.tgz", - "integrity": "sha1-PMWfAAJRlLarLjjbrmaJJWtmBXI=", - "dev": true + "integrity": "sha1-PMWfAAJRlLarLjjbrmaJJWtmBXI=" }, "is-typedarray": { "version": "1.0.0", @@ -3424,6 +3441,14 @@ "integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==", "dev": true }, + "min-document": { + "version": "2.19.0", + "resolved": "https://registry.npmjs.org/min-document/-/min-document-2.19.0.tgz", + "integrity": "sha1-e9KC4/WELtKVu3SM3Z8f+iyCRoU=", + "requires": { + "dom-walk": "0.1.1" + } + }, "minimatch": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", @@ -3518,8 +3543,16 @@ "object-keys": { "version": "1.0.11", "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.0.11.tgz", - "integrity": "sha1-xUYBd4rVYPEULODgG8yotW0TQm0=", - "dev": true + "integrity": "sha1-xUYBd4rVYPEULODgG8yotW0TQm0=" + }, + "object.getownpropertydescriptors": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.0.3.tgz", + "integrity": "sha1-h1jIRvW0B62rDyNuCYbxSwUcqhY=", + "requires": { + "define-properties": "1.1.2", + "es-abstract": "1.7.0" + } }, "object.omit": { "version": "2.0.1", @@ -3616,6 +3649,15 @@ "is-glob": "2.0.1" } }, + "parse-headers": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/parse-headers/-/parse-headers-2.0.1.tgz", + "integrity": "sha1-aug6eqJanZtwCswoaYzR8e1+lTY=", + "requires": { + "for-each": "0.3.2", + "trim": "0.0.1" + } + }, "parse-json": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", @@ -3728,6 +3770,11 @@ "integrity": "sha512-VvivMrbvd2nKkiG38qjULzlc+4Vx4wm/whI9pQD35YrARNnhxeiRktSOhSukRLFNlzg6Br/cJPet5J/u19r/mg==", "dev": true }, + "process": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/process/-/process-0.5.2.tgz", + "integrity": "sha1-FjjYqONML0QKkduVq5rrZ3/Bhc8=" + }, "process-nextick-args": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz", @@ -4345,6 +4392,11 @@ "punycode": "1.4.1" } }, + "trim": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/trim/-/trim-0.0.1.tgz", + "integrity": "sha1-WFhUf2spB1fulczMZm+1AITEYN0=" + }, "trim-right": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/trim-right/-/trim-right-1.0.1.tgz", @@ -4425,6 +4477,15 @@ "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", "dev": true }, + "util.promisify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/util.promisify/-/util.promisify-1.0.0.tgz", + "integrity": "sha512-i+6qA2MPhvoKLuxnJNpXAGhg7HphQOSUq2LKMZD0m15EiskXUkMvKdF4Uui0WYeCUGea+o2cw/ZuwehtfsrNkA==", + "requires": { + "define-properties": "1.1.2", + "object.getownpropertydescriptors": "2.0.3" + } + }, "uuid": { "version": "3.2.1", "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.2.1.tgz", @@ -4486,6 +4547,17 @@ "mkdirp": "0.5.1" } }, + "xhr": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/xhr/-/xhr-2.4.1.tgz", + "integrity": "sha512-pAIU5vBr9Hiy5cpFIbPnwf0C18ZF86DBsZKrlsf87N5De/JbA6RJ83UP/cv+aljl4S40iRVMqP4pr4sF9Dnj0A==", + "requires": { + "global": "4.3.2", + "is-function": "1.0.1", + "parse-headers": "2.0.1", + "xtend": "4.0.1" + } + }, "xtend": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", From 1f31bdaae23fda282bd94f98b741db917b836743 Mon Sep 17 00:00:00 2001 From: Jordan Wallet Date: Tue, 3 Apr 2018 12:36:24 -0700 Subject: [PATCH 5/9] Add documentation for XHR option Also removed trailing whitespace from "//Can be created in your profile", and since I was doing that anyway, added a space between "//" and "Can" --- README.md | 46 +++++++++++++++++++++++++++++++--------------- 1 file changed, 31 insertions(+), 15 deletions(-) diff --git a/README.md b/README.md index 0a388137..1748a0fc 100644 --- a/README.md +++ b/README.md @@ -139,7 +139,7 @@ const Gitlab = require('node-gitlab-api/dist/es5').default // Instantiating const api = new Gitlab({ url: 'http://example.com', // Defaults to http://gitlab.com - token: 'abcdefghij123456' //Can be created in your profile. + token: 'abcdefghij123456' // Can be created in your profile. }) // Or, use a OAuth token instead! @@ -160,7 +160,7 @@ import { Projects } from 'node-gitlab-api'; const service = new Projects({ url: 'http://example.com', // Defaults to http://gitlab.com - token: 'abcdefghij123456' //Can be created in your profile. + token: 'abcdefghij123456' // Can be created in your profile. }) ``` @@ -175,7 +175,7 @@ import { ProjectsBundle } from 'node-gitlab-api'; const services = new ProjectsBundle({ url: 'http://example.com', // Defaults to http://gitlab.com - token: 'abcdefghij123456' //Can be created in your profile. + token: 'abcdefghij123456' // Can be created in your profile. }) services.Projects.all() @@ -253,6 +253,22 @@ EpicNotes EpicDiscussions ``` +### Using XMLHttpRequest +This package uses the [Request](https://github.com/request/request) library by default, which is built into Node. However, if your code is running in a browser, you can get better built-in resolution of proxies and self-signed certificates by using the browser's XMLHttpRequest implementation instead: + +```javascript +import Gitlab from 'node-gitlab-api'; + +const api = new Gitlab({ + url: 'http://example.com', // Defaults to http://gitlab.com + token: 'abcdefghij123456', // Can be created in your profile. + + useXMLHttpRequest: true // Use the browser's XMLHttpRequest instead of Node's Request library +}) +``` + +**WARNING:** Currently this option does not support the `multipart/form-data` content type, and therefore the endpoint for [uploading a file to a project](https://docs.gitlab.com/ee/api/projects.html#upload-a-file) will not work correctly. All other endpoints should work exactly as expected. + ### Examples Once you have your library instantiated, you can utilize many of the API's functionality: @@ -263,7 +279,7 @@ import Gitlab from 'node-gitlab-api'; const api = new Gitlab({ url: 'http://example.com', // Defaults to http://gitlab.com - token: 'abcdefghij123456' //Can be created in your profile. + token: 'abcdefghij123456' // Can be created in your profile. }); // Listing users @@ -280,14 +296,14 @@ General rule about all the function parameters: - If its a required parameter, it is a named argument in the functions - If its an optional parameter, it is defined in a options object following the named arguments -ie. +ie. ```javascript import Gitlab from 'node-gitlab-api'; const api = new Gitlab({ url: 'http://example.com', // Defaults to http://gitlab.com - token: 'abcdefghij123456' //Can be created in your profile. + token: 'abcdefghij123456' // Can be created in your profile. }); api.Projects.create(projectId, { @@ -305,7 +321,7 @@ import Gitlab from 'node-gitlab-api'; const api = new Gitlab({ url: 'http://example.com', // Defaults to http://gitlab.com - token: 'abcdefghij123456' //Can be created in your profile. + token: 'abcdefghij123456' // Can be created in your profile. }); let projects = await api.Projects.all({maxPages:2}); @@ -319,7 +335,7 @@ import Gitlab from 'node-gitlab-api'; const api = new Gitlab({ url: 'http://example.com', // Defaults to http://gitlab.com - token: 'abcdefghij123456' //Can be created in your profile. + token: 'abcdefghij123456' // Can be created in your profile. }); let projects = await api.Projects.all({maxPages:2, perPage:40}); @@ -349,7 +365,7 @@ This started off as a fork from [node-gitlab](https://github.com/node-gitlab/nod - [Christoph Lehmann](https://github.com/christophlehmann) - [Frank V](https://github.com/FrankV01) - [Salim Benabbou](https://github.com/Salimlou) -- [Tamás Török-Vistai](https://github.com/tvtamas) +- [Tamás Török-Vistai](https://github.com/tvtamas) - [Martin Benninger](https://github.com/MartinBenninger) - [Adam Dehnel](https://github.com/arsdehnel) - [fewieden](https://github.com/fewieden) @@ -442,7 +458,7 @@ Runners = ProjectRunners + Runners. ProjectId is optional for all() [2.2.3](https://github.com/jdalrymple/node-gitlab-api/ce7f17693168b5dec3b36eb1d5ab796c9374613f) (2018-2-3) ------------------ -- Fixed #37 - Bug within the customAttributes logic +- Fixed #37 - Bug within the customAttributes logic [2.2.2](https://github.com/jdalrymple/node-gitlab-api/ca1906879d869bf5b9aca0b2f64e46c89f3b5f4f) (2018-1-24) ------------------ @@ -471,7 +487,7 @@ how to run locally via npm linking for Development testing thanks to [Adam Dehne - Updating project docs for consistency - Adding project unsharing to API. It was in the docs, but missing from the API - Updating deprecated protected branches endpoint. Previously this was `projects.branches.protect` now its `projects.protectedBranches.protect` -- Added Owned Runners and Runner Jobs API +- Added Owned Runners and Runner Jobs API ### Breaking Changes between 1.3.3 and 2.1.0 - The `list` functions are no longer supported and have all been renamed to `all` @@ -489,7 +505,7 @@ how to run locally via npm linking for Development testing thanks to [Adam Dehne - Updating pagination changes into v2.0.1 - Removed unused labels endpoint since it already exists under projects.labels - Added a mergeRequests class for the merge_requests endpoints -- Extended the ProjectMergeRequests class for additional functionality that was missing for project merge requests such as +- Extended the ProjectMergeRequests class for additional functionality that was missing for project merge requests such as accepting merge requests, cancelling merges when the pipeline succeeds, listing issues that will close on merge, subscribing/unsubscribing to merges, creating todos, time spent and time estimates as well as time stats. - Fixed the notes endpoints for ProjectMergeRequests. This can now be access via projects.mergeRequests.notes.[command here] - Added comments endpoints to the ProjectRepositoryCommits class @@ -499,7 +515,7 @@ accepting merge requests, cancelling merges when the pipeline succeeds, listing [1.3.3](https://github.com/jdalrymple/node-gitlab-api/b8a3db4a4aaf9482fb3905883d92d940babfb461) (2017-11-29) ------------------ - Adding pagination to project pipelines thanks to [Tamás Török-Vistai](https://github.com/tvtamas) - + [2.0.0-rc.2](https://github.com/jdalrymple/node-gitlab-api/62a4d360f0ca2cd584caf852d96ced3761992072) (2017-11-28) ------------------ - Updating all recent core changes into v2.0.0 @@ -558,7 +574,7 @@ accepting merge requests, cancelling merges when the pipeline succeeds, listing [1.1.1](https://github.com/jdalrymple/node-gitlab-api/67df1c8772614b3856f2995eaa7d260d0f697e49) (2017-09-24) ------------------ -- Patch, fixed a broken pagination property +- Patch, fixed a broken pagination property - Adding in missing options parameter in the groups API thanks to a pull request from [Cory Zibell](https://github.com/coryzibell) [1.1.0](https://github.com/jdalrymple/node-gitlab-api/385ef9f351981f26180e1381525ade458bcde1cd) (2017-09-24) @@ -665,4 +681,4 @@ to this "node-gitlab-api": "" ... } -``` \ No newline at end of file +``` From ec90ec3585123fdc1e12a65e84cd53317426c87f Mon Sep 17 00:00:00 2001 From: Jordan Wallet Date: Wed, 4 Apr 2018 09:34:02 -0700 Subject: [PATCH 6/9] Alias "del" to "delete" on XMLHttpRequester --- src/infrastructure/XMLHttpRequester.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/infrastructure/XMLHttpRequester.js b/src/infrastructure/XMLHttpRequester.js index be88f258..d8bd229c 100644 --- a/src/infrastructure/XMLHttpRequester.js +++ b/src/infrastructure/XMLHttpRequester.js @@ -3,6 +3,7 @@ import XHR from 'xhr'; const XMLHttpRequester = Promisify(XHR); XMLHttpRequester.del = Promisify(XHR.del); +XMLHttpRequester.delete = XMLHttpRequester.del; XMLHttpRequester.get = Promisify(XHR.get); XMLHttpRequester.head = Promisify(XHR.head); XMLHttpRequester.patch = Promisify(XHR.patch); From 1732a2c4a6f747acb96566f4d5e567026a7ca2a1 Mon Sep 17 00:00:00 2001 From: Jordan Wallet Date: Wed, 4 Apr 2018 12:36:41 -0700 Subject: [PATCH 7/9] Make XmlHttpRequest respect resolveWithFullResponse --- src/infrastructure/XMLHttpRequester.js | 26 +++++++++++++++++++------- 1 file changed, 19 insertions(+), 7 deletions(-) diff --git a/src/infrastructure/XMLHttpRequester.js b/src/infrastructure/XMLHttpRequester.js index d8bd229c..4d008fc3 100644 --- a/src/infrastructure/XMLHttpRequester.js +++ b/src/infrastructure/XMLHttpRequester.js @@ -1,13 +1,25 @@ import Promisify from 'util.promisify'; import XHR from 'xhr'; -const XMLHttpRequester = Promisify(XHR); -XMLHttpRequester.del = Promisify(XHR.del); +function PromisifyWithFullResponseOption(fn) { + const promisifiedFn = Promisify(fn); + + return async (params) => { + const response = await promisifiedFn(params); + + return params.resolveWithFullResponse + ? response + : response.body; + }; +} + +const XMLHttpRequester = PromisifyWithFullResponseOption(XHR); +XMLHttpRequester.del = PromisifyWithFullResponseOption(XHR.del); XMLHttpRequester.delete = XMLHttpRequester.del; -XMLHttpRequester.get = Promisify(XHR.get); -XMLHttpRequester.head = Promisify(XHR.head); -XMLHttpRequester.patch = Promisify(XHR.patch); -XMLHttpRequester.post = Promisify(XHR.post); -XMLHttpRequester.put = Promisify(XHR.put); +XMLHttpRequester.get = PromisifyWithFullResponseOption(XHR.get); +XMLHttpRequester.head = PromisifyWithFullResponseOption(XHR.head); +XMLHttpRequester.patch = PromisifyWithFullResponseOption(XHR.patch); +XMLHttpRequester.post = PromisifyWithFullResponseOption(XHR.post); +XMLHttpRequester.put = PromisifyWithFullResponseOption(XHR.put); export default XMLHttpRequester; From caf8cb45d76e5a86e3d200d5f341f839585b7198 Mon Sep 17 00:00:00 2001 From: Joshua Grosso Date: Fri, 6 Apr 2018 15:51:31 -0700 Subject: [PATCH 8/9] Reject when an `XMLHttpRequester` request fails --- README.md | 1 + package.json | 1 + src/infrastructure/XMLHttpRequester.js | 31 ++++++++++++++++---------- 3 files changed, 21 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index 1748a0fc..01b78da9 100644 --- a/README.md +++ b/README.md @@ -375,6 +375,7 @@ This started off as a fork from [node-gitlab](https://github.com/node-gitlab/nod - [Jordan Wallet](https://github.com/Mr-Wallet) - [Ev Haus](https://github.com/EvHaus) - [zhao0](https://github.com/zhao0) +- [Joshua Grosso](https://github.com/jgrosso) ## License diff --git a/package.json b/package.json index 24d0660e..396eaa5b 100644 --- a/package.json +++ b/package.json @@ -49,6 +49,7 @@ "qs": "^6.5.1", "request": "^2.85.0", "request-promise": "^4.2.2", + "request-promise-core": "^1.1.1", "url-join": "^4.0.0", "util.promisify": "^1.0.0", "xhr": "^2.4.1" diff --git a/src/infrastructure/XMLHttpRequester.js b/src/infrastructure/XMLHttpRequester.js index 4d008fc3..655cdbdf 100644 --- a/src/infrastructure/XMLHttpRequester.js +++ b/src/infrastructure/XMLHttpRequester.js @@ -1,25 +1,32 @@ +import { + StatusCodeError, +} from 'request-promise-core/errors'; import Promisify from 'util.promisify'; import XHR from 'xhr'; -function PromisifyWithFullResponseOption(fn) { +const promisifyFn = (fn) => { const promisifiedFn = Promisify(fn); - return async (params) => { - const response = await promisifiedFn(params); + return async (opts) => { + const response = await promisifiedFn(opts); - return params.resolveWithFullResponse + if (response.statusCode >= 400 && response.statusCode <= 599) { + throw new StatusCodeError(response.statusCode, response.body, {}, null); + } + + return opts.resolveWithFullResponse ? response : response.body; }; -} +}; -const XMLHttpRequester = PromisifyWithFullResponseOption(XHR); -XMLHttpRequester.del = PromisifyWithFullResponseOption(XHR.del); +const XMLHttpRequester = promisifyFn(XHR); +XMLHttpRequester.del = promisifyFn(XHR.del); XMLHttpRequester.delete = XMLHttpRequester.del; -XMLHttpRequester.get = PromisifyWithFullResponseOption(XHR.get); -XMLHttpRequester.head = PromisifyWithFullResponseOption(XHR.head); -XMLHttpRequester.patch = PromisifyWithFullResponseOption(XHR.patch); -XMLHttpRequester.post = PromisifyWithFullResponseOption(XHR.post); -XMLHttpRequester.put = PromisifyWithFullResponseOption(XHR.put); +XMLHttpRequester.get = promisifyFn(XHR.get); +XMLHttpRequester.head = promisifyFn(XHR.head); +XMLHttpRequester.patch = promisifyFn(XHR.patch); +XMLHttpRequester.post = promisifyFn(XHR.post); +XMLHttpRequester.put = promisifyFn(XHR.put); export default XMLHttpRequester; From 2e5472fe747ae7041a5fa2efb2c5bb2939b26817 Mon Sep 17 00:00:00 2001 From: Joshua Grosso Date: Tue, 10 Apr 2018 09:37:07 -0700 Subject: [PATCH 9/9] Fix style --- src/infrastructure/XMLHttpRequester.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/infrastructure/XMLHttpRequester.js b/src/infrastructure/XMLHttpRequester.js index 655cdbdf..45f37d6f 100644 --- a/src/infrastructure/XMLHttpRequester.js +++ b/src/infrastructure/XMLHttpRequester.js @@ -4,10 +4,10 @@ import { import Promisify from 'util.promisify'; import XHR from 'xhr'; -const promisifyFn = (fn) => { +function promisifyFn(fn) { const promisifiedFn = Promisify(fn); - return async (opts) => { + return async function(opts) { const response = await promisifiedFn(opts); if (response.statusCode >= 400 && response.statusCode <= 599) { @@ -18,7 +18,7 @@ const promisifyFn = (fn) => { ? response : response.body; }; -}; +} const XMLHttpRequester = promisifyFn(XHR); XMLHttpRequester.del = promisifyFn(XHR.del);