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

exports lib packages in package.json #5000

Closed
trim21 opened this issue Oct 4, 2022 · 32 comments · Fixed by #5677
Closed

exports lib packages in package.json #5000

trim21 opened this issue Oct 4, 2022 · 32 comments · Fixed by #5677

Comments

@trim21
Copy link
Contributor

trim21 commented Oct 4, 2022

TLDR:

Oh, yeah I don't think we will ever export that.

#5000 (comment)

Is your feature request related to a problem? Please describe.

Yes. I'm writing a adaptor to be used in userscript like tampermonkey or Violentmonkey,
it use a xhr provided be broser extension GM.xmlHttpRequest to make cors request.

And to make it behavior like axios' xhr adaptor, I'm using some axios' helper functions directly by

import buildFullPath from "axios/lib/core/buildFullPath";
import settle from "axios/lib/core/settle";
import buildURL from "axios/lib/helpers/buildURL";
import parseHeaders from "axios/lib/helpers/parseHeaders";
import utils from "axios/lib/utils";

But after axios 1.0.0 is released, a exports field is added to package.json, and lib directory is no longer exported anymore, this make me unable to use helper function provided by axios anymore.

axios/package.json

Lines 6 to 17 in 484aa4f

"exports": {
".": {
"browser": {
"require": "./index.js",
"default": "./index.js"
},
"default": {
"require": "./dist/node/axios.cjs",
"default": "./index.js"
}
}
},

modern js bundler will raise a error for this: Package subpath './lib/core/buildFullPath' is not defined by "exports" in .../node_modules/axios/package.json by bundler.

Describe the solution you'd like

add lib dir to package.json#exports

@arthurfiorette
Copy link
Contributor

arthurfiorette commented Oct 5, 2022

And, if I'm not mistaken, react native users needs the package.json file to be exported as well.

Some users of axios-cache-interceptor raised an issue about this same problem and, after some reading, this may also be the best way to deascribe your exports in a project coded by default with ESM:

https://github.com/arthurfiorette/axios-cache-interceptor/blob/4bf049b935d47f5fc46c587ff81c0e4d15b52e8b/package.json#L9-L20

@arthurfiorette
Copy link
Contributor

Also, it would be great if a simple export * from '../index.d.ts declaration file was shipped with the same name for each file in the dist folder, this way direct imports would work flawlessly with typescript.

Like: import ... from 'axios/dist/node/axios.cjs'

@jasonsaayman
Copy link
Member

See #5030 merged should fix this.

@trim21
Copy link
Contributor Author

trim21 commented Oct 6, 2022

No, this is not fixed by #5030, it's a complete different problem.

People who are affected by this issue want to import utils from axios/lib/..., which is curretly forbidden by package.json#exports.

Currently package.json#exports only allow us to import 'axios', but we are not just importing axios, we are importing axios/lib/..., and change exports of axios won't help.

The other issues closed by this #5030 are indeed importing from axios, they are fixed by #5030, but not this one.

@trim21
Copy link
Contributor Author

trim21 commented Oct 6, 2022

@jasonsaayman could you re-open this issue?

@jasonsaayman jasonsaayman reopened this Oct 6, 2022
@jasonsaayman
Copy link
Member

Ok fair enough, I have re-opened and will investigate as soon as I can

@ivanpepelko
Copy link
Contributor

No, this is not fixed by #5030, it's a complete different problem.

People who are affected by this issue want to import utils from axios/lib/..., which is curretly forbidden by package.json#exports.

Currently package.json#exports only allow us to import 'axios', but we are not just importing axios, we are importing axios/lib/..., and change exports of axios won't help.

The other issues closed by this #5030 are indeed importing from axios, they are fixed by #5030, but not this one.

This is correct, I made a mistake in when describing #5030, as this issue was mentioned in #5008 (comment).

@tusbar
Copy link
Contributor

tusbar commented Oct 13, 2022

Related: jamesmbourne/aws4-axios#701

@kranzhoff
Copy link

I think my issue is related to this:
Trying to set the axios.defaults.adapter in my TS project's test files like this:

axios.defaults.adapter = require('axios/lib/adapters/http')

fails with axios 1.x due to the httpAdapter not being exported.
This used to work just fine with axios 0.27.2.

@jasonsaayman
Copy link
Member

Hi 👋

Please try the latest pre-release by running the following:

npm i axios@1.2.0-alpha.1

Please provide feedback in either the pinned issue or the discussion thread 🧵

@trim21
Copy link
Contributor Author

trim21 commented Nov 10, 2022

I'm pretty sure it's not what we wanted… utils are still not exported, makes no difference

@trim21 trim21 mentioned this issue Nov 11, 2022
@jasonsaayman
Copy link
Member

Oh, yeah I don't think we will ever export that. Exporting the entire libs would cause a large potential issue and cause people to use Axios outside of the scope of its declared public API. If you could motivate what you would like and why maybe I would look into it but blanket exports of the directory would not be smart.

@trim21
Copy link
Contributor Author

trim21 commented Nov 11, 2022

Ok

@jasonsaayman
Copy link
Member

Yeah sorry, I get what you are trying to do but should we do this we would then open ourselves up to so much more issues if we declared this as part of the public API. That being said if you would like to roll what you are working on into a package we can maybe work on that and see how we can make it possible to provide this to a consumer.

@trim21
Copy link
Contributor Author

trim21 commented Nov 11, 2022

I think it's very understandable that these API are not stable.You can document that they may change any time and export them.

@florianbepunkt
Copy link

@jasonsaayman One possible use case is aws4-axios, which uses

import buildUrl from "axios/lib/helpers/buildURL";
import combineURLs from "axios/lib/helpers/combineURLs";
import isAbsoluteURL from "axios/lib/helpers/isAbsoluteURL";

