@node-cli/bundlesize 2.1.4 → 3.0.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 +118 -36
- package/dist/bundlesize.js +58 -25
- package/dist/bundlesize.js.map +1 -1
- package/dist/defaults.d.ts +1 -0
- package/dist/defaults.js +2 -1
- package/dist/defaults.js.map +1 -1
- package/dist/getRawStats.d.ts +12 -0
- package/dist/getRawStats.js +96 -0
- package/dist/getRawStats.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/parse.d.ts +1 -0
- package/dist/parse.js +6 -0
- package/dist/parse.js.map +1 -1
- package/dist/reportStats.d.ts +10 -0
- package/dist/reportStats.js +108 -0
- package/dist/reportStats.js.map +1 -0
- package/dist/utilities.d.ts +16 -12
- package/dist/utilities.js +75 -74
- package/dist/utilities.js.map +1 -1
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -12,56 +12,74 @@
|
|
|
12
12
|
|
|
13
13
|
## Configuration
|
|
14
14
|
|
|
15
|
-
A configuration file must be provided via the `-c` parameter
|
|
15
|
+
A configuration file must be provided via the `-c` parameter.
|
|
16
|
+
|
|
17
|
+
For the size option, it must export an object named "size" which is an array of objects with the following properties:
|
|
16
18
|
|
|
17
19
|
- `path`: the path to the file to check
|
|
18
20
|
- `limit`: the limit to check against
|
|
19
21
|
|
|
20
|
-
|
|
22
|
+
For the report option, it must export an object named "report" which is an object with the following properties:
|
|
23
|
+
|
|
24
|
+
- `header`: the header to display (optional, string)
|
|
25
|
+
- `footer`: the footer to display (optional, function receiving a boolean indicating if the limit has been reached, and a value corresponding to the diff. It must return a string)
|
|
26
|
+
- `previous`: the previous path to the report to compare against (required, string)
|
|
27
|
+
- `current`: the current path to the report to compare against (required, string)
|
|
28
|
+
- `columns`: the columns to display (optional, array of objects)
|
|
29
|
+
|
|
30
|
+
## Examples
|
|
31
|
+
|
|
32
|
+
### Getting stats from files
|
|
21
33
|
|
|
22
34
|
#### Single file
|
|
23
35
|
|
|
24
36
|
```js
|
|
25
|
-
export default
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
37
|
+
export default {
|
|
38
|
+
sizes: [
|
|
39
|
+
{
|
|
40
|
+
path: "dist/some-bundle.js",
|
|
41
|
+
limit: "10 kB",
|
|
42
|
+
},
|
|
43
|
+
],
|
|
44
|
+
};
|
|
31
45
|
```
|
|
32
46
|
|
|
33
47
|
#### Multiple files
|
|
34
48
|
|
|
35
49
|
```js
|
|
36
|
-
export default
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
50
|
+
export default {
|
|
51
|
+
sizes: [
|
|
52
|
+
{
|
|
53
|
+
path: "dist/some-bundle.js",
|
|
54
|
+
limit: "10 kB",
|
|
55
|
+
},
|
|
56
|
+
{
|
|
57
|
+
path: "dist/some-other-bundle.js",
|
|
58
|
+
limit: "100 kB",
|
|
59
|
+
},
|
|
60
|
+
],
|
|
61
|
+
};
|
|
46
62
|
```
|
|
47
63
|
|
|
48
64
|
#### With glob patterns
|
|
49
65
|
|
|
50
66
|
```js
|
|
51
|
-
export default
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
67
|
+
export default {
|
|
68
|
+
sizes: [
|
|
69
|
+
{
|
|
70
|
+
path: "dist/**/some-bundle.js",
|
|
71
|
+
limit: "10 kB",
|
|
72
|
+
},
|
|
73
|
+
{
|
|
74
|
+
path: "dist/**/some-other-bundle-*.js",
|
|
75
|
+
limit: "100 kB",
|
|
76
|
+
},
|
|
77
|
+
{
|
|
78
|
+
path: "dist/**/extra-+([a-zA-Z0-9]).js",
|
|
79
|
+
limit: "100 kB",
|
|
80
|
+
},
|
|
81
|
+
],
|
|
82
|
+
};
|
|
65
83
|
```
|
|
66
84
|
|
|
67
85
|
#### With a hash
|
|
@@ -76,9 +94,65 @@ The special keyword `<hash>` can be used to match a hash in the filename. It can
|
|
|
76
94
|
| Not OK | `dist/**/some-bundle-<hash>.js` | If multiple files match the pattern |
|
|
77
95
|
| Not OK | `dist/**/some-bundle-<hash>.*` | Cannot use `<hash>` with `*` |
|
|
78
96
|
|
|
97
|
+
### Printing reports from stats
|
|
98
|
+
|
|
99
|
+
#### Simple report
|
|
100
|
+
|
|
101
|
+
```js
|
|
102
|
+
export default {
|
|
103
|
+
report: {
|
|
104
|
+
prev: "stats/previous.json",
|
|
105
|
+
current: "stats/current.json",
|
|
106
|
+
},
|
|
107
|
+
};
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
#### Simple report with custom header
|
|
111
|
+
|
|
112
|
+
```js
|
|
113
|
+
export default {
|
|
114
|
+
report: {
|
|
115
|
+
header: "## My custom header",
|
|
116
|
+
prev: "stats/previous.json",
|
|
117
|
+
current: "stats/current.json",
|
|
118
|
+
},
|
|
119
|
+
};
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
#### Simple report with custom footer
|
|
123
|
+
|
|
124
|
+
```js
|
|
125
|
+
export default {
|
|
126
|
+
report: {
|
|
127
|
+
footer: (limitReached, diff) => {
|
|
128
|
+
return `## My custom footer: ${limitReached} ${diff}`;
|
|
129
|
+
},
|
|
130
|
+
prev: "stats/previous.json",
|
|
131
|
+
current: "stats/current.json",
|
|
132
|
+
},
|
|
133
|
+
};
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
#### Simple report with custom columns
|
|
137
|
+
|
|
138
|
+
```js
|
|
139
|
+
export default {
|
|
140
|
+
report: {
|
|
141
|
+
columns: [
|
|
142
|
+
{ status: "Status" },
|
|
143
|
+
{ file: "File" },
|
|
144
|
+
{ size: "Size" },
|
|
145
|
+
{ limits: "Limits" },
|
|
146
|
+
],
|
|
147
|
+
prev: "stats/previous.json",
|
|
148
|
+
current: "stats/current.json",
|
|
149
|
+
},
|
|
150
|
+
};
|
|
151
|
+
```
|
|
152
|
+
|
|
79
153
|
## Usage
|
|
80
154
|
|
|
81
|
-
### Print the
|
|
155
|
+
### Print the stats at the command line
|
|
82
156
|
|
|
83
157
|
```json
|
|
84
158
|
"scripts": {
|
|
@@ -86,7 +160,7 @@ The special keyword `<hash>` can be used to match a hash in the filename. It can
|
|
|
86
160
|
}
|
|
87
161
|
```
|
|
88
162
|
|
|
89
|
-
### Print the
|
|
163
|
+
### Print the stats in a file
|
|
90
164
|
|
|
91
165
|
```json
|
|
92
166
|
"scripts": {
|
|
@@ -94,7 +168,7 @@ The special keyword `<hash>` can be used to match a hash in the filename. It can
|
|
|
94
168
|
}
|
|
95
169
|
```
|
|
96
170
|
|
|
97
|
-
### Print the
|
|
171
|
+
### Print the stats in a file but do not fail if the limit is reached
|
|
98
172
|
|
|
99
173
|
```json
|
|
100
174
|
"scripts": {
|
|
@@ -102,7 +176,7 @@ The special keyword `<hash>` can be used to match a hash in the filename. It can
|
|
|
102
176
|
}
|
|
103
177
|
```
|
|
104
178
|
|
|
105
|
-
### Add a prefix to the
|
|
179
|
+
### Add a prefix to the stats
|
|
106
180
|
|
|
107
181
|
```json
|
|
108
182
|
"scripts": {
|
|
@@ -118,6 +192,14 @@ The special keyword `<hash>` can be used to match a hash in the filename. It can
|
|
|
118
192
|
}
|
|
119
193
|
```
|
|
120
194
|
|
|
195
|
+
### Compare current stats with the previous ones
|
|
196
|
+
|
|
197
|
+
```json
|
|
198
|
+
"scripts": {
|
|
199
|
+
"stats": "bundlesize -c bundlesize.config.js --type report"
|
|
200
|
+
}
|
|
201
|
+
```
|
|
202
|
+
|
|
121
203
|
## Get help
|
|
122
204
|
|
|
123
205
|
```sh
|
package/dist/bundlesize.js
CHANGED
|
@@ -1,39 +1,72 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
/* istanbul ignore file */ import {
|
|
3
|
-
import {
|
|
2
|
+
/* istanbul ignore file */ import { Logger } from "@node-cli/logger";
|
|
3
|
+
import { STDOUT } from "./utilities.js";
|
|
4
4
|
import { config } from "./parse.js";
|
|
5
5
|
import fs from "fs-extra";
|
|
6
|
+
import { getRawStats } from "./getRawStats.js";
|
|
7
|
+
import { reportStats } from "./reportStats.js";
|
|
6
8
|
const flags = config.flags;
|
|
7
9
|
const log = new Logger({
|
|
8
10
|
boring: flags.boring
|
|
9
11
|
});
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
12
|
+
if (flags.type === "size") {
|
|
13
|
+
try {
|
|
14
|
+
const result = await getRawStats({
|
|
15
|
+
flags
|
|
16
|
+
});
|
|
17
|
+
if (result.exitMessage !== "") {
|
|
18
|
+
log.error(result.exitMessage);
|
|
19
|
+
process.exit(result.exitCode);
|
|
20
|
+
}
|
|
21
|
+
if (result.outputFile === STDOUT) {
|
|
22
|
+
log.info(`Configuration: ${flags.configuration}`);
|
|
23
|
+
log.info(`Output: ${result.outputFile}`);
|
|
24
|
+
log.info(`Output prefix: ${result.prefix}`);
|
|
25
|
+
log.log(result.data);
|
|
26
|
+
} else {
|
|
27
|
+
try {
|
|
28
|
+
fs.outputJsonSync(result.outputFile, result.data, {
|
|
29
|
+
spaces: 2
|
|
30
|
+
});
|
|
31
|
+
} catch (error) {
|
|
32
|
+
log.error(`Failed to write to file: ${error.message}`);
|
|
33
|
+
process.exit(1);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
16
36
|
process.exit(result.exitCode);
|
|
37
|
+
} catch (error) {
|
|
38
|
+
log.error(error);
|
|
39
|
+
process.exit(1);
|
|
17
40
|
}
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
});
|
|
28
|
-
} catch (error) {
|
|
29
|
-
log.error(`Failed to write to file: ${error.message}`);
|
|
30
|
-
process.exit(1);
|
|
41
|
+
}
|
|
42
|
+
if (flags.type === "report") {
|
|
43
|
+
try {
|
|
44
|
+
const result = await reportStats({
|
|
45
|
+
flags
|
|
46
|
+
});
|
|
47
|
+
if (result.exitMessage !== "") {
|
|
48
|
+
log.error(result.exitMessage);
|
|
49
|
+
process.exit(result.exitCode);
|
|
31
50
|
}
|
|
51
|
+
if (result.outputFile === STDOUT) {
|
|
52
|
+
log.info(`Configuration: ${flags.configuration}`);
|
|
53
|
+
log.info(`Output: ${result.outputFile}`);
|
|
54
|
+
log.log(result.data);
|
|
55
|
+
} else {
|
|
56
|
+
try {
|
|
57
|
+
fs.outputFileSync(result.outputFile, result.data);
|
|
58
|
+
} catch (error) {
|
|
59
|
+
log.error(`Failed to write to file: ${error.message}`);
|
|
60
|
+
process.exit(1);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
process.exit(result.exitCode);
|
|
64
|
+
} catch (error) {
|
|
65
|
+
log.error(error);
|
|
66
|
+
process.exit(1);
|
|
32
67
|
}
|
|
33
|
-
process.exit(result.exitCode);
|
|
34
|
-
} catch (error) {
|
|
35
|
-
log.error(error);
|
|
36
|
-
process.exit(1);
|
|
37
68
|
}
|
|
69
|
+
log.error("Invalid type, please use 'size' or 'report'");
|
|
70
|
+
process.exit(1);
|
|
38
71
|
|
|
39
72
|
//# sourceMappingURL=bundlesize.js.map
|
package/dist/bundlesize.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/bundlesize.ts"],"sourcesContent":["#!/usr/bin/env node\n/* istanbul ignore file */\n\nimport {
|
|
1
|
+
{"version":3,"sources":["../src/bundlesize.ts"],"sourcesContent":["#!/usr/bin/env node\n/* istanbul ignore file */\n\nimport { Logger } from \"@node-cli/logger\";\nimport { STDOUT } from \"./utilities.js\";\nimport { config } from \"./parse.js\";\nimport fs from \"fs-extra\";\nimport { getRawStats } from \"./getRawStats.js\";\nimport { reportStats } from \"./reportStats.js\";\n\nconst flags = config.flags;\n\nconst log = new Logger({\n\tboring: flags.boring,\n});\n\nif (flags.type === \"size\") {\n\ttry {\n\t\tconst result = await getRawStats({ flags });\n\n\t\tif (result.exitMessage !== \"\") {\n\t\t\tlog.error(result.exitMessage);\n\t\t\tprocess.exit(result.exitCode);\n\t\t}\n\n\t\tif (result.outputFile === STDOUT) {\n\t\t\tlog.info(`Configuration: ${flags.configuration}`);\n\t\t\tlog.info(`Output: ${result.outputFile}`);\n\t\t\tlog.info(`Output prefix: ${result.prefix}`);\n\t\t\tlog.log(result.data);\n\t\t} else {\n\t\t\ttry {\n\t\t\t\tfs.outputJsonSync(result.outputFile, result.data, { spaces: 2 });\n\t\t\t} catch (error) {\n\t\t\t\tlog.error(`Failed to write to file: ${error.message}`);\n\t\t\t\tprocess.exit(1);\n\t\t\t}\n\t\t}\n\t\tprocess.exit(result.exitCode);\n\t} catch (error) {\n\t\tlog.error(error);\n\t\tprocess.exit(1);\n\t}\n}\n\nif (flags.type === \"report\") {\n\ttry {\n\t\tconst result = await reportStats({ flags });\n\n\t\tif (result.exitMessage !== \"\") {\n\t\t\tlog.error(result.exitMessage);\n\t\t\tprocess.exit(result.exitCode);\n\t\t}\n\n\t\tif (result.outputFile === STDOUT) {\n\t\t\tlog.info(`Configuration: ${flags.configuration}`);\n\t\t\tlog.info(`Output: ${result.outputFile}`);\n\t\t\tlog.log(result.data);\n\t\t} else {\n\t\t\ttry {\n\t\t\t\tfs.outputFileSync(result.outputFile, result.data);\n\t\t\t} catch (error) {\n\t\t\t\tlog.error(`Failed to write to file: ${error.message}`);\n\t\t\t\tprocess.exit(1);\n\t\t\t}\n\t\t}\n\t\tprocess.exit(result.exitCode);\n\t} catch (error) {\n\t\tlog.error(error);\n\t\tprocess.exit(1);\n\t}\n}\n\nlog.error(\"Invalid type, please use 'size' or 'report'\");\nprocess.exit(1);\n"],"names":["Logger","STDOUT","config","fs","getRawStats","reportStats","flags","log","boring","type","result","exitMessage","error","process","exit","exitCode","outputFile","info","configuration","prefix","data","outputJsonSync","spaces","message","outputFileSync"],"mappings":";AACA,wBAAwB,GAExB,SAASA,MAAM,QAAQ,mBAAmB;AAC1C,SAASC,MAAM,QAAQ,iBAAiB;AACxC,SAASC,MAAM,QAAQ,aAAa;AACpC,OAAOC,QAAQ,WAAW;AAC1B,SAASC,WAAW,QAAQ,mBAAmB;AAC/C,SAASC,WAAW,QAAQ,mBAAmB;AAE/C,MAAMC,QAAQJ,OAAOI,KAAK;AAE1B,MAAMC,MAAM,IAAIP,OAAO;IACtBQ,QAAQF,MAAME,MAAM;AACrB;AAEA,IAAIF,MAAMG,IAAI,KAAK,QAAQ;IAC1B,IAAI;QACH,MAAMC,SAAS,MAAMN,YAAY;YAAEE;QAAM;QAEzC,IAAII,OAAOC,WAAW,KAAK,IAAI;YAC9BJ,IAAIK,KAAK,CAACF,OAAOC,WAAW;YAC5BE,QAAQC,IAAI,CAACJ,OAAOK,QAAQ;QAC7B;QAEA,IAAIL,OAAOM,UAAU,KAAKf,QAAQ;YACjCM,IAAIU,IAAI,CAAC,CAAC,eAAe,EAAEX,MAAMY,aAAa,CAAC,CAAC;YAChDX,IAAIU,IAAI,CAAC,CAAC,QAAQ,EAAEP,OAAOM,UAAU,CAAC,CAAC;YACvCT,IAAIU,IAAI,CAAC,CAAC,eAAe,EAAEP,OAAOS,MAAM,CAAC,CAAC;YAC1CZ,IAAIA,GAAG,CAACG,OAAOU,IAAI;QACpB,OAAO;YACN,IAAI;gBACHjB,GAAGkB,cAAc,CAACX,OAAOM,UAAU,EAAEN,OAAOU,IAAI,EAAE;oBAAEE,QAAQ;gBAAE;YAC/D,EAAE,OAAOV,OAAO;gBACfL,IAAIK,KAAK,CAAC,CAAC,yBAAyB,EAAEA,MAAMW,OAAO,CAAC,CAAC;gBACrDV,QAAQC,IAAI,CAAC;YACd;QACD;QACAD,QAAQC,IAAI,CAACJ,OAAOK,QAAQ;IAC7B,EAAE,OAAOH,OAAO;QACfL,IAAIK,KAAK,CAACA;QACVC,QAAQC,IAAI,CAAC;IACd;AACD;AAEA,IAAIR,MAAMG,IAAI,KAAK,UAAU;IAC5B,IAAI;QACH,MAAMC,SAAS,MAAML,YAAY;YAAEC;QAAM;QAEzC,IAAII,OAAOC,WAAW,KAAK,IAAI;YAC9BJ,IAAIK,KAAK,CAACF,OAAOC,WAAW;YAC5BE,QAAQC,IAAI,CAACJ,OAAOK,QAAQ;QAC7B;QAEA,IAAIL,OAAOM,UAAU,KAAKf,QAAQ;YACjCM,IAAIU,IAAI,CAAC,CAAC,eAAe,EAAEX,MAAMY,aAAa,CAAC,CAAC;YAChDX,IAAIU,IAAI,CAAC,CAAC,QAAQ,EAAEP,OAAOM,UAAU,CAAC,CAAC;YACvCT,IAAIA,GAAG,CAACG,OAAOU,IAAI;QACpB,OAAO;YACN,IAAI;gBACHjB,GAAGqB,cAAc,CAACd,OAAOM,UAAU,EAAEN,OAAOU,IAAI;YACjD,EAAE,OAAOR,OAAO;gBACfL,IAAIK,KAAK,CAAC,CAAC,yBAAyB,EAAEA,MAAMW,OAAO,CAAC,CAAC;gBACrDV,QAAQC,IAAI,CAAC;YACd;QACD;QACAD,QAAQC,IAAI,CAACJ,OAAOK,QAAQ;IAC7B,EAAE,OAAOH,OAAO;QACfL,IAAIK,KAAK,CAACA;QACVC,QAAQC,IAAI,CAAC;IACd;AACD;AAEAP,IAAIK,KAAK,CAAC;AACVC,QAAQC,IAAI,CAAC"}
|
package/dist/defaults.d.ts
CHANGED
package/dist/defaults.js
CHANGED
package/dist/defaults.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/defaults.ts"],"sourcesContent":["/* istanbul ignore file */\n\nexport const defaultFlags = {\n\tboring: false,\n\tconfiguration: \"\",\n\tsilent: false,\n};\n"],"names":["defaultFlags","boring","configuration","silent"],"mappings":"AAAA,wBAAwB,GAExB,OAAO,MAAMA,eAAe;IAC3BC,QAAQ;IACRC,eAAe;IACfC,QAAQ;
|
|
1
|
+
{"version":3,"sources":["../src/defaults.ts"],"sourcesContent":["/* istanbul ignore file */\n\nexport const defaultFlags = {\n\tboring: false,\n\tconfiguration: \"\",\n\tsilent: false,\n\ttype: \"size\",\n};\n"],"names":["defaultFlags","boring","configuration","silent","type"],"mappings":"AAAA,wBAAwB,GAExB,OAAO,MAAMA,eAAe;IAC3BC,QAAQ;IACRC,eAAe;IACfC,QAAQ;IACRC,MAAM;AACP,EAAE"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
type ReportStats = {
|
|
2
|
+
data: Record<string, unknown>;
|
|
3
|
+
exitCode: number;
|
|
4
|
+
exitMessage: string;
|
|
5
|
+
outputFile: string;
|
|
6
|
+
pass: boolean;
|
|
7
|
+
prefix: string;
|
|
8
|
+
};
|
|
9
|
+
export declare const getRawStats: ({ flags }: {
|
|
10
|
+
flags: any;
|
|
11
|
+
}) => Promise<ReportStats>;
|
|
12
|
+
export {};
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import { STDOUT, getOutputFile, gzipSizeFromFileSync, validateConfigurationFile } from "./utilities.js";
|
|
2
|
+
import { basename, dirname, join } from "node:path";
|
|
3
|
+
import bytes from "bytes";
|
|
4
|
+
import fs from "fs-extra";
|
|
5
|
+
import { glob } from "glob";
|
|
6
|
+
import { statSync } from "node:fs";
|
|
7
|
+
export const getRawStats = async ({ flags })=>{
|
|
8
|
+
const result = {
|
|
9
|
+
pass: true,
|
|
10
|
+
exitCode: 0,
|
|
11
|
+
exitMessage: "",
|
|
12
|
+
outputFile: "",
|
|
13
|
+
prefix: "",
|
|
14
|
+
data: {}
|
|
15
|
+
};
|
|
16
|
+
let failed = false;
|
|
17
|
+
const isValidConfigResult = validateConfigurationFile(flags.configuration);
|
|
18
|
+
if (isValidConfigResult.exitMessage !== "") {
|
|
19
|
+
return {
|
|
20
|
+
...result,
|
|
21
|
+
...isValidConfigResult
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
const configurationFile = isValidConfigResult.data;
|
|
25
|
+
const outputFile = getOutputFile(flags.output);
|
|
26
|
+
const prefix = flags.prefix || "0.0.0";
|
|
27
|
+
const currentResults = {};
|
|
28
|
+
const configuration = await import(configurationFile).then((m)=>m.default);
|
|
29
|
+
if (configuration.sizes === undefined) {
|
|
30
|
+
result.exitMessage = "Invalid configuration file: missing sizes object!";
|
|
31
|
+
result.exitCode = 1;
|
|
32
|
+
return result;
|
|
33
|
+
}
|
|
34
|
+
for (const artifact of configuration.sizes){
|
|
35
|
+
const rootPath = artifact.path.startsWith("/") ? "" : dirname(configurationFile);
|
|
36
|
+
const artifactPath = dirname(artifact.path);
|
|
37
|
+
const globReplace = "+([a-zA-Z0-9_-])";
|
|
38
|
+
const hasHash = artifact.path.includes("<hash>");
|
|
39
|
+
/**
|
|
40
|
+
* if the artifact.path has the string <hash> in it,
|
|
41
|
+
* then we need to check for other characters:
|
|
42
|
+
* - Double stars ** are allowed.
|
|
43
|
+
* - Single stars * are not allowed.
|
|
44
|
+
*/ if (hasHash && /(?<!\*)\*(?!\*)/.test(artifact.path)) {
|
|
45
|
+
result.exitCode = 1;
|
|
46
|
+
result.exitMessage = `Invalid path: ${artifact.path}.\nSingle stars (*) are not allowed when using the special keyword <hash>`;
|
|
47
|
+
return result;
|
|
48
|
+
}
|
|
49
|
+
const fileGlob = join(rootPath, artifact.path.replace("<hash>", globReplace));
|
|
50
|
+
const files = glob.sync(fileGlob);
|
|
51
|
+
if (files.length === 0) {
|
|
52
|
+
result.exitCode = 1;
|
|
53
|
+
result.exitMessage = `File not found: ${fileGlob}`;
|
|
54
|
+
return result;
|
|
55
|
+
}
|
|
56
|
+
if (files.length > 1 && hasHash) {
|
|
57
|
+
result.exitCode = 1;
|
|
58
|
+
result.exitMessage = `Multiple files found for: ${artifact.path}.\nPlease use a more specific path when using the special keyword <hash>.`;
|
|
59
|
+
return result;
|
|
60
|
+
}
|
|
61
|
+
for (const file of files){
|
|
62
|
+
const fileSize = statSync(file).size;
|
|
63
|
+
const fileSizeGzip = gzipSizeFromFileSync(file);
|
|
64
|
+
const passed = fileSizeGzip < bytes(artifact.limit);
|
|
65
|
+
if (passed === false) {
|
|
66
|
+
result.pass = false;
|
|
67
|
+
failed = true;
|
|
68
|
+
}
|
|
69
|
+
let index = hasHash ? artifact.path : join(artifactPath, basename(file));
|
|
70
|
+
currentResults[index] = {
|
|
71
|
+
fileSize,
|
|
72
|
+
fileSizeGzip,
|
|
73
|
+
limit: artifact.limit,
|
|
74
|
+
passed
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
let existingResults = {};
|
|
79
|
+
if (outputFile !== STDOUT) {
|
|
80
|
+
try {
|
|
81
|
+
existingResults = fs.readJsonSync(outputFile);
|
|
82
|
+
} catch {
|
|
83
|
+
/**
|
|
84
|
+
* There are no existing results, so we can ignore this error,
|
|
85
|
+
* and simply write the current results to the output file.
|
|
86
|
+
*/ }
|
|
87
|
+
}
|
|
88
|
+
existingResults[prefix] = currentResults;
|
|
89
|
+
result.prefix = prefix;
|
|
90
|
+
result.outputFile = outputFile;
|
|
91
|
+
result.exitCode = failed && flags.silent === false ? 1 : 0;
|
|
92
|
+
result.data = existingResults;
|
|
93
|
+
return result;
|
|
94
|
+
};
|
|
95
|
+
|
|
96
|
+
//# sourceMappingURL=getRawStats.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/getRawStats.ts"],"sourcesContent":["import {\n\tSTDOUT,\n\tgetOutputFile,\n\tgzipSizeFromFileSync,\n\tvalidateConfigurationFile,\n} from \"./utilities.js\";\nimport { basename, dirname, join } from \"node:path\";\n\nimport bytes from \"bytes\";\nimport fs from \"fs-extra\";\nimport { glob } from \"glob\";\nimport { statSync } from \"node:fs\";\n\ntype SizesConfiguration = {\n\tlimit: string;\n\tpath: string;\n};\n\ntype ReportStats = {\n\tdata: Record<string, unknown>;\n\texitCode: number;\n\texitMessage: string;\n\toutputFile: string;\n\tpass: boolean;\n\tprefix: string;\n};\n\nexport const getRawStats = async ({ flags }): Promise<ReportStats> => {\n\tconst result: ReportStats = {\n\t\tpass: true,\n\t\texitCode: 0,\n\t\texitMessage: \"\",\n\t\toutputFile: \"\",\n\t\tprefix: \"\",\n\t\tdata: {},\n\t};\n\tlet failed = false;\n\tconst isValidConfigResult = validateConfigurationFile(flags.configuration);\n\tif (isValidConfigResult.exitMessage !== \"\") {\n\t\treturn {\n\t\t\t...result,\n\t\t\t...isValidConfigResult,\n\t\t};\n\t}\n\tconst configurationFile = isValidConfigResult.data;\n\tconst outputFile = getOutputFile(flags.output);\n\tconst prefix = flags.prefix || \"0.0.0\";\n\tconst currentResults = {};\n\n\tconst configuration: { sizes: SizesConfiguration[] } = await import(\n\t\tconfigurationFile\n\t).then((m) => m.default);\n\n\tif (configuration.sizes === undefined) {\n\t\tresult.exitMessage = \"Invalid configuration file: missing sizes object!\";\n\t\tresult.exitCode = 1;\n\t\treturn result;\n\t}\n\n\tfor (const artifact of configuration.sizes) {\n\t\tconst rootPath = artifact.path.startsWith(\"/\")\n\t\t\t? \"\"\n\t\t\t: dirname(configurationFile);\n\t\tconst artifactPath = dirname(artifact.path);\n\t\tconst globReplace = \"+([a-zA-Z0-9_-])\";\n\t\tconst hasHash = artifact.path.includes(\"<hash>\");\n\n\t\t/**\n\t\t * if the artifact.path has the string <hash> in it,\n\t\t * then we need to check for other characters:\n\t\t * - Double stars ** are allowed.\n\t\t * - Single stars * are not allowed.\n\t\t */\n\t\tif (hasHash && /(?<!\\*)\\*(?!\\*)/.test(artifact.path)) {\n\t\t\tresult.exitCode = 1;\n\t\t\tresult.exitMessage = `Invalid path: ${artifact.path}.\\nSingle stars (*) are not allowed when using the special keyword <hash>`;\n\t\t\treturn result;\n\t\t}\n\n\t\tconst fileGlob = join(\n\t\t\trootPath,\n\t\t\tartifact.path.replace(\"<hash>\", globReplace),\n\t\t);\n\t\tconst files = glob.sync(fileGlob);\n\n\t\tif (files.length === 0) {\n\t\t\tresult.exitCode = 1;\n\t\t\tresult.exitMessage = `File not found: ${fileGlob}`;\n\t\t\treturn result;\n\t\t}\n\n\t\tif (files.length > 1 && hasHash) {\n\t\t\tresult.exitCode = 1;\n\t\t\tresult.exitMessage = `Multiple files found for: ${artifact.path}.\\nPlease use a more specific path when using the special keyword <hash>.`;\n\t\t\treturn result;\n\t\t}\n\n\t\tfor (const file of files) {\n\t\t\tconst fileSize = statSync(file).size;\n\t\t\tconst fileSizeGzip = gzipSizeFromFileSync(file);\n\t\t\tconst passed = fileSizeGzip < bytes(artifact.limit);\n\n\t\t\tif (passed === false) {\n\t\t\t\tresult.pass = false;\n\t\t\t\tfailed = true;\n\t\t\t}\n\t\t\tlet index = hasHash ? artifact.path : join(artifactPath, basename(file));\n\n\t\t\tcurrentResults[index] = {\n\t\t\t\tfileSize,\n\t\t\t\tfileSizeGzip,\n\t\t\t\tlimit: artifact.limit,\n\t\t\t\tpassed,\n\t\t\t};\n\t\t}\n\t}\n\n\tlet existingResults = {};\n\tif (outputFile !== STDOUT) {\n\t\ttry {\n\t\t\texistingResults = fs.readJsonSync(outputFile);\n\t\t} catch {\n\t\t\t/**\n\t\t\t * There are no existing results, so we can ignore this error,\n\t\t\t * and simply write the current results to the output file.\n\t\t\t */\n\t\t}\n\t}\n\texistingResults[prefix] = currentResults;\n\n\tresult.prefix = prefix;\n\tresult.outputFile = outputFile;\n\tresult.exitCode = failed && flags.silent === false ? 1 : 0;\n\tresult.data = existingResults;\n\treturn result;\n};\n"],"names":["STDOUT","getOutputFile","gzipSizeFromFileSync","validateConfigurationFile","basename","dirname","join","bytes","fs","glob","statSync","getRawStats","flags","result","pass","exitCode","exitMessage","outputFile","prefix","data","failed","isValidConfigResult","configuration","configurationFile","output","currentResults","then","m","default","sizes","undefined","artifact","rootPath","path","startsWith","artifactPath","globReplace","hasHash","includes","test","fileGlob","replace","files","sync","length","file","fileSize","size","fileSizeGzip","passed","limit","index","existingResults","readJsonSync","silent"],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
package/dist/parse.d.ts
CHANGED
package/dist/parse.js
CHANGED
|
@@ -4,6 +4,12 @@ import { parser } from "@node-cli/parser";
|
|
|
4
4
|
meta: import.meta,
|
|
5
5
|
examples: [],
|
|
6
6
|
flags: {
|
|
7
|
+
type: {
|
|
8
|
+
shortFlag: "t",
|
|
9
|
+
description: "Specify the type of output: size or report",
|
|
10
|
+
type: "string",
|
|
11
|
+
default: defaultFlags.type
|
|
12
|
+
},
|
|
7
13
|
configuration: {
|
|
8
14
|
shortFlag: "c",
|
|
9
15
|
description: "Specify a configuration file",
|
package/dist/parse.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/parse.ts"],"sourcesContent":["import { defaultFlags } from \"./defaults.js\";\nimport { parser } from \"@node-cli/parser\";\n\nexport type Flags = {\n\tboring?: boolean;\n\thelp?: boolean;\n\tversion?: boolean;\n\tconfiguration?: string;\n\toutput?: string;\n\tprefix?: string;\n\tsilent?: boolean;\n};\n\nexport type Configuration = {\n\tflags?: Flags;\n\tusage?: boolean;\n\tshowHelp?: () => void;\n};\n\n/* istanbul ignore next */\nexport const config: Configuration = parser({\n\tmeta: import.meta,\n\texamples: [],\n\tflags: {\n\t\tconfiguration: {\n\t\t\tshortFlag: \"c\",\n\t\t\tdescription: \"Specify a configuration file\",\n\t\t\ttype: \"string\",\n\t\t},\n\t\toutput: {\n\t\t\tshortFlag: \"o\",\n\t\t\tdescription: \"Specify the output file\",\n\t\t\ttype: \"string\",\n\t\t},\n\t\tprefix: {\n\t\t\tshortFlag: \"p\",\n\t\t\tdescription: \"Specify a prefix to use in the output file\",\n\t\t\ttype: \"string\",\n\t\t},\n\t\tsilent: {\n\t\t\tshortFlag: \"s\",\n\t\t\tdefault: defaultFlags.silent,\n\t\t\tdescription: \"Do not exit in error when a limit is exceeded\",\n\t\t\ttype: \"boolean\",\n\t\t},\n\t\tboring: {\n\t\t\tshortFlag: \"b\",\n\t\t\tdefault: defaultFlags.boring,\n\t\t\tdescription: \"Do not use color output\",\n\t\t\ttype: \"boolean\",\n\t\t},\n\t\thelp: {\n\t\t\tshortFlag: \"h\",\n\t\t\tdescription: \"Display help instructions\",\n\t\t\ttype: \"boolean\",\n\t\t},\n\t\tversion: {\n\t\t\tshortFlag: \"v\",\n\t\t\tdescription: \"Output the current version\",\n\t\t\ttype: \"boolean\",\n\t\t},\n\t},\n\tusage: true,\n\tdefaultFlags,\n});\n"],"names":["defaultFlags","parser","config","meta","examples","flags","
|
|
1
|
+
{"version":3,"sources":["../src/parse.ts"],"sourcesContent":["import { defaultFlags } from \"./defaults.js\";\nimport { parser } from \"@node-cli/parser\";\n\nexport type Flags = {\n\tboring?: boolean;\n\thelp?: boolean;\n\tversion?: boolean;\n\tconfiguration?: string;\n\toutput?: string;\n\tprefix?: string;\n\tsilent?: boolean;\n\ttype?: \"size\" | \"report\";\n};\n\nexport type Configuration = {\n\tflags?: Flags;\n\tusage?: boolean;\n\tshowHelp?: () => void;\n};\n\n/* istanbul ignore next */\nexport const config: Configuration = parser({\n\tmeta: import.meta,\n\texamples: [],\n\tflags: {\n\t\ttype: {\n\t\t\tshortFlag: \"t\",\n\t\t\tdescription: \"Specify the type of output: size or report\",\n\t\t\ttype: \"string\",\n\t\t\tdefault: defaultFlags.type,\n\t\t},\n\t\tconfiguration: {\n\t\t\tshortFlag: \"c\",\n\t\t\tdescription: \"Specify a configuration file\",\n\t\t\ttype: \"string\",\n\t\t},\n\t\toutput: {\n\t\t\tshortFlag: \"o\",\n\t\t\tdescription: \"Specify the output file\",\n\t\t\ttype: \"string\",\n\t\t},\n\t\tprefix: {\n\t\t\tshortFlag: \"p\",\n\t\t\tdescription: \"Specify a prefix to use in the output file\",\n\t\t\ttype: \"string\",\n\t\t},\n\t\tsilent: {\n\t\t\tshortFlag: \"s\",\n\t\t\tdefault: defaultFlags.silent,\n\t\t\tdescription: \"Do not exit in error when a limit is exceeded\",\n\t\t\ttype: \"boolean\",\n\t\t},\n\t\tboring: {\n\t\t\tshortFlag: \"b\",\n\t\t\tdefault: defaultFlags.boring,\n\t\t\tdescription: \"Do not use color output\",\n\t\t\ttype: \"boolean\",\n\t\t},\n\t\thelp: {\n\t\t\tshortFlag: \"h\",\n\t\t\tdescription: \"Display help instructions\",\n\t\t\ttype: \"boolean\",\n\t\t},\n\t\tversion: {\n\t\t\tshortFlag: \"v\",\n\t\t\tdescription: \"Output the current version\",\n\t\t\ttype: \"boolean\",\n\t\t},\n\t},\n\tusage: true,\n\tdefaultFlags,\n});\n"],"names":["defaultFlags","parser","config","meta","examples","flags","type","shortFlag","description","default","configuration","output","prefix","silent","boring","help","version","usage"],"mappings":"AAAA,SAASA,YAAY,QAAQ,gBAAgB;AAC7C,SAASC,MAAM,QAAQ,mBAAmB;AAmB1C,wBAAwB,GACxB,OAAO,MAAMC,SAAwBD,OAAO;IAC3CE,MAAM;IACNC,UAAU,EAAE;IACZC,OAAO;QACNC,MAAM;YACLC,WAAW;YACXC,aAAa;YACbF,MAAM;YACNG,SAAST,aAAaM,IAAI;QAC3B;QACAI,eAAe;YACdH,WAAW;YACXC,aAAa;YACbF,MAAM;QACP;QACAK,QAAQ;YACPJ,WAAW;YACXC,aAAa;YACbF,MAAM;QACP;QACAM,QAAQ;YACPL,WAAW;YACXC,aAAa;YACbF,MAAM;QACP;QACAO,QAAQ;YACPN,WAAW;YACXE,SAAST,aAAaa,MAAM;YAC5BL,aAAa;YACbF,MAAM;QACP;QACAQ,QAAQ;YACPP,WAAW;YACXE,SAAST,aAAac,MAAM;YAC5BN,aAAa;YACbF,MAAM;QACP;QACAS,MAAM;YACLR,WAAW;YACXC,aAAa;YACbF,MAAM;QACP;QACAU,SAAS;YACRT,WAAW;YACXC,aAAa;YACbF,MAAM;QACP;IACD;IACAW,OAAO;IACPjB;AACD,GAAG"}
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
import { addMDrow, formatFooter, getMostRecentVersion, getOutputFile, percentFormatter, readJSONFile, validateConfigurationFile } from "./utilities.js";
|
|
2
|
+
import { basename, dirname, join } from "node:path";
|
|
3
|
+
import bytes from "bytes";
|
|
4
|
+
export const reportStats = async ({ flags })=>{
|
|
5
|
+
const result = {
|
|
6
|
+
exitCode: 0,
|
|
7
|
+
exitMessage: "",
|
|
8
|
+
outputFile: "",
|
|
9
|
+
data: ""
|
|
10
|
+
};
|
|
11
|
+
let previousStats, previousVersion;
|
|
12
|
+
const isValidConfigResult = validateConfigurationFile(flags.configuration);
|
|
13
|
+
if (isValidConfigResult.exitMessage !== "") {
|
|
14
|
+
return {
|
|
15
|
+
...result,
|
|
16
|
+
...isValidConfigResult
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
const configurationFile = isValidConfigResult.data;
|
|
20
|
+
const outputFile = getOutputFile(flags.output);
|
|
21
|
+
result.outputFile = outputFile;
|
|
22
|
+
const configuration = await import(configurationFile).then((m)=>m.default);
|
|
23
|
+
const currentStats = readJSONFile(join(dirname(configurationFile), configuration.report.current));
|
|
24
|
+
if (currentStats.exitMessage !== "") {
|
|
25
|
+
return {
|
|
26
|
+
...result,
|
|
27
|
+
...currentStats
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
try {
|
|
31
|
+
previousStats = readJSONFile(join(dirname(configurationFile), configuration.report.previous));
|
|
32
|
+
if (previousStats.exitMessage !== "") {
|
|
33
|
+
return {
|
|
34
|
+
...result,
|
|
35
|
+
...previousStats
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
previousVersion = getMostRecentVersion(previousStats.data);
|
|
39
|
+
} catch {
|
|
40
|
+
// nothing to declare officer
|
|
41
|
+
}
|
|
42
|
+
const currentVersion = getMostRecentVersion(currentStats.data);
|
|
43
|
+
let limitReached = false;
|
|
44
|
+
let overallDiff = 0;
|
|
45
|
+
const headerString = configuration.report.header || "## Bundle Size";
|
|
46
|
+
const footerFormatter = configuration.report.footer || formatFooter;
|
|
47
|
+
const columns = configuration.report.columns || [
|
|
48
|
+
{
|
|
49
|
+
status: "Status"
|
|
50
|
+
},
|
|
51
|
+
{
|
|
52
|
+
file: "File"
|
|
53
|
+
},
|
|
54
|
+
{
|
|
55
|
+
size: "Size (Gzip)"
|
|
56
|
+
},
|
|
57
|
+
{
|
|
58
|
+
limits: "Limits"
|
|
59
|
+
}
|
|
60
|
+
];
|
|
61
|
+
const rowsMD = [];
|
|
62
|
+
rowsMD.push(addMDrow({
|
|
63
|
+
type: "header",
|
|
64
|
+
columns
|
|
65
|
+
}));
|
|
66
|
+
for (const key of Object.keys(currentStats.data[currentVersion])){
|
|
67
|
+
const item = currentStats.data[currentVersion][key];
|
|
68
|
+
const name = basename(key);
|
|
69
|
+
if (!item.passed) {
|
|
70
|
+
limitReached = true;
|
|
71
|
+
}
|
|
72
|
+
let diffString = "";
|
|
73
|
+
if (previousStats && previousVersion) {
|
|
74
|
+
const previousFileStats = previousStats.data[previousVersion] && previousStats.data[previousVersion][key];
|
|
75
|
+
const previousFileSizeGzip = previousFileStats.fileSizeGzip;
|
|
76
|
+
const diff = item.fileSizeGzip - previousFileSizeGzip;
|
|
77
|
+
overallDiff += diff;
|
|
78
|
+
diffString = diff === 0 ? "" : ` (${diff > 0 ? "+" : "-"}${bytes(Math.abs(diff), {
|
|
79
|
+
unitSeparator: " "
|
|
80
|
+
})} ${percentFormatter.format(diff / previousFileSizeGzip)})`;
|
|
81
|
+
}
|
|
82
|
+
rowsMD.push(addMDrow({
|
|
83
|
+
type: "row",
|
|
84
|
+
passed: item.passed,
|
|
85
|
+
name: name,
|
|
86
|
+
size: item.fileSizeGzip,
|
|
87
|
+
diff: diffString,
|
|
88
|
+
limit: item.limit,
|
|
89
|
+
columns
|
|
90
|
+
}));
|
|
91
|
+
}
|
|
92
|
+
const overallDiffString = overallDiff === 0 ? "" : `(${overallDiff > 0 ? "+" : "-"}${bytes(Math.abs(overallDiff), {
|
|
93
|
+
unitSeparator: " "
|
|
94
|
+
})})`;
|
|
95
|
+
const template = `
|
|
96
|
+
${headerString}
|
|
97
|
+
${rowsMD.join("\n")}
|
|
98
|
+
|
|
99
|
+
${footerFormatter(limitReached, overallDiffString).trim()}
|
|
100
|
+
`;
|
|
101
|
+
if (limitReached) {
|
|
102
|
+
result.exitCode = 1;
|
|
103
|
+
}
|
|
104
|
+
result.data = template;
|
|
105
|
+
return result;
|
|
106
|
+
};
|
|
107
|
+
|
|
108
|
+
//# sourceMappingURL=reportStats.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/reportStats.ts"],"sourcesContent":["import {\n\taddMDrow,\n\tformatFooter,\n\tgetMostRecentVersion,\n\tgetOutputFile,\n\tpercentFormatter,\n\treadJSONFile,\n\tvalidateConfigurationFile,\n} from \"./utilities.js\";\nimport { basename, dirname, join } from \"node:path\";\n\nimport bytes from \"bytes\";\n\ntype ReportConfiguration = {\n\tcurrent: string;\n\tprevious: string;\n\n\theader?: string;\n\tfooter?: (limit: boolean, diff: string | number) => string;\n\tcolumns?: { [key: string]: string }[];\n};\n\ntype ReportCompare = {\n\tdata: string;\n\texitCode: number;\n\texitMessage: string;\n\toutputFile: string;\n};\n\nexport const reportStats = async ({ flags }): Promise<ReportCompare> => {\n\tconst result: ReportCompare = {\n\t\texitCode: 0,\n\t\texitMessage: \"\",\n\t\toutputFile: \"\",\n\t\tdata: \"\",\n\t};\n\tlet previousStats, previousVersion: string;\n\tconst isValidConfigResult = validateConfigurationFile(flags.configuration);\n\tif (isValidConfigResult.exitMessage !== \"\") {\n\t\treturn {\n\t\t\t...result,\n\t\t\t...isValidConfigResult,\n\t\t};\n\t}\n\tconst configurationFile = isValidConfigResult.data;\n\tconst outputFile = getOutputFile(flags.output);\n\tresult.outputFile = outputFile;\n\n\tconst configuration: { report: ReportConfiguration } = await import(\n\t\tconfigurationFile\n\t).then((m) => m.default);\n\n\tconst currentStats = readJSONFile(\n\t\tjoin(dirname(configurationFile), configuration.report.current),\n\t);\n\tif (currentStats.exitMessage !== \"\") {\n\t\treturn {\n\t\t\t...result,\n\t\t\t...currentStats,\n\t\t};\n\t}\n\n\ttry {\n\t\tpreviousStats = readJSONFile(\n\t\t\tjoin(dirname(configurationFile), configuration.report.previous),\n\t\t);\n\t\tif (previousStats.exitMessage !== \"\") {\n\t\t\treturn {\n\t\t\t\t...result,\n\t\t\t\t...previousStats,\n\t\t\t};\n\t\t}\n\t\tpreviousVersion = getMostRecentVersion(previousStats.data);\n\t} catch {\n\t\t// nothing to declare officer\n\t}\n\tconst currentVersion = getMostRecentVersion(currentStats.data);\n\n\tlet limitReached = false;\n\tlet overallDiff = 0;\n\tconst headerString = configuration.report.header || \"## Bundle Size\";\n\tconst footerFormatter = configuration.report.footer || formatFooter;\n\tconst columns = configuration.report.columns || [\n\t\t{ status: \"Status\" },\n\t\t{ file: \"File\" },\n\t\t{ size: \"Size (Gzip)\" },\n\t\t{ limits: \"Limits\" },\n\t];\n\n\tconst rowsMD = [];\n\trowsMD.push(addMDrow({ type: \"header\", columns }));\n\n\tfor (const key of Object.keys(currentStats.data[currentVersion])) {\n\t\tconst item = currentStats.data[currentVersion][key];\n\t\tconst name = basename(key);\n\t\tif (!item.passed) {\n\t\t\tlimitReached = true;\n\t\t}\n\n\t\tlet diffString = \"\";\n\t\tif (previousStats && previousVersion) {\n\t\t\tconst previousFileStats =\n\t\t\t\tpreviousStats.data[previousVersion] &&\n\t\t\t\tpreviousStats.data[previousVersion][key];\n\t\t\tconst previousFileSizeGzip = previousFileStats.fileSizeGzip;\n\t\t\tconst diff = item.fileSizeGzip - previousFileSizeGzip;\n\n\t\t\toverallDiff += diff;\n\t\t\tdiffString =\n\t\t\t\tdiff === 0\n\t\t\t\t\t? \"\"\n\t\t\t\t\t: ` (${diff > 0 ? \"+\" : \"-\"}${bytes(Math.abs(diff), {\n\t\t\t\t\t\t\tunitSeparator: \" \",\n\t\t\t\t\t\t})} ${percentFormatter.format(diff / previousFileSizeGzip)})`;\n\t\t}\n\n\t\trowsMD.push(\n\t\t\taddMDrow({\n\t\t\t\ttype: \"row\",\n\t\t\t\tpassed: item.passed,\n\t\t\t\tname: name,\n\t\t\t\tsize: item.fileSizeGzip,\n\t\t\t\tdiff: diffString,\n\t\t\t\tlimit: item.limit,\n\t\t\t\tcolumns,\n\t\t\t}),\n\t\t);\n\t}\n\n\tconst overallDiffString =\n\t\toverallDiff === 0\n\t\t\t? \"\"\n\t\t\t: `(${overallDiff > 0 ? \"+\" : \"-\"}${bytes(Math.abs(overallDiff), {\n\t\t\t\t\tunitSeparator: \" \",\n\t\t\t\t})})`;\n\n\tconst template = `\n${headerString}\n${rowsMD.join(\"\\n\")}\n\n${footerFormatter(limitReached, overallDiffString).trim()}\n`;\n\n\tif (limitReached) {\n\t\tresult.exitCode = 1;\n\t}\n\n\tresult.data = template;\n\n\treturn result;\n};\n"],"names":["addMDrow","formatFooter","getMostRecentVersion","getOutputFile","percentFormatter","readJSONFile","validateConfigurationFile","basename","dirname","join","bytes","reportStats","flags","result","exitCode","exitMessage","outputFile","data","previousStats","previousVersion","isValidConfigResult","configuration","configurationFile","output","then","m","default","currentStats","report","current","previous","currentVersion","limitReached","overallDiff","headerString","header","footerFormatter","footer","columns","status","file","size","limits","rowsMD","push","type","key","Object","keys","item","name","passed","diffString","previousFileStats","previousFileSizeGzip","fileSizeGzip","diff","Math","abs","unitSeparator","format","limit","overallDiffString","template","trim"],"mappings":"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"}
|
package/dist/utilities.d.ts
CHANGED
|
@@ -1,13 +1,17 @@
|
|
|
1
|
-
type ReportStats = {
|
|
2
|
-
pass: boolean;
|
|
3
|
-
exitCode: number;
|
|
4
|
-
exitMessage: string;
|
|
5
|
-
outputFile: string;
|
|
6
|
-
prefix: string;
|
|
7
|
-
data: Record<string, unknown>;
|
|
8
|
-
};
|
|
9
1
|
export declare const STDOUT = "stdout";
|
|
10
|
-
export declare const
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
export
|
|
2
|
+
export declare const gzipSizeFromFileSync: (file: string) => number;
|
|
3
|
+
export declare const getOutputFile: (file: string) => string;
|
|
4
|
+
export declare const validateConfigurationFile: (file: string) => any;
|
|
5
|
+
export declare const readJSONFile: (file: string) => any;
|
|
6
|
+
export declare const getMostRecentVersion: (data: []) => any;
|
|
7
|
+
export declare const percentFormatter: Intl.NumberFormat;
|
|
8
|
+
export declare const formatFooter: (limit: boolean, diff: number | string) => string;
|
|
9
|
+
export declare const addMDrow: ({ type, passed, name, size, diff, limit, columns, }: {
|
|
10
|
+
columns: any;
|
|
11
|
+
type: "header" | "row";
|
|
12
|
+
passed?: boolean;
|
|
13
|
+
name?: string;
|
|
14
|
+
size?: number;
|
|
15
|
+
diff?: string;
|
|
16
|
+
limit?: string;
|
|
17
|
+
}) => string;
|
package/dist/utilities.js
CHANGED
|
@@ -1,96 +1,97 @@
|
|
|
1
1
|
import bytes from "bytes";
|
|
2
2
|
import fs from "fs-extra";
|
|
3
|
-
import {
|
|
4
|
-
import
|
|
5
|
-
import
|
|
6
|
-
import { statSync } from "node:fs";
|
|
3
|
+
import { join } from "node:path";
|
|
4
|
+
import semver from "semver";
|
|
5
|
+
import zlib from "node:zlib";
|
|
7
6
|
export const STDOUT = "stdout";
|
|
8
7
|
const CWD = process.cwd();
|
|
9
|
-
export const
|
|
8
|
+
export const gzipSizeFromFileSync = (file)=>{
|
|
9
|
+
return zlib.gzipSync(fs.readFileSync(file)).length;
|
|
10
|
+
};
|
|
11
|
+
export const getOutputFile = (file)=>{
|
|
12
|
+
return file === "" || file === undefined ? STDOUT : join(CWD, file);
|
|
13
|
+
};
|
|
14
|
+
export const validateConfigurationFile = (file)=>{
|
|
10
15
|
const result = {
|
|
11
|
-
pass: true,
|
|
12
16
|
exitCode: 0,
|
|
13
17
|
exitMessage: "",
|
|
14
|
-
outputFile: "",
|
|
15
|
-
prefix: "",
|
|
16
18
|
data: {}
|
|
17
19
|
};
|
|
18
|
-
|
|
19
|
-
const configurationFile = flags.configuration.startsWith("/") ? flags.configuration : path.join(CWD, flags.configuration);
|
|
20
|
-
const outputFile = flags.output === "" || flags.output === undefined ? STDOUT : path.join(CWD, flags.output);
|
|
21
|
-
const prefix = flags.prefix || "0.0.0";
|
|
22
|
-
const currentResults = {};
|
|
23
|
-
if (flags.configuration === "") {
|
|
20
|
+
if (file === "") {
|
|
24
21
|
result.exitMessage = "Please provide a configuration file";
|
|
25
22
|
result.exitCode = 1;
|
|
26
23
|
return result;
|
|
27
24
|
}
|
|
25
|
+
const configurationFile = file.startsWith("/") ? file : join(CWD, file);
|
|
28
26
|
if (fs.existsSync(configurationFile) === false) {
|
|
29
|
-
result.exitMessage =
|
|
27
|
+
result.exitMessage = `Invalid or missing configuration file!\n${configurationFile}`;
|
|
30
28
|
result.exitCode = 1;
|
|
31
29
|
return result;
|
|
32
30
|
}
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
if (files.length > 1 && hasHash) {
|
|
57
|
-
result.exitCode = 1;
|
|
58
|
-
result.exitMessage = `Multiple files found for: ${artifact.path}.\nPlease use a more specific path when using the special keyword <hash>.`;
|
|
59
|
-
return result;
|
|
60
|
-
}
|
|
61
|
-
for (const file of files){
|
|
62
|
-
const fileSize = statSync(file).size;
|
|
63
|
-
const fileSizeGzip = gzipSizeFromFileSync(file);
|
|
64
|
-
const passed = fileSizeGzip < bytes(artifact.limit);
|
|
65
|
-
if (passed === false) {
|
|
66
|
-
result.pass = false;
|
|
67
|
-
failed = true;
|
|
68
|
-
}
|
|
69
|
-
let index = hasHash ? artifact.path : path.join(artifactPath, path.basename(file));
|
|
70
|
-
currentResults[index] = {
|
|
71
|
-
fileSize,
|
|
72
|
-
fileSizeGzip,
|
|
73
|
-
limit: artifact.limit,
|
|
74
|
-
passed
|
|
75
|
-
};
|
|
76
|
-
}
|
|
31
|
+
return {
|
|
32
|
+
...result,
|
|
33
|
+
data: configurationFile
|
|
34
|
+
};
|
|
35
|
+
};
|
|
36
|
+
export const readJSONFile = (file)=>{
|
|
37
|
+
try {
|
|
38
|
+
return {
|
|
39
|
+
exitCode: 0,
|
|
40
|
+
exitMessage: "",
|
|
41
|
+
data: fs.readJsonSync(file)
|
|
42
|
+
};
|
|
43
|
+
} catch (error) {
|
|
44
|
+
return {
|
|
45
|
+
exitCode: 1,
|
|
46
|
+
exitMessage: `Failed to read JSON file: ${error.message}`
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
};
|
|
50
|
+
export const getMostRecentVersion = (data)=>{
|
|
51
|
+
const keys = [];
|
|
52
|
+
for (const key of Object.keys(data)){
|
|
53
|
+
keys.push(key);
|
|
77
54
|
}
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
55
|
+
keys.sort(semver.rcompare);
|
|
56
|
+
return keys[0];
|
|
57
|
+
};
|
|
58
|
+
export const percentFormatter = new Intl.NumberFormat("en", {
|
|
59
|
+
style: "percent",
|
|
60
|
+
signDisplay: "exceptZero",
|
|
61
|
+
minimumFractionDigits: 2,
|
|
62
|
+
maximumFractionDigits: 2
|
|
63
|
+
});
|
|
64
|
+
export const formatFooter = (limit, diff)=>{
|
|
65
|
+
return `Overall status: ${limit ? "🚫" : "✅"} ${diff}`;
|
|
66
|
+
};
|
|
67
|
+
export const addMDrow = ({ type, passed = true, name = "", size = 0, diff = "", limit = "", columns })=>{
|
|
68
|
+
const totalColumns = columns.length;
|
|
69
|
+
if (type === "header") {
|
|
70
|
+
const separator = " --- |".repeat(totalColumns);
|
|
71
|
+
const header = columns.map((column)=>column[Object.keys(column)[0]]);
|
|
72
|
+
return `| ${header.join(" | ")} |\n|${separator}`;
|
|
73
|
+
}
|
|
74
|
+
if (type === "row") {
|
|
75
|
+
const row = columns.map((column)=>{
|
|
76
|
+
const key = Object.keys(column)[0];
|
|
77
|
+
if (key === "status") {
|
|
78
|
+
return passed ? "✅" : "🚫";
|
|
79
|
+
}
|
|
80
|
+
if (key === "file") {
|
|
81
|
+
return name.replaceAll("<", "[").replaceAll(">", "]");
|
|
82
|
+
}
|
|
83
|
+
if (key === "size") {
|
|
84
|
+
return `${bytes(size, {
|
|
85
|
+
unitSeparator: " "
|
|
86
|
+
})}${diff}`;
|
|
87
|
+
}
|
|
88
|
+
if (key === "limits") {
|
|
89
|
+
return limit;
|
|
90
|
+
}
|
|
91
|
+
return "";
|
|
92
|
+
});
|
|
93
|
+
return `| ${row.join(" | ")} |`;
|
|
87
94
|
}
|
|
88
|
-
existingResults[prefix] = currentResults;
|
|
89
|
-
result.prefix = prefix;
|
|
90
|
-
result.outputFile = outputFile;
|
|
91
|
-
result.exitCode = failed && flags.silent === false ? 1 : 0;
|
|
92
|
-
result.data = existingResults;
|
|
93
|
-
return result;
|
|
94
95
|
};
|
|
95
96
|
|
|
96
97
|
//# sourceMappingURL=utilities.js.map
|
package/dist/utilities.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/utilities.ts"],"sourcesContent":["import bytes from \"bytes\";\nimport fs from \"fs-extra\";\nimport {
|
|
1
|
+
{"version":3,"sources":["../src/utilities.ts"],"sourcesContent":["import bytes from \"bytes\";\nimport fs from \"fs-extra\";\nimport { join } from \"node:path\";\nimport semver from \"semver\";\nimport zlib from \"node:zlib\";\n\nexport const STDOUT = \"stdout\";\nconst CWD = process.cwd();\n\nexport const gzipSizeFromFileSync = (file: string): number => {\n\treturn zlib.gzipSync(fs.readFileSync(file)).length;\n};\n\nexport const getOutputFile = (file: string): string => {\n\treturn file === \"\" || file === undefined ? STDOUT : join(CWD, file);\n};\n\nexport const validateConfigurationFile = (file: string): any => {\n\tconst result = {\n\t\texitCode: 0,\n\t\texitMessage: \"\",\n\t\tdata: {},\n\t};\n\tif (file === \"\") {\n\t\tresult.exitMessage = \"Please provide a configuration file\";\n\t\tresult.exitCode = 1;\n\t\treturn result;\n\t}\n\n\tconst configurationFile = file.startsWith(\"/\") ? file : join(CWD, file);\n\n\tif (fs.existsSync(configurationFile) === false) {\n\t\tresult.exitMessage = `Invalid or missing configuration file!\\n${configurationFile}`;\n\t\tresult.exitCode = 1;\n\t\treturn result;\n\t}\n\n\treturn {\n\t\t...result,\n\t\tdata: configurationFile,\n\t};\n};\n\nexport const readJSONFile = (file: string): any => {\n\ttry {\n\t\treturn {\n\t\t\texitCode: 0,\n\t\t\texitMessage: \"\",\n\t\t\tdata: fs.readJsonSync(file),\n\t\t};\n\t} catch (error) {\n\t\treturn {\n\t\t\texitCode: 1,\n\t\t\texitMessage: `Failed to read JSON file: ${error.message}`,\n\t\t};\n\t}\n};\n\nexport const getMostRecentVersion = (data: []) => {\n\tconst keys = [];\n\tfor (const key of Object.keys(data)) {\n\t\tkeys.push(key);\n\t}\n\tkeys.sort(semver.rcompare);\n\treturn keys[0];\n};\n\nexport const percentFormatter = new Intl.NumberFormat(\"en\", {\n\tstyle: \"percent\",\n\tsignDisplay: \"exceptZero\",\n\tminimumFractionDigits: 2,\n\tmaximumFractionDigits: 2,\n});\n\nexport const formatFooter = (limit: boolean, diff: number | string): string => {\n\treturn `Overall status: ${limit ? \"🚫\" : \"✅\"} ${diff}`;\n};\n\nexport const addMDrow = ({\n\ttype,\n\tpassed = true,\n\tname = \"\",\n\tsize = 0,\n\tdiff = \"\",\n\tlimit = \"\",\n\tcolumns,\n}: {\n\tcolumns: any;\n\ttype: \"header\" | \"row\";\n\tpassed?: boolean;\n\tname?: string;\n\tsize?: number;\n\tdiff?: string;\n\tlimit?: string;\n}) => {\n\tconst totalColumns = columns.length;\n\n\tif (type === \"header\") {\n\t\tconst separator = \" --- |\".repeat(totalColumns);\n\t\tconst header = columns.map((column) => column[Object.keys(column)[0]]);\n\t\treturn `| ${header.join(\" | \")} |\\n|${separator}`;\n\t}\n\tif (type === \"row\") {\n\t\tconst row = columns.map((column) => {\n\t\t\tconst key = Object.keys(column)[0];\n\t\t\tif (key === \"status\") {\n\t\t\t\treturn passed ? \"✅\" : \"🚫\";\n\t\t\t}\n\t\t\tif (key === \"file\") {\n\t\t\t\treturn name.replaceAll(\"<\", \"[\").replaceAll(\">\", \"]\");\n\t\t\t}\n\t\t\tif (key === \"size\") {\n\t\t\t\treturn `${bytes(size, {\n\t\t\t\t\tunitSeparator: \" \",\n\t\t\t\t})}${diff}`;\n\t\t\t}\n\t\t\tif (key === \"limits\") {\n\t\t\t\treturn limit;\n\t\t\t}\n\t\t\treturn \"\";\n\t\t});\n\n\t\treturn `| ${row.join(\" | \")} |`;\n\t}\n};\n"],"names":["bytes","fs","join","semver","zlib","STDOUT","CWD","process","cwd","gzipSizeFromFileSync","file","gzipSync","readFileSync","length","getOutputFile","undefined","validateConfigurationFile","result","exitCode","exitMessage","data","configurationFile","startsWith","existsSync","readJSONFile","readJsonSync","error","message","getMostRecentVersion","keys","key","Object","push","sort","rcompare","percentFormatter","Intl","NumberFormat","style","signDisplay","minimumFractionDigits","maximumFractionDigits","formatFooter","limit","diff","addMDrow","type","passed","name","size","columns","totalColumns","separator","repeat","header","map","column","row","replaceAll","unitSeparator"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@node-cli/bundlesize",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "3.0.0",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"author": "Arno Versini",
|
|
6
6
|
"description": "Simple CLI tool that checks file(s) size and report if limits have been reached",
|
|
@@ -32,10 +32,10 @@
|
|
|
32
32
|
"bytes": "3.1.2",
|
|
33
33
|
"fs-extra": "11.2.0",
|
|
34
34
|
"glob": "10.3.10",
|
|
35
|
-
"
|
|
35
|
+
"semver": "7.5.4"
|
|
36
36
|
},
|
|
37
37
|
"publishConfig": {
|
|
38
38
|
"access": "public"
|
|
39
39
|
},
|
|
40
|
-
"gitHead": "
|
|
40
|
+
"gitHead": "852bffa76c7fb0ad5bb594c7b71ffe68f8c8faff"
|
|
41
41
|
}
|