Files
bruno/packages/bruno-lang/v2/src/bruToJson.js
lohit 4797abbeff feat: add tokenType support for OAuth2 (#7314)
* feat: add tokenType support for OAuth2

* refactor: rename tokenType to source in OpenCollection OAuth2 mapping

* refactor: rename tokenType to source in OAuth2 configuration

* chore: bump @opencollection/types to ~0.8.0

* fix: correct OAuth2 token type label in token viewer

* refactor: replace Dropdown with MenuDropdown in OAuth2 components

Migrate all 12 dropdown instances across 5 OAuth2 auth components to use
the MenuDropdown component, removing manual tippy ref management and
forwardRef icon patterns in favor of a declarative items-based API.
2026-02-27 20:50:23 +05:30

1101 lines
34 KiB
JavaScript

const ohm = require('ohm-js');
const _ = require('lodash');
const { safeParseJson, outdentString } = require('./utils');
const parseExample = require('./example/bruToJson');
/**
* A Bru file is made up of blocks.
* There are three types of blocks
*
* 1. Dictionary Blocks - These are blocks that have key value pairs
* ex:
* headers {
* content-type: application/json
* }
*
* 2. Text Blocks - These are blocks that have text
* ex:
* body:json {
* {
* "username": "John Nash",
* "password": "governingdynamics
* }
* 3. List Blocks - These are blocks that have a list of items
* ex:
* tags [
* regression
* smoke-test
* ]
*
*/
const grammar = ohm.grammar(`Bru {
BruFile = (meta | http | grpc | ws | query | params | headers | metadata | auths | bodies | varsandassert | script | tests | settings | docs | example)*
auths = authawsv4 | authbasic | authbearer | authdigest | authNTLM | authOAuth2 | authwsse | authapikey | authOauth2Configs
bodies = bodyjson | bodytext | bodyxml | bodysparql | bodygraphql | bodygraphqlvars | bodyforms | body | bodygrpc | bodyws
bodyforms = bodyformurlencoded | bodymultipart | bodyfile
params = paramspath | paramsquery
// Oauth2 additional parameters
authOauth2Configs = oauth2AuthReqConfig | oauth2AccessTokenReqConfig | oauth2RefreshTokenReqConfig
oauth2AuthReqConfig = oauth2AuthReqHeaders | oauth2AuthReqQueryParams
oauth2AccessTokenReqConfig = oauth2AccessTokenReqHeaders | oauth2AccessTokenReqQueryParams | oauth2AccessTokenReqBody
oauth2RefreshTokenReqConfig = oauth2RefreshTokenReqHeaders | oauth2RefreshTokenReqQueryParams | oauth2RefreshTokenReqBody
nl = "\\r"? "\\n"
st = " " | "\\t"
stnl = st | nl
tagend = nl "}"
optionalnl = ~tagend nl
keychar = ~(tagend | st | nl | ":") any
valuechar = ~(nl | tagend) any
// Multiline text block surrounded by '''
multilinetextblockdelimiter = "'''"
multilinetextblock = multilinetextblockdelimiter (~multilinetextblockdelimiter any)* multilinetextblockdelimiter st* contenttypeannotation?
contenttypeannotation = "@contentType(" (~")" any)* ")"
// Dictionary Blocks
dictionary = st* "{" pairlist? tagend
pairlist = optionalnl* pair (~tagend stnl* pair)* (~tagend space)*
pair = st* (quoted_key | key) st* ":" st* value st*
disable_char = "~"
quote_char = "\\""
esc_char = "\\\\"
esc_quote_char = esc_char quote_char
quoted_key_char = ~(quote_char | esc_quote_char | nl) any
quoted_key = disable_char? quote_char (esc_quote_char | quoted_key_char)* quote_char
key = keychar*
value = list | multilinetextblock | singlelinevalue
singlelinevalue = valuechar*
// Dictionary for Assert Block
assertdictionary = st* "{" assertpairlist? tagend
assertpairlist = optionalnl* assertpair (~tagend stnl* assertpair)* (~tagend space)*
assertpair = st* assertkey st* ":" st* value st*
assertkey = ~tagend assertkeychar*
assertkeychar = ~(tagend | nl | ":") any
// Text Blocks
textblock = textline (~tagend nl textline)*
textline = textchar*
textchar = ~nl any
// List
list = st* "[" nl+ listitems? st* nl+ st* "]"
listitems = listitem (nl+ listitem)*
listitem = st+ (alnum | "_" | "-")+ st*
meta = "meta" dictionary
settings = "settings" dictionary
http = get | post | put | delete | patch | options | head | connect | trace | httpcustom
grpc = "grpc" dictionary
ws = "ws" dictionary
get = "get" dictionary
post = "post" dictionary
put = "put" dictionary
delete = "delete" dictionary
patch = "patch" dictionary
options = "options" dictionary
head = "head" dictionary
connect = "connect" dictionary
trace = "trace" dictionary
httpcustom = "http" dictionary
headers = "headers" dictionary
metadata = "metadata" dictionary
query = "query" dictionary
paramspath = "params:path" dictionary
paramsquery = "params:query" dictionary
varsandassert = varsreq | varsres | assert
varsreq = "vars:pre-request" dictionary
varsres = "vars:post-response" dictionary
assert = "assert" assertdictionary
authawsv4 = "auth:awsv4" dictionary
authbasic = "auth:basic" dictionary
authbearer = "auth:bearer" dictionary
authdigest = "auth:digest" dictionary
authNTLM = "auth:ntlm" dictionary
authOAuth2 = "auth:oauth2" dictionary
authwsse = "auth:wsse" dictionary
authapikey = "auth:apikey" dictionary
oauth2AuthReqHeaders = "auth:oauth2:additional_params:auth_req:headers" dictionary
oauth2AuthReqQueryParams = "auth:oauth2:additional_params:auth_req:queryparams" dictionary
oauth2AccessTokenReqHeaders = "auth:oauth2:additional_params:access_token_req:headers" dictionary
oauth2AccessTokenReqQueryParams = "auth:oauth2:additional_params:access_token_req:queryparams" dictionary
oauth2AccessTokenReqBody = "auth:oauth2:additional_params:access_token_req:body" dictionary
oauth2RefreshTokenReqHeaders = "auth:oauth2:additional_params:refresh_token_req:headers" dictionary
oauth2RefreshTokenReqQueryParams = "auth:oauth2:additional_params:refresh_token_req:queryparams" dictionary
oauth2RefreshTokenReqBody = "auth:oauth2:additional_params:refresh_token_req:body" dictionary
body = "body" st* "{" nl* textblock tagend
bodyjson = "body:json" st* "{" nl* textblock tagend
bodytext = "body:text" st* "{" nl* textblock tagend
bodyxml = "body:xml" st* "{" nl* textblock tagend
bodysparql = "body:sparql" st* "{" nl* textblock tagend
bodygraphql = "body:graphql" st* "{" nl* textblock tagend
bodygraphqlvars = "body:graphql:vars" st* "{" nl* textblock tagend
bodygrpc = "body:grpc" dictionary
bodyws = "body:ws" dictionary
bodyformurlencoded = "body:form-urlencoded" dictionary
bodymultipart = "body:multipart-form" dictionary
bodyfile = "body:file" dictionary
// Examples - multiple example blocks
example = "example" st* "{" nl* examplecontent tagend
examplecontent = (~tagend any)*
script = scriptreq | scriptres
scriptreq = "script:pre-request" st* "{" nl* textblock tagend
scriptres = "script:post-response" st* "{" nl* textblock tagend
tests = "tests" st* "{" nl* textblock tagend
docs = "docs" st* "{" nl* textblock tagend
}`);
const mapPairListToKeyValPairs = (pairList = [], parseEnabled = true) => {
if (!pairList.length) {
return [];
}
return _.map(pairList[0], (pair) => {
let name = _.keys(pair)[0];
let value = pair[name];
if (!parseEnabled) {
return {
name,
value
};
}
let enabled = true;
if (name && name.length && name.charAt(0) === '~') {
name = name.slice(1);
enabled = false;
}
return {
name,
value,
enabled
};
});
};
const mapRequestParams = (pairList = [], type) => {
if (!pairList.length) {
return [];
}
return _.map(pairList[0], (pair) => {
let name = _.keys(pair)[0];
let value = pair[name];
let enabled = true;
if (name && name.length && name.charAt(0) === '~') {
name = name.slice(1);
enabled = false;
}
return {
name,
value,
enabled,
type
};
});
};
const multipartExtractContentType = (pair) => {
if (_.isString(pair.value)) {
const match = pair.value.match(/^(.*?)\s*@contentType\((.*?)\)\s*$/s);
if (match != null && match.length > 2) {
pair.value = match[1];
pair.contentType = match[2];
} else {
pair.contentType = '';
}
}
};
const fileExtractContentType = (pair) => {
if (_.isString(pair.value)) {
const match = pair.value.match(/^(.*?)\s*@contentType\((.*?)\)\s*$/s);
if (match && match.length > 2) {
pair.value = match[1].trim();
pair.contentType = match[2].trim();
} else {
pair.contentType = '';
}
}
};
const mapPairListToKeyValPairsMultipart = (pairList = [], parseEnabled = true) => {
const pairs = mapPairListToKeyValPairs(pairList, parseEnabled);
return pairs.map((pair) => {
pair.type = 'text';
multipartExtractContentType(pair);
if (pair.value.startsWith('@file(') && pair.value.endsWith(')')) {
let filestr = pair.value.replace(/^@file\(/, '').replace(/\)$/, '');
pair.type = 'file';
pair.value = filestr.split('|');
}
return pair;
});
};
const mapPairListToKeyValPairsFile = (pairList = [], parseEnabled = true) => {
const pairs = mapPairListToKeyValPairs(pairList, parseEnabled);
return pairs.map((pair) => {
fileExtractContentType(pair);
if (pair.value.startsWith('@file(') && pair.value.endsWith(')')) {
let filePath = pair.value.replace(/^@file\(/, '').replace(/\)$/, '');
pair.filePath = filePath;
pair.selected = pair.enabled;
// Remove pair.value as it only contains the file path reference
delete pair.value;
// Remove pair.name as it is auto-generated (e.g., file1, file2, file3, etc.)
delete pair.name;
delete pair.enabled;
}
return pair;
});
};
const concatArrays = (objValue, srcValue) => {
if (_.isArray(objValue) && _.isArray(srcValue)) {
return objValue.concat(srcValue);
}
};
const mapPairListToKeyValPair = (pairList = []) => {
if (!pairList || !pairList.length) {
return {};
}
return _.merge({}, ...pairList[0]);
};
/**
* @param {Record<unknown,unknown>} obj
* @returns {(key:string, opts?:{fallback: number })=>number|undefined}
*/
const createGetNumFromRecord = (obj) => (key, { fallback } = {}) => {
if (!(key in obj)) return fallback;
const asNumber = typeof obj[key] === 'number' ? obj[key] : Number(obj[key]);
if (isNaN(asNumber)) {
return fallback;
}
return asNumber;
};
// Parse example content using dedicated example parser
const parseExampleContent = (content) => {
try {
// Unindent the content by removing leading whitespace from each line
const lines = content.split('\n');
// Find the minimum indentation (excluding empty lines)
let minIndent = Infinity;
lines.forEach((line) => {
if (line.trim() !== '') {
const indent = line.match(/^[ \t]*/)[0].length;
minIndent = Math.min(minIndent, indent);
}
});
// Remove the minimum indentation from all lines
const unindentedLines = lines.map((line) => {
if (line.trim() === '') return line; // Keep empty lines as is
return line.substring(minIndent);
});
const unindentedContent = unindentedLines.join('\n').trim();
// Parse the unindented content using the dedicated example parser
return parseExample(unindentedContent);
} catch (error) {
console.error('Error parsing example content:', error);
return { error: error.message };
}
};
const sem = grammar.createSemantics().addAttribute('ast', {
BruFile(tags) {
if (!tags || !tags.ast || !tags.ast.length) {
return {};
}
return _.reduce(
tags.ast,
(result, item) => {
return _.mergeWith(result, item, concatArrays);
},
{}
);
},
dictionary(_1, _2, pairlist, _3) {
return pairlist.ast;
},
pairlist(_1, pair, _2, rest, _3) {
return [pair.ast, ...rest.ast];
},
pair(_1, key, _2, _3, _4, value, _5) {
let res = {};
if (Array.isArray(value.ast)) {
res[key.ast] = value.ast;
return res;
}
res[key.ast] = value.ast ? value.ast.trim() : '';
return res;
},
esc_quote_char(_1, quote) {
// unescape
return quote.sourceString;
},
quoted_key(disabled, _1, chars, _2) {
// unquote
return (disabled ? disabled.sourceString : '') + chars.ast.join('');
},
key(chars) {
return chars.sourceString ? chars.sourceString.trim() : '';
},
assertdictionary(_1, _2, pairlist, _3) {
return pairlist.ast;
},
assertpairlist(_1, pair, _2, rest, _3) {
return [pair.ast, ...rest.ast];
},
assertpair(_1, key, _2, _3, _4, value, _5) {
let res = {};
res[key.ast] = value.ast ? value.ast.trim() : '';
return res;
},
assertkey(chars) {
return chars.sourceString ? chars.sourceString.trim() : '';
},
list(_1, _2, _3, listitems, _4, _5, _6, _7) {
return listitems.ast.flat();
},
listitems(listitem, _1, rest) {
return [listitem.ast, ...rest.ast];
},
listitem(_1, textchar, _2) {
return textchar.sourceString;
},
textblock(line, _1, rest) {
return [line.ast, ...rest.ast].join('\n');
},
textline(chars) {
return chars.sourceString;
},
textchar(char) {
return char.sourceString;
},
nl(_1, _2) {
return '';
},
st(_) {
return '';
},
tagend(_1, _2) {
return '';
},
_terminal() {
return this.sourceString;
},
multilinetextblockdelimiter(_) {
return '';
},
multilinetextblock(_1, content, _2, _3, contentType) {
const multilineString = content.sourceString
.split('\n')
.map((line) => line.slice(4))
.join('\n');
if (!contentType.sourceString) {
return multilineString;
}
return `${multilineString} ${contentType.sourceString}`;
},
singlelinevalue(chars) {
return chars.sourceString?.trim() || '';
},
_iter(...elements) {
return elements.map((e) => e.ast);
},
meta(_1, dictionary) {
let meta = mapPairListToKeyValPair(dictionary.ast);
if (!meta.seq) {
meta.seq = 1;
}
if (!meta.type) {
meta.type = 'http';
}
return {
meta
};
},
settings(_1, dictionary) {
let settings = mapPairListToKeyValPair(dictionary.ast);
const getNumFromRecord = createGetNumFromRecord(settings);
const keepAliveInterval = getNumFromRecord('keepAliveInterval');
const parsedSettings = {};
if (settings.followRedirects !== undefined) {
parsedSettings.followRedirects = typeof settings.followRedirects === 'boolean' ? settings.followRedirects : settings.followRedirects === 'true';
}
// Parse maxRedirects as number
if (settings.maxRedirects !== undefined) {
const maxRedirects = parseInt(settings.maxRedirects, 10);
if (!isNaN(maxRedirects)) {
parsedSettings.maxRedirects = maxRedirects;
}
}
// Parse timeout as number or inherit
if (settings.timeout !== undefined) {
if (settings.timeout === 'inherit') {
parsedSettings.timeout = 'inherit';
} else {
const timeout = parseInt(settings.timeout, 10);
if (!isNaN(timeout)) {
parsedSettings.timeout = timeout;
}
}
}
const _settings = {
encodeUrl: typeof settings.encodeUrl === 'boolean' ? settings.encodeUrl : settings.encodeUrl === 'true',
timeout: parsedSettings.timeout !== undefined ? parsedSettings.timeout : 0
};
if (parsedSettings.followRedirects !== undefined) {
_settings.followRedirects = parsedSettings.followRedirects;
}
if (parsedSettings.maxRedirects !== undefined) {
_settings.maxRedirects = parsedSettings.maxRedirects;
}
if (keepAliveInterval) {
_settings.keepAliveInterval = keepAliveInterval;
}
return {
settings: _settings
};
},
grpc(_1, dictionary) {
return {
grpc: mapPairListToKeyValPair(dictionary.ast)
};
},
ws(_1, dictionary) {
return {
ws: mapPairListToKeyValPair(dictionary.ast)
};
},
get(_1, dictionary) {
return {
http: {
method: 'get',
...mapPairListToKeyValPair(dictionary.ast)
}
};
},
post(_1, dictionary) {
return {
http: {
method: 'post',
...mapPairListToKeyValPair(dictionary.ast)
}
};
},
put(_1, dictionary) {
return {
http: {
method: 'put',
...mapPairListToKeyValPair(dictionary.ast)
}
};
},
delete(_1, dictionary) {
return {
http: {
method: 'delete',
...mapPairListToKeyValPair(dictionary.ast)
}
};
},
patch(_1, dictionary) {
return {
http: {
method: 'patch',
...mapPairListToKeyValPair(dictionary.ast)
}
};
},
options(_1, dictionary) {
return {
http: {
method: 'options',
...mapPairListToKeyValPair(dictionary.ast)
}
};
},
head(_1, dictionary) {
return {
http: {
method: 'head',
...mapPairListToKeyValPair(dictionary.ast)
}
};
},
connect(_1, dictionary) {
return {
http: {
method: 'connect',
...mapPairListToKeyValPair(dictionary.ast)
}
};
},
trace(_1, dictionary) {
return {
http: {
method: 'trace',
...mapPairListToKeyValPair(dictionary.ast)
}
};
},
httpcustom(_1, dictionary) {
const dict = mapPairListToKeyValPair(dictionary.ast);
const method = dict.method;
const rest = { ...dict };
delete rest.method;
return {
http: {
method,
...rest
}
};
},
query(_1, dictionary) {
return {
params: mapRequestParams(dictionary.ast, 'query')
};
},
paramspath(_1, dictionary) {
return {
params: mapRequestParams(dictionary.ast, 'path')
};
},
paramsquery(_1, dictionary) {
return {
params: mapRequestParams(dictionary.ast, 'query')
};
},
headers(_1, dictionary) {
return {
headers: mapPairListToKeyValPairs(dictionary.ast)
};
},
metadata(_1, dictionary) {
return {
metadata: mapPairListToKeyValPairs(dictionary.ast)
};
},
authawsv4(_1, dictionary) {
const auth = mapPairListToKeyValPairs(dictionary.ast, false);
const accessKeyIdKey = _.find(auth, { name: 'accessKeyId' });
const secretAccessKeyKey = _.find(auth, { name: 'secretAccessKey' });
const sessionTokenKey = _.find(auth, { name: 'sessionToken' });
const serviceKey = _.find(auth, { name: 'service' });
const regionKey = _.find(auth, { name: 'region' });
const profileNameKey = _.find(auth, { name: 'profileName' });
const accessKeyId = accessKeyIdKey ? accessKeyIdKey.value : '';
const secretAccessKey = secretAccessKeyKey ? secretAccessKeyKey.value : '';
const sessionToken = sessionTokenKey ? sessionTokenKey.value : '';
const service = serviceKey ? serviceKey.value : '';
const region = regionKey ? regionKey.value : '';
const profileName = profileNameKey ? profileNameKey.value : '';
return {
auth: {
awsv4: {
accessKeyId,
secretAccessKey,
sessionToken,
service,
region,
profileName
}
}
};
},
authbasic(_1, dictionary) {
const auth = mapPairListToKeyValPairs(dictionary.ast, false);
const usernameKey = _.find(auth, { name: 'username' });
const passwordKey = _.find(auth, { name: 'password' });
const username = usernameKey ? usernameKey.value : '';
const password = passwordKey ? passwordKey.value : '';
return {
auth: {
basic: {
username,
password
}
}
};
},
authbearer(_1, dictionary) {
const auth = mapPairListToKeyValPairs(dictionary.ast, false);
const tokenKey = _.find(auth, { name: 'token' });
const token = tokenKey ? tokenKey.value : '';
return {
auth: {
bearer: {
token
}
}
};
},
authdigest(_1, dictionary) {
const auth = mapPairListToKeyValPairs(dictionary.ast, false);
const usernameKey = _.find(auth, { name: 'username' });
const passwordKey = _.find(auth, { name: 'password' });
const username = usernameKey ? usernameKey.value : '';
const password = passwordKey ? passwordKey.value : '';
return {
auth: {
digest: {
username,
password
}
}
};
},
authNTLM(_1, dictionary) {
const auth = mapPairListToKeyValPairs(dictionary.ast, false);
const usernameKey = _.find(auth, { name: 'username' });
const passwordKey = _.find(auth, { name: 'password' });
const domainKey = _.find(auth, { name: 'domain' });
const username = usernameKey ? usernameKey.value : '';
const password = passwordKey ? passwordKey.value : '';
const domain = passwordKey ? domainKey.value : '';
return {
auth: {
ntlm: {
username,
password,
domain
}
}
};
},
authOAuth2(_1, dictionary) {
const auth = mapPairListToKeyValPairs(dictionary.ast, false);
const grantTypeKey = _.find(auth, { name: 'grant_type' });
const usernameKey = _.find(auth, { name: 'username' });
const passwordKey = _.find(auth, { name: 'password' });
const callbackUrlKey = _.find(auth, { name: 'callback_url' });
const authorizationUrlKey = _.find(auth, { name: 'authorization_url' });
const accessTokenUrlKey = _.find(auth, { name: 'access_token_url' });
const refreshTokenUrlKey = _.find(auth, { name: 'refresh_token_url' });
const clientIdKey = _.find(auth, { name: 'client_id' });
const clientSecretKey = _.find(auth, { name: 'client_secret' });
const scopeKey = _.find(auth, { name: 'scope' });
const stateKey = _.find(auth, { name: 'state' });
const pkceKey = _.find(auth, { name: 'pkce' });
const credentialsPlacementKey = _.find(auth, { name: 'credentials_placement' });
const credentialsIdKey = _.find(auth, { name: 'credentials_id' });
const tokenPlacementKey = _.find(auth, { name: 'token_placement' });
const tokenHeaderPrefixKey = _.find(auth, { name: 'token_header_prefix' });
const tokenQueryKeyKey = _.find(auth, { name: 'token_query_key' });
const autoFetchTokenKey = _.find(auth, { name: 'auto_fetch_token' });
const autoRefreshTokenKey = _.find(auth, { name: 'auto_refresh_token' });
const tokenSourceKey = _.find(auth, { name: 'token_source' });
return {
auth: {
oauth2:
grantTypeKey?.value && grantTypeKey?.value == 'password'
? {
grantType: grantTypeKey ? grantTypeKey.value : '',
accessTokenUrl: accessTokenUrlKey ? accessTokenUrlKey.value : '',
refreshTokenUrl: refreshTokenUrlKey ? refreshTokenUrlKey.value : '',
username: usernameKey ? usernameKey.value : '',
password: passwordKey ? passwordKey.value : '',
clientId: clientIdKey ? clientIdKey.value : '',
clientSecret: clientSecretKey ? clientSecretKey.value : '',
scope: scopeKey ? scopeKey.value : '',
credentialsPlacement: credentialsPlacementKey?.value ? credentialsPlacementKey.value : 'body',
credentialsId: credentialsIdKey?.value ? credentialsIdKey.value : 'credentials',
tokenSource: tokenSourceKey?.value ? tokenSourceKey.value : 'access_token',
tokenPlacement: tokenPlacementKey?.value ? tokenPlacementKey.value : 'header',
tokenHeaderPrefix: tokenHeaderPrefixKey?.value ? tokenHeaderPrefixKey.value : '',
tokenQueryKey: tokenQueryKeyKey?.value ? tokenQueryKeyKey.value : 'access_token',
autoFetchToken: autoFetchTokenKey ? safeParseJson(autoFetchTokenKey?.value) ?? true : true,
autoRefreshToken: autoRefreshTokenKey ? safeParseJson(autoRefreshTokenKey?.value) ?? false : false
}
: grantTypeKey?.value && grantTypeKey?.value == 'authorization_code'
? {
grantType: grantTypeKey ? grantTypeKey.value : '',
callbackUrl: callbackUrlKey ? callbackUrlKey.value : '',
authorizationUrl: authorizationUrlKey ? authorizationUrlKey.value : '',
accessTokenUrl: accessTokenUrlKey ? accessTokenUrlKey.value : '',
refreshTokenUrl: refreshTokenUrlKey ? refreshTokenUrlKey.value : '',
clientId: clientIdKey ? clientIdKey.value : '',
clientSecret: clientSecretKey ? clientSecretKey.value : '',
scope: scopeKey ? scopeKey.value : '',
state: stateKey ? stateKey.value : '',
pkce: pkceKey ? safeParseJson(pkceKey?.value) ?? false : false,
credentialsPlacement: credentialsPlacementKey?.value ? credentialsPlacementKey.value : 'body',
credentialsId: credentialsIdKey?.value ? credentialsIdKey.value : 'credentials',
tokenSource: tokenSourceKey?.value ? tokenSourceKey.value : 'access_token',
tokenPlacement: tokenPlacementKey?.value ? tokenPlacementKey.value : 'header',
tokenHeaderPrefix: tokenHeaderPrefixKey?.value ? tokenHeaderPrefixKey.value : '',
tokenQueryKey: tokenQueryKeyKey?.value ? tokenQueryKeyKey.value : 'access_token',
autoFetchToken: autoFetchTokenKey ? safeParseJson(autoFetchTokenKey?.value) ?? true : true,
autoRefreshToken: autoRefreshTokenKey ? safeParseJson(autoRefreshTokenKey?.value) ?? false : false
}
: grantTypeKey?.value && grantTypeKey?.value == 'client_credentials'
? {
grantType: grantTypeKey ? grantTypeKey.value : '',
accessTokenUrl: accessTokenUrlKey ? accessTokenUrlKey.value : '',
refreshTokenUrl: refreshTokenUrlKey ? refreshTokenUrlKey.value : '',
clientId: clientIdKey ? clientIdKey.value : '',
clientSecret: clientSecretKey ? clientSecretKey.value : '',
scope: scopeKey ? scopeKey.value : '',
credentialsPlacement: credentialsPlacementKey?.value ? credentialsPlacementKey.value : 'body',
credentialsId: credentialsIdKey?.value ? credentialsIdKey.value : 'credentials',
tokenSource: tokenSourceKey?.value ? tokenSourceKey.value : 'access_token',
tokenPlacement: tokenPlacementKey?.value ? tokenPlacementKey.value : 'header',
tokenHeaderPrefix: tokenHeaderPrefixKey?.value ? tokenHeaderPrefixKey.value : '',
tokenQueryKey: tokenQueryKeyKey?.value ? tokenQueryKeyKey.value : 'access_token',
autoFetchToken: autoFetchTokenKey ? safeParseJson(autoFetchTokenKey?.value) ?? true : true,
autoRefreshToken: autoRefreshTokenKey ? safeParseJson(autoRefreshTokenKey?.value) ?? false : false
}
: grantTypeKey?.value && grantTypeKey?.value == 'implicit'
? {
grantType: grantTypeKey ? grantTypeKey.value : '',
callbackUrl: callbackUrlKey ? callbackUrlKey.value : '',
authorizationUrl: authorizationUrlKey ? authorizationUrlKey.value : '',
clientId: clientIdKey ? clientIdKey.value : '',
scope: scopeKey ? scopeKey.value : '',
state: stateKey ? stateKey.value : '',
credentialsId: credentialsIdKey?.value ? credentialsIdKey.value : 'credentials',
tokenSource: tokenSourceKey?.value ? tokenSourceKey.value : 'access_token',
tokenPlacement: tokenPlacementKey?.value ? tokenPlacementKey.value : 'header',
tokenHeaderPrefix: tokenHeaderPrefixKey?.value ? tokenHeaderPrefixKey.value : '',
tokenQueryKey: tokenQueryKeyKey?.value ? tokenQueryKeyKey.value : 'access_token',
autoFetchToken: autoFetchTokenKey ? safeParseJson(autoFetchTokenKey?.value) ?? true : true
}
: {}
}
};
},
oauth2AuthReqHeaders(_1, dictionary) {
return {
oauth2_additional_parameters_auth_req_headers: mapPairListToKeyValPairs(dictionary.ast)
};
},
oauth2AuthReqQueryParams(_1, dictionary) {
return {
oauth2_additional_parameters_auth_req_queryparams: mapPairListToKeyValPairs(dictionary.ast)
};
},
oauth2AccessTokenReqHeaders(_1, dictionary) {
return {
oauth2_additional_parameters_access_token_req_headers: mapPairListToKeyValPairs(dictionary.ast)
};
},
oauth2AccessTokenReqQueryParams(_1, dictionary) {
return {
oauth2_additional_parameters_access_token_req_queryparams: mapPairListToKeyValPairs(dictionary.ast)
};
},
oauth2AccessTokenReqBody(_1, dictionary) {
return {
oauth2_additional_parameters_access_token_req_bodyvalues: mapPairListToKeyValPairs(dictionary.ast)
};
},
oauth2RefreshTokenReqHeaders(_1, dictionary) {
return {
oauth2_additional_parameters_refresh_token_req_headers: mapPairListToKeyValPairs(dictionary.ast)
};
},
oauth2RefreshTokenReqQueryParams(_1, dictionary) {
return {
oauth2_additional_parameters_refresh_token_req_queryparams: mapPairListToKeyValPairs(dictionary.ast)
};
},
oauth2RefreshTokenReqBody(_1, dictionary) {
return {
oauth2_additional_parameters_refresh_token_req_bodyvalues: mapPairListToKeyValPairs(dictionary.ast)
};
},
authwsse(_1, dictionary) {
const auth = mapPairListToKeyValPairs(dictionary.ast, false);
const userKey = _.find(auth, { name: 'username' });
const secretKey = _.find(auth, { name: 'password' });
const username = userKey ? userKey.value : '';
const password = secretKey ? secretKey.value : '';
return {
auth: {
wsse: {
username,
password
}
}
};
},
authapikey(_1, dictionary) {
const auth = mapPairListToKeyValPairs(dictionary.ast, false);
const findValueByName = (name) => {
const item = _.find(auth, { name });
return item ? item.value : '';
};
const key = findValueByName('key');
const value = findValueByName('value');
const placement = findValueByName('placement');
return {
auth: {
apikey: {
key,
value,
placement
}
}
};
},
bodyformurlencoded(_1, dictionary) {
return {
body: {
formUrlEncoded: mapPairListToKeyValPairs(dictionary.ast)
}
};
},
bodymultipart(_1, dictionary) {
return {
body: {
multipartForm: mapPairListToKeyValPairsMultipart(dictionary.ast)
}
};
},
bodyfile(_1, dictionary) {
return {
body: {
file: mapPairListToKeyValPairsFile(dictionary.ast)
}
};
},
body(_1, _2, _3, _4, textblock, _5) {
return {
http: {
body: 'json'
},
body: {
json: outdentString(textblock.sourceString)
}
};
},
bodyjson(_1, _2, _3, _4, textblock, _5) {
return {
body: {
json: outdentString(textblock.sourceString)
}
};
},
bodytext(_1, _2, _3, _4, textblock, _5) {
return {
body: {
text: outdentString(textblock.sourceString)
}
};
},
bodyxml(_1, _2, _3, _4, textblock, _5) {
return {
body: {
xml: outdentString(textblock.sourceString)
}
};
},
bodysparql(_1, _2, _3, _4, textblock, _5) {
return {
body: {
sparql: outdentString(textblock.sourceString)
}
};
},
bodygraphql(_1, _2, _3, _4, textblock, _5) {
return {
body: {
graphql: {
query: outdentString(textblock.sourceString)
}
}
};
},
bodygraphqlvars(_1, _2, _3, _4, textblock, _5) {
return {
body: {
graphql: {
variables: outdentString(textblock.sourceString)
}
}
};
},
varsreq(_1, dictionary) {
const vars = mapPairListToKeyValPairs(dictionary.ast);
_.each(vars, (v) => {
let name = v.name;
if (name && name.length && name.charAt(0) === '@') {
v.name = name.slice(1);
v.local = true;
} else {
v.local = false;
}
});
return {
vars: {
req: vars
}
};
},
varsres(_1, dictionary) {
const vars = mapPairListToKeyValPairs(dictionary.ast);
_.each(vars, (v) => {
let name = v.name;
if (name && name.length && name.charAt(0) === '@') {
v.name = name.slice(1);
v.local = true;
} else {
v.local = false;
}
});
return {
vars: {
res: vars
}
};
},
assert(_1, dictionary) {
return {
assertions: mapPairListToKeyValPairs(dictionary.ast)
};
},
scriptreq(_1, _2, _3, _4, textblock, _5) {
return {
script: {
req: outdentString(textblock.sourceString)
}
};
},
scriptres(_1, _2, _3, _4, textblock, _5) {
return {
script: {
res: outdentString(textblock.sourceString)
}
};
},
tests(_1, _2, _3, _4, textblock, _5) {
return {
tests: outdentString(textblock.sourceString)
};
},
docs(_1, _2, _3, _4, textblock, _5) {
return {
docs: outdentString(textblock.sourceString)
};
},
bodygrpc(_1, dictionary) {
const pairs = mapPairListToKeyValPairs(dictionary.ast, false);
const namePair = _.find(pairs, { name: 'name' });
const contentPair = _.find(pairs, { name: 'content' });
const messageName = namePair ? namePair.value : '';
const messageContent = contentPair ? contentPair.value : '';
return {
body: {
mode: 'grpc',
grpc: [{
name: messageName,
content: messageContent
}]
}
};
},
bodyws(_1, dictionary) {
const pairs = mapPairListToKeyValPairs(dictionary.ast, false);
const namePair = _.find(pairs, { name: 'name' });
const contentPair = _.find(pairs, { name: 'content' });
const typePair = _.find(pairs, { name: 'type' });
const messageName = namePair ? namePair.value : '';
const messageContent = contentPair ? contentPair.value : '';
const messageTypeContent = typePair ? typePair.value : '';
return {
body: {
mode: 'ws',
ws: [
{
name: messageName,
type: messageTypeContent,
content: messageContent
}
]
}
};
},
example(_1, _2, _3, _4, examplecontent, _5) {
const content = examplecontent.sourceString;
const parsedExample = parseExampleContent(content);
return {
examples: [parsedExample]
};
},
examplecontent(chars) {
return outdentString(chars.sourceString);
}
});
const parser = (input) => {
const match = grammar.match(input);
if (match.succeeded()) {
let ast = sem(match).ast;
return ast;
} else {
throw new Error(match.message);
}
};
module.exports = parser;