package-build-stats 7.3.8 → 8.0.0-beta.1

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.
Files changed (47) hide show
  1. package/.parcelrc +37 -0
  2. package/package.json +96 -68
  3. package/src/common.types.ts +3 -10
  4. package/src/config/{config.ts → index.ts} +1 -0
  5. package/{build → src}/errors/CustomError.d.ts +0 -0
  6. package/{build → src}/errors/CustomError.js +1 -0
  7. package/src/errors/CustomError.js.map +1 -0
  8. package/src/fixed/parseReference.js +762 -727
  9. package/src/getPackageExportSizes.ts +33 -14
  10. package/src/getPackageStats.ts +55 -16
  11. package/src/typings/is-valid-npm-name.d.ts +3 -0
  12. package/src/utils/build.utils.ts +258 -230
  13. package/src/utils/common.utils.ts +138 -0
  14. package/src/utils/exports.utils.ts +34 -21
  15. package/src/utils/installation.utils.ts +28 -5
  16. package/src/utils/telemetry.utils.ts +0 -21
  17. package/LICENSE +0 -21
  18. package/README.md +0 -67
  19. package/build/common.types.d.ts +0 -34
  20. package/build/common.types.js +0 -2
  21. package/build/config/config.d.ts +0 -4
  22. package/build/config/config.js +0 -10
  23. package/build/config/makeWebpackConfig.d.ts +0 -11
  24. package/build/config/makeWebpackConfig.js +0 -225
  25. package/build/fixed/parseReference.js +0 -5353
  26. package/build/getDependencySizeTree.d.ts +0 -6
  27. package/build/getDependencySizeTree.js +0 -238
  28. package/build/getPackageExportSizes.d.ts +0 -44
  29. package/build/getPackageExportSizes.js +0 -77
  30. package/build/getPackageStats.d.ts +0 -73
  31. package/build/getPackageStats.js +0 -90
  32. package/build/getParseTime.d.ts +0 -8
  33. package/build/getParseTime.js +0 -49
  34. package/build/index.d.ts +0 -5
  35. package/build/index.js +0 -24
  36. package/build/utils/build.utils.d.ts +0 -84
  37. package/build/utils/build.utils.js +0 -261
  38. package/build/utils/common.utils.d.ts +0 -19
  39. package/build/utils/common.utils.js +0 -118
  40. package/build/utils/exports.utils.d.ts +0 -17
  41. package/build/utils/exports.utils.js +0 -238
  42. package/build/utils/installation.utils.d.ts +0 -8
  43. package/build/utils/installation.utils.js +0 -122
  44. package/build/utils/telemetry.utils.d.ts +0 -15
  45. package/build/utils/telemetry.utils.js +0 -127
  46. package/src/config/makeWebpackConfig.ts +0 -251
  47. package/src/getDependencySizeTree.ts +0 -266
@@ -3,6 +3,9 @@ import path from 'path'
3
3
  import builtInModules from 'builtin-modules'
4
4
  import fs from 'fs'
5
5
  import os from 'os'
6
+ import memoize from 'memoizee'
7
+ import ThrowableDiagnostic from '@parcel/diagnostic'
8
+ import { codeFrameColumns } from '@babel/code-frame'
6
9
 
7
10
  const homeDirectory = os.homedir()
8
11
 
@@ -146,3 +149,138 @@ export function parsePackageString(packageString: string): ParsePackageResult {
146
149
  return parseUnscopedPackageString(normalPackageString)
147
150
  }
148
151
  }
