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 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 [fast-json-format](https://github.com/usebruno/fast-json-format)
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
- You can override any of the [Prettier options](https://prettier.io/docs/options) via the `prettier` property in your `.prettifybrurc` file.
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 = ['prettier']
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 (supportedProperties.includes(key)) {
50
- if (key === 'prettier') {
51
- const value = fileConfig[key]
52
- if (value === null || typeof value !== 'object' || Array.isArray(value)) {
53
- console.warn(
54
- `⚠️ \x1b[33mprettier is not correct type, it should be an object\x1b[0m`
55
- )
56
- return
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[33m${key} is not a supported property\x1b[0m`)
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 fastJsonFormat from 'fast-json-format'
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 overall structure of bru lang file and uses Prettier to format blocks of JSON/JavaScript
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} config
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, config = {}) {
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 prettierConfig = Object.assign(
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, prettierConfig)
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 {Object} prettierConfig
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, prettierConfig) {
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 indent = ' '.repeat(prettierConfig.tabWidth)
116
- reformatted = fastJsonFormat(unindented, indent)
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, prettierConfig)
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.7.0",
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
- "fast-json-format": "^0.4.0",
31
+ "jsonc-parser": "^3.3.1",
32
32
  "prettier": "^3.3.3",
33
33
  "yargs": "18.0.0"
34
34
  },