@statewalker/webrun-files 0.3.1 → 0.5.0

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.
Files changed (54) hide show
  1. package/README.md +188 -6
  2. package/dist/cjs/index.cjs +599 -0
  3. package/dist/esm/index.js +584 -0
  4. package/dist/files-api.d.ts +44 -0
  5. package/dist/files-api.d.ts.map +1 -0
  6. package/dist/impl/index.d.ts +6 -0
  7. package/dist/impl/index.d.ts.map +1 -0
  8. package/dist/impl/mem-files-api.d.ts +13 -0
  9. package/dist/impl/mem-files-api.d.ts.map +1 -0
  10. package/dist/impl/node-files-api.d.ts +24 -0
  11. package/dist/impl/node-files-api.d.ts.map +1 -0
  12. package/dist/index.d.ts +12 -0
  13. package/dist/index.d.ts.map +1 -0
  14. package/dist/types.d.ts +67 -0
  15. package/dist/types.d.ts.map +1 -0
  16. package/dist/utils/collect-stream.d.ts +16 -0
  17. package/dist/utils/collect-stream.d.ts.map +1 -0
  18. package/dist/utils/file-info-utils.d.ts +10 -0
  19. package/dist/utils/file-info-utils.d.ts.map +1 -0
  20. package/dist/utils/index.d.ts +8 -0
  21. package/dist/utils/index.d.ts.map +1 -0
  22. package/dist/utils/normalize-path.d.ts +21 -0
  23. package/dist/utils/normalize-path.d.ts.map +1 -0
  24. package/dist/utils/path-utils.d.ts +20 -0
  25. package/dist/utils/path-utils.d.ts.map +1 -0
  26. package/package.json +30 -31
  27. package/src/files-api.ts +168 -0
  28. package/src/impl/index.ts +6 -0
  29. package/src/impl/mem-files-api.ts +323 -0
  30. package/src/impl/node-files-api.ts +271 -0
  31. package/src/index.ts +36 -0
  32. package/src/types.ts +79 -0
  33. package/src/utils/collect-stream.ts +35 -0
  34. package/src/utils/file-info-utils.ts +15 -0
  35. package/src/utils/index.ts +8 -0
  36. package/src/utils/normalize-path.ts +34 -0
  37. package/src/utils/path-utils.ts +46 -0
  38. package/CHANGELOG.md +0 -2
  39. package/dist/index-umd.js +0 -1054
  40. package/dist/index-umd.min.js +0 -2
  41. package/dist/index.js +0 -1033
  42. package/dist/index.min.js +0 -2
  43. package/index.js +0 -1
  44. package/src/BrowserFilesApi.js +0 -335
  45. package/src/FilesApi.js +0 -133
  46. package/src/MemFilesApi.js +0 -129
  47. package/src/NodeFilesApi.js +0 -222
  48. package/src/addFilesApiLogger.js +0 -25
  49. package/src/getMimeType.js +0 -19
  50. package/src/index.js +0 -10
  51. package/src/mimeTypes.js +0 -96
  52. package/src/normalizePath.js +0 -8
  53. package/src/notImplemented.js +0 -3
  54. package/src/openBrowserFilesApi.js +0 -67
package/README.md CHANGED
@@ -1,17 +1,199 @@
1
+ # @statewalker/webrun-files
1
2
 
2
- # @statewalker/files
3
+ The core filesystem API for cross-platform file operations. This package provides a clean, minimal interface for reading, writing, and managing files that works consistently whether you're running in Node.js or need an in-memory implementation for browsers and testing.
3
4
 
4
- Minimalistic cross-plateform files API implementation.
5
+ ## Installation
5
6
 
6
- ## Usage
7
+ ```bash
8
+ npm install @statewalker/webrun-files
9
+ # or
10
+ pnpm add @statewalker/webrun-files
11
+ ```
12
+
13
+ ## Quick Start
14
+
15
+ The fastest way to get going is to create a `FilesApi` instance with one of the built-in backends. Here's an example using the in-memory implementation:
16
+
17
+ ```typescript
18
+ import { FilesApi, MemFilesApi } from '@statewalker/webrun-files';
19
+
20
+ const files = new FilesApi(new MemFilesApi());
21
+
22
+ // Write a file
23
+ await files.write('/documents/notes.txt', [
24
+ new TextEncoder().encode('Remember to water the plants')
25
+ ]);
26
+
27
+ // Read it back
28
+ const content = await files.readFile('/documents/notes.txt');
29
+ console.log(new TextDecoder().decode(content));
30
+ ```
31
+
32
+ For Node.js applications that need to work with the actual filesystem, switch to `NodeFilesApi`:
33
+
34
+ ```typescript
35
+ import { FilesApi, NodeFilesApi } from '@statewalker/webrun-files';
36
+
37
+ const files = new FilesApi(new NodeFilesApi('/path/to/root'));
38
+ ```
39
+
40
+ The `NodeFilesApi` constructor accepts an optional root directory path. When provided, all file operations will be relative to this directory, effectively sandboxing the API.
41
+
42
+ ## Working with Files
43
+
44
+ The `FilesApi` class provides everything you need for common file operations. Writing content is straightforward—just pass an array of `Uint8Array` chunks:
7
45
 
