source-map-explorer 2.3.1 → 2.5.0

Sign up to get free protection for your applications and to get access to all the features.
package/README.md CHANGED
@@ -126,11 +126,15 @@ source-map-explorer foo.min.js --tsv result.tsv
126
126
 
127
127
  These are regular expressions.
128
128
 
129
- * `--no-root`: By default, source-map-explorer finds common prefixes between all source files and eliminates them, since they add complexity to the visualization with no real benefit. But if you want to disable this behavior, set the `--no-root` flag.
129
+ * `--no-root`: By default, `source-map-explorer` finds common prefixes between all source files and eliminates them, since they add complexity to the visualization with no real benefit. But if you want to disable this behavior, set the `--no-root` flag.
130
+
131
+ * `--no-border-checks`: Disable invalid mapping column/line checks. By default, when a source map references column/line with bigger index than available in the source `source-map-explorers` throws an error indicating that specified source map might be wrong for the source.
130
132
 
131
133
  * `--coverage`: If the path to a valid a chrome code coverage JSON export is supplied, the tree map will be colorized according to which percentage of the modules code was executed
132
134
 
133
- * `--gzip`: calculate gzip size. It also sets `onlyMapped` flag
135
+ * `--gzip`: Calculate gzip size. It also sets `onlyMapped` flag
136
+
137
+ * `--sort`: Sort filenames
134
138
 
135
139
  <details>
136
140
  <summary>Examples</summary>
@@ -143,7 +147,7 @@ source-map-explorer -h
143
147
  ```
144
148
  Analyze and debug space usage through source maps.
145
149
  Usage:
146
- source-map-explorer script.js [script.js.map] [--json [result.json] | --html [result.html] | --tsv [result.csv]] [-m | --only-mapped] [--exclude-source-map] [--gzip] [--replace=BEFORE_1 BEFORE_2 --with=AFTER_1 AFTER_2] [--no-root] [--coverage coverage.json] [--version] [--help | -h]
150
+ source-map-explorer script.js [script.js.map] [--json [result.json] | --html [result.html] | --tsv [result.csv]] [-m | --only-mapped] [--exclude-source-map] [--no-border-checks] [--gzip] [--sort] [--replace=BEFORE_1 BEFORE_2 --with=AFTER_1 AFTER_2] [--no-root] [--coverage coverage.json] [--version] [--help | -h]
147
151
 
148
152
  Output:
149
153
  --json If filename specified save output as JSON to specified file otherwise output to stdout. [string]
@@ -160,9 +164,11 @@ Options:
160
164
  --only-mapped, -m Exclude "unmapped" bytes from the output. This will result in total counts less than the file size [boolean]
161
165
  --exclude-source-map Exclude source map comment size from output [boolean]
162
166
  --no-root To simplify the visualization, source-map-explorer will remove any prefix shared by all sources. If you wish to disable this behavior, set --no-root. [boolean]
167
+ --no-border-checks Disable invalid mapping column/line checks. [boolean]
163
168
  --coverage If the path to a valid a chrome code coverage JSON export is supplied, the tree map will be colorized according to which percentage of the modules code was executed
164
169
  [string]
165
170
  --gzip Calculate gzip size. It also sets onlyMapped flag [boolean]
171
+ --sort Sort filenames [boolean]
166
172
  -h, --help Show help [boolean]
167
173
 
168
174
  Examples:
@@ -294,10 +300,10 @@ source-map-explorer script.js --tsv --no-root
294
300
  ### On error
295
301
  Errors will be displayed only if no output flags specified
296
302
  ```
297
- source-map-explore with-unmapped.js no-map.js
303
+ source-map-explore with-unmapped.js no-map-comment.js
298
304
  ```
299
305
  ```
300
- no-map.js
306
+ no-map-comment.js
301
307
  Unable to find a source map.
302
308
  See https://github.com/danvk/source-map-explorer/blob/master/README.md#generating-source-maps
303
309
  with-unmapped.js
@@ -326,6 +332,7 @@ with-unmapped.js
326
332
  * `format`: [string] - `'json'`, `'tsv'` or `'html'`
327
333
  * `filename`: [string] - Filename to save output to
328
334
  * `noRoot`: [boolean] (default `false`) - See `--no-root` option above for details
335
+ * `noBorderChecks`: [boolean] - Disable invalid mapping column/line checks. See `--no-border-checks` above.
329
336
  * `replaceMap`: <[Object]<{ [from: [string]]: [string] }>> - Mapping for replacement, see `--replace`, `--with` options above for details.
330
337
  * `coverage`: [string] - If the path to a valid a chrome code coverage JSON export is supplied, the tree map will be colorized according to which percentage of the modules code was executed
331
338
  * `gzip`: [boolean] - Calculate gzip size. It also sets `onlyMapped` flag
@@ -555,9 +562,14 @@ source-map-explorer path/to/foo.min.js{,.map}
555
562
 