152
+
153
+ // Works only when the `path` begins with the package name
154
+ export const parsePackageNameFromPath = (path: string): string => {
155
+ const fragments = path.split('/')
156
+ if (path.startsWith('@')) {
157
+ return [fragments[0], fragments[1]].join('/')
158
+ } else {
159
+ return fragments[0]
160
+ }
161
+ }
162
+
163
+ export function getPackageFromWebpackPath(filePath: string) {
164
+ let filePathReal = filePath.includes('!')
165
+ ? filePath.split('!')[filePath.split('!').length - 1]
166
+ : filePath
167
+ let lastNodeModulesIndex =
168
+ filePathReal.lastIndexOf('node_modules') + 'node_modules'.length + 1
169
+ return {
170
+ name: parsePackageNameFromPath(
171
+ filePathReal.substring(lastNodeModulesIndex)
172
+ ),
173
+ cleanPath: filePathReal,
174
+ }
175
+ }
176
+
177
+ export const getPackageJSONFromPath = memoize(
178
+ (filePath: string) => {
179
+ const { cleanPath, name } = getPackageFromWebpackPath(filePath)
180
+ const packageRoot = cleanPath.substring(
181
+ 0,
182
+ cleanPath.lastIndexOf(name) + name.length
183
+ )
184
+ try {
185
+ const packageJSON = require(path.join(packageRoot, 'package.json'))
186
+ return packageJSON
187
+ } catch (err) {
188
+ return null
189
+ }
190
+ },
191
+ { max: 1000 }
192
+ )
193
+
194
+ export async function updateProjectPeerDependencies(
195
+ projectPath: string,
196
+ peerDependencies: {
197
+ [key: string]: string
198
+ }
199
+ ) {
200
+ const packageJSONPath = path.join(projectPath, 'package.json')
201
+ const packageJSONContents = JSON.parse(
202
+ await fs.promises.readFile(packageJSONPath, 'utf-8')
203
+ )
204
+ const updatedJSON = {
205
+ ...packageJSONContents,
206
+ peerDependencies: {
207
+ ...packageJSONContents.peerDependencies,
208
+ ...peerDependencies,
209
+ },
210
+ }
211
+ await fs.promises.writeFile(
212
+ packageJSONPath,
213
+ JSON.stringify(updatedJSON, null, 2),
214
+ 'utf-8'
215
+ )
216
+ }
217
+
218
+ export async function updateProjectEntries(
219
+ projectPath: string,
220
+ entries: {
221
+ [key: string]: string
222
+ }
223
+ ) {
224
+ return
225
+ const packageJSONPath = path.join(projectPath, 'package.json')
226
+ const packageJSONContents = JSON.parse(
227
+ await fs.promises.readFile(packageJSONPath, 'utf-8')
228
+ )
229
+ const updatedJSON = {
230
+ ...packageJSONContents,
231
+ targets: Object.fromEntries(
232
+ Object.entries(entries).map(([entryName, entryPath]) => [
233
+ entryName,
234
+ {
235
+ source: entryName + '.html',
236
+ },
237
+ ])
238
+ ),
239
+ }
240
+
241
+ await fs.promises.writeFile(
242
+ packageJSONPath,
243
+ JSON.stringify(updatedJSON, null, 2),
244
+ 'utf-8'
245
+ )
246
+ }
247
+
248
+ /**
249
+ * eg.
250
+ * loader!/private/tmp/tmp-build/packages/build-gulp-ORQ/node_modules/.pnpm/is-data@0.1.4/node_modules/is-data/index.ts => is-data/index.ts
251
+ */
252
+ export function cleanWebpackPath(filePath: string, installPath: string) {
253
+ // Webpack paths are of the form `loader!path`
254
+ let filePathReal = filePath.includes('!')
255
+ ? filePath.split('!')[filePath.split('!').length - 1]
256
+ : filePath
257
+ let fragments = filePathReal
258
+ .substring(filePathReal.indexOf(installPath) + installPath.length + 1)
259
+ .split(path.sep)
260
+ // let currentFragment = fragments[0]
261
+ // while (['node_modules', '.pnpm'].includes(currentFragment)) {
262
+ // currentFragment = fragments.shift() || ''
263
+ // }
264
+ return filePath //fragments.join(path.sep)
265
+ }
266
+
267
+ exports.cleanWebpackPath = cleanWebpackPath
268
+
269
+ export function isReactNativePackage(packageName: string) {
270
+ return packageName.startsWith('react-native')
271
+ }
272
+
273
+ export function printDiagnosticError(error: ThrowableDiagnostic) {
274
+ error.diagnostics.forEach(diagnostic => {
275
+ console.error(
276
+ ...[diagnostic.name, diagnostic.origin, diagnostic.message].filter(
277
+ Boolean
278
+ )
279
+ )
280
+ diagnostic.codeFrames?.forEach(codeFrame => {
281
+ codeFrame.codeHighlights.forEach(highlight => {
282
+ if (codeFrame.code) codeFrameColumns(codeFrame.code, highlight)
283
+ })
284
+ })
285
+ })
286
+ }
@@ -3,7 +3,6 @@ import traverse from '@babel/traverse'
3
3
  import path from 'path'
