Skip to content

Commit 5737c33

Browse files
authoredDec 6, 2021
fix(lambda-nodejs): bundling fails with a file dependency in nodeModules (#17851)
If the dependency version is a `file:`, find its absolute path so that we can install it in the temporary bundling folder. Closes #17830 ---- *By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license*
1 parent 86e7780 commit 5737c33

File tree

4 files changed

+47
-12
lines changed

4 files changed

+47
-12
lines changed
 

‎packages/@aws-cdk/aws-lambda-nodejs/lib/package-installation.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { spawnSync } from 'child_process';
2-
import { tryGetModuleVersion } from './util';
2+
import { tryGetModuleVersionFromRequire } from './util';
33

44
/**
55
* Package installation
@@ -8,7 +8,7 @@ export abstract class PackageInstallation {
88
public static detect(module: string): PackageInstallation | undefined {
99
try {
1010
// Check local version first
11-
const version = tryGetModuleVersion(module);
11+
const version = tryGetModuleVersionFromRequire(module);
1212
if (version) {
1313
return {
1414
isLocal: true,

‎packages/@aws-cdk/aws-lambda-nodejs/lib/util.ts

+27-8
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ export function exec(cmd: string, args: string[], options?: SpawnSyncOptions) {
7373
/**
7474
* Returns a module version by requiring its package.json file
7575
*/
76-
export function tryGetModuleVersion(mod: string): string | undefined {
76+
export function tryGetModuleVersionFromRequire(mod: string): string | undefined {
7777
try {
7878
// eslint-disable-next-line @typescript-eslint/no-require-imports
7979
return require(`${mod}/package.json`).version;
@@ -82,6 +82,30 @@ export function tryGetModuleVersion(mod: string): string | undefined {
8282
}
8383
}
8484

85+
/**
86+
* Gets module version from package.json content
87+
*/
88+
export function tryGetModuleVersionFromPkg(mod: string, pkgJson: { [key: string]: any }, pkgPath: string): string | undefined {
89+
const dependencies = {
90+
...pkgJson.dependencies ?? {},
91+
...pkgJson.devDependencies ?? {},
92+
...pkgJson.peerDependencies ?? {},
93+
};
94+
95+
if (!dependencies[mod]) {
96+
return undefined;
97+
}
98+
99+
// If it's a "file:" version, make it absolute
100+
const fileMatch = dependencies[mod].match(/file:(.+)/);
101+
if (fileMatch && !path.isAbsolute(fileMatch[1])) {
102+
const absoluteFilePath = path.join(path.dirname(pkgPath), fileMatch[1]);
103+
return `file:${absoluteFilePath}`;
104+
};
105+
106+
return dependencies[mod];
107+
}
108+
85109
/**
86110
* Extract versions for a list of modules.
87111
*
@@ -94,14 +118,9 @@ export function extractDependencies(pkgPath: string, modules: string[]): { [key:
94118
// Use require for cache
95119
const pkgJson = require(pkgPath); // eslint-disable-line @typescript-eslint/no-require-imports
96120

97-
const pkgDependencies = {
98-
...pkgJson.dependencies ?? {},
99-
...pkgJson.devDependencies ?? {},
100-
...pkgJson.peerDependencies ?? {},
101-
};
102-
103121
for (const mod of modules) {
104-
const version = pkgDependencies[mod] ?? tryGetModuleVersion(mod);
122+
const version = tryGetModuleVersionFromPkg(mod, pkgJson, pkgPath)
123+
?? tryGetModuleVersionFromRequire(mod);
105124
if (!version) {
106125
throw new Error(`Cannot extract version for module '${mod}'. Check that it's referenced in your package.json or installed.`);
107126
}

‎packages/@aws-cdk/aws-lambda-nodejs/test/package-installation.test.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ test('detects local version', () => {
1313
});
1414

1515
test('checks global version if local detection fails', () => {
16-
const getModuleVersionMock = jest.spyOn(util, 'tryGetModuleVersion').mockReturnValue(undefined);
16+
const getModuleVersionMock = jest.spyOn(util, 'tryGetModuleVersionFromRequire').mockReturnValue(undefined);
1717
const spawnSyncMock = jest.spyOn(child_process, 'spawnSync').mockReturnValue({
1818
status: 0,
1919
stderr: Buffer.from('stderr'),
@@ -33,7 +33,7 @@ test('checks global version if local detection fails', () => {
3333
});
3434

3535
test('returns undefined on error', () => {
36-
const getModuleVersionMock = jest.spyOn(util, 'tryGetModuleVersion').mockReturnValue(undefined);
36+
const getModuleVersionMock = jest.spyOn(util, 'tryGetModuleVersionFromRequire').mockReturnValue(undefined);
3737
const spawnSyncMock = jest.spyOn(child_process, 'spawnSync').mockReturnValue({
3838
error: new Error('bad error'),
3939
status: 0,

‎packages/@aws-cdk/aws-lambda-nodejs/test/util.test.ts

+16
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import * as child_process from 'child_process';
2+
import * as fs from 'fs';
23
import * as path from 'path';
34
import { callsites, exec, extractDependencies, findUp } from '../lib/util';
45

@@ -119,4 +120,19 @@ describe('extractDependencies', () => {
119120
['unknown'],
120121
)).toThrow(/Cannot extract version for module 'unknown'/);
121122
});
123+
124+
test('with file dependency', () => {
125+
const pkgPath = path.join(__dirname, 'package-file.json');
126+
fs.writeFileSync(pkgPath, JSON.stringify({
127+
dependencies: {
128+
'my-module': 'file:../../core',
129+
},
130+
}));
131+
132+
expect(extractDependencies(pkgPath, ['my-module'])).toEqual({
133+
'my-module': expect.stringMatching(/aws-cdk\/packages\/@aws-cdk\/core/),
134+
});
135+
136+
fs.unlinkSync(pkgPath);
137+
});
122138
});

0 commit comments

Comments
 (0)
Please sign in to comment.