8
- ```js
46
+ ```typescript
47
+ const text = new TextEncoder().encode('Hello, World!');
48
+ await files.write('/greeting.txt', [text]);
49
+ ```
50
+
51
+ Reading comes in two flavors. Use `readFile` when you want the entire contents as a single buffer:
52
+
53
+ ```typescript
54
+ const content = await files.readFile('/greeting.txt');
55
+ ```
9
56
 
57
+ For large files, `read` returns an async generator that yields chunks as they come in, keeping memory usage under control:
10
58
 
59
+ ```typescript
60
+ for await (const chunk of files.read('/large-file.bin')) {
61
+ process.stdout.write(chunk);
62
+ }
11
63
  ```
12
64
 
13
- ## Example
65
+ You can also read specific portions of a file by specifying start and end positions:
14
66
 
15
- ```js
67
+ ```typescript
68
+ for await (const chunk of files.read('/data.bin', { start: 100, end: 200 })) {
69
+ // Only bytes 100-199
70
+ }
71
+ ```
72
+
73
+ ## Managing Files and Directories
16
74
 
75
+ Checking whether a file or directory exists is simple:
76
+
77
+ ```typescript
78
+ if (await files.exists('/config.json')) {
79
+ // Load configuration
80
+ }
17
81
  ```
82
+
83
+ To get detailed information about a file, use `stats`:
84
+
85
+ ```typescript
86
+ const info = await files.stats('/photo.jpg');
87
+ if (info) {
88
+ console.log(`Size: ${info.size} bytes`);
89
+ console.log(`Modified: ${new Date(info.lastModified)}`);
90
+ console.log(`Type: ${info.kind}`); // "file" or "directory"
91
+ }
92
+ ```
93
+
94
+ Listing directory contents returns an async generator of file info objects:
95
+
96
+ ```typescript
97
+ for await (const entry of files.list('/documents')) {
98
+ console.log(`${entry.name} (${entry.kind})`);
99
+ }
100
+ ```
101
+
102
+ Pass `{ recursive: true }` to traverse subdirectories:
103
+
104
+ ```typescript
105
+ for await (const entry of files.list('/project', { recursive: true })) {
106
+ console.log(entry.path);
107
+ }
108
+ ```
109
+
110
+ Creating directories, copying, moving, and deleting all work as you'd expect:
111
+
112
+ ```typescript
113
+ await files.mkdir('/archive/2024');
114
+ await files.copy('/report.pdf', '/archive/2024/report.pdf');
115
+ await files.move('/temp/draft.txt', '/documents/final.txt');
116
+ await files.remove('/old-stuff'); // Recursively deletes directories
117
+ ```
118
+
119
+ ## Low-Level File Handle Operations
120
+
121
+ When you need fine-grained control over file operations, work directly with file handles. Opening a file gives you a handle that supports reading, writing, and appending at specific positions:
122
+
123
+ ```typescript
124
+ const handle = await files.open('/data.bin');
125
+
126
+ // Get the current file size
127
+ console.log(`File is ${handle.size} bytes`);
128
+
129
+ // Read a specific range
130
+ for await (const chunk of handle.createReadStream({ start: 0, end: 100 })) {
131
+ // First 100 bytes
132
+ }
133
+
134
+ // Write at a specific position
135
+ await handle.createWriteStream([newData], { start: 50 });
136
+
137
+ // Append to the end
138
+ await handle.appendFile([moreData]);
139
+
140
+ // Always close when done
141
+ await handle.close();
142
+ ```
143
+
144
+ ## Building Your Own Backend
145
+
146
+ The `IFilesApi` interface defines the contract that all backends must implement. At minimum, you need four methods:
147
+
148
+ ```typescript
149
+ interface IFilesApi {
150
+ list(file: FileRef, options?: ListOptions): AsyncGenerator<FileInfo>;
151
+ stats(file: FileRef): Promise<FileInfo | undefined>;
152
+ remove(file: FileRef): Promise<boolean>;
153
+ open(file: FileRef): Promise<FileHandle>;
154
+ }
155
+ ```
156
+
157
+ The `FilesApi` wrapper class builds convenience methods like `read`, `write`, `copy`, and `move` on top of these primitives. Backends can optionally implement native versions of `move`, `copy`, and `mkdir` for better performance.
158
+
159
+ Take a look at `MemFilesApi` or `NodeFilesApi` in the source code for reference implementations.
160
+
161
+ ## Type Reference
162
+
163
+ The package exports all the TypeScript types you'll need:
164
+
165
+ ```typescript
166
+ import type {
167
+ IFilesApi, // Core interface for backends
168
+ FilesApi, // Wrapper class with convenience methods
169
+ FileInfo, // Metadata returned by stats() and list()
170
+ FileHandle, // Low-level file operations
171
+ FileRef, // string | { path: string }
172
+ FileKind, // "file" | "directory"
173
+ BinaryStream, // AsyncIterable<Uint8Array> | Iterable<Uint8Array>
174
+ ListOptions, // { recursive?: boolean }
175
+ CopyOptions, // { recursive?: boolean }
176
+ ReadStreamOptions, // { start?: number, end?: number, signal?: AbortSignal }
177
+ WriteStreamOptions, // { start?: number, signal?: AbortSignal }
178
+ } from '@statewalker/webrun-files';
179
+ ```
180
+
181
+ ## Utility Functions
182
+
183
+ The package includes helpful utilities for working with paths and streams:
184
+
185
+ ```typescript
186
+ import {
187
+ normalizePath, // Clean up path strings
188
+ resolveFileRef, // Convert FileRef to normalized path
189
+ joinPath, // Join path segments
190
+ dirname, // Get directory portion of path
191
+ basename, // Get filename portion
192
+ extname, // Get file extension
193
+ collectGenerator, // Collect async iterable into array
194
+ } from '@statewalker/webrun-files';
195
+ ```
196
+
197
+ ## License
198
+
199
+ MIT