Repository: swc-project/swc (rust)

Issue:
Directory import error on compiled output
### Describe the bug

Hi everyone,

I have created a small reproducible example of the error which you can find [here](https://github.com/stelescuraul/dep-cruiser-issue).

Using path aliases in `tsconfig` and `swcrc`, the index.js filename is stripped from the end of the import path when using ESM modules. 

```
> npx swc -d ./dist -D --delete-dir-on-start --only="**/*.js,**/*.ts,**/*.cjs,**/*.mjs" --ignore ./node_modules,./dist .
> node dist/projects/api/main.js

Error [ERR_UNSUPPORTED_DIR_IMPORT]: Directory import 'workspaces/dist/libs/math' is not supported resolving ES modules imported from workspaces/dist/projects/api/main.js
```

The output of in the `dist/projects/api/main.js` looks like this:
```js
import { sum } from "../../libs/math"; <<-- should be /math/index.js
```

Renaming the file "index.js" to anything else resolves the issue and the path is added correctly. EG renaming it to `main.js`:
```js
import { sum } from "../../libs/math/main.js"; <<-- main.js is correctly appended
```

This issue seems to have been introduced in `1.3.106`. last version that worked with this setup was `1.3.105`

### Input code

```typescript
// projects/api/main.ts

import { sum } from "@foo/math";

console.log(sum(1, 2));
```


### Config

```json
{
  "$schema": "https://json.schemastore.org/swcrc",
  "isModule": true,
  "jsc": {
    "target": "es2022",
    "keepClassNames": true,
    "loose": false,
    "baseUrl": ".",
    "paths": {
      "@foo/math": ["libs/math/index.js"],
      "@foo/math/*": ["libs/math/*"],
      "@foo/common": ["libs/common/main.js"]
    },
    "parser": {
      "syntax": "typescript"
    }
  },
  "minify": false,
  "module": {
    "type": "es6",
    "resolveFully": true
  }
}
```


### Playground link (or link to the minimal reproduction)

https://github.com/stelescuraul/dep-cruiser-issue

### SWC Info output

_No response_

### Expected behavior

Correctly append `/index.js` for path aliases.

### Actual behavior

_No response_

### Version

>1.3.105

### Additional context

_No response_

Pull request:
fix(es/module): Fix `jsc.paths` with `resolveFully`
**Description:**


**Related issue:**

 - Closes #8782

Patch:
diff --git a/crates/swc_ecma_loader/src/resolvers/tsc.rs b/crates/swc_ecma_loader/src/resolvers/tsc.rs
index aaf0c03563..293b7e578f 100644
--- a/crates/swc_ecma_loader/src/resolvers/tsc.rs
+++ b/crates/swc_ecma_loader/src/resolvers/tsc.rs
@@ -289,7 +289,10 @@ where
                     let slug = to[0]
                         .split([std::path::MAIN_SEPARATOR, '/'])
                         .last()
-                        .map(|v| v.into());
+                        .filter(|&slug| slug != "index.ts" && slug != "index.tsx")
+                        .map(|v| v.split_once('.').map(|v| v.0).unwrap_or(v))
+                        .map(From::from);
+
                     if tp.is_absolute() {
                         return Ok(Resolution {
                             filename: FileName::Real(tp.into()),
@@ -297,18 +300,10 @@ where
                         });
                     }
 
-                    if let Ok(res) = self.resolve(&self.base_url_filename, &format!("./{}", &to[0]))
+                    if let Ok(res) = self
+                        .invoke_inner_resolver(&self.base_url_filename, &format!("./{}", &to[0]))
                     {
-                        return Ok(Resolution {
-                            slug: match &res.filename {
-                                FileName::Real(p) => p
-                                    .file_stem()
-                                    .filter(|&s| s != "index")
-                                    .map(|v| v.to_string_lossy().into()),
-                                _ => None,
-                            },
-                            ..res
-                        });
+                        return Ok(Resolution { slug, ..res });
                     }
 
                     return Ok(Resolution {


Test patch:
diff --git a/crates/swc/tests/fixture/issues-7xxx/7829/1/input/.swcrc b/crates/swc/tests/fixture/issues-7xxx/7829/1/input/.swcrc
index d4cbce916e..ba1eaadb2d 100644
--- a/crates/swc/tests/fixture/issues-7xxx/7829/1/input/.swcrc
+++ b/crates/swc/tests/fixture/issues-7xxx/7829/1/input/.swcrc
@@ -1,6 +1,7 @@
 {
     "module": {
-        "type": "es6"
+        "type": "es6",
+        "resolveFully": true
     },
     "jsc": {
         "baseUrl": ".",
diff --git a/crates/swc/tests/fixture/issues-7xxx/7829/1/output/1.js b/crates/swc/tests/fixture/issues-7xxx/7829/1/output/1.js
index f11774c357..f8527ad825 100644
--- a/crates/swc/tests/fixture/issues-7xxx/7829/1/output/1.js
+++ b/crates/swc/tests/fixture/issues-7xxx/7829/1/output/1.js
@@ -1,2 +1,2 @@
-import { fn } from "./libs/pkg/src/index.ts";
+import { fn } from "./libs/pkg/src/index.js";
 console.log(fn);
diff --git a/crates/swc/tests/fixture/issues-7xxx/7829/2/input/.swcrc b/crates/swc/tests/fixture/issues-7xxx/7829/2/input/.swcrc
index a7f2c9c9ca..5e0a285b2b 100644
--- a/crates/swc/tests/fixture/issues-7xxx/7829/2/input/.swcrc
+++ b/crates/swc/tests/fixture/issues-7xxx/7829/2/input/.swcrc
@@ -1,6 +1,7 @@
 {
     "module": {
-        "type": "es6"
+        "type": "es6",
+        "resolveFully": true
     },
     "jsc": {
         "baseUrl": ".",
diff --git a/crates/swc/tests/fixture/issues-7xxx/7898/1/output/index.ts b/crates/swc/tests/fixture/issues-7xxx/7898/1/output/index.ts
index e080b6248a..5ac4603ec6 100644
--- a/crates/swc/tests/fixture/issues-7xxx/7898/1/output/index.ts
+++ b/crates/swc/tests/fixture/issues-7xxx/7898/1/output/index.ts
@@ -2,5 +2,5 @@
 Object.defineProperty(exports, "__esModule", {
     value: true
 });
-const _a = require("./packages/a/src/index.ts");
+const _a = require("./packages/a/src/index.js");
 console.log(`${(0, _a.displayA)()}`);
diff --git a/crates/swc/tests/fixture/issues-8xxx/8782/input/.swcrc b/crates/swc/tests/fixture/issues-8xxx/8782/input/.swcrc
new file mode 100644
index 0000000000..b5fe835cde
--- /dev/null
+++ b/crates/swc/tests/fixture/issues-8xxx/8782/input/.swcrc
@@ -0,0 +1,23 @@
+{
+  "$schema": "https://json.schemastore.org/swcrc",
+  "isModule": true,
+  "jsc": {
+    "target": "es2022",
+    "keepClassNames": true,
+    "loose": false,
+    "baseUrl": ".",
+    "paths": {
+      "@foo/math": ["libs/math/index.js"],
+      "@foo/math/*": ["libs/math/*"],
+      "@foo/common": ["libs/common/main.js"]
+    },
+    "parser": {
+      "syntax": "typescript"
+    }
+  },
+  "minify": false,
+  "module": {
+    "type": "es6",
+    "resolveFully": true
+  }
+}
diff --git a/crates/swc/tests/fixture/issues-8xxx/8782/input/libs/common/main.js b/crates/swc/tests/fixture/issues-8xxx/8782/input/libs/common/main.js
new file mode 100644
index 0000000000..6454def9fa
--- /dev/null
+++ b/crates/swc/tests/fixture/issues-8xxx/8782/input/libs/common/main.js
@@ -0,0 +1,1 @@
+export const commonStuff = 'common string';
diff --git a/crates/swc/tests/fixture/issues-8xxx/8782/input/libs/math/index.js b/crates/swc/tests/fixture/issues-8xxx/8782/input/libs/math/index.js
new file mode 100644
index 0000000000..acbaf9c00d
--- /dev/null
+++ b/crates/swc/tests/fixture/issues-8xxx/8782/input/libs/math/index.js
@@ -0,0 +1,9 @@
+import { models } from "../../projects/api/models.js";
+
+console.log(models);
+
+export { foo } from "./src/foo.js";
+
+export const sum = function(a, b) {
+  return a + b;
+};
diff --git a/crates/swc/tests/fixture/issues-8xxx/8782/input/libs/math/src/foo.js b/crates/swc/tests/fixture/issues-8xxx/8782/input/libs/math/src/foo.js
new file mode 100644
index 0000000000..ad5d062e40
--- /dev/null
+++ b/crates/swc/tests/fixture/issues-8xxx/8782/input/libs/math/src/foo.js
@@ -0,0 +1,5 @@
+// import { commonStuff } from '../../common/index.js';
+import { commonStuff } from '@foo/common';
+console.log(commonStuff)
+
+export const foo = 'foo';
diff --git a/crates/swc/tests/fixture/issues-8xxx/8782/input/projects/api/main.ts b/crates/swc/tests/fixture/issues-8xxx/8782/input/projects/api/main.ts
new file mode 100644
index 0000000000..b1e98e0819
--- /dev/null
+++ b/crates/swc/tests/fixture/issues-8xxx/8782/input/projects/api/main.ts
@@ -0,0 +1,6 @@
+import { sum } from "@foo/math";
+// import { foo } from "@foo/math/src/foo";
+import { foo } from "@foo/math/src/foo.js";
+console.log(foo);
+
+console.log(sum(1, 2));
diff --git a/crates/swc/tests/fixture/issues-8xxx/8782/input/projects/api/models.js b/crates/swc/tests/fixture/issues-8xxx/8782/input/projects/api/models.js
new file mode 100644
index 0000000000..c4987de551
--- /dev/null
+++ b/crates/swc/tests/fixture/issues-8xxx/8782/input/projects/api/models.js
@@ -0,0 +1,3 @@
+export const models = {
+  foo: 'foo'
+}
diff --git a/crates/swc/tests/fixture/issues-8xxx/8782/output/libs/common/main.js b/crates/swc/tests/fixture/issues-8xxx/8782/output/libs/common/main.js
new file mode 100644
index 0000000000..6454def9fa
--- /dev/null
+++ b/crates/swc/tests/fixture/issues-8xxx/8782/output/libs/common/main.js
@@ -0,0 +1,1 @@
+export const commonStuff = 'common string';
diff --git a/crates/swc/tests/fixture/issues-8xxx/8782/output/libs/math/index.js b/crates/swc/tests/fixture/issues-8xxx/8782/output/libs/math/index.js
new file mode 100644
index 0000000000..dfe8dba5cd
--- /dev/null
+++ b/crates/swc/tests/fixture/issues-8xxx/8782/output/libs/math/index.js
@@ -0,0 +1,6 @@
+import { models } from "../../projects/api/models.js";
+console.log(models);
+export { foo } from "./src/foo.js";
+export const sum = function(a, b) {
+    return a + b;
+};
diff --git a/crates/swc/tests/fixture/issues-8xxx/8782/output/libs/math/src/foo.js b/crates/swc/tests/fixture/issues-8xxx/8782/output/libs/math/src/foo.js
new file mode 100644
index 0000000000..576185a3f2
--- /dev/null
+++ b/crates/swc/tests/fixture/issues-8xxx/8782/output/libs/math/src/foo.js
@@ -0,0 +1,4 @@
+// import { commonStuff } from '../../common/index.js';
+import { commonStuff } from "../../common/main.js";
+console.log(commonStuff);
+export const foo = 'foo';
diff --git a/crates/swc/tests/fixture/issues-8xxx/8782/output/projects/api/main.ts b/crates/swc/tests/fixture/issues-8xxx/8782/output/projects/api/main.ts
new file mode 100644
index 0000000000..e3ca8bf473
--- /dev/null
+++ b/crates/swc/tests/fixture/issues-8xxx/8782/output/projects/api/main.ts
@@ -0,0 +1,5 @@
+import { sum } from "../../libs/math/index.js";
+// import { foo } from "@foo/math/src/foo";
+import { foo } from "../../libs/math/src/foo.js";
+console.log(foo);
+console.log(sum(1, 2));
diff --git a/crates/swc/tests/fixture/issues-8xxx/8782/output/projects/api/models.js b/crates/swc/tests/fixture/issues-8xxx/8782/output/projects/api/models.js
new file mode 100644
index 0000000000..1c5d906f61
--- /dev/null
+++ b/crates/swc/tests/fixture/issues-8xxx/8782/output/projects/api/models.js
@@ -0,0 +1,3 @@
+export const models = {
+    foo: 'foo'
+};
diff --git a/crates/swc_ecma_loader/tests/tsc_resolver.rs b/crates/swc_ecma_loader/tests/tsc_resolver.rs
index a8cebfa6a9..b806707ce1 100644
--- a/crates/swc_ecma_loader/tests/tsc_resolver.rs
+++ b/crates/swc_ecma_loader/tests/tsc_resolver.rs
@@ -41,7 +41,7 @@ fn exact() {
             resolved,
             Resolution {
                 filename: FileName::Custom("success".into()),
-                slug: None
+                slug: Some("jquery".into())
             }
         );
     }
diff --git a/crates/swc_ecma_transforms_module/tests/path_node.rs b/crates/swc_ecma_transforms_module/tests/path_node.rs
index 62c3e6298d..10fcf48cf0 100644
--- a/crates/swc_ecma_transforms_module/tests/path_node.rs
+++ b/crates/swc_ecma_transforms_module/tests/path_node.rs
@@ -99,7 +99,7 @@ fn paths_resolver(base_dir: &Path, rules: Vec<(String, Vec<String>)>) -> JscPath
         ),
         swc_ecma_transforms_module::path::Config {
             base_dir: Some(base_dir),
-            resolve_fully: false,
+            resolve_fully: true,
         },
     )
 }
diff --git a/crates/swc_ecma_transforms_module/tests/paths/issue-7417/output/index.ts b/crates/swc_ecma_transforms_module/tests/paths/issue-7417/output/index.ts
index d2b5aa4bb4..bd56226a5a 100644
--- a/crates/swc_ecma_transforms_module/tests/paths/issue-7417/output/index.ts
+++ b/crates/swc_ecma_transforms_module/tests/paths/issue-7417/output/index.ts
@@ -1,4 +1,4 @@
-import o from ".";
+import o from "./index.js";
 export default function bar() {
     console.log(o);
 }
diff --git a/node-swc/__tests__/transform/issue_4730_test.mjs b/node-swc/__tests__/transform/issue_4730_test.mjs
index 825e6cb0ca..a9c6e20ef4 100644
--- a/node-swc/__tests__/transform/issue_4730_test.mjs
+++ b/node-swc/__tests__/transform/issue_4730_test.mjs
@@ -30,6 +30,7 @@ it("should work", async () => {
         },
         module: {
             type: "commonjs",
+            resolveFully: true,
         },
     });
     expect(code).toMatchInlineSnapshot(`