@boba-cli/filesystem 0.1.0-alpha.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 +299 -0
- package/dist/index.cjs +187 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +169 -0
- package/dist/index.d.ts +169 -0
- package/dist/index.js +164 -0
- package/dist/index.js.map +1 -0
- package/package.json +43 -0
package/README.md
ADDED
|
@@ -0,0 +1,299 @@
|
|
|
1
|
+
# @boba-cli/filesystem
|
|
2
|
+
|
|
3
|
+
Filesystem utility functions for Boba terminal UIs. This package provides a collection of helper functions for working with the filesystem, ported from the [teacup](https://github.com/mistakenelf/teacup) Go library.
|
|
4
|
+
|
|
5
|
+
This package uses `@boba-cli/machine` abstractions to ensure browser compatibility and platform independence.
|
|
6
|
+
|
|
7
|
+
## Installation
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
npm install @boba-cli/filesystem @boba-cli/machine
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## Features
|
|
14
|
+
|
|
15
|
+
### Directory Constants
|
|
16
|
+
|
|
17
|
+
- `CurrentDirectory` - Current directory (`.`)
|
|
18
|
+
- `PreviousDirectory` - Previous directory (`..`)
|
|
19
|
+
- `HomeDirectory` - Home directory (`~`)
|
|
20
|
+
- `RootDirectory` - Root directory (`/`)
|
|
21
|
+
|
|
22
|
+
### Listing Types
|
|
23
|
+
|
|
24
|
+
- `DirectoriesListingType` - Filter for directories only
|
|
25
|
+
- `FilesListingType` - Filter for files only
|
|
26
|
+
|
|
27
|
+
## Usage
|
|
28
|
+
|
|
29
|
+
All functions require `FileSystemAdapter` and/or `PathAdapter` instances from `@boba-cli/machine`. This design allows the package to work in both Node.js and browser environments.
|
|
30
|
+
|
|
31
|
+
```typescript
|
|
32
|
+
import { NodeFileSystemAdapter, NodePathAdapter } from '@boba-cli/machine/node'
|
|
33
|
+
import { getDirectoryListing } from '@boba-cli/filesystem'
|
|
34
|
+
|
|
35
|
+
// Create adapter instances
|
|
36
|
+
const fs = new NodeFileSystemAdapter()
|
|
37
|
+
const path = new NodePathAdapter()
|
|
38
|
+
|
|
39
|
+
// Use with functions
|
|
40
|
+
const entries = await getDirectoryListing(fs, '/path/to/dir')
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
## API
|
|
44
|
+
|
|
45
|
+
### Directory Listing
|
|
46
|
+
|
|
47
|
+
#### `getDirectoryListing(fs: FileSystemAdapter, dir: string, showHidden?: boolean): Promise<DirectoryEntry[]>`
|
|
48
|
+
|
|
49
|
+
Returns a list of files and directories within a given directory.
|
|
50
|
+
|
|
51
|
+
```typescript
|
|
52
|
+
import { NodeFileSystemAdapter } from '@boba-cli/machine/node'
|
|
53
|
+
import { getDirectoryListing } from '@boba-cli/filesystem'
|
|
54
|
+
|
|
55
|
+
const fs = new NodeFileSystemAdapter()
|
|
56
|
+
const entries = await getDirectoryListing(fs, '/path/to/dir')
|
|
57
|
+
const allEntries = await getDirectoryListing(fs, '/path/to/dir', true) // includes hidden files
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
#### `getDirectoryListingByType(fs: FileSystemAdapter, dir: string, listingType: string, showHidden?: boolean): Promise<DirectoryEntry[]>`
|
|
61
|
+
|
|
62
|
+
Returns a directory listing filtered by type (directories or files).
|
|
63
|
+
|
|
64
|
+
```typescript
|
|
65
|
+
import { NodeFileSystemAdapter } from '@boba-cli/machine/node'
|
|
66
|
+
import {
|
|
67
|
+
getDirectoryListingByType,
|
|
68
|
+
DirectoriesListingType,
|
|
69
|
+
FilesListingType,
|
|
70
|
+
} from '@boba-cli/filesystem'
|
|
71
|
+
|
|
72
|
+
const fs = new NodeFileSystemAdapter()
|
|
73
|
+
const dirs = await getDirectoryListingByType(
|
|
74
|
+
fs,
|
|
75
|
+
'/path/to/dir',
|
|
76
|
+
DirectoriesListingType,
|
|
77
|
+
)
|
|
78
|
+
const files = await getDirectoryListingByType(fs, '/path/to/dir', FilesListingType)
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
### Directory Navigation
|
|
82
|
+
|
|
83
|
+
#### `getHomeDirectory(fs: FileSystemAdapter): string`
|
|
84
|
+
|
|
85
|
+
Returns the user's home directory.
|
|
86
|
+
|
|
87
|
+
```typescript
|
|
88
|
+
import { NodeFileSystemAdapter } from '@boba-cli/machine/node'
|
|
89
|
+
import { getHomeDirectory } from '@boba-cli/filesystem'
|
|
90
|
+
|
|
91
|
+
const fs = new NodeFileSystemAdapter()
|
|
92
|
+
const home = getHomeDirectory(fs)
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
#### `getWorkingDirectory(fs: FileSystemAdapter): string`
|
|
96
|
+
|
|
97
|
+
Returns the current working directory.
|
|
98
|
+
|
|
99
|
+
```typescript
|
|
100
|
+
import { NodeFileSystemAdapter } from '@boba-cli/machine/node'
|
|
101
|
+
import { getWorkingDirectory } from '@boba-cli/filesystem'
|
|
102
|
+
|
|
103
|
+
const fs = new NodeFileSystemAdapter()
|
|
104
|
+
const cwd = getWorkingDirectory(fs)
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
### File Reading
|
|
108
|
+
|
|
109
|
+
#### `readFileContent(fs: FileSystemAdapter, name: string): Promise<string>`
|
|
110
|
+
|
|
111
|
+
Returns the contents of a file as a string.
|
|
112
|
+
|
|
113
|
+
```typescript
|
|
114
|
+
import { NodeFileSystemAdapter } from '@boba-cli/machine/node'
|
|
115
|
+
import { readFileContent } from '@boba-cli/filesystem'
|
|
116
|
+
|
|
117
|
+
const fs = new NodeFileSystemAdapter()
|
|
118
|
+
const content = await readFileContent(fs, '/path/to/file.txt')
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
### Size Calculation
|
|
122
|
+
|
|
123
|
+
#### `getDirectoryItemSize(fs: FileSystemAdapter, path: PathAdapter, itemPath: string): Promise<number>`
|
|
124
|
+
|
|
125
|
+
Calculates the size of a directory or file in bytes.
|
|
126
|
+
|
|
127
|
+
```typescript
|
|
128
|
+
import { NodeFileSystemAdapter, NodePathAdapter } from '@boba-cli/machine/node'
|
|
129
|
+
import { getDirectoryItemSize } from '@boba-cli/filesystem'
|
|
130
|
+
|
|
131
|
+
const fs = new NodeFileSystemAdapter()
|
|
132
|
+
const path = new NodePathAdapter()
|
|
133
|
+
const size = await getDirectoryItemSize(fs, path, '/path/to/item')
|
|
134
|
+
console.log(`Size: ${size} bytes`)
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
### File Search
|
|
138
|
+
|
|
139
|
+
#### `findFilesByName(fs: FileSystemAdapter, path: PathAdapter, name: string, dir: string): Promise<{ paths: string[]; entries: DirectoryEntry[] }>`
|
|
140
|
+
|
|
141
|
+
Searches for files by name (supports partial matches).
|
|
142
|
+
|
|
143
|
+
```typescript
|
|
144
|
+
import { NodeFileSystemAdapter, NodePathAdapter } from '@boba-cli/machine/node'
|
|
145
|
+
import { findFilesByName } from '@boba-cli/filesystem'
|
|
146
|
+
|
|
147
|
+
const fs = new NodeFileSystemAdapter()
|
|
148
|
+
const path = new NodePathAdapter()
|
|
149
|
+
const { paths, entries } = await findFilesByName(fs, path, '*.txt', '/path/to/search')
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
### File Operations
|
|
153
|
+
|
|
154
|
+
#### `createFile(fs: FileSystemAdapter, name: string): Promise<void>`
|
|
155
|
+
|
|
156
|
+
Creates a new file.
|
|
157
|
+
|
|
158
|
+
```typescript
|
|
159
|
+
import { NodeFileSystemAdapter } from '@boba-cli/machine/node'
|
|
160
|
+
import { createFile } from '@boba-cli/filesystem'
|
|
161
|
+
|
|
162
|
+
const fs = new NodeFileSystemAdapter()
|
|
163
|
+
await createFile(fs, '/path/to/newfile.txt')
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
#### `deleteFile(fs: FileSystemAdapter, name: string): Promise<void>`
|
|
167
|
+
|
|
168
|
+
Deletes a file.
|
|
169
|
+
|
|
170
|
+
```typescript
|
|
171
|
+
import { NodeFileSystemAdapter } from '@boba-cli/machine/node'
|
|
172
|
+
import { deleteFile } from '@boba-cli/filesystem'
|
|
173
|
+
|
|
174
|
+
const fs = new NodeFileSystemAdapter()
|
|
175
|
+
await deleteFile(fs, '/path/to/file.txt')
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
#### `writeToFile(fs: FileSystemAdapter, filePath: string, content: string): Promise<void>`
|
|
179
|
+
|
|
180
|
+
Writes content to a file (overwrites if exists).
|
|
181
|
+
|
|
182
|
+
```typescript
|
|
183
|
+
import { NodeFileSystemAdapter } from '@boba-cli/machine/node'
|
|
184
|
+
import { writeToFile } from '@boba-cli/filesystem'
|
|
185
|
+
|
|
186
|
+
const fs = new NodeFileSystemAdapter()
|
|
187
|
+
await writeToFile(fs, '/path/to/file.txt', 'Hello, World!')
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
#### `copyFile(fs: FileSystemAdapter, path: PathAdapter, name: string): Promise<string>`
|
|
191
|
+
|
|
192
|
+
Copies a file with a timestamp suffix and returns the new file path.
|
|
193
|
+
|
|
194
|
+
```typescript
|
|
195
|
+
import { NodeFileSystemAdapter, NodePathAdapter } from '@boba-cli/machine/node'
|
|
196
|
+
import { copyFile } from '@boba-cli/filesystem'
|
|
197
|
+
|
|
198
|
+
const fs = new NodeFileSystemAdapter()
|
|
199
|
+
const path = new NodePathAdapter()
|
|
200
|
+
const newPath = await copyFile(fs, path, '/path/to/file.txt')
|
|
201
|
+
// Returns: /path/to/file_1234567890.txt
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
### Directory Operations
|
|
205
|
+
|
|
206
|
+
#### `createDirectory(fs: FileSystemAdapter, name: string): Promise<void>`
|
|
207
|
+
|
|
208
|
+
Creates a new directory.
|
|
209
|
+
|
|
210
|
+
```typescript
|
|
211
|
+
import { NodeFileSystemAdapter } from '@boba-cli/machine/node'
|
|
212
|
+
import { createDirectory } from '@boba-cli/filesystem'
|
|
213
|
+
|
|
214
|
+
const fs = new NodeFileSystemAdapter()
|
|
215
|
+
await createDirectory(fs, '/path/to/newdir')
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
#### `deleteDirectory(fs: FileSystemAdapter, name: string): Promise<void>`
|
|
219
|
+
|
|
220
|
+
Deletes a directory recursively.
|
|
221
|
+
|
|
222
|
+
```typescript
|
|
223
|
+
import { NodeFileSystemAdapter } from '@boba-cli/machine/node'
|
|
224
|
+
import { deleteDirectory } from '@boba-cli/filesystem'
|
|
225
|
+
|
|
226
|
+
const fs = new NodeFileSystemAdapter()
|
|
227
|
+
await deleteDirectory(fs, '/path/to/dir')
|
|
228
|
+
```
|
|
229
|
+
|
|
230
|
+
#### `copyDirectory(fs: FileSystemAdapter, path: PathAdapter, name: string): Promise<string>`
|
|
231
|
+
|
|
232
|
+
Copies a directory recursively with a timestamp suffix and returns the new directory path.
|
|
233
|
+
|
|
234
|
+
```typescript
|
|
235
|
+
import { NodeFileSystemAdapter, NodePathAdapter } from '@boba-cli/machine/node'
|
|
236
|
+
import { copyDirectory } from '@boba-cli/filesystem'
|
|
237
|
+
|
|
238
|
+
const fs = new NodeFileSystemAdapter()
|
|
239
|
+
const path = new NodePathAdapter()
|
|
240
|
+
const newPath = await copyDirectory(fs, path, '/path/to/dir')
|
|
241
|
+
// Returns: /path/to/dir_1234567890
|
|
242
|
+
```
|
|
243
|
+
|
|
244
|
+
### Rename and Move Operations
|
|
245
|
+
|
|
246
|
+
#### `renameDirectoryItem(fs: FileSystemAdapter, src: string, dst: string): Promise<void>`
|
|
247
|
+
|
|
248
|
+
Renames a file or directory.
|
|
249
|
+
|
|
250
|
+
```typescript
|
|
251
|
+
import { NodeFileSystemAdapter } from '@boba-cli/machine/node'
|
|
252
|
+
import { renameDirectoryItem } from '@boba-cli/filesystem'
|
|
253
|
+
|
|
254
|
+
const fs = new NodeFileSystemAdapter()
|
|
255
|
+
await renameDirectoryItem(fs, '/path/to/old.txt', '/path/to/new.txt')
|
|
256
|
+
```
|
|
257
|
+
|
|
258
|
+
#### `moveDirectoryItem(fs: FileSystemAdapter, src: string, dst: string): Promise<void>`
|
|
259
|
+
|
|
260
|
+
Moves a file or directory to a new location.
|
|
261
|
+
|
|
262
|
+
```typescript
|
|
263
|
+
import { NodeFileSystemAdapter } from '@boba-cli/machine/node'
|
|
264
|
+
import { moveDirectoryItem } from '@boba-cli/filesystem'
|
|
265
|
+
|
|
266
|
+
const fs = new NodeFileSystemAdapter()
|
|
267
|
+
await moveDirectoryItem(fs, '/path/to/file.txt', '/new/path/file.txt')
|
|
268
|
+
```
|
|
269
|
+
|
|
270
|
+
## Archive Operations
|
|
271
|
+
|
|
272
|
+
Archive operations (zip/unzip) have been moved to `@boba-cli/machine`. Use the `ArchiveAdapter` from that package:
|
|
273
|
+
|
|
274
|
+
```typescript
|
|
275
|
+
import { NodeArchiveAdapter } from '@boba-cli/machine/node'
|
|
276
|
+
|
|
277
|
+
const archive = new NodeArchiveAdapter()
|
|
278
|
+
await archive.zip('/path/to/source', '/path/to/output.zip')
|
|
279
|
+
await archive.unzip('/path/to/archive.zip', '/path/to/extract')
|
|
280
|
+
```
|
|
281
|
+
|
|
282
|
+
## Types
|
|
283
|
+
|
|
284
|
+
### `DirectoryEntry`
|
|
285
|
+
|
|
286
|
+
Represents a directory entry with the following properties and methods:
|
|
287
|
+
|
|
288
|
+
- `name: string` - The name of the entry
|
|
289
|
+
- `isDirectory(): boolean` - Returns true if the entry is a directory
|
|
290
|
+
- `isFile(): boolean` - Returns true if the entry is a file
|
|
291
|
+
- `isSymbolicLink(): boolean` - Returns true if the entry is a symbolic link
|
|
292
|
+
|
|
293
|
+
## Cross-Platform Compatibility
|
|
294
|
+
|
|
295
|
+
All functions use `@boba-cli/machine` adapters to ensure compatibility across Node.js and browser environments. The adapters handle platform-specific implementation details, allowing this package to provide a consistent API regardless of the runtime environment.
|
|
296
|
+
|
|
297
|
+
## License
|
|
298
|
+
|
|
299
|
+
MIT
|
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
// src/filesystem.ts
|
|
4
|
+
var CurrentDirectory = ".";
|
|
5
|
+
var PreviousDirectory = "..";
|
|
6
|
+
var HomeDirectory = "~";
|
|
7
|
+
var RootDirectory = "/";
|
|
8
|
+
var DirectoriesListingType = "directories";
|
|
9
|
+
var FilesListingType = "files";
|
|
10
|
+
function generateTimestampedFilename(filePath, extension, path) {
|
|
11
|
+
const timestamp = Math.floor(Date.now() / 1e3);
|
|
12
|
+
const ext = path.extname(filePath);
|
|
13
|
+
const basename = path.basename(filePath, ext);
|
|
14
|
+
const dirname = path.dirname(filePath);
|
|
15
|
+
const filename = path.basename(filePath);
|
|
16
|
+
let output;
|
|
17
|
+
if (filename.startsWith(".") && ext === "") {
|
|
18
|
+
output = path.join(dirname, `${filename}_${timestamp}${extension}`);
|
|
19
|
+
} else if (filename.startsWith(".") && ext !== "") {
|
|
20
|
+
output = path.join(dirname, `${basename}_${timestamp}${ext}${extension}`);
|
|
21
|
+
} else if (ext !== "" && extension === "") {
|
|
22
|
+
output = path.join(dirname, `${basename}_${timestamp}${ext}`);
|
|
23
|
+
} else {
|
|
24
|
+
output = path.join(dirname, `${filename}_${timestamp}${extension}`);
|
|
25
|
+
}
|
|
26
|
+
return output;
|
|
27
|
+
}
|
|
28
|
+
async function getDirectoryListing(fs, dir, showHidden = false) {
|
|
29
|
+
const entries = await fs.readdir(dir, {
|
|
30
|
+
withFileTypes: true
|
|
31
|
+
});
|
|
32
|
+
if (!showHidden) {
|
|
33
|
+
return entries.filter((entry) => !entry.name.startsWith("."));
|
|
34
|
+
}
|
|
35
|
+
return entries;
|
|
36
|
+
}
|
|
37
|
+
async function getDirectoryListingByType(fs, dir, listingType, showHidden = false) {
|
|
38
|
+
const entries = await fs.readdir(dir, {
|
|
39
|
+
withFileTypes: true
|
|
40
|
+
});
|
|
41
|
+
return entries.filter((entry) => {
|
|
42
|
+
const isHidden = entry.name.startsWith(".");
|
|
43
|
+
if (!showHidden && isHidden) {
|
|
44
|
+
return false;
|
|
45
|
+
}
|
|
46
|
+
if (listingType === DirectoriesListingType) {
|
|
47
|
+
return entry.isDirectory();
|
|
48
|
+
} else if (listingType === FilesListingType) {
|
|
49
|
+
return entry.isFile();
|
|
50
|
+
}
|
|
51
|
+
return false;
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
function getHomeDirectory(fs) {
|
|
55
|
+
return fs.homedir();
|
|
56
|
+
}
|
|
57
|
+
function getWorkingDirectory(fs) {
|
|
58
|
+
return fs.cwd();
|
|
59
|
+
}
|
|
60
|
+
async function readFileContent(fs, name) {
|
|
61
|
+
const content = await fs.readFile(name, "utf-8");
|
|
62
|
+
return content;
|
|
63
|
+
}
|
|
64
|
+
async function getDirectoryItemSize(fs, path, itemPath) {
|
|
65
|
+
const stats = await fs.stat(itemPath);
|
|
66
|
+
if (!stats.isDirectory) {
|
|
67
|
+
return stats.size;
|
|
68
|
+
}
|
|
69
|
+
let totalSize = 0;
|
|
70
|
+
const entries = await fs.readdir(itemPath, {
|
|
71
|
+
withFileTypes: true
|
|
72
|
+
});
|
|
73
|
+
for (const entry of entries) {
|
|
74
|
+
const fullPath = path.join(itemPath, entry.name);
|
|
75
|
+
if (entry.isDirectory()) {
|
|
76
|
+
totalSize += await getDirectoryItemSize(fs, path, fullPath);
|
|
77
|
+
} else {
|
|
78
|
+
const fileStats = await fs.stat(fullPath);
|
|
79
|
+
totalSize += fileStats.size;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
return totalSize;
|
|
83
|
+
}
|
|
84
|
+
async function findFilesByName(fs, path, name, dir) {
|
|
85
|
+
const paths = [];
|
|
86
|
+
const entries = [];
|
|
87
|
+
async function search(searchDir) {
|
|
88
|
+
try {
|
|
89
|
+
const items = await fs.readdir(searchDir, {
|
|
90
|
+
withFileTypes: true
|
|
91
|
+
});
|
|
92
|
+
for (const item of items) {
|
|
93
|
+
const fullPath = path.join(searchDir, item.name);
|
|
94
|
+
if (item.name.includes(name)) {
|
|
95
|
+
paths.push(fullPath);
|
|
96
|
+
entries.push(item);
|
|
97
|
+
}
|
|
98
|
+
if (item.isDirectory()) {
|
|
99
|
+
await search(fullPath);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
} catch {
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
await search(dir);
|
|
106
|
+
return { paths, entries };
|
|
107
|
+
}
|
|
108
|
+
async function createFile(fs, name) {
|
|
109
|
+
await fs.writeFile(name, "");
|
|
110
|
+
}
|
|
111
|
+
async function createDirectory(fs, name) {
|
|
112
|
+
const exists = await fs.exists(name);
|
|
113
|
+
if (!exists) {
|
|
114
|
+
await fs.mkdir(name, { recursive: false });
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
async function deleteFile(fs, name) {
|
|
118
|
+
await fs.unlink(name);
|
|
119
|
+
}
|
|
120
|
+
async function deleteDirectory(fs, name) {
|
|
121
|
+
await fs.rmdir(name, { recursive: true, force: true });
|
|
122
|
+
}
|
|
123
|
+
async function renameDirectoryItem(fs, src, dst) {
|
|
124
|
+
await fs.rename(src, dst);
|
|
125
|
+
}
|
|
126
|
+
async function moveDirectoryItem(fs, src, dst) {
|
|
127
|
+
await fs.rename(src, dst);
|
|
128
|
+
}
|
|
129
|
+
async function copyFile(fs, path, name) {
|
|
130
|
+
const output = generateTimestampedFilename(name, "", path);
|
|
131
|
+
await fs.copyFile(name, output);
|
|
132
|
+
return output;
|
|
133
|
+
}
|
|
134
|
+
async function copyDirectory(fs, path, name) {
|
|
135
|
+
const timestamp = Math.floor(Date.now() / 1e3);
|
|
136
|
+
const output = `${name}_${timestamp}`;
|
|
137
|
+
async function copyRecursive(src, dest) {
|
|
138
|
+
const stats = await fs.stat(src);
|
|
139
|
+
if (stats.isDirectory) {
|
|
140
|
+
await fs.mkdir(dest, { recursive: true });
|
|
141
|
+
const entries = await fs.readdir(src, {
|
|
142
|
+
withFileTypes: true
|
|
143
|
+
});
|
|
144
|
+
for (const entry of entries) {
|
|
145
|
+
const srcPath = path.join(src, entry.name);
|
|
146
|
+
const destPath = path.join(dest, entry.name);
|
|
147
|
+
if (entry.isDirectory()) {
|
|
148
|
+
await copyRecursive(srcPath, destPath);
|
|
149
|
+
} else {
|
|
150
|
+
await fs.copyFile(srcPath, destPath);
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
} else {
|
|
154
|
+
await fs.copyFile(src, dest);
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
await copyRecursive(name, output);
|
|
158
|
+
return output;
|
|
159
|
+
}
|
|
160
|
+
async function writeToFile(fs, filePath, content) {
|
|
161
|
+
await fs.writeFile(filePath, content);
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
exports.CurrentDirectory = CurrentDirectory;
|
|
165
|
+
exports.DirectoriesListingType = DirectoriesListingType;
|
|
166
|
+
exports.FilesListingType = FilesListingType;
|
|
167
|
+
exports.HomeDirectory = HomeDirectory;
|
|
168
|
+
exports.PreviousDirectory = PreviousDirectory;
|
|
169
|
+
exports.RootDirectory = RootDirectory;
|
|
170
|
+
exports.copyDirectory = copyDirectory;
|
|
171
|
+
exports.copyFile = copyFile;
|
|
172
|
+
exports.createDirectory = createDirectory;
|
|
173
|
+
exports.createFile = createFile;
|
|
174
|
+
exports.deleteDirectory = deleteDirectory;
|
|
175
|
+
exports.deleteFile = deleteFile;
|
|
176
|
+
exports.findFilesByName = findFilesByName;
|
|
177
|
+
exports.getDirectoryItemSize = getDirectoryItemSize;
|
|
178
|
+
exports.getDirectoryListing = getDirectoryListing;
|
|
179
|
+
exports.getDirectoryListingByType = getDirectoryListingByType;
|
|
180
|
+
exports.getHomeDirectory = getHomeDirectory;
|
|
181
|
+
exports.getWorkingDirectory = getWorkingDirectory;
|
|
182
|
+
exports.moveDirectoryItem = moveDirectoryItem;
|
|
183
|
+
exports.readFileContent = readFileContent;
|
|
184
|
+
exports.renameDirectoryItem = renameDirectoryItem;
|
|
185
|
+
exports.writeToFile = writeToFile;
|
|
186
|
+
//# sourceMappingURL=index.cjs.map
|
|
187
|
+
//# sourceMappingURL=index.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/filesystem.ts"],"names":[],"mappings":"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","file":"index.cjs","sourcesContent":["import type {\n DirectoryEntry,\n FileSystemAdapter,\n PathAdapter,\n} from '@boba-cli/machine'\n\n/**\n * Directory shortcuts.\n * @public\n */\nexport const CurrentDirectory = '.'\n\n/**\n * Previous directory shortcut.\n * @public\n */\nexport const PreviousDirectory = '..'\n\n/**\n * Home directory shortcut.\n * @public\n */\nexport const HomeDirectory = '~'\n\n/**\n * Root directory shortcut.\n * @public\n */\nexport const RootDirectory = '/'\n\n/**\n * Listing type for directories only.\n * @public\n */\nexport const DirectoriesListingType = 'directories'\n\n/**\n * Listing type for files only.\n * @public\n */\nexport const FilesListingType = 'files'\n\n/**\n * Generates a timestamped filename for a copy operation.\n * @param filePath - The original file path\n * @param extension - The extension to use (e.g., \"\" for copy)\n * @param path - Path adapter for path operations\n * @returns The new filename with timestamp\n */\nfunction generateTimestampedFilename(\n filePath: string,\n extension: string,\n path: PathAdapter,\n): string {\n const timestamp = Math.floor(Date.now() / 1000)\n const ext = path.extname(filePath)\n const basename = path.basename(filePath, ext)\n const dirname = path.dirname(filePath)\n const filename = path.basename(filePath)\n\n let output: string\n\n if (filename.startsWith('.') && ext === '') {\n // Hidden file with no extension (e.g., \".gitignore\")\n output = path.join(dirname, `${filename}_${timestamp}${extension}`)\n } else if (filename.startsWith('.') && ext !== '') {\n // Hidden file with extension (e.g., \".config.json\")\n output = path.join(dirname, `${basename}_${timestamp}${ext}${extension}`)\n } else if (ext !== '' && extension === '') {\n // Regular file with extension, copying (preserve original extension)\n output = path.join(dirname, `${basename}_${timestamp}${ext}`)\n } else if (ext !== '' && extension !== '') {\n // Regular file with extension, with new extension (replace with new extension)\n output = path.join(dirname, `${basename}_${timestamp}${extension}`)\n } else {\n // File without extension\n output = path.join(dirname, `${filename}_${timestamp}${extension}`)\n }\n\n return output\n}\n\n/**\n * Returns a list of files and directories within a given directory.\n * @param fs - FileSystem adapter\n * @param dir - The directory path to list\n * @param showHidden - Whether to include hidden files (starting with .)\n * @returns Array of directory entries\n * @public\n */\nexport async function getDirectoryListing(\n fs: FileSystemAdapter,\n dir: string,\n showHidden: boolean = false,\n): Promise<DirectoryEntry[]> {\n const entries = (await fs.readdir(dir, {\n withFileTypes: true,\n })) as DirectoryEntry[]\n\n if (!showHidden) {\n return entries.filter((entry) => !entry.name.startsWith('.'))\n }\n\n return entries\n}\n\n/**\n * Returns a directory listing based on type (directories | files).\n * @param fs - FileSystem adapter\n * @param dir - The directory path to list\n * @param listingType - Type of listing: \"directories\" or \"files\"\n * @param showHidden - Whether to include hidden files (starting with .)\n * @returns Array of directory entries matching the type\n * @public\n */\nexport async function getDirectoryListingByType(\n fs: FileSystemAdapter,\n dir: string,\n listingType: typeof DirectoriesListingType | typeof FilesListingType,\n showHidden: boolean = false,\n): Promise<DirectoryEntry[]> {\n const entries = (await fs.readdir(dir, {\n withFileTypes: true,\n })) as DirectoryEntry[]\n\n return entries.filter((entry) => {\n const isHidden = entry.name.startsWith('.')\n\n if (!showHidden && isHidden) {\n return false\n }\n\n if (listingType === DirectoriesListingType) {\n return entry.isDirectory()\n } else if (listingType === FilesListingType) {\n return entry.isFile()\n }\n\n return false\n })\n}\n\n/**\n * Returns the user's home directory.\n * @param fs - FileSystem adapter\n * @returns The home directory path\n * @public\n */\nexport function getHomeDirectory(fs: FileSystemAdapter): string {\n return fs.homedir()\n}\n\n/**\n * Returns the current working directory.\n * @param fs - FileSystem adapter\n * @returns The current working directory path\n * @public\n */\nexport function getWorkingDirectory(fs: FileSystemAdapter): string {\n return fs.cwd()\n}\n\n/**\n * Returns the contents of a file.\n * @param fs - FileSystem adapter\n * @param name - The file path to read\n * @returns The file contents as a string\n * @public\n */\nexport async function readFileContent(\n fs: FileSystemAdapter,\n name: string,\n): Promise<string> {\n const content = await fs.readFile(name, 'utf-8')\n return content\n}\n\n/**\n * Calculates size of a directory or file.\n * @param fs - FileSystem adapter\n * @param path - Path adapter\n * @param itemPath - The path to calculate size for\n * @returns The size in bytes\n * @public\n */\nexport async function getDirectoryItemSize(\n fs: FileSystemAdapter,\n path: PathAdapter,\n itemPath: string,\n): Promise<number> {\n const stats = await fs.stat(itemPath)\n\n if (!stats.isDirectory) {\n return stats.size\n }\n\n let totalSize = 0\n const entries = (await fs.readdir(itemPath, {\n withFileTypes: true,\n })) as DirectoryEntry[]\n\n for (const entry of entries) {\n const fullPath = path.join(itemPath, entry.name)\n if (entry.isDirectory()) {\n totalSize += await getDirectoryItemSize(fs, path, fullPath)\n } else {\n const fileStats = await fs.stat(fullPath)\n totalSize += fileStats.size\n }\n }\n\n return totalSize\n}\n\n/**\n * Search for files by name.\n * @param fs - FileSystem adapter\n * @param path - Path adapter\n * @param name - The name or partial name to search for\n * @param dir - The directory to search in\n * @returns Object containing arrays of paths and entries\n * @public\n */\nexport async function findFilesByName(\n fs: FileSystemAdapter,\n path: PathAdapter,\n name: string,\n dir: string,\n): Promise<{ paths: string[]; entries: DirectoryEntry[] }> {\n const paths: string[] = []\n const entries: DirectoryEntry[] = []\n\n async function search(searchDir: string): Promise<void> {\n try {\n const items = (await fs.readdir(searchDir, {\n withFileTypes: true,\n })) as DirectoryEntry[]\n\n for (const item of items) {\n const fullPath = path.join(searchDir, item.name)\n\n if (item.name.includes(name)) {\n paths.push(fullPath)\n entries.push(item)\n }\n\n if (item.isDirectory()) {\n await search(fullPath)\n }\n }\n } catch {\n // Skip directories we can't access (e.g., permission denied)\n // This allows the search to continue even when some directories are inaccessible\n }\n }\n\n await search(dir)\n\n return { paths, entries }\n}\n\n/**\n * Creates a new file.\n * @param fs - FileSystem adapter\n * @param name - The file path to create\n * @public\n */\nexport async function createFile(\n fs: FileSystemAdapter,\n name: string,\n): Promise<void> {\n // Create an empty file by writing an empty string\n await fs.writeFile(name, '')\n}\n\n/**\n * Creates a new directory.\n * Note: Parent directories must exist. Use recursive operations if you need to create nested directories.\n * @param fs - FileSystem adapter\n * @param name - The directory path to create\n * @public\n */\nexport async function createDirectory(\n fs: FileSystemAdapter,\n name: string,\n): Promise<void> {\n const exists = await fs.exists(name)\n if (!exists) {\n await fs.mkdir(name, { recursive: false })\n }\n}\n\n/**\n * Deletes a file.\n * @param fs - FileSystem adapter\n * @param name - The file path to delete\n * @public\n */\nexport async function deleteFile(\n fs: FileSystemAdapter,\n name: string,\n): Promise<void> {\n await fs.unlink(name)\n}\n\n/**\n * Deletes a directory recursively.\n * @param fs - FileSystem adapter\n * @param name - The directory path to delete\n * @public\n */\nexport async function deleteDirectory(\n fs: FileSystemAdapter,\n name: string,\n): Promise<void> {\n await fs.rmdir(name, { recursive: true, force: true })\n}\n\n/**\n * Renames a file or directory.\n * @param fs - FileSystem adapter\n * @param src - The source path\n * @param dst - The destination path\n * @public\n */\nexport async function renameDirectoryItem(\n fs: FileSystemAdapter,\n src: string,\n dst: string,\n): Promise<void> {\n await fs.rename(src, dst)\n}\n\n/**\n * Moves a file or directory.\n * @param fs - FileSystem adapter\n * @param src - The source path\n * @param dst - The destination path\n * @public\n */\nexport async function moveDirectoryItem(\n fs: FileSystemAdapter,\n src: string,\n dst: string,\n): Promise<void> {\n await fs.rename(src, dst)\n}\n\n/**\n * Copies a file with timestamp suffix.\n * @param fs - FileSystem adapter\n * @param path - Path adapter\n * @param name - The file path to copy\n * @returns The new file path\n * @public\n */\nexport async function copyFile(\n fs: FileSystemAdapter,\n path: PathAdapter,\n name: string,\n): Promise<string> {\n const output = generateTimestampedFilename(name, '', path)\n\n await fs.copyFile(name, output)\n return output\n}\n\n/**\n * Copies a directory recursively with timestamp suffix.\n * @param fs - FileSystem adapter\n * @param path - Path adapter\n * @param name - The directory path to copy\n * @returns The new directory path\n * @public\n */\nexport async function copyDirectory(\n fs: FileSystemAdapter,\n path: PathAdapter,\n name: string,\n): Promise<string> {\n const timestamp = Math.floor(Date.now() / 1000)\n const output = `${name}_${timestamp}`\n\n async function copyRecursive(src: string, dest: string): Promise<void> {\n const stats = await fs.stat(src)\n\n if (stats.isDirectory) {\n await fs.mkdir(dest, { recursive: true })\n const entries = (await fs.readdir(src, {\n withFileTypes: true,\n })) as DirectoryEntry[]\n\n for (const entry of entries) {\n const srcPath = path.join(src, entry.name)\n const destPath = path.join(dest, entry.name)\n\n if (entry.isDirectory()) {\n await copyRecursive(srcPath, destPath)\n } else {\n await fs.copyFile(srcPath, destPath)\n }\n }\n } else {\n await fs.copyFile(src, dest)\n }\n }\n\n await copyRecursive(name, output)\n return output\n}\n\n/**\n * Writes content to a file.\n * @param fs - FileSystem adapter\n * @param filePath - The file path to write to\n * @param content - The content to write\n * @public\n */\nexport async function writeToFile(\n fs: FileSystemAdapter,\n filePath: string,\n content: string,\n): Promise<void> {\n await fs.writeFile(filePath, content)\n}\n"]}
|
package/dist/index.d.cts
ADDED
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
import { FileSystemAdapter, DirectoryEntry, PathAdapter } from '@boba-cli/machine';
|
|
2
|
+
export { DirectoryEntry } from '@boba-cli/machine';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Directory shortcuts.
|
|
6
|
+
* @public
|
|
7
|
+
*/
|
|
8
|
+
declare const CurrentDirectory = ".";
|
|
9
|
+
/**
|
|
10
|
+
* Previous directory shortcut.
|
|
11
|
+
* @public
|
|
12
|
+
*/
|
|
13
|
+
declare const PreviousDirectory = "..";
|
|
14
|
+
/**
|
|
15
|
+
* Home directory shortcut.
|
|
16
|
+
* @public
|
|
17
|
+
*/
|
|
18
|
+
declare const HomeDirectory = "~";
|
|
19
|
+
/**
|
|
20
|
+
* Root directory shortcut.
|
|
21
|
+
* @public
|
|
22
|
+
*/
|
|
23
|
+
declare const RootDirectory = "/";
|
|
24
|
+
/**
|
|
25
|
+
* Listing type for directories only.
|
|
26
|
+
* @public
|
|
27
|
+
*/
|
|
28
|
+
declare const DirectoriesListingType = "directories";
|
|
29
|
+
/**
|
|
30
|
+
* Listing type for files only.
|
|
31
|
+
* @public
|
|
32
|
+
*/
|
|
33
|
+
declare const FilesListingType = "files";
|
|
34
|
+
/**
|
|
35
|
+
* Returns a list of files and directories within a given directory.
|
|
36
|
+
* @param fs - FileSystem adapter
|
|
37
|
+
* @param dir - The directory path to list
|
|
38
|
+
* @param showHidden - Whether to include hidden files (starting with .)
|
|
39
|
+
* @returns Array of directory entries
|
|
40
|
+
* @public
|
|
41
|
+
*/
|
|
42
|
+
declare function getDirectoryListing(fs: FileSystemAdapter, dir: string, showHidden?: boolean): Promise<DirectoryEntry[]>;
|
|
43
|
+
/**
|
|
44
|
+
* Returns a directory listing based on type (directories | files).
|
|
45
|
+
* @param fs - FileSystem adapter
|
|
46
|
+
* @param dir - The directory path to list
|
|
47
|
+
* @param listingType - Type of listing: "directories" or "files"
|
|
48
|
+
* @param showHidden - Whether to include hidden files (starting with .)
|
|
49
|
+
* @returns Array of directory entries matching the type
|
|
50
|
+
* @public
|
|
51
|
+
*/
|
|
52
|
+
declare function getDirectoryListingByType(fs: FileSystemAdapter, dir: string, listingType: typeof DirectoriesListingType | typeof FilesListingType, showHidden?: boolean): Promise<DirectoryEntry[]>;
|
|
53
|
+
/**
|
|
54
|
+
* Returns the user's home directory.
|
|
55
|
+
* @param fs - FileSystem adapter
|
|
56
|
+
* @returns The home directory path
|
|
57
|
+
* @public
|
|
58
|
+
*/
|
|
59
|
+
declare function getHomeDirectory(fs: FileSystemAdapter): string;
|
|
60
|
+
/**
|
|
61
|
+
* Returns the current working directory.
|
|
62
|
+
* @param fs - FileSystem adapter
|
|
63
|
+
* @returns The current working directory path
|
|
64
|
+
* @public
|
|
65
|
+
*/
|
|
66
|
+
declare function getWorkingDirectory(fs: FileSystemAdapter): string;
|
|
67
|
+
/**
|
|
68
|
+
* Returns the contents of a file.
|
|
69
|
+
* @param fs - FileSystem adapter
|
|
70
|
+
* @param name - The file path to read
|
|
71
|
+
* @returns The file contents as a string
|
|
72
|
+
* @public
|
|
73
|
+
*/
|
|
74
|
+
declare function readFileContent(fs: FileSystemAdapter, name: string): Promise<string>;
|
|
75
|
+
/**
|
|
76
|
+
* Calculates size of a directory or file.
|
|
77
|
+
* @param fs - FileSystem adapter
|
|
78
|
+
* @param path - Path adapter
|
|
79
|
+
* @param itemPath - The path to calculate size for
|
|
80
|
+
* @returns The size in bytes
|
|
81
|
+
* @public
|
|
82
|
+
*/
|
|
83
|
+
declare function getDirectoryItemSize(fs: FileSystemAdapter, path: PathAdapter, itemPath: string): Promise<number>;
|
|
84
|
+
/**
|
|
85
|
+
* Search for files by name.
|
|
86
|
+
* @param fs - FileSystem adapter
|
|
87
|
+
* @param path - Path adapter
|
|
88
|
+
* @param name - The name or partial name to search for
|
|
89
|
+
* @param dir - The directory to search in
|
|
90
|
+
* @returns Object containing arrays of paths and entries
|
|
91
|
+
* @public
|
|
92
|
+
*/
|
|
93
|
+
declare function findFilesByName(fs: FileSystemAdapter, path: PathAdapter, name: string, dir: string): Promise<{
|
|
94
|
+
paths: string[];
|
|
95
|
+
entries: DirectoryEntry[];
|
|
96
|
+
}>;
|
|
97
|
+
/**
|
|
98
|
+
* Creates a new file.
|
|
99
|
+
* @param fs - FileSystem adapter
|
|
100
|
+
* @param name - The file path to create
|
|
101
|
+
* @public
|
|
102
|
+
*/
|
|
103
|
+
declare function createFile(fs: FileSystemAdapter, name: string): Promise<void>;
|
|
104
|
+
/**
|
|
105
|
+
* Creates a new directory.
|
|
106
|
+
* Note: Parent directories must exist. Use recursive operations if you need to create nested directories.
|
|
107
|
+
* @param fs - FileSystem adapter
|
|
108
|
+
* @param name - The directory path to create
|
|
109
|
+
* @public
|
|
110
|
+
*/
|
|
111
|
+
declare function createDirectory(fs: FileSystemAdapter, name: string): Promise<void>;
|
|
112
|
+
/**
|
|
113
|
+
* Deletes a file.
|
|
114
|
+
* @param fs - FileSystem adapter
|
|
115
|
+
* @param name - The file path to delete
|
|
116
|
+
* @public
|
|
117
|
+
*/
|
|
118
|
+
declare function deleteFile(fs: FileSystemAdapter, name: string): Promise<void>;
|
|
119
|
+
/**
|
|
120
|
+
* Deletes a directory recursively.
|
|
121
|
+
* @param fs - FileSystem adapter
|
|
122
|
+
* @param name - The directory path to delete
|
|
123
|
+
* @public
|
|
124
|
+
*/
|
|
125
|
+
declare function deleteDirectory(fs: FileSystemAdapter, name: string): Promise<void>;
|
|
126
|
+
/**
|
|
127
|
+
* Renames a file or directory.
|
|
128
|
+
* @param fs - FileSystem adapter
|
|
129
|
+
* @param src - The source path
|
|
130
|
+
* @param dst - The destination path
|
|
131
|
+
* @public
|
|
132
|
+
*/
|
|
133
|
+
declare function renameDirectoryItem(fs: FileSystemAdapter, src: string, dst: string): Promise<void>;
|
|
134
|
+
/**
|
|
135
|
+
* Moves a file or directory.
|
|
136
|
+
* @param fs - FileSystem adapter
|
|
137
|
+
* @param src - The source path
|
|
138
|
+
* @param dst - The destination path
|
|
139
|
+
* @public
|
|
140
|
+
*/
|
|
141
|
+
declare function moveDirectoryItem(fs: FileSystemAdapter, src: string, dst: string): Promise<void>;
|
|
142
|
+
/**
|
|
143
|
+
* Copies a file with timestamp suffix.
|
|
144
|
+
* @param fs - FileSystem adapter
|
|
145
|
+
* @param path - Path adapter
|
|
146
|
+
* @param name - The file path to copy
|
|
147
|
+
* @returns The new file path
|
|
148
|
+
* @public
|
|
149
|
+
*/
|
|
150
|
+
declare function copyFile(fs: FileSystemAdapter, path: PathAdapter, name: string): Promise<string>;
|
|
151
|
+
/**
|
|
152
|
+
* Copies a directory recursively with timestamp suffix.
|
|
153
|
+
* @param fs - FileSystem adapter
|
|
154
|
+
* @param path - Path adapter
|
|
155
|
+
* @param name - The directory path to copy
|
|
156
|
+
* @returns The new directory path
|
|
157
|
+
* @public
|
|
158
|
+
*/
|
|
159
|
+
declare function copyDirectory(fs: FileSystemAdapter, path: PathAdapter, name: string): Promise<string>;
|
|
160
|
+
/**
|
|
161
|
+
* Writes content to a file.
|
|
162
|
+
* @param fs - FileSystem adapter
|
|
163
|
+
* @param filePath - The file path to write to
|
|
164
|
+
* @param content - The content to write
|
|
165
|
+
* @public
|
|
166
|
+
*/
|
|
167
|
+
declare function writeToFile(fs: FileSystemAdapter, filePath: string, content: string): Promise<void>;
|
|
168
|
+
|
|
169
|
+
export { CurrentDirectory, DirectoriesListingType, FilesListingType, HomeDirectory, PreviousDirectory, RootDirectory, copyDirectory, copyFile, createDirectory, createFile, deleteDirectory, deleteFile, findFilesByName, getDirectoryItemSize, getDirectoryListing, getDirectoryListingByType, getHomeDirectory, getWorkingDirectory, moveDirectoryItem, readFileContent, renameDirectoryItem, writeToFile };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
import { FileSystemAdapter, DirectoryEntry, PathAdapter } from '@boba-cli/machine';
|
|
2
|
+
export { DirectoryEntry } from '@boba-cli/machine';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Directory shortcuts.
|
|
6
|
+
* @public
|
|
7
|
+
*/
|
|
8
|
+
declare const CurrentDirectory = ".";
|
|
9
|
+
/**
|
|
10
|
+
* Previous directory shortcut.
|
|
11
|
+
* @public
|
|
12
|
+
*/
|
|
13
|
+
declare const PreviousDirectory = "..";
|
|
14
|
+
/**
|
|
15
|
+
* Home directory shortcut.
|
|
16
|
+
* @public
|
|
17
|
+
*/
|
|
18
|
+
declare const HomeDirectory = "~";
|
|
19
|
+
/**
|
|
20
|
+
* Root directory shortcut.
|
|
21
|
+
* @public
|
|
22
|
+
*/
|
|
23
|
+
declare const RootDirectory = "/";
|
|
24
|
+
/**
|
|
25
|
+
* Listing type for directories only.
|
|
26
|
+
* @public
|
|
27
|
+
*/
|
|
28
|
+
declare const DirectoriesListingType = "directories";
|
|
29
|
+
/**
|
|
30
|
+
* Listing type for files only.
|
|
31
|
+
* @public
|
|
32
|
+
*/
|
|
33
|
+
declare const FilesListingType = "files";
|
|
34
|
+
/**
|
|
35
|
+
* Returns a list of files and directories within a given directory.
|
|
36
|
+
* @param fs - FileSystem adapter
|
|
37
|
+
* @param dir - The directory path to list
|
|
38
|
+
* @param showHidden - Whether to include hidden files (starting with .)
|
|
39
|
+
* @returns Array of directory entries
|
|
40
|
+
* @public
|
|
41
|
+
*/
|
|
42
|
+
declare function getDirectoryListing(fs: FileSystemAdapter, dir: string, showHidden?: boolean): Promise<DirectoryEntry[]>;
|
|
43
|
+
/**
|
|
44
|
+
* Returns a directory listing based on type (directories | files).
|
|
45
|
+
* @param fs - FileSystem adapter
|
|
46
|
+
* @param dir - The directory path to list
|
|
47
|
+
* @param listingType - Type of listing: "directories" or "files"
|
|
48
|
+
* @param showHidden - Whether to include hidden files (starting with .)
|
|
49
|
+
* @returns Array of directory entries matching the type
|
|
50
|
+
* @public
|
|
51
|
+
*/
|
|
52
|
+
declare function getDirectoryListingByType(fs: FileSystemAdapter, dir: string, listingType: typeof DirectoriesListingType | typeof FilesListingType, showHidden?: boolean): Promise<DirectoryEntry[]>;
|
|
53
|
+
/**
|
|
54
|
+
* Returns the user's home directory.
|
|
55
|
+
* @param fs - FileSystem adapter
|
|
56
|
+
* @returns The home directory path
|
|
57
|
+
* @public
|
|
58
|
+
*/
|
|
59
|
+
declare function getHomeDirectory(fs: FileSystemAdapter): string;
|
|
60
|
+
/**
|
|
61
|
+
* Returns the current working directory.
|
|
62
|
+
* @param fs - FileSystem adapter
|
|
63
|
+
* @returns The current working directory path
|
|
64
|
+
* @public
|
|
65
|
+
*/
|
|
66
|
+
declare function getWorkingDirectory(fs: FileSystemAdapter): string;
|
|
67
|
+
/**
|
|
68
|
+
* Returns the contents of a file.
|
|
69
|
+
* @param fs - FileSystem adapter
|
|
70
|
+
* @param name - The file path to read
|
|
71
|
+
* @returns The file contents as a string
|
|
72
|
+
* @public
|
|
73
|
+
*/
|
|
74
|
+
declare function readFileContent(fs: FileSystemAdapter, name: string): Promise<string>;
|
|
75
|
+
/**
|
|
76
|
+
* Calculates size of a directory or file.
|
|
77
|
+
* @param fs - FileSystem adapter
|
|
78
|
+
* @param path - Path adapter
|
|
79
|
+
* @param itemPath - The path to calculate size for
|
|
80
|
+
* @returns The size in bytes
|
|
81
|
+
* @public
|
|
82
|
+
*/
|
|
83
|
+
declare function getDirectoryItemSize(fs: FileSystemAdapter, path: PathAdapter, itemPath: string): Promise<number>;
|
|
84
|
+
/**
|
|
85
|
+
* Search for files by name.
|
|
86
|
+
* @param fs - FileSystem adapter
|
|
87
|
+
* @param path - Path adapter
|
|
88
|
+
* @param name - The name or partial name to search for
|
|
89
|
+
* @param dir - The directory to search in
|
|
90
|
+
* @returns Object containing arrays of paths and entries
|
|
91
|
+
* @public
|
|
92
|
+
*/
|
|
93
|
+
declare function findFilesByName(fs: FileSystemAdapter, path: PathAdapter, name: string, dir: string): Promise<{
|
|
94
|
+
paths: string[];
|
|
95
|
+
entries: DirectoryEntry[];
|
|
96
|
+
}>;
|
|
97
|
+
/**
|
|
98
|
+
* Creates a new file.
|
|
99
|
+
* @param fs - FileSystem adapter
|
|
100
|
+
* @param name - The file path to create
|
|
101
|
+
* @public
|
|
102
|
+
*/
|
|
103
|
+
declare function createFile(fs: FileSystemAdapter, name: string): Promise<void>;
|
|
104
|
+
/**
|
|
105
|
+
* Creates a new directory.
|
|
106
|
+
* Note: Parent directories must exist. Use recursive operations if you need to create nested directories.
|
|
107
|
+
* @param fs - FileSystem adapter
|
|
108
|
+
* @param name - The directory path to create
|
|
109
|
+
* @public
|
|
110
|
+
*/
|
|
111
|
+
declare function createDirectory(fs: FileSystemAdapter, name: string): Promise<void>;
|
|
112
|
+
/**
|
|
113
|
+
* Deletes a file.
|
|
114
|
+
* @param fs - FileSystem adapter
|
|
115
|
+
* @param name - The file path to delete
|
|
116
|
+
* @public
|
|
117
|
+
*/
|
|
118
|
+
declare function deleteFile(fs: FileSystemAdapter, name: string): Promise<void>;
|
|
119
|
+
/**
|
|
120
|
+
* Deletes a directory recursively.
|
|
121
|
+
* @param fs - FileSystem adapter
|
|
122
|
+
* @param name - The directory path to delete
|
|
123
|
+
* @public
|
|
124
|
+
*/
|
|
125
|
+
declare function deleteDirectory(fs: FileSystemAdapter, name: string): Promise<void>;
|
|
126
|
+
/**
|
|
127
|
+
* Renames a file or directory.
|
|
128
|
+
* @param fs - FileSystem adapter
|
|
129
|
+
* @param src - The source path
|
|
130
|
+
* @param dst - The destination path
|
|
131
|
+
* @public
|
|
132
|
+
*/
|
|
133
|
+
declare function renameDirectoryItem(fs: FileSystemAdapter, src: string, dst: string): Promise<void>;
|
|
134
|
+
/**
|
|
135
|
+
* Moves a file or directory.
|
|
136
|
+
* @param fs - FileSystem adapter
|
|
137
|
+
* @param src - The source path
|
|
138
|
+
* @param dst - The destination path
|
|
139
|
+
* @public
|
|
140
|
+
*/
|
|
141
|
+
declare function moveDirectoryItem(fs: FileSystemAdapter, src: string, dst: string): Promise<void>;
|
|
142
|
+
/**
|
|
143
|
+
* Copies a file with timestamp suffix.
|
|
144
|
+
* @param fs - FileSystem adapter
|
|
145
|
+
* @param path - Path adapter
|
|
146
|
+
* @param name - The file path to copy
|
|
147
|
+
* @returns The new file path
|
|
148
|
+
* @public
|
|
149
|
+
*/
|
|
150
|
+
declare function copyFile(fs: FileSystemAdapter, path: PathAdapter, name: string): Promise<string>;
|
|
151
|
+
/**
|
|
152
|
+
* Copies a directory recursively with timestamp suffix.
|
|
153
|
+
* @param fs - FileSystem adapter
|
|
154
|
+
* @param path - Path adapter
|
|
155
|
+
* @param name - The directory path to copy
|
|
156
|
+
* @returns The new directory path
|
|
157
|
+
* @public
|
|
158
|
+
*/
|
|
159
|
+
declare function copyDirectory(fs: FileSystemAdapter, path: PathAdapter, name: string): Promise<string>;
|
|
160
|
+
/**
|
|
161
|
+
* Writes content to a file.
|
|
162
|
+
* @param fs - FileSystem adapter
|
|
163
|
+
* @param filePath - The file path to write to
|
|
164
|
+
* @param content - The content to write
|
|
165
|
+
* @public
|
|
166
|
+
*/
|
|
167
|
+
declare function writeToFile(fs: FileSystemAdapter, filePath: string, content: string): Promise<void>;
|
|
168
|
+
|
|
169
|
+
export { CurrentDirectory, DirectoriesListingType, FilesListingType, HomeDirectory, PreviousDirectory, RootDirectory, copyDirectory, copyFile, createDirectory, createFile, deleteDirectory, deleteFile, findFilesByName, getDirectoryItemSize, getDirectoryListing, getDirectoryListingByType, getHomeDirectory, getWorkingDirectory, moveDirectoryItem, readFileContent, renameDirectoryItem, writeToFile };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
// src/filesystem.ts
|
|
2
|
+
var CurrentDirectory = ".";
|
|
3
|
+
var PreviousDirectory = "..";
|
|
4
|
+
var HomeDirectory = "~";
|
|
5
|
+
var RootDirectory = "/";
|
|
6
|
+
var DirectoriesListingType = "directories";
|
|
7
|
+
var FilesListingType = "files";
|
|
8
|
+
function generateTimestampedFilename(filePath, extension, path) {
|
|
9
|
+
const timestamp = Math.floor(Date.now() / 1e3);
|
|
10
|
+
const ext = path.extname(filePath);
|
|
11
|
+
const basename = path.basename(filePath, ext);
|
|
12
|
+
const dirname = path.dirname(filePath);
|
|
13
|
+
const filename = path.basename(filePath);
|
|
14
|
+
let output;
|
|
15
|
+
if (filename.startsWith(".") && ext === "") {
|
|
16
|
+
output = path.join(dirname, `${filename}_${timestamp}${extension}`);
|
|
17
|
+
} else if (filename.startsWith(".") && ext !== "") {
|
|
18
|
+
output = path.join(dirname, `${basename}_${timestamp}${ext}${extension}`);
|
|
19
|
+
} else if (ext !== "" && extension === "") {
|
|
20
|
+
output = path.join(dirname, `${basename}_${timestamp}${ext}`);
|
|
21
|
+
} else {
|
|
22
|
+
output = path.join(dirname, `${filename}_${timestamp}${extension}`);
|
|
23
|
+
}
|
|
24
|
+
return output;
|
|
25
|
+
}
|
|
26
|
+
async function getDirectoryListing(fs, dir, showHidden = false) {
|
|
27
|
+
const entries = await fs.readdir(dir, {
|
|
28
|
+
withFileTypes: true
|
|
29
|
+
});
|
|
30
|
+
if (!showHidden) {
|
|
31
|
+
return entries.filter((entry) => !entry.name.startsWith("."));
|
|
32
|
+
}
|
|
33
|
+
return entries;
|
|
34
|
+
}
|
|
35
|
+
async function getDirectoryListingByType(fs, dir, listingType, showHidden = false) {
|
|
36
|
+
const entries = await fs.readdir(dir, {
|
|
37
|
+
withFileTypes: true
|
|
38
|
+
});
|
|
39
|
+
return entries.filter((entry) => {
|
|
40
|
+
const isHidden = entry.name.startsWith(".");
|
|
41
|
+
if (!showHidden && isHidden) {
|
|
42
|
+
return false;
|
|
43
|
+
}
|
|
44
|
+
if (listingType === DirectoriesListingType) {
|
|
45
|
+
return entry.isDirectory();
|
|
46
|
+
} else if (listingType === FilesListingType) {
|
|
47
|
+
return entry.isFile();
|
|
48
|
+
}
|
|
49
|
+
return false;
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
function getHomeDirectory(fs) {
|
|
53
|
+
return fs.homedir();
|
|
54
|
+
}
|
|
55
|
+
function getWorkingDirectory(fs) {
|
|
56
|
+
return fs.cwd();
|
|
57
|
+
}
|
|
58
|
+
async function readFileContent(fs, name) {
|
|
59
|
+
const content = await fs.readFile(name, "utf-8");
|
|
60
|
+
return content;
|
|
61
|
+
}
|
|
62
|
+
async function getDirectoryItemSize(fs, path, itemPath) {
|
|
63
|
+
const stats = await fs.stat(itemPath);
|
|
64
|
+
if (!stats.isDirectory) {
|
|
65
|
+
return stats.size;
|
|
66
|
+
}
|
|
67
|
+
let totalSize = 0;
|
|
68
|
+
const entries = await fs.readdir(itemPath, {
|
|
69
|
+
withFileTypes: true
|
|
70
|
+
});
|
|
71
|
+
for (const entry of entries) {
|
|
72
|
+
const fullPath = path.join(itemPath, entry.name);
|
|
73
|
+
if (entry.isDirectory()) {
|
|
74
|
+
totalSize += await getDirectoryItemSize(fs, path, fullPath);
|
|
75
|
+
} else {
|
|
76
|
+
const fileStats = await fs.stat(fullPath);
|
|
77
|
+
totalSize += fileStats.size;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
return totalSize;
|
|
81
|
+
}
|
|
82
|
+
async function findFilesByName(fs, path, name, dir) {
|
|
83
|
+
const paths = [];
|
|
84
|
+
const entries = [];
|
|
85
|
+
async function search(searchDir) {
|
|
86
|
+
try {
|
|
87
|
+
const items = await fs.readdir(searchDir, {
|
|
88
|
+
withFileTypes: true
|
|
89
|
+
});
|
|
90
|
+
for (const item of items) {
|
|
91
|
+
const fullPath = path.join(searchDir, item.name);
|
|
92
|
+
if (item.name.includes(name)) {
|
|
93
|
+
paths.push(fullPath);
|
|
94
|
+
entries.push(item);
|
|
95
|
+
}
|
|
96
|
+
if (item.isDirectory()) {
|
|
97
|
+
await search(fullPath);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
} catch {
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
await search(dir);
|
|
104
|
+
return { paths, entries };
|
|
105
|
+
}
|
|
106
|
+
async function createFile(fs, name) {
|
|
107
|
+
await fs.writeFile(name, "");
|
|
108
|
+
}
|
|
109
|
+
async function createDirectory(fs, name) {
|
|
110
|
+
const exists = await fs.exists(name);
|
|
111
|
+
if (!exists) {
|
|
112
|
+
await fs.mkdir(name, { recursive: false });
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
async function deleteFile(fs, name) {
|
|
116
|
+
await fs.unlink(name);
|
|
117
|
+
}
|
|
118
|
+
async function deleteDirectory(fs, name) {
|
|
119
|
+
await fs.rmdir(name, { recursive: true, force: true });
|
|
120
|
+
}
|
|
121
|
+
async function renameDirectoryItem(fs, src, dst) {
|
|
122
|
+
await fs.rename(src, dst);
|
|
123
|
+
}
|
|
124
|
+
async function moveDirectoryItem(fs, src, dst) {
|
|
125
|
+
await fs.rename(src, dst);
|
|
126
|
+
}
|
|
127
|
+
async function copyFile(fs, path, name) {
|
|
128
|
+
const output = generateTimestampedFilename(name, "", path);
|
|
129
|
+
await fs.copyFile(name, output);
|
|
130
|
+
return output;
|
|
131
|
+
}
|
|
132
|
+
async function copyDirectory(fs, path, name) {
|
|
133
|
+
const timestamp = Math.floor(Date.now() / 1e3);
|
|
134
|
+
const output = `${name}_${timestamp}`;
|
|
135
|
+
async function copyRecursive(src, dest) {
|
|
136
|
+
const stats = await fs.stat(src);
|
|
137
|
+
if (stats.isDirectory) {
|
|
138
|
+
await fs.mkdir(dest, { recursive: true });
|
|
139
|
+
const entries = await fs.readdir(src, {
|
|
140
|
+
withFileTypes: true
|
|
141
|
+
});
|
|
142
|
+
for (const entry of entries) {
|
|
143
|
+
const srcPath = path.join(src, entry.name);
|
|
144
|
+
const destPath = path.join(dest, entry.name);
|
|
145
|
+
if (entry.isDirectory()) {
|
|
146
|
+
await copyRecursive(srcPath, destPath);
|
|
147
|
+
} else {
|
|
148
|
+
await fs.copyFile(srcPath, destPath);
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
} else {
|
|
152
|
+
await fs.copyFile(src, dest);
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
await copyRecursive(name, output);
|
|
156
|
+
return output;
|
|
157
|
+
}
|
|
158
|
+
async function writeToFile(fs, filePath, content) {
|
|
159
|
+
await fs.writeFile(filePath, content);
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
export { CurrentDirectory, DirectoriesListingType, FilesListingType, HomeDirectory, PreviousDirectory, RootDirectory, copyDirectory, copyFile, createDirectory, createFile, deleteDirectory, deleteFile, findFilesByName, getDirectoryItemSize, getDirectoryListing, getDirectoryListingByType, getHomeDirectory, getWorkingDirectory, moveDirectoryItem, readFileContent, renameDirectoryItem, writeToFile };
|
|
163
|
+
//# sourceMappingURL=index.js.map
|
|
164
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/filesystem.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["import type {\n DirectoryEntry,\n FileSystemAdapter,\n PathAdapter,\n} from '@boba-cli/machine'\n\n/**\n * Directory shortcuts.\n * @public\n */\nexport const CurrentDirectory = '.'\n\n/**\n * Previous directory shortcut.\n * @public\n */\nexport const PreviousDirectory = '..'\n\n/**\n * Home directory shortcut.\n * @public\n */\nexport const HomeDirectory = '~'\n\n/**\n * Root directory shortcut.\n * @public\n */\nexport const RootDirectory = '/'\n\n/**\n * Listing type for directories only.\n * @public\n */\nexport const DirectoriesListingType = 'directories'\n\n/**\n * Listing type for files only.\n * @public\n */\nexport const FilesListingType = 'files'\n\n/**\n * Generates a timestamped filename for a copy operation.\n * @param filePath - The original file path\n * @param extension - The extension to use (e.g., \"\" for copy)\n * @param path - Path adapter for path operations\n * @returns The new filename with timestamp\n */\nfunction generateTimestampedFilename(\n filePath: string,\n extension: string,\n path: PathAdapter,\n): string {\n const timestamp = Math.floor(Date.now() / 1000)\n const ext = path.extname(filePath)\n const basename = path.basename(filePath, ext)\n const dirname = path.dirname(filePath)\n const filename = path.basename(filePath)\n\n let output: string\n\n if (filename.startsWith('.') && ext === '') {\n // Hidden file with no extension (e.g., \".gitignore\")\n output = path.join(dirname, `${filename}_${timestamp}${extension}`)\n } else if (filename.startsWith('.') && ext !== '') {\n // Hidden file with extension (e.g., \".config.json\")\n output = path.join(dirname, `${basename}_${timestamp}${ext}${extension}`)\n } else if (ext !== '' && extension === '') {\n // Regular file with extension, copying (preserve original extension)\n output = path.join(dirname, `${basename}_${timestamp}${ext}`)\n } else if (ext !== '' && extension !== '') {\n // Regular file with extension, with new extension (replace with new extension)\n output = path.join(dirname, `${basename}_${timestamp}${extension}`)\n } else {\n // File without extension\n output = path.join(dirname, `${filename}_${timestamp}${extension}`)\n }\n\n return output\n}\n\n/**\n * Returns a list of files and directories within a given directory.\n * @param fs - FileSystem adapter\n * @param dir - The directory path to list\n * @param showHidden - Whether to include hidden files (starting with .)\n * @returns Array of directory entries\n * @public\n */\nexport async function getDirectoryListing(\n fs: FileSystemAdapter,\n dir: string,\n showHidden: boolean = false,\n): Promise<DirectoryEntry[]> {\n const entries = (await fs.readdir(dir, {\n withFileTypes: true,\n })) as DirectoryEntry[]\n\n if (!showHidden) {\n return entries.filter((entry) => !entry.name.startsWith('.'))\n }\n\n return entries\n}\n\n/**\n * Returns a directory listing based on type (directories | files).\n * @param fs - FileSystem adapter\n * @param dir - The directory path to list\n * @param listingType - Type of listing: \"directories\" or \"files\"\n * @param showHidden - Whether to include hidden files (starting with .)\n * @returns Array of directory entries matching the type\n * @public\n */\nexport async function getDirectoryListingByType(\n fs: FileSystemAdapter,\n dir: string,\n listingType: typeof DirectoriesListingType | typeof FilesListingType,\n showHidden: boolean = false,\n): Promise<DirectoryEntry[]> {\n const entries = (await fs.readdir(dir, {\n withFileTypes: true,\n })) as DirectoryEntry[]\n\n return entries.filter((entry) => {\n const isHidden = entry.name.startsWith('.')\n\n if (!showHidden && isHidden) {\n return false\n }\n\n if (listingType === DirectoriesListingType) {\n return entry.isDirectory()\n } else if (listingType === FilesListingType) {\n return entry.isFile()\n }\n\n return false\n })\n}\n\n/**\n * Returns the user's home directory.\n * @param fs - FileSystem adapter\n * @returns The home directory path\n * @public\n */\nexport function getHomeDirectory(fs: FileSystemAdapter): string {\n return fs.homedir()\n}\n\n/**\n * Returns the current working directory.\n * @param fs - FileSystem adapter\n * @returns The current working directory path\n * @public\n */\nexport function getWorkingDirectory(fs: FileSystemAdapter): string {\n return fs.cwd()\n}\n\n/**\n * Returns the contents of a file.\n * @param fs - FileSystem adapter\n * @param name - The file path to read\n * @returns The file contents as a string\n * @public\n */\nexport async function readFileContent(\n fs: FileSystemAdapter,\n name: string,\n): Promise<string> {\n const content = await fs.readFile(name, 'utf-8')\n return content\n}\n\n/**\n * Calculates size of a directory or file.\n * @param fs - FileSystem adapter\n * @param path - Path adapter\n * @param itemPath - The path to calculate size for\n * @returns The size in bytes\n * @public\n */\nexport async function getDirectoryItemSize(\n fs: FileSystemAdapter,\n path: PathAdapter,\n itemPath: string,\n): Promise<number> {\n const stats = await fs.stat(itemPath)\n\n if (!stats.isDirectory) {\n return stats.size\n }\n\n let totalSize = 0\n const entries = (await fs.readdir(itemPath, {\n withFileTypes: true,\n })) as DirectoryEntry[]\n\n for (const entry of entries) {\n const fullPath = path.join(itemPath, entry.name)\n if (entry.isDirectory()) {\n totalSize += await getDirectoryItemSize(fs, path, fullPath)\n } else {\n const fileStats = await fs.stat(fullPath)\n totalSize += fileStats.size\n }\n }\n\n return totalSize\n}\n\n/**\n * Search for files by name.\n * @param fs - FileSystem adapter\n * @param path - Path adapter\n * @param name - The name or partial name to search for\n * @param dir - The directory to search in\n * @returns Object containing arrays of paths and entries\n * @public\n */\nexport async function findFilesByName(\n fs: FileSystemAdapter,\n path: PathAdapter,\n name: string,\n dir: string,\n): Promise<{ paths: string[]; entries: DirectoryEntry[] }> {\n const paths: string[] = []\n const entries: DirectoryEntry[] = []\n\n async function search(searchDir: string): Promise<void> {\n try {\n const items = (await fs.readdir(searchDir, {\n withFileTypes: true,\n })) as DirectoryEntry[]\n\n for (const item of items) {\n const fullPath = path.join(searchDir, item.name)\n\n if (item.name.includes(name)) {\n paths.push(fullPath)\n entries.push(item)\n }\n\n if (item.isDirectory()) {\n await search(fullPath)\n }\n }\n } catch {\n // Skip directories we can't access (e.g., permission denied)\n // This allows the search to continue even when some directories are inaccessible\n }\n }\n\n await search(dir)\n\n return { paths, entries }\n}\n\n/**\n * Creates a new file.\n * @param fs - FileSystem adapter\n * @param name - The file path to create\n * @public\n */\nexport async function createFile(\n fs: FileSystemAdapter,\n name: string,\n): Promise<void> {\n // Create an empty file by writing an empty string\n await fs.writeFile(name, '')\n}\n\n/**\n * Creates a new directory.\n * Note: Parent directories must exist. Use recursive operations if you need to create nested directories.\n * @param fs - FileSystem adapter\n * @param name - The directory path to create\n * @public\n */\nexport async function createDirectory(\n fs: FileSystemAdapter,\n name: string,\n): Promise<void> {\n const exists = await fs.exists(name)\n if (!exists) {\n await fs.mkdir(name, { recursive: false })\n }\n}\n\n/**\n * Deletes a file.\n * @param fs - FileSystem adapter\n * @param name - The file path to delete\n * @public\n */\nexport async function deleteFile(\n fs: FileSystemAdapter,\n name: string,\n): Promise<void> {\n await fs.unlink(name)\n}\n\n/**\n * Deletes a directory recursively.\n * @param fs - FileSystem adapter\n * @param name - The directory path to delete\n * @public\n */\nexport async function deleteDirectory(\n fs: FileSystemAdapter,\n name: string,\n): Promise<void> {\n await fs.rmdir(name, { recursive: true, force: true })\n}\n\n/**\n * Renames a file or directory.\n * @param fs - FileSystem adapter\n * @param src - The source path\n * @param dst - The destination path\n * @public\n */\nexport async function renameDirectoryItem(\n fs: FileSystemAdapter,\n src: string,\n dst: string,\n): Promise<void> {\n await fs.rename(src, dst)\n}\n\n/**\n * Moves a file or directory.\n * @param fs - FileSystem adapter\n * @param src - The source path\n * @param dst - The destination path\n * @public\n */\nexport async function moveDirectoryItem(\n fs: FileSystemAdapter,\n src: string,\n dst: string,\n): Promise<void> {\n await fs.rename(src, dst)\n}\n\n/**\n * Copies a file with timestamp suffix.\n * @param fs - FileSystem adapter\n * @param path - Path adapter\n * @param name - The file path to copy\n * @returns The new file path\n * @public\n */\nexport async function copyFile(\n fs: FileSystemAdapter,\n path: PathAdapter,\n name: string,\n): Promise<string> {\n const output = generateTimestampedFilename(name, '', path)\n\n await fs.copyFile(name, output)\n return output\n}\n\n/**\n * Copies a directory recursively with timestamp suffix.\n * @param fs - FileSystem adapter\n * @param path - Path adapter\n * @param name - The directory path to copy\n * @returns The new directory path\n * @public\n */\nexport async function copyDirectory(\n fs: FileSystemAdapter,\n path: PathAdapter,\n name: string,\n): Promise<string> {\n const timestamp = Math.floor(Date.now() / 1000)\n const output = `${name}_${timestamp}`\n\n async function copyRecursive(src: string, dest: string): Promise<void> {\n const stats = await fs.stat(src)\n\n if (stats.isDirectory) {\n await fs.mkdir(dest, { recursive: true })\n const entries = (await fs.readdir(src, {\n withFileTypes: true,\n })) as DirectoryEntry[]\n\n for (const entry of entries) {\n const srcPath = path.join(src, entry.name)\n const destPath = path.join(dest, entry.name)\n\n if (entry.isDirectory()) {\n await copyRecursive(srcPath, destPath)\n } else {\n await fs.copyFile(srcPath, destPath)\n }\n }\n } else {\n await fs.copyFile(src, dest)\n }\n }\n\n await copyRecursive(name, output)\n return output\n}\n\n/**\n * Writes content to a file.\n * @param fs - FileSystem adapter\n * @param filePath - The file path to write to\n * @param content - The content to write\n * @public\n */\nexport async function writeToFile(\n fs: FileSystemAdapter,\n filePath: string,\n content: string,\n): Promise<void> {\n await fs.writeFile(filePath, content)\n}\n"]}
|
package/package.json
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@boba-cli/filesystem",
|
|
3
|
+
"description": "Filesystem utility functions for Boba terminal UIs",
|
|
4
|
+
"version": "0.1.0-alpha.2",
|
|
5
|
+
"dependencies": {
|
|
6
|
+
"@boba-cli/machine": "0.1.0-alpha.1"
|
|
7
|
+
},
|
|
8
|
+
"devDependencies": {
|
|
9
|
+
"typescript": "5.8.2",
|
|
10
|
+
"vitest": "^4.0.16"
|
|
11
|
+
},
|
|
12
|
+
"engines": {
|
|
13
|
+
"node": ">=20.0.0"
|
|
14
|
+
},
|
|
15
|
+
"exports": {
|
|
16
|
+
".": {
|
|
17
|
+
"import": {
|
|
18
|
+
"types": "./dist/index.d.ts",
|
|
19
|
+
"default": "./dist/index.js"
|
|
20
|
+
},
|
|
21
|
+
"require": {
|
|
22
|
+
"types": "./dist/index.d.cts",
|
|
23
|
+
"default": "./dist/index.cjs"
|
|
24
|
+
}
|
|
25
|
+
},
|
|
26
|
+
"./package.json": "./package.json"
|
|
27
|
+
},
|
|
28
|
+
"files": [
|
|
29
|
+
"dist"
|
|
30
|
+
],
|
|
31
|
+
"main": "./dist/index.cjs",
|
|
32
|
+
"module": "./dist/index.js",
|
|
33
|
+
"type": "module",
|
|
34
|
+
"types": "./dist/index.d.ts",
|
|
35
|
+
"scripts": {
|
|
36
|
+
"build": "tsup",
|
|
37
|
+
"check:api-report": "pnpm run generate:api-report",
|
|
38
|
+
"check:eslint": "pnpm run lint",
|
|
39
|
+
"generate:api-report": "api-extractor run --local",
|
|
40
|
+
"lint": "eslint \"{src,test}/**/*.{ts,tsx}\"",
|
|
41
|
+
"test": "vitest run"
|
|
42
|
+
}
|
|
43
|
+
}
|