-
Notifications
You must be signed in to change notification settings - Fork 245
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(jsii): enforce peer dependencies (#294)
If a jsii module exposes a type from a dependency in it's public API, jsii now enforces that this dependency is also defined as a "peer" instead of a normal dependency. This tells npm that if a user of this module already installed a compatible verison of this dependency in their closure, npm will pick the one installed by the user (as a peer) instead of fetching another version. jsii will also flag these dependencies as "peer" in the jsii spec. At the moment, this won't have implications on generated language packages, but in environments that have support for peer dependencies, we should make sure the module's metadata reflects this idea as well. A utility called "jsii-fix-peers" is included. It will inspect .jsii and package.json and will add "peerDependencies" to package.json for all dependencies that have types in the public API. Related to aws/aws-cdk#979
- Loading branch information
Elad Ben-Israel
authored
Nov 6, 2018
1 parent
4d135cf
commit 1753910
Showing
17 changed files
with
221 additions
and
28 deletions.
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
#!/usr/bin/env node | ||
require('./jsii-fix-peers.js'); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,95 @@ | ||
// | ||
// jsii-fix-peers | ||
// | ||
// Inspects the local .jsii file and adds "peerDependencies" to the local | ||
// package.json for all modules that include types that are referenced as part | ||
// of the current module's public API. | ||
// | ||
// This resolves all peer dependency warnings emitted by the jsii compiler. | ||
// | ||
|
||
// tslint:disable:no-console | ||
|
||
import fs = require('fs-extra'); | ||
import spec = require('jsii-spec'); | ||
|
||
fixPeers().catch(e => { | ||
console.error(e.stack); | ||
process.exit(1); | ||
}); | ||
|
||
async function fixPeers() { | ||
const jsiiFile = './.jsii'; | ||
const pkgFile = './package.json'; | ||
|
||
if (!(await fs.pathExists(jsiiFile))) { | ||
throw new Error(`Cannot find '${jsiiFile}. Make sure to compile first`); | ||
} | ||
|
||
if (!(await fs.pathExists(pkgFile))) { | ||
throw new Error(`Cannot find '${pkgFile}' in current working directory`); | ||
} | ||
|
||
const jsii = await fs.readJson(jsiiFile) as spec.Assembly; | ||
const pkg = await fs.readJson(pkgFile); | ||
|
||
// find all type references (FQNs) in the assembly. | ||
const fqns = findAllFQNs(jsii); | ||
|
||
let updated = false; | ||
|
||
// read "dependencies" and "peerDependencies" from package.json | ||
if (!pkg.peerDependencies) { pkg.peerDependencies = {}; } | ||
const peers = pkg.peerDependencies; | ||
const deps = pkg.dependencies || {}; | ||
|
||
// iterate over all FQNs and ensure that all referenced modules appear as peer dependencies | ||
for (const fqn of fqns) { | ||
const [ module, ] = fqn.split('.'); | ||
if (module === jsii.name) { | ||
continue; | ||
} | ||
|
||
// verify that `module` exists in peerDependencies | ||
if (module in peers) { | ||
continue; | ||
} | ||
|
||
// fetch the module's version requirement from "dependencies" (we expect it to be there) | ||
const dep = deps[module]; | ||
if (!dep) { | ||
throw new Error(`Cannot find ${module} neither under "peerDependencies" nor "dependencies". Can't fix.`); | ||
} | ||
|
||
// fixing time! add this module to "peerDependencies" | ||
peers[module] = dep; | ||
console.log(`added ${module}@${dep} to "peerDependencies"`); | ||
updated = true; | ||
} | ||
|
||
if (updated) { | ||
await fs.writeJson(pkgFile, pkg, { spaces: 2 }); | ||
} | ||
} | ||
|
||
/** | ||
* Looks up all { "fqn": "boom" } objects in a JSON tree. | ||
* @param node Initial node (i.e. a JSII assembly) | ||
* @param out Used by the recursive call to collect outputs | ||
*/ | ||
function findAllFQNs(node: any, out = new Set<string>()) { | ||
if (typeof(node) === 'object' && 'fqn' in node) { | ||
out.add(node.fqn); | ||
} | ||
|
||
for (const key of Object.keys(node)) { | ||
const value = node[key]; | ||
if (Array.isArray(value)) { | ||
value.forEach(v => findAllFQNs(v, out)); | ||
} else if (typeof(value) === 'object') { | ||
findAllFQNs(value, out); | ||
} | ||
} | ||
|
||
return Array.from(out); | ||
} |
Oops, something went wrong.