@reliverse/pathkit 1.2.0 → 1.2.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +510 -247
- package/bin/impl/getFileImportsExports.d.ts +2 -0
- package/bin/impl/getFileImportsExports.js +44 -5
- package/bin/mod.js +3 -2
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,247 +1,510 @@
|
|
|
1
|
-
# pathkit • cross‑platform path manipulation
|
|
2
|
-
|
|
3
|
-
> @reliverse/pathkit is a slash‑consistent, cross‑platform path manipulation, with POSIX forward slash, drop‑in for node:path and unjs/pathe. This library extends the node:path module with a set of functions for manipulating file paths.
|
|
4
|
-
|
|
5
|
-
[sponsor](https://github.com/sponsors/blefnk) • [discord](https://discord.gg/Pb8uKbwpsJ) • [npm](https://npmjs.com/package/@reliverse/pathkit) • [repo](https://github.com/reliverse/pathkit)
|
|
6
|
-
|
|
7
|
-
## Key Features
|
|
8
|
-
|
|
9
|
-
- 🔹 **drop in** and replace `node:path` and `unjs/pathe` instantly
|
|
10
|
-
- ➕ **`unjs/pathe` on steroids** – alias resolution, import parsing, and more
|
|
11
|
-
- 🌀 **always `/`** – posix separators 100% of the time (buh‑bye `\\`)
|
|
12
|
-
- ⚙️ **node.js api compatible** – familiar methods, no learning curve
|
|
13
|
-
- 🚀 **modern & fast** – typescript, pure esm, bun & node‑ready
|
|
14
|
-
- 🧠 **predictable & testable** – deterministic output across windows / macos / linux
|
|
15
|
-
- 🧼 **no dependencies** – just better path api + couple of cool utilities = [4kB](https://bundlephobia.com/package/@reliverse/pathkit@latest)
|
|
16
|
-
|
|
17
|
-
## Installation
|
|
18
|
-
|
|
19
|
-
```bash
|
|
20
|
-
# bun • pnpm • yarn • npm
|
|
21
|
-
bun add @reliverse/pathkit
|
|
22
|
-
```
|
|
23
|
-
|
|
24
|
-
**Migrate**:
|
|
25
|
-
|
|
26
|
-
```bash
|
|
27
|
-
# soon:
|
|
28
|
-
# bun add -D @reliverse/dler
|
|
29
|
-
# bun dler migrate --lib path-to-pathkit
|
|
30
|
-
# bun dler migrate --lib pathe-to-pathkit
|
|
31
|
-
```
|
|
32
|
-
|
|
33
|
-
### `unjs/pathe` vs `@reliverse/pathkit`
|
|
34
|
-
|
|
35
|
-
| Package | What you get | When to use |
|
|
36
|
-
|---------|--------------|-------------|
|
|
37
|
-
| **`pathe`** | Path API only (with POSIX everywhere) | You only need a drop‑in for `node:path` |
|
|
38
|
-
| **`pathkit`** | Everything in `pathe` **+** advanced utilities | You need alias resolution, import transforms, etc. |
|
|
39
|
-
|
|
40
|
-
## Why Pathkit? — The Problem with Native Paths
|
|
41
|
-
|
|
42
|
-
Native `node:path` flips behavior between operating systems, spurring subtle bugs and OS checks.
|
|
43
|
-
|
|
44
|
-
```js
|
|
45
|
-
// With node:path – the same call may yield different separators on each OS
|
|
46
|
-
import path from "node:path";
|
|
47
|
-
|
|
48
|
-
const project = "users/blefnk/project";
|
|
49
|
-
const full = path.join("C:\\", project);
|
|
50
|
-
console.log(full); // "C:\\users\\blefnk\\project" (Windows) vs ??? (others)
|
|
51
|
-
```
|
|
52
|
-
|
|
53
|
-
### ✅ The `pathkit` Fix
|
|
54
|
-
|
|
55
|
-
```js
|
|
56
|
-
import { join } from "@reliverse/pathkit";
|
|
57
|
-
|
|
58
|
-
const full = join("C:", "users", "blefnk", "project");
|
|
59
|
-
console.log(full); // "C:/users/blefnk/project" on **every** OS 🎉
|
|
60
|
-
```
|
|
61
|
-
|
|
62
|
-
| Pain Point | `@reliverse/pathkit` Solution |
|
|
63
|
-
| :----------------------------- | :--------------------------- |
|
|
64
|
-
| Inconsistent separators | ✅ Always `/` |
|
|
65
|
-
| OS‑specific work‑arounds | ✅ One code path |
|
|
66
|
-
| Needs TypeScript + ESM | ✅ Built‑in |
|
|
67
|
-
| Works in Bun / Deno / Node | ✅ Out of the box |
|
|
68
|
-
|
|
69
|
-
## Quick Start
|
|
70
|
-
|
|
71
|
-
```ts
|
|
72
|
-
import { resolve, join, normalize } from "@reliverse/pathkit";
|
|
73
|
-
|
|
74
|
-
// Mixed slashes & dot‑segments? No problem.
|
|
75
|
-
const messy = "src\\..\\./dist///file.js";
|
|
76
|
-
console.log(resolve(messy)); // → "dist/file.js"
|
|
77
|
-
|
|
78
|
-
// Join is predictable everywhere:
|
|
79
|
-
console.log(join("users", "blefnk")); // → "users/blefnk"
|
|
80
|
-
```
|
|
81
|
-
|
|
82
|
-
**Side‑by‑Side Demo**:
|
|
83
|
-
|
|
84
|
-
| Code | Windows Output | macOS / Linux Output |
|
|
85
|
-
|------|----------------|----------------------|
|
|
86
|
-
| `join("a", "b")` | `a/b` | `a/b` |
|
|
87
|
-
| `resolve("..", "x")` | `x` | `x` |
|
|
88
|
-
|
|
89
|
-
Say goodbye to `process.platform` conditionals 👋.
|
|
90
|
-
|
|
91
|
-
## pathkit advanced features
|
|
92
|
-
|
|
93
|
-
`@reliverse/pathkit` extends the core functionality of `node:path` with powerful utilities for working with imports, aliases, and more.
|
|
94
|
-
|
|
95
|
-
### Import/Export Analysis
|
|
96
|
-
|
|
97
|
-
The `getFileImportsExports` function provides detailed analysis of ES module imports and exports:
|
|
98
|
-
|
|
99
|
-
```ts
|
|
100
|
-
import { getFileImportsExports } from "@reliverse/pathkit";
|
|
101
|
-
|
|
102
|
-
const code = `
|
|
103
|
-
import { ref } from "vue";
|
|
104
|
-
import utils from "@/utils";
|
|
105
|
-
import type { Config } from "./types";
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
1
|
+
# pathkit • cross‑platform path manipulation
|
|
2
|
+
|
|
3
|
+
> @reliverse/pathkit is a slash‑consistent, cross‑platform path manipulation, with POSIX forward slash, drop‑in for node:path and unjs/pathe. This library extends the node:path module with a set of functions for manipulating file paths.
|
|
4
|
+
|
|
5
|
+
[sponsor](https://github.com/sponsors/blefnk) • [discord](https://discord.gg/Pb8uKbwpsJ) • [npm](https://npmjs.com/package/@reliverse/pathkit) • [repo](https://github.com/reliverse/pathkit)
|
|
6
|
+
|
|
7
|
+
## Key Features
|
|
8
|
+
|
|
9
|
+
- 🔹 **drop in** and replace `node:path` and `unjs/pathe` instantly
|
|
10
|
+
- ➕ **`unjs/pathe` on steroids** – alias resolution, import parsing, and more
|
|
11
|
+
- 🌀 **always `/`** – posix separators 100% of the time (buh‑bye `\\`)
|
|
12
|
+
- ⚙️ **node.js api compatible** – familiar methods, no learning curve
|
|
13
|
+
- 🚀 **modern & fast** – typescript, pure esm, bun & node‑ready
|
|
14
|
+
- 🧠 **predictable & testable** – deterministic output across windows / macos / linux
|
|
15
|
+
- 🧼 **no dependencies** – just better path api + couple of cool utilities = [4kB](https://bundlephobia.com/package/@reliverse/pathkit@latest)
|
|
16
|
+
|
|
17
|
+
## Installation
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
# bun • pnpm • yarn • npm
|
|
21
|
+
bun add @reliverse/pathkit
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
**Migrate**:
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
# soon:
|
|
28
|
+
# bun add -D @reliverse/dler
|
|
29
|
+
# bun dler migrate --lib path-to-pathkit
|
|
30
|
+
# bun dler migrate --lib pathe-to-pathkit
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
### `unjs/pathe` vs `@reliverse/pathkit`
|
|
34
|
+
|
|
35
|
+
| Package | What you get | When to use |
|
|
36
|
+
|---------|--------------|-------------|
|
|
37
|
+
| **`pathe`** | Path API only (with POSIX everywhere) | You only need a drop‑in for `node:path` |
|
|
38
|
+
| **`pathkit`** | Everything in `pathe` **+** advanced utilities | You need alias resolution, import transforms, etc. |
|
|
39
|
+
|
|
40
|
+
## Why Pathkit? — The Problem with Native Paths
|
|
41
|
+
|
|
42
|
+
Native `node:path` flips behavior between operating systems, spurring subtle bugs and OS checks.
|
|
43
|
+
|
|
44
|
+
```js
|
|
45
|
+
// With node:path – the same call may yield different separators on each OS
|
|
46
|
+
import path from "node:path";
|
|
47
|
+
|
|
48
|
+
const project = "users/blefnk/project";
|
|
49
|
+
const full = path.join("C:\\", project);
|
|
50
|
+
console.log(full); // "C:\\users\\blefnk\\project" (Windows) vs ??? (others)
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
### ✅ The `pathkit` Fix
|
|
54
|
+
|
|
55
|
+
```js
|
|
56
|
+
import { join } from "@reliverse/pathkit";
|
|
57
|
+
|
|
58
|
+
const full = join("C:", "users", "blefnk", "project");
|
|
59
|
+
console.log(full); // "C:/users/blefnk/project" on **every** OS 🎉
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
| Pain Point | `@reliverse/pathkit` Solution |
|
|
63
|
+
| :----------------------------- | :--------------------------- |
|
|
64
|
+
| Inconsistent separators | ✅ Always `/` |
|
|
65
|
+
| OS‑specific work‑arounds | ✅ One code path |
|
|
66
|
+
| Needs TypeScript + ESM | ✅ Built‑in |
|
|
67
|
+
| Works in Bun / Deno / Node | ✅ Out of the box |
|
|
68
|
+
|
|
69
|
+
## Quick Start
|
|
70
|
+
|
|
71
|
+
```ts
|
|
72
|
+
import { resolve, join, normalize } from "@reliverse/pathkit";
|
|
73
|
+
|
|
74
|
+
// Mixed slashes & dot‑segments? No problem.
|
|
75
|
+
const messy = "src\\..\\./dist///file.js";
|
|
76
|
+
console.log(resolve(messy)); // → "dist/file.js"
|
|
77
|
+
|
|
78
|
+
// Join is predictable everywhere:
|
|
79
|
+
console.log(join("users", "blefnk")); // → "users/blefnk"
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
**Side‑by‑Side Demo**:
|
|
83
|
+
|
|
84
|
+
| Code | Windows Output | macOS / Linux Output |
|
|
85
|
+
|------|----------------|----------------------|
|
|
86
|
+
| `join("a", "b")` | `a/b` | `a/b` |
|
|
87
|
+
| `resolve("..", "x")` | `x` | `x` |
|
|
88
|
+
|
|
89
|
+
Say goodbye to `process.platform` conditionals 👋.
|
|
90
|
+
|
|
91
|
+
## pathkit advanced features
|
|
92
|
+
|
|
93
|
+
`@reliverse/pathkit` extends the core functionality of `node:path` with powerful utilities for working with imports, aliases, and more.
|
|
94
|
+
|
|
95
|
+
### Import/Export Analysis
|
|
96
|
+
|
|
97
|
+
The `getFileImportsExports` function provides detailed analysis of ES module imports and exports in your code:
|
|
98
|
+
|
|
99
|
+
```ts
|
|
100
|
+
import { getFileImportsExports } from "@reliverse/pathkit";
|
|
101
|
+
|
|
102
|
+
const code = `
|
|
103
|
+
import { ref } from "vue";
|
|
104
|
+
import utils from "@/utils";
|
|
105
|
+
import type { Config } from "./types";
|
|
106
|
+
import * as React from "react";
|
|
107
|
+
import { Button as UIButton } from "./components";
|
|
108
|
+
export { default as MyComponent } from "./MyComponent";
|
|
109
|
+
export type { Props } from "./types";
|
|
110
|
+
`;
|
|
111
|
+
|
|
112
|
+
const analysis = getFileImportsExports(code, {
|
|
113
|
+
kind: "all", // "import" | "export" | "all"
|
|
114
|
+
pathTypes: ["alias"], // Filter by path types: "alias" | "relative" | "absolute" | "bare" | "module"
|
|
115
|
+
limitPerType: 2 // Limit results per type
|
|
116
|
+
});
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
The analysis provides rich information about each import/export statement:
|
|
120
|
+
|
|
121
|
+
```ts
|
|
122
|
+
interface ImportExportInfo {
|
|
123
|
+
statement: string; // Full original statement
|
|
124
|
+
type: "static" | "dynamic"; // Import type (static or dynamic import())
|
|
125
|
+
kind: "import" | "export"; // Statement kind
|
|
126
|
+
source?: string; // Import/export source path
|
|
127
|
+
pathType?: "alias" | "relative" | "absolute" | "bare" | "module";
|
|
128
|
+
pathTypeSymbol?: string; // Path prefix (e.g., "@/", "~/")
|
|
129
|
+
isTypeOnly?: boolean; // Type-only import/export
|
|
130
|
+
specifiers?: { // Imported/exported items
|
|
131
|
+
type: "named" | "default" | "namespace" | "all";
|
|
132
|
+
name: string;
|
|
133
|
+
alias?: string;
|
|
134
|
+
isType?: boolean;
|
|
135
|
+
}[];
|
|
136
|
+
start: number; // Position in source
|
|
137
|
+
end: number;
|
|
138
|
+
importExt?: string; // Extension as written in import/export statement
|
|
139
|
+
realFileExt?: string; // Likely actual file extension (e.g., .ts for .js imports)
|
|
140
|
+
}
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
Features:
|
|
144
|
+
|
|
145
|
+
- ✨ **Comprehensive Syntax Support**
|
|
146
|
+
- Static imports (`import x from "y"`)
|
|
147
|
+
- Dynamic imports (`import("y")`)
|
|
148
|
+
- Named imports/exports (`import { x } from "y"`)
|
|
149
|
+
- Default imports/exports (`import x from "y"`)
|
|
150
|
+
- Namespace imports (`import * as x from "y"`)
|
|
151
|
+
- Re-exports (`export * from "y"`)
|
|
152
|
+
- Type imports/exports (`import type { x } from "y"`)
|
|
153
|
+
|
|
154
|
+
- 🔍 **Path Analysis**
|
|
155
|
+
- Detects path types (alias, relative, absolute, bare, module)
|
|
156
|
+
- Extracts path prefixes (e.g., `@/`, `~/`)
|
|
157
|
+
- Preserves original path format
|
|
158
|
+
- Tracks both import statement extensions and likely real file extensions
|
|
159
|
+
- Handles TypeScript/JavaScript extension conversion (e.g., `.js` → `.ts`)
|
|
160
|
+
|
|
161
|
+
- 🎯 **Specifier Details**
|
|
162
|
+
- Named imports/exports with aliases
|
|
163
|
+
- Default imports/exports
|
|
164
|
+
- Namespace imports
|
|
165
|
+
- Type-only imports/exports
|
|
166
|
+
- Mixed type and value imports
|
|
167
|
+
|
|
168
|
+
- 📊 **Filtering Options**
|
|
169
|
+
- Filter by statement kind (import/export)
|
|
170
|
+
- Filter by path types
|
|
171
|
+
- Limit results per type
|
|
172
|
+
- Preserve statement order
|
|
173
|
+
|
|
174
|
+
- 🛡️ **Type Safety**
|
|
175
|
+
- Full TypeScript support
|
|
176
|
+
- Detailed type definitions
|
|
177
|
+
- Null-safe operations
|
|
178
|
+
|
|
179
|
+
Example output:
|
|
180
|
+
|
|
181
|
+
```ts
|
|
182
|
+
[
|
|
183
|
+
{
|
|
184
|
+
statement: 'import { ref } from "vue"',
|
|
185
|
+
type: "static",
|
|
186
|
+
kind: "import",
|
|
187
|
+
source: "vue",
|
|
188
|
+
pathType: "bare",
|
|
189
|
+
specifiers: [{
|
|
190
|
+
type: "named",
|
|
191
|
+
name: "ref"
|
|
192
|
+
}],
|
|
193
|
+
start: 0,
|
|
194
|
+
end: 24,
|
|
195
|
+
importExt: "",
|
|
196
|
+
realFileExt: ""
|
|
197
|
+
},
|
|
198
|
+
{
|
|
199
|
+
statement: 'import type { Config } from "./types.js"',
|
|
200
|
+
type: "static",
|
|
201
|
+
kind: "import",
|
|
202
|
+
source: "./types.js",
|
|
203
|
+
pathType: "relative",
|
|
204
|
+
isTypeOnly: true,
|
|
205
|
+
specifiers: [{
|
|
206
|
+
type: "named",
|
|
207
|
+
name: "Config",
|
|
208
|
+
isType: true
|
|
209
|
+
}],
|
|
210
|
+
start: 45,
|
|
211
|
+
end: 85,
|
|
212
|
+
importExt: ".js",
|
|
213
|
+
realFileExt: ".ts"
|
|
214
|
+
}
|
|
215
|
+
]
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
### Path Transformation
|
|
219
|
+
|
|
220
|
+
Convert between different path formats:
|
|
221
|
+
|
|
222
|
+
```ts
|
|
223
|
+
import { convertImportPaths } from "@reliverse/pathkit";
|
|
224
|
+
|
|
225
|
+
await convertImportPaths({
|
|
226
|
+
baseDir: "./src",
|
|
227
|
+
fromType: "relative", // "./components/Button"
|
|
228
|
+
toType: "alias", // "@/components/Button"
|
|
229
|
+
aliasPrefix: "@/",
|
|
230
|
+
generateSourceMap: true
|
|
231
|
+
});
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
### Extension Conversion
|
|
235
|
+
|
|
236
|
+
```ts
|
|
237
|
+
import { convertImportsExt } from "@reliverse/pathkit";
|
|
238
|
+
|
|
239
|
+
// Basic usage - convert all relative imports to .ts
|
|
240
|
+
await convertImportsExt({
|
|
241
|
+
targetDir: "./src",
|
|
242
|
+
extFrom: "none",
|
|
243
|
+
extTo: "ts"
|
|
244
|
+
});
|
|
245
|
+
|
|
246
|
+
// Convert .js to .ts
|
|
247
|
+
await convertImportsExt({
|
|
248
|
+
targetDir: "./src",
|
|
249
|
+
extFrom: "js",
|
|
250
|
+
extTo: "ts"
|
|
251
|
+
});
|
|
252
|
+
|
|
253
|
+
// Remove extensions
|
|
254
|
+
await convertImportsExt({
|
|
255
|
+
targetDir: "./src",
|
|
256
|
+
extFrom: "ts",
|
|
257
|
+
extTo: "none"
|
|
258
|
+
});
|
|
259
|
+
|
|
260
|
+
// Handle alias paths (e.g. @/components)
|
|
261
|
+
await convertImportsExt({
|
|
262
|
+
targetDir: "./src",
|
|
263
|
+
extFrom: "none",
|
|
264
|
+
extTo: "ts",
|
|
265
|
+
alias: "@" // or "@/*"
|
|
266
|
+
});
|
|
267
|
+
```
|
|
268
|
+
|
|
269
|
+
The function intelligently handles different import types:
|
|
270
|
+
|
|
271
|
+
- ✅ Relative imports (`./file`, `../file`)
|
|
272
|
+
- ✅ Alias imports (when alias is specified)
|
|
273
|
+
- ✅ Package imports (`lodash`, `@scope/pkg`)
|
|
274
|
+
- ✅ Node built-ins (`node:path`, `node:fs`)
|
|
275
|
+
- ✅ URLs (`http://`, `https://`)
|
|
276
|
+
- ✅ Already processed paths
|
|
277
|
+
|
|
278
|
+
Features:
|
|
279
|
+
|
|
280
|
+
- 🔄 Recursively processes directories
|
|
281
|
+
- 🎯 Preserves package imports
|
|
282
|
+
- 🛡️ Safe for code generation
|
|
283
|
+
- 📝 Detailed change logging
|
|
284
|
+
- 🎨 Supports custom aliases
|
|
285
|
+
|
|
286
|
+
### Path Segment Manipulation
|
|
287
|
+
|
|
288
|
+
Manipulate path segments in import statements:
|
|
289
|
+
|
|
290
|
+
```ts
|
|
291
|
+
import {
|
|
292
|
+
stripPathSegments,
|
|
293
|
+
stripPathSegmentsInDirectory,
|
|
294
|
+
attachPathSegments,
|
|
295
|
+
attachPathSegmentsInDirectory
|
|
296
|
+
} from "@reliverse/pathkit";
|
|
297
|
+
|
|
298
|
+
// Strip segments from a path
|
|
299
|
+
stripPathSegments("src/components/Button.tsx", 1); // "components/Button.tsx"
|
|
300
|
+
|
|
301
|
+
// Strip segments from imports in a directory
|
|
302
|
+
await stripPathSegmentsInDirectory({
|
|
303
|
+
targetDir: "./src",
|
|
304
|
+
segmentsToStrip: 1,
|
|
305
|
+
alias: "@" // Optional: preserve alias prefix
|
|
306
|
+
});
|
|
307
|
+
|
|
308
|
+
// Attach segments to a path
|
|
309
|
+
attachPathSegments("Button.tsx", "components", {
|
|
310
|
+
position: "before", // "before" | "after"
|
|
311
|
+
normalize: true, // Normalize the path
|
|
312
|
+
ensureSlash: true, // Ensure slash between segments
|
|
313
|
+
preserveRoot: true, // Preserve root in absolute paths
|
|
314
|
+
preserveAlias: "@" // Optional: preserve alias prefix
|
|
315
|
+
});
|
|
316
|
+
|
|
317
|
+
// Attach segments to imports in a directory
|
|
318
|
+
await attachPathSegmentsInDirectory({
|
|
319
|
+
targetDir: "./src",
|
|
320
|
+
segments: "components",
|
|
321
|
+
options: {
|
|
322
|
+
position: "before",
|
|
323
|
+
preserveAlias: "@"
|
|
324
|
+
}
|
|
325
|
+
});
|
|
326
|
+
```
|
|
327
|
+
|
|
328
|
+
### Alias Resolution
|
|
329
|
+
|
|
330
|
+
Advanced alias handling and resolution:
|
|
331
|
+
|
|
332
|
+
```ts
|
|
333
|
+
import {
|
|
334
|
+
normalizeAliases,
|
|
335
|
+
resolveAlias,
|
|
336
|
+
reverseResolveAlias
|
|
337
|
+
} from "@reliverse/pathkit";
|
|
338
|
+
|
|
339
|
+
const aliases = { "@/": "/src/", "~/": "/home/user/" };
|
|
340
|
+
|
|
341
|
+
// Normalize alias config
|
|
342
|
+
console.log(normalizeAliases(aliases));
|
|
343
|
+
|
|
344
|
+
// Resolve alias to absolute path
|
|
345
|
+
console.log(resolveAlias("@/components", aliases)); // "/src/components"
|
|
346
|
+
|
|
347
|
+
// Convert absolute path back to alias
|
|
348
|
+
console.log(reverseResolveAlias("/src/utils", aliases)); // "@/utils"
|
|
349
|
+
```
|
|
350
|
+
|
|
351
|
+
```ts
|
|
352
|
+
import {
|
|
353
|
+
normalizeAliases,
|
|
354
|
+
resolveAlias,
|
|
355
|
+
reverseResolveAlias,
|
|
356
|
+
findAliasMatch
|
|
357
|
+
} from "@reliverse/pathkit";
|
|
358
|
+
|
|
359
|
+
// Normalize and optimize alias configurations
|
|
360
|
+
const aliases = {
|
|
361
|
+
"@/": "/src/",
|
|
362
|
+
"~/": "/home/user/",
|
|
363
|
+
"@/components/": "/src/components/" // Nested alias
|
|
364
|
+
};
|
|
365
|
+
const normalized = normalizeAliases(aliases);
|
|
366
|
+
|
|
367
|
+
// Resolve aliased paths
|
|
368
|
+
resolveAlias("@/components/Button", aliases); // "/src/components/Button"
|
|
369
|
+
|
|
370
|
+
// Convert absolute paths back to aliases
|
|
371
|
+
reverseResolveAlias("/src/utils", aliases); // ["@/utils"]
|
|
372
|
+
|
|
373
|
+
// Find matching alias in tsconfig-style paths
|
|
374
|
+
const paths = {
|
|
375
|
+
"@/*": ["./src/*"],
|
|
376
|
+
"~/*": ["./home/*"]
|
|
377
|
+
};
|
|
378
|
+
findAliasMatch("@/components/Button", paths);
|
|
379
|
+
```
|
|
380
|
+
|
|
381
|
+
### Path Conversion
|
|
382
|
+
|
|
383
|
+
Convert between different path formats:
|
|
384
|
+
|
|
385
|
+
```ts
|
|
386
|
+
import {
|
|
387
|
+
convertStringAliasRelative,
|
|
388
|
+
convertImportsAliasToRelative
|
|
389
|
+
} from "@reliverse/pathkit";
|
|
390
|
+
|
|
391
|
+
// Convert a single aliased path to relative
|
|
392
|
+
await convertStringAliasRelative({
|
|
393
|
+
importPath: "@/components/Button",
|
|
394
|
+
importerFile: "src/pages/Home.tsx",
|
|
395
|
+
pathPattern: "@/*",
|
|
396
|
+
targetDir: "src"
|
|
397
|
+
});
|
|
398
|
+
|
|
399
|
+
// Convert all aliased imports to relative in a directory
|
|
400
|
+
await convertImportsAliasToRelative({
|
|
401
|
+
targetDir: "./src",
|
|
402
|
+
aliasToReplace: "@",
|
|
403
|
+
pathExtFilter: "js-ts-none" // "js" | "ts" | "none" | "js-ts-none"
|
|
404
|
+
});
|
|
405
|
+
```
|
|
406
|
+
|
|
407
|
+
### Platform-Specific Features
|
|
408
|
+
|
|
409
|
+
Handle platform-specific path operations:
|
|
410
|
+
|
|
411
|
+
```ts
|
|
412
|
+
import { posix, win32 } from "@reliverse/pathkit";
|
|
413
|
+
|
|
414
|
+
// Use platform-specific path handling
|
|
415
|
+
const path = process.platform === "win32" ? win32 : posix;
|
|
416
|
+
|
|
417
|
+
// Windows-specific features
|
|
418
|
+
win32.toNamespacedPath("C:\\path\\to\\file"); // "\\\\?\\C:\\path\\to\\file"
|
|
419
|
+
win32.delimiter; // ";"
|
|
420
|
+
|
|
421
|
+
// POSIX-specific features
|
|
422
|
+
posix.delimiter; // ":"
|
|
423
|
+
```
|
|
424
|
+
|
|
425
|
+
### Utility Functions
|
|
426
|
+
|
|
427
|
+
```ts
|
|
428
|
+
import {
|
|
429
|
+
filename, // Strip extension
|
|
430
|
+
normalizeQuotes, // Standardize quote style
|
|
431
|
+
matchesGlob // Test glob patterns
|
|
432
|
+
} from "@reliverse/pathkit";
|
|
433
|
+
|
|
434
|
+
console.log(filename("/path/component.vue")); // "component"
|
|
435
|
+
console.log(normalizeQuotes("import 'pkg'")); // 'import "pkg"'
|
|
436
|
+
console.log(matchesGlob("file.ts", "**/*.ts")); // true
|
|
437
|
+
```
|
|
438
|
+
|
|
439
|
+
```ts
|
|
440
|
+
import {
|
|
441
|
+
filename,
|
|
442
|
+
normalizeWindowsPath,
|
|
443
|
+
replaceAllInString
|
|
444
|
+
} from "@reliverse/pathkit";
|
|
445
|
+
|
|
446
|
+
// Get filename without extension
|
|
447
|
+
filename("/path/to/file.ts"); // "file"
|
|
448
|
+
|
|
449
|
+
// Normalize Windows paths
|
|
450
|
+
normalizeWindowsPath("C:\\path\\to\\file"); // "C:/path/to/file"
|
|
451
|
+
|
|
452
|
+
// Replace strings while tracking position
|
|
453
|
+
replaceAllInString("import x from 'y'", "'y'", "'z'");
|
|
454
|
+
```
|
|
455
|
+
|
|
456
|
+
### Supported File Extensions
|
|
457
|
+
|
|
458
|
+
The library supports the following file extensions by default:
|
|
459
|
+
|
|
460
|
+
```ts
|
|
461
|
+
const EXTENSIONS = [".ts", ".tsx", ".js", ".jsx", ".mjs", ".cjs"];
|
|
462
|
+
```
|
|
463
|
+
|
|
464
|
+
### Type Definitions
|
|
465
|
+
|
|
466
|
+
```ts
|
|
467
|
+
type PathExtFilter = "js" | "ts" | "none" | "js-ts-none";
|
|
468
|
+
type ImportExtType = "js" | "ts" | "none";
|
|
469
|
+
```
|
|
470
|
+
|
|
471
|
+
## Use Cases / Ideal For
|
|
472
|
+
|
|
473
|
+
- 🛠️ **CLI tools**
|
|
474
|
+
- 🌍 **Cross‑platform dev environments**
|
|
475
|
+
- 🔄 **Bundlers, linters, compilers**
|
|
476
|
+
- 🏗️ **Framework & library authors**
|
|
477
|
+
- 📜 **Scripts / test runners**
|
|
478
|
+
- …anywhere file‑paths roam!
|
|
479
|
+
|
|
480
|
+
## Examples & Contributing
|
|
481
|
+
|
|
482
|
+
```bash
|
|
483
|
+
git clone https://github.com/reliverse/pathkit.git
|
|
484
|
+
cd pathkit
|
|
485
|
+
bun install
|
|
486
|
+
bun dev
|
|
487
|
+
```
|
|
488
|
+
|
|
489
|
+
Bug reports & PRs are warmly welcome—come on in!
|
|
490
|
+
|
|
491
|
+
## Related
|
|
492
|
+
|
|
493
|
+
- [`@reliverse/rempts`](https://npmjs.com/package/@reliverse/rempts) – Terminal Prompts Engine
|
|
494
|
+
|
|
495
|
+
## Community
|
|
496
|
+
|
|
497
|
+
- ⭐ **Star** the repo if this helped you.
|
|
498
|
+
- 💖 **Sponsor** [@blefnk](https://github.com/sponsors/blefnk) to keep the lights on.
|
|
499
|
+
- 💬 **Chat** with us on [Discord](https://discord.gg/Pb8uKbwpsJ).
|
|
500
|
+
|
|
501
|
+
## License
|
|
502
|
+
|
|
503
|
+
[MIT](LICENSE) © [Nazar Kornienko (blefnk)](https://github.com/blefnk), [Reliverse](https://github.com/reliverse)
|
|
504
|
+
|
|
505
|
+
## Badges
|
|
506
|
+
|
|
507
|
+
[](https://npmjs.com/package/@reliverse/pathkit)
|
|
508
|
+
[](https://npmjs.com/package/@reliverse/pathkit)
|
|
509
|
+
[](https://github.com/reliverse/pathkit)
|
|
510
|
+
[](LICENSE)
|
|
@@ -5,6 +5,35 @@ export function getFileImportsExports(content, options = {}) {
|
|
|
5
5
|
limitPerType
|
|
6
6
|
} = options;
|
|
7
7
|
const results = [];
|
|
8
|
+
function getImportExtension(path) {
|
|
9
|
+
if (!path) return "";
|
|
10
|
+
const lastDotIndex = path.lastIndexOf(".");
|
|
11
|
+
if (lastDotIndex <= 0 || lastDotIndex === path.length - 1) {
|
|
12
|
+
return "";
|
|
13
|
+
}
|
|
14
|
+
const extension = path.slice(lastDotIndex);
|
|
15
|
+
if (path.endsWith(".d.ts")) {
|
|
16
|
+
return ".d.ts";
|
|
17
|
+
}
|
|
18
|
+
return extension;
|
|
19
|
+
}
|
|
20
|
+
function getRealFileExtension(path, pathType) {
|
|
21
|
+
if (pathType === "bare" || pathType === "alias") {
|
|
22
|
+
return "";
|
|
23
|
+
}
|
|
24
|
+
if (pathType === "module") {
|
|
25
|
+
return getImportExtension(path);
|
|
26
|
+
}
|
|
27
|
+
const pathExt = getImportExtension(path);
|
|
28
|
+
if (!pathExt) return "";
|
|
29
|
+
if (pathExt === ".js" || pathExt === ".jsx") {
|
|
30
|
+
return pathExt === ".jsx" ? ".tsx" : ".ts";
|
|
31
|
+
}
|
|
32
|
+
if (pathExt === ".ts" || pathExt === ".tsx") {
|
|
33
|
+
return pathExt;
|
|
34
|
+
}
|
|
35
|
+
return pathExt;
|
|
36
|
+
}
|
|
8
37
|
const patterns = {
|
|
9
38
|
// import statements with from clause
|
|
10
39
|
staticImport: /import\s+(?:type\s+)?(?:(?:\w+)(?:\s*,\s*)?)?(?:\{[^}]*\}|\*\s+as\s+\w+)?\s+from\s+['"]([^'"]+)['"]|import\s+(?:type\s+)?(\w+)\s+from\s+['"]([^'"]+)['"]/g,
|
|
@@ -92,7 +121,9 @@ export function getFileImportsExports(content, options = {}) {
|
|
|
92
121
|
isTypeOnly: match[0].includes("import type"),
|
|
93
122
|
specifiers: extractSpecifiers(match[0]),
|
|
94
123
|
start: match.index ?? 0,
|
|
95
|
-
end: (match.index ?? 0) + match[0].length
|
|
124
|
+
end: (match.index ?? 0) + match[0].length,
|
|
125
|
+
importExt: getImportExtension(source),
|
|
126
|
+
realFileExt: getRealFileExtension(source, pathType)
|
|
96
127
|
};
|
|
97
128
|
results.push(info);
|
|
98
129
|
}
|
|
@@ -112,7 +143,9 @@ export function getFileImportsExports(content, options = {}) {
|
|
|
112
143
|
isTypeOnly: false,
|
|
113
144
|
specifiers: [],
|
|
114
145
|
start: match.index ?? 0,
|
|
115
|
-
end: (match.index ?? 0) + match[0].length
|
|
146
|
+
end: (match.index ?? 0) + match[0].length,
|
|
147
|
+
importExt: getImportExtension(source),
|
|
148
|
+
realFileExt: getRealFileExtension(source, pathType)
|
|
116
149
|
};
|
|
117
150
|
results.push(info);
|
|
118
151
|
}
|
|
@@ -134,7 +167,9 @@ export function getFileImportsExports(content, options = {}) {
|
|
|
134
167
|
isTypeOnly: match[0].includes("export type"),
|
|
135
168
|
specifiers: extractSpecifiers(match[0]),
|
|
136
169
|
start: match.index ?? 0,
|
|
137
|
-
end: (match.index ?? 0) + match[0].length
|
|
170
|
+
end: (match.index ?? 0) + match[0].length,
|
|
171
|
+
importExt: getImportExtension(source),
|
|
172
|
+
realFileExt: getRealFileExtension(source, pathType)
|
|
138
173
|
};
|
|
139
174
|
results.push(info);
|
|
140
175
|
}
|
|
@@ -150,7 +185,9 @@ export function getFileImportsExports(content, options = {}) {
|
|
|
150
185
|
isTypeOnly: false,
|
|
151
186
|
specifiers: [{ type: "default", name: "default" }],
|
|
152
187
|
start: match.index,
|
|
153
|
-
end: match.index + match[0].length
|
|
188
|
+
end: match.index + match[0].length,
|
|
189
|
+
importExt: void 0,
|
|
190
|
+
realFileExt: void 0
|
|
154
191
|
};
|
|
155
192
|
results.push(info);
|
|
156
193
|
}
|
|
@@ -168,7 +205,9 @@ export function getFileImportsExports(content, options = {}) {
|
|
|
168
205
|
isTypeOnly: match[0].includes("export type"),
|
|
169
206
|
specifiers: [{ type: "named", name }],
|
|
170
207
|
start: match.index,
|
|
171
|
-
end: match.index + match[0].length
|
|
208
|
+
end: match.index + match[0].length,
|
|
209
|
+
importExt: void 0,
|
|
210
|
+
realFileExt: void 0
|
|
172
211
|
};
|
|
173
212
|
results.push(info);
|
|
174
213
|
}
|
package/bin/mod.js
CHANGED
|
@@ -15,7 +15,7 @@ const logInternal = (msg) => {
|
|
|
15
15
|
}
|
|
16
16
|
};
|
|
17
17
|
const DEBUG_MODE = false;
|
|
18
|
-
const EXTENSIONS = [".ts", ".tsx", ".js", ".jsx", ".mjs", ".cjs"];
|
|
18
|
+
const EXTENSIONS = [".ts", ".tsx", ".js", ".jsx", ".mjs", ".cjs", ".d.ts"];
|
|
19
19
|
const SLASH = "/";
|
|
20
20
|
const BACK_SLASH = "\\";
|
|
21
21
|
const DOT = ".";
|
|
@@ -600,6 +600,7 @@ async function convertImportsExt({
|
|
|
600
600
|
return true;
|
|
601
601
|
if (path2.startsWith("http://") || path2.startsWith("https://")) return true;
|
|
602
602
|
if (extTo !== "none" && path2.endsWith(`.${extTo}`)) return true;
|
|
603
|
+
if (extFrom === "none" && /\.[^/]+$/.test(path2)) return true;
|
|
603
604
|
return false;
|
|
604
605
|
}
|
|
605
606
|
try {
|
|
@@ -633,7 +634,7 @@ async function convertImportsExt({
|
|
|
633
634
|
}
|
|
634
635
|
let replacementPath;
|
|
635
636
|
if (extFrom === "none") {
|
|
636
|
-
replacementPath = importPath + toExtStr;
|
|
637
|
+
replacementPath = /\.[^/]+$/.test(importPath) ? importPath : importPath + toExtStr;
|
|
637
638
|
} else if (extTo === "none") {
|
|
638
639
|
replacementPath = importPath.slice(0, -fromExtStr.length);
|
|
639
640
|
} else {
|