diff --git a/lib/Adaptor.js b/lib/Adaptor.js index 2fec042..4f720cc 100644 --- a/lib/Adaptor.js +++ b/lib/Adaptor.js @@ -3,90 +3,77 @@ Object.defineProperty(exports, "__esModule", { value: true }); -exports.lastReferenceValue = exports.dataValue = exports.dataPath = exports.merge = exports.each = exports.alterState = exports.sourceValue = exports.fields = exports.field = undefined; +exports.sourceValue = exports.merge = exports.lastReferenceValue = exports.fields = exports.field = exports.each = exports.dataValue = exports.dataPath = exports.alterState = undefined; -var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol ? "symbol" : typeof obj; }; +var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; /** @module Adaptor */ -var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; exports.execute = execute; -exports.fetch = fetch; -exports.fetchWithErrors = fetchWithErrors; -exports.post = post; -exports.postData = postData; exports.get = get; +exports.post = post; +exports.put = put; +exports.patch = patch; +exports.del = del; var _languageCommon = require('language-common'); -Object.defineProperty(exports, 'field', { +Object.defineProperty(exports, 'alterState', { enumerable: true, get: function get() { - return _languageCommon.field; + return _languageCommon.alterState; } }); -Object.defineProperty(exports, 'fields', { +Object.defineProperty(exports, 'dataPath', { enumerable: true, get: function get() { - return _languageCommon.fields; + return _languageCommon.dataPath; } }); -Object.defineProperty(exports, 'sourceValue', { +Object.defineProperty(exports, 'dataValue', { enumerable: true, get: function get() { - return _languageCommon.sourceValue; + return _languageCommon.dataValue; } }); -Object.defineProperty(exports, 'alterState', { +Object.defineProperty(exports, 'each', { enumerable: true, get: function get() { - return _languageCommon.alterState; + return _languageCommon.each; } }); -Object.defineProperty(exports, 'each', { +Object.defineProperty(exports, 'field', { enumerable: true, get: function get() { - return _languageCommon.each; + return _languageCommon.field; } }); -Object.defineProperty(exports, 'merge', { +Object.defineProperty(exports, 'fields', { enumerable: true, get: function get() { - return _languageCommon.merge; + return _languageCommon.fields; } }); -Object.defineProperty(exports, 'dataPath', { +Object.defineProperty(exports, 'lastReferenceValue', { enumerable: true, get: function get() { - return _languageCommon.dataPath; + return _languageCommon.lastReferenceValue; } }); -Object.defineProperty(exports, 'dataValue', { +Object.defineProperty(exports, 'merge', { enumerable: true, get: function get() { - return _languageCommon.dataValue; + return _languageCommon.merge; } }); -Object.defineProperty(exports, 'lastReferenceValue', { +Object.defineProperty(exports, 'sourceValue', { enumerable: true, get: function get() { - return _languageCommon.lastReferenceValue; + return _languageCommon.sourceValue; } }); var _Client = require('./Client'); -var _request = require('request'); - -var _request2 = _interopRequireDefault(_request); - -var _url = require('url'); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } } - -/** @module Adaptor */ - /** * Execute a sequence of operations. * Wraps `language-common/execute`, and prepends initial state for http. @@ -95,7 +82,7 @@ function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr * create('foo'), * delete('bar') * )(state) - * @constructor + * @function * @param {Operations} operations - Operations to be performed. * @returns {Operation} */ @@ -115,43 +102,49 @@ function execute() { } /** - * Make a GET request and POST it somewhere else + * Make a GET request + * @public * @example - * execute( - * fetch(params) - * )(state) - * @constructor - * @param {object} params - data to make the fetch + * get("/myendpoint", { + * query: {foo: "bar", a: 1}, + * headers: {"content-type": "application/json"}, + * authentication: {username: "user", password: "pass"} + * }, + * function(state) { + * return state; + * } + * ) + * @function + * @param {string} path - Path to resource + * @param {object} params - Query, Headers and Authentication parameters + * @param {function} callback - (Optional) Callback function * @returns {Operation} */ -function fetch(params) { +function get(path, params, callback) { return function (state) { - var _expandReferences = (0, _languageCommon.expandReferences)(params)(state); - - var getEndpoint = _expandReferences.getEndpoint; - var query = _expandReferences.query; - var postUrl = _expandReferences.postUrl; - var _state$configuration = state.configuration; - var username = _state$configuration.username; - var password = _state$configuration.password; - var baseUrl = _state$configuration.baseUrl; - var authType = _state$configuration.authType; - - - var sendImmediately = authType == 'digest' ? false : true; - - var url = (0, _url.resolve)(baseUrl + '/', getEndpoint); - - console.log("Fetching data from URL: " + url); - console.log("Applying query: " + JSON.stringify(query)); - - return (0, _Client.getThenPost)({ username: username, password: password, query: query, url: url, sendImmediately: sendImmediately, postUrl: postUrl }).then(function (response) { - console.log("Success:", response); - var result = (typeof response === 'undefined' ? 'undefined' : _typeof(response)) === 'object' ? response : JSON.parse(response); - return _extends({}, state, { references: [result].concat(_toConsumableArray(state.references)) }); - }).then(function (data) { - var nextState = _extends({}, state, { response: { body: data } }); + var _state$configuration = state.configuration, + baseUrl = _state$configuration.baseUrl, + username = _state$configuration.username, + password = _state$configuration.password, + authType = _state$configuration.authType; + + var url = baseUrl ? baseUrl + path : path; + + var _expandReferences = (0, _languageCommon.expandReferences)(params)(state), + query = _expandReferences.query, + headers = _expandReferences.headers, + authentication = _expandReferences.authentication; + + var auth = authentication || { + 'username': username, + 'password': password, + 'sendImmediately': authType != 'digest' + }; + + return (0, _Client.req)("GET", { url: url, query: query, auth: auth, headers: headers }).then(function (response) { + console.log(response); + var nextState = (0, _languageCommon.composeNextState)(state, response); if (callback) return callback(nextState); return nextState; }); @@ -159,233 +152,199 @@ function fetch(params) { } /** - * Make a GET request and POST the response somewhere else without failing. + * Make a POST request + * @public + * @example + * post("/myendpoint", { + * body: {"foo": "bar"}, + * headers: {"content-type": "json"}, + * authentication: {username: "user", password: "pass"}, + * }, + * function(state) { + * return state; + * } + * ) + * @function + * @param {string} path - Path to resource + * @param {object} params - Body, Query, Headers and Authentication parameters + * @param {function} callback - (Optional) Callback function + * @returns {Operation} */ -function fetchWithErrors(params) { +function post(path, params, callback) { return function (state) { - var _expandReferences2 = (0, _languageCommon.expandReferences)(params)(state); - - var getEndpoint = _expandReferences2.getEndpoint; - var query = _expandReferences2.query; - var externalId = _expandReferences2.externalId; - var postUrl = _expandReferences2.postUrl; - var _state$configuration2 = state.configuration; - var username = _state$configuration2.username; - var password = _state$configuration2.password; - var baseUrl = _state$configuration2.baseUrl; - var authType = _state$configuration2.authType; - - - var sendImmediately = authType == 'digest' ? false : true; - - var url = (0, _url.resolve)(baseUrl + '/', getEndpoint); - - console.log("Performing an error-less GET on URL: " + url); - console.log("Applying query: " + JSON.stringify(query)); - - function assembleError(_ref) { - var response = _ref.response; - var error = _ref.error; - - if (response && [200, 201, 202].indexOf(response.statusCode) > -1) return false; - if (error) return error; - return new Error('Server responded with ' + response.statusCode); - } - - return new Promise(function (resolve, reject) { - - (0, _request2.default)({ - url: url, //URL to hit - qs: query, //Query string data - method: 'GET', //Specify the method - auth: { - 'user': username, - 'pass': password, - 'sendImmediately': sendImmediately - } - }, function (error, response, body) { - var taggedResponse = { - response: response, - externalId: externalId - }; - console.log(taggedResponse); - _request2.default.post({ - url: postUrl, - json: taggedResponse - }, function (error, response, postResponseBody) { - error = assembleError({ error: error, response: response }); - if (error) { - console.error("POST failed."); - reject(error); - } else { - console.log("POST succeeded."); - resolve(body); - } - }); - }); - }).then(function (data) { - var nextState = _extends({}, state, { response: { body: data } }); + var _state$configuration2 = state.configuration, + baseUrl = _state$configuration2.baseUrl, + username = _state$configuration2.username, + password = _state$configuration2.password, + authType = _state$configuration2.authType; + + var url = baseUrl ? baseUrl + path : path; + + var _expandReferences2 = (0, _languageCommon.expandReferences)(params)(state), + query = _expandReferences2.query, + headers = _expandReferences2.headers, + authentication = _expandReferences2.authentication, + body = _expandReferences2.body; + + var auth = authentication || { + 'username': username, + 'password': password, + 'sendImmediately': authType != 'digest' + }; + + return (0, _Client.req)("POST", { url: url, query: query, body: body, auth: auth, headers: headers }).then(function (response) { + var nextState = (0, _languageCommon.composeNextState)(state, response); + if (callback) return callback(nextState); return nextState; }); }; } /** - * Make a POST request + * Make a PUT request + * @public * @example - * execute( - * post(params) - * )(state) - * @constructor - * @param {object} params - data to make the POST + * put("/myendpoint", { + * body: {"foo": "bar"}, + * headers: {"content-type": "json"}, + * authentication: {username: "user", password: "pass"}, + * }, + * function(state) { + * return state; + * } + * ) + * @function + * @param {string} path - Path to resource + * @param {object} params - Body, Query, Headers and Auth parameters + * @param {function} callback - (Optional) Callback function * @returns {Operation} */ -function post(url, _ref2) { - var body = _ref2.body; - var callback = _ref2.callback; - var headers = _ref2.headers; - +function put(path, params, callback) { return function (state) { - - return new Promise(function (resolve, reject) { - _request2.default.post({ - url: url, - json: body, - headers: headers - }, function (error, response, body) { - if (error) { - reject(error); - } else { - console.log("POST succeeded."); - resolve(body); - } - }); - }).then(function (data) { - var nextState = _extends({}, state, { response: { body: data } }); + var _state$configuration3 = state.configuration, + baseUrl = _state$configuration3.baseUrl, + username = _state$configuration3.username, + password = _state$configuration3.password, + authType = _state$configuration3.authType; + + var url = baseUrl ? baseUrl + path : path; + + var _expandReferences3 = (0, _languageCommon.expandReferences)(params)(state), + query = _expandReferences3.query, + headers = _expandReferences3.headers, + authentication = _expandReferences3.authentication, + body = _expandReferences3.body; + + var auth = authentication || { + 'username': username, + 'password': password, + 'sendImmediately': authType != 'digest' + }; + + return (0, _Client.req)("PUT", { url: url, query: query, body: body, auth: auth, headers: headers }).then(function (response) { + var nextState = (0, _languageCommon.composeNextState)(state, response); if (callback) return callback(nextState); return nextState; }); }; } -/* -* Make a POST request using existing data from another POST -*/ - -function postData(params) { +/** + * Make a PATCH request + * @public + * @example + * patch("/myendpoint", { + * body: {"foo": "bar"}, + * headers: {"content-type": "json"}, + * authentication: {username: "user", password: "pass"}, + * }, + * function(state) { + * return state; + * } + * ) + * @function + * @param {string} path - Path to resource + * @param {object} params - Body, Query, Headers and Auth parameters + * @param {function} callback - (Optional) Callback function + * @returns {Operation} + */ +function patch(path, params, callback) { return function (state) { - - function assembleError(_ref3) { - var response = _ref3.response; - var error = _ref3.error; - - if (response && [200, 201, 202].indexOf(response.statusCode) > -1) return false; - if (error) return error; - return new Error('Server responded with ' + response.statusCode); - } - - var _expandReferences3 = (0, _languageCommon.expandReferences)(params)(state); - - var url = _expandReferences3.url; - var body = _expandReferences3.body; - var headers = _expandReferences3.headers; - - - return new Promise(function (resolve, reject) { - console.log("Request body:"); - console.log("\n" + JSON.stringify(body, null, 4) + "\n"); - _request2.default.post({ - url: url, - json: body, - headers: headers - }, function (error, response, body) { - error = assembleError({ error: error, response: response }); - if (error) { - reject(error); - console.log(response); - } else { - console.log("Printing response...\n"); - console.log(JSON.stringify(response, null, 4) + "\n"); - console.log("POST succeeded."); - resolve(body); - } - }); - }).then(function (data) { - var nextState = _extends({}, state, { response: { body: data } }); + var _state$configuration4 = state.configuration, + baseUrl = _state$configuration4.baseUrl, + username = _state$configuration4.username, + password = _state$configuration4.password, + authType = _state$configuration4.authType; + + var url = baseUrl ? baseUrl + path : path; + + var _expandReferences4 = (0, _languageCommon.expandReferences)(params)(state), + query = _expandReferences4.query, + headers = _expandReferences4.headers, + authentication = _expandReferences4.authentication, + body = _expandReferences4.body; + + var auth = authentication || { + 'username': username, + 'password': password, + 'sendImmediately': authType != 'digest' + }; + + return (0, _Client.req)("PATCH", { url: url, query: query, body: body, auth: auth, headers: headers }).then(function (response) { + var nextState = (0, _languageCommon.composeNextState)(state, response); + if (callback) return callback(nextState); return nextState; }); }; } /** - * Make a GET request + * Make a DELETE request + * @public * @example - * execute( - * get("my/endpoint", { - * callback: function(data, state) { - * return state; - * } - * }) - * )(state) - * @constructor - * @param {string} url - Path to resource - * @param {object} params - callback and query parameters + * del("/myendpoint", { + * body: {"foo": "bar"}, + * headers: {"content-type": "json"}, + * authentication: {username: "user", password: "pass"}, + * }, + * function(state) { + * return state; + * } + * ) + * @function + * @param {string} path - Path to resource + * @param {object} params - Body, Query, Headers and Auth parameters + * @param {function} callback - (Optional) Callback function * @returns {Operation} */ -function get(path, _ref4) { - var query = _ref4.query; - var callback = _ref4.callback; - - function assembleError(_ref5) { - var response = _ref5.response; - var error = _ref5.error; - - if ([200, 201, 202].indexOf(response.statusCode) > -1) return false; - if (error) return error; - - return new Error('Server responded with ' + response.statusCode); - } +function del(path, params, callback) { return function (state) { - var _state$configuration3 = state.configuration; - var username = _state$configuration3.username; - var password = _state$configuration3.password; - var baseUrl = _state$configuration3.baseUrl; - var authType = _state$configuration3.authType; - - var _expandReferences4 = (0, _languageCommon.expandReferences)({ query: query })(state); - - var qs = _expandReferences4.query; - - - var sendImmediately = authType != 'digest'; - - var url = (0, _url.resolve)(baseUrl + '/', path); - - return new Promise(function (resolve, reject) { - - (0, _request2.default)({ - url: url, //URL to hit - qs: qs, //Query string data - method: 'GET', //Specify the method - auth: { - 'user': username, - 'pass': password, - 'sendImmediately': sendImmediately - } - }, function (error, response, body) { - error = assembleError({ error: error, response: response }); - if (error) { - reject(error); - } else { - resolve(JSON.parse(body)); - } - }); - }).then(function (data) { - var nextState = _extends({}, state, { response: { body: data } }); + var _state$configuration5 = state.configuration, + baseUrl = _state$configuration5.baseUrl, + username = _state$configuration5.username, + password = _state$configuration5.password, + authType = _state$configuration5.authType; + + var url = baseUrl ? baseUrl + path : path; + + var _expandReferences5 = (0, _languageCommon.expandReferences)(params)(state), + query = _expandReferences5.query, + headers = _expandReferences5.headers, + authentication = _expandReferences5.authentication, + body = _expandReferences5.body; + + var auth = authentication || { + 'username': username, + 'password': password, + 'sendImmediately': authType != 'digest' + }; + + return (0, _Client.req)("DELETE", { url: url, query: query, body: body, auth: auth, headers: headers }).then(function (response) { + var nextState = (0, _languageCommon.composeNextState)(state, response); if (callback) return callback(nextState); return nextState; }); diff --git a/lib/Client.js b/lib/Client.js index 1ac981a..c628594 100644 --- a/lib/Client.js +++ b/lib/Client.js @@ -3,88 +3,38 @@ Object.defineProperty(exports, "__esModule", { value: true }); -exports.clientPost = clientPost; -exports.getThenPost = getThenPost; +exports.req = req; var _request = require('request'); var _request2 = _interopRequireDefault(_request); +var _Utils = require('./Utils'); + function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } -function clientPost(_ref) { - var username = _ref.username; - var password = _ref.password; - var body = _ref.body; - var url = _ref.url; +function req(method, _ref) { + var url = _ref.url, + headers = _ref.headers, + body = _ref.body, + auth = _ref.auth, + query = _ref.query; return new Promise(function (resolve, reject) { - _request2.default.post({ + (0, _request2.default)({ url: url, + headers: headers, + auth: auth, + qs: query, + method: method, json: body }, function (error, response, body) { + error = (0, _Utils.assembleError)({ error: error, response: response }); if (error) { reject(error); } else { - console.log("POST succeeded."); - resolve(body); - } - }); - }); -} - -function getThenPost(_ref2) { - var username = _ref2.username; - var password = _ref2.password; - var query = _ref2.query; - var url = _ref2.url; - var sendImmediately = _ref2.sendImmediately; - var postUrl = _ref2.postUrl; - - - function assembleError(_ref3) { - var response = _ref3.response; - var error = _ref3.error; - - if (response && [200, 201, 202].indexOf(response.statusCode) > -1) return false; - if (error) return error; - return new Error('Server responded with ' + response.statusCode); - } - - return new Promise(function (resolve, reject) { - - (0, _request2.default)({ - url: url, //URL to hit - qs: query, //Query string data - method: 'GET', //Specify the method - 'auth': { - 'user': username, - 'pass': password, - 'sendImmediately': sendImmediately - } - }, function (error, response, getResponseBody) { - error = assembleError({ error: error, response: response }); - if (error) { - console.error("GET failed."); - console.log(response); - reject(error); - } else { - console.log("GET succeeded."); - console.log(response); - console.log(getResponseBody); - _request2.default.post({ - url: postUrl, - json: JSON.parse(getResponseBody) - }, function (error, response, postResponseBody) { - error = assembleError({ error: error, response: response }); - if (error) { - console.error("POST failed."); - reject(error); - } else { - console.log("POST succeeded."); - resolve(getResponseBody); - } - }); + console.log("\x1b[32m%s\x1b[0m", '\u2713 ' + method + ' succeeded.'); + resolve((0, _Utils.tryJson)(body)); } }); }); diff --git a/lib/Utils.js b/lib/Utils.js new file mode 100644 index 0000000..df3e367 --- /dev/null +++ b/lib/Utils.js @@ -0,0 +1,23 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.assembleError = assembleError; +exports.tryJson = tryJson; +function assembleError(_ref) { + var response = _ref.response, + error = _ref.error; + + if ([200, 201, 202].indexOf(response.statusCode) > -1) return false; + if (error) return error; + return new Error("Server responded with " + response.statusCode); +} + +function tryJson(data) { + try { + return JSON.parse(data); + } catch (e) { + return data; + } +} diff --git a/package.json b/package.json index cba5691..0642807 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "language-http", - "version": "0.4.0", - "description": "An HTTP Language Pack for OpenFn", + "version": "1.0.0", + "description": "An HTTP request language package for use with Open Function", "main": "lib/index.js", "scripts": { "build": "make", @@ -14,7 +14,7 @@ "lib/" ], "dependencies": { - "language-common": "github:openfn/language-common#v0.0.5", + "language-common": "github:openfn/language-common#v0.1.1", "request": "^2.72.0" }, "devDependencies": { diff --git a/src/Adaptor.js b/src/Adaptor.js index d01ede0..16c539a 100644 --- a/src/Adaptor.js +++ b/src/Adaptor.js @@ -1,9 +1,10 @@ -import { execute as commonExecute, expandReferences } from 'language-common'; -import { getThenPost, clientPost } from './Client'; -import request from 'request'; -import { resolve as resolveUrl } from 'url'; - /** @module Adaptor */ +import { req } from './Client'; +import { + execute as commonExecute, + expandReferences, + composeNextState +} from 'language-common'; /** * Execute a sequence of operations. @@ -13,7 +14,7 @@ import { resolve as resolveUrl } from 'url'; * create('foo'), * delete('bar') * )(state) - * @constructor + * @function * @param {Operations} operations - Operations to be performed. * @returns {Operation} */ @@ -30,245 +31,219 @@ export function execute(...operations) { } /** - * Make a GET request and POST it somewhere else + * Make a GET request + * @public * @example - * execute( - * fetch(params) - * )(state) - * @constructor - * @param {object} params - data to make the fetch + * get("/myendpoint", { + * query: {foo: "bar", a: 1}, + * headers: {"content-type": "application/json"}, + * authentication: {username: "user", password: "pass"} + * }, + * function(state) { + * return state; + * } + * ) + * @function + * @param {string} path - Path to resource + * @param {object} params - Query, Headers and Authentication parameters + * @param {function} callback - (Optional) Callback function * @returns {Operation} */ -export function fetch(params) { - - return state => { + export function get(path, params, callback) { - const { getEndpoint, query, postUrl } = expandReferences(params)(state); + return state => { - const { username, password, baseUrl, authType } = state.configuration; + const { baseUrl, username, password, authType } = state.configuration; + const url = ( baseUrl ? baseUrl + path : path ); - var sendImmediately = authType == 'digest' ? false : true; + const { query, headers, authentication } = expandReferences(params)(state); - const url = resolveUrl(baseUrl + '/', getEndpoint) + const auth = authentication || { + 'username': username, + 'password': password, + 'sendImmediately': (authType != 'digest') + } - console.log("Fetching data from URL: " + url); - console.log("Applying query: " + JSON.stringify(query)) + return req("GET", {url, query, auth, headers}) + .then((response) => { + const nextState = composeNextState(state, response) + if (callback) return callback(nextState); + return nextState; + }) - return getThenPost({ username, password, query, url, sendImmediately, postUrl }) - .then((response) => { - console.log("Success:", response); - let result = (typeof response === 'object') ? response : JSON.parse(response); - return { ...state, references: [ result, ...state.references ] } - }).then((data) => { - const nextState = { ...state, response: { body: data } }; - if (callback) return callback(nextState); - return nextState; - }) + } + } - } -} /** - * Make a GET request and POST the response somewhere else without failing. + * Make a POST request + * @public + * @example + * post("/myendpoint", { + * body: {"foo": "bar"}, + * headers: {"content-type": "json"}, + * authentication: {username: "user", password: "pass"}, + * }, + * function(state) { + * return state; + * } + * ) + * @function + * @param {string} path - Path to resource + * @param {object} params - Body, Query, Headers and Authentication parameters + * @param {function} callback - (Optional) Callback function + * @returns {Operation} */ -export function fetchWithErrors(params) { + export function post(path, params, callback) { - return state => { + return state => { - const { getEndpoint, query, externalId, postUrl } = expandReferences(params)(state); + const { baseUrl, username, password, authType } = state.configuration; + const url = ( baseUrl ? baseUrl + path : path ); - const { username, password, baseUrl, authType } = state.configuration; + const { query, headers, authentication, body } = expandReferences(params)(state); - var sendImmediately = authType == 'digest' ? false : true; + const auth = authentication || { + 'username': username, + 'password': password, + 'sendImmediately': (authType != 'digest') + } - const url = resolveUrl(baseUrl + '/', getEndpoint) + return req("POST", {url, query, body, auth, headers}) + .then((response) => { + const nextState = composeNextState(state, response) + if (callback) return callback(nextState); + return nextState; + }) - console.log("Performing an error-less GET on URL: " + url); - console.log("Applying query: " + JSON.stringify(query)) + } + } - function assembleError({ response, error }) { - if (response && ([200,201,202].indexOf(response.statusCode) > -1)) return false; - if (error) return error; - return new Error(`Server responded with ${response.statusCode}`) - } - - return new Promise((resolve, reject) => { - - request({ - url: url, //URL to hit - qs: query, //Query string data - method: 'GET', //Specify the method - auth: { - 'user': username, - 'pass': password, - 'sendImmediately': sendImmediately - } - }, function(error, response, body){ - var taggedResponse = { - response: response, - externalId: externalId - } - console.log(taggedResponse) - request.post ({ - url: postUrl, - json: taggedResponse - }, function(error, response, postResponseBody){ - error = assembleError({error, response}) - if (error) { - console.error("POST failed.") - reject(error); - } else { - console.log("POST succeeded."); - resolve(body); - } - }) - }); - - }).then((data) => { - const nextState = { ...state, response: { body: data } }; - return nextState; - }) - } -} /** - * Make a POST request + * Make a PUT request + * @public * @example - * execute( - * post(params) - * )(state) - * @constructor - * @param {object} params - data to make the POST + * put("/myendpoint", { + * body: {"foo": "bar"}, + * headers: {"content-type": "json"}, + * authentication: {username: "user", password: "pass"}, + * }, + * function(state) { + * return state; + * } + * ) + * @function + * @param {string} path - Path to resource + * @param {object} params - Body, Query, Headers and Auth parameters + * @param {function} callback - (Optional) Callback function * @returns {Operation} */ -export function post(url, {body, callback, headers}) { +export function put(path, params, callback) { return state => { - return new Promise((resolve, reject) => { - request.post ({ - url: url, - json: body, - headers - }, function(error, response, body){ - if(error) { - reject(error); - } else { - console.log("POST succeeded."); - resolve(body); - } - }) - }).then((data) => { - const nextState = { ...state, response: { body: data } }; + const { baseUrl, username, password, authType } = state.configuration; + const url = ( baseUrl ? baseUrl + path : path ); + + const { query, headers, authentication, body } = expandReferences(params)(state); + + const auth = authentication || { + 'username': username, + 'password': password, + 'sendImmediately': (authType != 'digest') + } + + return req("PUT", {url, query, body, auth, headers}) + .then((response) => { + const nextState = composeNextState(state, response) if (callback) return callback(nextState); return nextState; }) - } } -/* -* Make a POST request using existing data from another POST -*/ -export function postData(params) { +/** + * Make a PATCH request + * @public + * @example + * patch("/myendpoint", { + * body: {"foo": "bar"}, + * headers: {"content-type": "json"}, + * authentication: {username: "user", password: "pass"}, + * }, + * function(state) { + * return state; + * } + * ) + * @function + * @param {string} path - Path to resource + * @param {object} params - Body, Query, Headers and Auth parameters + * @param {function} callback - (Optional) Callback function + * @returns {Operation} + */ +export function patch(path, params, callback) { return state => { - function assembleError({ response, error }) { - if (response && ([200,201,202].indexOf(response.statusCode) > -1)) return false; - if (error) return error; - return new Error(`Server responded with ${response.statusCode}`) + const { baseUrl, username, password, authType } = state.configuration; + const url = ( baseUrl ? baseUrl + path : path ); + + const { query, headers, authentication, body } = expandReferences(params)(state); + + const auth = authentication || { + 'username': username, + 'password': password, + 'sendImmediately': (authType != 'digest') } - const { url, body, headers } = expandReferences(params)(state); - - return new Promise((resolve, reject) => { - console.log("Request body:"); - console.log("\n" + JSON.stringify(body, null, 4) + "\n"); - request.post ({ - url: url, - json: body, - headers - }, function(error, response, body){ - error = assembleError({error, response}) - if(error) { - reject(error); - console.log(response); - } else { - console.log("Printing response...\n"); - console.log(JSON.stringify(response, null, 4) + "\n"); - console.log("POST succeeded."); - resolve(body); - } - }) - }).then((data) => { - const nextState = { ...state, response: { body: data } }; + return req("PATCH", {url, query, body, auth, headers}) + .then((response) => { + const nextState = composeNextState(state, response) + if (callback) return callback(nextState); return nextState; }) - } - } - - - - /** - * Make a GET request + * Make a DELETE request + * @public * @example - * execute( - * get("my/endpoint", { - * callback: function(data, state) { - * return state; - * } - * }) - * )(state) - * @constructor - * @param {string} url - Path to resource - * @param {object} params - callback and query parameters + * del("/myendpoint", { + * body: {"foo": "bar"}, + * headers: {"content-type": "json"}, + * authentication: {username: "user", password: "pass"}, + * }, + * function(state) { + * return state; + * } + * ) + * @function + * @param {string} path - Path to resource + * @param {object} params - Body, Query, Headers and Auth parameters + * @param {function} callback - (Optional) Callback function * @returns {Operation} */ -export function get(path, {query, callback}) { - function assembleError({ response, error }) { - if ([200,201,202].indexOf(response.statusCode) > -1) return false; - if (error) return error; - - return new Error(`Server responded with ${response.statusCode}`) - } +export function del(path, params, callback) { return state => { - const { username, password, baseUrl, authType } = state.configuration; - const { query: qs } = expandReferences({query})(state); - - const sendImmediately = (authType != 'digest'); - - const url = resolveUrl(baseUrl + '/', path) - - return new Promise((resolve, reject) => { - - request({ - url, //URL to hit - qs, //Query string data - method: 'GET', //Specify the method - auth: { - 'user': username, - 'pass': password, - 'sendImmediately': sendImmediately - } - }, function(error, response, body){ - error = assembleError({error, response}) - if (error) { - reject(error); - } else { - resolve(JSON.parse(body)) - } - }); - - }).then((data) => { - const nextState = { ...state, response: { body: data } }; + const { baseUrl, username, password, authType } = state.configuration; + const url = ( baseUrl ? baseUrl + path : path ); + + const { query, headers, authentication, body } = expandReferences(params)(state); + + const auth = authentication || { + 'username': username, + 'password': password, + 'sendImmediately': (authType != 'digest') + } + + return req("DELETE", {url, query, body, auth, headers}) + .then((response) => { + const nextState = composeNextState(state, response) if (callback) return callback(nextState); return nextState; }) @@ -276,6 +251,13 @@ export function get(path, {query, callback}) { } export { - field, fields, sourceValue, alterState, each, - merge, dataPath, dataValue, lastReferenceValue + alterState, + dataPath, + dataValue, + each, + field, + fields, + lastReferenceValue, + merge, + sourceValue, } from 'language-common'; diff --git a/src/Client.js b/src/Client.js index 57d3c2f..1ce65d9 100644 --- a/src/Client.js +++ b/src/Client.js @@ -1,64 +1,25 @@ import request from 'request' +import { assembleError, tryJson } from './Utils'; -export function clientPost({ username, password, body, url }) { +export function req( method, { url, headers, body, auth, query } ) { return new Promise((resolve, reject) => { - request.post ({ - url: url, + request ({ + url, + headers, + auth, + qs: query, + method: method, json: body }, function(error, response, body){ + error = assembleError({error, response}) if(error) { reject(error); } else { - console.log("POST succeeded."); - resolve(body); + console.log("\x1b[32m%s\x1b[0m", `✓ ${method} succeeded.`); + resolve( + tryJson(body) + ); } }) }) } - -export function getThenPost({ username, password, query, url, sendImmediately, postUrl }) { - - function assembleError({ response, error }) { - if (response && ([200,201,202].indexOf(response.statusCode) > -1)) return false; - if (error) return error; - return new Error(`Server responded with ${response.statusCode}`) - } - - return new Promise((resolve, reject) => { - - request({ - url: url, //URL to hit - qs: query, //Query string data - method: 'GET', //Specify the method - 'auth': { - 'user': username, - 'pass': password, - 'sendImmediately': sendImmediately - } - }, function(error, response, getResponseBody){ - error = assembleError({error, response}) - if (error) { - console.error("GET failed.") - console.log(response) - reject(error); - } else { - console.log("GET succeeded."); - console.log(response) - console.log(getResponseBody) - request.post ({ - url: postUrl, - json: JSON.parse(getResponseBody) - }, function(error, response, postResponseBody){ - error = assembleError({error, response}) - if (error) { - console.error("POST failed.") - reject(error); - } else { - console.log("POST succeeded."); - resolve(getResponseBody); - } - }) - } - }); - }) -} diff --git a/src/Utils.js b/src/Utils.js new file mode 100644 index 0000000..e9d2910 --- /dev/null +++ b/src/Utils.js @@ -0,0 +1,13 @@ +export function assembleError({ response, error }) { + if ([200,201,202].indexOf(response.statusCode) > -1) return false; + if (error) return error; + return new Error(`Server responded with ${response.statusCode}`) +} + +export function tryJson(data) { + try { + return JSON.parse(data) + } catch(e) { + return data + } +} diff --git a/test/ClientFixtures.js b/test/ClientFixtures.js deleted file mode 100644 index 2ff9182..0000000 --- a/test/ClientFixtures.js +++ /dev/null @@ -1,50 +0,0 @@ -const fixtures = { - event: { - requestBody: { - "program": "eBAyeGv0exc", - "orgUnit": "DiszpKrYNg8", - "eventDate": "2013-05-17", - "status": "COMPLETED", - "storedBy": "admin", - "coordinate": { - "latitude": "59.8", - "longitude": "10.9" - }, - "dataValues": [ - { "dataElement": "qrur9Dvnyt5", "value": "99" }, - { "dataElement": "oZg33kd9taw", "value": "Female" }, - { "dataElement": "msodh3rEMJa", "value": "2013-05-18" } - ] - }, - responseBody: { - "httpStatus":"OK", - "httpStatusCode":200,"status":"OK","message":"Import was successful.","response":{"responseType":"ImportSummaries","imported":3,"updated":0,"deleted":0,"ignored":0,"importSummaries":[{"responseType":"ImportSummary","status":"SUCCESS","importCount":{"imported":3,"updated":0,"ignored":0,"deleted":0},"reference":"rrPOYH80oqG","href":"https://play.http.org/demo/api/events/rrPOYH80oqG"}]}} - - - } -} - -export { fixtures }; - -export default [ { - pattern: 'https://play.http.org/demo(.*)', - - fixtures( match, params, headers ) { - if( match[1] === '/api/events' ) { - return { - body: fixtures.event.responseBody, - params, headers - } - } - - throw new Error( `No Fixture Match\ngot: ${JSON.stringify(match, 2, null)}`) - }, - - post(match, data) { - return { ok: true, match, ...data } - }, - - get(match, data) { - return { ok: true, match, ...data } - } -} ] diff --git a/test/index.js b/test/index.js index 2f3b52c..ba0bc85 100644 --- a/test/index.js +++ b/test/index.js @@ -1,11 +1,8 @@ +import Adaptor from '../src'; import { expect } from 'chai'; - import nock from 'nock'; -import ClientFixtures, { fixtures } from './ClientFixtures' - -import Adaptor from '../src'; -const { execute, event, dataElement, get } = Adaptor; +const { execute, get } = Adaptor; describe("execute", () => { @@ -21,12 +18,12 @@ describe("execute", () => { .then((finalState) => { expect(finalState).to.eql({ counter: 3 }) }) - .then(done).catch(done) - + .then(done) + .catch(done) }) - it("assigns references, data to the initialState", () => { + it("assigns references, data to the initialState", (done) => { let state = {} let finalState = execute()(state) @@ -38,6 +35,8 @@ describe("execute", () => { data: null }) }) + .then(done) + .catch(done) }) }) @@ -45,35 +44,33 @@ describe("execute", () => { describe("get", () => { before(() => { - nock('https://play.http.org') - .get('/demo/api/events') - .reply(200, { foo: 'bar' }); + nock('https://www.example.com') + .get('/api/fake') + .reply(200, { + httpStatus:'OK', + message: 'the response' + }); }) - it("calls the callback", () => { + it("prepares nextState properly", () => { let state = { configuration: { username: "hello", password: "there", - baseUrl: 'https://play.http.org/demo' + baseUrl: 'https://www.example.com' + }, + data: { + "triggering": "event" } }; return execute( - get("api/events", { - callback: (response, state) => { - return { ...state, references: [response] } - }, - username: null - }) + get("/api/fake", {}) )(state) - .then((state) => { - let responseBody = state.references[0].response.body - - // Check that the eventData made it's way to the request as a string. - expect(responseBody). - to.eql({foo: 'bar'}) - + .then((nextState) => { + const { data, references } = nextState; + expect(data).to.eql({ httpStatus: 'OK', message: 'the response' }) + expect(references).to.eql([{ "triggering": "event" }]) }) })