Skip to content

Conversation

@tjlahr
Copy link
Contributor

@tjlahr tjlahr commented Mar 20, 2025

WIP / HOLD MERGE

  • tabtab autocompletion relies on module.parent and doesn't work with ESM
  • personally, I had difficulties getting tabtab to work even on main (generators showing up as "[object Object]" for example)
  • I'm skipping the broken tabtab test for now, while the rest of the change is under review.
  • Would love any suggestions on how to solve for old tabtab.

This PR migrates Yo to ECMAScript modules (ESM).

Most of the lines changed are related to the import/export syntax itself.

However, a few libraries and techniques had to be updated in order to work around older and non-ESM issue. I've listed those changes below.

Purpose of this pull request?

Switch from CJS to ESM in order to solve issue 787.

What changes did you make?

  • switch project to type=module
  • adopt import/export syntax throughout codebase
  • update meow (ESM support since v10)
  • remove global-tunnel-ng branch since we're > Node 10
  • replace proxyquire (no ESM) with testdouble
  • replace nyc (no ESM) with c8
  • shim __dirname
  • remove unused --no-update-notifier in CLI

Is there anything you'd like reviewers to focus on?

* switch project to type=module
* adopt import/export syntax throughout codebase
* update meow (ESM support since v10)
* remove global-tunnel-ng branch since we're > Node 10
* replace proxyquire (no ESM) with testdouble
* replace nyc (no ESM) with c8
* shim __dirname
* remove unused --no-update-notifier in CLI
* [WIP] disable failing tabtab test
@socket-security
Copy link

socket-security bot commented Mar 20, 2025

New, updated, and removed dependencies detected. Learn more about Socket for GitHub ↗︎

Package New capabilities Transitives Size Publisher
npm/[email protected] Transitive: environment, filesystem, shell +37 2.85 MB
npm/[email protected]13.2.0 None 0 419 kB sindresorhus
npm/[email protected] None +4 14.3 kB sindresorhus

🚮 Removed packages: npm/[email protected]

View full report↗︎

// `global-tunnel-ng` works only with Node.js v10 and below.
require('global-tunnel-ng').initialize();
}
bootstrap();
Copy link
Contributor Author

Choose a reason for hiding this comment

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

We can eliminate this branching because we're > Node 10.
Simply import and call bootstrap.


const cli = gens.map(gen => {
const minicli = meow({autoHelp: false, autoVersion: true, pkg, argv: gen});
const minicli = meow({autoHelp: false, autoVersion: true, pkg, argv: gen, importMeta: import.meta});
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Small tweak to support the latest meow version.

router.registerRoute('install', routes.install);
router.registerRoute('exit', routes.exit);
router.registerRoute('clearConfig', routes.clearConfig);
router.registerRoute('home', routes.home);
Copy link
Contributor Author

Choose a reason for hiding this comment

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

I collected these into a routes object that can be imported at once.


return fullname().then(name => {
const allo = (name && isString(name)) ? `'Allo ${name.split(' ')[0]}! ` : '\'Allo! ';
const allo = (name && _.isString(name)) ? `'Allo ${name.split(' ')[0]}! ` : '\'Allo! ';
Copy link
Contributor Author

Choose a reason for hiding this comment

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

I will occasionally inline lodash if it's a one-off and the specific method was imported directly.

*/
export const getDirname = fileUrl => {
return path.dirname(fileURLToPath(fileUrl));
};
Copy link
Contributor Author

Choose a reason for hiding this comment

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

__dirname shim.

I did not write a corresponding test for this because __dirname is used all over the place anyway and failures here would show up as failures there. Also, it's tiny and the test would be 99% mock setup.

"test": "nyc mocha --timeout=30000",
"coverage": "nyc report --reporter=text-lcov | coveralls"
"test": "c8 mocha --timeout=30000",
"coverage": "c8 report --reporter=text-lcov | coveralls"
Copy link
Contributor Author

Choose a reason for hiding this comment

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

"proxyquire": "^2.0.1",
"registry-url": "^5.1.0",
"sinon": "^19.0.2",
"testdouble": "^3.20.2",
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Also considered sinon and rewiremock as alternatives here but this was the most seamless.

If this were my project, I'd switch to jest and use their module mocking.

Copy link
Member

Choose a reason for hiding this comment

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

We have adopted vitest in some packages.

const cp = execFile('node', [
path.resolve(__dirname, '..', pkg.bin.yo),
'--version',
'--no-update-notifier'
Copy link
Contributor Author

Choose a reason for hiding this comment

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

I couldn't find any evidence that this is used anywhere.

});

describe('Test completion STDOUT output', () => {
describe.skip('Test completion STDOUT output', () => {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

WIP - see comment about tabtab relying on module.parent

@mshima
Copy link
Member

mshima commented Apr 4, 2025

@tjlahr can we merge to a branch to make easier to contribute?

@tjlahr
Copy link
Contributor Author

tjlahr commented Apr 4, 2025

@mshima That's fine. What branch would you like to merge this to?

@mshima
Copy link
Member

mshima commented Apr 4, 2025

I will create a new one.

@mshima mshima changed the base branch from main to esm April 4, 2025 17:45
@mshima mshima merged commit d30469c into yeoman:esm Apr 4, 2025
11 checks passed
@tjlahr tjlahr deleted the 787-switch-from-cjs-to-esm branch April 4, 2025 17:53
@mshima mshima mentioned this pull request Apr 4, 2025
4 tasks
mshima added a commit that referenced this pull request Apr 6, 2025
* Switch from CJS to ESM (#859)

* Fix 787 - Switch from CJS to ESM

* switch project to type=module
* adopt import/export syntax throughout codebase
* update meow (ESM support since v10)
* remove global-tunnel-ng branch since we're > Node 10
* replace proxyquire (no ESM) with testdouble
* replace nyc (no ESM) with c8
* shim __dirname
* remove unused --no-update-notifier in CLI
* [WIP] disable failing tabtab test

* Make sure we're resetting td mocks

* Delete .nyc_output directory

* revert tab completion to cjs

* adjust autocomplete binary

* re-add --no-update-notifier

* disable update-notifier using env

* remove console.log leftover

---------

Co-authored-by: Thomas Lahr <[email protected]>
@mshima mshima mentioned this pull request Apr 10, 2025
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.

2 participants