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

Add exports field to package.json in order to support moduleResolution node12/nodenext #1726

Closed
viell-dev opened this issue Jun 15, 2022 · 11 comments · Fixed by #1765
Closed
Milestone

Comments

@viell-dev
Copy link

🚀 Feature request

Current Behavior

When using "moduleResolution": "NodeNext", in your tsconfig it expects an "exports": ... field in package.json in order to resolve the package.

Otherwise:
Cannot find module 'fp-ts/Either' or its corresponding type declarations.ts(2307)

Desired Behavior

Importing to work.

Suggested Solution

Shove this in package.json:

  "exports": {
    ".": {
      "import": {
        "types": "./es6/index.d.ts",
        "default": "./es6/index.js"
      },
      "require": {
        "types": "./lib/index.d.ts",
        "default": "./lib/index.js"
      }
    },
    "./*": {
      "import": {
        "types": "./es6/*.d.ts",
        "default": "./es6/*.js"
      },
      "require": {
        "types": "./lib/*.d.ts",
        "default": "./lib/*.js"
      }
    },
    "./es6/*": {
      "import": {
        "types": "./es6/*.d.ts",
        "default": "./es6/*.js"
      }
    },
    "./lib/*": {
      "require": {
        "types": "./lib/*.d.ts",
        "default": "./lib/*.js"
      }
    }
  },

Tested it locally by putting that above "main" like in the example as seen in the TS 4.7 link below, seems to do the job.
The "./es6/*" or "./lib/*" parts are only needed for backwards-compatibility with the old import paths.

Who does this impact? Who is this for?

People wanting to use fp-ts with the new ECMAScript Module Support added with TypeScript 4.7.

Describe alternatives you've considered

Not using the new ECMAScript Module support feature. 🤷‍♂️
Most NPM packages aren't updated to support this yet.

Additional context

TS 4.7 link: https://devblogs.microsoft.com/typescript/announcing-typescript-4-7/#esm-nodejs
Node.js link: https://nodejs.org/api/packages.html#package-entry-points

Your environment

Software Version(s)
fp-ts 2.12.1
TypeScript 4.7.3
@andreavaccari
Copy link

The above suggestion is mostly correct, but there's a caveat with the file extensions. Depending on the the value of the type field in package.json, Node will treat .js files either as CJS or ESM, while it will always treat .cjs file as the former and .mjs files as the latter.

To make Node happy we have to either:

  1. Rename ./es6/index.js to ./es6/index.mjs and ./es6/*.js to ./es6/*.mjs
  2. Add type: module and rename ./lib/index.js to ./lib/index.cjs and ./lib/*.js to ./lib/*.cjs
  3. Add a package.json inside ./es6 with type: module (and for good measure do the equivalent in ./lib)

There's also the option of dropping CJS completely, adding type: module in package.json, and living a happier life.

@viell-dev
Copy link
Author

viell-dev commented Aug 15, 2022

I don't think the suggestion by @andreavaccari is currently applicable, since fp-ts isn't building ECMAScript Modules.

My suggestion would allow a user using ESM to load the ES6 version of fp-ts without issue. fp-ts does not need to use ESM itself to be compatible.

Though, to be fair, I don't think there is much of a difference between ES6 and ESM files. I believe it's just the internal import statements requiring extensions. And the package.json stuff with type: module. But I feel that's another issue entirely.

Edit:
See https://github.com/viell-dev/fp-ts for a test fork.
Only change there is the addition of the exports section in package.json.

@viell-dev
Copy link
Author

Updated my test fork to 2.12.3. (viell-dev/fp-ts)

Also I saw that #1525 also talks about exports stuff.
Not sure what that means for 2.x ESM support.
Is it planned for 3.x and thus not a concern for 2.x?

@gcanti gcanti added this to the 2.13 milestone Aug 31, 2022
@gcanti
Copy link
Owner

gcanti commented Sep 8, 2022

@viell-dev in v3 I'm using

{
  "exports": {
    ".": {
      "require": "./lib/index.js",
      "import": "./es6/index.js"
    },
    "./*": {
      "require": "./lib/*.js",
      "import": "./es6/*.js"
    }
  },
  "types": "index.d.ts",
  "typesVersions": {
    "*": {
      "*": [
        "./types/*"
      ]
    }
  },
  "sideEffects": false
}

So for backwards-compatibility in v2 would be

{
  "exports": {
    ".": {
      "require": "./lib/index.js",
      "import": "./es6/index.js"
    },
    "./*": {
      "require": "./lib/*.js",
      "import": "./es6/*.js"
    },
    "./es6/*": {
      "import": "./es6/*.js"
    },
    "./lib/*": {
      "require": "./lib/*.js"
    }
  },
  "types": "index.d.ts",
  "typesVersions": {
    "*": {
      "*": [
        "./types/*"
      ]
    }
  },
  "sideEffects": false
}

@gcanti
Copy link
Owner

gcanti commented Sep 15, 2022

Hi all, I've just released https://github.com/gcanti/fp-ts/releases/tag/2.13.0-rc.2 (install with npm i fp-ts@rc), could you please try it out and let me know if everything is ok?

@viell-dev
Copy link
Author

@gcanti I tried it and I'm getting: "Could not find a declaration file for module 'fp-ts/Option'."

After testing locally I've concluded that you will need to have the types sections under exports as well.

e.g.

{
  "exports": {
    ".": {
      "require": "./lib/index.js",
      "import": "./es6/index.js",
      "types": "./types/index.d.ts"
    },
    "./*": {
      "require": "./lib/*.js",
      "import": "./es6/*.js",
      "types": "./types/*.d.ts"
    },
    "./es6/*": {
      "import": "./es6/*.js",
      "types": "./types/*.d.ts"
    },
    "./lib/*": {
      "require": "./lib/*.js",
      "types": "./types/*.d.ts"
    }
  },
}

@gcanti
Copy link
Owner

gcanti commented Sep 17, 2022

Ok, thank you, going to release 2.13.0-rc.3 with the fix asap

gcanti added a commit that referenced this issue Sep 17, 2022
gcanti added a commit that referenced this issue Sep 17, 2022
@gcanti
Copy link
Owner

gcanti commented Sep 17, 2022

going to release 2.13.0-rc.3 with the fix asap

done

@viell-dev
Copy link
Author

Looks great. 👍🏻

@gcanti
Copy link
Owner

gcanti commented Sep 17, 2022

Nice, thank you for your help @viell-dev

@viell-dev
Copy link
Author

I saw that the changes got reverted in 2.13.1 due to #1799 and similar issues. So I'm using a fork for my use-cases since I have need of fp-ts in projects where the types don't work without the exports field.

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 a pull request may close this issue.

3 participants