A possible solution for package maintainers would be to duplicate these axios methods in their own codebase.

On the other hand I believe the majority of signing-related middleware/interceptors would need these set of helpers. Do you think increasing the surface of the public API will increase issues in general, or is there anything particular about these helpers (e. g. frequent changes).

@dhensby
Copy link

dhensby commented Nov 11, 2022

Still doesn't work for me.

Error [ERR_PACKAGE_PATH_NOT_EXPORTED]: Package subpath './lib/core/settle' is not defined by "exports" in .\node_modules\axios\package.json

The docs here are quire explicit about using the settle.js function both in testing and if creating bespoke adapters.

@dhensby dhensby mentioned this issue Nov 11, 2022
@spyndutz
Copy link

spyndutz commented Nov 17, 2022

I'm not sure if this is the correct suggestion since it's basically changing how Axios package is being shipped (And the effort is definitely huge). What if we modularize it and make the repository a monorepo approach similar to what parcel did?
So we have scoped package like @axios/core, @axios/helpers, @axios/adapters and let them import from those instead? While the main Axios package itself only export the public API it intended, so we have a different package versioning for those scoped modules and the main Axios package.

@guoyunhe
Copy link

@jasonsaayman could you please provide a way to export built-in adaptors, which is a config option of axios? I want to use http adaptor in jsdom environment. jsdom's XHR implementation is a trouble...

@DigitalBrainJS
Copy link
Collaborator

@guoyunhe Manual adapter switching without the need for direct import will be provided by #5277 PR.

@bigmeow
Copy link

bigmeow commented Nov 22, 2022

I have a solution and it wasted me a few days:
make it not work that "exports" field in the package.json file, see the webpack doc.

webpack.config.js

module.exports = {
  //...
  resolve: {
    exportsFields: ['exports2'],
  },
};

or webpackChain

chain.merge({
    resolve: {
      exportsFields: ["exports2"],
    }
});

It really works

@trim21 @kranzhoff @guoyunhe

@arthurfiorette
Copy link
Contributor

@DigitalBrainJS, Actually, this just extends the current problem into smaller ones. Everytime someone will be needing an internal function from axios that is not exported. As you can see in #5324, #5264 and so on...

Why can't all functions be exported as normal so anyone can use it while integrating with axios? The bytesize wouldn't be that big? or would it?

@jasonsaayman
Copy link
Member

@arthurfiorette we don't want to export everything else people will rely on code that can change without being documented as we can change underlying implementations without changing the public API. The only way I can see this working is we either export it and then whoever uses it does so explicitly at their own risk or we export only what is needed. For now I would like to do it one by one but if there are many uses cases and people really want us to do so we can look into everything being exported.

@damirbogdanov
Copy link

the following fixed the issue for me

webpack.config.js

module.exports = {
  resolve: {
    alias: {
      "axios/lib": path.resolve(__dirname, "../../node_modules/axios/lib"),
    },
  },
};

@Liubasara
Copy link

any news? same problem here.

@arthurfiorette
Copy link
Contributor

Hey @jasonsaayman. I know that importing code inside lib folder that are not part of the public API is strongly discouraged and it may break even in patch versions.

The main reason we import things inside the lib/related folders is because we are trying to do something that axios does not support yet or reusing axios's logic in another part of our codebase.

The code is in OUR node_modules and just disallowing us from accessing it WILL not prevent us from using it. It is going to just create another bigger problem as, to solve our problem, we will copy/paste axios source code, which is much worse than our code breaking when upgrading axios, because it creates duplicity anyway and even future critical problems axios may fix won't reflect on our copy-pasted code.

And even if we achieve to import axios internal content without copy-pasting functions, I am sure that the code written to access it is more error-prone than just hypothetic incompatibilities axios may bring with a patch/minor version.

I am strongly in favor of exporting everything axios has, even if it is going to be under a internal property or similar names.

I know that creating a issue to export X functionality will leave axios with much more control of what APIs you should care about or not, but in this issue/code/release meantime, the end-user will already have copied the function into his source code and probably will never look at it again, which leverages us to the same prior problem of axios fixing critical stuff and it not reflecting everywhere.

Happy to discuss more, also if you want, I can create another issue.

@jasonsaayman
Copy link
Member

Ok fair enough, I have been gone for a bit of a hiatus, but seems as good as any time to start getting stuck in again. I will look into this

@jasonsaayman jasonsaayman reopened this Apr 25, 2023
@trim21
Copy link
Contributor Author

trim21 commented Apr 25, 2023

I have been using https://github.com/ds300/patch-package to patch package.json of axios for a while....

@DigitalBrainJS
Copy link
Collaborator

DigitalBrainJS commented Apr 25, 2023

Perhaps we can export the lib folder with some prefix in the path to highlight this as an unsafe operation. I would like to avoid potential situations when we change the internal structure of Axios in a minor version, causing a bunch of issue reports. The next major version will have intensive changes to internal modules, as the core needs a deep rework in order to add middleware/hooks functionality and a plugin loader.

@marcin-wlodarczyk
Copy link

@DigitalBrainJS I'm trying to implement a custom Axios adapter.
Looks like the path ./unsafe/core/settle.js is not recognized by TypeScript.

@eizodann
Copy link

@DigitalBrainJS I'm trying to implement a custom Axios adapter. Looks like the path ./unsafe/core/settle.js is not recognized by TypeScript.

Same here

@trim21
Copy link
Contributor Author

trim21 commented Aug 10, 2023

@DigitalBrainJS I'm trying to implement a custom Axios adapter. Looks like the path ./unsafe/core/settle.js is not recognized by TypeScript.

axios internal files are plain js, so you need to write your own type defs for them.

There is nothing axios can do unless they rewrite whole project into TypeScript.

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.