@fnndsc/fond 0.1.2 → 0.2.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.
- package/README.md +20 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.js +3 -0
- package/dist/index.js.map +1 -1
- package/dist/vfs/dispatcher.d.ts +150 -0
- package/dist/vfs/dispatcher.js +322 -0
- package/dist/vfs/dispatcher.js.map +1 -0
- package/dist/vfs/provider.d.ts +128 -0
- package/dist/vfs/provider.js +13 -0
- package/dist/vfs/provider.js.map +1 -0
- package/dist/vfs/sort.d.ts +18 -0
- package/dist/vfs/sort.js +33 -0
- package/dist/vfs/sort.js.map +1 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -21,6 +21,9 @@ fond's one rule: **it depends on nothing in `@fnndsc`**. CI holds it to that (`n
|
|
|
21
21
|
| `Result<T>`, `Ok`, `Err`, `result_isOk`, `result_isErr` | An explicit success-or-failure value. A function returns `Result<T>` rather than `T \| null`, and TypeScript will not let a caller read `.value` until it has checked `.ok`. |
|
|
22
22
|
| `errorStack` | The process-wide message stack that failures are reported on, with context-isolated scopes and checkpoints. |
|
|
23
23
|
| `errorStack_configure`, `errorStack_getAllOfType`, `StackMessage` | Configuration, a convenience reader, and the message type. |
|
|
24
|
+
| `VFSProvider`, `VFSItem`, `CpOptions` | The virtual filesystem's contracts: a mount that claims a path prefix and lists, copies and (optionally) reads, writes, makes, removes and renames under it; the items it lists. |
|
|
25
|
+
| `VFSDispatcher` | Routes each filesystem request to the mount that owns the path, or to a fallback. It knows no backend: a backend registers its mounts and names its fallback. |
|
|
26
|
+
| `vfsItems_sort` | Sorts a listing's items by name, size, date or owner without changing the array given. |
|
|
24
27
|
|
|
25
28
|
## Using `Result`
|
|
26
29
|
|
|
@@ -79,6 +82,23 @@ const reasons: StackMessage[] = errorStack.checkpoint_drain(mark);
|
|
|
79
82
|
|
|
80
83
|
`errorStack_configure({ functionNamePadWidth })` sets how wide the function-name stamp is padded.
|
|
81
84
|
|
|
85
|
+
## The virtual filesystem
|
|
86
|
+
|
|
87
|
+
A session's filesystem is a tree of mounts. Each mount (a `VFSProvider`) claims a path prefix and answers for everything at or under it; the longest prefix that matches at a segment boundary wins, so `/proc/jobs` takes precedence over `/proc`, and `/procs` is not under `/proc`. A path no mount claims goes to the fallback.
|
|
88
|
+
|
|
89
|
+
```typescript
|
|
90
|
+
import { VFSDispatcher, type VFSProvider } from '@fnndsc/fond';
|
|
91
|
+
|
|
92
|
+
const dispatcher: VFSDispatcher = new VFSDispatcher(filesFallback); // what no mount claims
|
|
93
|
+
dispatcher.provider_register(notesMount); // prefix '/notes'
|
|
94
|
+
dispatcher.provider_register(jobsMount); // prefix '/proc/jobs'
|
|
95
|
+
|
|
96
|
+
await dispatcher.list('/proc'); // the mounts beneath it ('jobs'), beside what the fallback holds there
|
|
97
|
+
await dispatcher.read('/notes/today'); // notesMount.read('/notes/today')
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
Every operation a mount does not offer is refused by name (`mkdir: cannot create directory '/x': Read-only file system`), never silently ignored. A dispatcher built without a fallback refuses any path no mount claims, rather than answering with an empty folder. `pathResolver_register` adds a hook that maps a path to the fallback's own form before the fallback sees it; a copy whose path cannot be resolved fails rather than guessing.
|
|
101
|
+
|
|
82
102
|
## One instance, whoever loads it
|
|
83
103
|
|
|
84
104
|
The error stack only works if the whole process shares one. fond is built as CommonJS, so packages that `require` it (cumin) and packages that `import` it (salsa, brasa, calypso) load the same module and so the same stack. `@fnndsc/cumin` re-exports fond's `Result` and `errorStack` rather than keeping copies, so code that imports them from cumin shares that stack too. If you bundle code that uses fond, keep it to one copy.
|
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
|
@@ -26,4 +26,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
26
26
|
*/
|
|
27
27
|
__exportStar(require("./result.js"), exports);
|
|
28
28
|
__exportStar(require("./errorStack.js"), exports);
|
|
29
|
+
__exportStar(require("./vfs/provider.js"), exports);
|
|
30
|
+
__exportStar(require("./vfs/sort.js"), exports);
|
|
31
|
+
__exportStar(require("./vfs/dispatcher.js"), exports);
|
|
29
32
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA;;;;;;;;;GASG;AACH,8CAA4B;AAC5B,kDAAgC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA;;;;;;;;;GASG;AACH,8CAA4B;AAC5B,kDAAgC;AAChC,oDAAkC;AAClC,gDAA8B;AAC9B,sDAAoC"}
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file The virtual filesystem's dispatcher: routes each request to the
|
|
3
|
+
* mount that owns the path.
|
|
4
|
+
*
|
|
5
|
+
* Mounts (providers) are registered with a path prefix; the longest prefix
|
|
6
|
+
* that matches at a segment boundary wins, so `/proc/jobs` takes precedence
|
|
7
|
+
* over `/proc`, and `/procs` is not under `/proc`. A path no mount claims
|
|
8
|
+
* goes to the fallback, the provider given to the constructor. The
|
|
9
|
+
* dispatcher itself knows no backend: a backend registers its mounts and
|
|
10
|
+
* names its fallback.
|
|
11
|
+
*
|
|
12
|
+
* @module
|
|
13
|
+
*/
|
|
14
|
+
import { Result } from "../result.js";
|
|
15
|
+
import { VFSProvider, VFSItem, CpOptions } from "./provider.js";
|
|
16
|
+
/**
|
|
17
|
+
* Routes filesystem requests to the mount that owns each path, or to the
|
|
18
|
+
* fallback.
|
|
19
|
+
*/
|
|
20
|
+
export declare class VFSDispatcher {
|
|
21
|
+
private providers;
|
|
22
|
+
private defaultProvider;
|
|
23
|
+
private pathResolver?;
|
|
24
|
+
/**
|
|
25
|
+
* @param fallback - The provider for paths no mount claims; one that holds
|
|
26
|
+
* nothing, and says so, when none is given.
|
|
27
|
+
*/
|
|
28
|
+
constructor(fallback?: VFSProvider);
|
|
29
|
+
/**
|
|
30
|
+
* Registers a path resolution hook that maps logical paths to physical paths.
|
|
31
|
+
*
|
|
32
|
+
* @param resolver - The resolver function mapping a logical path to a physical path.
|
|
33
|
+
*/
|
|
34
|
+
pathResolver_register(resolver: (path: string) => Promise<string>): void;
|
|
35
|
+
/**
|
|
36
|
+
* Registers a new VFS Provider.
|
|
37
|
+
*
|
|
38
|
+
* @param provider - The provider instance to register.
|
|
39
|
+
*/
|
|
40
|
+
provider_register(provider: VFSProvider): void;
|
|
41
|
+
/**
|
|
42
|
+
* Returns every registered mount (not the fallback). Used by callers that
|
|
43
|
+
* need to detect parent-of-prefix paths.
|
|
44
|
+
*/
|
|
45
|
+
providers_get(): VFSProvider[];
|
|
46
|
+
/**
|
|
47
|
+
* Resolves the matching provider for a given virtual path.
|
|
48
|
+
*
|
|
49
|
+
* @param pathStr - The absolute virtual path.
|
|
50
|
+
* @returns The matching mount, or the fallback.
|
|
51
|
+
*/
|
|
52
|
+
provider_get(pathStr: string): VFSProvider;
|
|
53
|
+
/**
|
|
54
|
+
* Whether a path belongs to a mount rather than to the fallback.
|
|
55
|
+
*
|
|
56
|
+
* Two shapes count: a path a mount owns (at or under its prefix), and a
|
|
57
|
+
* path that is a strict ancestor of a mount's prefix (`/proc` above
|
|
58
|
+
* `/proc/jobs`), whose only children are the mounts beneath it. The root
|
|
59
|
+
* `/` never counts: it is the fallback's own root.
|
|
60
|
+
*
|
|
61
|
+
* It keeps the fallback from being asked to answer for a path it has no
|
|
62
|
+
* folder behind, which cannot succeed and only fills the error stack once
|
|
63
|
+
* per ancestor a path walk visits.
|
|
64
|
+
*
|
|
65
|
+
* @param pathStr - The absolute (or root-relative) path to classify.
|
|
66
|
+
* @returns True when a mount owns, or is owned by, the path.
|
|
67
|
+
*/
|
|
68
|
+
path_isVirtual(pathStr: string): boolean;
|
|
69
|
+
/**
|
|
70
|
+
* Dispatches directory listing to matched provider.
|
|
71
|
+
* Supports dynamic intermediate parent path synthesis for virtual prefixes.
|
|
72
|
+
*
|
|
73
|
+
* @param pathStr - The absolute virtual path to list.
|
|
74
|
+
* @param options - Sort controls.
|
|
75
|
+
* @returns Promise resolving to Result<VFSItem[]>.
|
|
76
|
+
*/
|
|
77
|
+
list(pathStr: string, options?: {
|
|
78
|
+
sort?: "name" | "size" | "date" | "owner";
|
|
79
|
+
reverse?: boolean;
|
|
80
|
+
}): Promise<Result<VFSItem[]>>;
|
|
81
|
+
/**
|
|
82
|
+
* Dispatches copy operation to matched provider.
|
|
83
|
+
*
|
|
84
|
+
* @param src - Source path.
|
|
85
|
+
* @param dest - Destination path.
|
|
86
|
+
* @param options - Copy options.
|
|
87
|
+
* @returns Promise resolving to success boolean.
|
|
88
|
+
*/
|
|
89
|
+
cp(src: string, dest: string, options: CpOptions): Promise<boolean>;
|
|
90
|
+
/**
|
|
91
|
+
* Dispatches file read operation to the matched provider.
|
|
92
|
+
*
|
|
93
|
+
* @param pathStr - The absolute virtual path of the file to read.
|
|
94
|
+
* @returns A Promise resolving to a Result containing the file contents as a string.
|
|
95
|
+
*/
|
|
96
|
+
read(pathStr: string): Promise<Result<string>>;
|
|
97
|
+
/**
|
|
98
|
+
* Dispatches a whole-file write to the matched provider: a mount
|
|
99
|
+
* that holds writable files (a feed's note) takes the content; any other
|
|
100
|
+
* path is refused by name rather than written somewhere it does not live.
|
|
101
|
+
*
|
|
102
|
+
* @param pathStr - The absolute virtual path of the file.
|
|
103
|
+
* @param content - The file's new content, whole.
|
|
104
|
+
* @returns True when the provider took it.
|
|
105
|
+
*/
|
|
106
|
+
/**
|
|
107
|
+
* Dispatches a folder's making to the matched provider; a mount that
|
|
108
|
+
* makes no folders refuses by name.
|
|
109
|
+
*
|
|
110
|
+
* @param pathStr - The absolute virtual path of the new folder.
|
|
111
|
+
* @returns True when the provider made it.
|
|
112
|
+
*/
|
|
113
|
+
mkdir(pathStr: string): Promise<boolean>;
|
|
114
|
+
/**
|
|
115
|
+
* Dispatches an empty folder's removal to the matched provider; a
|
|
116
|
+
* mount that removes no folders refuses by name.
|
|
117
|
+
*
|
|
118
|
+
* @param pathStr - The absolute virtual path of the folder.
|
|
119
|
+
* @returns True when the provider removed it.
|
|
120
|
+
*/
|
|
121
|
+
rmdir(pathStr: string): Promise<boolean>;
|
|
122
|
+
/**
|
|
123
|
+
* Dispatches a rename within one mount; a rename across mounts, or in a
|
|
124
|
+
* mount that renames nothing, is refused by name.
|
|
125
|
+
*
|
|
126
|
+
* @param src - The absolute virtual path now.
|
|
127
|
+
* @param dest - The absolute virtual path it takes.
|
|
128
|
+
* @returns True when the provider renamed it.
|
|
129
|
+
*/
|
|
130
|
+
rename(src: string, dest: string): Promise<boolean>;
|
|
131
|
+
write(pathStr: string, content: string): Promise<boolean>;
|
|
132
|
+
/**
|
|
133
|
+
* Dispatches binary file read operation to the matched provider.
|
|
134
|
+
*
|
|
135
|
+
* @param pathStr - The absolute virtual path of the file to read.
|
|
136
|
+
* @returns A Promise resolving to a Result containing the file contents as a Buffer.
|
|
137
|
+
*/
|
|
138
|
+
readBinary(pathStr: string): Promise<Result<Buffer>>;
|
|
139
|
+
/**
|
|
140
|
+
* Resolves a lazy link through the provider that owns it.
|
|
141
|
+
*
|
|
142
|
+
* This is deliberately distinct from {@link list}: a structural traversal
|
|
143
|
+
* can display an unresolved link without causing its provider to fetch the
|
|
144
|
+
* target from a remote service.
|
|
145
|
+
*
|
|
146
|
+
* @param pathStr - Absolute path of the provider-defined link.
|
|
147
|
+
* @returns The resolved target path, or an error if unsupported or absent.
|
|
148
|
+
*/
|
|
149
|
+
linkTarget_resolve(pathStr: string): Promise<Result<string>>;
|
|
150
|
+
}
|
|
@@ -0,0 +1,322 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* @file The virtual filesystem's dispatcher: routes each request to the
|
|
4
|
+
* mount that owns the path.
|
|
5
|
+
*
|
|
6
|
+
* Mounts (providers) are registered with a path prefix; the longest prefix
|
|
7
|
+
* that matches at a segment boundary wins, so `/proc/jobs` takes precedence
|
|
8
|
+
* over `/proc`, and `/procs` is not under `/proc`. A path no mount claims
|
|
9
|
+
* goes to the fallback, the provider given to the constructor. The
|
|
10
|
+
* dispatcher itself knows no backend: a backend registers its mounts and
|
|
11
|
+
* names its fallback.
|
|
12
|
+
*
|
|
13
|
+
* @module
|
|
14
|
+
*/
|
|
15
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
16
|
+
exports.VFSDispatcher = void 0;
|
|
17
|
+
const result_js_1 = require("../result.js");
|
|
18
|
+
const errorStack_js_1 = require("../errorStack.js");
|
|
19
|
+
/**
|
|
20
|
+
* The fallback when none is given: it holds nothing, and says so by name
|
|
21
|
+
* rather than answering with an empty folder.
|
|
22
|
+
*/
|
|
23
|
+
const VFS_FALLBACK_NONE = {
|
|
24
|
+
prefix: "",
|
|
25
|
+
async list(path) {
|
|
26
|
+
errorStack_js_1.errorStack.stack_push("error", `No mount serves ${path}.`);
|
|
27
|
+
return (0, result_js_1.Err)();
|
|
28
|
+
},
|
|
29
|
+
async cp(src) {
|
|
30
|
+
errorStack_js_1.errorStack.stack_push("error", `cp: no mount serves ${src}`);
|
|
31
|
+
return false;
|
|
32
|
+
},
|
|
33
|
+
};
|
|
34
|
+
/**
|
|
35
|
+
* Routes filesystem requests to the mount that owns each path, or to the
|
|
36
|
+
* fallback.
|
|
37
|
+
*/
|
|
38
|
+
class VFSDispatcher {
|
|
39
|
+
/**
|
|
40
|
+
* @param fallback - The provider for paths no mount claims; one that holds
|
|
41
|
+
* nothing, and says so, when none is given.
|
|
42
|
+
*/
|
|
43
|
+
constructor(fallback = VFS_FALLBACK_NONE) {
|
|
44
|
+
this.providers = [];
|
|
45
|
+
this.defaultProvider = fallback;
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Registers a path resolution hook that maps logical paths to physical paths.
|
|
49
|
+
*
|
|
50
|
+
* @param resolver - The resolver function mapping a logical path to a physical path.
|
|
51
|
+
*/
|
|
52
|
+
pathResolver_register(resolver) {
|
|
53
|
+
this.pathResolver = resolver;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Registers a new VFS Provider.
|
|
57
|
+
*
|
|
58
|
+
* @param provider - The provider instance to register.
|
|
59
|
+
*/
|
|
60
|
+
provider_register(provider) {
|
|
61
|
+
this.providers.push(provider);
|
|
62
|
+
// Sort by prefix length descending to match most specific prefix first
|
|
63
|
+
this.providers.sort((a, b) => b.prefix.length - a.prefix.length);
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Returns every registered mount (not the fallback). Used by callers that
|
|
67
|
+
* need to detect parent-of-prefix paths.
|
|
68
|
+
*/
|
|
69
|
+
providers_get() {
|
|
70
|
+
return [...this.providers];
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Resolves the matching provider for a given virtual path.
|
|
74
|
+
*
|
|
75
|
+
* @param pathStr - The absolute virtual path.
|
|
76
|
+
* @returns The matching mount, or the fallback.
|
|
77
|
+
*/
|
|
78
|
+
provider_get(pathStr) {
|
|
79
|
+
const absolutePath = pathStr.startsWith("/") ? pathStr : "/" + pathStr;
|
|
80
|
+
const match = this.providers.find((p) => absolutePath === p.prefix || absolutePath.startsWith(p.prefix + "/"));
|
|
81
|
+
return match || this.defaultProvider;
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Whether a path belongs to a mount rather than to the fallback.
|
|
85
|
+
*
|
|
86
|
+
* Two shapes count: a path a mount owns (at or under its prefix), and a
|
|
87
|
+
* path that is a strict ancestor of a mount's prefix (`/proc` above
|
|
88
|
+
* `/proc/jobs`), whose only children are the mounts beneath it. The root
|
|
89
|
+
* `/` never counts: it is the fallback's own root.
|
|
90
|
+
*
|
|
91
|
+
* It keeps the fallback from being asked to answer for a path it has no
|
|
92
|
+
* folder behind, which cannot succeed and only fills the error stack once
|
|
93
|
+
* per ancestor a path walk visits.
|
|
94
|
+
*
|
|
95
|
+
* @param pathStr - The absolute (or root-relative) path to classify.
|
|
96
|
+
* @returns True when a mount owns, or is owned by, the path.
|
|
97
|
+
*/
|
|
98
|
+
path_isVirtual(pathStr) {
|
|
99
|
+
const absolutePath = pathStr.startsWith("/") ? pathStr : "/" + pathStr;
|
|
100
|
+
const clean = absolutePath.length > 1 && absolutePath.endsWith("/") ? absolutePath.slice(0, -1) : absolutePath;
|
|
101
|
+
if (clean === "/")
|
|
102
|
+
return false;
|
|
103
|
+
return this.providers.some((p) => p.prefix.length > 0 &&
|
|
104
|
+
(clean === p.prefix || clean.startsWith(p.prefix + "/") || p.prefix.startsWith(clean + "/")));
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Dispatches directory listing to matched provider.
|
|
108
|
+
* Supports dynamic intermediate parent path synthesis for virtual prefixes.
|
|
109
|
+
*
|
|
110
|
+
* @param pathStr - The absolute virtual path to list.
|
|
111
|
+
* @param options - Sort controls.
|
|
112
|
+
* @returns Promise resolving to Result<VFSItem[]>.
|
|
113
|
+
*/
|
|
114
|
+
async list(pathStr, options) {
|
|
115
|
+
const absolutePath = pathStr.startsWith("/") ? pathStr : "/" + pathStr;
|
|
116
|
+
const cleanPath = absolutePath.endsWith("/") && absolutePath.length > 1 ? absolutePath.slice(0, -1) : absolutePath;
|
|
117
|
+
// Check if cleanPath is a parent of any registered provider's prefix
|
|
118
|
+
const prefixParent = cleanPath === "/" ? "/" : cleanPath + "/";
|
|
119
|
+
const children = this.providers.filter((p) => p.prefix.startsWith(prefixParent));
|
|
120
|
+
if (children.length > 0) {
|
|
121
|
+
const segmentIndex = cleanPath === "/" ? 1 : cleanPath.split("/").length;
|
|
122
|
+
const virtualSubdirs = new Set();
|
|
123
|
+
for (const p of children) {
|
|
124
|
+
const segments = p.prefix.split("/");
|
|
125
|
+
const nextSegment = segments[segmentIndex];
|
|
126
|
+
if (nextSegment) {
|
|
127
|
+
virtualSubdirs.add(nextSegment);
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
if (virtualSubdirs.size > 0) {
|
|
131
|
+
const vfsItems = Array.from(virtualSubdirs).map((name) => ({
|
|
132
|
+
name,
|
|
133
|
+
type: "vfs",
|
|
134
|
+
size: 0,
|
|
135
|
+
owner: "root",
|
|
136
|
+
date: new Date().toISOString(),
|
|
137
|
+
}));
|
|
138
|
+
// The fallback may hold real items in this folder too: list them beside the mounts
|
|
139
|
+
let resolvedPathStr = pathStr;
|
|
140
|
+
if (this.pathResolver) {
|
|
141
|
+
try {
|
|
142
|
+
resolvedPathStr = await this.pathResolver(pathStr);
|
|
143
|
+
}
|
|
144
|
+
catch (e) {
|
|
145
|
+
// Deliberate absorption: for a read-only listing, the logical
|
|
146
|
+
// path is a valid fallback (the provider lists what it can);
|
|
147
|
+
// contrast cp(), where a guessed path could write wrongly.
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
const fallbackResult = await this.defaultProvider.list(resolvedPathStr, options);
|
|
151
|
+
if (fallbackResult.ok && fallbackResult.value) {
|
|
152
|
+
const fallbackItems = fallbackResult.value;
|
|
153
|
+
for (const item of fallbackItems) {
|
|
154
|
+
if (!virtualSubdirs.has(item.name)) {
|
|
155
|
+
vfsItems.push(item);
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
return (0, result_js_1.Ok)(vfsItems);
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
const provider = this.provider_get(pathStr);
|
|
163
|
+
if (provider === this.defaultProvider && this.pathResolver) {
|
|
164
|
+
try {
|
|
165
|
+
const resolvedPath = await this.pathResolver(pathStr);
|
|
166
|
+
return provider.list(resolvedPath, options);
|
|
167
|
+
}
|
|
168
|
+
catch (e) {
|
|
169
|
+
// Deliberate absorption: same read-only-listing rationale as above.
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
return provider.list(pathStr, options);
|
|
173
|
+
}
|
|
174
|
+
/**
|
|
175
|
+
* Dispatches copy operation to matched provider.
|
|
176
|
+
*
|
|
177
|
+
* @param src - Source path.
|
|
178
|
+
* @param dest - Destination path.
|
|
179
|
+
* @param options - Copy options.
|
|
180
|
+
* @returns Promise resolving to success boolean.
|
|
181
|
+
*/
|
|
182
|
+
async cp(src, dest, options) {
|
|
183
|
+
const provider = this.provider_get(src);
|
|
184
|
+
if (provider === this.defaultProvider && this.pathResolver) {
|
|
185
|
+
// A copy must never proceed on a guessed path: an unresolved source
|
|
186
|
+
// copies the wrong thing, an unresolved destination writes to the wrong
|
|
187
|
+
// place. Resolution failure fails the copy.
|
|
188
|
+
let resolvedSrc;
|
|
189
|
+
let resolvedDest;
|
|
190
|
+
try {
|
|
191
|
+
resolvedSrc = await this.pathResolver(src);
|
|
192
|
+
}
|
|
193
|
+
catch (e) {
|
|
194
|
+
const msg = e instanceof Error ? e.message : String(e);
|
|
195
|
+
errorStack_js_1.errorStack.stack_push("error", `cp: cannot resolve source path ${src}: ${msg}`);
|
|
196
|
+
return false;
|
|
197
|
+
}
|
|
198
|
+
try {
|
|
199
|
+
resolvedDest = await this.pathResolver(dest);
|
|
200
|
+
}
|
|
201
|
+
catch (e) {
|
|
202
|
+
const msg = e instanceof Error ? e.message : String(e);
|
|
203
|
+
errorStack_js_1.errorStack.stack_push("error", `cp: cannot resolve destination path ${dest}: ${msg}`);
|
|
204
|
+
return false;
|
|
205
|
+
}
|
|
206
|
+
return provider.cp(resolvedSrc, resolvedDest, options);
|
|
207
|
+
}
|
|
208
|
+
return provider.cp(src, dest, options);
|
|
209
|
+
}
|
|
210
|
+
/**
|
|
211
|
+
* Dispatches file read operation to the matched provider.
|
|
212
|
+
*
|
|
213
|
+
* @param pathStr - The absolute virtual path of the file to read.
|
|
214
|
+
* @returns A Promise resolving to a Result containing the file contents as a string.
|
|
215
|
+
*/
|
|
216
|
+
async read(pathStr) {
|
|
217
|
+
const provider = this.provider_get(pathStr);
|
|
218
|
+
if (provider !== this.defaultProvider && provider.read) {
|
|
219
|
+
return provider.read(pathStr);
|
|
220
|
+
}
|
|
221
|
+
errorStack_js_1.errorStack.stack_push("error", `File read not supported for path: ${pathStr}`);
|
|
222
|
+
return (0, result_js_1.Err)();
|
|
223
|
+
}
|
|
224
|
+
/**
|
|
225
|
+
* Dispatches a whole-file write to the matched provider: a mount
|
|
226
|
+
* that holds writable files (a feed's note) takes the content; any other
|
|
227
|
+
* path is refused by name rather than written somewhere it does not live.
|
|
228
|
+
*
|
|
229
|
+
* @param pathStr - The absolute virtual path of the file.
|
|
230
|
+
* @param content - The file's new content, whole.
|
|
231
|
+
* @returns True when the provider took it.
|
|
232
|
+
*/
|
|
233
|
+
/**
|
|
234
|
+
* Dispatches a folder's making to the matched provider; a mount that
|
|
235
|
+
* makes no folders refuses by name.
|
|
236
|
+
*
|
|
237
|
+
* @param pathStr - The absolute virtual path of the new folder.
|
|
238
|
+
* @returns True when the provider made it.
|
|
239
|
+
*/
|
|
240
|
+
async mkdir(pathStr) {
|
|
241
|
+
const provider = this.provider_get(pathStr);
|
|
242
|
+
if (provider !== this.defaultProvider && provider.mkdir)
|
|
243
|
+
return provider.mkdir(pathStr);
|
|
244
|
+
errorStack_js_1.errorStack.stack_push("error", `mkdir: cannot create directory '${pathStr}': Read-only file system`);
|
|
245
|
+
return false;
|
|
246
|
+
}
|
|
247
|
+
/**
|
|
248
|
+
* Dispatches an empty folder's removal to the matched provider; a
|
|
249
|
+
* mount that removes no folders refuses by name.
|
|
250
|
+
*
|
|
251
|
+
* @param pathStr - The absolute virtual path of the folder.
|
|
252
|
+
* @returns True when the provider removed it.
|
|
253
|
+
*/
|
|
254
|
+
async rmdir(pathStr) {
|
|
255
|
+
const provider = this.provider_get(pathStr);
|
|
256
|
+
if (provider !== this.defaultProvider && provider.rmdir)
|
|
257
|
+
return provider.rmdir(pathStr);
|
|
258
|
+
errorStack_js_1.errorStack.stack_push("error", `rmdir: failed to remove '${pathStr}': Read-only file system`);
|
|
259
|
+
return false;
|
|
260
|
+
}
|
|
261
|
+
/**
|
|
262
|
+
* Dispatches a rename within one mount; a rename across mounts, or in a
|
|
263
|
+
* mount that renames nothing, is refused by name.
|
|
264
|
+
*
|
|
265
|
+
* @param src - The absolute virtual path now.
|
|
266
|
+
* @param dest - The absolute virtual path it takes.
|
|
267
|
+
* @returns True when the provider renamed it.
|
|
268
|
+
*/
|
|
269
|
+
async rename(src, dest) {
|
|
270
|
+
const provider = this.provider_get(src);
|
|
271
|
+
if (provider !== this.provider_get(dest)) {
|
|
272
|
+
errorStack_js_1.errorStack.stack_push("error", `mv: cannot move '${src}' to '${dest}': Invalid cross-device link`);
|
|
273
|
+
return false;
|
|
274
|
+
}
|
|
275
|
+
if (provider !== this.defaultProvider && provider.rename)
|
|
276
|
+
return provider.rename(src, dest);
|
|
277
|
+
errorStack_js_1.errorStack.stack_push("error", `mv: cannot move '${src}': Read-only file system`);
|
|
278
|
+
return false;
|
|
279
|
+
}
|
|
280
|
+
async write(pathStr, content) {
|
|
281
|
+
const provider = this.provider_get(pathStr);
|
|
282
|
+
if (provider !== this.defaultProvider && provider.write) {
|
|
283
|
+
return provider.write(pathStr, content);
|
|
284
|
+
}
|
|
285
|
+
errorStack_js_1.errorStack.stack_push("error", `File write not supported for path: ${pathStr}`);
|
|
286
|
+
return false;
|
|
287
|
+
}
|
|
288
|
+
/**
|
|
289
|
+
* Dispatches binary file read operation to the matched provider.
|
|
290
|
+
*
|
|
291
|
+
* @param pathStr - The absolute virtual path of the file to read.
|
|
292
|
+
* @returns A Promise resolving to a Result containing the file contents as a Buffer.
|
|
293
|
+
*/
|
|
294
|
+
async readBinary(pathStr) {
|
|
295
|
+
const provider = this.provider_get(pathStr);
|
|
296
|
+
if (provider !== this.defaultProvider && provider.readBinary) {
|
|
297
|
+
return provider.readBinary(pathStr);
|
|
298
|
+
}
|
|
299
|
+
errorStack_js_1.errorStack.stack_push("error", `Binary file read not supported for path: ${pathStr}`);
|
|
300
|
+
return (0, result_js_1.Err)();
|
|
301
|
+
}
|
|
302
|
+
/**
|
|
303
|
+
* Resolves a lazy link through the provider that owns it.
|
|
304
|
+
*
|
|
305
|
+
* This is deliberately distinct from {@link list}: a structural traversal
|
|
306
|
+
* can display an unresolved link without causing its provider to fetch the
|
|
307
|
+
* target from a remote service.
|
|
308
|
+
*
|
|
309
|
+
* @param pathStr - Absolute path of the provider-defined link.
|
|
310
|
+
* @returns The resolved target path, or an error if unsupported or absent.
|
|
311
|
+
*/
|
|
312
|
+
async linkTarget_resolve(pathStr) {
|
|
313
|
+
const provider = this.provider_get(pathStr);
|
|
314
|
+
if (provider.linkTarget_resolve) {
|
|
315
|
+
return provider.linkTarget_resolve(pathStr);
|
|
316
|
+
}
|
|
317
|
+
errorStack_js_1.errorStack.stack_push('error', `Link resolution not supported for path: ${pathStr}`);
|
|
318
|
+
return (0, result_js_1.Err)();
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
exports.VFSDispatcher = VFSDispatcher;
|
|
322
|
+
//# sourceMappingURL=dispatcher.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dispatcher.js","sourceRoot":"","sources":["../../src/vfs/dispatcher.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file The virtual filesystem's contracts: a mount (provider), the items it
|
|
3
|
+
* lists, and the options a copy takes.
|
|
4
|
+
*
|
|
5
|
+
* A session's filesystem is a tree of mounts. Each provider claims a path
|
|
6
|
+
* prefix and answers for everything at or under it; whatever no provider
|
|
7
|
+
* claims goes to the dispatcher's fallback (see `dispatcher.ts`).
|
|
8
|
+
*
|
|
9
|
+
* @module
|
|
10
|
+
*/
|
|
11
|
+
import { Result } from "../result.js";
|
|
12
|
+
/**
|
|
13
|
+
* Standard interface representing a virtual file system item.
|
|
14
|
+
*/
|
|
15
|
+
export interface VFSItem {
|
|
16
|
+
/** The display name of the item. */
|
|
17
|
+
name: string;
|
|
18
|
+
/**
|
|
19
|
+
* What the item is: `dir`, `file`, `link` or `vfs` (a mount), or a kind a
|
|
20
|
+
* backend lists beside them. An open string: a consumer handles the kinds it
|
|
21
|
+
* knows and treats any other as a plain entry.
|
|
22
|
+
*/
|
|
23
|
+
type: string;
|
|
24
|
+
/** Size in bytes. */
|
|
25
|
+
size: number;
|
|
26
|
+
/** Username of the owner. */
|
|
27
|
+
owner: string;
|
|
28
|
+
/** Creation date (ISO string). */
|
|
29
|
+
date: string;
|
|
30
|
+
/** Target path (for links). */
|
|
31
|
+
target?: string;
|
|
32
|
+
/** Version string (for plugins). */
|
|
33
|
+
version?: string;
|
|
34
|
+
/** Title or description, when the item has one. */
|
|
35
|
+
title?: string;
|
|
36
|
+
/** Backing resource ID, when the virtual entry represents one. */
|
|
37
|
+
id?: number;
|
|
38
|
+
/** Execution status (for job type items). */
|
|
39
|
+
status?: string;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Options for VFS copy operations.
|
|
43
|
+
*/
|
|
44
|
+
export interface CpOptions {
|
|
45
|
+
/** Recursively copy subdirectories. */
|
|
46
|
+
recursive?: boolean;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Base contract that every Virtual File System Provider must implement.
|
|
50
|
+
*/
|
|
51
|
+
export interface VFSProvider {
|
|
52
|
+
/** The path prefix this provider matches (e.g. '/net/pacs', '/bin'); empty for a fallback. */
|
|
53
|
+
prefix: string;
|
|
54
|
+
/**
|
|
55
|
+
* Lists the contents of a directory matching this provider.
|
|
56
|
+
*
|
|
57
|
+
* @param path - The absolute virtual directory path.
|
|
58
|
+
* @param options - Optional sorting controls.
|
|
59
|
+
* @returns A Promise resolving to a Result containing VFSItems.
|
|
60
|
+
*/
|
|
61
|
+
list(path: string, options?: {
|
|
62
|
+
sort?: "name" | "size" | "date" | "owner";
|
|
63
|
+
reverse?: boolean;
|
|
64
|
+
}): Promise<Result<VFSItem[]>>;
|
|
65
|
+
/**
|
|
66
|
+
* Copies files or folders from/to paths under this provider.
|
|
67
|
+
*
|
|
68
|
+
* @param src - The absolute source path.
|
|
69
|
+
* @param dest - The absolute destination path.
|
|
70
|
+
* @param options - Copy flags like recursive.
|
|
71
|
+
* @returns A Promise resolving to true on successful copy execution.
|
|
72
|
+
*/
|
|
73
|
+
cp(src: string, dest: string, options: CpOptions): Promise<boolean>;
|
|
74
|
+
/**
|
|
75
|
+
* Reads the content of a virtual file under this provider as a string.
|
|
76
|
+
*
|
|
77
|
+
* @param path - The absolute virtual path of the file to read.
|
|
78
|
+
* @returns A Promise resolving to a Result containing the file contents as a string.
|
|
79
|
+
*/
|
|
80
|
+
read?(path: string): Promise<Result<string>>;
|
|
81
|
+
/**
|
|
82
|
+
* Reads the content of a virtual file under this provider as a binary Buffer.
|
|
83
|
+
*
|
|
84
|
+
* @param path - The absolute virtual path of the file to read.
|
|
85
|
+
* @returns A Promise resolving to a Result containing the file contents as a Buffer.
|
|
86
|
+
*/
|
|
87
|
+
readBinary?(path: string): Promise<Result<Buffer>>;
|
|
88
|
+
/**
|
|
89
|
+
* Writes a file whole, when the provider holds writable files (a note).
|
|
90
|
+
* Absent or false, the path is read-only.
|
|
91
|
+
*
|
|
92
|
+
* @param path - The absolute path of the file.
|
|
93
|
+
* @param content - The new content, whole.
|
|
94
|
+
* @returns True when it was written.
|
|
95
|
+
*/
|
|
96
|
+
write?(path: string, content: string): Promise<boolean>;
|
|
97
|
+
/**
|
|
98
|
+
* Makes a folder, when the provider's folders are things a user makes (a
|
|
99
|
+
* tag). Absent, the provider is read-only for mkdir.
|
|
100
|
+
* @param path - The absolute path of the new folder.
|
|
101
|
+
* @returns True when made; false with the reason stacked.
|
|
102
|
+
*/
|
|
103
|
+
mkdir?(path: string): Promise<boolean>;
|
|
104
|
+
/**
|
|
105
|
+
* Removes an empty folder (`rmdir`).
|
|
106
|
+
* @param path - The absolute path of the folder.
|
|
107
|
+
* @returns True when removed; false with the reason stacked.
|
|
108
|
+
*/
|
|
109
|
+
rmdir?(path: string): Promise<boolean>;
|
|
110
|
+
/**
|
|
111
|
+
* Renames an entry within this provider (`mv`).
|
|
112
|
+
* @param src - The absolute path now.
|
|
113
|
+
* @param dest - The absolute path it takes.
|
|
114
|
+
* @returns True when renamed; false with the reason stacked.
|
|
115
|
+
*/
|
|
116
|
+
rename?(src: string, dest: string): Promise<boolean>;
|
|
117
|
+
/**
|
|
118
|
+
* Resolves the target of a provider-defined lazy link when an operation
|
|
119
|
+
* actually follows it.
|
|
120
|
+
*
|
|
121
|
+
* Listings must not use this hook: providers may expose an unresolved link
|
|
122
|
+
* as structural metadata without paying for its target until navigation.
|
|
123
|
+
*
|
|
124
|
+
* @param path - Absolute virtual path naming the link.
|
|
125
|
+
* @returns The target path, or an error when the provider cannot resolve it.
|
|
126
|
+
*/
|
|
127
|
+
linkTarget_resolve?(path: string): Promise<Result<string>>;
|
|
128
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* @file The virtual filesystem's contracts: a mount (provider), the items it
|
|
4
|
+
* lists, and the options a copy takes.
|
|
5
|
+
*
|
|
6
|
+
* A session's filesystem is a tree of mounts. Each provider claims a path
|
|
7
|
+
* prefix and answers for everything at or under it; whatever no provider
|
|
8
|
+
* claims goes to the dispatcher's fallback (see `dispatcher.ts`).
|
|
9
|
+
*
|
|
10
|
+
* @module
|
|
11
|
+
*/
|
|
12
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
13
|
+
//# sourceMappingURL=provider.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"provider.js","sourceRoot":"","sources":["../../src/vfs/provider.ts"],"names":[],"mappings":";AAAA;;;;;;;;;GASG"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file Sorting a listing's items by a field, without changing the array given.
|
|
3
|
+
*
|
|
4
|
+
* @module
|
|
5
|
+
*/
|
|
6
|
+
import { VFSItem } from './provider.js';
|
|
7
|
+
/**
|
|
8
|
+
* Sorts VFS items by a field (name/size/date/owner), non-destructively.
|
|
9
|
+
*
|
|
10
|
+
* Strings are compared with localeCompare, numbers numerically; mismatched or
|
|
11
|
+
* unsupported types are left in their original relative order.
|
|
12
|
+
*
|
|
13
|
+
* @param items - Items to sort.
|
|
14
|
+
* @param sortField - Field to sort by (default 'name').
|
|
15
|
+
* @param reverse - Whether to reverse the resulting order.
|
|
16
|
+
* @returns A new sorted array.
|
|
17
|
+
*/
|
|
18
|
+
export declare function vfsItems_sort(items: VFSItem[], sortField?: 'name' | 'size' | 'date' | 'owner', reverse?: boolean): VFSItem[];
|
package/dist/vfs/sort.js
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.vfsItems_sort = vfsItems_sort;
|
|
4
|
+
/**
|
|
5
|
+
* Sorts VFS items by a field (name/size/date/owner), non-destructively.
|
|
6
|
+
*
|
|
7
|
+
* Strings are compared with localeCompare, numbers numerically; mismatched or
|
|
8
|
+
* unsupported types are left in their original relative order.
|
|
9
|
+
*
|
|
10
|
+
* @param items - Items to sort.
|
|
11
|
+
* @param sortField - Field to sort by (default 'name').
|
|
12
|
+
* @param reverse - Whether to reverse the resulting order.
|
|
13
|
+
* @returns A new sorted array.
|
|
14
|
+
*/
|
|
15
|
+
function vfsItems_sort(items, sortField, reverse) {
|
|
16
|
+
const field = sortField || 'name';
|
|
17
|
+
const sorted = [...items].sort((a, b) => {
|
|
18
|
+
const valA = a[field];
|
|
19
|
+
const valB = b[field];
|
|
20
|
+
if (typeof valA === 'string' && typeof valB === 'string') {
|
|
21
|
+
return valA.localeCompare(valB);
|
|
22
|
+
}
|
|
23
|
+
if (typeof valA === 'number' && typeof valB === 'number') {
|
|
24
|
+
return valA - valB;
|
|
25
|
+
}
|
|
26
|
+
return 0;
|
|
27
|
+
});
|
|
28
|
+
if (reverse) {
|
|
29
|
+
sorted.reverse();
|
|
30
|
+
}
|
|
31
|
+
return sorted;
|
|
32
|
+
}
|
|
33
|
+
//# sourceMappingURL=sort.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sort.js","sourceRoot":"","sources":["../../src/vfs/sort.ts"],"names":[],"mappings":";;AAkBA,sCAqBC;AAhCD;;;;;;;;;;GAUG;AACH,SAAgB,aAAa,CAC3B,KAAgB,EAChB,SAA8C,EAC9C,OAAiB;IAEjB,MAAM,KAAK,GAAkB,SAAS,IAAI,MAAM,CAAC;IACjD,MAAM,MAAM,GAAc,CAAC,GAAG,KAAK,CAAC,CAAC,IAAI,CAAC,CAAC,CAAU,EAAE,CAAU,EAAE,EAAE;QACnE,MAAM,IAAI,GAA2B,CAAC,CAAC,KAAK,CAAC,CAAC;QAC9C,MAAM,IAAI,GAA2B,CAAC,CAAC,KAAK,CAAC,CAAC;QAC9C,IAAI,OAAO,IAAI,KAAK,QAAQ,IAAI,OAAO,IAAI,KAAK,QAAQ,EAAE,CAAC;YACzD,OAAO,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC;QAClC,CAAC;QACD,IAAI,OAAO,IAAI,KAAK,QAAQ,IAAI,OAAO,IAAI,KAAK,QAAQ,EAAE,CAAC;YACzD,OAAO,IAAI,GAAG,IAAI,CAAC;QACrB,CAAC;QACD,OAAO,CAAC,CAAC;IACX,CAAC,CAAC,CAAC;IACH,IAAI,OAAO,EAAE,CAAC;QACZ,MAAM,CAAC,OAAO,EAAE,CAAC;IACnB,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC"}
|