From ee9ef14238a52bf934cf068f44845c719568e0ff Mon Sep 17 00:00:00 2001 From: Tyler Hall Date: Thu, 16 Dec 2021 17:48:42 -0500 Subject: [PATCH] fix: add status and message on error --- adapter.js | 180 ++++++++++++++++++++++++--------------------- async-fetch.js | 7 +- deps.js | 2 +- deps_lock.json | 2 +- dev_deps.js | 2 +- dev_deps_lock.json | 6 +- 6 files changed, 107 insertions(+), 92 deletions(-) diff --git a/adapter.js b/adapter.js index 2b264e8..54fd010 100644 --- a/adapter.js +++ b/adapter.js @@ -1,4 +1,4 @@ -import { R } from "./deps.js"; +import { crocks, R } from "./deps.js"; import { bulkPath, @@ -25,64 +25,77 @@ const { toPairs, } = R; +const { Async } = crocks; + /** - * - * @typedef {Object} IndexInfo - * @property {string} index - index name - * @property {Object} mappings - * - * @typedef {Object} BulkSearchDoc - * @property {boolean} ok - * @property {string} [msg] - * @property {Array} results - * - * @typedef {Object} SearchDoc - * @property {string} index - * @property {string} key - * @property {Object} doc - * - * @typedef {Object} SearchInfo - * @property {string} index - * @property {string} key - * - * @typedef {Object} SearchOptions - * @property {Array} fields - * @property {Object} boost - * @property {boolean} prefix - * - * @typedef {Object} SearchQuery - * @property {string} index - * @property {string} query - * @property {SearchOptions} [options] - * - * @typedef {Object} Response - * @property {boolean} ok - * @property {string} [msg] - * - * @typedef {Object} ResponseWithResults - * @property {boolean} ok - * @property {string} [msg] - * @property {Array} results - * - * @typedef {Object} ResponseWithMatches - * @property {boolean} ok - * @property {string} [msg] - * @property {Array} matches + * @typedef {Object} IndexInfo + * @property {string} index - index name + * @property {Object} mappings + * + * @typedef {Object} BulkSearchDoc + * @property {boolean} ok + * @property {string} [msg] + * @property {Array} results + * + * @typedef {Object} SearchDoc + * @property {string} index + * @property {string} key + * @property {Object} doc + * + * @typedef {Object} SearchInfo + * @property {string} index + * @property {string} key + * + * @typedef {Object} SearchOptions + * @property {Array} fields + * @property {Object} boost + * @property {boolean} prefix + * + * @typedef {Object} SearchQuery + * @property {string} index + * @property {string} query + * @property {SearchOptions} [options] + * + * @typedef {Object} Response + * @property {boolean} ok + * @property {string} [msg] + * + * @typedef {Object} ResponseWithResults + * @property {boolean} ok + * @property {string} [msg] + * @property {Array} results + * + * @typedef {Object} ResponseWithMatches + * @property {boolean} ok + * @property {string} [msg] + * @property {Array} matches */ +const handleRejectedResponse = (res) => + Async.of(res) + .chain(Async.fromPromise((res) => res.json())) + .bichain( + () => Async.Rejected({ ok: false, status: res.status }), // not json body, so no message + (body) => + Async.Rejected({ + ok: false, + status: res.status, + msg: JSON.stringify(body), + }), + ); + /** - * TODO: - * - Sanitize inputs ie. index names - * - Map Port api to Elasticsearch api for creating an index - * - Enable monitoring ie. with bimap(tap(console.err), tap(console.log)) - * - How to support different versions of Elasticsearch? - * - ? Should we expose Elasticsearch response in result as res? - */ + * TODO: + * - Sanitize inputs ie. index names + * - Map Port api to Elasticsearch api for creating an index + * - Enable monitoring ie. with bimap(tap(console.err), tap(console.log)) + * - How to support different versions of Elasticsearch? + * - ? Should we expose Elasticsearch response in result as res? + */ export default function ({ config, asyncFetch, headers, handleResponse }) { /** * @param {IndexInfo} * @returns {Promise} - * */ function createIndex({ index, mappings }) { const properties = mappings.fields.reduce( @@ -101,12 +114,10 @@ export default function ({ config, asyncFetch, headers, handleResponse }) { }), }, ) - .chain( - handleResponse((res) => res.status < 400), - ) - .bimap( - (res) => ({ ok: false, msg: JSON.stringify(res) }), - always({ ok: true }), + .chain(handleResponse((res) => res.status < 400)) + .bichain( + handleRejectedResponse, + always(Async.Resolved({ ok: true })), ) .toPromise(); } @@ -126,9 +137,9 @@ export default function ({ config, asyncFetch, headers, handleResponse }) { .chain( handleResponse((res) => res.status === 200), ) - .bimap( - always({ ok: false }), - always({ ok: true }), + .bichain( + handleRejectedResponse, + always(Async.Resolved({ ok: true })), ) .toPromise(); } @@ -149,9 +160,9 @@ export default function ({ config, asyncFetch, headers, handleResponse }) { .chain( handleResponse((res) => res.status < 400), ) - .bimap( - always({ ok: false }), - always({ ok: true }), + .bichain( + handleRejectedResponse, + always(Async.Resolved({ ok: true })), ) .toPromise(); } @@ -171,9 +182,9 @@ export default function ({ config, asyncFetch, headers, handleResponse }) { .chain( handleResponse((res) => res.status < 400), ) - .bimap( - always({ ok: false }), - (res) => ({ ok: true, key, doc: res }), + .bichain( + handleRejectedResponse, + (res) => Async.Resolved({ ok: true, key, doc: res }), ) .toPromise(); } @@ -194,9 +205,9 @@ export default function ({ config, asyncFetch, headers, handleResponse }) { .chain( handleResponse((res) => res.status < 400), ) - .bimap( - always({ ok: false }), - always({ ok: true }), + .bichain( + handleRejectedResponse, + always(Async.Resolved({ ok: true })), ) .toPromise(); } @@ -216,9 +227,9 @@ export default function ({ config, asyncFetch, headers, handleResponse }) { .chain( handleResponse((res) => res.status < 400), ) - .bimap( - always({ ok: false }), - always({ ok: true }), + .bichain( + handleRejectedResponse, + always(Async.Resolved({ ok: true })), ) .toPromise(); } @@ -255,15 +266,14 @@ export default function ({ config, asyncFetch, headers, handleResponse }) { .chain( handleResponse((res) => res.status < 400), ) - .bimap( - always({ ok: false }), - (res) => ({ ok: true, results: res.items }), + .bichain( + handleRejectedResponse, + (res) => Async.Resolved({ ok: true, results: res.items }), ) .toPromise(); } /** - * * @param {SearchQuery} * @returns {Promise} */ @@ -294,13 +304,17 @@ export default function ({ config, asyncFetch, headers, handleResponse }) { }, ) .chain(handleResponse((res) => res.status < 400)) - .bimap( - // TODO: what should message be for a failed query? - (res) => ({ ok: false, msg: JSON.stringify(res) }), - (res) => ({ - ok: true, - matches: pluck("_source", res.hits.hits), - }), + .bichain( + // query failure + handleRejectedResponse, + // Success + (res) => + Async.Resolved( + ({ + ok: true, + matches: pluck("_source", res.hits.hits), + }), + ), ) .toPromise(); } diff --git a/async-fetch.js b/async-fetch.js index 0879769..1feef39 100644 --- a/async-fetch.js +++ b/async-fetch.js @@ -9,6 +9,7 @@ const asyncFetch = (fetch) => Async.fromPromise(fetch); const createHeaders = (username, password) => pipe( assoc("Content-Type", "application/json"), + assoc("Accept", "application/json"), ifElse( () => username && password, assoc( @@ -24,10 +25,10 @@ const createHeaders = (username, password) => const handleResponse = (pred) => ifElse( (res) => pred(res), - (res) => Async.fromPromise(() => res.json())(), (res) => - Async.fromPromise(() => res.json())() - .chain(Async.Rejected), + Async.of(res) + .chain(Async.fromPromise((res) => res.json())), + (res) => Async.Rejected(res), ); export { asyncFetch, createHeaders, handleResponse }; diff --git a/deps.js b/deps.js index a322f5c..f4b1200 100644 --- a/deps.js +++ b/deps.js @@ -1,4 +1,4 @@ export * as R from "https://cdn.skypack.dev/ramda@^0.27.1"; export { default as crocks } from "https://cdn.skypack.dev/crocks@^0.12.4"; -export { encode as base64Encode } from "https://deno.land/std@0.116.0/encoding/base64.ts"; +export { encode as base64Encode } from "https://deno.land/std@0.117.0/encoding/base64.ts"; diff --git a/deps_lock.json b/deps_lock.json index 68d49e8..f76d7e9 100644 --- a/deps_lock.json +++ b/deps_lock.json @@ -3,5 +3,5 @@ "https://cdn.skypack.dev/-/ramda@v0.27.1-3ePaNsppsnXYRcaNcaWn/dist=es2019,mode=imports/optimized/ramda.js": "0e51cd76039fc9669f9179d935b261bcbb19ecbb11d49e7e60cfbc14360a85d2", "https://cdn.skypack.dev/crocks@^0.12.4": "fc624b776247aa182539fed6fe1b21a578609d1c2c0e31830c4469f2bcd099cd", "https://cdn.skypack.dev/ramda@^0.27.1": "a87add6080b004efb8072f81063306b03dac107cd2b6e5fca726f1a8bbb969b4", - "https://deno.land/std@0.116.0/encoding/base64.ts": "0b58bd6477214838bf711eef43eac21e47ba9e5c81b2ce185fe25d9ecab3ebb3" + "https://deno.land/std@0.117.0/encoding/base64.ts": "0b58bd6477214838bf711eef43eac21e47ba9e5c81b2ce185fe25d9ecab3ebb3" } diff --git a/dev_deps.js b/dev_deps.js index e17c642..b95a19b 100644 --- a/dev_deps.js +++ b/dev_deps.js @@ -3,5 +3,5 @@ export { assertEquals, assertObjectMatch, assertThrows, -} from "https://deno.land/std@0.116.0/testing/asserts.ts"; +} from "https://deno.land/std@0.117.0/testing/asserts.ts"; export { spy } from "https://deno.land/x/mock@0.12.1/mod.ts"; diff --git a/dev_deps_lock.json b/dev_deps_lock.json index a1837cd..e848c16 100644 --- a/dev_deps_lock.json +++ b/dev_deps_lock.json @@ -3,9 +3,9 @@ "https://deno.land/std@0.115.1/fmt/colors.ts": "8368ddf2d48dfe413ffd04cdbb7ae6a1009cf0dccc9c7ff1d76259d9c61a0621", "https://deno.land/std@0.115.1/testing/_diff.ts": "e6a10d2aca8d6c27a9c5b8a2dbbf64353874730af539707b5b39d4128140642d", "https://deno.land/std@0.115.1/testing/asserts.ts": "a1fef0239a2c343b0baa49c77dcdd7412613c46f3aba2887c331a2d7ed1f645e", - "https://deno.land/std@0.116.0/fmt/colors.ts": "8368ddf2d48dfe413ffd04cdbb7ae6a1009cf0dccc9c7ff1d76259d9c61a0621", - "https://deno.land/std@0.116.0/testing/_diff.ts": "e6a10d2aca8d6c27a9c5b8a2dbbf64353874730af539707b5b39d4128140642d", - "https://deno.land/std@0.116.0/testing/asserts.ts": "a1fef0239a2c343b0baa49c77dcdd7412613c46f3aba2887c331a2d7ed1f645e", + "https://deno.land/std@0.117.0/fmt/colors.ts": "8368ddf2d48dfe413ffd04cdbb7ae6a1009cf0dccc9c7ff1d76259d9c61a0621", + "https://deno.land/std@0.117.0/testing/_diff.ts": "e6a10d2aca8d6c27a9c5b8a2dbbf64353874730af539707b5b39d4128140642d", + "https://deno.land/std@0.117.0/testing/asserts.ts": "a1fef0239a2c343b0baa49c77dcdd7412613c46f3aba2887c331a2d7ed1f645e", "https://deno.land/x/collections@0.11.2/common.ts": "34e8367e3696c3f872ae417d7c421fa908a5a2125a1c4cb259f7dee9561a7096", "https://deno.land/x/collections@0.11.2/comparators.ts": "08563340dbb0051f032bacdcf854bcabd13d607d2e8cb1889826417419df89d0", "https://deno.land/x/collections@0.11.2/trees/bs_node.ts": "854d39f6d60cdcb47e1183f0fa67091e6bad59dd2b13252a8b38b1b37269fa67",