@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 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"]}
@@ -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 };
@@ -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
+ }