diff --git a/.changeset/light-spiders-move.md b/.changeset/light-spiders-move.md new file mode 100644 index 000000000..9679ef656 --- /dev/null +++ b/.changeset/light-spiders-move.md @@ -0,0 +1,6 @@ +--- +'@openfn/language-common': minor +--- + +Common util functions `encode` and `decode` can now take a JavaScript object and +stringify diff --git a/packages/common/src/util/base64.js b/packages/common/src/util/base64.js index 810f8cea0..86db0ff9d 100644 --- a/packages/common/src/util/base64.js +++ b/packages/common/src/util/base64.js @@ -1,26 +1,63 @@ +import _ from 'lodash'; + /** - * Encodes a given string into Base64 format. + * Encodes a given string or Javascript object into Base64 format. * @function * @public * @namespace util - * @param {string} data - The string to be encoded. + * @param {string | object} data - The string or object to be encoded. + * @param {object} options - Options. * @returns {string} - The Base64 encoded string. * @example Encode a string - * const encoded = encode('Hello World'); + * const encodedString = encode('Hello World'); * console.log(encoded); // Output: SGVsbG8gV29ybGQ= + * @example Encode an object + * const encodedObject = encode({name: 'Jane Doe'}) + * console.log(encodedObject); //output eyJuYW1lIjoiSmFuZSBEb2UifQ== + * @example To skip the JSON stringification step + * const encodedObject = encode('Hello World', {parseJson: false}) */ -export const encode = data => Buffer.from(data, 'utf-8').toString('base64'); +export const encode = (data, options = {parseJson: true}) => { + let str = data; -/** + if(typeof data !== "string" && options.parseJson){ + try { + str = JSON.stringify(str); + } catch (e){ + console.log(e.message); + } + } + + return Buffer.from(str, 'utf-8').toString('base64'); +} + +/**4 * 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. + * @param {object} options - Options. + * @returns {string | object} - The decoded string or JavaScript Object. * @example Decode a Base64 string * const decoded = decode('SGVsbG8gV29ybGQ='); - * console.log(decoded); // Output: Hello World + * @example Decode a Base64 JSON object to a standard JavaScript object + * const decoded = decode('eyJuYW1lIjoiSmFuZSBEb2UifQ=='); + * console.log(decoded); // Output: {name: 'Jane Doe'} + * @example To skip the JSON stringification step + * const decodedString = decode('Hello World', {parseJson: false}) */ -export const decode = base64Data => - Buffer.from(base64Data, 'base64').toString('utf-8'); +export const decode = (base64Data, options = {parseJson: true}) =>{ + let decodedValue = Buffer.from(base64Data, 'base64').toString('utf-8'); + + if((_.startsWith(decodedValue, '[') || _.startsWith(decodedValue, '{')) && options.parseJson) { + try { + decodedValue = JSON.parse(decodedValue); + } catch (e) { + console.log(e.message); + } + } + + return decodedValue; +} + diff --git a/packages/common/test/util/index.test.js b/packages/common/test/util/index.test.js index eb7f91ddc..cea484550 100644 --- a/packages/common/test/util/index.test.js +++ b/packages/common/test/util/index.test.js @@ -22,6 +22,9 @@ describe('encode', () => { it('should encode a string to Base64', () => { expect(encode('Hello World')).to.eql('SGVsbG8gV29ybGQ='); }); + it('should encode a string to Base64 while skipping the JSON stringification step', () => { + expect(encode('Hello World', {parseJson: false})).to.eql('SGVsbG8gV29ybGQ='); + }); it('should encode an empty string to Base64', () => { expect(encode('')).to.eql(''); @@ -29,13 +32,13 @@ describe('encode', () => { it('should encode emoji to Base64', () => { expect(encode('😀')).to.eql('8J+YgA=='); }); - it('should throw an error if the string is not a string', () => { - expect(() => encode(123)).to.throw(errorMsg); - expect(() => encode(true)).to.throw(errorMsg); - expect(() => encode(null)).to.throw(errorMsg); - expect(() => encode({})).to.throw(errorMsg); + it('should throw an error if a function is passed', () => { expect(() => encode(() => {})).to.throw(errorMsg); }); + it('should encode a javascript object', () => { + const obj = {"name": "Jane Doe"} + expect(encode(obj)).to.eql("eyJuYW1lIjoiSmFuZSBEb2UifQ=="); + }); }); describe('decode', () => { @@ -52,8 +55,15 @@ describe('decode', () => { it('should decode a Base64 string back to its original string', () => { expect(decode('SGVsbG8gV29ybGQ=')).to.eql('Hello World'); }); + it('should decode a Base64 string back to its original string without needing to JSON parse', () => { + expect(decode('SGVsbG8gV29ybGQ=', {parseJson: false})).to.eql('Hello World'); + }); it('should decode an empty Base64 string', () => { expect(decode('')).to.eql(''); }); + it('should decode a JSON object into a standard javascript object', () => { + const obj = {name: "Jane Doe"} + expect(decode('eyJuYW1lIjoiSmFuZSBEb2UifQ==')).to.eql(obj); + }); });