Skip to content

Cannot use parseFile if the TypeScript compiler moduleResolution is set to bundler #2370

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

Closed
2 tasks done
lowvisiondave opened this issue Mar 4, 2025 · 10 comments · Fixed by #2378 · May be fixed by lowvisiondave/music-metadata-typescript-repro#1
Closed
2 tasks done
Assignees

Comments

@lowvisiondave
Copy link

lowvisiondave commented Mar 4, 2025

Is there an existing issue for this?

  • I have searched the existing issues

music-metadata version

11.0.0

Current Behavior

TypeScript throw an error when doing the following:

import { parseFile } from "music-metadata";

Because node_modules/music-metadata/lib/core.d.ts does not include a type for parseFile.

Adding // @ts-expect-error allows the application to build successfully, so it seems to just a types issue.

Reproduction repository

Expected Behavior

I would expect the types to match the functions being exported.

Attached audio sample?

  • I have provided sufficient information to reproduce the issue
@lowvisiondave lowvisiondave added the bug Bug, will addressed with high priority label Mar 4, 2025
@Borewit
Copy link
Owner

Borewit commented Mar 5, 2025

Thanks for creating a reproduction repository @lowvisiondave !

The problem you are facing is because the node condition, a condition exports, is not correctly set when your project imports music-metadata.

Because node_modules/music-metadata/lib/index.d.ts does not include a type for parseFile.

It certainly does, it is right here:

export async function parseFile(filePath: string, options: IOptions = {}): Promise<IAudioMetadata> {

But you are not importing this file, you are importing the compiled version of core.ts, and that does indeed not have parseFile() included.

The reason your conditional export is not working, is most likely related to the fact you are using, "moduleResolution": "bundler", in your tsconfig.json. This module resolution, does not seem to set the node condition, maybe because it is designed for browser usage, I can only speculate why it done like that.

What I fear neither works is this (almost literally taken from TypeScript documentation)

{
  "compilerOptions": {
    "....": "",
    "moduleResolution": "bundler",
    "customConditions": ["node"],
     "....": "",
  }
}

Identical issue on file-type: sindresorhus/file-type#738

I will investigate possible workarounds, to be continued....

@Borewit
Copy link
Owner

Borewit commented Mar 5, 2025

Adding the "customConditions": ["node"] solves the issue, evidence: lowvisiondave/music-metadata-typescript-repro#1

@Borewit Borewit changed the title parseFile is missing in TypeScript types Cannot use parseFile if the TypeScript compiler moduleResolution is set to bundler Mar 5, 2025
@lowvisiondave
Copy link
Author

Interesting, I've never come across that before. Thanks for the explanation!

It might be worth adding a note to the documentation, since I experienced this on a fresh Next.js project and it was discouraging me from using your library.

@net
Copy link

net commented Mar 7, 2025

Also having this problem. Can this be made to just work out of the box? I've never encountered this issue with any other library before.

@Borewit
Copy link
Owner

Borewit commented Mar 9, 2025

Also having this problem. Can this be made to just work out of the box?

The problem is your TypeScript compiler does not including Node specific functionality, as it believes that if you set the module resolution to bundler , you won't need it.

What do you want me to do about that?

I've never encountered this issue with any other library before.

And which of those libraries have Node.js specific functionality, and nicely integrate browser platforms as well?

Raise the issue where it comes from:

@net
Copy link

net commented Mar 10, 2025

Apologies, that makes sense.

@net
Copy link

net commented Mar 10, 2025

I wonder if core.ts could include a stub parseFile() whose doc links to this issue and describes the fix for users on Node with moduleResolution set to bundler.

@Borewit
Copy link
Owner

Borewit commented Mar 10, 2025

I wonder if core.ts could include a stub parseFile() whose doc links to this issue and describes the fix for users on Node with moduleResolution set to bundler.

That is a very clever workaround @net.

It is not just not putting in a pointer to the documentation, it is actually sufficient to fool the TypeScript compiler to make it working.

I tested it with Nest.js, by adding to node_modules/music-metadata/lib/core.d.ts :

export declare function parseFile(filePath: string, options?: IOptions): Promise<IAudioMetadata>;

We could implement this in code, and in case it is called runtime we throw an error: "Not loaded with node condition enabled".

@net
Copy link

net commented Mar 10, 2025

Very nice! Probably should be a maximal descriptive runtime error since it could potentially be seen both by users in a browser runtime and users in a weird TypeScript runtime.

@Borewit
Copy link
Owner

Borewit commented Mar 10, 2025

Very nice! Probably should be a maximal descriptive runtime error since it could potentially be seen both by users in a browser runtime and users in a weird TypeScript runtime.

I agree, and third that parseFile is not designed to parse Web API File, which is also a common misunderstanding.

Can you review? (Written before reading your last suggestion): #2378

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
3 participants