@statewalker/webrun-files 0.5.0 → 0.9.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 (42) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +131 -114
  3. package/dist/cjs/index.cjs +85 -529
  4. package/dist/esm/index.js +78 -519
  5. package/dist/file-utils.d.ts +47 -0
  6. package/dist/file-utils.d.ts.map +1 -0
  7. package/dist/index.d.ts +14 -8
  8. package/dist/index.d.ts.map +1 -1
  9. package/dist/{utils/path-utils.d.ts → path-utils.d.ts} +10 -1
  10. package/dist/path-utils.d.ts.map +1 -0
  11. package/dist/types.d.ts +130 -51
  12. package/dist/types.d.ts.map +1 -1
  13. package/package.json +7 -10
  14. package/src/file-utils.ts +106 -0
  15. package/src/index.ts +38 -27
  16. package/src/{utils/path-utils.ts → path-utils.ts} +16 -2
  17. package/src/types.ts +136 -53
  18. package/dist/files-api.d.ts +0 -44
  19. package/dist/files-api.d.ts.map +0 -1
  20. package/dist/impl/index.d.ts +0 -6
  21. package/dist/impl/index.d.ts.map +0 -1
  22. package/dist/impl/mem-files-api.d.ts +0 -13
  23. package/dist/impl/mem-files-api.d.ts.map +0 -1
  24. package/dist/impl/node-files-api.d.ts +0 -24
  25. package/dist/impl/node-files-api.d.ts.map +0 -1
  26. package/dist/utils/collect-stream.d.ts +0 -16
  27. package/dist/utils/collect-stream.d.ts.map +0 -1
  28. package/dist/utils/file-info-utils.d.ts +0 -10
  29. package/dist/utils/file-info-utils.d.ts.map +0 -1
  30. package/dist/utils/index.d.ts +0 -8
  31. package/dist/utils/index.d.ts.map +0 -1
  32. package/dist/utils/normalize-path.d.ts +0 -21
  33. package/dist/utils/normalize-path.d.ts.map +0 -1
  34. package/dist/utils/path-utils.d.ts.map +0 -1
  35. package/src/files-api.ts +0 -168
  36. package/src/impl/index.ts +0 -6
  37. package/src/impl/mem-files-api.ts +0 -323
  38. package/src/impl/node-files-api.ts +0 -271
  39. package/src/utils/collect-stream.ts +0 -35
  40. package/src/utils/file-info-utils.ts +0 -15
  41. package/src/utils/index.ts +0 -8
  42. package/src/utils/normalize-path.ts +0 -34
package/src/types.ts CHANGED
@@ -1,79 +1,162 @@
1
1
  /**
2
- * Type definitions for IFilesApi
2
+ * Core types for FilesApi abstraction
3
3
  */
4
4
 
5
5
  export type FileKind = "file" | "directory";
6
6
 
