11import path from 'node:path' ;
22import { readFile , writeFile , stat , readdir } from 'node:fs/promises' ;
3+ import { createRequire } from 'node:module' ;
4+ import { fileURLToPath } from 'node:url' ;
35import prettier from 'prettier' ;
46import { BUNDLED_DEPENDENCIES } from '../shared/bundled-dependencies.js' ;
57
8+ const require = createRequire ( import . meta. url ) ;
9+
10+ const atLwcPackages = ( await readdir ( 'packages/@lwc' ) )
11+ // skip dotfiles like .DS_Store
12+ . filter ( ( _ ) => ! _ . startsWith ( '.' ) )
13+ . map ( ( _ ) => `@lwc/${ _ } ` ) ;
14+
615// Generate our LICENSE files for each package, including any bundled dependencies
716// This is modeled after how Rollup does it:
817// https://github.com/rollup/rollup/blob/0b665c3/build-plugins/generate-license-file.ts
@@ -17,14 +26,43 @@ async function exists(filename) {
1726 }
1827}
1928
29+ /**
30+ * Tries `require.resolve` with additional paths (`packages/@lwc/___/node_modules`)
31+ * and `import.meta.resolve` (unmodified) to find a package's entrypoint.
32+ */
33+ function tryResolve ( specifier ) {
34+ try {
35+ // As far as I can tell, there's no way to modify the `import` lookup paths
36+ return fileURLToPath ( import . meta. resolve ( specifier ) ) ;
37+ } catch ( err ) {
38+ // We expect to see missing packages, but throw other errors
39+ if ( err . code !== 'ERR_MODULE_NOT_FOUND' ) {
40+ throw err ;
41+ }
42+ }
43+ // `require.resolve` accepts a second parameter of additional places to look
44+ return require . resolve ( specifier , {
45+ paths : atLwcPackages . map ( ( pkg ) => path . join ( 'packages' , pkg , 'node_modules' ) ) ,
46+ } ) ;
47+ }
48+
49+ /**
50+ * Finds a dependency in our monorepo.
51+ * @param {string } specifier - package name to find
52+ */
53+ function findPackageDirectory ( specifier ) {
54+ const resolved = tryResolve ( specifier ) ;
55+ // An import can resolve to a nested directory, e.g. dist/index.js. We want the package
56+ // root, which will always be the last node_modules/${specifier}.
57+ const lookup = path . join ( '/node_modules' , specifier ) ;
58+ return resolved . slice ( 0 , resolved . lastIndexOf ( lookup ) + lookup . length ) ;
59+ }
60+
2061async function findLicenseText ( depName ) {
2162 // Iterate through possible names for the license file
2263 const names = [ 'LICENSE' , 'LICENSE.md' , 'LICENSE.txt' ] ;
2364
24- // We would use require.resolve, but 1) that doesn't work if the module lacks a "main" in its `package.json`,
25- // and 2) it gives us a deep `./path/to/index.js` which makes it harder to find a top-level LICENSE file. So
26- // just assume that our deps are hoisted to the top-level `node_modules`.
27- const resolvedDepPath = path . join ( process . cwd ( ) , 'node_modules' , depName ) ;
65+ const resolvedDepPath = findPackageDirectory ( depName ) ;
2866
2967 for ( const name of names ) {
3068 const fullFilePath = path . join ( resolvedDepPath , name ) ;
@@ -34,9 +72,9 @@ async function findLicenseText(depName) {
3472 }
3573
3674 // Get the license from the package.json if we can't find it elsewhere
37- const pkgJson = JSON . parse ( await readFile ( path . join ( resolvedDepPath , 'package.json' ) , 'utf-8' ) ) ;
38-
39- const { license , version } = pkgJson ;
75+ const { license , version } = JSON . parse (
76+ await readFile ( path . join ( resolvedDepPath , 'package.json' ) , 'utf-8' )
77+ ) ;
4078
4179 return `${ license } license defined in package.json in v${ version } .` ;
4280}
@@ -65,10 +103,7 @@ const shouldWarnChanges =
65103await writeFile ( 'LICENSE.md' , formattedLicense , 'utf-8' ) ;
66104
67105// License file for each package as well, so that we publish it to npm
68- const atLwcPackages = ( await readdir ( 'packages/@lwc' ) )
69- // skip dotfiles like .DS_Store
70- . filter ( ( _ ) => ! _ . startsWith ( '.' ) )
71- . map ( ( _ ) => `@lwc/${ _ } ` ) ;
106+
72107const packages = [ 'lwc' , ...atLwcPackages ] ;
73108
74109await Promise . all (
0 commit comments