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

Tracking Issue for ESM Support #1016

Closed
phil-lgr opened this issue Oct 27, 2022 · 14 comments
Closed

Tracking Issue for ESM Support #1016

phil-lgr opened this issue Oct 27, 2022 · 14 comments
Labels
ESM Related to ESM support

Comments

@phil-lgr
Copy link

phil-lgr commented Oct 27, 2022

UPDATE 7/26/2023: Please see the Official ESM Support Mega Issue for the latest on this topic

AFAIK we do not have complete ESM support in oclif, could we have a tracking issue to identify what is missing?
Edit: see comment below for ESM support

Questions:

  1. Can we use "type": "module" in an oclif cli package?
  2. Reading Can't use typescript commands with ESM modules core#421 (comment) it looks like it's possible with ts-node, but what about without ts-node?
  3. The docs should explain how to use oclif with ESM

Issues in oclif with keyword ESM: https://github.com/oclif/oclif/issues?q=is%3Aissue+is%3Aopen+esm

Related in core:

@mdonnalley
Copy link
Contributor

@phil-lgr Thanks for posting the issue. I agree that this is not clearly communicated or documented anywhere - oclif does have ESM support, it just requires a few tweaks to the bin scripts and tsconfig.json

  • Rename bin/dev to bin/dev.js and replace contents with this:
#!/usr/bin/env ts-node

/* eslint-disable node/shebang */

import oclif from '@oclif/core'
import path from 'node:path'
import url from 'node:url'
// eslint-disable-next-line node/no-unpublished-import
import {register} from 'ts-node'

// In dev mode -> use ts-node and dev plugins
process.env.NODE_ENV = 'development'

register({
  project: path.join(path.dirname(url.fileURLToPath(import.meta.url)), '..', 'tsconfig.json'),
})

// In dev mode, always show stack traces
oclif.settings.debug = true

// Start the CLI
oclif
.run(process.argv.slice(2), import.meta.url)
.then(oclif.flush)
.catch(oclif.Errors.handle)
  • Rename bin/run to bin/run.js and replace contents with this:
#!/usr/bin/env node

import oclif from '@oclif/core'

oclif
.run(process.argv.slice(2), import.meta.url)
.then(oclif.flush)
.catch(oclif.Errors.handle)
  • Update tsconfig.json to include the following
{
  "compilerOptions": {
    "module": "ES2020",
    "moduleResolution": "node",
  },
  "ts-node": {
    "esm": true
  }
}
  • Add "type": "module" to package.json

I'm planning on updating the documentation with the above steps later today

As for the future, we currently weighing our options.

We might migrate the entire oclif/core project to ESM, which would make writing ESM plugins much easier. However, this would be a significant breaking change for any plugins that can't move to ESM quickly or at all. For that reason it's entirely possible that we keep the project in CommonJS for the foreseeable future.

Either way, we have an open PR for version 2. So please let us know if you have any suggestions on how to make the ESM plugin experience any better and we can work into that PR.

@mdonnalley
Copy link
Contributor

Reading oclif/core#421 (comment) it looks like it's possible with ts-node, but what about without ts-node?

ts-node is required for using bin/dev.js because ts-node needs to compile the typescript at runtime. If, however, you cannot use ts-node, you can use the bin/run.js in the above comment - you'll just need to compile your code before running it

@phil-lgr
Copy link
Author

phil-lgr commented Nov 4, 2022

@mdonnalley awesome, I will give this a try !

edit: I can confirm that with the changes above, and changing import to end with .js in my oclif src code, everything works with ESM!

timgreen added a commit to timgreen/Anki.md that referenced this issue Nov 18, 2022
Also tweak oclif to support ESM.
oclif/oclif#1016
@Rinse12
Copy link

Rinse12 commented Nov 22, 2022

@phil-lgr Were you able to get oclif/test working in an ESM environment? It's throwing an error in my case

oclif/test#301

@g-sabharwal
Copy link

g-sabharwal commented Nov 29, 2022

@phil-lgr Were you able to get oclif/test working in an ESM environment? It's throwing an error in my case

oclif/test#301

I was able to make it work by using below statements as a workaround since esm modules don't have a parent property defined from what I have read.

import { createRequire } from "module";
const { expect, test } = createRequire(import.meta.url)("@oclif/test");

@phil-lgr
Copy link
Author

@Rinse12 I have the same issue you raised oclif/test#301

mrloop added a commit to mrloop/netlify-git-branch that referenced this issue Jan 7, 2023
mrloop added a commit to mrloop/netlify-git-branch that referenced this issue Jan 15, 2023
@cyberwombat
Copy link

