From 68de3e62a72d8227b6d0a64986d190b1a0a3b3a9 Mon Sep 17 00:00:00 2001 From: Emmanuel Evance Date: Wed, 11 Dec 2024 17:17:14 +0300 Subject: [PATCH 1/9] wip: fixing util export --- packages/common/src/Adaptor.js | 5 ++++- packages/common/src/http.js | 4 ++-- packages/common/src/index.js | 1 + packages/common/src/{util/helpers.js => util.js} | 0 packages/common/src/util/index.js | 1 - packages/common/test/util/{helpers.test.js => index.test.js} | 2 +- 6 files changed, 8 insertions(+), 5 deletions(-) rename packages/common/src/{util/helpers.js => util.js} (100%) rename packages/common/test/util/{helpers.test.js => index.test.js} (96%) diff --git a/packages/common/src/Adaptor.js b/packages/common/src/Adaptor.js index 7efcba0c3..133c63157 100644 --- a/packages/common/src/Adaptor.js +++ b/packages/common/src/Adaptor.js @@ -11,7 +11,10 @@ import { Readable } from 'node:stream'; import { request } from 'undici'; import dateFns from 'date-fns'; -import { expandReferences as newExpandReferences, parseDate } from './util'; +import { + expandReferences as newExpandReferences, + parseDate, +} from './util/index.js'; const schemaCache = {}; diff --git a/packages/common/src/http.js b/packages/common/src/http.js index a70bcf2a7..afef1b7ea 100644 --- a/packages/common/src/http.js +++ b/packages/common/src/http.js @@ -1,4 +1,4 @@ -import { expandReferences } from './util'; +import { expandReferences } from './util/references'; import { request } from './util/http'; import set from 'lodash/set'; @@ -44,7 +44,7 @@ const helpers = { * @function * @public * @example Get with a query an oath token - * get($.data.url, http.options({ query: $.query }).oath($.configuration.access_token) + * get($.data.url, http.options({ query: $.query }).oath($.configuration.access_token)) */ export function options(opts = {}) { for (let h in helpers) { diff --git a/packages/common/src/index.js b/packages/common/src/index.js index a67f6043e..ef497e134 100644 --- a/packages/common/src/index.js +++ b/packages/common/src/index.js @@ -5,4 +5,5 @@ export * from './Adaptor'; export * as beta from './beta'; export * as http from './http'; +export * as util from './util'; export * as dateFns from './dateFns'; diff --git a/packages/common/src/util/helpers.js b/packages/common/src/util.js similarity index 100% rename from packages/common/src/util/helpers.js rename to packages/common/src/util.js diff --git a/packages/common/src/util/index.js b/packages/common/src/util/index.js index c7fba722f..3bab65022 100644 --- a/packages/common/src/util/index.js +++ b/packages/common/src/util/index.js @@ -1,5 +1,4 @@ export * from './http'; -export * from './helpers'; export * from './references'; import parseDate from './parse-date'; import throwError from './throw-error'; diff --git a/packages/common/test/util/helpers.test.js b/packages/common/test/util/index.test.js similarity index 96% rename from packages/common/test/util/helpers.test.js rename to packages/common/test/util/index.test.js index ac6eb8997..eb7f91ddc 100644 --- a/packages/common/test/util/helpers.test.js +++ b/packages/common/test/util/index.test.js @@ -1,5 +1,5 @@ import { expect } from 'chai'; -import { encode, decode, uuid } from '../../src/util/helpers.js'; +import { encode, decode, uuid } from '../../src/util'; describe('uuid', () => { it('should generate a uuid', () => { From eeab15a47a982294484067ac5c8c0bb0cec20a02 Mon Sep 17 00:00:00 2001 From: Joe Clark Date: Tue, 7 Jan 2025 16:25:32 +0000 Subject: [PATCH 2/9] tools: update docgen to support namespacing on functions --- tools/build/jsdoc/custom-tags.cjs | 8 ++++++++ tools/build/src/commands/docs.ts | 5 ++++- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/tools/build/jsdoc/custom-tags.cjs b/tools/build/jsdoc/custom-tags.cjs index 33640f548..0c0b6c06b 100644 --- a/tools/build/jsdoc/custom-tags.cjs +++ b/tools/build/jsdoc/custom-tags.cjs @@ -16,4 +16,12 @@ exports.defineTags = dictionary => { }); }, }); + + dictionary.defineTag('namespace', { + canHaveName: true, + canHaveType: false, + onTagged: (doclet, tag) => { + doclet.namespace = tag.value.name; + }, + }); }; diff --git a/tools/build/src/commands/docs.ts b/tools/build/src/commands/docs.ts index 59a116037..09a972e5f 100644 --- a/tools/build/src/commands/docs.ts +++ b/tools/build/src/commands/docs.ts @@ -106,8 +106,11 @@ const build = async (lang: string) => { } templateData.forEach(data => { + if (data.namespace) { + data.scope = data.namespace; + } // all typedefs are global - if (data.kind === 'typedef') { + else if (data.kind === 'typedef') { data.scope = 'global'; } // Set scope to be the file name From 1f7b8c9c4948fabd6dd0c1cb68d9640b2f012d81 Mon Sep 17 00:00:00 2001 From: Joe Clark Date: Tue, 7 Jan 2025 16:25:50 +0000 Subject: [PATCH 3/9] common: update and fix namespacing --- packages/common/src/Adaptor.js | 5 +---- packages/common/src/http.js | 3 +-- packages/common/src/index.js | 2 +- packages/common/src/index.ts | 1 + packages/common/src/metadata.ts | 4 ++-- packages/common/src/{util.js => util/base64.js} | 15 ++------------- packages/common/src/util/http.js | 4 ++-- packages/common/src/util/index.js | 7 ++++--- packages/common/src/util/uuid.js | 13 +++++++++++++ 9 files changed, 27 insertions(+), 27 deletions(-) rename packages/common/src/{util.js => util/base64.js} (70%) create mode 100644 packages/common/src/util/uuid.js diff --git a/packages/common/src/Adaptor.js b/packages/common/src/Adaptor.js index 133c63157..7efcba0c3 100644 --- a/packages/common/src/Adaptor.js +++ b/packages/common/src/Adaptor.js @@ -11,10 +11,7 @@ import { Readable } from 'node:stream'; import { request } from 'undici'; import dateFns from 'date-fns'; -import { - expandReferences as newExpandReferences, - parseDate, -} from './util/index.js'; +import { expandReferences as newExpandReferences, parseDate } from './util'; const schemaCache = {}; diff --git a/packages/common/src/http.js b/packages/common/src/http.js index afef1b7ea..838a5660b 100644 --- a/packages/common/src/http.js +++ b/packages/common/src/http.js @@ -1,6 +1,5 @@ -import { expandReferences } from './util/references'; -import { request } from './util/http'; import set from 'lodash/set'; +import { request, expandReferences } from './util'; /** * Helper functions provided by `http.options`. diff --git a/packages/common/src/index.js b/packages/common/src/index.js index ef497e134..07aff8c1c 100644 --- a/packages/common/src/index.js +++ b/packages/common/src/index.js @@ -5,5 +5,5 @@ export * from './Adaptor'; export * as beta from './beta'; export * as http from './http'; -export * as util from './util'; +export * as util from './util/index.js'; export * as dateFns from './dateFns'; diff --git a/packages/common/src/index.ts b/packages/common/src/index.ts index b42e69cd5..bff5fdc1c 100644 --- a/packages/common/src/index.ts +++ b/packages/common/src/index.ts @@ -6,6 +6,7 @@ export * from './Adaptor'; export * as beta from './beta'; export * as http from './http'; export * as dateFns from './dateFns'; +export * as util from './util'; import * as metadata from './metadata'; export { metadata }; diff --git a/packages/common/src/metadata.ts b/packages/common/src/metadata.ts index 319623cb5..78669e8e0 100644 --- a/packages/common/src/metadata.ts +++ b/packages/common/src/metadata.ts @@ -1,5 +1,5 @@ // Generic entity in a data model -type Entity = { +export type Entity = { name: string; // the value when inserted type: string; // domain-specific type string (eg OrgUnit, sObject) @@ -18,4 +18,4 @@ type Entity = { // we need to map data types into a standard // SF's types are UI focused, like picklist, reference, id. They also have string and datetime // So we need to work out what htis list is -type DataType = 'string' | 'boolean' | 'date'; +export type DataType = 'string' | 'boolean' | 'date'; diff --git a/packages/common/src/util.js b/packages/common/src/util/base64.js similarity index 70% rename from packages/common/src/util.js rename to packages/common/src/util/base64.js index ef4bdbfc3..810f8cea0 100644 --- a/packages/common/src/util.js +++ b/packages/common/src/util/base64.js @@ -1,9 +1,8 @@ -import { randomUUID } from 'node:crypto'; - /** * Encodes a given string into Base64 format. * @function * @public + * @namespace util * @param {string} data - The string to be encoded. * @returns {string} - The Base64 encoded string. * @example Encode a string @@ -16,6 +15,7 @@ export const encode = data => Buffer.from(data, 'utf-8').toString('base64'); * Decodes a Base64 encoded string back to its original format. * @function * @public + * @namespace util * @param {string} base64Data - The Base64 encoded string. * @returns {string} - The decoded string. * @example Decode a Base64 string @@ -24,14 +24,3 @@ export const encode = data => Buffer.from(data, 'utf-8').toString('base64'); */ export const decode = base64Data => Buffer.from(base64Data, 'base64').toString('utf-8'); - -/** - * Generates a UUID (Universally Unique Identifier). - * @function - * @public - * @returns {string} - A newly generated UUID. - * @example Generate a UUID - * const id = uuid(); - * console.log(id); // Output:'3f4e254e-8f6f-4f8b-9651-1c1c262cc83f' - */ -export const uuid = () => randomUUID(); diff --git a/packages/common/src/util/http.js b/packages/common/src/util/http.js index d06af9f15..75203e8e5 100644 --- a/packages/common/src/util/http.js +++ b/packages/common/src/util/http.js @@ -57,14 +57,14 @@ const assertOK = async (response, errorMap, fullUrl, method, startTime) => { const body = await readResponseBody(response); const statusText = getReasonPhrase(response.statusCode); - const defaultErrorMesssage = `${method} to ${fullUrl} returned ${response.statusCode}: ${statusText}`; + const defaultErrorMessage = `${method} to ${fullUrl} returned ${response.statusCode}: ${statusText}`; const duration = Date.now() - startTime; const errMessage = typeof errMapMessage === 'function' ? errMapMessage(response) - : errMapMessage || defaultErrorMesssage; + : errMapMessage || defaultErrorMessage; const error = new Error(errMessage); error.statusCode = response.statusCode; diff --git a/packages/common/src/util/index.js b/packages/common/src/util/index.js index 3bab65022..90e118199 100644 --- a/packages/common/src/util/index.js +++ b/packages/common/src/util/index.js @@ -1,6 +1,7 @@ export * from './http'; export * from './references'; -import parseDate from './parse-date'; -import throwError from './throw-error'; -export { parseDate, throwError }; +export { default as parseDate } from './parse-date'; +export { default as throwError } from './throw-error'; +export { encode, decode } from './base64'; +export { uuid } from './uuid'; diff --git a/packages/common/src/util/uuid.js b/packages/common/src/util/uuid.js new file mode 100644 index 000000000..779d5639b --- /dev/null +++ b/packages/common/src/util/uuid.js @@ -0,0 +1,13 @@ +import { randomUUID } from 'node:crypto'; + +/** + * Generates a UUID (Universally Unique Identifier). + * @function + * @public + * @namespace util + * @returns {string} - A newly generated UUID. + * @example Generate a UUID + * const id = uuid(); + * console.log(id); // Output:'3f4e254e-8f6f-4f8b-9651-1c1c262cc83f' + */ +export const uuid = () => randomUUID(); From a47d8d54f8f60949ff7ec5838917315f99daf9ce Mon Sep 17 00:00:00 2001 From: Joe Clark Date: Tue, 7 Jan 2025 16:26:27 +0000 Subject: [PATCH 4/9] changeset --- .changeset/healthy-islands-tell.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/healthy-islands-tell.md diff --git a/.changeset/healthy-islands-tell.md b/.changeset/healthy-islands-tell.md new file mode 100644 index 000000000..b5710f3c8 --- /dev/null +++ b/.changeset/healthy-islands-tell.md @@ -0,0 +1,5 @@ +--- +'@openfn/language-common': minor +--- + +Fix namespacing of utils.\* From 7e9a056d2cc1949729b8d079856d78531649fb48 Mon Sep 17 00:00:00 2001 From: Emmanuel Evance Date: Thu, 9 Jan 2025 12:50:59 +0300 Subject: [PATCH 5/9] re-organize helpers and util --- packages/http/src/Adaptor.js | 2 +- packages/http/src/helpers.js | 146 ++++++++++++++++++++++++++++++++++ packages/http/src/util.js | 148 +---------------------------------- 3 files changed, 151 insertions(+), 145 deletions(-) create mode 100644 packages/http/src/helpers.js diff --git a/packages/http/src/Adaptor.js b/packages/http/src/Adaptor.js index 8d1afb9e4..21ff26e06 100644 --- a/packages/http/src/Adaptor.js +++ b/packages/http/src/Adaptor.js @@ -1,5 +1,5 @@ import { execute as commonExecute } from '@openfn/language-common'; -import { request as sendRequest, xmlParser } from './util'; +import { request as sendRequest, xmlParser } from './helpers'; /** * Options provided to the HTTP request diff --git a/packages/http/src/helpers.js b/packages/http/src/helpers.js new file mode 100644 index 000000000..ce9d8ff86 --- /dev/null +++ b/packages/http/src/helpers.js @@ -0,0 +1,146 @@ +import { composeNextState } from '@openfn/language-common'; +import { + request as commonRequest, + makeBasicAuthHeader, + expandReferences, + logResponse, +} from '@openfn/language-common/util'; +import * as cheerio from 'cheerio'; +import cheerioTableparser from 'cheerio-tableparser'; + +export function addAuth(configuration, headers) { + if (headers.Authorization) { + return; + } + + const { username, password, access_token } = configuration ?? {}; + + if (access_token) { + Object.assign(headers, { Authorization: `Bearer ${access_token}` }); + } else if (username && password) { + Object.assign(headers, makeBasicAuthHeader(username, password)); + } +} + +function encodeFormBody(data) { + const form = new FormData(); + for (const [key, value] of Object.entries(data)) { + form.append(key, value); + } + return form; +} + +const assertUrl = (pathOrUrl, baseUrl) => { + if (!baseUrl && pathOrUrl && !/^https?:\/\//.test(pathOrUrl)) { + const e = new Error('UNEXPECTED_RELATIVE_URL'); + e.code = 'UNEXPECTED_RELATIVE_URL'; + e.description = `You passed a relative URL but didn't set baseUrl`; + e.url = pathOrUrl; + e.fix = `Set the baseUrl on state.configuration or use an absolute URL, like https://example.com/api/${pathOrUrl}`; + throw e; + } + if (!baseUrl && !pathOrUrl) { + const e = new Error('NO_URL'); + e.code = 'NO_URL'; + e.description = `No URL provided`; + e.fix = `Make sure to pass a URL string into the request. You may need to set a baseURL on state.configuration.`; + throw e; + } +}; + +/** + * Request helper function + * @function + * @private + */ +export function request(method, path, params, callback = s => s) { + return state => { + const [resolvedPath, resolvedParams = {}] = expandReferences( + state, + path, + params + ); + + let { body, headers = {} } = resolvedParams; + + if (resolvedParams.json) { + console.warn( + 'WARNING: The `json` option has been deprecated. Use `body` instead' + ); + body = resolvedParams.json; + } + + if (resolvedParams.form) { + body = encodeFormBody(resolvedParams.form); + } + + const baseUrl = state.configuration?.baseUrl; + + assertUrl(resolvedPath, baseUrl); + + if (baseUrl) { + addAuth(state.configuration, headers); + } + + const maxRedirections = + resolvedParams.maxRedirections ?? + (resolvedParams.followAllRedirects === false ? 0 : 5); + + const tls = resolvedParams.tls ?? resolvedParams.agentOptions; + + if (resolvedParams.agentOptions) { + console.warn( + 'WARNING: The `agentOptions` option has been deprecated. Use `tls` instead' + ); + } + + const options = { + ...resolvedParams, + headers, + baseUrl, + body, + tls, + maxRedirections, + }; + + return commonRequest(method, resolvedPath, options) + .then(response => { + logResponse(response); + + return { + ...composeNextState(state, response.body), + response, + }; + }) + .then(callback) + .catch(err => { + logResponse(err); + + throw err; + }); + }; +} +/** + * XML parser helper function + * @function + * @private + */ +export function xmlParser(body, script, callback = s => s) { + return state => { + const [resolvedBody] = expandReferences(state, body); + const $ = cheerio.load(resolvedBody); + cheerioTableparser($); + + if (script) { + const result = script($); + try { + const r = JSON.parse(result); + return callback(composeNextState(state, r)); + } catch (e) { + return callback(composeNextState(state, { body: result })); + } + } else { + return callback(composeNextState(state, { body: resolvedBody })); + } + }; +} diff --git a/packages/http/src/util.js b/packages/http/src/util.js index 5670bb0b2..2cea62962 100644 --- a/packages/http/src/util.js +++ b/packages/http/src/util.js @@ -1,144 +1,4 @@ -import { composeNextState } from '@openfn/language-common'; -import { - request as commonRequest, - makeBasicAuthHeader, - expandReferences, - logResponse, - encode, - decode, - uuid, -} from '@openfn/language-common/util'; - -import * as cheerio from 'cheerio'; -import cheerioTableparser from 'cheerio-tableparser'; - -export function addAuth(configuration, headers) { - if (headers.Authorization) { - return; - } - - const { username, password, access_token } = configuration ?? {}; - - if (access_token) { - Object.assign(headers, { Authorization: `Bearer ${access_token}` }); - } else if (username && password) { - Object.assign(headers, makeBasicAuthHeader(username, password)); - } -} - -function encodeFormBody(data) { - const form = new FormData(); - for (const [key, value] of Object.entries(data)) { - form.append(key, value); - } - return form; -} - -const assertUrl = (pathOrUrl, baseUrl) => { - if (!baseUrl && pathOrUrl && !/^https?:\/\//.test(pathOrUrl)) { - const e = new Error('UNEXPECTED_RELATIVE_URL'); - e.code = 'UNEXPECTED_RELATIVE_URL'; - e.description = `You passed a relative URL but didn't set baseUrl`; - e.url = pathOrUrl; - e.fix = `Set the baseUrl on state.configuration or use an absolute URL, like https://example.com/api/${pathOrUrl}`; - throw e; - } - if (!baseUrl && !pathOrUrl) { - const e = new Error('NO_URL'); - e.code = 'NO_URL'; - e.description = `No URL provided`; - e.fix = `Make sure to pass a URL string into the request. You may need to set a baseURL on state.configuration.`; - throw e; - } -}; - -export function request(method, path, params, callback = s => s) { - return state => { - const [resolvedPath, resolvedParams = {}] = expandReferences( - state, - path, - params - ); - - let { body, headers = {} } = resolvedParams; - - if (resolvedParams.json) { - console.warn( - 'WARNING: The `json` option has been deprecated. Use `body` instead' - ); - body = resolvedParams.json; - } - - if (resolvedParams.form) { - body = encodeFormBody(resolvedParams.form); - } - - const baseUrl = state.configuration?.baseUrl; - - assertUrl(resolvedPath, baseUrl); - - if (baseUrl) { - addAuth(state.configuration, headers); - } - - const maxRedirections = - resolvedParams.maxRedirections ?? - (resolvedParams.followAllRedirects === false ? 0 : 5); - - const tls = resolvedParams.tls ?? resolvedParams.agentOptions; - - if (resolvedParams.agentOptions) { - console.warn( - 'WARNING: The `agentOptions` option has been deprecated. Use `tls` instead' - ); - } - - const options = { - ...resolvedParams, - headers, - baseUrl, - body, - tls, - maxRedirections, - }; - - return commonRequest(method, resolvedPath, options) - .then(response => { - logResponse(response); - - return { - ...composeNextState(state, response.body), - response, - }; - }) - .then(callback) - .catch(err => { - logResponse(err); - - throw err; - }); - }; -} - -export function xmlParser(body, script, callback = s => s) { - return state => { - const [resolvedBody] = expandReferences(state, body); - const $ = cheerio.load(resolvedBody); - cheerioTableparser($); - - if (script) { - const result = script($); - try { - const r = JSON.parse(result); - return callback(composeNextState(state, r)); - } catch (e) { - return callback(composeNextState(state, { body: result })); - } - } else { - return callback(composeNextState(state, { body: resolvedBody })); - } - }; -} +import { encode, decode, uuid } from '@openfn/language-common/util'; export { /** @@ -148,7 +8,7 @@ export { * @param {string} data - The string to be encoded. * @returns {string} - The Base64 encoded string. * @example Encode a string - * const encoded = Util.encode('Hello World'); + * const encoded = util.encode('Hello World'); * console.log(encoded); // Output: SGVsbG8gV29ybGQ= */ encode, @@ -159,7 +19,7 @@ export { * @param {string} base64Data - The Base64 encoded string. * @returns {string} - The decoded string. * @example Decode a Base64 string - * const decoded = Util.decode('SGVsbG8gV29ybGQ='); + * const decoded = util.decode('SGVsbG8gV29ybGQ='); * console.log(decoded); // Output: Hello World */ decode, @@ -169,7 +29,7 @@ export { * @public * @returns {string} - A newly generated UUID. * @example Generate a UUID - * const id = Util.uuid(); + * const id = util.uuid(); * console.log(id); // Output:'3f4e254e-8f6f-4f8b-9651-1c1c262cc83f' */ uuid, From 33c11f14f2d001cb2b55d50d6d27236e78f7f37a Mon Sep 17 00:00:00 2001 From: Emmanuel Evance Date: Thu, 9 Jan 2025 13:09:06 +0300 Subject: [PATCH 6/9] remove export from addAuth --- packages/http/src/helpers.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/http/src/helpers.js b/packages/http/src/helpers.js index ce9d8ff86..7d15a42bc 100644 --- a/packages/http/src/helpers.js +++ b/packages/http/src/helpers.js @@ -8,7 +8,7 @@ import { import * as cheerio from 'cheerio'; import cheerioTableparser from 'cheerio-tableparser'; -export function addAuth(configuration, headers) { +function addAuth(configuration, headers) { if (headers.Authorization) { return; } From 4b9a5b9dcb6f469361baf14352dc6e9535319e1f Mon Sep 17 00:00:00 2001 From: Emmanuel Evance Date: Thu, 9 Jan 2025 13:10:32 +0300 Subject: [PATCH 7/9] add changeset --- .changeset/dull-peas-peel.md | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 .changeset/dull-peas-peel.md diff --git a/.changeset/dull-peas-peel.md b/.changeset/dull-peas-peel.md new file mode 100644 index 000000000..9bbe8abc0 --- /dev/null +++ b/.changeset/dull-peas-peel.md @@ -0,0 +1,7 @@ +--- +'@openfn/language-http': patch +--- + +- Fix typo in util functions examples +- Move helper functions to `helper.js` +- Remove export for `addAuth()` helper From 99344c340fcc1c86526fec9755c511fe9c246773 Mon Sep 17 00:00:00 2001 From: Emmanuel Evance Date: Thu, 9 Jan 2025 20:38:19 +0300 Subject: [PATCH 8/9] remove helpers.js --- packages/http/src/Adaptor.js | 2 +- packages/http/src/helpers.js | 146 ---------------------------------- packages/http/src/util.js | 150 ++++++++++++++++++++++++++++++++++- 3 files changed, 150 insertions(+), 148 deletions(-) delete mode 100644 packages/http/src/helpers.js diff --git a/packages/http/src/Adaptor.js b/packages/http/src/Adaptor.js index 21ff26e06..8d1afb9e4 100644 --- a/packages/http/src/Adaptor.js +++ b/packages/http/src/Adaptor.js @@ -1,5 +1,5 @@ import { execute as commonExecute } from '@openfn/language-common'; -import { request as sendRequest, xmlParser } from './helpers'; +import { request as sendRequest, xmlParser } from './util'; /** * Options provided to the HTTP request diff --git a/packages/http/src/helpers.js b/packages/http/src/helpers.js deleted file mode 100644 index 7d15a42bc..000000000 --- a/packages/http/src/helpers.js +++ /dev/null @@ -1,146 +0,0 @@ -import { composeNextState } from '@openfn/language-common'; -import { - request as commonRequest, - makeBasicAuthHeader, - expandReferences, - logResponse, -} from '@openfn/language-common/util'; -import * as cheerio from 'cheerio'; -import cheerioTableparser from 'cheerio-tableparser'; - -function addAuth(configuration, headers) { - if (headers.Authorization) { - return; - } - - const { username, password, access_token } = configuration ?? {}; - - if (access_token) { - Object.assign(headers, { Authorization: `Bearer ${access_token}` }); - } else if (username && password) { - Object.assign(headers, makeBasicAuthHeader(username, password)); - } -} - -function encodeFormBody(data) { - const form = new FormData(); - for (const [key, value] of Object.entries(data)) { - form.append(key, value); - } - return form; -} - -const assertUrl = (pathOrUrl, baseUrl) => { - if (!baseUrl && pathOrUrl && !/^https?:\/\//.test(pathOrUrl)) { - const e = new Error('UNEXPECTED_RELATIVE_URL'); - e.code = 'UNEXPECTED_RELATIVE_URL'; - e.description = `You passed a relative URL but didn't set baseUrl`; - e.url = pathOrUrl; - e.fix = `Set the baseUrl on state.configuration or use an absolute URL, like https://example.com/api/${pathOrUrl}`; - throw e; - } - if (!baseUrl && !pathOrUrl) { - const e = new Error('NO_URL'); - e.code = 'NO_URL'; - e.description = `No URL provided`; - e.fix = `Make sure to pass a URL string into the request. You may need to set a baseURL on state.configuration.`; - throw e; - } -}; - -/** - * Request helper function - * @function - * @private - */ -export function request(method, path, params, callback = s => s) { - return state => { - const [resolvedPath, resolvedParams = {}] = expandReferences( - state, - path, - params - ); - - let { body, headers = {} } = resolvedParams; - - if (resolvedParams.json) { - console.warn( - 'WARNING: The `json` option has been deprecated. Use `body` instead' - ); - body = resolvedParams.json; - } - - if (resolvedParams.form) { - body = encodeFormBody(resolvedParams.form); - } - - const baseUrl = state.configuration?.baseUrl; - - assertUrl(resolvedPath, baseUrl); - - if (baseUrl) { - addAuth(state.configuration, headers); - } - - const maxRedirections = - resolvedParams.maxRedirections ?? - (resolvedParams.followAllRedirects === false ? 0 : 5); - - const tls = resolvedParams.tls ?? resolvedParams.agentOptions; - - if (resolvedParams.agentOptions) { - console.warn( - 'WARNING: The `agentOptions` option has been deprecated. Use `tls` instead' - ); - } - - const options = { - ...resolvedParams, - headers, - baseUrl, - body, - tls, - maxRedirections, - }; - - return commonRequest(method, resolvedPath, options) - .then(response => { - logResponse(response); - - return { - ...composeNextState(state, response.body), - response, - }; - }) - .then(callback) - .catch(err => { - logResponse(err); - - throw err; - }); - }; -} -/** - * XML parser helper function - * @function - * @private - */ -export function xmlParser(body, script, callback = s => s) { - return state => { - const [resolvedBody] = expandReferences(state, body); - const $ = cheerio.load(resolvedBody); - cheerioTableparser($); - - if (script) { - const result = script($); - try { - const r = JSON.parse(result); - return callback(composeNextState(state, r)); - } catch (e) { - return callback(composeNextState(state, { body: result })); - } - } else { - return callback(composeNextState(state, { body: resolvedBody })); - } - }; -} diff --git a/packages/http/src/util.js b/packages/http/src/util.js index 2cea62962..7bfefdc27 100644 --- a/packages/http/src/util.js +++ b/packages/http/src/util.js @@ -1,4 +1,152 @@ -import { encode, decode, uuid } from '@openfn/language-common/util'; +import { composeNextState } from '@openfn/language-common'; +import { + request as commonRequest, + makeBasicAuthHeader, + expandReferences, + logResponse, + encode, + decode, + uuid, +} from '@openfn/language-common/util'; +import * as cheerio from 'cheerio'; +import cheerioTableparser from 'cheerio-tableparser'; + +function addAuth(configuration, headers) { + if (headers.Authorization) { + return; + } + + const { username, password, access_token } = configuration ?? {}; + + if (access_token) { + Object.assign(headers, { Authorization: `Bearer ${access_token}` }); + } else if (username && password) { + Object.assign(headers, makeBasicAuthHeader(username, password)); + } +} + +function encodeFormBody(data) { + const form = new FormData(); + for (const [key, value] of Object.entries(data)) { + form.append(key, value); + } + return form; +} + +const assertUrl = (pathOrUrl, baseUrl) => { + if (!baseUrl && pathOrUrl && !/^https?:\/\//.test(pathOrUrl)) { + const e = new Error('UNEXPECTED_RELATIVE_URL'); + e.code = 'UNEXPECTED_RELATIVE_URL'; + e.description = `You passed a relative URL but didn't set baseUrl`; + e.url = pathOrUrl; + e.fix = `Set the baseUrl on state.configuration or use an absolute URL, like https://example.com/api/${pathOrUrl}`; + throw e; + } + if (!baseUrl && !pathOrUrl) { + const e = new Error('NO_URL'); + e.code = 'NO_URL'; + e.description = `No URL provided`; + e.fix = `Make sure to pass a URL string into the request. You may need to set a baseURL on state.configuration.`; + throw e; + } +}; + +/** + * Request helper function + * @function + * @private + */ +export function request(method, path, params, callback = s => s) { + return state => { + const [resolvedPath, resolvedParams = {}] = expandReferences( + state, + path, + params + ); + + let { body, headers = {} } = resolvedParams; + + if (resolvedParams.json) { + console.warn( + 'WARNING: The `json` option has been deprecated. Use `body` instead' + ); + body = resolvedParams.json; + } + + if (resolvedParams.form) { + body = encodeFormBody(resolvedParams.form); + } + + const baseUrl = state.configuration?.baseUrl; + + assertUrl(resolvedPath, baseUrl); + + if (baseUrl) { + addAuth(state.configuration, headers); + } + + const maxRedirections = + resolvedParams.maxRedirections ?? + (resolvedParams.followAllRedirects === false ? 0 : 5); + + const tls = resolvedParams.tls ?? resolvedParams.agentOptions; + + if (resolvedParams.agentOptions) { + console.warn( + 'WARNING: The `agentOptions` option has been deprecated. Use `tls` instead' + ); + } + + const options = { + ...resolvedParams, + headers, + baseUrl, + body, + tls, + maxRedirections, + }; + + return commonRequest(method, resolvedPath, options) + .then(response => { + logResponse(response); + + return { + ...composeNextState(state, response.body), + response, + }; + }) + .then(callback) + .catch(err => { + logResponse(err); + + throw err; + }); + }; +} +/** + * XML parser helper function + * @function + * @private + */ +export function xmlParser(body, script, callback = s => s) { + return state => { + const [resolvedBody] = expandReferences(state, body); + const $ = cheerio.load(resolvedBody); + cheerioTableparser($); + + if (script) { + const result = script($); + try { + const r = JSON.parse(result); + return callback(composeNextState(state, r)); + } catch (e) { + return callback(composeNextState(state, { body: result })); + } + } else { + return callback(composeNextState(state, { body: resolvedBody })); + } + }; +} export { /** From 17d153448a21c8c8dc178d112ac0c9397b44cf64 Mon Sep 17 00:00:00 2001 From: Emmanuel Evance Date: Thu, 9 Jan 2025 20:39:50 +0300 Subject: [PATCH 9/9] update changeset --- .changeset/dull-peas-peel.md | 1 - 1 file changed, 1 deletion(-) diff --git a/.changeset/dull-peas-peel.md b/.changeset/dull-peas-peel.md index 9bbe8abc0..ce7f2da55 100644 --- a/.changeset/dull-peas-peel.md +++ b/.changeset/dull-peas-peel.md @@ -3,5 +3,4 @@ --- - Fix typo in util functions examples -- Move helper functions to `helper.js` - Remove export for `addAuth()` helper