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

feat: migrate to typescript #253

Merged
merged 10 commits into from Nov 25, 2023
Merged

feat: migrate to typescript #253

merged 10 commits into from Nov 25, 2023

Conversation

mindhells
Copy link
Member

@mindhells
Copy link
Member Author

This relates to #250, #251 and #252

Please @yutak23 @rchl have a look

Copy link

@rchl rchl left a comment

Choose a reason for hiding this comment

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

I will have a more proper look from the interoperability standpoint once other comments are clarified/addressed.

fixup Outdated
Copy link

@rchl rchl Nov 17, 2023

Choose a reason for hiding this comment

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

This might be something from before but I wonder what's the reasoning for adding those package.json files in the first place? I'm pretty sure that those don't really have any effect since it's the package's main package.json that decides whether something is an esm or commonjs module.

.eslintrc Outdated Show resolved Hide resolved
.eslintrc Outdated Show resolved Hide resolved
package.json Outdated Show resolved Hide resolved
package.json Outdated Show resolved Hide resolved
spec/index.spec.ts Outdated Show resolved Hide resolved
spec/index.spec.ts Outdated Show resolved Hide resolved
spec/index.spec.ts Outdated Show resolved Hide resolved
spec/index.spec.ts Outdated Show resolved Hide resolved
src/index.ts Outdated Show resolved Hide resolved
@mindhells
Copy link
Member Author

Awesome feedback @rchl
Thanks a ton!
I believe I have addressed everything. Had to do some extra adjustments in the internal typings for everything to gear up.
Feel free to resolve the conversations as you think they are correctly addressed.
Looking forward for your feedback from the interoperability stand point 🙇‍♂️

src/index.ts Show resolved Hide resolved
es/index.mjs Show resolved Hide resolved
.eslintrc Outdated Show resolved Hide resolved
package.json Outdated Show resolved Hide resolved
.vscode/settings.json Outdated Show resolved Hide resolved
@mindhells
Copy link
Member Author

@rchl about removing @eslint/recommended, I had to, because otherwise it complains about "unused params"... in the interface declarations 🤷

@rchl
Copy link

rchl commented Nov 18, 2023

Feel free to resolve the conversations as you think they are correctly addressed.

Please resolve them. I, not being a contributor or maintainer, can't resolve them. I find it weird about github but oh well...

@rchl
Copy link

rchl commented Nov 18, 2023

@rchl about removing @eslint/recommended, I had to, because otherwise it complains about "unused params"... in the interface declarations 🤷

So typescript-eslint documentation suggests this: https://typescript-eslint.io/linting/configs#eslint-recommended

(Keep eslint rules and only extend with @typescript-eslint/eslint-recommended. That should disable eslint rules that are not compatible with typescript.)

@rchl
Copy link

rchl commented Nov 18, 2023

@rchl about removing @eslint/recommended, I had to, because otherwise it complains about "unused params"... in the interface declarations 🤷

So typescript-eslint documentation suggests this: typescript-eslint.io/linting/configs#eslint-recommended

(Keep eslint rules and only extend with @typescript-eslint/eslint-recommended. That should disable eslint rules that are not compatible with typescript.)

I do see the issue also when testing it myself though. Though I think it's better to manually disable no-unused-vars than removing eslint:recommended because otherwise we'd loose a lot of checks that are not present in the typescript rules.

src/index.ts Show resolved Hide resolved
.vscode/settings.json Outdated Show resolved Hide resolved
spec/index.spec.ts Outdated Show resolved Hide resolved
package.json Outdated Show resolved Hide resolved
src/index.ts Show resolved Hide resolved
@rchl
Copy link

rchl commented Nov 19, 2023

It looks good to me. Just run npm i again because package lock is not fully up-to-date.

@mindhells
Copy link
Member Author

@rchl My plan is to publish this as a minor, as there shouldn't be any breaking changes in the public API. WDYT?

@rchl
Copy link

rchl commented Nov 20, 2023

I would not vouch with my life that it won't break anything but I agree that it shouldn't.

There is added peer dependency which is sort of a breaking change typically but technically it should have had that since the beginning so it seems more like a bug fix.

I suppose it's also good to wait for @yutak23 to check it out first.

package.json Outdated
"require": "./index.js"
"types": "./dist/index.d.ts",
"import": "./dist/esm/index.js",
"require": "./dist/cjs/index.js"
Copy link
Contributor

Choose a reason for hiding this comment

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

@mindhells

This setup would result in the following error.

