forked from extern/bruno
feat: generic key val line parser
This commit is contained in:
parent
b88848f0dc
commit
d9ef1692fe
@ -1,16 +1,9 @@
|
|||||||
const {
|
const {
|
||||||
between,
|
between,
|
||||||
regex,
|
regex,
|
||||||
everyCharUntil,
|
everyCharUntil
|
||||||
digit,
|
|
||||||
whitespace,
|
|
||||||
optionalWhitespace,
|
|
||||||
endOfInput,
|
|
||||||
choice,
|
|
||||||
many,
|
|
||||||
sepBy,
|
|
||||||
sequenceOf
|
|
||||||
} = require("arcsecond");
|
} = require("arcsecond");
|
||||||
|
const keyvalLines = require('./key-val-lines');
|
||||||
|
|
||||||
// body(type=json)
|
// body(type=json)
|
||||||
const bodyJsonBegin = regex(/^body\s*\(\s*type\s*=\s*json\s*\)\s*\r?\n/);
|
const bodyJsonBegin = regex(/^body\s*\(\s*type\s*=\s*json\s*\)\s*\r?\n/);
|
||||||
@ -60,32 +53,6 @@ const bodyXmlTag = between(bodyXmlBegin)(bodyEnd)(everyCharUntil(bodyEnd)).map((
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// generic key value parser
|
|
||||||
const newline = regex(/^\r?\n/);
|
|
||||||
const newLineOrEndOfInput = choice([newline, endOfInput]);
|
|
||||||
const wordWithoutWhitespace = regex(/^[^\s\t\r?\n]+/g);
|
|
||||||
const wordWithWhitespace = regex(/^[^\r?\n]+/g);
|
|
||||||
|
|
||||||
const line = sequenceOf([
|
|
||||||
optionalWhitespace,
|
|
||||||
digit,
|
|
||||||
whitespace,
|
|
||||||
wordWithoutWhitespace,
|
|
||||||
whitespace,
|
|
||||||
wordWithWhitespace,
|
|
||||||
newLineOrEndOfInput
|
|
||||||
]).map(([_, enabled, __, key, ___, value]) => {
|
|
||||||
return {
|
|
||||||
"enabled": Number(enabled) ? true : false,
|
|
||||||
"name": key,
|
|
||||||
"value": value
|
|
||||||
};
|
|
||||||
});
|
|
||||||
|
|
||||||
const lines = many(line);
|
|
||||||
const keyvalLines = sepBy(newline)(lines);
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* We have deprecated form-url-encoded type in body tag, it was a misspelling on my part
|
* We have deprecated form-url-encoded type in body tag, it was a misspelling on my part
|
||||||
* The new type is form-urlencoded
|
* The new type is form-urlencoded
|
||||||
|
@ -1,44 +1,18 @@
|
|||||||
const {
|
const {
|
||||||
sequenceOf,
|
|
||||||
whitespace,
|
|
||||||
optionalWhitespace,
|
|
||||||
choice,
|
|
||||||
endOfInput,
|
|
||||||
between,
|
between,
|
||||||
digit,
|
|
||||||
many,
|
|
||||||
regex,
|
regex,
|
||||||
sepBy
|
|
||||||
} = require("arcsecond");
|
} = require("arcsecond");
|
||||||
|
const { each } = require('lodash');
|
||||||
const newline = regex(/^\r?\n/);
|
const keyValLines = require('./key-val-lines');
|
||||||
const newLineOrEndOfInput = choice([newline, endOfInput]);
|
|
||||||
|
|
||||||
const begin = regex(/^vars\s*\r?\n/);
|
const begin = regex(/^vars\s*\r?\n/);
|
||||||
const end = regex(/^[\r?\n]*\/vars\s*[\r?\n]*/);
|
const end = regex(/^[\r?\n]*\/vars\s*[\r?\n]*/);
|
||||||
const wordWithoutWhitespace = regex(/^[^\s\r?\t\n]+/g);
|
|
||||||
const wordWithWhitespace = regex(/^[^\r?\n]+/g);
|
|
||||||
|
|
||||||
const line = sequenceOf([
|
const envVarsTag = between(begin)(end)(keyValLines).map(([variables]) => {
|
||||||
optionalWhitespace,
|
each(variables, (variable) => {
|
||||||
digit,
|
variable.type = "text"
|
||||||
whitespace,
|
});
|
||||||
wordWithoutWhitespace,
|
|
||||||
whitespace,
|
|
||||||
wordWithWhitespace,
|
|
||||||
newLineOrEndOfInput
|
|
||||||
]).map(([_, enabled, __, key, ___, value]) => {
|
|
||||||
return {
|
|
||||||
"enabled": Number(enabled) ? true : false,
|
|
||||||
"name": key,
|
|
||||||
"value": value,
|
|
||||||
"type": "text"
|
|
||||||
};
|
|
||||||
});
|
|
||||||
|
|
||||||
const lines = many(line);
|
|
||||||
const envVarsLines = sepBy(newline)(lines);
|
|
||||||
const envVarsTag = between(begin)(end)(envVarsLines).map(([variables]) => {
|
|
||||||
return {
|
return {
|
||||||
variables
|
variables
|
||||||
};
|
};
|
||||||
|
@ -1,43 +1,13 @@
|
|||||||
const {
|
const {
|
||||||
sequenceOf,
|
|
||||||
whitespace,
|
|
||||||
optionalWhitespace,
|
|
||||||
choice,
|
|
||||||
endOfInput,
|
|
||||||
between,
|
between,
|
||||||
digit,
|
regex
|
||||||
many,
|
|
||||||
regex,
|
|
||||||
sepBy
|
|
||||||
} = require("arcsecond");
|
} = require("arcsecond");
|
||||||
|
const keyValLines = require('./key-val-lines');
|
||||||
const newline = regex(/^\r?\n/);
|
|
||||||
const newLineOrEndOfInput = choice([newline, endOfInput]);
|
|
||||||
|
|
||||||
const begin = regex(/^headers\s*\r?\n/);
|
const begin = regex(/^headers\s*\r?\n/);
|
||||||
const end = regex(/^[\r?\n]*\/headers\s*[\r?\n]*/);
|
const end = regex(/^[\r?\n]*\/headers\s*[\r?\n]*/);
|
||||||
const wordWithoutWhitespace = regex(/^[^\s\t\n]+/g);
|
|
||||||
const wordWithWhitespace = regex(/^[^\r?\n]+/g);
|
|
||||||
|
|
||||||
const line = sequenceOf([
|
const headersTag = between(begin)(end)(keyValLines).map(([headers]) => {
|
||||||
optionalWhitespace,
|
|
||||||
digit,
|
|
||||||
whitespace,
|
|
||||||
wordWithoutWhitespace,
|
|
||||||
whitespace,
|
|
||||||
wordWithWhitespace,
|
|
||||||
newLineOrEndOfInput
|
|
||||||
]).map(([_, enabled, __, key, ___, value]) => {
|
|
||||||
return {
|
|
||||||
"enabled": Number(enabled) ? true : false,
|
|
||||||
"name": key,
|
|
||||||
"value": value
|
|
||||||
};
|
|
||||||
});
|
|
||||||
|
|
||||||
const lines = many(line);
|
|
||||||
const headersLines = sepBy(newline)(lines);
|
|
||||||
const headersTag = between(begin)(end)(headersLines).map(([headers]) => {
|
|
||||||
return {
|
return {
|
||||||
headers
|
headers
|
||||||
};
|
};
|
||||||
|
64
packages/bruno-lang/src/key-val-lines.js
Normal file
64
packages/bruno-lang/src/key-val-lines.js
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
const {
|
||||||
|
sequenceOf,
|
||||||
|
whitespace,
|
||||||
|
optionalWhitespace,
|
||||||
|
choice,
|
||||||
|
digit,
|
||||||
|
many,
|
||||||
|
regex,
|
||||||
|
sepBy,
|
||||||
|
} = require("arcsecond");
|
||||||
|
|
||||||
|
const newline = regex(/^\r?\n/);
|
||||||
|
const wordWithoutWhitespace = regex(/^[^\s\r?\t\n]+/g);
|
||||||
|
const wordWithWhitespace = regex(/^[^\r?\n]+/g);
|
||||||
|
|
||||||
|
// matching lines like: 1 key value
|
||||||
|
const line = sequenceOf([
|
||||||
|
optionalWhitespace,
|
||||||
|
digit,
|
||||||
|
whitespace,
|
||||||
|
wordWithoutWhitespace,
|
||||||
|
whitespace,
|
||||||
|
wordWithWhitespace
|
||||||
|
]).map(([_, enabled, __, key, ___, value]) => {
|
||||||
|
return {
|
||||||
|
"enabled": Number(enabled) ? true : false,
|
||||||
|
"name": key ? key.trim() : "",
|
||||||
|
"value": value ? value.trim() : ""
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
// matching lines like: 1 key follows by [whitespaces] and a newline
|
||||||
|
const line2 = sequenceOf([
|
||||||
|
optionalWhitespace,
|
||||||
|
digit,
|
||||||
|
whitespace,
|
||||||
|
wordWithoutWhitespace,
|
||||||
|
regex(/^\s*\r?\n/)
|
||||||
|
]).map(([_, enabled, __, key]) => {
|
||||||
|
return {
|
||||||
|
"enabled": Number(enabled) ? true : false,
|
||||||
|
"name": key,
|
||||||
|
"value": ""
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
// matching lines like: 1 followed by [whitespaces] and a newline
|
||||||
|
const line3 = sequenceOf([
|
||||||
|
optionalWhitespace,
|
||||||
|
digit,
|
||||||
|
regex(/^\s*\r?\n/)
|
||||||
|
]).map(([_, enabled]) => {
|
||||||
|
return {
|
||||||
|
"enabled": Number(enabled) ? true : false,
|
||||||
|
"name": "",
|
||||||
|
"value": ""
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
const lines = many(choice([line3, line2, line]));
|
||||||
|
|
||||||
|
const keyValLines = sepBy(newline)(lines);
|
||||||
|
|
||||||
|
module.exports = keyValLines;
|
@ -1,44 +1,13 @@
|
|||||||
const {
|
const {
|
||||||
sequenceOf,
|
|
||||||
whitespace,
|
|
||||||
optionalWhitespace,
|
|
||||||
choice,
|
|
||||||
endOfInput,
|
|
||||||
everyCharUntil,
|
|
||||||
between,
|
between,
|
||||||
digit,
|
regex
|
||||||
many,
|
|
||||||
regex,
|
|
||||||
sepBy
|
|
||||||
} = require("arcsecond");
|
} = require("arcsecond");
|
||||||
|
const keyValLines = require('./key-val-lines');
|
||||||
const newline = regex(/^\r?\n/);
|
|
||||||
const newLineOrEndOfInput = choice([newline, endOfInput]);
|
|
||||||
|
|
||||||
const begin = regex(/^params\s*\r?\n/);
|
const begin = regex(/^params\s*\r?\n/);
|
||||||
const end = regex(/^[\r?\n]*\/params\s*[\r?\n]*/);
|
const end = regex(/^[\r?\n]*\/params\s*[\r?\n]*/);
|
||||||
const wordWithoutWhitespace = regex(/^[^\s\t\r?\n]+/g);
|
|
||||||
const wordWithWhitespace = regex(/^[^\r?\n]+/g);
|
|
||||||
|
|
||||||
const line = sequenceOf([
|
const paramsTag = between(begin)(end)(keyValLines).map(([params]) => {
|
||||||
optionalWhitespace,
|
|
||||||
digit,
|
|
||||||
whitespace,
|
|
||||||
wordWithoutWhitespace,
|
|
||||||
whitespace,
|
|
||||||
wordWithWhitespace,
|
|
||||||
newLineOrEndOfInput
|
|
||||||
]).map(([_, enabled, __, key, ___, value]) => {
|
|
||||||
return {
|
|
||||||
"enabled": Number(enabled) ? true : false,
|
|
||||||
"name": key,
|
|
||||||
"value": value
|
|
||||||
};
|
|
||||||
});
|
|
||||||
|
|
||||||
const lines = many(line);
|
|
||||||
const paramsLines = sepBy(newline)(lines);
|
|
||||||
const paramsTag = between(begin)(end)(paramsLines).map(([params]) => {
|
|
||||||
return {
|
return {
|
||||||
params
|
params
|
||||||
};
|
};
|
||||||
|
230
packages/bruno-lang/tests/key-val-lines.spec.js
Normal file
230
packages/bruno-lang/tests/key-val-lines.spec.js
Normal file
@ -0,0 +1,230 @@
|
|||||||
|
const {
|
||||||
|
between,
|
||||||
|
regex,
|
||||||
|
anyChar,
|
||||||
|
many,
|
||||||
|
choice
|
||||||
|
} = require("arcsecond");
|
||||||
|
const _ = require('lodash');
|
||||||
|
|
||||||
|
const keyValLines = require('../src/key-val-lines');
|
||||||
|
|
||||||
|
const begin = regex(/^vars\s*\r?\n/);
|
||||||
|
const end = regex(/^[\r?\n]*\/vars\s*[\r?\n]*/);
|
||||||
|
|
||||||
|
const varsTag = between(begin)(end)(keyValLines).map(([variables]) => {
|
||||||
|
return {
|
||||||
|
variables
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
const toJson = (fileContents) => {
|
||||||
|
const parser = many(choice([
|
||||||
|
varsTag,
|
||||||
|
anyChar
|
||||||
|
]));
|
||||||
|
|
||||||
|
const parsed = parser
|
||||||
|
.run(fileContents)
|
||||||
|
.result
|
||||||
|
.reduce((acc, item) => _.merge(acc, item), {});
|
||||||
|
|
||||||
|
const json = {
|
||||||
|
variables: parsed.variables || []
|
||||||
|
};
|
||||||
|
|
||||||
|
return json;
|
||||||
|
};
|
||||||
|
|
||||||
|
describe('bool-key-val', () => {
|
||||||
|
it('should parse bool-key-val - case 1', () => {
|
||||||
|
const file = `
|
||||||
|
vars
|
||||||
|
1 host https://www.google.com
|
||||||
|
/vars
|
||||||
|
`;
|
||||||
|
|
||||||
|
const result = toJson(file);
|
||||||
|
expect(result).toEqual({
|
||||||
|
variables: [{
|
||||||
|
enabled: true,
|
||||||
|
name: 'host',
|
||||||
|
value: 'https://www.google.com'
|
||||||
|
}]
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should parse bool-key-val - case 2', () => {
|
||||||
|
const file = `
|
||||||
|
vars
|
||||||
|
1 host https://www.google.com
|
||||||
|
1 auth jwt secret
|
||||||
|
/vars
|
||||||
|
`;
|
||||||
|
|
||||||
|
const result = toJson(file);
|
||||||
|
expect(result).toEqual({
|
||||||
|
variables: [{
|
||||||
|
enabled: true,
|
||||||
|
name: 'host',
|
||||||
|
value: 'https://www.google.com'
|
||||||
|
}, {
|
||||||
|
enabled: true,
|
||||||
|
name: 'auth',
|
||||||
|
value: 'jwt secret'
|
||||||
|
}]
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// following test cases are for edge cases
|
||||||
|
|
||||||
|
// one line with just enabled flag
|
||||||
|
it('should parse bool-key-val - case 3', () => {
|
||||||
|
const file = `
|
||||||
|
vars
|
||||||
|
1
|
||||||
|
/vars
|
||||||
|
`;
|
||||||
|
const result = toJson(file);
|
||||||
|
expect(result).toEqual({
|
||||||
|
variables: [{
|
||||||
|
enabled: true,
|
||||||
|
name: '',
|
||||||
|
value: ''
|
||||||
|
}]
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// one line with just enabled flag and a space
|
||||||
|
it('should parse bool-key-val - case 4', () => {
|
||||||
|
const file = `
|
||||||
|
vars
|
||||||
|
1
|
||||||
|
/vars
|
||||||
|
`;
|
||||||
|
const result = toJson(file);
|
||||||
|
expect(result).toEqual({
|
||||||
|
variables: [{
|
||||||
|
enabled: true,
|
||||||
|
name: '',
|
||||||
|
value: ''
|
||||||
|
}]
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// one line with just enabled flag and a space and a name
|
||||||
|
it('should parse bool-key-val - case 5', () => {
|
||||||
|
const file = `
|
||||||
|
vars
|
||||||
|
1 host
|
||||||
|
/vars
|
||||||
|
`;
|
||||||
|
const result = toJson(file);
|
||||||
|
expect(result).toEqual({
|
||||||
|
variables: [{
|
||||||
|
enabled: true,
|
||||||
|
name: 'host',
|
||||||
|
value: ''
|
||||||
|
}]
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// one line with just enabled flag and a space and a name and a space
|
||||||
|
it('should parse bool-key-val - case 6', () => {
|
||||||
|
const file = `
|
||||||
|
vars
|
||||||
|
1 host
|
||||||
|
/vars
|
||||||
|
`;
|
||||||
|
const result = toJson(file);
|
||||||
|
expect(result).toEqual({
|
||||||
|
variables: [{
|
||||||
|
enabled: true,
|
||||||
|
name: 'host',
|
||||||
|
value: ''
|
||||||
|
}]
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// three lines, second line with just enabled flag
|
||||||
|
it('should parse bool-key-val - case 7', () => {
|
||||||
|
const file = `
|
||||||
|
vars
|
||||||
|
1 host https://www.google.com
|
||||||
|
1
|
||||||
|
0 Content-type application/json
|
||||||
|
/vars
|
||||||
|
`;
|
||||||
|
const result = toJson(file);
|
||||||
|
expect(result).toEqual({
|
||||||
|
variables: [{
|
||||||
|
enabled: true,
|
||||||
|
name: 'host',
|
||||||
|
value: 'https://www.google.com'
|
||||||
|
}, {
|
||||||
|
enabled: true,
|
||||||
|
name: '',
|
||||||
|
value: ''
|
||||||
|
}, {
|
||||||
|
enabled: false,
|
||||||
|
name: 'Content-type',
|
||||||
|
value: 'application/json'
|
||||||
|
}]
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// three lines, second line with just enabled flag and a space
|
||||||
|
it('should parse bool-key-val - case 8', () => {
|
||||||
|
const file = `
|
||||||
|
vars
|
||||||
|
1 host https://www.google.com
|
||||||
|
1
|
||||||
|
0 Content-type application/json
|
||||||
|
/vars
|
||||||
|
`;
|
||||||
|
const result = toJson(file);
|
||||||
|
expect(result).toEqual({
|
||||||
|
variables: [{
|
||||||
|
enabled: true,
|
||||||
|
name: 'host',
|
||||||
|
value: 'https://www.google.com'
|
||||||
|
}, {
|
||||||
|
enabled: true,
|
||||||
|
name: '',
|
||||||
|
value: ''
|
||||||
|
}, {
|
||||||
|
enabled: false,
|
||||||
|
name: 'Content-type',
|
||||||
|
value: 'application/json'
|
||||||
|
}]
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// three lines, second line with just enabled flag and a space and a name
|
||||||
|
it('should parse bool-key-val - case 9', () => {
|
||||||
|
const file = `
|
||||||
|
vars
|
||||||
|
1 host https://www.google.com
|
||||||
|
1 auth
|
||||||
|
0 Content-type application/json
|
||||||
|
/vars
|
||||||
|
`;
|
||||||
|
const result = toJson(file);
|
||||||
|
expect(result).toEqual({
|
||||||
|
variables: [{
|
||||||
|
enabled: true,
|
||||||
|
name: 'host',
|
||||||
|
value: 'https://www.google.com'
|
||||||
|
}, {
|
||||||
|
enabled: true,
|
||||||
|
name: 'auth',
|
||||||
|
value: ''
|
||||||
|
}, {
|
||||||
|
enabled: false,
|
||||||
|
name: 'Content-type',
|
||||||
|
value: 'application/json'
|
||||||
|
}]
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
Loading…
Reference in New Issue
Block a user