556
563
  ### Other source map tools
557
564
 
558
- [source-map-visualization](https://sokra.github.io/source-map-visualization)
565
+ - [source-map-visualization](https://sokra.github.io/source-map-visualization)
566
+
567
+ - [bundle-wizard](https://github.com/aholachek/bundle-wizard) - Easier analysis of webapp entry points (uses source-map-explorer under the hood)
568
+
569
+ ### Learn about source maps
559
570
 
560
- [bundle-wizard](https://github.com/aholachek/bundle-wizard): Easier analysis of webapp entry points (uses source-map-explorer under the hood)
571
+ - [Standard](https://docs.google.com/document/d/1U1RGAehQwRypUTovF1KRlpiOFze0b-_2gc6fAH0KY0k/edit)
572
+ - [Anatomy of source maps](https://www.bugsnag.com/blog/source-maps)
561
573
 
562
574
  [demo]: https://cdn.rawgit.com/danvk/source-map-explorer/08b0e130cb9345f9061760bf8a8d9136ea60b457/demo.html
563
575
  [another demo]: https://cdn.rawgit.com/danvk/source-map-explorer/08b0e130cb9345f9061760bf8a8d9136ea60b457/demo-bug.html
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import { ErrorContext } from './app-error';
2
+ import type { ErrorContext } from '../lib/app-error';
3
3
  export declare function logError(message: string | ErrorContext, error?: Error): void;
4
4
  export declare function logWarn(message: string): void;
5
5
  export declare function logInfo(message: string): void;
@@ -1,41 +1,28 @@
1
1
  #!/usr/bin/env node
2
2
  'use strict';
3
-
4
- Object.defineProperty(exports, '__esModule', {
5
- value: true,
6
- });
7
- exports.logError = logError;
8
- exports.logWarn = logWarn;
9
- exports.logInfo = logInfo;
10
-
11
- var _yargs = _interopRequireDefault(require('yargs'));
12
-
13
- var _fs = _interopRequireDefault(require('fs'));
14
-
15
- var _temp = _interopRequireDefault(require('temp'));
16
-
17
- var _open = _interopRequireDefault(require('open'));
18
-
19
- var _chalk = _interopRequireDefault(require('chalk'));
20
-
21
- var _lodash = require('lodash');
22
-
23
- var _api = require('./api');
24
-
25
- var _appError = require('./app-error');
26
-
27
- function _interopRequireDefault(obj) {
28
- return obj && obj.__esModule ? obj : { default: obj };
29
- }
30
-
3
+ var __importDefault =
4
+ (this && this.__importDefault) ||
5
+ function (mod) {
6
+ return mod && mod.__esModule ? mod : { default: mod };
7
+ };
8
+ Object.defineProperty(exports, '__esModule', { value: true });
9
+ exports.logInfo = exports.logWarn = exports.logError = void 0;
10
+ const yargs_1 = __importDefault(require('yargs'));
11
+ const fs_1 = __importDefault(require('fs'));
12
+ const temp_1 = __importDefault(require('temp'));
13
+ const open_1 = __importDefault(require('open'));
14
+ const chalk_1 = __importDefault(require('chalk'));
15
+ const lodash_1 = require('lodash');
16
+ const api_1 = require('../lib/api');
17
+ const app_error_1 = require('../lib/app-error');
31
18
  function parseArguments() {
32
- const argv = _yargs.default
19
+ const argv = yargs_1.default
33
20
  .strict()
34
21
  .scriptName('source-map-explorer')
35
22
  .usage('Analyze and debug space usage through source maps.')
36
23
  .usage('Usage:')
37
24
  .usage(
38
- '$0 script.js [script.js.map] [--json [result.json] | --html [result.html] | --tsv [result.csv]] [-m | --only-mapped] [--exclude-source-map] [--gzip] [--replace=BEFORE_1 BEFORE_2 --with=AFTER_1 AFTER_2] [--no-root] [--coverage coverage.json] [--version] [--help | -h]'
25
+ '$0 script.js [script.js.map] [--json [result.json] | --html [result.html] | --tsv [result.csv]] [-m | --only-mapped] [--exclude-source-map] [--no-border-checks] [--gzip] [--sort] [--replace=BEFORE_1 BEFORE_2 --with=AFTER_1 AFTER_2] [--no-root] [--coverage coverage.json] [--version] [--help | -h]'
39
26
  )
40
27
  .example('$0 script.js script.js.map', 'Explore bundle')
41
28
  .example('$0 script.js', 'Explore bundle with inline source map')
@@ -90,6 +77,10 @@ function parseArguments() {
90
77
  description: 'See --replace.',
91
78
  implies: 'replace',
92
79
  },
80
+ 'no-border-checks': {
81
+ type: 'boolean',
82
+ description: 'Disable invalid mapping column/line checks.',
83
+ },
93
84
  coverage: {
94
85
  type: 'string',
95
86
  normalize: true,
@@ -101,53 +92,50 @@ function parseArguments() {
101
92
  description: 'Calculate gzip size. It also sets onlyMapped flag',
102
93
  conflicts: ['only-mapped'],
103
94
  },
95
+ sort: {
96
+ type: 'boolean',
97
+ description: 'Sort filenames',
98
+ },
104
99
  })
105
100
  .group(['json', 'tsv', 'html'], 'Output:')
106
101
  .group(['replace', 'with'], 'Replace:')
107
102
  .help('h')
108
103
  .alias('h', 'help')
109
104
  .showHelpOnFail(false, 'Specify --help for available options')
110
- .wrap(null) // Do not limit line length
105
+ .wrap(null)
111
106
  .parserConfiguration({
112
- 'boolean-negation': false, // Allow --no-root
107
+ 'boolean-negation': false,
113
108
  })
114
- .check(argv => {
109
+ .check((argv) => {
115
110
  if (argv.replace && argv.with && argv.replace.length !== argv.with.length) {
116
111
  throw new Error('--replace flags must be paired with --with flags');
117
112
  }
118
-
119
113
  return true;
120
114
  })
121
- .parse(); // Trim extra quotes
122
-
115
+ .parse();
123
116
  const quoteRegex = /'/g;
124
- argv._ = argv._.map(path => path.replace(quoteRegex, ''));
117
+ argv._ = argv._.map((path) => path.replace(quoteRegex, ''));
125
118
  return argv;
126
119
  }
127
-
128
120
  function logError(message, error) {
129
- if (!(0, _lodash.isString)(message)) {
130
- message = (0, _appError.getErrorMessage)(message);
121
+ if (!lodash_1.isString(message)) {
122
+ message = app_error_1.getErrorMessage(message);
131
123
  }
132
-
133
124
  if (error) {
134
- console.error(_chalk.default.red(message), error);
125
+ console.error(chalk_1.default.red(message), error);
135
126
  } else {
136
- console.error(_chalk.default.red(message));
127
+ console.error(chalk_1.default.red(message));
137
128
  }
138
129
  }
139
-
130
+ exports.logError = logError;
140
131
  function logWarn(message) {
141
- console.warn(_chalk.default.yellow(message));
132
+ console.warn(chalk_1.default.yellow(message));
142
133
  }
143
-
134
+ exports.logWarn = logWarn;
144
135
  function logInfo(message) {
145
- console.log(_chalk.default.green(message));
136
+ console.log(chalk_1.default.green(message));
146
137
  }
147
- /**
148
- * Create options object for `explore` method
149
- */
150
-
138
+ exports.logInfo = logInfo;
151
139
  function getExploreOptions(argv) {
152
140
  const {
153
141
  json,
@@ -158,83 +146,60 @@ function getExploreOptions(argv) {
158
146
  onlyMapped,
159
147
  excludeSourceMap: excludeSourceMapComment,
160
148
  noRoot,
149
+ noBorderChecks,
161
150
  coverage,
162
151
  gzip,
152
+ sort,
163
153
  } = argv;
164
154
  let replaceMap;
165
-
166
155
  if (replaceItems && withItems) {
167
156
  replaceMap = replaceItems.reduce((result, item, index) => {
168
157
  result[item] = withItems[index];
169
158
  return result;
170
159
  }, {});
171
160
  }
172
-
173
161
  return {
174
162
  output: {
175
- // By default CLI needs result in HTML in order to create a temporary file
176
- format: (0, _lodash.isString)(json) ? 'json' : (0, _lodash.isString)(tsv) ? 'tsv' : 'html',
163
+ format: lodash_1.isString(json) ? 'json' : lodash_1.isString(tsv) ? 'tsv' : 'html',
177
164
  filename: json || tsv || html,
178
165
  },
179
166
  replaceMap,
180
167
  onlyMapped,
181
168
  excludeSourceMapComment,
182
169
  noRoot,
170
+ noBorderChecks,
183
171
  coverage,
184
172
  gzip,
173
+ sort,
185
174
  };
186
175
  }
187
- /**
188
- * Write HTML content to a temporary file and open the file in a browser
189
- */
190
-
191
176
  async function writeHtmlToTempFile(html) {
192
177
  if (!html) {
193
178
  return;
194
179
  }
195
-
196
180
  try {
197
- const tempFile = _temp.default.path({
198
- prefix: 'sme-result-',
199
- suffix: '.html',
200
- });
201
-
202
- _fs.default.writeFileSync(tempFile, html);
203
-
204
- const childProcess = await (0, _open.default)(tempFile);
205
-
181
+ const tempFile = temp_1.default.path({ prefix: 'sme-result-', suffix: '.html' });
182
+ fs_1.default.writeFileSync(tempFile, html);
183
+ const childProcess = await open_1.default(tempFile);
206
184
  if (childProcess.stderr) {
207
- // Catch error output from child process
208
- childProcess.stderr.once('data', error => {
209
- logError({
210
- code: 'CannotOpenTempFile',
211
- tempFile,
212
- error,
213
- });
185
+ childProcess.stderr.once('data', (error) => {
186
+ logError({ code: 'CannotOpenTempFile', tempFile, error });
214
187
  });
215
188
  }
216
189
  } catch (error) {
217
- throw new _appError.AppError(
218
- {
219
- code: 'CannotCreateTempFile',
220
- },
221
- error
222
- );
190
+ throw new app_error_1.AppError({ code: 'CannotCreateTempFile' }, error);
223
191
  }
224
192
  }
225
-
226
193
  function outputErrors({ errors }) {
227
194
  if (errors.length === 0) {
228
195
  return;
229
- } // Group errors by bundle name
230
-
231
- const groupedErrors = (0, _lodash.groupBy)(errors, 'bundleName');
196
+ }
197
+ const groupedErrors = lodash_1.groupBy(errors, 'bundleName');
232
198
  Object.entries(groupedErrors).forEach(([bundleName, errors]) => {
233
199
  console.group(bundleName);
234
200
  const hasManyErrors = errors.length > 1;
235
201
  errors.forEach((error, index) => {
236
202
  const message = `${hasManyErrors ? `${index + 1}. ` : ''}${error.message}`;
237
-
238
203
  if (error.isWarning) {
239
204
  logWarn(message);
240
205
  } else {
@@ -244,16 +209,15 @@ function outputErrors({ errors }) {
244
209
  console.groupEnd();
245
210
  });
246
211
  }
247
-
248
212
  if (require.main === module) {
249
213
  const argv = parseArguments();
250
- const isOutputFormatSpecified = [argv.json, argv.tsv, argv.html].some(_lodash.isString);
214
+ const isOutputFormatSpecified = [argv.json, argv.tsv, argv.html].some(lodash_1.isString);
251
215
  const options = getExploreOptions(argv);
252
- (0, _api.explore)(argv._, options)
253
- .then(result => {
216
+ api_1
217
+ .explore(argv._, options)
218
+ .then((result) => {
254
219
  if (isOutputFormatSpecified && options.output) {
255
220
  const filename = options.output.filename;
256
-
257
221
  if (filename) {
258
222
  logInfo(`Output saved to ${filename}`);
259
223
  outputErrors(result);
@@ -266,11 +230,13 @@ if (require.main === module) {
266
230
  });
267
231
  }
268
232
  })
269
- .catch(error => {
233
+ .catch((error) => {
270
234
  if (error.errors) {
271
235
  outputErrors(error);
272
236
  } else {
273
237
  logError('Failed to explore', error);
274
238
  }
239
+ process.exitCode = 1;
275
240
  });
276
241
  }
242
+ //# sourceMappingURL=cli.js.map
package/bin/cli.js.map ADDED
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli/cli.ts"],"names":[],"mappings":"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","sourcesContent":["#!/usr/bin/env node\n\nimport yargs from 'yargs';\nimport fs from 'fs';\nimport temp from 'temp';\nimport open from 'open';\nimport chalk from 'chalk';\nimport { groupBy, isString } from 'lodash';\n\nimport { explore } from '../lib/api';\nimport { AppError, getErrorMessage } from '../lib/app-error';\n\nimport type { ErrorContext } from '../lib/app-error';\nimport type { ExploreOptions, ReplaceMap, ExploreResult } from '../lib/types';\n\n/** Parsed CLI arguments */\ninterface Arguments {\n _: string[];\n json?: string;\n tsv?: string;\n html?: string;\n onlyMapped?: boolean;\n excludeSourceMap?: boolean;\n noRoot?: boolean;\n replace?: string[];\n with?: string[];\n noBorderChecks?: boolean;\n coverage?: string;\n gzip?: boolean;\n sort?: boolean;\n}\n\nfunction parseArguments(): Arguments {\n const argv = yargs\n .strict()\n .scriptName('source-map-explorer')\n .usage('Analyze and debug space usage through source maps.')\n .usage('Usage:')\n .usage(\n '$0 script.js [script.js.map] [--json [result.json] | --html [result.html] | --tsv [result.csv]] [-m | --only-mapped] [--exclude-source-map] [--no-border-checks] [--gzip] [--sort] [--replace=BEFORE_1 BEFORE_2 --with=AFTER_1 AFTER_2] [--no-root] [--coverage coverage.json] [--version] [--help | -h]'\n )\n .example('$0 script.js script.js.map', 'Explore bundle')\n .example('$0 script.js', 'Explore bundle with inline source map')\n .example('$0 dist/js/*.*', 'Explore all bundles inside dist/js folder')\n .example('$0 script.js --tsv', 'Explore and output result as TSV to stdout')\n .example('$0 script.js --json result.json', 'Explore and save result as JSON to the file')\n .demandCommand(1, 'At least one js file must be specified')\n .options({\n json: {\n type: 'string',\n description:\n 'If filename specified save output as JSON to specified file otherwise output to stdout.',\n conflicts: ['tsv', 'html'],\n },\n tsv: {\n type: 'string',\n description:\n 'If filename specified save output as TSV to specified file otherwise output to stdout.',\n conflicts: ['json', 'html'],\n },\n html: {\n type: 'string',\n description:\n 'If filename specified save output as HTML to specified file otherwise output to stdout rather than opening a browser.',\n conflicts: ['json', 'tsv'],\n },\n\n 'only-mapped': {\n alias: 'm',\n type: 'boolean',\n description:\n 'Exclude \"unmapped\" bytes from the output. This will result in total counts less than the file size',\n },\n\n 'exclude-source-map': {\n type: 'boolean',\n description: 'Exclude source map comment size from output',\n },\n\n 'no-root': {\n type: 'boolean',\n description:\n 'To simplify the visualization, source-map-explorer will remove any prefix shared by all sources. If you wish to disable this behavior, set --no-root.',\n },\n\n replace: {\n type: 'string',\n array: true,\n description:\n 'Apply a simple find/replace on source file names. This can be used to fix some oddities with paths that appear in the source map generation process. Accepts regular expressions.',\n implies: 'with',\n },\n with: {\n type: 'string',\n array: true,\n description: 'See --replace.',\n implies: 'replace',\n },\n\n 'no-border-checks': {\n type: 'boolean',\n description: 'Disable invalid mapping column/line checks.',\n },\n\n coverage: {\n type: 'string',\n normalize: true,\n description:\n 'If the path to a valid a chrome code coverage JSON export is supplied, the tree map will be colorized according to which percentage of the modules code was executed',\n },\n\n gzip: {\n type: 'boolean',\n description: 'Calculate gzip size. It also sets onlyMapped flag',\n conflicts: ['only-mapped'],\n },\n\n sort: {\n type: 'boolean',\n description: 'Sort filenames',\n },\n })\n .group(['json', 'tsv', 'html'], 'Output:')\n .group(['replace', 'with'], 'Replace:')\n .help('h')\n .alias('h', 'help')\n .showHelpOnFail(false, 'Specify --help for available options')\n .wrap(null) // Do not limit line length\n .parserConfiguration({\n 'boolean-negation': false, // Allow --no-root\n })\n .check((argv) => {\n if (argv.replace && argv.with && argv.replace.length !== argv.with.length) {\n throw new Error('--replace flags must be paired with --with flags');\n }\n\n return true;\n })\n .parse();\n\n // Trim extra quotes\n const quoteRegex = /'/g;\n\n argv._ = argv._.map((path) => path.replace(quoteRegex, ''));\n\n return argv;\n}\n\nexport function logError(message: string | ErrorContext, error?: Error): void {\n if (!isString(message)) {\n message = getErrorMessage(message);\n }\n\n if (error) {\n console.error(chalk.red(message), error);\n } else {\n console.error(chalk.red(message));\n }\n}\n\nexport function logWarn(message: string): void {\n console.warn(chalk.yellow(message));\n}\n\nexport function logInfo(message: string): void {\n console.log(chalk.green(message));\n}\n\n/**\n * Create options object for `explore` method\n */\nfunction getExploreOptions(argv: Arguments): ExploreOptions {\n const {\n json,\n tsv,\n html,\n replace: replaceItems,\n with: withItems,\n onlyMapped,\n excludeSourceMap: excludeSourceMapComment,\n noRoot,\n noBorderChecks,\n coverage,\n gzip,\n sort,\n } = argv;\n\n let replaceMap: ReplaceMap | undefined;\n\n if (replaceItems && withItems) {\n replaceMap = replaceItems.reduce<ReplaceMap>((result, item, index) => {\n result[item] = withItems[index];\n\n return result;\n }, {});\n }\n\n return {\n output: {\n // By default CLI needs result in HTML in order to create a temporary file\n format: isString(json) ? 'json' : isString(tsv) ? 'tsv' : 'html',\n filename: json || tsv || html,\n },\n replaceMap,\n onlyMapped,\n excludeSourceMapComment,\n noRoot,\n noBorderChecks,\n coverage,\n gzip,\n sort,\n };\n}\n\n/**\n * Write HTML content to a temporary file and open the file in a browser\n */\nasync function writeHtmlToTempFile(html?: string): Promise<void> {\n if (!html) {\n return;\n }\n\n try {\n const tempFile = temp.path({ prefix: 'sme-result-', suffix: '.html' });\n\n fs.writeFileSync(tempFile, html);\n\n const childProcess = await open(tempFile);\n\n if (childProcess.stderr) {\n // Catch error output from child process\n childProcess.stderr.once('data', (error: Buffer) => {\n logError({ code: 'CannotOpenTempFile', tempFile, error });\n });\n }\n } catch (error) {\n throw new AppError({ code: 'CannotCreateTempFile' }, error);\n }\n}\n\nfunction outputErrors({ errors }: ExploreResult): void {\n if (errors.length === 0) {\n return;\n }\n\n // Group errors by bundle name\n const groupedErrors = groupBy(errors, 'bundleName');\n\n Object.entries(groupedErrors).forEach(([bundleName, errors]) => {\n console.group(bundleName);\n\n const hasManyErrors = errors.length > 1;\n\n errors.forEach((error, index) => {\n const message = `${hasManyErrors ? `${index + 1}. ` : ''}${error.message}`;\n\n if (error.isWarning) {\n logWarn(message);\n } else {\n logError(message);\n }\n });\n\n console.groupEnd();\n });\n}\n\nif (require.main === module) {\n const argv = parseArguments();\n\n const isOutputFormatSpecified = [argv.json, argv.tsv, argv.html].some(isString);\n\n const options = getExploreOptions(argv);\n\n explore(argv._, options)\n .then((result) => {\n if (isOutputFormatSpecified && options.output) {\n const filename = options.output.filename;\n\n if (filename) {\n logInfo(`Output saved to ${filename}`);\n outputErrors(result);\n } else {\n console.log(result.output);\n }\n } else {\n writeHtmlToTempFile(result.output).then(() => {\n outputErrors(result);\n });\n }\n })\n .catch((error) => {\n if (error.errors) {\n outputErrors(error);\n } else {\n logError('Failed to explore', error);\n }\n\n process.exitCode = 1;\n });\n}\n"]}
@@ -1,10 +1,4 @@
1
- import { BundlesAndFileTokens, ExploreOptions, ExploreResult, Bundle } from './index';
2
- /**
3
- * Analyze bundle(s)
4
- */
1
+ import type { Bundle, BundlesAndFileTokens, ExploreOptions, ExploreResult } from './types';
5
2
  export declare function explore(bundlesAndFileTokens: BundlesAndFileTokens, options?: ExploreOptions): Promise<ExploreResult>;
6
- /**
7
- * Expand list of file tokens into a list of bundles
8
- */
9
3
  export declare function getBundles(fileTokens: string[]): Bundle[];
10
4
  export declare function getBundleName(bundle: Bundle): string;
package/lib/api.js ADDED
@@ -0,0 +1,134 @@
1
+ 'use strict';
2
+ var __importDefault =
3
+ (this && this.__importDefault) ||
4
+ function (mod) {
5
+ return mod && mod.__esModule ? mod : { default: mod };
6
+ };
7
+ Object.defineProperty(exports, '__esModule', { value: true });
8
+ exports.getBundleName = exports.getBundles = exports.explore = void 0;
9
+ const glob_1 = __importDefault(require('glob'));
10
+ const lodash_1 = require('lodash');
11
+ const explore_1 = require('./explore');
12
+ const app_error_1 = require('./app-error');
13
+ const output_1 = require('./output');
14
+ const coverage_1 = require('./coverage');
15
+ function adjustOptions(options) {
16
+ if (options.gzip) {
17
+ options.onlyMapped = true;
18
+ }
19
+ return options;
20
+ }
21
+ async function explore(bundlesAndFileTokens, options = {}) {
22
+ bundlesAndFileTokens = Array.isArray(bundlesAndFileTokens)
23
+ ? bundlesAndFileTokens
24
+ : [bundlesAndFileTokens];
25
+ if (bundlesAndFileTokens.length === 0) {
26
+ throw new app_error_1.AppError({ code: 'NoBundles' });
27
+ }
28
+ adjustOptions(options);
29
+ const [fileTokens, bundles] = lodash_1.partition(bundlesAndFileTokens, lodash_1.isString);
30
+ bundles.push(...getBundles(fileTokens));
31
+ coverage_1.addCoverageRanges(bundles, options.coverage);
32
+ const results = await Promise.all(
33
+ bundles.map((bundle) =>
34
+ explore_1.exploreBundle(bundle, options).catch((error) => onExploreError(bundle, error))
35
+ )
36
+ );
37
+ const exploreResult = getExploreResult(results, options);
38
+ if (exploreResult.bundles.length === 0) {
39
+ return Promise.reject(exploreResult);
40
+ }
41
+ output_1.saveOutputToFile(exploreResult, options);
42
+ return exploreResult;
43
+ }
44
+ exports.explore = explore;
45
+ function getBundles(fileTokens) {
46
+ const filenames = lodash_1.flatMap(fileTokens, (filePath) =>
47
+ glob_1.default.hasMagic(filePath) ? expandGlob(filePath) : filePath
48
+ );
49
+ const [mapFilenames, codeFilenames] = lodash_1.partition(filenames, (filename) =>
50
+ filename.endsWith('.map')
51
+ );
52
+ return codeFilenames.map((code) => ({
53
+ code,
54
+ map: mapFilenames.find((filename) => filename === `${code}.map`),
55
+ }));
56
+ }
57
+ exports.getBundles = getBundles;
58
+ function expandGlob(pattern) {
59
+ if (pattern.endsWith('.js')) {
60
+ pattern = `${pattern}?(.map)`;
61
+ }
62
+ return glob_1.default.sync(pattern);
63
+ }
64
+ function getBundleName(bundle) {
65
+ return Buffer.isBuffer(bundle.code) ? 'Buffer' : bundle.code;
66
+ }
67
+ exports.getBundleName = getBundleName;
68
+ function onExploreError(bundle, error) {
69
+ return {
70
+ bundleName: getBundleName(bundle),
71
+ code: error.code || 'Unknown',
72
+ message: error.message,
73
+ error,
74
+ };
75
+ }
76
+ function sortFilenames(bundles) {
77
+ return bundles.map((bundle) => ({
78
+ ...bundle,
79
+ files: lodash_1.fromPairs(lodash_1.sortBy(lodash_1.toPairs(bundle.files), 0)),
80
+ }));
81
+ }
82
+ function getExploreResult(results, options) {
83
+ const [bundles, errors] = lodash_1.partition(results, (result) => 'files' in result);
84
+ let sortedBundles = lodash_1.sortBy(bundles, (bundle) => bundle.bundleName);
85
+ if (options.sort) {
86
+ sortedBundles = sortFilenames(sortedBundles);
87
+ }
88
+ errors.push(...getPostExploreErrors(bundles));
89
+ return {
90
+ bundles: sortedBundles,
91
+ errors,
92
+ ...(bundles.length > 0 && { output: output_1.formatOutput(sortedBundles, options) }),
93
+ };
94
+ }
95
+ function getPostExploreErrors(exploreBundleResults) {
96
+ const errors = [];
97
+ const isSingleBundle = exploreBundleResults.length === 1;
98
+ for (const result of exploreBundleResults) {
99
+ const { bundleName, files, totalBytes } = result;
100
+ if (isSingleBundle) {
101
+ const filenames = Object.keys(files).filter(
102
+ (filename) => !explore_1.SPECIAL_FILENAMES.includes(filename)
103
+ );
104
+ if (filenames.length === 1) {
105
+ errors.push({
106
+ bundleName,
107
+ isWarning: true,
108
+ code: 'OneSourceSourceMap',
109
+ message: app_error_1.getErrorMessage({
110
+ code: 'OneSourceSourceMap',
111
+ filename: filenames[0],
112
+ }),
113
+ });
114
+ }
115
+ }
116
+ if (files[explore_1.UNMAPPED_KEY] !== undefined) {
117
+ const { size: unmappedBytes } = files[explore_1.UNMAPPED_KEY];
118
+ if (unmappedBytes) {
119
+ errors.push({
120
+ bundleName,
121
+ isWarning: true,
122
+ code: 'UnmappedBytes',
123
+ message: app_error_1.getErrorMessage({
124
+ code: 'UnmappedBytes',
125
+ unmappedBytes,
126
+ totalBytes,
127
+ }),
128
+ });
129
+ }
130
+ }
131
+ }
132
+ return errors;
133
+ }
134
+ //# sourceMappingURL=api.js.map
package/lib/api.js.map ADDED
@@ -0,0 +1 @@
1
+ {"version":3,"file":"api.js","sourceRoot":"","sources":["../src/lib/api.ts"],"names":[],"mappings":"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","sourcesContent":["import glob from 'glob';\nimport { partition, flatMap, isString, toPairs, fromPairs, sortBy } from 'lodash';\n\nimport { exploreBundle, UNMAPPED_KEY, SPECIAL_FILENAMES } from './explore';\nimport { AppError, getErrorMessage } from './app-error';\nimport { formatOutput, saveOutputToFile } from './output';\nimport { addCoverageRanges } from './coverage';\n\nimport type {\n Bundle,\n BundlesAndFileTokens,\n ExploreBundleResult,\n ExploreErrorResult,\n ExploreOptions,\n ExploreResult,\n} from './types';\n\nfunction adjustOptions(options: ExploreOptions): ExploreOptions {\n /* Unmapped bytes cannot be calculate because it's impossible to get total size by summing files'\n sizes when calculating gzip size for a file. */\n if (options.gzip) {\n options.onlyMapped = true;\n }\n\n return options;\n}\n\n/**\n * Analyze bundle(s)\n */\nexport async function explore(\n bundlesAndFileTokens: BundlesAndFileTokens,\n options: ExploreOptions = {}\n): Promise<ExploreResult> {\n bundlesAndFileTokens = Array.isArray(bundlesAndFileTokens)\n ? bundlesAndFileTokens\n : [bundlesAndFileTokens];\n\n if (bundlesAndFileTokens.length === 0) {\n throw new AppError({ code: 'NoBundles' });\n }\n\n adjustOptions(options);\n\n // Separate bundles from file tokens\n const [fileTokens, bundles] = partition(bundlesAndFileTokens, isString);\n\n // Get bundles from file tokens\n bundles.push(...getBundles(fileTokens));\n\n addCoverageRanges(bundles, options.coverage);\n\n const results = await Promise.all(\n bundles.map((bundle) =>\n exploreBundle(bundle, options).catch<ExploreErrorResult>((error) =>\n onExploreError(bundle, error)\n )\n )\n );\n\n const exploreResult = getExploreResult(results, options);\n\n // Reject if none of results is successful\n if (exploreResult.bundles.length === 0) {\n return Promise.reject(exploreResult);\n }\n\n saveOutputToFile(exploreResult, options);\n\n return exploreResult;\n}\n\n/**\n * Expand list of file tokens into a list of bundles\n */\nexport function getBundles(fileTokens: string[]): Bundle[] {\n const filenames = flatMap(fileTokens, (filePath) =>\n glob.hasMagic(filePath) ? expandGlob(filePath) : filePath\n );\n\n const [mapFilenames, codeFilenames] = partition(filenames, (filename) =>\n filename.endsWith('.map')\n );\n\n return codeFilenames.map<Bundle>((code) => ({\n code,\n map: mapFilenames.find((filename) => filename === `${code}.map`),\n }));\n}\n\nfunction expandGlob(pattern: string): string[] {\n // Make sure pattern match `.map` files as well\n if (pattern.endsWith('.js')) {\n pattern = `${pattern}?(.map)`;\n }\n\n return glob.sync(pattern);\n}\n\nexport function getBundleName(bundle: Bundle): string {\n return Buffer.isBuffer(bundle.code) ? 'Buffer' : bundle.code;\n}\n\n/**\n * Handle error during bundle processing\n */\nfunction onExploreError(bundle: Bundle, error: NodeJS.ErrnoException): ExploreErrorResult {\n return {\n bundleName: getBundleName(bundle),\n code: error.code || 'Unknown',\n message: error.message,\n error,\n };\n}\n\nfunction sortFilenames(bundles: ExploreBundleResult[]): ExploreBundleResult[] {\n return bundles.map((bundle) => ({\n ...bundle,\n files: fromPairs(sortBy(toPairs(bundle.files), 0)),\n }));\n}\n\nfunction getExploreResult(\n results: (ExploreBundleResult | ExploreErrorResult)[],\n options: ExploreOptions\n): ExploreResult {\n const [bundles, errors] = partition(\n results,\n (result): result is ExploreBundleResult => 'files' in result\n );\n\n let sortedBundles = sortBy(bundles, (bundle) => bundle.bundleName);\n\n if (options.sort) {\n sortedBundles = sortFilenames(sortedBundles);\n }\n\n errors.push(...getPostExploreErrors(bundles));\n\n return {\n bundles: sortedBundles,\n errors,\n ...(bundles.length > 0 && { output: formatOutput(sortedBundles, options) }),\n };\n}\n\nfunction getPostExploreErrors(exploreBundleResults: ExploreBundleResult[]): ExploreErrorResult[] {\n const errors: ExploreErrorResult[] = [];\n\n const isSingleBundle = exploreBundleResults.length === 1;\n\n for (const result of exploreBundleResults) {\n const { bundleName, files, totalBytes } = result;\n\n // Check if source map contains only one file - this make result useless when exploring single bundle\n if (isSingleBundle) {\n const filenames = Object.keys(files).filter(\n (filename) => !SPECIAL_FILENAMES.includes(filename)\n );\n\n if (filenames.length === 1) {\n errors.push({\n bundleName,\n isWarning: true,\n code: 'OneSourceSourceMap',\n message: getErrorMessage({ code: 'OneSourceSourceMap', filename: filenames[0] }),\n });\n }\n }\n\n if (files[UNMAPPED_KEY] !== undefined) {\n const { size: unmappedBytes } = files[UNMAPPED_KEY];\n\n if (unmappedBytes) {\n errors.push({\n bundleName,\n isWarning: true,\n code: 'UnmappedBytes',\n message: getErrorMessage({ code: 'UnmappedBytes', unmappedBytes, totalBytes }),\n });\n }\n }\n }\n\n return errors;\n}\n"]}
@@ -1,5 +1,5 @@
1
1
  /// <reference types="node" />
2
- import { ErrorCode } from './index';
2
+ import type { ErrorCode } from './types';
3
3
  export declare class AppError extends Error {
4
4
  code?: ErrorCode;
5
5
  cause?: Error;