@b9g/filesystem 0.1.7 → 0.1.9
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 +8 -8
- package/package.json +12 -7
- package/src/bun-s3.d.ts +6 -6
- package/src/bun-s3.js +3 -3
- package/src/index.d.ts +33 -38
- package/src/index.js +48 -34
- package/src/memory.d.ts +7 -7
- package/src/memory.js +27 -3
- package/src/node-fs.d.ts +45 -0
- package/src/{node.js → node-fs.js} +22 -12
- package/src/node.d.ts +0 -37
package/README.md
CHANGED
|
@@ -251,28 +251,28 @@ router.post('/upload', async (request) => {
|
|
|
251
251
|
- `ShovelFileHandle` - FileSystemFileHandle implementation
|
|
252
252
|
- `ShovelDirectoryHandle` - FileSystemDirectoryHandle implementation
|
|
253
253
|
- `ShovelHandle` - Base handle class
|
|
254
|
-
- `
|
|
254
|
+
- `CustomDirectoryStorage` - Directory storage with custom backend factories
|
|
255
255
|
|
|
256
256
|
### Types
|
|
257
257
|
|
|
258
|
-
- `
|
|
259
|
-
- `
|
|
260
|
-
- `
|
|
258
|
+
- `Directory` - Alias for FileSystemDirectoryHandle
|
|
259
|
+
- `DirectoryStorage` - Interface for directory storage (`open(name): Promise<FileSystemDirectoryHandle>`)
|
|
260
|
+
- `DirectoryFactory` - Factory function type for creating directory backends
|
|
261
261
|
- `FileSystemConfig` - Configuration for filesystem backends
|
|
262
262
|
- `FileSystemPermissionDescriptor` - Permission descriptor type
|
|
263
263
|
- `FileSystemBackend` - Backend interface for filesystem implementations
|
|
264
264
|
|
|
265
265
|
## API Reference
|
|
266
266
|
|
|
267
|
-
###
|
|
267
|
+
### DirectoryStorage
|
|
268
268
|
|
|
269
269
|
```typescript
|
|
270
|
-
interface
|
|
270
|
+
interface DirectoryStorage {
|
|
271
271
|
open(name: string): Promise<FileSystemDirectoryHandle>;
|
|
272
272
|
}
|
|
273
273
|
|
|
274
|
-
class
|
|
275
|
-
register(name: string, factory:
|
|
274
|
+
class CustomDirectoryStorage implements DirectoryStorage {
|
|
275
|
+
register(name: string, factory: DirectoryFactory): void;
|
|
276
276
|
open(name: string): Promise<FileSystemDirectoryHandle>;
|
|
277
277
|
}
|
|
278
278
|
```
|
package/package.json
CHANGED
|
@@ -1,8 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@b9g/filesystem",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.9",
|
|
4
4
|
"description": "Universal File System Access API implementations for all platforms",
|
|
5
5
|
"license": "MIT",
|
|
6
|
+
"repository": {
|
|
7
|
+
"type": "git",
|
|
8
|
+
"url": "https://github.com/bikeshaving/shovel.git",
|
|
9
|
+
"directory": "packages/filesystem"
|
|
10
|
+
},
|
|
6
11
|
"dependencies": {
|
|
7
12
|
"mime": "^4.0.4"
|
|
8
13
|
},
|
|
@@ -50,13 +55,13 @@
|
|
|
50
55
|
"types": "./src/memory.d.ts",
|
|
51
56
|
"import": "./src/memory.js"
|
|
52
57
|
},
|
|
53
|
-
"./node": {
|
|
54
|
-
"types": "./src/node.d.ts",
|
|
55
|
-
"import": "./src/node.js"
|
|
58
|
+
"./node-fs": {
|
|
59
|
+
"types": "./src/node-fs.d.ts",
|
|
60
|
+
"import": "./src/node-fs.js"
|
|
56
61
|
},
|
|
57
|
-
"./node.js": {
|
|
58
|
-
"types": "./src/node.d.ts",
|
|
59
|
-
"import": "./src/node.js"
|
|
62
|
+
"./node-fs.js": {
|
|
63
|
+
"types": "./src/node-fs.d.ts",
|
|
64
|
+
"import": "./src/node-fs.js"
|
|
60
65
|
},
|
|
61
66
|
"./package.json": "./package.json"
|
|
62
67
|
}
|
package/src/bun-s3.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Bun S3 filesystem implementation
|
|
3
3
|
*
|
|
4
|
-
* Provides
|
|
4
|
+
* Provides S3Directory (root) and S3FileSystemBackend for storage operations
|
|
5
5
|
* using Bun's native S3 client.
|
|
6
6
|
*/
|
|
7
7
|
import { type FileSystemBackend } from "./index.js";
|
|
@@ -27,16 +27,16 @@ export declare class S3FileSystemBackend implements FileSystemBackend {
|
|
|
27
27
|
remove(path: string, recursive?: boolean): Promise<void>;
|
|
28
28
|
}
|
|
29
29
|
/**
|
|
30
|
-
* S3
|
|
30
|
+
* S3 directory - root entry point for S3 filesystem using Bun's S3 client
|
|
31
31
|
* Implements FileSystemDirectoryHandle for S3 object storage
|
|
32
32
|
*
|
|
33
33
|
* Example usage with namespacing:
|
|
34
34
|
* ```typescript
|
|
35
35
|
* const s3 = new S3Client({ ... });
|
|
36
36
|
*
|
|
37
|
-
* // Use in
|
|
38
|
-
* const
|
|
39
|
-
* return new
|
|
37
|
+
* // Use in CustomDirectoryStorage factory for multi-tenancy
|
|
38
|
+
* const directories = new CustomDirectoryStorage(async (name) => {
|
|
39
|
+
* return new S3Directory(
|
|
40
40
|
* s3,
|
|
41
41
|
* "my-company-bucket",
|
|
42
42
|
* `my-app/production/${name}` // Prefix for isolation
|
|
@@ -44,7 +44,7 @@ export declare class S3FileSystemBackend implements FileSystemBackend {
|
|
|
44
44
|
* });
|
|
45
45
|
* ```
|
|
46
46
|
*/
|
|
47
|
-
export declare class
|
|
47
|
+
export declare class S3Directory implements FileSystemDirectoryHandle {
|
|
48
48
|
#private;
|
|
49
49
|
readonly kind: "directory";
|
|
50
50
|
readonly name: string;
|
package/src/bun-s3.js
CHANGED
|
@@ -179,7 +179,7 @@ var S3FileSystemBackend = class {
|
|
|
179
179
|
return this.#prefix ? `${this.#prefix}/${cleanPath}` : cleanPath;
|
|
180
180
|
}
|
|
181
181
|
};
|
|
182
|
-
var
|
|
182
|
+
var S3Directory = class _S3Directory {
|
|
183
183
|
kind;
|
|
184
184
|
name;
|
|
185
185
|
#backend;
|
|
@@ -259,7 +259,7 @@ var S3Bucket = class _S3Bucket {
|
|
|
259
259
|
async isSameEntry(other) {
|
|
260
260
|
if (other.kind !== "directory")
|
|
261
261
|
return false;
|
|
262
|
-
return other instanceof
|
|
262
|
+
return other instanceof _S3Directory && other.name === this.name;
|
|
263
263
|
}
|
|
264
264
|
async queryPermission() {
|
|
265
265
|
return "granted";
|
|
@@ -269,6 +269,6 @@ var S3Bucket = class _S3Bucket {
|
|
|
269
269
|
}
|
|
270
270
|
};
|
|
271
271
|
export {
|
|
272
|
-
|
|
272
|
+
S3Directory,
|
|
273
273
|
S3FileSystemBackend
|
|
274
274
|
};
|
package/src/index.d.ts
CHANGED
|
@@ -7,11 +7,6 @@ export interface FileSystemConfig {
|
|
|
7
7
|
/** Platform-specific configuration */
|
|
8
8
|
[key: string]: any;
|
|
9
9
|
}
|
|
10
|
-
/**
|
|
11
|
-
* Bucket is a semantic alias for FileSystemDirectoryHandle
|
|
12
|
-
* Represents a named storage bucket that provides direct filesystem access
|
|
13
|
-
*/
|
|
14
|
-
export type Bucket = FileSystemDirectoryHandle;
|
|
15
10
|
/**
|
|
16
11
|
* Permission descriptor for File System Access API
|
|
17
12
|
*/
|
|
@@ -84,11 +79,12 @@ export declare abstract class ShovelHandle implements FileSystemHandle {
|
|
|
84
79
|
get name(): string;
|
|
85
80
|
get backend(): FileSystemBackend;
|
|
86
81
|
isSameEntry(other: FileSystemHandle): Promise<boolean>;
|
|
87
|
-
queryPermission(
|
|
88
|
-
requestPermission(
|
|
82
|
+
queryPermission(_descriptor?: FileSystemPermissionDescriptor): Promise<PermissionState>;
|
|
83
|
+
requestPermission(_descriptor?: FileSystemPermissionDescriptor): Promise<PermissionState>;
|
|
89
84
|
/**
|
|
90
85
|
* Validates that a name is actually a name and not a path
|
|
91
86
|
* The File System Access API only accepts names, not paths
|
|
87
|
+
* WPT expects TypeError for invalid names
|
|
92
88
|
*/
|
|
93
89
|
validateName(name: string): void;
|
|
94
90
|
}
|
|
@@ -134,82 +130,81 @@ export declare class ShovelDirectoryHandle extends ShovelHandle implements FileS
|
|
|
134
130
|
]>;
|
|
135
131
|
}
|
|
136
132
|
/**
|
|
137
|
-
*
|
|
138
|
-
* This could become a future web standard
|
|
133
|
+
* Directory storage interface - parallels CacheStorage for filesystem access
|
|
139
134
|
*/
|
|
140
|
-
export interface
|
|
135
|
+
export interface DirectoryStorage {
|
|
141
136
|
/**
|
|
142
|
-
* Open a named
|
|
137
|
+
* Open a named directory - returns FileSystemDirectoryHandle (root)
|
|
143
138
|
* Well-known names: 'static', 'tmp'
|
|
144
139
|
*/
|
|
145
140
|
open(name: string): Promise<FileSystemDirectoryHandle>;
|
|
146
141
|
/**
|
|
147
|
-
* Check if a named
|
|
142
|
+
* Check if a named directory exists
|
|
148
143
|
*/
|
|
149
144
|
has(name: string): Promise<boolean>;
|
|
150
145
|
/**
|
|
151
|
-
* Delete a named
|
|
146
|
+
* Delete a named directory and all its contents
|
|
152
147
|
*/
|
|
153
148
|
delete(name: string): Promise<boolean>;
|
|
154
149
|
/**
|
|
155
|
-
* List all available
|
|
150
|
+
* List all available directory names
|
|
156
151
|
*/
|
|
157
152
|
keys(): Promise<string[]>;
|
|
158
153
|
}
|
|
159
154
|
/**
|
|
160
|
-
* Factory function type for creating
|
|
161
|
-
* @param name
|
|
162
|
-
* @returns FileSystemDirectoryHandle
|
|
155
|
+
* Factory function type for creating directories
|
|
156
|
+
* @param name Directory name to create
|
|
157
|
+
* @returns FileSystemDirectoryHandle instance
|
|
163
158
|
*/
|
|
164
|
-
export type
|
|
159
|
+
export type DirectoryFactory = (name: string) => FileSystemDirectoryHandle | Promise<FileSystemDirectoryHandle>;
|
|
165
160
|
/**
|
|
166
|
-
* Custom
|
|
161
|
+
* Custom directory storage with factory-based directory creation
|
|
167
162
|
*
|
|
168
|
-
* Provides a registry of named
|
|
169
|
-
* with lazy instantiation and singleton behavior per
|
|
163
|
+
* Provides a registry of named directories (FileSystemDirectoryHandle instances)
|
|
164
|
+
* with lazy instantiation and singleton behavior per directory name.
|
|
170
165
|
*
|
|
171
166
|
* Mirrors the CustomCacheStorage pattern for consistency across the platform.
|
|
172
167
|
*/
|
|
173
|
-
export declare class
|
|
168
|
+
export declare class CustomDirectoryStorage {
|
|
174
169
|
#private;
|
|
175
170
|
/**
|
|
176
|
-
* @param factory Function that creates
|
|
171
|
+
* @param factory Function that creates directory instances by name
|
|
177
172
|
*/
|
|
178
|
-
constructor(factory:
|
|
173
|
+
constructor(factory: DirectoryFactory);
|
|
179
174
|
/**
|
|
180
|
-
* Open a named
|
|
175
|
+
* Open a named directory - creates if it doesn't exist
|
|
181
176
|
*
|
|
182
|
-
* @param name
|
|
183
|
-
* @returns FileSystemDirectoryHandle for the
|
|
177
|
+
* @param name Directory name (e.g., 'tmp', 'dist', 'uploads')
|
|
178
|
+
* @returns FileSystemDirectoryHandle for the directory
|
|
184
179
|
*/
|
|
185
180
|
open(name: string): Promise<FileSystemDirectoryHandle>;
|
|
186
181
|
/**
|
|
187
|
-
* Check if a named
|
|
182
|
+
* Check if a named directory exists
|
|
188
183
|
*
|
|
189
|
-
* @param name
|
|
190
|
-
* @returns true if
|
|
184
|
+
* @param name Directory name to check
|
|
185
|
+
* @returns true if directory has been opened
|
|
191
186
|
*/
|
|
192
187
|
has(name: string): Promise<boolean>;
|
|
193
188
|
/**
|
|
194
|
-
* Delete a named
|
|
189
|
+
* Delete a named directory
|
|
195
190
|
*
|
|
196
|
-
* @param name
|
|
197
|
-
* @returns true if
|
|
191
|
+
* @param name Directory name to delete
|
|
192
|
+
* @returns true if directory was deleted, false if it didn't exist
|
|
198
193
|
*/
|
|
199
194
|
delete(name: string): Promise<boolean>;
|
|
200
195
|
/**
|
|
201
|
-
* List all opened
|
|
196
|
+
* List all opened directory names
|
|
202
197
|
*
|
|
203
|
-
* @returns Array of
|
|
198
|
+
* @returns Array of directory names
|
|
204
199
|
*/
|
|
205
200
|
keys(): Promise<string[]>;
|
|
206
201
|
/**
|
|
207
|
-
* Get statistics about opened
|
|
202
|
+
* Get statistics about opened directories (non-standard utility method)
|
|
208
203
|
*
|
|
209
|
-
* @returns Object with
|
|
204
|
+
* @returns Object with directory statistics
|
|
210
205
|
*/
|
|
211
206
|
getStats(): {
|
|
212
207
|
openInstances: number;
|
|
213
|
-
|
|
208
|
+
directoryNames: string[];
|
|
214
209
|
};
|
|
215
210
|
}
|
package/src/index.js
CHANGED
|
@@ -41,11 +41,29 @@ var ShovelWritableFileStream = class extends WritableStream {
|
|
|
41
41
|
try {
|
|
42
42
|
if (typeof data === "string") {
|
|
43
43
|
await writer.write(new TextEncoder().encode(data));
|
|
44
|
-
} else if (data instanceof Uint8Array
|
|
45
|
-
|
|
46
|
-
|
|
44
|
+
} else if (data instanceof Uint8Array) {
|
|
45
|
+
await writer.write(data);
|
|
46
|
+
} else if (data instanceof ArrayBuffer) {
|
|
47
|
+
await writer.write(new Uint8Array(data));
|
|
48
|
+
} else if (data instanceof Blob) {
|
|
49
|
+
const buffer = await data.arrayBuffer();
|
|
50
|
+
await writer.write(new Uint8Array(buffer));
|
|
51
|
+
} else if (ArrayBuffer.isView(data)) {
|
|
52
|
+
await writer.write(
|
|
53
|
+
new Uint8Array(data.buffer, data.byteOffset, data.byteLength)
|
|
54
|
+
);
|
|
55
|
+
} else if (typeof data === "object" && data !== null && "type" in data) {
|
|
56
|
+
const params = data;
|
|
57
|
+
if (params.type === "write" && params.data !== void 0) {
|
|
58
|
+
await this.write(params.data);
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
throw new DOMException("Invalid write params", "NotSupportedError");
|
|
47
62
|
} else {
|
|
48
|
-
|
|
63
|
+
throw new DOMException(
|
|
64
|
+
"Invalid data type for write",
|
|
65
|
+
"NotSupportedError"
|
|
66
|
+
);
|
|
49
67
|
}
|
|
50
68
|
} finally {
|
|
51
69
|
writer.releaseLock();
|
|
@@ -84,30 +102,26 @@ var ShovelHandle = class _ShovelHandle {
|
|
|
84
102
|
return false;
|
|
85
103
|
return this.path === other.path;
|
|
86
104
|
}
|
|
87
|
-
async queryPermission(
|
|
88
|
-
const _mode = descriptor?.mode || "read";
|
|
105
|
+
async queryPermission(_descriptor) {
|
|
89
106
|
return "granted";
|
|
90
107
|
}
|
|
91
|
-
async requestPermission(
|
|
92
|
-
const _mode = descriptor?.mode || "read";
|
|
108
|
+
async requestPermission(_descriptor) {
|
|
93
109
|
return "granted";
|
|
94
110
|
}
|
|
95
111
|
/**
|
|
96
112
|
* Validates that a name is actually a name and not a path
|
|
97
113
|
* The File System Access API only accepts names, not paths
|
|
114
|
+
* WPT expects TypeError for invalid names
|
|
98
115
|
*/
|
|
99
116
|
validateName(name) {
|
|
100
117
|
if (!name || name.trim() === "") {
|
|
101
|
-
throw new
|
|
118
|
+
throw new TypeError("Name cannot be empty");
|
|
102
119
|
}
|
|
103
120
|
if (name.includes("/") || name.includes("\\")) {
|
|
104
|
-
throw new
|
|
105
|
-
"Name cannot contain path separators",
|
|
106
|
-
"NotAllowedError"
|
|
107
|
-
);
|
|
121
|
+
throw new TypeError("Name cannot contain path separators");
|
|
108
122
|
}
|
|
109
123
|
if (name === "." || name === "..") {
|
|
110
|
-
throw new
|
|
124
|
+
throw new TypeError("Name cannot be '.' or '..'");
|
|
111
125
|
}
|
|
112
126
|
}
|
|
113
127
|
};
|
|
@@ -249,45 +263,45 @@ var ShovelDirectoryHandle = class _ShovelDirectoryHandle extends ShovelHandle {
|
|
|
249
263
|
return `${base}/${name}`;
|
|
250
264
|
}
|
|
251
265
|
};
|
|
252
|
-
var
|
|
266
|
+
var CustomDirectoryStorage = class {
|
|
253
267
|
#instances;
|
|
254
268
|
#factory;
|
|
255
269
|
/**
|
|
256
|
-
* @param factory Function that creates
|
|
270
|
+
* @param factory Function that creates directory instances by name
|
|
257
271
|
*/
|
|
258
272
|
constructor(factory) {
|
|
259
273
|
this.#instances = /* @__PURE__ */ new Map();
|
|
260
274
|
this.#factory = factory;
|
|
261
275
|
}
|
|
262
276
|
/**
|
|
263
|
-
* Open a named
|
|
277
|
+
* Open a named directory - creates if it doesn't exist
|
|
264
278
|
*
|
|
265
|
-
* @param name
|
|
266
|
-
* @returns FileSystemDirectoryHandle for the
|
|
279
|
+
* @param name Directory name (e.g., 'tmp', 'dist', 'uploads')
|
|
280
|
+
* @returns FileSystemDirectoryHandle for the directory
|
|
267
281
|
*/
|
|
268
282
|
async open(name) {
|
|
269
283
|
const existing = this.#instances.get(name);
|
|
270
284
|
if (existing) {
|
|
271
285
|
return existing;
|
|
272
286
|
}
|
|
273
|
-
const
|
|
274
|
-
this.#instances.set(name,
|
|
275
|
-
return
|
|
287
|
+
const dir = await this.#factory(name);
|
|
288
|
+
this.#instances.set(name, dir);
|
|
289
|
+
return dir;
|
|
276
290
|
}
|
|
277
291
|
/**
|
|
278
|
-
* Check if a named
|
|
292
|
+
* Check if a named directory exists
|
|
279
293
|
*
|
|
280
|
-
* @param name
|
|
281
|
-
* @returns true if
|
|
294
|
+
* @param name Directory name to check
|
|
295
|
+
* @returns true if directory has been opened
|
|
282
296
|
*/
|
|
283
297
|
async has(name) {
|
|
284
298
|
return this.#instances.has(name);
|
|
285
299
|
}
|
|
286
300
|
/**
|
|
287
|
-
* Delete a named
|
|
301
|
+
* Delete a named directory
|
|
288
302
|
*
|
|
289
|
-
* @param name
|
|
290
|
-
* @returns true if
|
|
303
|
+
* @param name Directory name to delete
|
|
304
|
+
* @returns true if directory was deleted, false if it didn't exist
|
|
291
305
|
*/
|
|
292
306
|
async delete(name) {
|
|
293
307
|
const instance = this.#instances.get(name);
|
|
@@ -298,27 +312,27 @@ var CustomBucketStorage = class {
|
|
|
298
312
|
return false;
|
|
299
313
|
}
|
|
300
314
|
/**
|
|
301
|
-
* List all opened
|
|
315
|
+
* List all opened directory names
|
|
302
316
|
*
|
|
303
|
-
* @returns Array of
|
|
317
|
+
* @returns Array of directory names
|
|
304
318
|
*/
|
|
305
319
|
async keys() {
|
|
306
320
|
return Array.from(this.#instances.keys());
|
|
307
321
|
}
|
|
308
322
|
/**
|
|
309
|
-
* Get statistics about opened
|
|
323
|
+
* Get statistics about opened directories (non-standard utility method)
|
|
310
324
|
*
|
|
311
|
-
* @returns Object with
|
|
325
|
+
* @returns Object with directory statistics
|
|
312
326
|
*/
|
|
313
327
|
getStats() {
|
|
314
328
|
return {
|
|
315
329
|
openInstances: this.#instances.size,
|
|
316
|
-
|
|
330
|
+
directoryNames: Array.from(this.#instances.keys())
|
|
317
331
|
};
|
|
318
332
|
}
|
|
319
333
|
};
|
|
320
334
|
export {
|
|
321
|
-
|
|
335
|
+
CustomDirectoryStorage,
|
|
322
336
|
ShovelDirectoryHandle,
|
|
323
337
|
ShovelFileHandle,
|
|
324
338
|
ShovelHandle
|
package/src/memory.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* In-memory filesystem implementation
|
|
3
3
|
*
|
|
4
|
-
* Provides
|
|
4
|
+
* Provides MemoryDirectory (root) and MemoryFileSystemBackend for storage operations
|
|
5
5
|
* using in-memory data structures.
|
|
6
6
|
*/
|
|
7
7
|
import { type FileSystemBackend } from "./index.js";
|
|
@@ -15,19 +15,19 @@ interface MemoryFile {
|
|
|
15
15
|
type: string;
|
|
16
16
|
}
|
|
17
17
|
/**
|
|
18
|
-
* In-memory directory data
|
|
18
|
+
* In-memory directory data (internal structure)
|
|
19
19
|
*/
|
|
20
|
-
interface
|
|
20
|
+
interface MemoryDirectoryData {
|
|
21
21
|
name: string;
|
|
22
22
|
files: Map<string, MemoryFile>;
|
|
23
|
-
directories: Map<string,
|
|
23
|
+
directories: Map<string, MemoryDirectoryData>;
|
|
24
24
|
}
|
|
25
25
|
/**
|
|
26
26
|
* In-memory storage backend that implements FileSystemBackend
|
|
27
27
|
*/
|
|
28
28
|
export declare class MemoryFileSystemBackend implements FileSystemBackend {
|
|
29
29
|
#private;
|
|
30
|
-
constructor(root:
|
|
30
|
+
constructor(root: MemoryDirectoryData);
|
|
31
31
|
stat(path: string): Promise<{
|
|
32
32
|
kind: "file" | "directory";
|
|
33
33
|
} | null>;
|
|
@@ -44,10 +44,10 @@ export declare class MemoryFileSystemBackend implements FileSystemBackend {
|
|
|
44
44
|
remove(path: string, recursive?: boolean): Promise<void>;
|
|
45
45
|
}
|
|
46
46
|
/**
|
|
47
|
-
* Memory
|
|
47
|
+
* Memory directory - root entry point for in-memory filesystem
|
|
48
48
|
* Implements FileSystemDirectoryHandle and owns the root data structure
|
|
49
49
|
*/
|
|
50
|
-
export declare class
|
|
50
|
+
export declare class MemoryDirectory implements FileSystemDirectoryHandle {
|
|
51
51
|
#private;
|
|
52
52
|
readonly kind: "directory";
|
|
53
53
|
readonly name: string;
|
package/src/memory.js
CHANGED
|
@@ -145,7 +145,7 @@ var MemoryFileSystemBackend = class {
|
|
|
145
145
|
return { parentDir: current, name };
|
|
146
146
|
}
|
|
147
147
|
};
|
|
148
|
-
var
|
|
148
|
+
var MemoryDirectory = class _MemoryDirectory {
|
|
149
149
|
kind;
|
|
150
150
|
name;
|
|
151
151
|
#backend;
|
|
@@ -160,6 +160,15 @@ var MemoryBucket = class _MemoryBucket {
|
|
|
160
160
|
this.#backend = new MemoryFileSystemBackend(root);
|
|
161
161
|
}
|
|
162
162
|
async getFileHandle(name, options) {
|
|
163
|
+
if (!name || name.trim() === "") {
|
|
164
|
+
throw new TypeError("Name cannot be empty");
|
|
165
|
+
}
|
|
166
|
+
if (name.includes("/") || name.includes("\\")) {
|
|
167
|
+
throw new TypeError("Name cannot contain path separators");
|
|
168
|
+
}
|
|
169
|
+
if (name === "." || name === "..") {
|
|
170
|
+
throw new TypeError("Name cannot be '.' or '..'");
|
|
171
|
+
}
|
|
163
172
|
const filePath = `/${name}`;
|
|
164
173
|
const stat = await this.#backend.stat(filePath);
|
|
165
174
|
if (!stat && options?.create) {
|
|
@@ -175,6 +184,15 @@ var MemoryBucket = class _MemoryBucket {
|
|
|
175
184
|
return new ShovelFileHandle(this.#backend, filePath);
|
|
176
185
|
}
|
|
177
186
|
async getDirectoryHandle(name, options) {
|
|
187
|
+
if (!name || name.trim() === "") {
|
|
188
|
+
throw new TypeError("Name cannot be empty");
|
|
189
|
+
}
|
|
190
|
+
if (name.includes("/") || name.includes("\\")) {
|
|
191
|
+
throw new TypeError("Name cannot contain path separators");
|
|
192
|
+
}
|
|
193
|
+
if (name === "." || name === "..") {
|
|
194
|
+
throw new TypeError("Name cannot be '.' or '..'");
|
|
195
|
+
}
|
|
178
196
|
const dirPath = `/${name}`;
|
|
179
197
|
const stat = await this.#backend.stat(dirPath);
|
|
180
198
|
if (!stat && options?.create) {
|
|
@@ -194,6 +212,12 @@ var MemoryBucket = class _MemoryBucket {
|
|
|
194
212
|
await this.#backend.remove(entryPath, options?.recursive);
|
|
195
213
|
}
|
|
196
214
|
async resolve(possibleDescendant) {
|
|
215
|
+
if (possibleDescendant instanceof _MemoryDirectory) {
|
|
216
|
+
if (await this.isSameEntry(possibleDescendant)) {
|
|
217
|
+
return [];
|
|
218
|
+
}
|
|
219
|
+
return null;
|
|
220
|
+
}
|
|
197
221
|
if (!(possibleDescendant instanceof ShovelDirectoryHandle || possibleDescendant instanceof ShovelFileHandle)) {
|
|
198
222
|
return null;
|
|
199
223
|
}
|
|
@@ -230,7 +254,7 @@ var MemoryBucket = class _MemoryBucket {
|
|
|
230
254
|
async isSameEntry(other) {
|
|
231
255
|
if (other.kind !== "directory")
|
|
232
256
|
return false;
|
|
233
|
-
return other instanceof
|
|
257
|
+
return other instanceof _MemoryDirectory && other.name === this.name;
|
|
234
258
|
}
|
|
235
259
|
async queryPermission() {
|
|
236
260
|
return "granted";
|
|
@@ -240,6 +264,6 @@ var MemoryBucket = class _MemoryBucket {
|
|
|
240
264
|
}
|
|
241
265
|
};
|
|
242
266
|
export {
|
|
243
|
-
|
|
267
|
+
MemoryDirectory,
|
|
244
268
|
MemoryFileSystemBackend
|
|
245
269
|
};
|
package/src/node-fs.d.ts
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Node.js filesystem implementation using node:fs
|
|
3
|
+
*
|
|
4
|
+
* Provides NodeFSDirectory (root) and NodeFSBackend for storage operations
|
|
5
|
+
* using Node.js fs module. Works in both Node.js and Bun.
|
|
6
|
+
*/
|
|
7
|
+
import { type FileSystemBackend, ShovelDirectoryHandle } from "./index.js";
|
|
8
|
+
/**
|
|
9
|
+
* Node.js storage backend using node:fs
|
|
10
|
+
*/
|
|
11
|
+
export declare class NodeFSBackend implements FileSystemBackend {
|
|
12
|
+
#private;
|
|
13
|
+
constructor(rootPath: string);
|
|
14
|
+
stat(filePath: string): Promise<{
|
|
15
|
+
kind: "file" | "directory";
|
|
16
|
+
} | null>;
|
|
17
|
+
readFile(filePath: string): Promise<{
|
|
18
|
+
content: Uint8Array;
|
|
19
|
+
lastModified?: number;
|
|
20
|
+
}>;
|
|
21
|
+
writeFile(filePath: string, data: Uint8Array): Promise<void>;
|
|
22
|
+
listDir(dirPath: string): Promise<Array<{
|
|
23
|
+
name: string;
|
|
24
|
+
kind: "file" | "directory";
|
|
25
|
+
}>>;
|
|
26
|
+
createDir(dirPath: string): Promise<void>;
|
|
27
|
+
remove(entryPath: string, recursive?: boolean): Promise<void>;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Node.js directory using node:fs - root entry point for local filesystem
|
|
31
|
+
* Extends ShovelDirectoryHandle with "/" as root path
|
|
32
|
+
*/
|
|
33
|
+
export declare class NodeFSDirectory extends ShovelDirectoryHandle {
|
|
34
|
+
#private;
|
|
35
|
+
/**
|
|
36
|
+
* Create a NodeFSDirectory
|
|
37
|
+
* @param name - Directory name (used for display)
|
|
38
|
+
* @param options - Options object containing the filesystem path
|
|
39
|
+
* @param options.path - The actual filesystem path to use as root
|
|
40
|
+
*/
|
|
41
|
+
constructor(name: string, options?: {
|
|
42
|
+
path?: string;
|
|
43
|
+
});
|
|
44
|
+
get name(): string;
|
|
45
|
+
}
|
|
@@ -1,9 +1,12 @@
|
|
|
1
|
-
/// <reference types="./node.d.ts" />
|
|
2
|
-
// src/node.ts
|
|
1
|
+
/// <reference types="./node-fs.d.ts" />
|
|
2
|
+
// src/node-fs.ts
|
|
3
3
|
import { ShovelDirectoryHandle } from "./index.js";
|
|
4
4
|
import * as FS from "fs/promises";
|
|
5
5
|
import * as Path from "path";
|
|
6
|
-
|
|
6
|
+
function isErrnoException(error) {
|
|
7
|
+
return error instanceof Error && "code" in error;
|
|
8
|
+
}
|
|
9
|
+
var NodeFSBackend = class {
|
|
7
10
|
#rootPath;
|
|
8
11
|
constructor(rootPath) {
|
|
9
12
|
this.#rootPath = rootPath;
|
|
@@ -20,7 +23,7 @@ var NodeFileSystemBackend = class {
|
|
|
20
23
|
return null;
|
|
21
24
|
}
|
|
22
25
|
} catch (error) {
|
|
23
|
-
if (error.code === "ENOENT") {
|
|
26
|
+
if (isErrnoException(error) && error.code === "ENOENT") {
|
|
24
27
|
return null;
|
|
25
28
|
}
|
|
26
29
|
throw error;
|
|
@@ -38,7 +41,7 @@ var NodeFileSystemBackend = class {
|
|
|
38
41
|
lastModified: stats.mtimeMs
|
|
39
42
|
};
|
|
40
43
|
} catch (error) {
|
|
41
|
-
if (error.code === "ENOENT") {
|
|
44
|
+
if (isErrnoException(error) && error.code === "ENOENT") {
|
|
42
45
|
throw new DOMException("File not found", "NotFoundError");
|
|
43
46
|
}
|
|
44
47
|
throw error;
|
|
@@ -70,7 +73,7 @@ var NodeFileSystemBackend = class {
|
|
|
70
73
|
}
|
|
71
74
|
return results;
|
|
72
75
|
} catch (error) {
|
|
73
|
-
if (error.code === "ENOENT") {
|
|
76
|
+
if (isErrnoException(error) && error.code === "ENOENT") {
|
|
74
77
|
throw new DOMException("Directory not found", "NotFoundError");
|
|
75
78
|
}
|
|
76
79
|
throw error;
|
|
@@ -108,7 +111,7 @@ var NodeFileSystemBackend = class {
|
|
|
108
111
|
}
|
|
109
112
|
}
|
|
110
113
|
} catch (error) {
|
|
111
|
-
if (error.code === "ENOENT") {
|
|
114
|
+
if (isErrnoException(error) && error.code === "ENOENT") {
|
|
112
115
|
throw new DOMException("Entry not found", "NotFoundError");
|
|
113
116
|
}
|
|
114
117
|
throw error;
|
|
@@ -135,10 +138,17 @@ var NodeFileSystemBackend = class {
|
|
|
135
138
|
return resolvedPath;
|
|
136
139
|
}
|
|
137
140
|
};
|
|
138
|
-
var
|
|
141
|
+
var NodeFSDirectory = class extends ShovelDirectoryHandle {
|
|
139
142
|
#rootPath;
|
|
140
|
-
|
|
141
|
-
|
|
143
|
+
/**
|
|
144
|
+
* Create a NodeFSDirectory
|
|
145
|
+
* @param name - Directory name (used for display)
|
|
146
|
+
* @param options - Options object containing the filesystem path
|
|
147
|
+
* @param options.path - The actual filesystem path to use as root
|
|
148
|
+
*/
|
|
149
|
+
constructor(name, options) {
|
|
150
|
+
const rootPath = options?.path ?? name;
|
|
151
|
+
super(new NodeFSBackend(rootPath), "/");
|
|
142
152
|
this.#rootPath = rootPath;
|
|
143
153
|
}
|
|
144
154
|
// Override name to use the directory basename instead of "/"
|
|
@@ -147,6 +157,6 @@ var NodeBucket = class extends ShovelDirectoryHandle {
|
|
|
147
157
|
}
|
|
148
158
|
};
|
|
149
159
|
export {
|
|
150
|
-
|
|
151
|
-
|
|
160
|
+
NodeFSBackend,
|
|
161
|
+
NodeFSDirectory
|
|
152
162
|
};
|
package/src/node.d.ts
DELETED
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Node.js filesystem implementation
|
|
3
|
-
*
|
|
4
|
-
* Provides NodeBucket (root) and NodeFileSystemBackend for storage operations
|
|
5
|
-
* using Node.js fs module.
|
|
6
|
-
*/
|
|
7
|
-
import { type FileSystemBackend, ShovelDirectoryHandle } from "./index.js";
|
|
8
|
-
/**
|
|
9
|
-
* Node.js storage backend that implements FileSystemBackend
|
|
10
|
-
*/
|
|
11
|
-
export declare class NodeFileSystemBackend implements FileSystemBackend {
|
|
12
|
-
#private;
|
|
13
|
-
constructor(rootPath: string);
|
|
14
|
-
stat(filePath: string): Promise<{
|
|
15
|
-
kind: "file" | "directory";
|
|
16
|
-
} | null>;
|
|
17
|
-
readFile(filePath: string): Promise<{
|
|
18
|
-
content: Uint8Array;
|
|
19
|
-
lastModified?: number;
|
|
20
|
-
}>;
|
|
21
|
-
writeFile(filePath: string, data: Uint8Array): Promise<void>;
|
|
22
|
-
listDir(dirPath: string): Promise<Array<{
|
|
23
|
-
name: string;
|
|
24
|
-
kind: "file" | "directory";
|
|
25
|
-
}>>;
|
|
26
|
-
createDir(dirPath: string): Promise<void>;
|
|
27
|
-
remove(entryPath: string, recursive?: boolean): Promise<void>;
|
|
28
|
-
}
|
|
29
|
-
/**
|
|
30
|
-
* Node bucket - root entry point for Node.js filesystem
|
|
31
|
-
* Extends ShovelDirectoryHandle with "/" as root path
|
|
32
|
-
*/
|
|
33
|
-
export declare class NodeBucket extends ShovelDirectoryHandle {
|
|
34
|
-
#private;
|
|
35
|
-
constructor(rootPath: string);
|
|
36
|
-
get name(): string;
|
|
37
|
-
}
|