7
- export interface FileInfo {
8
- kind: FileKind;
9
- name: string;
10
- path: string;
11
- type?: string;
12
- size?: number;
13
- lastModified: number;
7
+ /**
8
+ * Options for reading file content with range support.
9
+ *
10
+ * @example
11
+ * // Read 100 bytes starting at position 50
12
+ * api.read("/file.bin", { start: 50, length: 100 })
13
+ *
14
+ * @example
15
+ * // Read from position 1000 to end of file
16
+ * api.read("/file.bin", { start: 1000 })
17
+ */
18
+ export interface ReadOptions {
19
+ /** Starting byte position (0-indexed). Defaults to 0. */
20
+ start?: number;
21
+ /** Number of bytes to read. If omitted, reads to end of file. */
22
+ length?: number;
23
+ /** AbortSignal for cancellation support. */
24
+ signal?: AbortSignal;
14
25
  }
15
26
 
16
- export type FileRef = string | { path: string };
17
-
27
+ /**
28
+ * Options for listing directory contents.
29
+ */
18
30
  export interface ListOptions {
31
+ /** If true, lists all descendants recursively. Defaults to false. */
19
32
  recursive?: boolean;
20
33
  }
21
34
 
22
- export interface CopyOptions {
23
- recursive?: boolean;
35
+ /**
36
+ * Metadata of a regular file.
37
+ *
38
+ * `size` and `lastModified` are REQUIRED. Every storage that can hold a file
39
+ * can say how large it is and when it last changed; an implementation that
40
+ * cannot is claiming less than it must, and the omission must surface as a
41
+ * failure rather than as an `undefined` a consumer has to defend against.
42
+ */
43
+ export interface FileEntryStats {
44
+ kind: "file";
45
+ /** Length in bytes. A zero-byte file is `0`, never `undefined`. */
46
+ size: number;
47
+ /** Modification time as milliseconds since the epoch. */
48
+ lastModified: number;
24
49
  }
25
50
 
26
- export interface AppendOptions {
27
- signal?: AbortSignal;
51
+ /**
52
+ * Metadata of a directory.
53
+ *
54
+ * Deliberately carries nothing else. A directory has no size, and a
55
+ * modification time is available on some storages (memory, a local
56
+ * filesystem) and unavailable on others (an object store, where a directory
57
+ * is a common prefix that exists only as an artefact of key naming). Neither
58
+ * value may be relied upon, so neither is part of the contract: an
59
+ * implementation that happens to know one drops it here instead of leaking a
60
+ * value consumers would have to treat as optional anyway.
61
+ */
62
+ export interface DirectoryEntryStats {
63
+ kind: "directory";
28
64
  }
29
65
 
30
- export interface ReadStreamOptions {
31
- start?: number;
32
- end?: number;
33
- signal?: AbortSignal;
34
- }
66
+ /**
67
+ * File or directory metadata returned by `stats()`.
68
+ *
69
+ * A DISCRIMINATED UNION on `kind`, not a single shape with optional fields.
70
+ * The optionality this replaces never expressed what a given implementation
71
+ * could report — it expressed a property of the entry kind, collapsed into
72
+ * one type because `kind` was an ordinary field. Narrow on `kind` and the
73
+ * fields that exist for that kind are then known to be present:
74
+ *
75
+ * @example
76
+ * const stats = await api.stats("/some/path");
77
+ * if (stats?.kind === "file") {
78
+ * console.log(stats.size, stats.lastModified); // both `number`
79
+ * }
80
+ */
81
+ export type FileStats = FileEntryStats | DirectoryEntryStats;
35
82
 
36
- export interface WriteStreamOptions {
37
- start?: number;
38
- signal?: AbortSignal;
83
+ /** Name and path carried by every entry a `list()` yields. */
84
+ export interface FileEntryLocation {
85
+ name: string;
86
+ path: string;
39
87
  }
40
88
 
41
- export type BinaryStream = AsyncIterable<Uint8Array> | Iterable<Uint8Array>;
89
+ /** A file yielded by `list()`. */
90
+ export interface FileEntryInfo extends FileEntryStats, FileEntryLocation {}
42
91
 
43
- export interface FileHandle {
44
- readonly size: number;
45
- close(): Promise<void>;
92
+ /** A directory yielded by `list()`. */
93
+ export interface DirectoryEntryInfo extends DirectoryEntryStats, FileEntryLocation {}
46
94
 
47
- appendFile(data: BinaryStream, options?: AppendOptions): Promise<number>;
48
- createReadStream(options?: ReadStreamOptions): AsyncGenerator<Uint8Array>;
49
- createWriteStream(data: BinaryStream, options?: WriteStreamOptions): Promise<number>;
95
+ /**
96
+ * File or directory information returned by `list()`.
97
+ *
98
+ * The same union as {@link FileStats}, plus `name` and `path`, so a listing
99
+ * consumer narrows per entry exactly as a `stats()` consumer does.
100
+ */
101
+ export type FileInfo = FileEntryInfo | DirectoryEntryInfo;
50
102
 
103
+ /**
104
+ * Cross-platform filesystem abstraction interface.
105
+ *
106
+ * All paths are virtual paths using forward slashes and starting with "/".
107
+ * Implementations handle mapping to underlying storage.
108
+ */
109
+ export interface FilesApi {
51
110
  /**
52
- * Read bytes from the file at a specific position.
53
- *
54
- * @param buffer - The buffer to read bytes into
55
- * @param offset - The offset in the buffer to start writing at
56
- * @param length - The number of bytes to read
57
- * @param position - The position in the file to start reading from
58
- * @returns The number of bytes actually read (may be less than length at EOF)
111
+ * Read file content as an async iterable of chunks.
112
+ * Returns empty iterable for non-existent files.
59
113
  */
60
- read(buffer: Uint8Array, offset: number, length: number, position: number): Promise<number>;
114
+ read(path: string, options?: ReadOptions): AsyncIterable<Uint8Array>;
61
115
 
62
- chmod?(mode: number): Promise<void>;
63
- chown?(uid: number, gid: number): Promise<void>;
64
- }
116
+ /**
117
+ * Write content to a file, creating parent directories as needed.
118
+ * Overwrites existing file content.
119
+ */
120
+ write(path: string, content: Iterable<Uint8Array> | AsyncIterable<Uint8Array>): Promise<void>;
65
121
 
66
- /**
67
- * Core filesystem interface - minimal contract for implementations.
68
- * Platform-specific implementations should implement this interface.
69
- */
70
- export interface IFilesApi {
71
- list(file: FileRef, options?: ListOptions): AsyncGenerator<FileInfo>;
72
- stats(file: FileRef): Promise<FileInfo | undefined>;
73
- remove(file: FileRef): Promise<boolean>;
74
- open(file: FileRef): Promise<FileHandle>;
75
-
76
- move?(source: FileRef, target: FileRef): Promise<boolean>;
77
- copy?(source: FileRef, target: FileRef, options?: CopyOptions): Promise<boolean>;
78
- mkdir?(file: FileRef): Promise<void>;
122
+ /**
123
+ * Create a directory and all parent directories.
124
+ * No-op if directory already exists.
125
+ */
126
+ mkdir(path: string): Promise<void>;
127
+
128
+ /**
129
+ * List directory contents.
130
+ * Returns empty iterable for non-existent or non-directory paths.
131
+ */
132
+ list(path: string, options?: ListOptions): AsyncIterable<FileInfo>;
133
+
134
+ /**
135
+ * Get file or directory metadata.
136
+ * Returns undefined for non-existent paths.
137
+ */
138
+ stats(path: string): Promise<FileStats | undefined>;
139
+
140
+ /**
141
+ * Check if a path exists.
142
+ */
143
+ exists(path: string): Promise<boolean>;
144
+
145
+ /**
146
+ * Remove a file or directory (recursively).
147
+ * Returns true if something was removed, false if path didn't exist.
148
+ */
149
+ remove(path: string): Promise<boolean>;
150
+
151
+ /**
152
+ * Move/rename a file or directory.
153
+ * Returns true on success, false if source doesn't exist.
154
+ */
155
+ move(source: string, target: string): Promise<boolean>;
156
+
157
+ /**
158
+ * Copy a file or directory (recursively).
159
+ * Returns true on success, false if source doesn't exist.
160
+ */
161
+ copy(source: string, target: string): Promise<boolean>;
79
162
  }
@@ -1,44 +0,0 @@
1
- /**
2
- * FilesApi wrapper class providing convenience methods on top of IFilesApi
3
- */
4
- import type { BinaryStream, CopyOptions, FileHandle, FileInfo, FileRef, IFilesApi, ListOptions, ReadStreamOptions } from "./types.js";
5
- export declare class FilesApi implements IFilesApi {
6
- private fs;
7
- constructor(fs: IFilesApi);
8
- list(file: FileRef, options?: ListOptions): AsyncGenerator<FileInfo>;
9
- stats(file: FileRef): Promise<FileInfo | undefined>;
10
- remove(file: FileRef): Promise<boolean>;
11
- open(file: FileRef): Promise<FileHandle>;
12
- /**
13
- * Checks if a file or directory exists.
14
- */
15
- exists(file: FileRef): Promise<boolean>;
16
- /**
17
- * Reads file content as a stream.
18
- */
19
- read(file: FileRef, options?: ReadStreamOptions): AsyncGenerator<Uint8Array>;
20
- /**
21
- * Writes content to a file.
22
- */
23
- write(file: FileRef, content: BinaryStream): Promise<void>;
24
- /**
25
- * Reads entire file into a single buffer.
26
- */
27
- readFile(file: FileRef): Promise<Uint8Array>;
28
- /**
29
- * Copies file or directory.
30
- * Uses native implementation if available, otherwise falls back to read/write.
31
- */
32
- copy(source: FileRef, target: FileRef, options?: CopyOptions): Promise<boolean>;
33
- /**
34
- * Moves file or directory.
35
- * Uses native implementation if available, otherwise falls back to copy+delete.
36
- */
37
- move(source: FileRef, target: FileRef): Promise<boolean>;
38
- /**
39
- * Creates a directory.
40
- * Uses native implementation if available, otherwise creates a placeholder file.
41
- */
42
- mkdir(file: FileRef): Promise<void>;
43
- }
44
- //# sourceMappingURL=files-api.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"files-api.d.ts","sourceRoot":"","sources":["../src/files-api.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EACV,YAAY,EACZ,WAAW,EACX,UAAU,EACV,QAAQ,EACR,OAAO,EACP,SAAS,EACT,WAAW,EACX,iBAAiB,EAClB,MAAM,YAAY,CAAC;AAOpB,qBAAa,QAAS,YAAW,SAAS;IAC5B,OAAO,CAAC,EAAE;gBAAF,EAAE,EAAE,SAAS;IAMjC,IAAI,CAAC,IAAI,EAAE,OAAO,EAAE,OAAO,CAAC,EAAE,WAAW,GAAG,cAAc,CAAC,QAAQ,CAAC;IAIpE,KAAK,CAAC,IAAI,EAAE,OAAO,GAAG,OAAO,CAAC,QAAQ,GAAG,SAAS,CAAC;IAInD,MAAM,CAAC,IAAI,EAAE,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC;IAIvC,IAAI,CAAC,IAAI,EAAE,OAAO,GAAG,OAAO,CAAC,UAAU,CAAC;IAQxC;;OAEG;IACG,MAAM,CAAC,IAAI,EAAE,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC;IAK7C;;OAEG;IACI,IAAI,CAAC,IAAI,EAAE,OAAO,EAAE,OAAO,GAAE,iBAAsB,GAAG,cAAc,CAAC,UAAU,CAAC;IASvF;;OAEG;IACG,KAAK,CAAC,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC;IAShE;;OAEG;IACG,QAAQ,CAAC,IAAI,EAAE,OAAO,GAAG,OAAO,CAAC,UAAU,CAAC;IAqBlD;;;OAGG;IACG,IAAI,CAAC,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,GAAE,WAAgB,GAAG,OAAO,CAAC,OAAO,CAAC;IA4BzF;;;OAGG;IACG,IAAI,CAAC,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC;IAa9D;;;OAGG;IACG,KAAK,CAAC,IAAI,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC;CAW1C"}
@@ -1,6 +0,0 @@
1
- /**
2
- * IFilesApi implementations
3
- */
4
- export * from "./mem-files-api.js";
5
- export * from "./node-files-api.js";
6
- //# sourceMappingURL=index.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/impl/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,cAAc,oBAAoB,CAAC;AACnC,cAAc,qBAAqB,CAAC"}
@@ -1,13 +0,0 @@
1
- /**
2
- * In-memory implementation of IFilesApi for testing
3
- */
4
- import type { FileHandle, FileInfo, FileRef, IFilesApi, ListOptions } from "../types.js";
5
- export declare class MemFilesApi implements IFilesApi {
6
- private store;
7
- list(file: FileRef, options?: ListOptions): AsyncGenerator<FileInfo>;
8
- stats(file: FileRef): Promise<FileInfo | undefined>;
9
- remove(file: FileRef): Promise<boolean>;
10
- open(file: FileRef): Promise<FileHandle>;
11
- mkdir(file: FileRef): Promise<void>;
12
- }
13
- //# sourceMappingURL=mem-files-api.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"mem-files-api.d.ts","sourceRoot":"","sources":["../../src/impl/mem-files-api.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAGV,UAAU,EACV,QAAQ,EACR,OAAO,EACP,SAAS,EACT,WAAW,EAGZ,MAAM,aAAa,CAAC;AA8JrB,qBAAa,WAAY,YAAW,SAAS;IAC3C,OAAO,CAAC,KAAK,CAA4B;IAElC,IAAI,CAAC,IAAI,EAAE,OAAO,EAAE,OAAO,GAAE,WAAgB,GAAG,cAAc,CAAC,QAAQ,CAAC;IAqEzE,KAAK,CAAC,IAAI,EAAE,OAAO,GAAG,OAAO,CAAC,QAAQ,GAAG,SAAS,CAAC;IA0CnD,MAAM,CAAC,IAAI,EAAE,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC;IAsBvC,IAAI,CAAC,IAAI,EAAE,OAAO,GAAG,OAAO,CAAC,UAAU,CAAC;IAKxC,KAAK,CAAC,IAAI,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC;CAS1C"}
@@ -1,24 +0,0 @@
1
- /**
2
- * Node.js implementation of IFilesApi
3
- */
4
- import type * as NodeFS from "node:fs/promises";
5
- import type { CopyOptions, FileHandle, FileInfo, FileRef, IFilesApi, ListOptions } from "../types.js";
6
- interface NodeFilesApiOptions {
7
- fs: typeof NodeFS;
8
- rootDir?: string;
9
- }
10
- export declare class NodeFilesApi implements IFilesApi {
11
- private fs;
12
- private rootDir;
13
- constructor(options: NodeFilesApiOptions);
14
- private resolvePath;
15
- list(file: FileRef, options?: ListOptions): AsyncGenerator<FileInfo>;
16
- stats(file: FileRef): Promise<FileInfo | undefined>;
17
- remove(file: FileRef): Promise<boolean>;
18
- open(file: FileRef): Promise<FileHandle>;
19
- move(source: FileRef, target: FileRef): Promise<boolean>;
20
- copy(source: FileRef, target: FileRef, options?: CopyOptions): Promise<boolean>;
21
- mkdir(file: FileRef): Promise<void>;
22
- }
23
- export {};
24
- //# sourceMappingURL=node-files-api.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"node-files-api.d.ts","sourceRoot":"","sources":["../../src/impl/node-files-api.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,KAAK,MAAM,MAAM,kBAAkB,CAAC;AAEhD,OAAO,KAAK,EAGV,WAAW,EACX,UAAU,EACV,QAAQ,EACR,OAAO,EACP,SAAS,EACT,WAAW,EAGZ,MAAM,aAAa,CAAC;AAIrB,UAAU,mBAAmB;IAC3B,EAAE,EAAE,OAAO,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AA4GD,qBAAa,YAAa,YAAW,SAAS;IAC5C,OAAO,CAAC,EAAE,CAAgB;IAC1B,OAAO,CAAC,OAAO,CAAS;gBAEZ,OAAO,EAAE,mBAAmB;IAKxC,OAAO,CAAC,WAAW;IAKZ,IAAI,CAAC,IAAI,EAAE,OAAO,EAAE,OAAO,GAAE,WAAgB,GAAG,cAAc,CAAC,QAAQ,CAAC;IAsCzE,KAAK,CAAC,IAAI,EAAE,OAAO,GAAG,OAAO,CAAC,QAAQ,GAAG,SAAS,CAAC;IAkBnD,MAAM,CAAC,IAAI,EAAE,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC;IAgBvC,IAAI,CAAC,IAAI,EAAE,OAAO,GAAG,OAAO,CAAC,UAAU,CAAC;IAexC,IAAI,CAAC,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC;IAgBxD,IAAI,CAAC,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,GAAE,WAAgB,GAAG,OAAO,CAAC,OAAO,CAAC;IAiBnF,KAAK,CAAC,IAAI,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC;CAI1C"}
@@ -1,16 +0,0 @@
1
- /**
2
- * Stream collection utilities
3
- */
4
- /**
5
- * Collects all values from an async generator into an array.
6
- */
7
- export declare function collectGenerator<T>(generator: AsyncIterable<T>): Promise<T[]>;
8
- /**
9
- * Converts a synchronous iterable to an async iterable.
10
- */
11
- export declare function toAsyncIterable<T>(iterable: Iterable<T>): AsyncIterable<T>;
12
- /**
13
- * Normalizes BinaryStream to AsyncIterable<Uint8Array>.
14
- */
15
- export declare function toBinaryAsyncIterable(data: AsyncIterable<Uint8Array> | Iterable<Uint8Array>): AsyncIterable<Uint8Array>;
16
- //# sourceMappingURL=collect-stream.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"collect-stream.d.ts","sourceRoot":"","sources":["../../src/utils/collect-stream.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH;;GAEG;AACH,wBAAsB,gBAAgB,CAAC,CAAC,EAAE,SAAS,EAAE,aAAa,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,EAAE,CAAC,CAMnF;AAED;;GAEG;AACH,wBAAuB,eAAe,CAAC,CAAC,EAAE,QAAQ,EAAE,QAAQ,CAAC,CAAC,CAAC,GAAG,aAAa,CAAC,CAAC,CAAC,CAIjF;AAED;;GAEG;AACH,wBAAgB,qBAAqB,CACnC,IAAI,EAAE,aAAa,CAAC,UAAU,CAAC,GAAG,QAAQ,CAAC,UAAU,CAAC,GACrD,aAAa,CAAC,UAAU,CAAC,CAK3B"}
@@ -1,10 +0,0 @@
1
- import type { FileInfo } from "../types.js";
2
- /**
3
- * Check if FileInfo represents a directory
4
- */
5
- export declare function isDirectory(info: FileInfo | undefined): boolean;
6
- /**
7
- * Check if FileInfo represents a file
8
- */
9
- export declare function isFile(info: FileInfo | undefined): boolean;
10
- //# sourceMappingURL=file-info-utils.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"file-info-utils.d.ts","sourceRoot":"","sources":["../../src/utils/file-info-utils.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAE5C;;GAEG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,QAAQ,GAAG,SAAS,GAAG,OAAO,CAE/D;AAED;;GAEG;AACH,wBAAgB,MAAM,CAAC,IAAI,EAAE,QAAQ,GAAG,SAAS,GAAG,OAAO,CAE1D"}
@@ -1,8 +0,0 @@
1
- /**
2
- * Utility functions
3
- */
4
- export * from "./collect-stream.js";
5
- export * from "./file-info-utils.js";
6
- export * from "./normalize-path.js";
7
- export * from "./path-utils.js";
8
- //# sourceMappingURL=index.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/utils/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,cAAc,qBAAqB,CAAC;AACpC,cAAc,sBAAsB,CAAC;AACrC,cAAc,qBAAqB,CAAC;AACpC,cAAc,iBAAiB,CAAC"}
@@ -1,21 +0,0 @@
1
- /**
2
- * Path normalization utilities
3
- */
4
- import type { FileRef } from "../types.js";
5
- /**
6
- * Normalizes a file path to a consistent format.
7
- * - Adds leading slash if missing
8
- * - Removes trailing slash
9
- * - Removes `.` segments
10
- * - Collapses multiple slashes
11
- */
12
- export declare function normalizePath(filePath: string): string;
13
- /**
14
- * Extracts path string from FileRef.
15
- */
16
- export declare function toPath(file: FileRef): string;
17
- /**
18
- * Normalizes FileRef to a path string.
19
- */
20
- export declare function resolveFileRef(file: FileRef): string;
21
- //# sourceMappingURL=normalize-path.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"normalize-path.d.ts","sourceRoot":"","sources":["../../src/utils/normalize-path.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAE3C;;;;;;GAMG;AACH,wBAAgB,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAMtD;AAED;;GAEG;AACH,wBAAgB,MAAM,CAAC,IAAI,EAAE,OAAO,GAAG,MAAM,CAE5C;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,OAAO,GAAG,MAAM,CAEpD"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"path-utils.d.ts","sourceRoot":"","sources":["../../src/utils/path-utils.ts"],"names":[],"mappings":"AAAA;;GAEG;AAIH;;GAEG;AACH,wBAAgB,QAAQ,CAAC,GAAG,QAAQ,EAAE,MAAM,EAAE,GAAG,MAAM,CAGtD;AAED;;GAEG;AACH,wBAAgB,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAK5C;AAED;;GAEG;AACH,wBAAgB,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,MAAM,GAAG,MAAM,CAQ3D;AAED;;GAEG;AACH,wBAAgB,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAK5C"}
package/src/files-api.ts DELETED
@@ -1,168 +0,0 @@
1
- /**
2
- * FilesApi wrapper class providing convenience methods on top of IFilesApi
3
- */
4
-
5
- import type {
6
- BinaryStream,
7
- CopyOptions,
8
- FileHandle,
9
- FileInfo,
10
- FileRef,
11
- IFilesApi,
12
- ListOptions,
13
- ReadStreamOptions,
14
- } from "./types.js";
15
- import { toBinaryAsyncIterable } from "./utils/collect-stream.js";
16
- import { resolveFileRef } from "./utils/index.js";
17
- import { joinPath } from "./utils/path-utils.js";
18
-
19
- const IGNORE_FILE = ".ignore";
20
-
21
- export class FilesApi implements IFilesApi {
22
- constructor(private fs: IFilesApi) {}
23
-
24
- // ========================================
25
- // IFilesApi delegation
26
- // ========================================
27
-
28
- list(file: FileRef, options?: ListOptions): AsyncGenerator<FileInfo> {
29
- return this.fs.list(file, options);
30
- }
31
-
32
- stats(file: FileRef): Promise<FileInfo | undefined> {
33
- return this.fs.stats(file);
34
- }
35
-
36
- remove(file: FileRef): Promise<boolean> {
37
- return this.fs.remove(file);
38
- }
39
-
40
- open(file: FileRef): Promise<FileHandle> {
41
- return this.fs.open(file);
42
- }
43
-
44
- // ========================================
45
- // Convenience methods built on core API
46
- // ========================================
47
-
48
- /**
49
- * Checks if a file or directory exists.
50
- */
51
- async exists(file: FileRef): Promise<boolean> {
52
- const info = await this.stats(file);
53
- return info !== undefined;
54
- }
55
-
56
- /**
57
- * Reads file content as a stream.
58
- */
59
- async *read(file: FileRef, options: ReadStreamOptions = {}): AsyncGenerator<Uint8Array> {
60
- const handle = await this.open(file);
61
- try {
62
- yield* handle.createReadStream(options);
63
- } finally {
64
- await handle.close();
65
- }
66
- }
67
-
68
- /**
69
- * Writes content to a file.
70
- */
71
- async write(file: FileRef, content: BinaryStream): Promise<void> {
72
- const handle = await this.open(file);
73
- try {
74
- await handle.createWriteStream(toBinaryAsyncIterable(content));
75
- } finally {
76
- await handle.close();
77
- }
78
- }
79
-
80
- /**
81
- * Reads entire file into a single buffer.
82
- */
83
- async readFile(file: FileRef): Promise<Uint8Array> {
84
- const chunks: Uint8Array[] = [];
85
- let totalLength = 0;
86
-
87
- for await (const chunk of this.read(file)) {
88
- chunks.push(chunk);
89
- totalLength += chunk.length;
90
- }
91
-
92
- if (chunks.length === 0) return new Uint8Array(0);
93
- if (chunks.length === 1) return chunks[0];
94
-
95
- const result = new Uint8Array(totalLength);
96
- let offset = 0;
97
- for (const chunk of chunks) {
98
- result.set(chunk, offset);
99
- offset += chunk.length;
100
- }
101
- return result;
102
- }
103
-
104
- /**
105
- * Copies file or directory.
106
- * Uses native implementation if available, otherwise falls back to read/write.
107
- */
108
- async copy(source: FileRef, target: FileRef, options: CopyOptions = {}): Promise<boolean> {
109
- // Try native implementation first
110
- if (this.fs.copy) {
111
- return this.fs.copy(source, target, options);
112
- }
113
-
114
- // Fallback: read from source, write to target
115
- const sourceInfo = await this.stats(source);
116
- if (!sourceInfo) return false;
117
-
118
- const sourcePath = resolveFileRef(source);
119
- const targetPath = resolveFileRef(target);
120
- const recursive = options.recursive ?? true;
121
-
122
- if (sourceInfo.kind === "directory") {
123
- for await (const entry of this.list(source, { recursive })) {
124
- if (entry.kind === "directory") continue;
125
- const suffix = entry.path.substring(sourcePath.length);
126
- const newTargetPath = targetPath + suffix;
127
- await this.write(newTargetPath, this.read(entry.path));
128
- }
129
- } else {
130
- await this.write(targetPath, this.read(sourcePath));
131
- }
132
-
133
- return true;
134
- }
135
-
136
- /**
137
- * Moves file or directory.
138
- * Uses native implementation if available, otherwise falls back to copy+delete.
139
- */
140
- async move(source: FileRef, target: FileRef): Promise<boolean> {
141
- // Try native implementation first
142
- if (this.fs.move) {
143
- return this.fs.move(source, target);
144
- }
145
-
146
- // Fallback: copy then delete
147
- const copied = await this.copy(source, target);
148
- if (!copied) return false;
149
- await this.remove(source);
150
- return true;
151
- }
152
-
153
- /**
154
- * Creates a directory.
155
- * Uses native implementation if available, otherwise creates a placeholder file.
156
- */
157
- async mkdir(file: FileRef): Promise<void> {
158
- // Try native implementation first
159
- if (this.fs.mkdir) {
160
- return this.fs.mkdir(file);
161
- }
162
-
163
- // Fallback: create a placeholder file to establish the directory
164
- const dirPath = resolveFileRef(file);
165
- const placeholderPath = joinPath(dirPath, IGNORE_FILE);
166
- await this.write(placeholderPath, [new Uint8Array(0)]);
167
- }
168
- }
package/src/impl/index.ts DELETED
@@ -1,6 +0,0 @@
1
- /**
2
- * IFilesApi implementations
3
- */
4
-
5
- export * from "./mem-files-api.js";
6
- export * from "./node-files-api.js";