feat(#1296): toml stringify simple get request

This commit is contained in:
Anoop M D 2023-12-28 22:52:30 +05:30
parent f7ea8c93a6
commit 41d0698a87
6 changed files with 391 additions and 0 deletions

31
package-lock.json generated
View File

@ -14,6 +14,7 @@
"packages/bruno-js", "packages/bruno-js",
"packages/bruno-lang", "packages/bruno-lang",
"packages/bruno-testbench", "packages/bruno-testbench",
"packages/bruno-toml",
"packages/bruno-graphql-docs" "packages/bruno-graphql-docs"
], ],
"devDependencies": { "devDependencies": {
@ -2679,6 +2680,11 @@
"graphql-ws": ">= 4.5.0" "graphql-ws": ">= 4.5.0"
} }
}, },
"node_modules/@iarna/toml": {
"version": "2.2.5",
"resolved": "https://registry.npmjs.org/@iarna/toml/-/toml-2.2.5.tgz",
"integrity": "sha512-trnsAYxU3xnS1gPHPyU961coFyLkh4gAD/0zQ5mymY4yOZ+CYvsPqUbOFSw0aDM4y0tV7tiFxL/1XfXPNC6IPg=="
},
"node_modules/@istanbuljs/load-nyc-config": { "node_modules/@istanbuljs/load-nyc-config": {
"version": "1.1.0", "version": "1.1.0",
"dev": true, "dev": true,
@ -4917,6 +4923,10 @@
"resolved": "packages/bruno-testbench", "resolved": "packages/bruno-testbench",
"link": true "link": true
}, },
"node_modules/@usebruno/toml": {
"resolved": "packages/bruno-toml",
"link": true
},
"node_modules/@webassemblyjs/ast": { "node_modules/@webassemblyjs/ast": {
"version": "1.11.1", "version": "1.11.1",
"dev": true, "dev": true,
@ -18089,6 +18099,15 @@
"bin": { "bin": {
"js-yaml": "bin/js-yaml.js" "js-yaml": "bin/js-yaml.js"
} }
},
"packages/bruno-toml": {
"name": "@usebruno/toml",
"version": "0.1.0",
"license": "MIT",
"dependencies": {
"@iarna/toml": "^2.2.5",
"lodash": "^4.17.21"
}
} }
}, },
"dependencies": { "dependencies": {
@ -19965,6 +19984,11 @@
"meros": "^1.1.4" "meros": "^1.1.4"
} }
}, },
"@iarna/toml": {
"version": "2.2.5",
"resolved": "https://registry.npmjs.org/@iarna/toml/-/toml-2.2.5.tgz",
"integrity": "sha512-trnsAYxU3xnS1gPHPyU961coFyLkh4gAD/0zQ5mymY4yOZ+CYvsPqUbOFSw0aDM4y0tV7tiFxL/1XfXPNC6IPg=="
},
"@istanbuljs/load-nyc-config": { "@istanbuljs/load-nyc-config": {
"version": "1.1.0", "version": "1.1.0",
"dev": true, "dev": true,
@ -22027,6 +22051,13 @@
} }
} }
}, },
"@usebruno/toml": {
"version": "file:packages/bruno-toml",
"requires": {
"@iarna/toml": "^2.2.5",
"lodash": "^4.17.21"
}
},
"@webassemblyjs/ast": { "@webassemblyjs/ast": {
"version": "1.11.1", "version": "1.11.1",
"dev": true, "dev": true,

View File

@ -10,6 +10,7 @@
"packages/bruno-js", "packages/bruno-js",
"packages/bruno-lang", "packages/bruno-lang",
"packages/bruno-testbench", "packages/bruno-testbench",
"packages/bruno-toml",
"packages/bruno-graphql-docs" "packages/bruno-graphql-docs"
], ],
"homepage": "https://usebruno.com", "homepage": "https://usebruno.com",

View File

