ktfile 0.0.1 → 0.0.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.
@@ -0,0 +1,34 @@
1
+ ---
2
+ name: Bug report
3
+ about: Create a report to help us improve
4
+ title: "[BUG]"
5
+ labels: ''
6
+ assignees: OguzhanUmutlu
7
+
8
+ ---
9
+
10
+ **Environment:**
11
+
12
+ - OS: [e.g. Windows 10, macOS 12, Ubuntu 20.04]
13
+ - Node.js: [e.g. 16.14.0]
14
+ - KTFile: [e.g. 1.0.0]
15
+
16
+ **Description:**
17
+ Clear description of the bug
18
+
19
+ **Reproduction:**
20
+
21
+ ```typescript
22
+ // Minimal code example
23
+ const file = fileSync('./example.txt');
24
+ // Steps to reproduce...
25
+ ```
26
+
27
+ **Expected Behavior:**
28
+ What should happen
29
+
30
+ **Actual Behavior:**
31
+ What actually happens
32
+
33
+ **Additional Context:**
34
+ Any other relevant information
@@ -0,0 +1,27 @@
1
+ ---
2
+ name: Feature request
3
+ about: Suggest an idea for this project
4
+ title: "[FEATURE]"
5
+ labels: enhancement
6
+ assignees: OguzhanUmutlu
7
+
8
+ ---
9
+
10
+ **Feature Description:**
11
+ Clear description of the proposed feature
12
+
13
+ **Use Case:**
14
+ Why is this feature needed? What problem does it solve?
15
+
16
+ **Proposed API:**
17
+
18
+ ```typescript
19
+ // Example of how the feature might work
20
+ file.newMethod(parameters);
21
+ ```
22
+
23
+ **Alternatives Considered:**
24
+ What other approaches did you consider?
25
+
26
+ **Additional Context:**
27
+ Any other relevant information
@@ -0,0 +1,291 @@
1
+ # Contributing to KTFile
2
+
3
+ Thank you for your interest in contributing to KTFile! This document provides guidelines and information for
4
+ contributors.
5
+
6
+ ## Table of Contents
7
+
8
+ - [Getting Started](#getting-started)
9
+ - [Development Setup](#development-setup)
10
+ - [Project Structure](#project-structure)
11
+ - [Development Workflow](#development-workflow)
12
+ - [Code Style Guidelines](#code-style-guidelines)
13
+ - [Testing](#testing)
14
+ - [Submitting Changes](#submitting-changes)
15
+
16
+ ## Getting Started
17
+
18
+ ### Prerequisites
19
+
20
+ - Node.js (version 14 or higher recommended)
21
+ - npm or yarn package manager
22
+ - Git
23
+
24
+ ### Fork and Clone
25
+
26
+ 1. Fork the repository on GitHub
27
+ 2. Clone your fork locally:
28
+ ```bash
29
+ git clone https://github.com/YOUR_USERNAME/ktfile.git
30
+ cd ktfile
31
+ ```
32
+ 3. Add the original repository as upstream:
33
+ ```bash
34
+ git remote add upstream https://github.com/OguzhanUmutlu/ktfile.git
35
+ ```
36
+
37
+ ## Development Setup
38
+
39
+ 1. Install dependencies:
40
+ ```bash
41
+ npm install
42
+ ```
43
+
44
+ 2. Build the project:
45
+ ```bash
46
+ npm run build
47
+ ```
48
+
49
+ 3. Run tests:
50
+ ```bash
51
+ npm test
52
+ ```
53
+
54
+ ## Project Structure
55
+
56
+ ```
57
+ ktfile/
58
+ ├── src/ # TypeScript source files
59
+ │ ├── async/ # Async file system implementations
60
+ │ │ ├── FileAsync.ts # Main async file class
61
+ │ │ └── IAsyncFS.ts # Async file system interface
62
+ │ ├── sync/ # Sync file system implementations
63
+ │ │ ├── FileSync.ts # Main sync file class
64
+ │ │ └── ISyncFS.ts # Sync file system interface
65
+ │ ├── IFile.ts # Base file interface
66
+ │ ├── Utils.ts # Utility functions
67
+ │ └── ktfile.ts # Main entry point
68
+ ├── types/ # Generated TypeScript declarations
69
+ ├── dist/ # Compiled JavaScript output
70
+ ├── tests/ # Test files
71
+ │ ├── test.ts # Main test suite
72
+ │ ├── test.html # Browser tests
73
+ │ └── clean.js # Test cleanup utility
74
+ ├── rollup.config.mjs # Build configuration
75
+ ├── tsconfig.json # TypeScript configuration
76
+ ├── index.min.js # Minified distribution file
77
+ └── package.json # Project metadata
78
+ ```
79
+
80
+ ### Key Files
81
+
82
+ - **`src/ktfile.ts`**: Main entry point, exports public API
83
+ - **`src/sync/FileSync.ts`**: Synchronous file operations implementation
84
+ - **`src/async/FileAsync.ts`**: Asynchronous file operations implementation
85
+ - **`src/IFile.ts`**: Base interface shared by both sync and async implementations
86
+ - **`src/Utils.ts`**: Shared utility functions
87
+
88
+ ## Development Workflow
89
+
90
+ ### Branch Strategy
91
+
92
+ 1. Create a feature branch from `main`:
93
+ ```bash
94
+ git checkout -b feature/your-feature-name
95
+ ```
96
+
97
+ 2. Make your changes and commit them with descriptive messages
98
+
99
+ 3. Keep your branch up to date with upstream:
100
+ ```bash
101
+ git fetch upstream
102
+ git rebase upstream/main
103
+ ```
104
+
105
+ 4. Push your branch and create a pull request
106
+
107
+ ### Building
108
+
109
+ The project uses Rollup for building. Available scripts:
110
+
111
+ ```bash
112
+ npm run build # Build TypeScript and create distributions
113
+ npm run build:types # Generate type declarations only
114
+ npm run dev # Watch mode for development
115
+ ```
116
+
117
+ ### File System Abstractions
118
+
119
+ KTFile uses interface-based abstractions to support different environments:
120
+
121
+ - **`ISyncFS`**: Interface for synchronous file system operations
122
+ - **`IAsyncFS`**: Interface for asynchronous file system operations
123
+
124
+ When adding new functionality:
125
+
126
+ 1. Add the method signature to the appropriate interface
127
+ 2. Implement it in both sync and async file classes
128
+ 3. Ensure cross-platform compatibility
129
+
130
+ ## Code Style Guidelines
131
+
132
+ ### TypeScript Standards
133
+
134
+ - Use TypeScript strict mode
135
+ - Provide explicit type annotations for public APIs
136
+ - Use meaningful variable and function names
137
+ - Follow existing naming conventions:
138
+ - Classes: `PascalCase`
139
+ - Methods/properties: `camelCase`
140
+ - Constants: `UPPER_SNAKE_CASE`
141
+
142
+ ### Code Formatting
143
+
144
+ - Use 4 spaces for indentation
145
+ - Use semicolons
146
+ - Use double quotes for strings
147
+ - Maximum line length: 120 characters
148
+
149
+ ### Error Handling
150
+
151
+ - Methods should return `null` on failure rather than throwing exceptions
152
+ - Use `| null` return types for operations that can fail
153
+ - Document when methods can return `null` and why
154
+
155
+ ### Example Code Style
156
+
157
+ ```typescript
158
+ export class FileSync extends IFile<ISyncFS> {
159
+ /**
160
+ * Reads file content as string or Buffer
161
+ * @param encoding Optional text encoding
162
+ * @returns File content or null if read fails
163
+ */
164
+ read(encoding?: BufferEncoding): string | null;
165
+ read(): Buffer | null;
166
+ read(encoding?: BufferEncoding): string | Buffer | null {
167
+ try {
168
+ // Implementation here
169
+ return this.fs.readFileSync(this.path, encoding);
170
+ } catch {
171
+ return null;
172
+ }
173
+ }
174
+ }
175
+ ```
176
+
177
+ ## Testing
178
+
179
+ ### Running Tests
180
+
181
+ ```bash
182
+ npm test # Run all tests
183
+ npm run test:node # Run Node.js tests only
184
+ npm run test:browser # Run browser tests only
185
+ ```
186
+
187
+ ### Test Structure
188
+
189
+ - Tests are located in the `tests/` directory
190
+ - Main test suite: `tests/test.ts`
191
+ - Browser compatibility tests: `tests/test.html`
192
+ - Test cleanup utility: `tests/clean.js`
193
+
194
+ ### Writing Tests
195
+
196
+ When adding new features:
197
+
198
+ 1. Add tests for both sync and async implementations
199
+ 2. Test error conditions (methods returning `null`)
200
+ 3. Test cross-platform behavior where applicable
201
+ 4. Include edge cases and boundary conditions
202
+
203
+ Example test pattern:
204
+
205
+ ```typescript
206
+ // Test successful operation
207
+ const file = fileSync('./test-file.txt');
208
+ file.write('test content');
209
+ assert.strictEqual(file.read(), 'test content');
210
+
211
+ // Test error condition
212
+ const nonexistent = fileSync('./nonexistent.txt');
213
+ assert.strictEqual(nonexistent.read(), null);
214
+
215
+ // Test async equivalent
216
+ const asyncFile = fileAsync('./test-file.txt');
217
+ await asyncFile.write('test content');
218
+ assert.strictEqual(await asyncFile.read(), 'test content');
219
+ ```
220
+
221
+ ## Submitting Changes
222
+
223
+ ### Pull Request Guidelines
224
+
225
+ 1. **Clear Title**: Use a descriptive title that summarizes the change
226
+ 2. **Description**: Include:
227
+ - What the change does
228
+ - Why it's needed
229
+ - Any breaking changes
230
+ - Testing performed
231
+
232
+ 3. **Code Quality**:
233
+ - Ensure all tests pass
234
+ - Follow coding standards
235
+ - Update documentation if needed
236
+ - Add tests for new functionality
237
+
238
+ 4. **Commit Messages**:
239
+ - Use clear, descriptive commit messages
240
+ - Reference issue numbers when applicable
241
+ - Use imperative mood: "Add feature" not "Added feature"
242
+
243
+ ### Pull Request Template
244
+
245
+ ```markdown
246
+ ## Description
247
+
248
+ Brief description of changes
249
+
250
+ ## Type of Change
251
+
252
+ - [ ] Bug fix
253
+ - [ ] New feature
254
+ - [ ] Breaking change
255
+ - [ ] Documentation update
256
+
257
+ ## Testing
258
+
259
+ - [ ] Tests pass locally
260
+ - [ ] Added tests for new functionality
261
+ - [ ] Tested on multiple platforms (if applicable)
262
+
263
+ ## Checklist
264
+
265
+ - [ ] Code follows project style guidelines
266
+ - [ ] Self-review completed
267
+ - [ ] Documentation updated (if needed)
268
+ - [ ] No breaking changes (or breaking changes documented)
269
+ ```
270
+
271
+ ## Debugging
272
+
273
+ - Test both sync and async implementations
274
+ - Verify behavior in both Node.js and browser environments
275
+
276
+ ## Getting Help
277
+
278
+ - **Documentation**: Check the README and inline code documentation
279
+ - **Issues**: Search existing issues for similar problems
280
+ - **Discussions**: Use GitHub Discussions for questions and ideas
281
+ - **Contact**: Reach out to maintainers through GitHub
282
+
283
+ ## Recognition
284
+
285
+ Contributors will be recognized in:
286
+
287
+ - GitHub contributors list
288
+ - Release notes (for significant contributions)
289
+ - Documentation acknowledgments
290
+
291
+ Thank you for contributing to KTFile! 🎉
package/README.md CHANGED
@@ -1,2 +1,431 @@
1
- # kfile
2
- Fluent, chainable File API
1
+ # KTFile
2
+
3
+ A powerful, cross-platform file system library for JavaScript/TypeScript that provides both synchronous and asynchronous APIs with a clean, object-oriented interface.
4
+
5
+ ## Features
6
+
7
+ - 🚀 **Dual API**: Both synchronous (`FileSync`) and asynchronous (`FileAsync`) operations
8
+ - 🔧 **Cross-platform**: Works in Node.js and other JavaScript environments
9
+ - 📁 **Rich file operations**: Create, read, write, copy, move, delete files and directories
10
+ - 🎯 **Type-safe**: Full TypeScript support with detailed type definitions
11
+ - 🔗 **Path manipulation**: Intuitive path joining and navigation
12
+ - 📊 **File metadata**: Access file properties like size, timestamps, permissions
13
+ - 🔄 **Directory traversal**: Walk through directory trees with generators
14
+ - 📝 **Multiple formats**: Support for text, binary, and JSON file operations
15
+
16
+ ## Installation
17
+
18
+ ```bash
19
+ npm install ktfile
20
+ ```
21
+
22
+ ## Quick Start
23
+
24
+ ### Basic Usage
25
+
26
+ ```javascript
27
+ import { fileSync, fileAsync, File } from 'ktfile';
28
+
29
+ // Synchronous API
30
+ const file = fileSync('/path/to/file.txt');
31
+ file.write('Hello, world!');
32
+ console.log(file.read()); // "Hello, world!"
33
+
34
+ // Asynchronous API
35
+ const asyncFile = fileAsync('/path/to/file.txt');
36
+ await asyncFile.write('Hello, async world!');
37
+ console.log(await asyncFile.read()); // "Hello, async world!"
38
+
39
+ // Alternative syntax
40
+ const file2 = new File('/another/path');
41
+ ```
42
+
43
+ ### Node.js Setup
44
+
45
+ The library automatically initializes with Node.js `fs` module when available. For custom environments:
46
+
47
+ ```javascript
48
+ import { initFS } from 'ktfile';
49
+ import fs from 'fs';
50
+
51
+ initFS(fs);
52
+ ```
53
+
54
+ ## API Reference
55
+
56
+ ### FileSync Class
57
+
58
+ #### Properties
59
+
60
+ - `fs: ISyncFS` - The underlying file system instance
61
+ - `canExecute: boolean` - File execute permission
62
+ - `canRead: boolean` - File read permission
63
+ - `canWrite: boolean` - File write permission
64
+ - `creationTime: Date | null` - File creation timestamp
65
+ - `lastModified: Date | null` - Last modification timestamp
66
+ - `lastAccess: Date | null` - Last access timestamp
67
+ - `exists: boolean | null` - Whether the file exists
68
+ - `name: string` - File name with extension
69
+ - `nameWithoutExtension: string` - File name without extension
70
+ - `extension: string` - File extension
71
+ - `parent: FileSync | null` - Parent directory
72
+ - `uri: string` - File URI
73
+ - `separator: string` - Path separator for the platform
74
+ - `isDirectory: boolean | null` - Whether this is a directory
75
+ - `isFile: boolean | null` - Whether this is a regular file
76
+ - `isHidden: boolean` - Whether the file is hidden
77
+ - `isSymbolicLink: boolean | null` - Whether this is a symbolic link
78
+ - `size: number | null` - File size in bytes
79
+ - `sizeKB: number | null` - File size in kilobytes
80
+ - `sizeMB: number | null` - File size in megabytes
81
+ - `sizeGB: number | null` - File size in gigabytes
82
+
83
+ #### Methods
84
+
85
+ ##### Path Operations
86
+ ```javascript
87
+ // Join paths
88
+ const newPath = file.to('subdirectory', 'file.txt');
89
+
90
+ // Check if path contains another path
91
+ const contains = parentDir.contains(childFile);
92
+ ```
93
+
94
+ ##### File Creation and Deletion
95
+ ```javascript
96
+ // Create file
97
+ file.createFile();
98
+
99
+ // Create temporary file
100
+ const tempFile = FileSync.createTempFile(directory, 'prefix', '.tmp');
101
+
102
+ // Delete file or directory
103
+ file.delete(recursive = false, force = false);
104
+
105
+ // Schedule deletion on exit
106
+ file.deleteOnExit(recursive = false);
107
+
108
+ // Clear directory contents
109
+ directory.clear(recursive = true);
110
+ ```
111
+
112
+ ##### Directory Operations
113
+ ```javascript
114
+ // Create directory
115
+ directory.mkdir(recursive = false);
116
+
117
+ // Create directory tree
118
+ directory.mkdirs();
119
+
120
+ // List files in directory
121
+ const files = directory.listFiles();
122
+ const filenames = directory.listFilenames();
123
+
124
+ // Walk directory tree
125
+ for (const file of directory.walk()) {
126
+ console.log(file.name);
127
+ }
128
+ ```
129
+
130
+ ##### File Operations
131
+ ```javascript
132
+ // Copy file
133
+ file.copyTo(destination, overwrite = false, recursive = false);
134
+
135
+ // Move/rename file
136
+ file.renameTo(newLocation, overwrite = false, recursive = false);
137
+ ```
138
+
139
+ ##### Reading Files
140
+ ```javascript
141
+ // Read as string
142
+ const content = file.read('utf8');
143
+
144
+ // Read as Buffer
145
+ const buffer = file.read();
146
+
147
+ // Read lines as array
148
+ const lines = file.readLines('utf8');
149
+
150
+ // Read JSON
151
+ const data = file.readJSON();
152
+
153
+ // Read symbolic link target
154
+ const target = symlink.readlink();
155
+ ```
156
+
157
+ ##### Writing Files
158
+ ```javascript
159
+ // Write string or Buffer
160
+ file.write('content', 'utf8');
161
+ file.write(buffer);
162
+
163
+ // Write with custom encoder
164
+ file.write(data, { write: () => data });
165
+
166
+ // Write JSON
167
+ file.writeJSON({ key: 'value' });
168
+
169
+ // Append to file
170
+ file.append('more content', 'utf8');
171
+ ```
172
+
173
+ ### FileAsync Class
174
+
175
+ The `FileAsync` class provides Promise-based asynchronous operations with a similar API to `FileSync`:
176
+
177
+ #### Properties
178
+
179
+ - `fs: IAsyncFS` - The underlying async file system instance
180
+ - `name: string` - File name with extension
181
+ - `nameWithoutExtension: string` - File name without extension
182
+ - `extension: string` - File extension
183
+ - `parent: FileAsync | null` - Parent directory
184
+ - `uri: string` - File URI
185
+ - `separator: string` - Path separator for the platform
186
+ - `isHidden: boolean` - Whether the file is hidden
187
+ - `sync: FileSync` - Access to synchronous version of this file
188
+
189
+ #### Methods
190
+
191
+ All methods that return metadata or perform operations are asynchronous and return Promises:
192
+
193
+ ##### Permission Methods
194
+ ```javascript
195
+ // Check permissions
196
+ const canRead = await file.canRead();
197
+ const canWrite = await file.canWrite();
198
+ const canExecute = await file.canExecute();
199
+
200
+ // Set permissions
201
+ await file.setReadable(true);
202
+ await file.setWritable(false);
203
+ await file.setExecutable(true);
204
+ ```
205
+
206
+ ##### Metadata Methods
207
+ ```javascript
208
+ // Get timestamps
209
+ const created = await file.creationTime();
210
+ const modified = await file.lastModified();
211
+ const accessed = await file.lastAccess();
212
+
213
+ // Set timestamps
214
+ await file.setCreationTime(new Date());
215
+ await file.setLastModified(new Date());
216
+
217
+ // File information
218
+ const exists = await file.exists();
219
+ const isDir = await file.isDirectory();
220
+ const isFile = await file.isFile();
221
+ const isLink = await file.isSymbolicLink();
222
+
223
+ // File sizes
224
+ const bytes = await file.size();
225
+ const kb = await file.sizeKB();
226
+ const mb = await file.sizeMB();
227
+ const gb = await file.sizeGB();
228
+ ```
229
+
230
+ ##### File Operations
231
+ ```javascript
232
+ // Create and delete
233
+ await file.createFile();
234
+ await file.delete(recursive, force);
235
+ await directory.clear(recursive);
236
+
237
+ // Copy and move
238
+ await file.copyTo(destination, overwrite, recursive);
239
+ await file.renameTo(newLocation, overwrite, recursive);
240
+ ```
241
+
242
+ ##### Directory Operations
243
+ ```javascript
244
+ // Create directories
245
+ await directory.mkdir(recursive);
246
+ await directory.mkdirs();
247
+
248
+ // List contents
249
+ const files = await directory.listFiles();
250
+ const filenames = await directory.listFilenames();
251
+
252
+ // Walk directory tree (AsyncGenerator)
253
+ for await (const file of directory.walk()) {
254
+ console.log(file.name);
255
+ }
256
+ ```
257
+
258
+ ##### Reading Files
259
+ ```javascript
260
+ // Read file contents
261
+ const content = await file.read('utf8');
262
+ const buffer = await file.read();
263
+ const lines = await file.readLines('utf8');
264
+ const data = await file.readJSON();
265
+
266
+ // Read symbolic link
267
+ const target = await symlink.readlink();
268
+ ```
269
+
270
+ ##### Writing Files
271
+ ```javascript
272
+ // Write content
273
+ await file.write('content', 'utf8');
274
+ await file.write(buffer);
275
+ await file.writeJSON({ key: 'value' });
276
+ await file.append('more content', 'utf8');
277
+ ```
278
+
279
+ ##### Static Methods
280
+ ```javascript
281
+ // Create temporary file
282
+ const tempFile = FileAsync.createTempFile(directory, 'prefix', '.tmp');
283
+ ```
284
+
285
+ ## Examples
286
+
287
+ ### Working with Directories
288
+
289
+ ```javascript
290
+ import { fileSync } from 'ktfile';
291
+
292
+ const projectDir = fileSync('./my-project');
293
+
294
+ // Create project structure
295
+ projectDir.mkdirs();
296
+ projectDir.to('src').mkdir();
297
+ projectDir.to('tests').mkdir();
298
+ projectDir.to('docs').mkdir();
299
+
300
+ // Create files
301
+ const packageJson = projectDir.to('package.json');
302
+ packageJson.writeJSON({
303
+ name: 'my-project',
304
+ version: '1.0.0'
305
+ });
306
+
307
+ const readme = projectDir.to('README.md');
308
+ readme.write('# My Project\n\nDescription here...');
309
+
310
+ // List all files
311
+ for (const file of projectDir.walk()) {
312
+ if (file.isFile) {
313
+ console.log(`File: ${file.name} (${file.sizeKB} KB)`);
314
+ }
315
+ }
316
+ ```
317
+
318
+ ### File Manipulation
319
+
320
+ ```javascript
321
+ import { fileSync } from 'ktfile';
322
+
323
+ const sourceFile = fileSync('./data.json');
324
+ const backupFile = fileSync('./backup/data-backup.json');
325
+
326
+ // Create backup directory
327
+ backupFile.parent?.mkdirs();
328
+
329
+ // Copy file
330
+ sourceFile.copyTo(backupFile, true);
331
+
332
+ // Read and modify JSON
333
+ const data = sourceFile.readJSON();
334
+ data.lastBackup = new Date().toISOString();
335
+ sourceFile.writeJSON(data);
336
+
337
+ console.log(`Backup created: ${backupFile.size} bytes`);
338
+ ```
339
+
340
+ ### Async Operations
341
+
342
+ ```javascript
343
+ import { fileAsync } from 'ktfile';
344
+
345
+ async function processFiles() {
346
+ const directory = fileAsync('./uploads');
347
+ const files = await directory.listFiles();
348
+
349
+ for (const file of files || []) {
350
+ if (file.extension === '.txt') {
351
+ const content = await file.read('utf8');
352
+ const processed = content.toUpperCase();
353
+
354
+ const outputFile = file.parent?.to('processed', file.name);
355
+ await outputFile?.parent?.mkdirs();
356
+ await outputFile?.write(processed);
357
+
358
+ console.log(`Processed: ${file.name}`);
359
+ }
360
+ }
361
+ }
362
+
363
+ processFiles().catch(console.error);
364
+ ```
365
+
366
+ ### Temporary Files
367
+
368
+ ```javascript
369
+ import { FileSync, fileSync } from 'ktfile';
370
+
371
+ const tempDir = fileSync('./temp');
372
+ tempDir.mkdirs();
373
+
374
+ // Create temporary file
375
+ const tempFile = FileSync.createTempFile(tempDir, 'data-', '.json');
376
+ tempFile.writeJSON({ processing: true, timestamp: Date.now() });
377
+
378
+ // Use the temporary file
379
+ console.log(`Temp file created: ${tempFile.name}`);
380
+
381
+ // Clean up on exit
382
+ tempFile.deleteOnExit();
383
+ ```
384
+
385
+ ## Error Handling
386
+
387
+ Methods return `null` when operations fail, allowing for graceful error handling:
388
+
389
+ ```javascript
390
+ const file = fileSync('./nonexistent.txt');
391
+
392
+ const content = file.read();
393
+ if (content === null) {
394
+ console.log('File does not exist or cannot be read');
395
+ } else {
396
+ console.log('File content:', content);
397
+ }
398
+
399
+ // Check existence before operations
400
+ if (file.exists) {
401
+ file.delete();
402
+ }
403
+ ```
404
+
405
+ ## Cross-Platform Compatibility
406
+
407
+ KTFile handles platform differences automatically:
408
+
409
+ ```javascript
410
+ const file = fileSync('./path/to/file.txt');
411
+
412
+ // Uses correct separator for platform
413
+ console.log(file.separator); // '/' on Unix, '\' on Windows
414
+
415
+ // Paths are normalized automatically
416
+ const nested = file.parent?.to('..', 'sibling', 'file.txt');
417
+ ```
418
+
419
+ ## License
420
+
421
+ MIT License
422
+
423
+ See the [LICENSE](LICENSE) file for details.
424
+
425
+ ## Contributing
426
+
427
+ Contributions are welcome! Please read the [CONTRIBUTING.md](CONTRIBUTING.md) for details on how to contribute to this project.
428
+
429
+ ## Support
430
+
431
+ If you find this library useful, please consider starring the repository on GitHub and sharing it with others!
package/index.min.js CHANGED
@@ -1 +1 @@
1
- let t=[];function s(s,e=t){s.startsWith("/")?(e=[],s=s.slice(1)):e=[...e];const i=s.split("/");for(const t of i)".."===t?e.pop():"."!==t&&""!==t&&e.push(t);return e}"undefined"!=typeof process&&"cwd"in process&&"function"==typeof process.cwd&&(t=s(process.cwd()));const e=new Map;function i(t,s,e){const i=t.listeners(s);t.removeAllListeners(s);for(const n of i)n!==e&&t.on(s,n);t.on(s,e)}function n(){for(const[t,s]of e.entries())new d(t).delete(s);e.clear(),"undefined"!=typeof process?(process.off("SIGINT",r),process.off("SIGTERM",l),process.off("exit",n)):"undefined"!=typeof window&&(window.removeEventListener("beforeunload",n),window.removeEventListener("pagehide",n))}function r(){n(),process.exit(130)}function l(){n(),process.exit(143)}function a(){"undefined"!=typeof process?(i(process,"exit",n),i(process,"SIGINT",r),i(process,"SIGTERM",l)):"undefined"!=typeof window&&(window.addEventListener("beforeunload",n),window.addEventListener("pagehide",n))}class h{split;constructor(t){this.split="string"==typeof t?s(t):[...t]}get fullPath(){return 0===this.split.length?this.separator:this.split.join(this.separator)}createWriteStream(t){if("object"==typeof this.fs&&"createWriteStream"in this.fs&&"function"==typeof this.fs.createWriteStream)return this.fs.createWriteStream(this.split.join("/"),t);throw new Error("File system does not support createWriteStream")}createReadStream(t){if("object"==typeof this.fs&&"createReadStream"in this.fs&&"function"==typeof this.fs.createReadStream)return this.fs.createReadStream(this.split.join("/"),t);throw new Error("File system does not support createReadStream")}createAppendStream(t){if("object"==typeof this.fs&&"createWriteStream"in this.fs&&"function"==typeof this.fs.createWriteStream)return this.fs.createWriteStream(this.split.join("/"),{flags:"a",encoding:t});throw new Error("File system does not support createAppendStream")}createInputStream(t){if("object"==typeof this.fs&&"createReadStream"in this.fs&&"function"==typeof this.fs.createReadStream)return this.fs.createReadStream(this.split.join("/"),{flags:"r",encoding:t});throw new Error("File system does not support createInputStream")}}async function u(t){try{return t().then(()=>!0).catch(()=>!1)}catch(t){return!1}}async function f(t){try{return t().then(t=>t).catch(()=>null)}catch(t){return null}}class c extends h{static fs;static createTempFile(t,s="kfile-temp",e=".tmp"){if(!("mkdTemp"in c.fs))throw new Error("mkdTemp is not available in the current FS.");const i=t?t.fullPath:".",n=this.fs.mkdtemp(`${i}/${s}-`);return new c(`${n}${e}`)}get fs(){return c.fs}canExecute(){return u(()=>this.fs.access(this.fullPath,this.fs?.constants?.X_OK??1))}async setExecutable(t=!0){return await u(()=>this.fs.chmod(this.fullPath,t?493:420))?this:null}canRead(){return u(()=>this.fs.access(this.fullPath,this.fs?.constants?.R_OK??4))}async setReadable(t=!0){return await u(()=>this.fs.chmod(this.fullPath,t?420:0))?this:null}canWrite(){return u(()=>this.fs.access(this.fullPath,this.fs?.constants?.W_OK??2))}async setWritable(t=!0){return await u(()=>this.fs.chmod(this.fullPath,t?420:292))?this:null}creationTime(){return f(()=>this.fs.stat(this.fullPath).then(t=>t.birthtime).catch(()=>null))}async setCreationTime(t){return await u(()=>this.fs.utimes(this.fullPath,t,t))?this:null}async lastModified(){return await f(()=>this.fs.stat(this.fullPath).then(t=>t.mtime).catch(()=>null))}async setLastModified(t){return await u(()=>this.fs.utimes(this.fullPath,t,t))?this:null}exists(){return f(()=>this.fs.exists(this.fullPath))}lastAccess(){return f(()=>this.fs.stat(this.fullPath).then(t=>t.atime).catch(()=>null))}get name(){return this.fullPath.split(this.separator).pop()||""}get nameWithoutExtension(){const t=this.name,s=t.lastIndexOf(".");return-1===s?t:t.substring(0,s)}get extension(){const t=this.name,s=t.lastIndexOf(".");return-1===s?"":t.substring(s+1)}get parent(){return 0===this.split.length?null:new c(this.split.slice(0,-1))}get uri(){return`file://${this.fullPath}`}get separator(){return"sep"in this.fs&&"string"==typeof this.fs.sep?this.fs.sep:"/"}isDirectory(){return f(()=>this.fs.stat(this.fullPath).then(t=>t.isDirectory()).catch(()=>null))}isFile(){return f(()=>this.fs.stat(this.fullPath).then(t=>t.isFile()).catch(()=>null))}get isHidden(){return this.name.startsWith(".")||this.fullPath.split(this.separator).some(t=>t.startsWith("."))}isSymbolicLink(){return f(()=>this.fs.lstat(this.fullPath).then(t=>t.isSymbolicLink()).catch(()=>null))}size(){return f(()=>this.fs.stat(this.fullPath).then(t=>t.size).catch(()=>null))}async sizeKB(){const t=await this.size();return null!==t?t/1024:null}async sizeMB(){const t=await this.size();return null!==t?t/1048576:null}async sizeGB(){const t=await this.size();return null!==t?t/1073741824:null}to(...t){return new c(this.fullPath+"/"+t.join("/"))}contains(t){if(t.split.length<=this.split.length)return!1;for(let s=0;s<this.split.length;s++)if(this.split[s]!==t.split[s])return!1;return!0}async createFile(){return await this.exists()?await this.isFile()?this:null:await this.write("")?this:null}async delete(t,s=t){if(t){if("rmSync"in this.fs)return await u(()=>this.fs.rm(this.fullPath,{recursive:!0,force:s}))?this:null;if("rmdirSync"in this.fs)return await u(()=>this.fs.rmdir(this.fullPath,{recursive:!0}))?this:null;let t=!1;for(const s of await this.listFiles()||[])await s.delete(!0)||(t=!0);if(t)return null}return await u(()=>this.fs.unlink(this.fullPath))?this:null}deleteOnExit(t){e.set(this.fullPath,t),a()}async clear(t){if(t){const t=await this.listFiles();if(null===t)return null;let s=!1;for(const e of t||[])await e.delete(!0)||(s=!0);return s?null:this}return await this.write(""),null}async listFiles(){if(!this.isDirectory)return null;const t=await f(()=>this.fs.readdir(this.fullPath));return t?t.map(t=>new c(`${this.fullPath}/${t}`)):null}listFilenames(){return f(()=>this.fs.readdir(this.fullPath))}async mkdir(t=!1){return await u(()=>this.fs.mkdir(this.fullPath,{recursive:t}))?this:null}async mkdirs(){return await this.mkdir(!0)?this:null}async renameTo(t,s,e){return this.fullPath===t.fullPath?this:!t.exists||s||await t.delete(e)?(e&&await(this.parent?.mkdirs()),await u(()=>this.fs.rename(this.fullPath,t.fullPath))?this:null):null}async copyTo(t,s,e){if(this.fullPath===t.fullPath)return this;if(!this.exists)return null;if(t.exists&&!s&&!await t.delete(e))return null;if(this.isFile){const s=await this.read();return null===s?null:await t.write(s)?this:null}if(!await t.mkdir(e))return null;const i=await this.listFiles();if(null===i)return null;let n=!1;for(const r of i){const i=t.to(r.name);await r.copyTo(i,s,e)||(n=!0)}return n?null:this}async*walk(){if(this.isDirectory){yield this;for(const t of await this.listFiles()||[])yield*t.walk()}else yield this}read(t){return f(()=>this.fs.readFile(this.fullPath,t))}async readLines(t="utf8"){const s=await this.read(t);return"string"==typeof s?s.split(/\r?\n/):null}async readJSON(){const t=await this.read("utf8");if("string"!=typeof t)return null;try{return JSON.parse(t)}catch(t){return null}}async readlink(){if(!this.isSymbolicLink)return null;const t=await f(()=>this.fs.readlink(this.fullPath));return t?new c(t):null}async write(t,s){return null!==s&&"object"==typeof s&&"write"in s&&"function"==typeof s.write&&(t=s.write()),await u(()=>this.fs.writeFile(this.fullPath,t,s))?this:null}async writeJSON(t){return await u(()=>this.write(JSON.stringify(t,null,2)))?this:null}async append(t,s){return await u(()=>this.fs.appendFile(this.fullPath,t,s))?this:null}get sync(){return new d(this.split)}}function o(t){try{return t(),!0}catch(t){return!1}}function p(t){try{return t()}catch(t){return null}}class d extends h{static fs;static createTempFile(t,s="kfile-temp",e=".tmp"){if(!("mkdTempSync"in d.fs))throw new Error("mkdTempSync is not available in the current FS.");const i=t?t.fullPath:".",n=this.fs.mkdtempSync(`${i}/${s}-`);return new d(`${n}${e}`)}get fs(){return d.fs}get canExecute(){return o(()=>this.fs.accessSync(this.fullPath,this.fs?.constants?.X_OK??1))}set canExecute(t){o(()=>this.fs.chmodSync(this.fullPath,t?493:420))}get canRead(){return o(()=>this.fs.accessSync(this.fullPath,this.fs?.constants?.R_OK??4))}set canRead(t){o(()=>this.fs.chmodSync(this.fullPath,t?420:0))}get canWrite(){return o(()=>this.fs.accessSync(this.fullPath,this.fs?.constants?.W_OK??2))}set canWrite(t){o(()=>this.fs.chmodSync(this.fullPath,t?420:292))}get creationTime(){return p(()=>this.fs.statSync(this.fullPath).birthtime)}set creationTime(t){o(()=>this.fs.utimesSync(this.fullPath,t,t))}get lastModified(){return p(()=>this.fs.statSync(this.fullPath).mtime)}set lastModified(t){o(()=>this.fs.utimesSync(this.fullPath,t,t))}get exists(){return p(()=>this.fs.existsSync(this.fullPath))}get lastAccess(){return p(()=>this.fs.statSync(this.fullPath).atime)}get name(){return this.fullPath.split(this.separator).pop()||""}get nameWithoutExtension(){const t=this.name,s=t.lastIndexOf(".");return-1===s?t:t.substring(0,s)}get extension(){const t=this.name,s=t.lastIndexOf(".");return-1===s?"":t.substring(s+1)}get parent(){return 0===this.split.length?null:new d(this.split.slice(0,-1))}get uri(){return`file://${this.fullPath}`}get separator(){return"sep"in this.fs&&"string"==typeof this.fs.sep?this.fs.sep:"/"}get isDirectory(){return p(()=>this.fs.statSync(this.fullPath).isDirectory())}get isFile(){return p(()=>this.fs.statSync(this.fullPath).isFile())}get isHidden(){return this.name.startsWith(".")||this.fullPath.split(this.separator).some(t=>t.startsWith("."))}get isSymbolicLink(){return p(()=>this.fs.lstatSync(this.fullPath).isSymbolicLink())}get size(){return p(()=>this.fs.statSync(this.fullPath).size)}get sizeKB(){const t=this.size;return null!==t?t/1024:null}get sizeMB(){const t=this.size;return null!==t?t/1048576:null}get sizeGB(){const t=this.size;return null!==t?t/1073741824:null}to(...t){return new d(this.fullPath+"/"+t.join("/"))}contains(t){if(t.split.length<=this.split.length)return!1;for(let s=0;s<this.split.length;s++)if(this.split[s]!==t.split[s])return!1;return!0}createFile(){return this.exists?this.isFile?this:null:this.write("")?this:null}delete(t,s=t){if(t){if("rmSync"in this.fs)return o(()=>this.fs.rmSync(this.fullPath,{recursive:!0,force:s}))?this:null;if("rmdirSync"in this.fs)return o(()=>this.fs.rmdirSync(this.fullPath,{recursive:!0}))?this:null;let t=!1;for(const s of this.listFiles()||[])s.delete(!0)||(t=!0);if(t)return null}return o(()=>this.fs.unlinkSync(this.fullPath))?this:null}deleteOnExit(t){e.set(this.fullPath,t),a()}clear(t){if(t){const t=this.listFiles();if(null===t)return null;let s=!1;for(const e of t||[])e.delete(!0)||(s=!0);return s?null:this}return this.write(""),null}listFiles(){if(!this.isDirectory)return null;const t=p(()=>this.fs.readdirSync(this.fullPath));return t?t.map(t=>new d(`${this.fullPath}/${t}`)):null}listFilenames(){return p(()=>this.fs.readdirSync(this.fullPath))}mkdir(t=!1){return o(()=>this.fs.mkdirSync(this.fullPath,{recursive:t}))?this:null}mkdirs(){return this.mkdir(!0)?this:null}renameTo(t,s,e){return this.fullPath===t.fullPath?this:!t.exists||s||t.delete(e)?(e&&this.parent?.mkdirs(),o(()=>this.fs.renameSync(this.fullPath,t.fullPath))?this:null):null}copyTo(t,s,e){if(this.fullPath===t.fullPath)return this;if(!this.exists)return null;if(t.exists&&!s&&!t.delete(e))return null;if(this.isFile){const s=this.read();return null===s?null:t.write(s)?this:null}if(!t.mkdir(e))return null;const i=this.listFiles();if(null===i)return null;let n=!1;for(const r of i){const i=t.to(r.name);r.copyTo(i,s,e)||(n=!0)}return n?null:this}*walk(){if(this.isDirectory){yield this;for(const t of this.listFiles()||[])yield*t.walk()}else yield this}read(t){return p(()=>this.fs.readFileSync(this.fullPath,t))}readLines(t="utf8"){const s=this.read(t);return"string"==typeof s?s.split(/\r?\n/):null}readJSON(){const t=this.read("utf8");if("string"!=typeof t)return null;try{return JSON.parse(t)}catch(t){return null}}readlink(){if(!this.isSymbolicLink)return null;const t=p(()=>this.fs.readlinkSync(this.fullPath));return t?new d(t):null}write(t,s){return null!==s&&"object"==typeof s&&"write"in s&&"function"==typeof s.write&&(t=s.write()),o(()=>this.fs.writeFileSync(this.fullPath,t,s))?this:null}writeJSON(t){return o(()=>this.write(JSON.stringify(t,null,2)))?this:null}append(t,s){return o(()=>this.fs.appendFileSync(this.fullPath,t,s))?this:null}get async(){return new c(this.split)}}function y(t){d.fs=t,c.fs=t.promises}function m(t){return new d(t)}function w(t){return new c(t)}if("undefined"!=typeof process)try{y(await import("fs"))}catch{}export{d as File,c as FileAsync,d as FileSync,w as fileAsync,m as fileSync,y as initFS};
1
+ let t=[];function s(s,e=t){s.startsWith("/")?(e=[],s=s.slice(1)):e=[...e];const i=s.split("/");for(const t of i)".."===t?e.pop():"."!==t&&""!==t&&e.push(t);return e}"undefined"!=typeof process&&"cwd"in process&&"function"==typeof process.cwd&&(t=s(process.cwd()));const e=new Map;function i(t,s,e){const i=t.listeners(s);t.removeAllListeners(s);for(const n of i)n!==e&&t.on(s,n);t.on(s,e)}function n(){for(const[t,s]of e.entries())new d(t).delete(s);e.clear(),"undefined"!=typeof process?(process.off("SIGINT",r),process.off("SIGTERM",l),process.off("exit",n)):"undefined"!=typeof window&&(window.removeEventListener("beforeunload",n),window.removeEventListener("pagehide",n))}function r(){n(),process.exit(130)}function l(){n(),process.exit(143)}function a(){"undefined"!=typeof process?(i(process,"exit",n),i(process,"SIGINT",r),i(process,"SIGTERM",l)):"undefined"!=typeof window&&(window.addEventListener("beforeunload",n),window.addEventListener("pagehide",n))}class h{split;constructor(t){this.split="string"==typeof t?s(t):[...t]}get fullPath(){return 0===this.split.length?this.separator:this.split.join(this.separator)}createWriteStream(t){if("object"==typeof this.fs&&"createWriteStream"in this.fs&&"function"==typeof this.fs.createWriteStream)return this.fs.createWriteStream(this.split.join("/"),t);throw new Error("File system does not support createWriteStream")}createReadStream(t){if("object"==typeof this.fs&&"createReadStream"in this.fs&&"function"==typeof this.fs.createReadStream)return this.fs.createReadStream(this.split.join("/"),t);throw new Error("File system does not support createReadStream")}createAppendStream(t){if("object"==typeof this.fs&&"createWriteStream"in this.fs&&"function"==typeof this.fs.createWriteStream)return this.fs.createWriteStream(this.split.join("/"),{flags:"a",encoding:t});throw new Error("File system does not support createAppendStream")}createInputStream(t){if("object"==typeof this.fs&&"createReadStream"in this.fs&&"function"==typeof this.fs.createReadStream)return this.fs.createReadStream(this.split.join("/"),{flags:"r",encoding:t});throw new Error("File system does not support createInputStream")}}async function u(t){try{return t().then(()=>!0).catch(()=>!1)}catch(t){return!1}}async function f(t){try{return t().then(t=>t).catch(()=>null)}catch(t){return null}}class c extends h{static fs;static createTempFile(t,s="ktfile-temp",e=".tmp"){if(!("mkdTemp"in c.fs))throw new Error("mkdTemp is not available in the current FS.");const i=t?t.fullPath:".",n=this.fs.mkdtemp(`${i}/${s}-`);return new c(`${n}${e}`)}get fs(){return c.fs}canExecute(){return u(()=>this.fs.access(this.fullPath,this.fs?.constants?.X_OK??1))}async setExecutable(t=!0){return await u(()=>this.fs.chmod(this.fullPath,t?493:420))?this:null}canRead(){return u(()=>this.fs.access(this.fullPath,this.fs?.constants?.R_OK??4))}async setReadable(t=!0){return await u(()=>this.fs.chmod(this.fullPath,t?420:0))?this:null}canWrite(){return u(()=>this.fs.access(this.fullPath,this.fs?.constants?.W_OK??2))}async setWritable(t=!0){return await u(()=>this.fs.chmod(this.fullPath,t?420:292))?this:null}creationTime(){return f(()=>this.fs.stat(this.fullPath).then(t=>t.birthtime).catch(()=>null))}async setCreationTime(t){return await u(()=>this.fs.utimes(this.fullPath,t,t))?this:null}async lastModified(){return await f(()=>this.fs.stat(this.fullPath).then(t=>t.mtime).catch(()=>null))}async setLastModified(t){return await u(()=>this.fs.utimes(this.fullPath,t,t))?this:null}exists(){return f(()=>this.fs.exists(this.fullPath))}lastAccess(){return f(()=>this.fs.stat(this.fullPath).then(t=>t.atime).catch(()=>null))}get name(){return this.fullPath.split(this.separator).pop()||""}get nameWithoutExtension(){const t=this.name,s=t.lastIndexOf(".");return-1===s?t:t.substring(0,s)}get extension(){const t=this.name,s=t.lastIndexOf(".");return-1===s?"":t.substring(s+1)}get parent(){return 0===this.split.length?null:new c(this.split.slice(0,-1))}get uri(){return`file://${this.fullPath}`}get separator(){return"sep"in this.fs&&"string"==typeof this.fs.sep?this.fs.sep:"/"}isDirectory(){return f(()=>this.fs.stat(this.fullPath).then(t=>t.isDirectory()).catch(()=>null))}isFile(){return f(()=>this.fs.stat(this.fullPath).then(t=>t.isFile()).catch(()=>null))}get isHidden(){return this.name.startsWith(".")||this.fullPath.split(this.separator).some(t=>t.startsWith("."))}isSymbolicLink(){return f(()=>this.fs.lstat(this.fullPath).then(t=>t.isSymbolicLink()).catch(()=>null))}size(){return f(()=>this.fs.stat(this.fullPath).then(t=>t.size).catch(()=>null))}async sizeKB(){const t=await this.size();return null!==t?t/1024:null}async sizeMB(){const t=await this.size();return null!==t?t/1048576:null}async sizeGB(){const t=await this.size();return null!==t?t/1073741824:null}to(...t){return new c(this.fullPath+"/"+t.join("/"))}contains(t){if(t.split.length<=this.split.length)return!1;for(let s=0;s<this.split.length;s++)if(this.split[s]!==t.split[s])return!1;return!0}async createFile(){return await this.exists()?await this.isFile()?this:null:await this.write("")?this:null}async delete(t,s=t){if(t){if("rmSync"in this.fs)return await u(()=>this.fs.rm(this.fullPath,{recursive:!0,force:s}))?this:null;if("rmdirSync"in this.fs)return await u(()=>this.fs.rmdir(this.fullPath,{recursive:!0}))?this:null;let t=!1;for(const s of await this.listFiles()||[])await s.delete(!0)||(t=!0);if(t)return null}return await u(()=>this.fs.unlink(this.fullPath))?this:null}deleteOnExit(t){e.set(this.fullPath,t),a()}async clear(t){if(t){const t=await this.listFiles();if(null===t)return null;let s=!1;for(const e of t||[])await e.delete(!0)||(s=!0);return s?null:this}return await this.write(""),null}async listFiles(){if(!this.isDirectory)return null;const t=await f(()=>this.fs.readdir(this.fullPath));return t?t.map(t=>new c(`${this.fullPath}/${t}`)):null}listFilenames(){return f(()=>this.fs.readdir(this.fullPath))}async mkdir(t=!1){return await u(()=>this.fs.mkdir(this.fullPath,{recursive:t}))?this:null}async mkdirs(){return await this.mkdir(!0)?this:null}async renameTo(t,s,e){return this.fullPath===t.fullPath?this:!t.exists||s||await t.delete(e)?(e&&await(this.parent?.mkdirs()),await u(()=>this.fs.rename(this.fullPath,t.fullPath))?this:null):null}async copyTo(t,s,e){if(this.fullPath===t.fullPath)return this;if(!this.exists)return null;if(t.exists&&!s&&!await t.delete(e))return null;if(this.isFile){const s=await this.read();return null===s?null:await t.write(s)?this:null}if(!await t.mkdir(e))return null;const i=await this.listFiles();if(null===i)return null;let n=!1;for(const r of i){const i=t.to(r.name);await r.copyTo(i,s,e)||(n=!0)}return n?null:this}async*walk(){if(this.isDirectory){yield this;for(const t of await this.listFiles()||[])yield*t.walk()}else yield this}read(t){return f(()=>this.fs.readFile(this.fullPath,t))}async readLines(t="utf8"){const s=await this.read(t);return"string"==typeof s?s.split(/\r?\n/):null}async readJSON(){const t=await this.read("utf8");if("string"!=typeof t)return null;try{return JSON.parse(t)}catch(t){return null}}async readlink(){if(!this.isSymbolicLink)return null;const t=await f(()=>this.fs.readlink(this.fullPath));return t?new c(t):null}async write(t,s){return null!==s&&"object"==typeof s&&"write"in s&&"function"==typeof s.write&&(t=s.write()),await u(()=>this.fs.writeFile(this.fullPath,t,s))?this:null}async writeJSON(t){return await u(()=>this.write(JSON.stringify(t,null,2)))?this:null}async append(t,s){return await u(()=>this.fs.appendFile(this.fullPath,t,s))?this:null}get sync(){return new d(this.split)}}function o(t){try{return t(),!0}catch(t){return!1}}function p(t){try{return t()}catch(t){return null}}class d extends h{static fs;static createTempFile(t,s="ktfile-temp",e=".tmp"){if(!("mkdTempSync"in d.fs))throw new Error("mkdTempSync is not available in the current FS.");const i=t?t.fullPath:".",n=this.fs.mkdtempSync(`${i}/${s}-`);return new d(`${n}${e}`)}get fs(){return d.fs}get canExecute(){return o(()=>this.fs.accessSync(this.fullPath,this.fs?.constants?.X_OK??1))}set canExecute(t){o(()=>this.fs.chmodSync(this.fullPath,t?493:420))}get canRead(){return o(()=>this.fs.accessSync(this.fullPath,this.fs?.constants?.R_OK??4))}set canRead(t){o(()=>this.fs.chmodSync(this.fullPath,t?420:0))}get canWrite(){return o(()=>this.fs.accessSync(this.fullPath,this.fs?.constants?.W_OK??2))}set canWrite(t){o(()=>this.fs.chmodSync(this.fullPath,t?420:292))}get creationTime(){return p(()=>this.fs.statSync(this.fullPath).birthtime)}set creationTime(t){o(()=>this.fs.utimesSync(this.fullPath,t,t))}get lastModified(){return p(()=>this.fs.statSync(this.fullPath).mtime)}set lastModified(t){o(()=>this.fs.utimesSync(this.fullPath,t,t))}get exists(){return p(()=>this.fs.existsSync(this.fullPath))}get lastAccess(){return p(()=>this.fs.statSync(this.fullPath).atime)}get name(){return this.fullPath.split(this.separator).pop()||""}get nameWithoutExtension(){const t=this.name,s=t.lastIndexOf(".");return-1===s?t:t.substring(0,s)}get extension(){const t=this.name,s=t.lastIndexOf(".");return-1===s?"":t.substring(s+1)}get parent(){return 0===this.split.length?null:new d(this.split.slice(0,-1))}get uri(){return`file://${this.fullPath}`}get separator(){return"sep"in this.fs&&"string"==typeof this.fs.sep?this.fs.sep:"/"}get isDirectory(){return p(()=>this.fs.statSync(this.fullPath).isDirectory())}get isFile(){return p(()=>this.fs.statSync(this.fullPath).isFile())}get isHidden(){return this.name.startsWith(".")||this.fullPath.split(this.separator).some(t=>t.startsWith("."))}get isSymbolicLink(){return p(()=>this.fs.lstatSync(this.fullPath).isSymbolicLink())}get size(){return p(()=>this.fs.statSync(this.fullPath).size)}get sizeKB(){const t=this.size;return null!==t?t/1024:null}get sizeMB(){const t=this.size;return null!==t?t/1048576:null}get sizeGB(){const t=this.size;return null!==t?t/1073741824:null}to(...t){return new d(this.fullPath+"/"+t.join("/"))}contains(t){if(t.split.length<=this.split.length)return!1;for(let s=0;s<this.split.length;s++)if(this.split[s]!==t.split[s])return!1;return!0}createFile(){return this.exists?this.isFile?this:null:this.write("")?this:null}delete(t,s=t){if(t){if("rmSync"in this.fs)return o(()=>this.fs.rmSync(this.fullPath,{recursive:!0,force:s}))?this:null;if("rmdirSync"in this.fs)return o(()=>this.fs.rmdirSync(this.fullPath,{recursive:!0}))?this:null;let t=!1;for(const s of this.listFiles()||[])s.delete(!0)||(t=!0);if(t)return null}return o(()=>this.fs.unlinkSync(this.fullPath))?this:null}deleteOnExit(t){e.set(this.fullPath,t),a()}clear(t){if(t){const t=this.listFiles();if(null===t)return null;let s=!1;for(const e of t||[])e.delete(!0)||(s=!0);return s?null:this}return this.write(""),null}listFiles(){if(!this.isDirectory)return null;const t=p(()=>this.fs.readdirSync(this.fullPath));return t?t.map(t=>new d(`${this.fullPath}/${t}`)):null}listFilenames(){return p(()=>this.fs.readdirSync(this.fullPath))}mkdir(t=!1){return o(()=>this.fs.mkdirSync(this.fullPath,{recursive:t}))?this:null}mkdirs(){return this.mkdir(!0)?this:null}renameTo(t,s,e){return this.fullPath===t.fullPath?this:!t.exists||s||t.delete(e)?(e&&this.parent?.mkdirs(),o(()=>this.fs.renameSync(this.fullPath,t.fullPath))?this:null):null}copyTo(t,s,e){if(this.fullPath===t.fullPath)return this;if(!this.exists)return null;if(t.exists&&!s&&!t.delete(e))return null;if(this.isFile){const s=this.read();return null===s?null:t.write(s)?this:null}if(!t.mkdir(e))return null;const i=this.listFiles();if(null===i)return null;let n=!1;for(const r of i){const i=t.to(r.name);r.copyTo(i,s,e)||(n=!0)}return n?null:this}*walk(){if(this.isDirectory){yield this;for(const t of this.listFiles()||[])yield*t.walk()}else yield this}read(t){return p(()=>this.fs.readFileSync(this.fullPath,t))}readLines(t="utf8"){const s=this.read(t);return"string"==typeof s?s.split(/\r?\n/):null}readJSON(){const t=this.read("utf8");if("string"!=typeof t)return null;try{return JSON.parse(t)}catch(t){return null}}readlink(){if(!this.isSymbolicLink)return null;const t=p(()=>this.fs.readlinkSync(this.fullPath));return t?new d(t):null}write(t,s){return null!==s&&"object"==typeof s&&"write"in s&&"function"==typeof s.write&&(t=s.write()),o(()=>this.fs.writeFileSync(this.fullPath,t,s))?this:null}writeJSON(t){return o(()=>this.write(JSON.stringify(t,null,2)))?this:null}append(t,s){return o(()=>this.fs.appendFileSync(this.fullPath,t,s))?this:null}get async(){return new c(this.split)}}function y(t){d.fs=t,c.fs=t.promises}function m(t){return new d(t)}function w(t){return new c(t)}if("undefined"!=typeof process)try{y(await import("fs"))}catch{}export{d as File,c as FileAsync,d as FileSync,w as fileAsync,m as fileSync,y as initFS};
package/package.json CHANGED
@@ -1,9 +1,9 @@
1
1
  {
2
2
  "name": "ktfile",
3
- "version": "0.0.1",
3
+ "version": "0.0.2",
4
4
  "description": "Fluent, modern and chainable File API\n\n",
5
5
  "main": "index.min.js",
6
- "types": "types/kfile.d.ts",
6
+ "types": "types/ktfile.d.ts",
7
7
  "type": "module",
8
8
  "scripts": {
9
9
  "test": "tsx tests/test.ts",
@@ -39,6 +39,6 @@
39
39
  "license": "MIT",
40
40
  "repository": {
41
41
  "type": "git",
42
- "url": "git+https://github.com/OguzhanUmutlu/kfile.git"
42
+ "url": "git+https://github.com/OguzhanUmutlu/ktfile.git"
43
43
  }
44
44
  }
File without changes