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

ability to test / detect if a module is a CJS module (parse without the exception) #35

Closed
thescientist13 opened this issue Jan 29, 2021 · 5 comments

Comments

@thescientist13
Copy link

thescientist13 commented Jan 29, 2021

Hello! 👋

Just started using this package for a project I've been working on, and one of my use cases is detecting if a package from node_modules is a CommonJS module. It would be great if this package could be extended with an additional function, something like test or validate, that would effectively be like parse, but rather than throw on not being able to analyze the module, it would just return true / false instead.

For example, this is how I am making it work now by using parse.

const testForCjsModule = async(url) => {
  let isCommonJs = false;
  
  try {
    const module = await fs.promises.readFile(url, 'utf-8');
    
    await parse(module);

    isCommonJs = true;
  } catch (e) {
    const { message } = e;
    const isProbablyLexarErrorSoIgnore = message.indexOf('Unexpected import statement in CJS module.') >= 0 
      || message.indexOf('Unexpected export statement in CJS module.') >= 0;
      
    if (!isProbablyLexarErrorSoIgnore) {
      // we probably _shouldn't_ ignore this, so let's log it since we don't want to swallow all errors
      console.error(e);
    }
  }

  return Promise.resolve(isCommonJs);
};


const isCjs = await testForCjsModule('path/to/something/in/node_modules/index.js')

i haven't looked into the code here yet, but if you are inclined to support something like, and you think it could be classified as a "good first issue", I would be happy to try and help.

I was thinking the usage could look something like this

const { detect } = require('cjs-module-lexer');

const module = fs.readFileSync('path/to/something/in/node_modules/index.js', 'utf-8');
const isCjsModule = await detect(module); 

console.debug(isCjsModule);  // true | false

Thanks in advance for your consideration on this, and additionally thanks for all your great work on this and other projects of yours, like es-module-shims and SystemJS. Great stuff! ⭐

@thescientist13 thescientist13 changed the title ability to test / detect if a module is CJS module (without parsing) ability to test / detect if a module is a CJS module (without parsing) Jan 29, 2021
@nicolo-ribaudo
Copy link
Contributor

nicolo-ribaudo commented Jan 29, 2021

Trying to parse a module is not enough. For example, you cannot know if this is an ES module or a CJS module just by parsing it, and at runtime it has two different behaviors:

console.log("is script?", this !== undefined);

@thescientist13
Copy link
Author

thescientist13 commented Jan 29, 2021

Sure, I understand a detect function would just be as limited as parse is, but it would still be nice to get the functionality of parse, but just without the Error being thrown if the lexar can't analyze it correctly. I understand there is some naivety in the approach, and my project absolutely favors users going down the ESM path, so it's mostly just for a convenience and a way to nudge people away from CommonJS in their dependency trees, (e.g. lodash vs lodash-es).

Or maybe there is a way with a combination of tools? Just trying to get it be "good enough". 😃

@nicolo-ribaudo
Copy link
Contributor

The proper way of detecting CJS vs ESM is to use these rules, which is what Node.js and the various bundlers do.

@thescientist13
Copy link
Author

Ah, excellent! Thank you so much for sharing, will definitely dive head first into that then. 👀

@thescientist13 thescientist13 changed the title ability to test / detect if a module is a CJS module (without parsing) ability to test / detect if a module is a CJS module (without using parse) Jan 30, 2021
@thescientist13 thescientist13 changed the title ability to test / detect if a module is a CJS module (without using parse) ability to test / detect if a module is a CJS module (parse without the exception) Jan 30, 2021
@guybedford
Copy link
Collaborator

Detecting modules based on whether they use module syntax can be brittle - hence why we use type package boundaries in Node.js.

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

No branches or pull requests

3 participants