$ npx tsc
srv/app.ts:5:1 - error TS2349: This expression is not callable.
  Type 'typeof import("/home/study/workspace/ts-node-oidc/node_modules/axios-retry/dist/index")' has no call signatures.

5 axiosRetry(axios);
  ~~~~~~~~~~

A draft amendment is prepared below. We hope you will review it.

#255

src/index.ts Outdated
import type { AxiosError, AxiosRequestConfig, AxiosInstance, AxiosStatic } from 'axios';
import isRetryAllowed from 'is-retry-allowed';

export namespace IAxiosRetry {
Copy link
Contributor

Choose a reason for hiding this comment

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

@mindhells

If you are moving to typescript, I don't think you need to bother with namespace. Also, the presence of this namespace would be a destructive change.

Specifically, this code does not export IAxiosRetryConfig, etc.

I would appreciate it if you could refer to the PR of the proposed fix below for more details.

#256

Copy link
Contributor

@yutak23 yutak23 Nov 21, 2023

Choose a reason for hiding this comment

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

If we want to keep namespace, we would need to export each one separately as follows. However, this is redundant, so I think a modification that eliminates the namespace declaration is fine.

export type AxiosRetry= IAxiosRetry.AxiosRetry;
export type IAxiosRetryConfig = IAxiosRetry.IAxiosRetryConfig;
export type IAxiosRetryConfigExtended = IAxiosRetry.IAxiosRetryConfigExtended;
export type IAxiosRetryReturn = IAxiosRetry.IAxiosRetryReturn;

@mindhells
Copy link
Member Author

Thanks a ton @yutak23, amazing job, I have incorporated both of your fixes 🙇

@mindhells
Copy link
Member Author

After @yutak23 fixes I understand we are safe to publish this a minor, are we?

Comment on lines +17 to +18
"build:esm": "tsc -p tsconfig.json && echo '{\"type\":\"module\"}' > dist/esm/package.json",
"build:cjs": "tsc -p tsconfig-cjs.json && echo '{\"type\":\"commonjs\"}' > dist/cjs/package.json",
Copy link

Choose a reason for hiding this comment

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

I find this creation of package.json in subdirectories weird and hacky. I have never seen it being done elsewhere.

Since the exports object defines whether something is esm or cjs, I don't get why it would be necessary to also add this package.json.

I saw this approach mentioned in the guide linked in this PR but it's not really explained much there and I haven't seen it used anywhere else.

Do you know of any specific case that would fail without it?

Copy link
Contributor

@yutak23 yutak23 Nov 21, 2023

Choose a reason for hiding this comment

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

While certainly a bit hackneyed, this is one effective method. This method is https://nodejs.org/api/packages.html#dual-package-hazard. The following is a summary of how the Dual Package can be achieved and is informative.

microsoft/TypeScript#49462 (comment)

And this method is also taken by other libraries such as stripe-node.
https://github.com/stripe/stripe-node/blob/v14.5.0/package.json#L64

Do you know of any specific case that would fail without it?

If we do not do this, even if you separate them into directories esm, cjs, the module system is still determined by the module settings in package.json's type(in this situation type is not set, so assumed to be a cjs setting since there is no type setting).
Therefore, you will get the following compile error.

This expression is not callable.
  Type 'typeof import("/home/study/workspace/ts-node-oidc/node_modules/axios-retry/dist/esm/index")' has no call signatures.ts(2349)

image

This error occurs when deleting package.json from esm in node_module.

image

This approach is necessary if you want to support both esm and cjs from a single TypeScript file, but it is a different story if you use .cts or .mts extensions like axios.

Copy link

Choose a reason for hiding this comment

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

OK. I trust what you are saying.
But just gonna note that the official Node documentation doesn't mention those extra package.json's so it's weird to me that that would be needed.

I wanted to also verify it on my own but I could not reproduce it on my side with this setup and extra package.json's removed:

Screenshot 2023-11-22 at 09 14 13

But I can see that Typescript insists on importing from /cjs/ so that's probably why but I'm not sure why it's doing that...

@mindhells
Copy link
Member Author

@rchl @yutak23 Thanks a lot for your contributions to this PR, you are awesome!
I'm publishing this as v4, even though no breaking changes should have been introduced (a part from what @rchl commented on the peerDeps) I think there's no reason to take the risk and create a new minor.

@mindhells mindhells merged commit add7b9c into master Nov 25, 2023
3 checks passed
@mindhells mindhells deleted the migrate-to-typescript branch November 25, 2023 11:18
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.

Argument of type 'AxiosInstance' is not assignable to parameter of type 'AxiosStatic | AxiosInstance'
3 participants