On a related issue - while I can run my commands as esm the oclif cli itself wont work w esm - for ex trying to generate docs with "type": "module" doesn't work. Workaround is removing that from package.json to generate docs and readding which is a bit lame.

@jameshfisher
Copy link

This advice doesn't work for me:

  • Update tsconfig.json to include the following
{
  "compilerOptions": {
    "module": "ES2020",
    "moduleResolution": "node",
  },
  "ts-node": {
    "esm": true
  }
}

I get the following error when building:

$ npm run build

> foobar-cli@0.0.1 build
> shx rm -rf dist && tsc -b

tsconfig.json:11:5 - error TS5023: Unknown compiler option 'ts-node'.

11     "ts-node": {
       ~~~~~~~~~


Found 1 error.

@glitch452
Copy link

Just wanted to leave a comment here. I just setup a fresh project and followed the instructions to convert to ESM on the docs https://oclif.io/docs/esm (although it's missing the step of adding "type": "module" to package.json).

Initially, a simple test command is working, but there seem to be some pain points still.

  1. ts-node has to be installed globally to use ./bin/dev.jsdirectly. (This should be added to the documentation)
  2. I am getting errors when trying to import files. See Below:

I setup a simple base command:

import {Command} from '@oclif/core'

abstract class BaseCommand extends Command {}

export default BaseCommand

Then I imported it and tried to use it in my test command:

import BaseCommand from '../base-command/base-command'

export default class Test extends BaseCommand {

I get the following output in the console:

(node:93614) Error Plugin: mynewcli: Cannot find module '<project_dir_redacted>/src/base-command/base-command' imported from <project_dir_redacted>/src/commands/test.ts
module: @oclif/core@2.1.6
task: toCached
plugin: mynewcli
root: <project_dir_redacted>
See more details with DEBUG=*
(Use `node --trace-warnings ...` to show where the warning was created)
Error: command test not found
    at Config.runCommand (<project_dir_redacted>/node_modules/@oclif/core/lib/config/config.js:271:19)
    at async Module.execute (<project_dir_redacted>/node_modules/@oclif/core/lib/main.js:136:5)
    at async file://<project_dir_redacted>/bin/dev.js:6:3

I'm not sure if I'm just missing something or doing something wrong. If so, please let me know. If not, I'm wondering if this should be tracked here, or if I should create a separate issue. Again, please let me know.

Thanks!

@jasonk
Copy link

jasonk commented Mar 5, 2023

ts-node has to be installed globally to use ./bin/dev.jsdirectly. (This should be added to the documentation)

ts-node has to be in your $PATH in order for it to be used as an executable but doesn't have to be installed globally (though that is one way to get it into your path). This is true for anything that uses a #!/usr/bin/env line to determine the executable, not just for ts-node.

I am getting errors when trying to import files. See Below:

Your error is because ESM requires you to include an extension when importing. You want:

import BaseCommand from '../base-command/base-command.js';

@glitch452
Copy link

Re: ts-node, fair enough... something regarding that would he helpful in the documentation.

Re: file extensions. Ahh yes, thank you! This is my first attempt at an ESM node project, so, I appreciate the tip. I was able to get the project converted to ESM and all the dependencies updated to the latest versions now. It might be helpful to add this to the documentation also?

@jenkin
Copy link

jenkin commented Jul 3, 2023

After some hours of pain, here is my working solution (no, official docs are not enough) created running npx oclif generate oclif-esm-starter (all default options and yarn package manager).

Please note that test suite doesn't work (yet) and generating cli from yarn (ie. yarn dlx oclif generate oclif-esm-example) fails.

Please note that ./bin/dev.js fails on node v20 (not lts, yet).

Environment:

  • node: v18.16.0 (npm v9.5.1)
  • yarn: v3.6.0
  • nvm: v0.39.3

@jgttech
Copy link

jgttech commented Jul 18, 2023

Is there a work around for doing directory based import in ESM with this current ESM setup?

@mdonnalley mdonnalley pinned this issue Jul 26, 2023
@mdonnalley mdonnalley added the ESM Related to ESM support label Jul 26, 2023
@mdonnalley
Copy link
Contributor

Please go to oclif/core#749 for any further comments/questions/concerns

@mdonnalley mdonnalley unpinned this issue Oct 10, 2023
mrloop added a commit to mrloop/netlify-git-branch that referenced this issue Jan 10, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
ESM Related to ESM support
Projects
None yet
Development

No branches or pull requests

10 participants