medusajs / medusa

The world's most flexible commerce platform.
https://medusajs.com
MIT License
25.69k stars 2.56k forks source link

[@medusajs/js-sdk] ERR_UNSUPPORTED_DIR_IMPORT when using the `js-sdk` #9573

Open RATIU5 opened 2 weeks ago

RATIU5 commented 2 weeks ago

Bug report

Describe the bug

When installing and and using the @medusajs/js-sdk and write the code to setup a client, it throws an ERR_UNSUPPORTED_DIR_IMPORT error similar to the following:

node:internal/modules/esm/resolve:251                                                                                        
    throw new ERR_UNSUPPORTED_DIR_IMPORT(path, fileURLToPath(base), String(resolved));                                       
          ^                                                                                                                  

Error [ERR_UNSUPPORTED_DIR_IMPORT]: Directory import '/Users/username/storefront/node
_modules/.pnpm/@medusajs+js-sdk@1.0.0-rc-20241014171650_awilix@8.0.1_ioredis@5.4.1_vite@5.4.9_@types+node@22.7.5_/node_module
s/@medusajs/js-sdk/dist/esm/admin' is not supported resolving ES modules imported from /Users/username/storefront/node_modules/
.pnpm/@medusajs+js-sdk@1.0.0-rc-20241014171650_awilix@8.0.1_ioredis@5.4.1_vite@5.4.
9_@types+node@22.7.5_/node_modules/@medusajs/js-sdk/dist/esm/index.js                                                        
    at finalizeResolution (node:internal/modules/esm/resolve:251:11)                                                         
    at moduleResolve (node:internal/modules/esm/resolve:914:10)                                                              
    at defaultResolve (node:internal/modules/esm/resolve:1038:11)                                                            
    at ModuleLoader.defaultResolve (node:internal/modules/esm/loader:557:12)                                                 
    at ModuleLoader.resolve (node:internal/modules/esm/loader:525:25)                                                        
    at ModuleLoader.getModuleJob (node:internal/modules/esm/loader:246:38)                                                   
    at ModuleJob._link (node:internal/modules/esm/module_job:126:49) {                                                       
  code: 'ERR_UNSUPPORTED_DIR_IMPORT',                                                                                        
  url: 'file:///Users/username/storefront/node_modules/.pnpm/@medusajs+js-sdk@1.0.0-r
c-20241014171650_awilix@8.0.1_ioredis@5.4.1_vite@5.4.9_@types+node@22.7.5_/node_modules/@medusajs/js-sdk/dist/esm/admin'     
}                                                                                                                            

Node.js v22.9.0

I got the same error using the following package managers:

System information

Medusa version (including plugins): Only @medusajs/js-sdk rc-4 Node.js version: 22.9.0 Database: Postgres 16 Operating system: macOS 15 Browser (if relevant): Arc (chromium)

Steps to reproduce the behavior

  1. Create a new storefront with a chosen framework (or initialize an empty/blank npm project)
  2. Add "type": "module", to your package.json
  3. Install the @medusajs/js-sdk package with version "rc"
  4. Run the server to see the error

Expected behavior

The error simply should not appear, and the client should import successfully.

Screenshots

If applicable, add screenshots to help explain your problem

Code snippets

I tested this error without a framework on an empty npm project, with this code inside run.js:

import Medusa from "@medusajs/js-sdk";

const client = new Medusa({
  baseUrl: "http://localhost:9000",
});

const test = client.store.cart.retrieve("test");
console.log(test);

Then I ran node run.js to replicate the error.

This is what the package.json looks like for this empty project:

{
  "name": "test",
  "version": "1.0.0",
  "main": "run.js",
  "type": "module",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "description": "",
  "dependencies": {
    "@medusajs/js-sdk": "rc"
  }
}

Additional context

My guess is that this has to do with the bundling/transpiling of the typescript to javascript in the js-sdk package.

RATIU5 commented 2 weeks ago

For the time being, I setup a temporary fix using the following script to rewrite all the imports and exports to be explicit in defining the file name:

const fs = require("fs");
const path = require("path");

function fixImports(dir) {
  const files = fs.readdirSync(dir);

  files.forEach((file) => {
    const filePath = path.join(dir, file);
    const stat = fs.statSync(filePath);

    if (stat.isDirectory()) {
      fixImports(filePath);
    } else if (file.endsWith(".js")) {
      let content = fs.readFileSync(filePath, "utf8");

      // Fix imports
      content = content.replace(
        /from\s+['"](\.[^'"]+)['"]/g,
        (match, importPath) => {
          const fullPath = path.resolve(path.dirname(filePath), importPath);
          let relativePath = path
            .relative(path.dirname(filePath), fullPath)
            .replace(/\\/g, "/");

          if (!relativePath.startsWith(".")) {
            relativePath = "./" + relativePath;
          }

          if (fs.existsSync(fullPath + ".js")) {
            return `from '${relativePath}.js'`;
          } else if (fs.existsSync(path.join(fullPath, "index.js"))) {
            return `from '${relativePath}/index.js'`;
          }
          return match;
        },
      );

      // Fix exports
      content = content.replace(
        /export\s+.*from\s+['"](\.[^'"]+)['"]/g,
        (match, exportPath) => {
          const fullPath = path.resolve(path.dirname(filePath), exportPath);
          let relativePath = path
            .relative(path.dirname(filePath), fullPath)
            .replace(/\\/g, "/");

          if (!relativePath.startsWith(".")) {
            relativePath = "./" + relativePath;
          }

          if (fs.existsSync(fullPath + ".js")) {
            return match.replace(exportPath, relativePath + ".js");
          } else if (fs.existsSync(path.join(fullPath, "index.js"))) {
            return match.replace(exportPath, relativePath + "/index.js");
          }
          return match;
        },
      );

      fs.writeFileSync(filePath, content);
    }
  });
}

const esmDir = path.join(
  __dirname,
  "..",
  "node_modules",
  "@medusajs",
  "js-sdk",
  "dist",
  "esm",
);
fixImports(esmDir);
console.log("Fixed ESM imports and exports for @medusajs/js-sdk");