Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Do not add .js extension to entries values #167

Merged
merged 8 commits into from
Jul 28, 2017
Merged

Do not add .js extension to entries values #167

merged 8 commits into from
Jul 28, 2017

Conversation

kikar
Copy link
Contributor

@kikar kikar commented Jul 27, 2017

What did you implement:

Closes #165

How did you implement it:

How can we verify it:

Todos:

  • Write tests
  • Write documentation
  • Fix linting errors (not yet implemented)
  • Make sure code coverage hasn't dropped (not yet implemented)
  • Provide verification config / commands / resources
  • Enable "Allow edits from maintainers" for this PR
  • Update the messages below

Is this ready for review?: YES
Is it a breaking change?: NO

lib/validate.js Outdated
@@ -8,7 +8,7 @@ const _ = require('lodash');

function getEntryForFunction(serverlessFunction) {
const handler = serverlessFunction.handler;
const handlerFile = /(.*)\..*?$/.exec(handler)[1] + '.js';
const handlerFile = /(.*)\..*?$/.exec(handler)[1];
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should actually retrieve the correct file extension here and set it in the value of the key, so that there's no need to use custom code in the webpack configuration to get the plugin running.

function getHandlerFileExtension(baseName) {
  // Use fs/fs-extra/path or any other appropriate mechanism to determine the actual file extension of the handler
  // Maybe we can search for known and supported endings in a predefined order
  // So that the standard extension 'js' is preferred if, by accident, there are multiple copies
  // of the handler with different extensions - or throw an error in that case.
  const allowedExtensions = [
    'js', 'ts', 'jsx'
  ];
  const handlerExtension = ...;
  ...
  return handlerExtension;
}
...
const handlerFileBaseName = /(.*)\..*?$/.exec(handler)[1];
const handerFile = `${handlerFileBaseName}.${getHandlerFileExtension(handlerFileBaseName)}`;
...
return {
  [handlerFileBaseName]: `./${handlerFile}`
};

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we assume all the function files are in the servicePath folder?

Copy link
Member

@HyperBrain HyperBrain Jul 27, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

At least somewhere under the servicePath. The handlerBaseName contains the path elements relative to the handler. So, for example, it could be handlers/shop/order/handler and handlers/shop/fulfill/handler, but we can assume that handler files are never outside the service folder (of course the user can use symlinks to access files outside the service directory, but checking if the baseName + extension exists, will automatically reveil the correct results in this case)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Better rename the handlerFileBaseName variable to handlerFilePathWithBaseName as it actually contains the path + the basename.

'module2.js': './module2.js',
'handlers/func3/module2.js': './handlers/func3/module2.js',
'handlers/module2/func3/module2.js': './handlers/module2/func3/module2.js',
'module1': './module1',
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The tests have to be adapted AFTER the changes above, because the used external functions to determine the extension have to be stubbed with sinon.

@HyperBrain
Copy link
Member

HyperBrain commented Jul 27, 2017

Determining the extension will also support the case where single functions in a project are updated and the used extension changes. E.g. if you change a function from js to jsx or from js to ts. Then the next deploy will just work out of the box because your config file does not need to know anything about the specific function configurations.

@kikar
Copy link
Contributor Author

kikar commented Jul 27, 2017

Latest commit should do the job. Problem is that all tests fail cause we don't actually have files to check

lib/validate.js Outdated
@@ -27,13 +49,14 @@ module.exports = {
// Expose entries - must be done before requiring the webpack configuration
const entries = {};
const functions = this.serverless.service.getAllFunctions();
const allFilesInServicePath = listFiles(this.serverless.config.servicePath);
Copy link
Member

@HyperBrain HyperBrain Jul 27, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it necessary to browse the whole service dir file tree here? I think that is very expensive - the directory might include node_modules etc.

Assuming that the handlers we have already point to the handler files we check, we know exactly where the files have to be. So just searching in getEntryExtension(handlerFile) for ${handlerFile}.* or ${handlerFile}.{js,ts,jsx} should retrieve the full file automatically (and even shows us if it is ambiguous, which is an error on the user side if multiple of our allowed extensions are found). We do not need to be aware of the complete file hierarchy here.

@HyperBrain
Copy link
Member

I can take care of the unit tests as soon as we have a performant and working solution.

@kikar
Copy link
Contributor Author

kikar commented Jul 27, 2017

Improved the file search as recommended

lib/validate.js Outdated
const lib = require('./index');
const _ = require('lodash');

function getEntryForFunction(serverlessFunction) {
function getEntryExtension(fileName, servicePath) {
let files = glob.sync(`${fileName}.*`, { cwd: servicePath });
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can be const

lib/validate.js Outdated
function getEntryForFunction(serverlessFunction) {
function getEntryExtension(fileName, servicePath) {
let files = glob.sync(`${fileName}.*`, { cwd: servicePath });
return path.extname(files[0]);
Copy link
Member

@HyperBrain HyperBrain Jul 27, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We could emit a warning in case more than one file (or no file at all) is found here:

if (_.size(files) > 1) {
  this.serverless.cli.log(`WARNING: More than one matching handlers found for ${fileName}. Using ${_.first(files)}.`);
}

Of course the now global function(s) have to be moved into validate() to have access to the correct this.

Also use _.first(files) here instead of files[0] as the lodash variant shows our intention in a better way and is safer.

@HyperBrain
Copy link
Member

I will add the unit tests and the doc/example updates tomorrow, so that we can release 2.2.0 also tomorrow.

@HyperBrain
Copy link
Member

HyperBrain commented Jul 27, 2017

I tested it with one of our projects. That worked nicely. Also rebased onto the current webpack master.
Everything should be ok now. The only thing that can happen is, that if there are unrelated files besides the handler, that just have a different ending, the glob could match them (e.g. handler.doc). However it will show the warning we implemented.

If that turns out to be a problem later, we can restrict the allowed extensions by setting the glob pattern to ${fileName}.@(js|ts|jsx).

@HyperBrain
Copy link
Member

Just added some more complex test cases and a preference sorting. I will do some final tests now.
For most standard uses of lib.entries it should work now - if someone needs more sophisticated handling he can program the complete stuff in his webpack.conf - thanks to the serverless and option exports.

@HyperBrain HyperBrain merged commit e7531dc into serverless-heaven:master Jul 28, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Can't use the new slsw.lib.entries with typescript
2 participants