sindresorhus/file-type

NextJS - cannot import fileTypeFromFile

nktnet1 opened this issue · 5 comments

Description

My project is using the NextJS framework (will self-host on a server with access to fs storage).

I'm getting this error:

'"file-type"' has no exported member named 'fileTypeFromFile'. Did you mean 'fileTypeFromBlob'?ts(2724)

When trying to:

import { fileTypeFromFile } from 'file-type';

Is there a way to make it work?

tsconfig.json
{
  "compilerOptions": {
    "target": "ES2017",
    "lib": [
      "dom",
      "dom.iterable",
      "esnext"
    ],
    "allowJs": true,
    "skipLibCheck": true,
    "verbatimModuleSyntax": true,
    "strict": true,
    "noEmit": true,
    "esModuleInterop": true,
    "module": "esnext",
    "moduleResolution": "bundler",
    "resolveJsonModule": true,
    "isolatedModules": true,
    "jsx": "preserve",
    "incremental": true,
    "plugins": [
      {
        "name": "next"
      }
    ],
    "paths": {
      "@/*": [
        "./src/*"
      ]
    }
  },
  "include": [
    "**/*.ts",
    "**/*.tsx",
    "dist/types/**/*.ts",
    "next-env.d.ts",
    "postcss.config.js",
    ".next/types/**/*.ts"
  ],
  "exclude": [
    "node_modules",
  ]
}
package.json
{
  // ...
  "type": "module",
  "engines": {
    "node": ">=18"
  }
  // ...
}

Existing Issue Check

  • I have searched the existing issues and could not find any related to my problem.

ESM (ECMAScript Module) Requirement Acknowledgment

  • My project is an ESM project and my package.json contains the following entry: "type": "module".

File-Type Scope Acknowledgment

  • I understand that file-type detects binary file types and not text or other formats.

If you can import fileTypeFromBlob() and you cannot use fileTypeFromFile() (being a function which require the Node engine), then the conditional exports1 are not correctly processed by Nest.js Next.js.

This is how the exports are defined:

file-type/package.json

Lines 14 to 29 in 1fe621a

"exports": {
".": {
"node": {
"types": "./index.d.ts",
"import": "./index.js"
},
"default": {
"types": "./core.d.ts",
"import": "./core.js"
}
},
"./core": {
"types": "./core.d.ts",
"import": "./core.js"
}
},

That means Nest.js is not following the "node" condition, but picks the "default" condition instead.

You may want to consider to raise this issue at Nest.js Next.js.

Footnotes

  1. https://nodejs.org/api/packages.html#conditional-exports

Hey @Borewit - thank you for your response.

However, I'm using NextJS instead of NestJS, and I'm using fileTypeFromFile server side along with other NodeJS specific features, e.g.

import fs from 'fs';

My application is self-hosted with server infrastructure - it's not being deployed as a serverless app on Vercel.

Next.js is is, sorry for confusing this with Nest,js.

Totally clear, you are running server side, you run in an engine which should have access to the file system (Node specific API), so you would expect fileTypeFromFile() would work. Also you import statement (import { fileTypeFromFile } from 'file-type';) is fine.

Problem is that the Node specific functions are not loaded. And that problem lies somewhere in technical stack you are using, I suspect Nextjs. With Node.js, which is the one and only reference engine, it is certainly working.

Alright, thank you for the follow-up @Borewit. I'll close the issue here.

EDIT: The workaround is to change the default NextJS tsconfig.json from

    "moduleResolution": "bundler",

to

    "moduleResolution": "node",

Although there are caveats - see #652.

Ah I see, I was not aware TypeScript was used. I have no problem for an explicit sub-path export for such scenario, but the owner of file-type disagrees.

If you use TypeScript in combination with CommonJS (your package.json does not contain type: module), check: load-esm.