Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 5 additions & 26 deletions packages/@aws-cdk/aws-lambda-nodejs/lib/function.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { Construct } from 'constructs';
import { Bundling } from './bundling';
import { LockFile } from './package-manager';
import { BundlingOptions } from './types';
import { callsites, findUpMultiple } from './util';
import { callsites, findDefiningFile, findUpMultiple } from './util';

/**
* Properties for a NodejsFunction
Expand Down Expand Up @@ -168,44 +168,23 @@ function findEntry(id: string, entry?: string): string {
return entry;
}

const definingFile = findDefiningFile();
const definingFile = findDefiningFile(callsites());
const extname = path.extname(definingFile);

const tsHandlerFile = definingFile.replace(new RegExp(`${extname}$`), `.${id}.ts`);
const tsHandlerFile = definingFile.replace(new RegExp(`${extname}$`), `.${id}.ts`).replace('file://', '');
if (fs.existsSync(tsHandlerFile)) {
return tsHandlerFile;
}

const jsHandlerFile = definingFile.replace(new RegExp(`${extname}$`), `.${id}.js`);
const jsHandlerFile = definingFile.replace(new RegExp(`${extname}$`), `.${id}.js`).replace('file://', '');
if (fs.existsSync(jsHandlerFile)) {
return jsHandlerFile;
}

const mjsHandlerFile = definingFile.replace(new RegExp(`${extname}$`), `.${id}.mjs`);
const mjsHandlerFile = definingFile.replace(new RegExp(`${extname}$`), `.${id}.mjs`).replace('file://', '');
if (fs.existsSync(mjsHandlerFile)) {
return mjsHandlerFile;
}

throw new Error(`Cannot find handler file ${tsHandlerFile}, ${jsHandlerFile} or ${mjsHandlerFile}`);
}

/**
* Finds the name of the file where the `NodejsFunction` is defined
*/
function findDefiningFile(): string {
let definingIndex;
const sites = callsites();
for (const [index, site] of sites.entries()) {
if (site.getFunctionName() === 'NodejsFunction') {
// The next site is the site where the NodejsFunction was created
definingIndex = index + 1;
break;
}
}

if (!definingIndex || !sites[definingIndex]) {
throw new Error('Cannot find defining file.');
}

return sites[definingIndex].getFileName();
}
21 changes: 21 additions & 0 deletions packages/@aws-cdk/aws-lambda-nodejs/lib/util.ts
Original file line number Diff line number Diff line change
Expand Up @@ -208,3 +208,24 @@ function extractTsConfig(tsconfigPath: string, previousCompilerOptions?: Record<
}
return updatedCompilerOptions;
}


/**
* Finds the name of the file where the `NodejsFunction` is defined
*/
export function findDefiningFile(sites: CallSite[]): string {
let definingIndex;
for (const [index, site] of sites.entries()) {
if (site.getFunctionName() === 'NodejsFunction') {
// The next site is the site where the NodejsFunction was created
definingIndex = index + 1;
break;
}
}

if (!definingIndex || !sites[definingIndex]) {
throw new Error('Cannot find defining file.');
}

return sites[definingIndex].getFileName();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
// Dummy for test purposes
51 changes: 51 additions & 0 deletions packages/@aws-cdk/aws-lambda-nodejs/test/function_esmPaths.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import { Template } from '@aws-cdk/assertions';
import { CodeConfig } from '@aws-cdk/aws-lambda';
import { Stack } from '@aws-cdk/core';
import { NodejsFunction } from '../lib';
import { Bundling } from '../lib/bundling';
import { CallSite } from '../lib/util';
import * as util from '../lib/util';

jest.mock('../lib/bundling', () => {
return {
Bundling: {
bundle: jest.fn().mockReturnValue({
bind: (): CodeConfig => {
return {
s3Location: {
bucketName: 'my-bucket',
objectKey: 'my-key',
},
};
},
bindToResource: () => { return; },
}),
},
};
});

const actualFindDefiningFile = util.findDefiningFile;

jest.spyOn(util, 'findDefiningFile').mockImplementation((sites: CallSite[]): string => {
return 'file://' + actualFindDefiningFile(sites);
});

let stack: Stack;
beforeEach(() => {
stack = new Stack();
jest.clearAllMocks();
});

test('NodejsFunction with .ts handler, with ESM file:// paths', () => {
// WHEN
new NodejsFunction(stack, 'handler1');

expect(Bundling.bundle).toHaveBeenCalledWith(expect.objectContaining({
entry: expect.stringContaining('function_esmPaths.test.handler1.ts'), // Automatically finds .ts handler file
}));

Template.fromStack(stack).hasResourceProperties('AWS::Lambda::Function', {
Handler: 'index.handler',
Runtime: 'nodejs14.x',
});
});