@ -0,0 +1,298 @@
/**
* Copyright (c) 2016, Rebecca Turner <me@re-becca.org>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* We have made some modifications to this file to support the bruno-toml
* You can search for "modified for bruno-toml" to see the changes
*/
'use strict'
module.exports = stringify
module.exports.value = stringifyInline
function stringify (obj) {
if (obj === null) throw typeError('null')
if (obj === void (0)) throw typeError('undefined')
if (typeof obj !== 'object') throw typeError(typeof obj)
if (typeof obj.toJSON === 'function') obj = obj.toJSON()
if (obj == null) return null
const type = tomlType(obj)
if (type !== 'table') throw typeError(type)
return stringifyObject('', '', obj)
}
function typeError (type) {
return new Error('Can only stringify objects, not ' + type)
}
function getInlineKeys (obj) {
return Object.keys(obj).filter(key => isInline(obj[key]))
}
function getComplexKeys (obj) {
return Object.keys(obj).filter(key => !isInline(obj[key]))
}
function toJSON (obj) {
let nobj = Array.isArray(obj) ? [] : Object.prototype.hasOwnProperty.call(obj, '__proto__') ? {['__proto__']: undefined} : {}
for (let prop of Object.keys(obj)) {
if (obj[prop] && typeof obj[prop].toJSON === 'function' && !('toISOString' in obj[prop])) {
nobj[prop] = obj[prop].toJSON()
} else {
nobj[prop] = obj[prop]
}
}
return nobj
}
function stringifyObject (prefix, indent, obj) {
obj = toJSON(obj)
let inlineKeys
let complexKeys
inlineKeys = getInlineKeys(obj)
complexKeys = getComplexKeys(obj)
const result = []
const inlineIndent = indent || ''
inlineKeys.forEach(key => {
var type = tomlType(obj[key])
if (type !== 'undefined' && type !== 'null') {
result.push(inlineIndent + stringifyKey(key) + ' = ' + stringifyAnyInline(obj[key], true))
}
})
if (result.length > 0) result.push('')
const complexIndent = prefix && inlineKeys.length > 0 ? indent + ' ' : ''
complexKeys.forEach(key => {
result.push(stringifyComplex(prefix, complexIndent, key, obj[key]))
})
return result.join('\n')
}
function isInline (value) {
switch (tomlType(value)) {
case 'undefined':
case 'null':
case 'integer':
case 'nan':
case 'float':
case 'boolean':
case 'string':
case 'datetime':
return true
case 'array':
return value.length === 0 || tomlType(value[0]) !== 'table'
case 'table':
return Object.keys(value).length === 0
/* istanbul ignore next */
default:
return false
}
}
function tomlType (value) {
if (value === undefined) {
return 'undefined'
} else if (value === null) {
return 'null'
} else if (typeof value === 'bigint' || (Number.isInteger(value) && !Object.is(value, -0))) {
return 'integer'
} else if (typeof value === 'number') {
return 'float'
} else if (typeof value === 'boolean') {
return 'boolean'
} else if (typeof value === 'string') {
return 'string'
} else if ('toISOString' in value) {
return isNaN(value) ? 'undefined' : 'datetime'
} else if (Array.isArray(value)) {
return 'array'
} else {
return 'table'
}
}
function stringifyKey (key) {
const keyStr = String(key)
if (/^[-A-Za-z0-9_]+$/.test(keyStr)) {
return keyStr
} else {
return stringifyBasicString(keyStr)
}
}
function stringifyBasicString (str) {
// original
// return '"' + escapeString(str).replace(/"/g, '\\"') + '"'
// modified for bruno-toml
return "'" + escapeString(str).replace(/'/g, "\\'") + "'"
}
function stringifyLiteralString (str) {
return "'" + str + "'"
}
function numpad (num, str) {
while (str.length < num) str = '0' + str
return str
}
function escapeString (str) {
return str.replace(/\\/g, '\\\\')
.replace(/[\b]/g, '\\b')
.replace(/\t/g, '\\t')
.replace(/\n/g, '\\n')
.replace(/\f/g, '\\f')
.replace(/\r/g, '\\r')
.replace(/([\u0000-\u001f\u007f])/, c => '\\u' + numpad(4, c.codePointAt(0).toString(16)))
}
function stringifyMultilineString (str) {
// original
// let escaped = str.split(/\n/).map(str => {
// return escapeString(str).replace(/"(?="")/g, '\\"')
// }).join('\n')
// if (escaped.slice(-1) === '"') escaped += '\\\n'
// return '"""\n' + escaped + '"""'
// modified for bruno-toml
let escaped = str.split(/\n/).map(str => {
return escapeString(str).replace(/'(?='')/g, "\\'")
}).join('\n')
if (escaped.slice(-1) === "'") escaped += '\\\n'
return "'''\n" + escaped + "\n'''"
}
function stringifyAnyInline (value, multilineOk) {
let type = tomlType(value)
if (type === 'string') {
if (multilineOk && /\n/.test(value)) {
type = 'string-multiline'
} else if (!/[\b\t\n\f\r']/.test(value) && /"/.test(value)) {
type = 'string-literal'
}
}
return stringifyInline(value, type)
}
function stringifyInline (value, type) {
if (!type) type = tomlType(value)
switch (type) {
case 'string-multiline':
return stringifyMultilineString(value)
case 'string':
return stringifyBasicString(value)
case 'string-literal':
return stringifyLiteralString(value)
case 'integer':
return stringifyInteger(value)
case 'float':
return stringifyFloat(value)
case 'boolean':
return stringifyBoolean(value)
case 'datetime':
return stringifyDatetime(value)
case 'array':
return stringifyInlineArray(value.filter(_ => tomlType(_) !== 'null' && tomlType(_) !== 'undefined' && tomlType(_) !== 'nan'))
case 'table':
return stringifyInlineTable(value)
/* istanbul ignore next */
default:
throw typeError(type)
}
}
function stringifyInteger (value) {
return String(value).replace(/\B(?=(\d{3})+(?!\d))/g, '_')
}
function stringifyFloat (value) {
if (value === Infinity) {
return 'inf'
} else if (value === -Infinity) {
return '-inf'
} else if (Object.is(value, NaN)) {
return 'nan'
} else if (Object.is(value, -0)) {
return '-0.0'
}
const [int, dec] = String(value).split('.')
return stringifyInteger(int) + '.' + dec
}
function stringifyBoolean (value) {
return String(value)
}
function stringifyDatetime (value) {
return value.toISOString()
}
function stringifyInlineArray (values) {
values = toJSON(values)
let result = '['
const stringified = values.map(_ => stringifyInline(_))
if (stringified.join(', ').length > 60 || /\n/.test(stringified)) {
result += '\n ' + stringified.join(',\n ') + '\n'
} else {
result += ' ' + stringified.join(', ') + (stringified.length > 0 ? ' ' : '')
}
return result + ']'
}
function stringifyInlineTable (value) {
value = toJSON(value)
const result = []
Object.keys(value).forEach(key => {
result.push(stringifyKey(key) + ' = ' + stringifyAnyInline(value[key], false))
})
return '{ ' + result.join(', ') + (result.length > 0 ? ' ' : '') + '}'
}
function stringifyComplex (prefix, indent, key, value) {
const valueType = tomlType(value)
/* istanbul ignore else */
if (valueType === 'array') {
return stringifyArrayOfTables(prefix, indent, key, value)
} else if (valueType === 'table') {
return stringifyComplexTable(prefix, indent, key, value)
} else {
throw typeError(valueType)
}
}
function stringifyArrayOfTables (prefix, indent, key, values) {
values = toJSON(values)
const firstValueType = tomlType(values[0])
/* istanbul ignore if */
if (firstValueType !== 'table') throw typeError(firstValueType)
const fullKey = prefix + stringifyKey(key)
let result = ''
values.forEach(table => {
if (result.length > 0) result += '\n'
result += indent + '[[' + fullKey + ']]\n'
result += stringifyObject(fullKey + '.', indent, table)
})
return result
}
function stringifyComplexTable (prefix, indent, key, value) {
const fullKey = prefix + stringifyKey(key)
let result = ''
if (getInlineKeys(value).length > 0) {
result += indent + '[' + fullKey + ']\n'
}
return result + stringifyObject(fullKey + '.', indent, value)
}

View File

@ -0,0 +1,18 @@
{
"name": "@usebruno/toml",
"version": "0.1.0",
"license": "MIT",
"main": "src/index.js",
"files": [
"lib",
"src",
"package.json"
],
"scripts": {
"test": "jest"
},
"dependencies": {
"@iarna/toml": "^2.2.5",
"lodash": "^4.17.21"
}
}

View File

@ -0,0 +1,7 @@
const stringify = require('../lib/stringify');
const jsonToToml = (json) => {
return stringify(json);
};
module.exports = jsonToToml;

View File

@ -0,0 +1,36 @@
const TOML = require('@iarna/toml');
const jsonToToml = require('../../src/jsonToToml');
const json = {
meta: {
name: 'Get users',
type: 'http',
seq: '1'
},
http: {
method: 'get',
url: 'https://reqres.in/api/users'
},
headers: {
Accept: 'application/json'
}
};
const toml = `[meta]
name = 'Get users'
type = 'http'
seq = '1'
[http]
method = 'get'
url = 'https://reqres.in/api/users'
[headers]
Accept = 'application/json'
`;
describe('jsonToToml - simple get', () => {
it('should parse the json file', () => {
expect(jsonToToml(json)).toEqual(toml);
});
});