Skip to content

Commit

Permalink
fix(pacmak): fails on bundled dependency without entry point (#3277)
Browse files Browse the repository at this point in the history
`projen` uses a bundled dependency called `shx`, and this library does
not have an entry point. It exposes some command-line tools and nothing
else.

This conflicts with our dependency finding mechanism, which performs
a `require()` on the library to find it.

Ignore bundled dependencies in `pacmak`, it never needs to pack them
individually anyway.


Fixes #3275.

---

By submitting this pull request, I confirm that my contribution is made under the terms of the [Apache 2.0 license].

[Apache 2.0 license]: https://www.apache.org/licenses/LICENSE-2.0
  • Loading branch information
rix0rrr authored Dec 22, 2021
1 parent 1fd2644 commit 6e5a0b5
Show file tree
Hide file tree
Showing 2 changed files with 97 additions and 1 deletion.
10 changes: 9 additions & 1 deletion packages/jsii-pacmak/lib/dependency-graph.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,8 @@ export interface TraverseDependencyGraphHost {
export interface PackageJson {
readonly dependencies?: { readonly [name: string]: string };
readonly peerDependencies?: { readonly [name: string]: string };
readonly bundleDependencies?: string[];
readonly bundledDependencies?: string[];

readonly [key: string]: unknown;
}
Expand Down Expand Up @@ -88,7 +90,13 @@ async function real$traverseDependencyGraph(
]);
return Promise.all(
Array.from(deps)
.filter((m) => !util.isBuiltinModule(m))
// No need to pacmak the dependency if it's built-in, or if it's bundled
.filter(
(m) =>
!util.isBuiltinModule(m) &&
!meta.bundledDependencies?.includes(m) &&
!meta.bundleDependencies?.includes(m),
)
.map(async (dep) => {
const dependencyDir = await host.findDependencyDirectory(
dep,
Expand Down
88 changes: 88 additions & 0 deletions packages/jsii-pacmak/test/dependency-graph.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -113,3 +113,91 @@ test('stops traversing when callback returns false', async () => {
expect(mockHost.readJson).toHaveBeenCalledTimes(2);
expect(mockHost.findDependencyDirectory).toHaveBeenCalledTimes(1);
});

test('dont call findDependencyDirectory for bundledDependencies', async () => {
const packages: Record<string, { root: string; meta: any }> = {
A: {
root: join(tmpdir(), 'A'),
meta: { dependencies: { B: '*' }, bundledDependencies: ['B'] },
},
};

const cb: Callback = jest.fn().mockName('callback').mockReturnValue(true);

fakeReadJson(packages);

// WHEN
await expect(
traverseDependencyGraph(packages.A.root, cb, mockHost),
).resolves.not.toThrow();

// THEN
expect(mockHost.findDependencyDirectory).not.toHaveBeenCalled();
});

test('dont call findDependencyDirectory for bundleDependencies', async () => {
const packages: Record<string, { root: string; meta: any }> = {
A: {
root: join(tmpdir(), 'A'),
meta: { dependencies: { B: '*' }, bundleDependencies: ['B'] },
},
};

const cb: Callback = jest.fn().mockName('callback').mockReturnValue(true);

fakeReadJson(packages);

// WHEN
await expect(
traverseDependencyGraph(packages.A.root, cb, mockHost),
).resolves.not.toThrow();

// THEN
expect(mockHost.findDependencyDirectory).not.toHaveBeenCalled();
});

test('dont call findDependencyDirectory for bundleDependencies AND bundledDependencies', async () => {
const packages: Record<string, { root: string; meta: any }> = {
A: {
root: join(tmpdir(), 'A'),
meta: {
dependencies: { B: '*', C: '*' },
bundleDependencies: ['B'],
bundledDependencies: ['C'],
},
},
};

const cb: Callback = jest.fn().mockName('callback').mockReturnValue(true);

fakeReadJson(packages);

// WHEN
await expect(
traverseDependencyGraph(packages.A.root, cb, mockHost),
).resolves.not.toThrow();

// THEN
expect(mockHost.findDependencyDirectory).not.toHaveBeenCalled();
});

function fakeReadJson(
fakePackages: Record<string, { root: string; meta: any }>,
) {
mockHost.readJson.mockImplementation((file) => {
const result = Object.values(fakePackages).find(
({ root }) => file === join(root, 'package.json'),
)?.meta;
return result != null
? Promise.resolve(result)
: Promise.reject(new Error(`Unexpected file access: ${file}`));
});

mockHost.findDependencyDirectory.mockImplementation(async (dep, _dir) => {
const result = fakePackages[dep]?.root;
if (result == null) {
throw new Error(`Unknown dependency: ${dep}`);
}
return result;
});
}

0 comments on commit 6e5a0b5

Please sign in to comment.