4
4
  import { promises as fs } from 'fs'
5
5
  import enhancedResolve from 'enhanced-resolve'
6
- import makeWebpackConfig from '../config/makeWebpackConfig'
7
6
  import {
8
7
  ArrayPattern,
9
8
  AssignmentPattern,
@@ -47,8 +46,8 @@ export function getExportsDetails(code: string) {
47
46
  result.push(property.value.name)
48
47
  }
49
48
  break
50
- // default:
51
- // assertUnreachable(property.type)
49
+ default:
50
+ assertUnreachable(property)
52
51
  }
53
52
  })
54
53
  }
@@ -73,8 +72,8 @@ export function getExportsDetails(code: string) {
73
72
  case 'MemberExpression':
74
73
  // unhandled
75
74
  break
76
- // default:
77
- // assertUnreachable(element.left.type)
75
+ default:
76
+ assertUnreachable(element.left)
78
77
  }
79
78
  }
80
79
 
@@ -109,13 +108,14 @@ export function getExportsDetails(code: string) {
109
108
  processAssignmentPattern(element, result)
110
109
  break
111
110
 
112
- // default:
113
- // assertUnreachable(element.type)
111
+ default:
112
+ assertUnreachable(element)
114
113
  }
115
114
  }
116
115
  })
117
116
  }
118
117
 
118
+ // @ts-ignore
119
119
  traverse(ast, {
120
120
  ExportNamedDeclaration(path) {
121
121
  const { specifiers, declaration } = path.node
@@ -148,8 +148,8 @@ export function getExportsDetails(code: string) {
148
148
  case 'TSParameterProperty':
149
149
  // unhandled
150
150
  break
151
- // default:
152
- // assertUnreachable(dec.id.type)
151
+ default:
152
+ assertUnreachable(dec.id)
153
153
  }
154
154
  })
155
155
  break
@@ -191,7 +191,16 @@ export function getExportsDetails(code: string) {
191
191
  }
192
192
  } else {
193
193
  specifiers.forEach(specifier => {
194
- exportsList.push(specifier.exported.name)
194
+ switch (specifier.exported.type) {
195
+ case 'Identifier':
196
+ exportsList.push(specifier.exported.name)
197
+ break
198
+
199
+ // The below case not be verified !!
200
+ case 'StringLiteral':
201
+ exportsList.push(specifier.exported.value)
202
+ break
203
+ }
195
204
  })
196
205
  }
197
206
  },
@@ -211,18 +220,21 @@ export function getExportsDetails(code: string) {
211
220
  }
212
221
  }
213
222
 
214
- const webpackConfig = makeWebpackConfig({
215
- packageName: '',
216
- entry: '',
217
- externals: { externalPackages: [], externalBuiltIns: [] },
218
- minifier: 'terser',
219
- })
220
-
221
223
  const resolver = enhancedResolve.create({
222
- extensions: webpackConfig?.resolve?.extensions,
223
- modules: webpackConfig?.resolve?.modules,
224
- // @ts-ignore Error due to unsynced types for enhanced resolve and webpack
225
- mainFields: webpackConfig?.resolve?.mainFields,
224
+ modules: ['node_modules'],
225
+ extensions: [
226
+ '.web.mjs',
227
+ '.mjs',
228
+ '.web.js',
229
+ '.js',
230
+ '.mjs',
231
+ '.json',
232
+ '.css',
233
+ '.sass',
234
+ '.scss',
235
+ ],
236
+ mainFields: ['browser', 'module', 'main', 'style'],
237
+ conditionNames: ['module', 'import', 'style', 'default'],
226
238
  })
