prettify-bru 1.7.0 → 1.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +44 -3
- package/lib/config.mjs +40 -12
- package/lib/format.mjs +43 -20
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -2,9 +2,10 @@
|
|
|
2
2
|
|
|
3
3
|
A CLI tool to [prettify and format Bruno `.bru` files](https://www.npmjs.com/package/prettify-bru).
|
|
4
4
|
|
|
5
|
+
Removes junk and makes code shorter and more transferable between systems.
|
|
5
6
|
Imposes a standard format on all blocks of JSON and JavaScript code across multiple [Bruno](https://www.usebruno.com/) `.bru` files in your project.
|
|
6
7
|
|
|
7
|
-
`body:json` blocks are formatted using [
|
|
8
|
+
`body:json` blocks are formatted using [jsonc-parser](https://www.npmjs.com/package/jsonc-parser)
|
|
8
9
|
|
|
9
10
|
`script:pre-request`, `script:post-response` and `tests` blocks are formatted using [Prettier](https://prettier.io/) with [Babel](https://babeljs.io/docs/babel-parser) parser.
|
|
10
11
|
|
|
@@ -119,7 +120,47 @@ npm prettify-bru --write --only body:json speed-tests/get-all.bru
|
|
|
119
120
|
|
|
120
121
|
## Config file
|
|
121
122
|
|
|
122
|
-
|
|
123
|
+
Create a `.prettifybrurc` file containing a JSON object with one or more of the following properties:
|
|
124
|
+
|
|
125
|
+
### Agnostic File Paths
|
|
126
|
+
|
|
127
|
+
Property: `agnosticFilePaths` {boolean} (Default: `true`)
|
|
128
|
+
|
|
129
|
+
Replaces backslash folder separators in filenames with forward slashes so they work on Windows, Mac and Linux
|
|
130
|
+
|
|
131
|
+
```
|
|
132
|
+
file: @file(\Images\Memes\3-Spidermen.jpg) @contentType(image/jpeg)
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
will be changed to...
|
|
136
|
+
|
|
137
|
+
```
|
|
138
|
+
file: @file(/Images/Memes/3-Spidermen.jpg) @contentType(image/jpeg)
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
### Shorten Getters
|
|
142
|
+
|
|
143
|
+
Property: `shortenGetters` {boolean} (Default: `true`)
|
|
144
|
+
|
|
145
|
+
Shorten code by replacing uses of getters with property references
|
|
146
|
+
|
|
147
|
+
```javascript
|
|
148
|
+
expect(res.getStatus()).to.eql(200)
|
|
149
|
+
expect(res.getBody().name).to.eql("Dave")
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
The above will become...
|
|
153
|
+
|
|
154
|
+
```javascript
|
|
155
|
+
expect(res.status).to.eql(200)
|
|
156
|
+
expect(res.body.name).to.eql("Dave")
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
### Prettier
|
|
160
|
+
|
|
161
|
+
Property: `prettier` {Object} (Default: `{}`)
|
|
162
|
+
|
|
163
|
+
The `prettier` property object can contain overrides for any of the [Prettier options](https://prettier.io/docs/options).
|
|
123
164
|
|
|
124
165
|
For example, to increase the line length limit from the default 80 up to 120 characters, your file would contain:
|
|
125
166
|
|
|
@@ -131,7 +172,7 @@ For example, to increase the line length limit from the default 80 up to 120 cha
|
|
|
131
172
|
}
|
|
132
173
|
```
|
|
133
174
|
|
|
134
|
-
*Note: Config file is supported from version 1.6.0 and above.*
|
|
175
|
+
*Note: Config file is supported from version [1.6.0](CHANGELOG.md#160) and above.*
|
|
135
176
|
|
|
136
177
|
## Automatically checking PRs
|
|
137
178
|
|
package/lib/config.mjs
CHANGED
|
@@ -2,6 +2,20 @@ import {readIfExists} from './files.mjs'
|
|
|
2
2
|
|
|
3
3
|
const configFilename = '.prettifybrurc'
|
|
4
4
|
|
|
5
|
+
/**
|
|
6
|
+
* @typedef {Object} PrettifyBruConfig
|
|
7
|
+
* @property {boolean} agnosticFilePaths
|
|
8
|
+
* @property {boolean} shortenGetters
|
|
9
|
+
* @property {Object} prettier Prettier options
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
/** @type {PrettifyBruConfig} */
|
|
13
|
+
export const defaultConfig = {
|
|
14
|
+
agnosticFilePaths: true,
|
|
15
|
+
shortenGetters: true,
|
|
16
|
+
prettier: {},
|
|
17
|
+
}
|
|
18
|
+
|
|
5
19
|
/**
|
|
6
20
|
*
|
|
7
21
|
* @param {Object} console
|
|
@@ -44,21 +58,26 @@ export function parseFile(console, fileContents) {
|
|
|
44
58
|
|
|
45
59
|
let config = {}
|
|
46
60
|
|
|
47
|
-
const supportedProperties =
|
|
61
|
+
const supportedProperties = {
|
|
62
|
+
agnosticFilePaths: 'a boolean',
|
|
63
|
+
shortenGetters: 'a boolean',
|
|
64
|
+
prettier: 'an object',
|
|
65
|
+
}
|
|
48
66
|
Object.keys(fileConfig).forEach(key => {
|
|
49
|
-
if (
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
67
|
+
if (Object.hasOwn(supportedProperties, key)) {
|
|
68
|
+
const value = fileConfig[key]
|
|
69
|
+
const validType = supportedProperties[key]
|
|
70
|
+
const validates = validators[validType]
|
|
71
|
+
|
|
72
|
+
if (validates(value)) {
|
|
73
|
+
config[key] = fileConfig[key]
|
|
74
|
+
} else {
|
|
75
|
+
console.warn(
|
|
76
|
+
`⚠️ \x1b[33m"${key}" is not correct type, it should be ${validType}\x1b[0m`
|
|
77
|
+
)
|
|
58
78
|
}
|
|
59
|
-
config[key] = fileConfig[key]
|
|
60
79
|
} else {
|
|
61
|
-
console.warn(`⚠️ \x1b[
|
|
80
|
+
console.warn(`⚠️ \x1b[33mIgnoring unsupported property "${key}"\x1b[0m`)
|
|
62
81
|
}
|
|
63
82
|
})
|
|
64
83
|
|
|
@@ -66,3 +85,12 @@ export function parseFile(console, fileContents) {
|
|
|
66
85
|
|
|
67
86
|
return config
|
|
68
87
|
}
|
|
88
|
+
|
|
89
|
+
const validators = {
|
|
90
|
+
'an object': value => {
|
|
91
|
+
return value !== null && typeof value === 'object' && !Array.isArray(value)
|
|
92
|
+
},
|
|
93
|
+
'a boolean': value => {
|
|
94
|
+
return typeof value === 'boolean'
|
|
95
|
+
},
|
|
96
|
+
}
|
package/lib/format.mjs
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import prettier from 'prettier'
|
|
2
|
-
import
|
|
2
|
+
import {defaultConfig} from './config.mjs'
|
|
3
|
+
import {format as jsoncFormat, applyEdits} from 'jsonc-parser'
|
|
3
4
|
|
|
4
5
|
// This Prettier config should match what the Bruno GUI implements
|
|
5
6
|
const defaultPrettierConfig = {
|
|
@@ -25,14 +26,26 @@ const formattableBlocks = ['body:json', 'script:pre-request', 'script:post-respo
|
|
|
25
26
|
*/
|
|
26
27
|
|
|
27
28
|
/**
|
|
28
|
-
* Tidies
|
|
29
|
+
* Tidies structure of bru lang file, makes code shorter and operating system agnostic,
|
|
30
|
+
* applies standard formatting to both JSON and JavaScript blocks
|
|
29
31
|
*
|
|
30
32
|
* @param {string} originalContents The file contents as loaded from file system
|
|
31
33
|
* @param {?string} only Limit to only the block type with a name containing value
|
|
32
|
-
* @param {Object}
|
|
34
|
+
* @param {Object} configOverrides Could be whole PrettifyBruConfig or partial
|
|
33
35
|
* @returns {Promise<FileOutcome>}
|
|
34
36
|
*/
|
|
35
|
-
export async function format(originalContents, only = null,
|
|
37
|
+
export async function format(originalContents, only = null, configOverrides = {}) {
|
|
38
|
+
/** @type {import('./config.mjs').PrettifyBruConfig} */
|
|
39
|
+
const config = {
|
|
40
|
+
...defaultConfig,
|
|
41
|
+
...configOverrides,
|
|
42
|
+
prettier: Object.assign(
|
|
43
|
+
{},
|
|
44
|
+
defaultPrettierConfig,
|
|
45
|
+
Object.hasOwn(configOverrides, 'prettier') ? configOverrides.prettier : {}
|
|
46
|
+
),
|
|
47
|
+
}
|
|
48
|
+
|
|
36
49
|
let fileOutcome = {
|
|
37
50
|
newContents: originalContents.replace(/\r\n/g, '\n'),
|
|
38
51
|
blocksSearchedFor: 0,
|
|
@@ -40,18 +53,10 @@ export async function format(originalContents, only = null, config = {}) {
|
|
|
40
53
|
errorMessages: [],
|
|
41
54
|
}
|
|
42
55
|
|
|
43
|
-
const
|
|
44
|
-
{},
|
|
45
|
-
defaultPrettierConfig,
|
|
46
|
-
Object.hasOwn(config, 'prettier') ? config.prettier : {}
|
|
47
|
-
)
|
|
48
|
-
|
|
49
|
-
let i
|
|
50
|
-
for (i in formattableBlocks) {
|
|
51
|
-
let blockName = formattableBlocks[i]
|
|
56
|
+
for (const blockName of formattableBlocks) {
|
|
52
57
|
if (only !== null && !blockName.includes(only)) continue
|
|
53
58
|
|
|
54
|
-
const blockOutcome = await formatBlock(fileOutcome.newContents, blockName,
|
|
59
|
+
const blockOutcome = await formatBlock(fileOutcome.newContents, blockName, config)
|
|
55
60
|
fileOutcome.blocksSearchedFor++
|
|
56
61
|
if (blockOutcome.errorMessage !== null) {
|
|
57
62
|
fileOutcome.errorMessages.push(blockOutcome.errorMessage)
|
|
@@ -70,7 +75,7 @@ export async function format(originalContents, only = null, config = {}) {
|
|
|
70
75
|
}
|
|
71
76
|
})
|
|
72
77
|
|
|
73
|
-
if (only === null) {
|
|
78
|
+
if (only === null && config.agnosticFilePaths) {
|
|
74
79
|
const fileBodyBlockOutcome = formatFilePaths(fileOutcome.newContents)
|
|
75
80
|
if (fileBodyBlockOutcome.errorMessage !== null) {
|
|
76
81
|
fileOutcome.errorMessages.push(fileBodyBlockOutcome.errorMessage)
|
|
@@ -92,10 +97,10 @@ export async function format(originalContents, only = null, config = {}) {
|
|
|
92
97
|
/**
|
|
93
98
|
* @param {string} fileContents
|
|
94
99
|
* @param {string} blockName
|
|
95
|
-
* @param {
|
|
100
|
+
* @param {import('./config.mjs').PrettifyBruConfig} config
|
|
96
101
|
* @returns {Promise<{fileContents: string, changeable: boolean, errorMessage: ?string}>}
|
|
97
102
|
*/
|
|
98
|
-
async function formatBlock(fileContents, blockName,
|
|
103
|
+
async function formatBlock(fileContents, blockName, config) {
|
|
99
104
|
let outcome = {fileContents, changeable: false, errorMessage: null}
|
|
100
105
|
|
|
101
106
|
const blockBodyRegex = new RegExp('\n' + blockName + ' [{]\\n(.+?)\\n}\\n', 's')
|
|
@@ -108,16 +113,20 @@ async function formatBlock(fileContents, blockName, prettierConfig) {
|
|
|
108
113
|
// Remove 2-spaces of indentation, added due to being inside a Bru lang block
|
|
109
114
|
let unindented = rawBody.replace(/^ /gm, '')
|
|
110
115
|
|
|
116
|
+
if (config.shortenGetters && ['script:post-response', 'tests'].includes(blockName)) {
|
|
117
|
+
unindented = shortenGetters(unindented)
|
|
118
|
+
}
|
|
119
|
+
|
|
111
120
|
let reformatted
|
|
112
121
|
|
|
113
122
|
if (blockName === 'body:json') {
|
|
114
123
|
unindented = wrapNonStringPlaceholdersInDelimiters(unindented)
|
|
115
|
-
const
|
|
116
|
-
reformatted =
|
|
124
|
+
const edits = jsoncFormat(unindented, undefined, {tabSize: 2, insertSpaces: true})
|
|
125
|
+
reformatted = applyEdits(unindented, edits)
|
|
117
126
|
reformatted = unwrapDelimitedPlaceholders(reformatted)
|
|
118
127
|
} else {
|
|
119
128
|
try {
|
|
120
|
-
reformatted = await prettier.format(unindented,
|
|
129
|
+
reformatted = await prettier.format(unindented, config.prettier)
|
|
121
130
|
} catch (e) {
|
|
122
131
|
outcome.errorMessage = `Prettier could not format ${blockName} because...\n${e.message}`
|
|
123
132
|
return outcome
|
|
@@ -145,6 +154,20 @@ async function formatBlock(fileContents, blockName, prettierConfig) {
|
|
|
145
154
|
return outcome
|
|
146
155
|
}
|
|
147
156
|
|
|
157
|
+
/**
|
|
158
|
+
* @param {string} blockContents
|
|
159
|
+
* @returns {string}
|
|
160
|
+
*/
|
|
161
|
+
function shortenGetters(blockContents) {
|
|
162
|
+
const props = ['body', 'headers', 'responseTime', 'status', 'statusText', 'url']
|
|
163
|
+
props.forEach(prop => {
|
|
164
|
+
const getter = 'get' + prop.substring(0, 1).toUpperCase() + prop.substring(1)
|
|
165
|
+
const getterRegex = new RegExp('(?<!\\w)res\.' + getter + '\\(\\)', 'g')
|
|
166
|
+
blockContents = blockContents.replaceAll(getterRegex, `res.${prop}`)
|
|
167
|
+
})
|
|
168
|
+
return blockContents
|
|
169
|
+
}
|
|
170
|
+
|
|
148
171
|
/**
|
|
149
172
|
* Turns Bruno variable placeholders into strings with special delimiters, effectively making it valid JSON
|
|
150
173
|
*
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "prettify-bru",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.8.0",
|
|
4
4
|
"description": "Prettifies JSON and JavaScript blocks in Bruno .bru files",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"bruno",
|
|
@@ -28,7 +28,7 @@
|
|
|
28
28
|
],
|
|
29
29
|
"bin": "./cli.js",
|
|
30
30
|
"dependencies": {
|
|
31
|
-
"
|
|
31
|
+
"jsonc-parser": "^3.3.1",
|
|
32
32
|
"prettier": "^3.3.3",
|
|
33
33
|
"yargs": "18.0.0"
|
|
34
34
|
},
|