Skip to content

Commit

Permalink
feat(compartment-mapper): support various types of optional deps
Browse files Browse the repository at this point in the history
  • Loading branch information
kumavis committed Nov 10, 2022
1 parent 3afd7c5 commit 72fa6e7
Show file tree
Hide file tree
Showing 11 changed files with 245 additions and 9 deletions.
44 changes: 36 additions & 8 deletions packages/compartment-mapper/src/node-modules.js
Expand Up @@ -252,27 +252,49 @@ const graphPackage = async (
graph[packageLocation] = /** @type {Node} */ (result);

/** @type {Record<string, string>} */
const dependencies = {};
const dependencyLocations = {};
const children = [];
const predicates = packageDescriptor.dependencies || {};
assign(predicates, packageDescriptor.peerDependencies || {});
assign(predicates, packageDescriptor.bundleDependencies || {});
const optionals = new Set();
const {
dependencies = {},
peerDependencies = {},
peerDependenciesMeta = {},
bundleDependencies = {},
optionalDependencies = {},
devDependencies = {},
} = packageDescriptor;
const allDependencies = {};
assign(allDependencies, dependencies);
assign(allDependencies, peerDependencies);
for (const [name, { optional }] of Object.entries(peerDependenciesMeta)) {
if (optional) {
optionals.add(name);
}
}
assign(allDependencies, bundleDependencies);
assign(allDependencies, optionalDependencies);
Object.keys(optionalDependencies).forEach(name => {
optionals.add(name);
});

if (dev) {
assign(predicates, packageDescriptor.devDependencies || {});
assign(allDependencies, devDependencies);
}
for (const name of keys(predicates).sort()) {

for (const name of keys(allDependencies).sort()) {
const optional = optionals.has(name);
children.push(
// Mutual recursion ahead:
// eslint-disable-next-line no-use-before-define
gatherDependency(
readDescriptor,
canonical,
graph,
dependencies,
dependencyLocations,
packageLocation,
name,
tags,
optional,
),
);
}
Expand All @@ -294,7 +316,7 @@ const graphPackage = async (
label: `${name}${version ? `-v${version}` : ''}`,
explicit: exports !== undefined,
exports: inferExports(packageDescriptor, tags, types),
dependencies,
dependencies: dependencyLocations,
types,
parsers: inferParsers(packageDescriptor, packageLocation),
});
Expand All @@ -320,6 +342,7 @@ const graphPackage = async (
* @param {string} packageLocation - location of the package of interest.
* @param {string} name - name of the package of interest.
* @param {Set<string>} tags
* @param {boolean} optional - whether the dependency is optional
*/
const gatherDependency = async (
readDescriptor,
Expand All @@ -329,6 +352,7 @@ const gatherDependency = async (
packageLocation,
name,
tags,
optional = false,
) => {
const dependency = await findPackage(
readDescriptor,
Expand All @@ -337,6 +361,10 @@ const gatherDependency = async (
name,
);
if (dependency === undefined) {
// allow the dependency to be missing if optional
if (optional) {
return;
}
throw new Error(`Cannot find dependency ${name} for ${packageLocation}`);
}
dependencies[name] = dependency.packageLocation;
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

10 changes: 9 additions & 1 deletion packages/compartment-mapper/test/scaffold.js
Expand Up @@ -53,10 +53,18 @@ export function scaffold(
fixture,
assertFixture,
fixtureAssertionCount,
{ onError, shouldFailBeforeArchiveOperations = false } = {},
{
onError,
shouldFailBeforeArchiveOperations = false,
knownFailure = false,
} = {},
) {
// wrapping each time allows for convenient use of test.only
const wrap = (testFunc, testCategoryHint) => (title, implementation) => {
// mark as known failure if available (but fallback to support test.only)
if (knownFailure) {
testFunc = testFunc.failing || testFunc;
}
return testFunc(title, async t => {
let namespace;
try {
Expand Down
78 changes: 78 additions & 0 deletions packages/compartment-mapper/test/test-optional.js
@@ -0,0 +1,78 @@
// import "./ses-lockdown.js";
import 'ses';
import test from 'ava';
import { scaffold } from './scaffold.js';

const fixtureOptionalDepsEsm = new URL(
'fixtures-optional/node_modules/optional-esm/index.js',
import.meta.url,
).toString();

const fixtureOptionalDepsCjs = new URL(
'fixtures-optional/node_modules/optional-cjs/index.js',
import.meta.url,
).toString();

scaffold(
'optionalDependencies/esm',
// this test fails because it relies on dynamic import
test,
fixtureOptionalDepsEsm,
async (t, { namespace }) => {
const { tryOptionalDeps } = namespace;
const result = await tryOptionalDeps();
t.deepEqual(
Reflect.ownKeys(result.exports),
['alpha', 'beta'],
'expected exports',
);
t.deepEqual(
Reflect.ownKeys(result.errors),
['one', 'two'],
'expected errors',
);
t.true(
result.errors.one.message.startsWith(
`Cannot find external module "missing-one" in package`,
),
);
t.true(
result.errors.two.message.startsWith(
`Cannot find external module "missing-two" in package`,
),
);
},
4,
{ knownFailure: true },
);

scaffold(
'optionalDependencies/cjs',
test,
fixtureOptionalDepsCjs,
(t, { namespace }) => {
const { tryOptionalDeps } = namespace;
const result = tryOptionalDeps();
t.deepEqual(
Reflect.ownKeys(result.exports),
['alpha', 'beta'],
'expected exports',
);
t.deepEqual(
Reflect.ownKeys(result.errors),
['one', 'two'],
'expected errors',
);
t.true(
result.errors.one.message.startsWith(
`Cannot find external module "missing-one" in package`,
),
);
t.true(
result.errors.two.message.startsWith(
`Cannot find external module "missing-two" in package`,
),
);
},
4,
);

0 comments on commit 72fa6e7

Please sign in to comment.