227
239
 
228
240
  const resolve = async (context: string, path: string): Promise<string> =>
@@ -239,6 +251,7 @@ const resolve = async (context: string, path: string): Promise<string> =>
239
251
  type ResolvedExports = {
240
252
  [key: string]: string
241
253
  }
254
+
242
255
  /**
243
256
  * Recursively get all exports starting
244
257
  * from a given path
@@ -1,13 +1,14 @@
1
- import shortId from 'shortid'
2
1
  import rimraf from 'rimraf'
2
+ import shortId from 'shortid'
3
3
  import path from 'path'
4
4
  import { promises as fs } from 'fs'
5
5
  import sanitize from 'sanitize-filename'
6
+ import semver from 'semver'
6
7
 
7
8
  const debug = require('debug')('bp:worker')
8
9
  import { InstallError, PackageNotFoundError } from '../errors/CustomError'
9
- import { exec } from './common.utils'
10
- import config from '../config/config'
10
+ import { exec, parsePackageString } from './common.utils'
11
+ import config from '../config'
11
12
  import { InstallPackageOptions } from '../common.types'
12
13
  import Telemetry from './telemetry.utils'
13
14
  import { performance } from 'perf_hooks'
@@ -23,6 +24,7 @@ const InstallationUtils = {
23
24
  return path.join(
24
25
  config.tmp,
25
26
  'packages',
27
+
26
28
  sanitize(`build-${packageName}-${id}`)
27
29
  )
28
30
  },
@@ -32,6 +34,10 @@ const InstallationUtils = {
32
34
 
33
35
  await fs.mkdir(config.tmp, { recursive: true })
34
36
  await fs.mkdir(installPath, { recursive: true })
37
+ await fs.mkdir(path.join(installPath, '.git'), {
38
+ recursive: true,
39
+ })
40
+ await fs.writeFile(path.join(installPath, 'yarn.lock'), '')
35
41
 
36
42
  await fs.writeFile(
37
43
  path.join(installPath, 'package.json'),
@@ -56,6 +62,7 @@ const InstallationUtils = {
56
62
  ) {
57
63
  let flags, command
58
64
  let installStartTime = performance.now()
65
+ const { version } = parsePackageString(packageString)
59
66
 
60
67
  const {
61
68
  client = 'npm',
@@ -104,6 +111,7 @@ const InstallationUtils = {
104
111
  'ignore-scripts',
105
112
  'save-exact',
106
113
  'production',
114
+ 'legacy-peer-deps',
107
115
  'json',
108
116
  ]
109
117
 
@@ -111,11 +119,26 @@ const InstallationUtils = {
111
119
  isLocal ? wrapPackCommand(packageString) : packageString
112
120
  } ${additionalPackages.join(' ')} --${flags.join(' --')}`
113
121
  } else if (client === 'pnpm') {
114
- flags = ['no-optional', 'loglevel error', 'ignore-scripts', 'save-exact']
122
+ flags = [
123
+ 'no-optional',
124
+ 'loglevel error',
125
+ 'ignore-scripts',
126
+ 'save-exact',
127
+ `store-dir=${path.join(config.tmp, 'cache', 'pnpm-cache')}`,
128
+ `virtual-store-dir=${path.join(
129
+ config.tmp,
130
+ 'cache',
131
+ 'pnpm-cache-virtual'
132
+ )}`,
133
+ ]
134
+
135
+ if (semver.valid(version)) {
136
+ flags.push(`prefer-offline`)
137
+ }
115
138
 
116
139
  command = `pnpm add ${packageString} ${additionalPackages.join(
117
140
  ' '
118
- )} --${[].join(' --')}`
141
+ )} --${flags.join(' --')}`
119
142
  } else {
120
143
  console.error('No valid client specified')
121
144
  process.exit(1)
@@ -107,20 +107,6 @@ export default class Telemetry {
107
107
  })
108
108
  }
109
109
 
110
- static parseWebpackStats(
111
- packageName: string,
112
- isSuccessful: boolean,
113
- startTime: number,
114
- error: any = null
115
- ) {
116
- emitter.emit('TASK_PACKAGE_PARSE_WEBPACK_STATS', {
117
- package: { name: packageName },
118
- isSuccessful,
119
- duration: performance.now() - startTime,
120
- error: errorToObject(error),
121
- })
122
- }
123
-
124
110
  static dependencySizes(
125
111
  packageName: string,
126
112
  startTime: number,
@@ -137,13 +123,6 @@ export default class Telemetry {
137
123
  })
138
124
  }
139
125
 
140
- static assetsGZIPParseTime(packageName: string, startTime: number) {
141
- emitter.emit('TASK_PACKAGE_ASSETS_GZIP_PARSE_TIME', {
142
- package: { name: packageName },
143
- duration: performance.now() - startTime,
144
- })
145
- }
146
-
147
126
  static walkPackageExportsTree(
148
127
  packageString: string,
149
128
  startTime: number,
package/LICENSE DELETED
@@ -1,21 +0,0 @@
1
- MIT License
2
-
3
- Copyright (c) 2017 Shubham Kanodia
4
-
5
- Permission is hereby granted, free of charge, to any person obtaining a copy
6
- of this software and associated documentation files (the "Software"), to deal
7
- in the Software without restriction, including without limitation the rights
8
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
- copies of the Software, and to permit persons to whom the Software is
10
- furnished to do so, subject to the following conditions:
11
-
12
- The above copyright notice and this permission notice shall be included in all
13
- copies or substantial portions of the Software.
14
-
15
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
- SOFTWARE.
package/README.md DELETED
@@ -1,67 +0,0 @@
1
- <img src="https://img.shields.io/npm/v/package-build-stats.svg" /> <img src="https://img.shields.io/npm/l/package-build-stats.svg" /> <img src="https://img.shields.io/github/workflow/status/pastelsky/package-build-stats/CI/master"/>
2
-
3
- This is the function that powers the core of building, minifying and gzipping of packages in bundlephobia.
4
-
5
- ## Usage
6
-
7
- ```js
8
- const { getPackageStats } = require('package-build-stats')
9
- ```
10
-
11
- #### Building packages from npm
12
-
13
- ##### Building the latest stable version
14
-
15
- ```js
16
- const results = await getPackageStats('moment')
17
- ```
18
-
19
- ##### Building a specific version / tag
20
-
21
- ```js
22
- const results = await getPackageStats('moment@2.24.0')
23
- ```
24
-
25
- ##### Building local packages (beta)
26
-
27
- ```js
28
- const results = await getPackageStats('~/dev/my-npm-package') // must have a package.json
29
- ```
30
-
31
- #### Passing options to the build
32
-
33
- ```js
34
- const results = await getBuiltPackageStats('moment', options)
35
- ```
36
-
37
- ##### Options
38
-
39
- | Option | Values | Default | Description |
40
- | ------------------ | --------------------- | -------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------- |
41
- | client | `npm` or `yarn` | `npm` | Which client to use to install package for building |
42
- | limitConcurrency | `true` or `false` | `false` | When using `yarn` as the client, use the network mutex to limit concurrency |
43
- | networkConcurrency | `number` | `false` | When using `yarn` as client, limit simultaneous installs to this number. |
44
- | customImports | `Array<string>` | `null` | By default, the default export is used for calculating sizes. Setting this option allows calculation of package stats based on more granular top-level exports. |
45
- | minifier | `terser` or `esbuild` | `terser` | ESbuild is faster, albeit with marginally larger file sizes |
46
- | installTimeout | number (ms) | 30000 | Timeout for package install |
47
-
48
- ## Listening to events
49
-
50
- `package-build-stats` emits various lifecycle events when building a package.
51
- You can listen to these events by subscribing to the event emitter (based on [mitt](https://github.com/developit/mitt)).
52
-
53
- ```js
54
- import { eventQueue } from 'package-build-stats'
55
-
56
- // Listen to all events
57
- eventQueue.on('*', callback)
58
-
59
- // Listen to specific events
60
- eventQueue.on('TASK_PACKAGE_BUILD', callback)
61
- ```
62
-
63
- For a list of all events, see [this](src/utils/telemetry.utils.ts).
64
-
65
- ## Contributing
66
-
67
- See [contributing guide.](CONTRIBUTING.md)
@@ -1,34 +0,0 @@
1
- declare type Minifier = 'esbuild' | 'terser';
2
- declare type AllOptions = {
3
- customImports?: Array<string>;
4
- splitCustomImports?: boolean;
5
- debug?: boolean;
6
- calcParse?: boolean;
7
- esm?: boolean;
8
- entryFilename?: string;
9
- client?: 'npm' | 'yarn';
10
- limitConcurrency?: boolean;
11
- networkConcurrency?: number;
12
- additionalPackages?: Array<string>;
13
- isLocal?: boolean;
14
- installTimeout?: number;
15
- };
16
- export declare type BuildPackageOptions = Pick<AllOptions, 'customImports' | 'splitCustomImports' | 'debug' | 'calcParse'> & {
17
- includeDependencySizes: boolean;
18
- minifier: Minifier;
19
- };
20
- export declare type CreateEntryPointOptions = Pick<AllOptions, 'esm' | 'customImports' | 'entryFilename'>;
21
- export declare type InstallPackageOptions = Pick<AllOptions, 'client' | 'limitConcurrency' | 'networkConcurrency' | 'additionalPackages' | 'isLocal' | 'installTimeout'>;
22
- export declare type GetPackageStatsOptions = Pick<AllOptions, 'client' | 'limitConcurrency' | 'networkConcurrency' | 'debug' | 'customImports' | 'installTimeout'> & {
23
- minifier?: Minifier;
24
- };
25
- export declare type Externals = {
26
- externalPackages: Array<string>;
27
- externalBuiltIns: Array<string>;
28
- };
29
- export declare type WebpackError = {
30
- name: 'ModuleNotFoundError';
31
- details?: string;
32
- error: Error;
33
- };
34
- export {};
@@ -1,2 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
@@ -1,4 +0,0 @@
1
- declare const _default: {
2
- tmp: string;
3
- };
4
- export default _default;
@@ -1,10 +0,0 @@
1
- "use strict";
2
- // Use ES6 supported by Node v6.10 only!
3
- var __importDefault = (this && this.__importDefault) || function (mod) {
4
- return (mod && mod.__esModule) ? mod : { "default": mod };
5
- };
6
- Object.defineProperty(exports, "__esModule", { value: true });
7
- const path_1 = __importDefault(require("path"));
8
- exports.default = {
9
- tmp: path_1.default.join('/tmp', 'tmp-build'),
10
- };
@@ -1,11 +0,0 @@
1
- import webpack, { Entry } from 'webpack';
2
- import { Externals } from '../common.types';
3
- declare type MakeWebpackConfigOptions = {
4
- packageName: string;
5
- externals: Externals;
6
- debug?: boolean;
7
- entry: string | string[] | Entry;
8
- minifier: 'esbuild' | 'terser';
9
- };
10
- export default function makeWebpackConfig({ packageName, entry, externals, debug, minifier, }: MakeWebpackConfigOptions): webpack.Configuration;
11
- export {};