Skip to content

Commit

Permalink
fix(lambda-nodejs): bundling fails with a file dependency in `nodeMod…
Browse files Browse the repository at this point in the history
…ules` (#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*
  • Loading branch information
jogold committed Dec 6, 2021
1 parent 86e7780 commit 5737c33
Show file tree
Hide file tree
Showing 4 changed files with 47 additions and 12 deletions.
@@ -1,5 +1,5 @@
import { spawnSync } from 'child_process';
import { tryGetModuleVersion } from './util';
import { tryGetModuleVersionFromRequire } from './util';

/**
* Package installation
Expand All @@ -8,7 +8,7 @@ export abstract class PackageInstallation {
public static detect(module: string): PackageInstallation | undefined {
try {
// Check local version first
const version = tryGetModuleVersion(module);
const version = tryGetModuleVersionFromRequire(module);
if (version) {
return {
isLocal: true,
Expand Down
35 changes: 27 additions & 8 deletions packages/@aws-cdk/aws-lambda-nodejs/lib/util.ts
Expand Up @@ -73,7 +73,7 @@ export function exec(cmd: string, args: string[], options?: SpawnSyncOptions) {
/**
* Returns a module version by requiring its package.json file
*/
export function tryGetModuleVersion(mod: string): string | undefined {
export function tryGetModuleVersionFromRequire(mod: string): string | undefined {
try {
// eslint-disable-next-line @typescript-eslint/no-require-imports
return require(`${mod}/package.json`).version;
Expand All @@ -82,6 +82,30 @@ export function tryGetModuleVersion(mod: string): string | undefined {
}
}

/**
* Gets module version from package.json content
*/
export function tryGetModuleVersionFromPkg(mod: string, pkgJson: { [key: string]: any }, pkgPath: string): string | undefined {
const dependencies = {
...pkgJson.dependencies ?? {},
...pkgJson.devDependencies ?? {},
...pkgJson.peerDependencies ?? {},
};

if (!dependencies[mod]) {
return undefined;
}

// If it's a "file:" version, make it absolute
const fileMatch = dependencies[mod].match(/file:(.+)/);
if (fileMatch && !path.isAbsolute(fileMatch[1])) {
const absoluteFilePath = path.join(path.dirname(pkgPath), fileMatch[1]);
return `file:${absoluteFilePath}`;
};

return dependencies[mod];
}

/**
* Extract versions for a list of modules.
*
Expand All @@ -94,14 +118,9 @@ export function extractDependencies(pkgPath: string, modules: string[]): { [key:
// Use require for cache
const pkgJson = require(pkgPath); // eslint-disable-line @typescript-eslint/no-require-imports

const pkgDependencies = {
...pkgJson.dependencies ?? {},
...pkgJson.devDependencies ?? {},
...pkgJson.peerDependencies ?? {},
};

for (const mod of modules) {
const version = pkgDependencies[mod] ?? tryGetModuleVersion(mod);
const version = tryGetModuleVersionFromPkg(mod, pkgJson, pkgPath)
?? tryGetModuleVersionFromRequire(mod);
if (!version) {
throw new Error(`Cannot extract version for module '${mod}'. Check that it's referenced in your package.json or installed.`);
}
Expand Down
Expand Up @@ -13,7 +13,7 @@ test('detects local version', () => {
});

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

test('returns undefined on error', () => {
const getModuleVersionMock = jest.spyOn(util, 'tryGetModuleVersion').mockReturnValue(undefined);
const getModuleVersionMock = jest.spyOn(util, 'tryGetModuleVersionFromRequire').mockReturnValue(undefined);
const spawnSyncMock = jest.spyOn(child_process, 'spawnSync').mockReturnValue({
error: new Error('bad error'),
status: 0,
Expand Down
16 changes: 16 additions & 0 deletions packages/@aws-cdk/aws-lambda-nodejs/test/util.test.ts
@@ -1,4 +1,5 @@
import * as child_process from 'child_process';
import * as fs from 'fs';
import * as path from 'path';
import { callsites, exec, extractDependencies, findUp } from '../lib/util';

Expand Down Expand Up @@ -119,4 +120,19 @@ describe('extractDependencies', () => {
['unknown'],
)).toThrow(/Cannot extract version for module 'unknown'/);
});

test('with file dependency', () => {
const pkgPath = path.join(__dirname, 'package-file.json');
fs.writeFileSync(pkgPath, JSON.stringify({
dependencies: {
'my-module': 'file:../../core',
},
}));

expect(extractDependencies(pkgPath, ['my-module'])).toEqual({
'my-module': expect.stringMatching(/aws-cdk\/packages\/@aws-cdk\/core/),
});

fs.unlinkSync(pkgPath);
});
});

0 comments on commit 5737c33

Please sign in to comment.