dsh-remote-vs 0.0.0-stage → 0.8.3
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/LICENSE +21 -0
- package/README.en.md +385 -0
- package/README.md +347 -2
- package/cordis.patch.yml +259 -0
- package/icon.svg +7 -0
- package/lib/client.js +62602 -0
- package/lib/index.js +4287 -0
- package/lib/p2-bridge-refs.js +10 -0
- package/lib/p2-bridge.js +16 -0
- package/lib/p2-router-fs.js +252 -0
- package/lib/p2-router-refs.js +466 -0
- package/lib/p2-router-spill.js +62 -0
- package/lib/p2-router-subprocess.js +64 -0
- package/lib/p2-shell-bash.js +24 -0
- package/lib/ssh-proc-arI5lm4W.js +632 -0
- package/lib/types/changes/recorder.d.ts +240 -0
- package/lib/types/changes/status.d.ts +201 -0
- package/lib/types/changes/text-diff.d.ts +65 -0
- package/lib/types/client/CodeEditor.d.ts +125 -0
- package/lib/types/client/Dialog.d.ts +14 -0
- package/lib/types/client/DirectoryFlow.d.ts +30 -0
- package/lib/types/client/EditorPane.d.ts +30 -0
- package/lib/types/client/HostsView.d.ts +10 -0
- package/lib/types/client/NativeExplorer.d.ts +39 -0
- package/lib/types/client/RemoteDirectoryPicker.d.ts +16 -0
- package/lib/types/client/RemoteEditorView.d.ts +20 -0
- package/lib/types/client/RemoteExplorer.d.ts +18 -0
- package/lib/types/client/RemoteRoot.d.ts +16 -0
- package/lib/types/client/SearchView.d.ts +14 -0
- package/lib/types/client/SettingsHosts.d.ts +15 -0
- package/lib/types/client/TerminalView.d.ts +16 -0
- package/lib/types/client/WorkspaceWizard.d.ts +16 -0
- package/lib/types/client/WorkspacesView.d.ts +14 -0
- package/lib/types/client/XTerm.d.ts +15 -0
- package/lib/types/client/api.d.ts +162 -0
- package/lib/types/client/changes/ChangesDock.d.ts +35 -0
- package/lib/types/client/changes/model.d.ts +36 -0
- package/lib/types/client/changes/undo-affordance.d.ts +48 -0
- package/lib/types/client/changes/undo-context.d.ts +25 -0
- package/lib/types/client/composer.d.ts +165 -0
- package/lib/types/client/i18n.d.ts +17 -0
- package/lib/types/client/index.d.ts +14 -0
- package/lib/types/client/remote-file-open-target.d.ts +247 -0
- package/lib/types/client/remote-file-open.d.ts +35 -0
- package/lib/types/client/reveal.d.ts +15 -0
- package/lib/types/client/scm/DiffView.d.ts +24 -0
- package/lib/types/client/scm/HistoryPanel.d.ts +12 -0
- package/lib/types/client/scm/RepoPicker.d.ts +24 -0
- package/lib/types/client/scm/ScmPanel.d.ts +15 -0
- package/lib/types/client/scm/actions.d.ts +170 -0
- package/lib/types/client/scm/diff-model.d.ts +29 -0
- package/lib/types/client/scm/stage-queue.d.ts +99 -0
- package/lib/types/client/scm/status-map.d.ts +157 -0
- package/lib/types/client/scm/untracked-dirs.d.ts +72 -0
- package/lib/types/client/selection-popup.d.ts +61 -0
- package/lib/types/client/store.d.ts +437 -0
- package/lib/types/client/theme.d.ts +15 -0
- package/lib/types/client/ui.d.ts +46 -0
- package/lib/types/client/upload-plan.d.ts +78 -0
- package/lib/types/client/upload-source.d.ts +46 -0
- package/lib/types/client/use-remote-chat-target.d.ts +17 -0
- package/lib/types/client/vsc/FindWidget.d.ts +81 -0
- package/lib/types/client/vsc/change-marks.d.ts +150 -0
- package/lib/types/client/vsc/editor-langs.d.ts +5 -0
- package/lib/types/client/vsc/editor-palette.d.ts +37 -0
- package/lib/types/client/vsc/editor-theme.d.ts +32 -0
- package/lib/types/client/vsc/fallback-highlight.d.ts +26 -0
- package/lib/types/client/vsc/kit.d.ts +195 -0
- package/lib/types/client/vsc/markdown.d.ts +11 -0
- package/lib/types/client/vsc/reveal-line.d.ts +38 -0
- package/lib/types/client/vsc/tokenize.d.ts +104 -0
- package/lib/types/deploy.d.ts +94 -0
- package/lib/types/fs-ops.d.ts +8 -0
- package/lib/types/git-format.d.ts +34 -0
- package/lib/types/git-ops.d.ts +183 -0
- package/lib/types/http.d.ts +14 -0
- package/lib/types/importers.d.ts +20 -0
- package/lib/types/index.d.ts +87 -0
- package/lib/types/keygen.d.ts +19 -0
- package/lib/types/loopback.d.ts +7 -0
- package/lib/types/p2/bridge-refs.d.ts +21 -0
- package/lib/types/p2/bridge.d.ts +24 -0
- package/lib/types/p2/file-refs.d.ts +73 -0
- package/lib/types/p2/helper-rpc.d.ts +63 -0
- package/lib/types/p2/in-flight-gate.d.ts +25 -0
- package/lib/types/p2/router-fs.d.ts +92 -0
- package/lib/types/p2/router-refs.d.ts +45 -0
- package/lib/types/p2/router-spill.d.ts +11 -0
- package/lib/types/p2/router-subprocess.d.ts +23 -0
- package/lib/types/p2/shell-bash.d.ts +16 -0
- package/lib/types/p2/ssh-proc.d.ts +22 -0
- package/lib/types/p2/worlds.d.ts +179 -0
- package/lib/types/paths.d.ts +12 -0
- package/lib/types/pool.d.ts +105 -0
- package/lib/types/protocol.d.ts +452 -0
- package/lib/types/routes.d.ts +27 -0
- package/lib/types/search-ops.d.ts +68 -0
- package/lib/types/sftp.d.ts +90 -0
- package/lib/types/store.d.ts +66 -0
- package/lib/types/terminal.d.ts +51 -0
- package/lib/types/timeouts.d.ts +83 -0
- package/lib/types/tools.d.ts +41 -0
- package/lib/worlds-PUumRIh7.js +18765 -0
- package/locale/en.json +6 -0
- package/locale/zh.json +6 -0
- package/package.json +189 -4
- package/src/changes/recorder.ts +902 -0
- package/src/changes/status.ts +448 -0
- package/src/changes/text-diff.ts +377 -0
- package/src/client/CodeEditor.tsx +923 -0
- package/src/client/Dialog.tsx +76 -0
- package/src/client/DirectoryFlow.tsx +431 -0
- package/src/client/EditorPane.tsx +512 -0
- package/src/client/HostsView.tsx +312 -0
- package/src/client/NativeExplorer.tsx +121 -0
- package/src/client/RemoteDirectoryPicker.tsx +157 -0
- package/src/client/RemoteEditorView.tsx +54 -0
- package/src/client/RemoteExplorer.tsx +1398 -0
- package/src/client/RemoteRoot.tsx +389 -0
- package/src/client/SearchView.tsx +407 -0
- package/src/client/SettingsHosts.tsx +136 -0
- package/src/client/TerminalView.tsx +308 -0
- package/src/client/WorkspaceWizard.tsx +199 -0
- package/src/client/WorkspacesView.tsx +93 -0
- package/src/client/XTerm.tsx +308 -0
- package/src/client/api.ts +331 -0
- package/src/client/changes/ChangesDock.tsx +348 -0
- package/src/client/changes/changes.css +230 -0
- package/src/client/changes/model.ts +347 -0
- package/src/client/changes/undo-affordance.ts +389 -0
- package/src/client/changes/undo-context.ts +34 -0
- package/src/client/composer.ts +436 -0
- package/src/client/css.d.ts +7 -0
- package/src/client/i18n.ts +702 -0
- package/src/client/index.tsx +286 -0
- package/src/client/remote-file-open-target.ts +553 -0
- package/src/client/remote-file-open.ts +261 -0
- package/src/client/reveal.ts +33 -0
- package/src/client/scm/DiffView.tsx +570 -0
- package/src/client/scm/HistoryPanel.tsx +353 -0
- package/src/client/scm/RepoPicker.tsx +238 -0
- package/src/client/scm/ScmPanel.tsx +857 -0
- package/src/client/scm/actions.ts +460 -0
- package/src/client/scm/diff-model.ts +206 -0
- package/src/client/scm/stage-queue.ts +264 -0
- package/src/client/scm/status-map.ts +381 -0
- package/src/client/scm/untracked-dirs.ts +139 -0
- package/src/client/selection-popup.ts +157 -0
- package/src/client/store.tsx +1670 -0
- package/src/client/theme.ts +54 -0
- package/src/client/ui.tsx +136 -0
- package/src/client/upload-plan.ts +153 -0
- package/src/client/upload-source.ts +145 -0
- package/src/client/use-remote-chat-target.ts +153 -0
- package/src/client/vsc/FindWidget.tsx +446 -0
- package/src/client/vsc/change-marks.ts +586 -0
- package/src/client/vsc/editor-langs.ts +137 -0
- package/src/client/vsc/editor-palette.ts +107 -0
- package/src/client/vsc/editor-theme.ts +93 -0
- package/src/client/vsc/fallback-highlight.ts +145 -0
- package/src/client/vsc/kit.tsx +777 -0
- package/src/client/vsc/markdown.tsx +172 -0
- package/src/client/vsc/reveal-line.ts +142 -0
- package/src/client/vsc/tokenize.ts +569 -0
- package/src/client/vsc/vsc.css +2669 -0
- package/src/deploy.ts +481 -0
- package/src/fs-ops.ts +57 -0
- package/src/git-format.ts +205 -0
- package/src/git-ops.ts +693 -0
- package/src/http.ts +55 -0
- package/src/importers.ts +141 -0
- package/src/index.ts +442 -0
- package/src/keygen.ts +77 -0
- package/src/loopback.ts +47 -0
- package/src/p2/bridge-refs.ts +27 -0
- package/src/p2/bridge.ts +32 -0
- package/src/p2/file-refs.ts +392 -0
- package/src/p2/helper-rpc.ts +394 -0
- package/src/p2/in-flight-gate.ts +63 -0
- package/src/p2/router-fs.ts +327 -0
- package/src/p2/router-refs.ts +166 -0
- package/src/p2/router-spill.ts +75 -0
- package/src/p2/router-subprocess.ts +92 -0
- package/src/p2/shell-bash.ts +30 -0
- package/src/p2/ssh-proc.ts +802 -0
- package/src/p2/worlds.ts +735 -0
- package/src/paths.ts +50 -0
- package/src/pool.ts +811 -0
- package/src/protocol.ts +460 -0
- package/src/routes.ts +802 -0
- package/src/search-ops.ts +220 -0
- package/src/sftp.ts +677 -0
- package/src/store.ts +364 -0
- package/src/terminal.ts +291 -0
- package/src/timeouts.ts +122 -0
- package/src/tools.ts +320 -0
- package/vendor/dsh-remote-helpers/dsh-ssh-helper-0.2.1-alpha.2-linux-x64.helper.json +16 -0
- package/vendor/dsh-remote-helpers/dsh-ssh-helper-0.2.1-alpha.2-linux-x64.tar.gz +4 -0
- package/vendor/dsh-remote-helpers/dsh-ssh-helper-0.2.1-alpha.2-linux-x64.tar.gz.sha256 +1 -0
- package/vendor/dsh-remote-helpers/glibc-ceiling.patch +31 -0
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
//#region src/p2/bridge-refs.ts
|
|
2
|
+
/** Stable cordis plugin name. */
|
|
3
|
+
const name = "dsh-remote-vs-p2-bridge-refs";
|
|
4
|
+
const inject = ["fileReferences"];
|
|
5
|
+
/** Publish the isolated local file-reference provider. */
|
|
6
|
+
function apply(ctx) {
|
|
7
|
+
ctx.provide("localFileReferences", ctx.fileReferences);
|
|
8
|
+
}
|
|
9
|
+
//#endregion
|
|
10
|
+
export { apply, inject, name };
|
package/lib/p2-bridge.js
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
//#region src/p2/bridge.ts
|
|
2
|
+
/** Stable cordis plugin name. */
|
|
3
|
+
const name = "dsh-remote-vs-p2-bridge";
|
|
4
|
+
const inject = [
|
|
5
|
+
"fs",
|
|
6
|
+
"subprocess",
|
|
7
|
+
"spillStore"
|
|
8
|
+
];
|
|
9
|
+
/** Publish isolated local providers without changing their implementation. */
|
|
10
|
+
function apply(ctx) {
|
|
11
|
+
ctx.provide("localFs", ctx.fs);
|
|
12
|
+
ctx.provide("localSpillStore", ctx.spillStore);
|
|
13
|
+
ctx.provide("localSubprocess", ctx.subprocess);
|
|
14
|
+
}
|
|
15
|
+
//#endregion
|
|
16
|
+
export { apply, inject, name };
|
|
@@ -0,0 +1,252 @@
|
|
|
1
|
+
import { l as aliasRoot, n as isWindowsAbsolute } from "./worlds-PUumRIh7.js";
|
|
2
|
+
import { FileSystem, FsError } from "@deepseek-ai/dsh-fs";
|
|
3
|
+
//#region src/p2/router-fs.ts
|
|
4
|
+
/**
|
|
5
|
+
* Transparent filesystem router: cwd/path-keyed delegation between the local
|
|
6
|
+
* backend (private realm) and per-host helper fs views. Targets are tracked
|
|
7
|
+
* in a WeakMap (never mutated — the helper's strict schemas would reject
|
|
8
|
+
* extra fields); unknown targets fail closed.
|
|
9
|
+
*/
|
|
10
|
+
var TransparentFileSystem = class extends FileSystem {
|
|
11
|
+
static inject = ["localFs", "remoteWorlds"];
|
|
12
|
+
/** Target identity -> owning world (full route for policy rewrites). */
|
|
13
|
+
worlds = /* @__PURE__ */ new WeakMap();
|
|
14
|
+
/**
|
|
15
|
+
* Hint for a target that was deliberately routed local from a remote session.
|
|
16
|
+
*
|
|
17
|
+
* The read tool observes absence through stat, which only ever receives the
|
|
18
|
+
* resolved target — the original path and cwd are gone by then. So the note is
|
|
19
|
+
* computed once, at resolve time, and carried on the target itself.
|
|
20
|
+
*/
|
|
21
|
+
missNotes = /* @__PURE__ */ new WeakMap();
|
|
22
|
+
get localFs() {
|
|
23
|
+
return this.ctx.localFs;
|
|
24
|
+
}
|
|
25
|
+
get remote() {
|
|
26
|
+
return this.ctx.remoteWorlds;
|
|
27
|
+
}
|
|
28
|
+
get sandboxMode() {
|
|
29
|
+
return this.localFs.sandboxMode;
|
|
30
|
+
}
|
|
31
|
+
effective(route, what) {
|
|
32
|
+
const mode = this.remote.mode;
|
|
33
|
+
if (mode === "off") return { kind: "local" };
|
|
34
|
+
if (mode === "shadow") {
|
|
35
|
+
this.remote.note(route, what);
|
|
36
|
+
return { kind: "local" };
|
|
37
|
+
}
|
|
38
|
+
return route;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* True when the path sits under the alias root — the only place a remote
|
|
42
|
+
* binding or a tombstone can live (every alias dir is `join(aliasRoot(), id)`,
|
|
43
|
+
* and `store.removeWorkspace` tombstones the same way), so it is exactly the
|
|
44
|
+
* input set whose route is not trivially local.
|
|
45
|
+
*/
|
|
46
|
+
underAliasRoot(path) {
|
|
47
|
+
return path !== void 0 && this.remote.underAlias(aliasRoot(), path);
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Mode-gated route for one call. `off` discards the route anyway (see
|
|
51
|
+
* `effective`), so computing it first — the argument-first idiom this used to
|
|
52
|
+
* have — was pure waste on the root fs path. Only an alias-root cwd or path
|
|
53
|
+
* can name a remote world, or a tombstoned one, and a tombstone must keep
|
|
54
|
+
* failing closed (`worlds.routePath` throws), so that case still resolves;
|
|
55
|
+
* everything else is local without touching the store. `enforce`/`shadow`
|
|
56
|
+
* take the exact path they took before.
|
|
57
|
+
*/
|
|
58
|
+
routeFor(path, cwd, what) {
|
|
59
|
+
if (this.remote.mode === "off" && !this.underAliasRoot(path) && !this.underAliasRoot(cwd)) return { kind: "local" };
|
|
60
|
+
return this.effective(this.remote.routePath(path, cwd), what);
|
|
61
|
+
}
|
|
62
|
+
async backendOf(target) {
|
|
63
|
+
const world = this.worlds.get(target);
|
|
64
|
+
if (world === void 0) throw new FsError("unknown target world (not resolved through this router)", "FS_IO_ERROR");
|
|
65
|
+
if (world.kind === "local") return {
|
|
66
|
+
fs: this.localFs,
|
|
67
|
+
world
|
|
68
|
+
};
|
|
69
|
+
return {
|
|
70
|
+
fs: await this.remote.fsFor(world.alias),
|
|
71
|
+
world
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
/** Translate call cwd into the routed world (alias -> remote, else drop). */
|
|
75
|
+
routeOpts(route, opts) {
|
|
76
|
+
if (route.kind === "local" || opts?.cwd === void 0) return opts;
|
|
77
|
+
const remoteCwd = this.cwdToRemote(route, opts.cwd);
|
|
78
|
+
if (remoteCwd === void 0) {
|
|
79
|
+
const { signal } = opts;
|
|
80
|
+
return signal === void 0 ? void 0 : { signal };
|
|
81
|
+
}
|
|
82
|
+
return {
|
|
83
|
+
...opts,
|
|
84
|
+
cwd: remoteCwd
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
cwdToRemote(route, cwd) {
|
|
88
|
+
try {
|
|
89
|
+
const check = this.remote.routeDir(cwd);
|
|
90
|
+
if (check.kind === "remote" && check.id === route.id) return this.remote.toRemotePath(route, cwd);
|
|
91
|
+
return;
|
|
92
|
+
} catch {
|
|
93
|
+
return;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Translate the call path into the routed world: alias-contained paths map
|
|
98
|
+
* to remote absolutes; already-remote absolutes and relatives (resolved
|
|
99
|
+
* against the translated cwd) pass through.
|
|
100
|
+
*/
|
|
101
|
+
routePathFor(route, path) {
|
|
102
|
+
if (route.kind !== "local" && this.remote.underAlias(route.aliasPath, path)) return this.remote.toRemotePath(route, path);
|
|
103
|
+
return path;
|
|
104
|
+
}
|
|
105
|
+
async resolve(path, opts) {
|
|
106
|
+
const route = this.routeFor(path, opts?.cwd, `resolve ${path}`);
|
|
107
|
+
const fs = route.kind === "local" ? this.localFs : await this.remote.fsFor(route.alias);
|
|
108
|
+
try {
|
|
109
|
+
const target = await fs.resolve(this.routePathFor(route, path), this.routeOpts(route, opts));
|
|
110
|
+
this.worlds.set(target, route);
|
|
111
|
+
const note = this.localMissNote(path, route, opts?.cwd);
|
|
112
|
+
if (note !== void 0) this.missNotes.set(target, note);
|
|
113
|
+
return target;
|
|
114
|
+
} catch (error) {
|
|
115
|
+
const note = this.localMissNote(path, route, opts?.cwd);
|
|
116
|
+
if (note === void 0) throw error;
|
|
117
|
+
const detail = error instanceof Error ? error.message : String(error);
|
|
118
|
+
const original = error?.code;
|
|
119
|
+
throw new FsError(`${detail}${note}`, original ?? "FS_IO_ERROR");
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* The explanatory suffix for the one genuinely confusing miss.
|
|
124
|
+
*
|
|
125
|
+
* `routePath` sends a Windows-absolute path outside the alias to the LOCAL
|
|
126
|
+
* world deliberately: a `C:\…` path can never name a remote file, and the tool
|
|
127
|
+
* seam's spill files genuinely live on the Host. But in a REMOTE session the
|
|
128
|
+
* likely mistake is that the caller wrote the remote path with a drive letter
|
|
129
|
+
* — `C:\opt\x` when it meant `/opt/x` — and a bare "not found" hides it.
|
|
130
|
+
* Naming both working forms is the difference between a guess and a fix.
|
|
131
|
+
*
|
|
132
|
+
* Returns undefined when nothing about this call is confusing, so callers can
|
|
133
|
+
* keep their normal behaviour untouched.
|
|
134
|
+
*/
|
|
135
|
+
localMissNote(path, route, cwd) {
|
|
136
|
+
if (route.kind !== "local") return void 0;
|
|
137
|
+
if (!isWindowsAbsolute(path)) return void 0;
|
|
138
|
+
if (cwd === void 0 || cwd.trim() === "") return void 0;
|
|
139
|
+
let remote;
|
|
140
|
+
try {
|
|
141
|
+
const byCwd = this.remote.routeDir(cwd);
|
|
142
|
+
if (byCwd.kind !== "remote") return void 0;
|
|
143
|
+
remote = byCwd;
|
|
144
|
+
} catch {
|
|
145
|
+
return;
|
|
146
|
+
}
|
|
147
|
+
const posix = `/${path.replace(/^[A-Za-z]:[\\/]/, "").split("\\").join("/")}`;
|
|
148
|
+
return ` — this session works in the remote workspace "${remote.remotePath}", and "${path}" is a Windows-absolute path outside that workspace's local alias, so it was looked up on the Host. If you meant the remote file, pass "${posix}" or a path relative to the workspace.`;
|
|
149
|
+
}
|
|
150
|
+
processPath(target) {
|
|
151
|
+
const world = this.worlds.get(target);
|
|
152
|
+
if (world === void 0) throw new FsError("unknown target world (not resolved through this router)", "FS_IO_ERROR");
|
|
153
|
+
if (world.kind === "local") return this.localFs.processPath(target);
|
|
154
|
+
const fs = this.remote.cachedFs(world.alias);
|
|
155
|
+
if (fs === void 0) throw new FsError(`remote fs view for ${world.alias} is not ready (resolve first)`, "FS_IO_ERROR");
|
|
156
|
+
return this.remote.toSessionPath(world, fs.processPath(target));
|
|
157
|
+
}
|
|
158
|
+
processPathFromHostPath(hostPath) {
|
|
159
|
+
try {
|
|
160
|
+
if (this.remote.routeDir(hostPath).kind !== "local") return void 0;
|
|
161
|
+
} catch {
|
|
162
|
+
return;
|
|
163
|
+
}
|
|
164
|
+
return this.localFs.processPathFromHostPath(hostPath);
|
|
165
|
+
}
|
|
166
|
+
fileUrl(target) {
|
|
167
|
+
const world = this.worlds.get(target);
|
|
168
|
+
if (world === void 0) throw new FsError("unknown target world (not resolved through this router)", "FS_IO_ERROR");
|
|
169
|
+
if (world.kind === "local") return this.localFs.fileUrl(target);
|
|
170
|
+
const fs = this.remote.cachedFs(world.alias);
|
|
171
|
+
if (fs === void 0) throw new FsError(`remote fs view for ${world.alias} is not ready (resolve first)`, "FS_IO_ERROR");
|
|
172
|
+
return fs.fileUrl(target);
|
|
173
|
+
}
|
|
174
|
+
contains(parent, child) {
|
|
175
|
+
const pw = this.worlds.get(parent);
|
|
176
|
+
const cw = this.worlds.get(child);
|
|
177
|
+
if (pw === void 0 || cw === void 0) return false;
|
|
178
|
+
if (pw.kind !== cw.kind) return false;
|
|
179
|
+
if (pw.kind === "local") return this.localFs.contains(parent, child);
|
|
180
|
+
if (pw.id !== cw.id) return false;
|
|
181
|
+
try {
|
|
182
|
+
const left = this.processPath(parent);
|
|
183
|
+
const right = this.processPath(child);
|
|
184
|
+
return right === left || right.startsWith(left.endsWith("/") ? left : `${left}/`);
|
|
185
|
+
} catch {
|
|
186
|
+
return false;
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
async stat(target, signal) {
|
|
190
|
+
const { fs } = await this.backendOf(target);
|
|
191
|
+
const info = await fs.stat(target, signal);
|
|
192
|
+
if (info === void 0) {
|
|
193
|
+
const note = this.missNotes.get(target);
|
|
194
|
+
if (note !== void 0) throw new FsError(`not found${note}`, "FS_NOT_FOUND");
|
|
195
|
+
}
|
|
196
|
+
return info;
|
|
197
|
+
}
|
|
198
|
+
async lstat(path, opts, signal) {
|
|
199
|
+
const route = this.routeFor(path, opts?.cwd, `lstat ${path}`);
|
|
200
|
+
const fs = route.kind === "local" ? this.localFs : await this.remote.fsFor(route.alias);
|
|
201
|
+
const routed = route.kind === "local" ? opts : this.routeOpts(route, opts);
|
|
202
|
+
try {
|
|
203
|
+
const info = await fs.lstat(this.routePathFor(route, path), routed, signal);
|
|
204
|
+
if (info === void 0) {
|
|
205
|
+
const note = this.localMissNote(path, route, opts?.cwd);
|
|
206
|
+
if (note !== void 0) throw new FsError(`not found${note}`, "FS_NOT_FOUND");
|
|
207
|
+
}
|
|
208
|
+
return info;
|
|
209
|
+
} catch (error) {
|
|
210
|
+
if (error instanceof FsError) throw error;
|
|
211
|
+
const note = this.localMissNote(path, route, opts?.cwd);
|
|
212
|
+
if (note === void 0) throw error;
|
|
213
|
+
throw new FsError(`${error instanceof Error ? error.message : String(error)}${note}`, "FS_IO_ERROR");
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
async readText(target, signal) {
|
|
217
|
+
const { fs } = await this.backendOf(target);
|
|
218
|
+
return fs.readText(target, signal);
|
|
219
|
+
}
|
|
220
|
+
async streamText(target, signal) {
|
|
221
|
+
const { fs } = await this.backendOf(target);
|
|
222
|
+
return fs.streamText(target, signal);
|
|
223
|
+
}
|
|
224
|
+
async readBytes(target, signal, maxBytes) {
|
|
225
|
+
const { fs } = await this.backendOf(target);
|
|
226
|
+
return fs.readBytes(target, signal, maxBytes);
|
|
227
|
+
}
|
|
228
|
+
async readByteRange(target, range, signal) {
|
|
229
|
+
const { fs } = await this.backendOf(target);
|
|
230
|
+
return fs.readByteRange(target, range, signal);
|
|
231
|
+
}
|
|
232
|
+
async listDir(target, signal) {
|
|
233
|
+
const { fs, world } = await this.backendOf(target);
|
|
234
|
+
const entries = await fs.listDir(target, signal);
|
|
235
|
+
for (const entry of entries) this.worlds.set(entry.target, world);
|
|
236
|
+
return entries;
|
|
237
|
+
}
|
|
238
|
+
async writeText(target, content, expected, signal, sandboxPolicy) {
|
|
239
|
+
const { fs, world } = await this.backendOf(target);
|
|
240
|
+
return fs.writeText(target, content, expected, signal, this.remote.rewritePolicy(sandboxPolicy, world));
|
|
241
|
+
}
|
|
242
|
+
async editText(target, edit, expected, signal, sandboxPolicy) {
|
|
243
|
+
const { fs, world } = await this.backendOf(target);
|
|
244
|
+
return fs.editText(target, edit, expected, signal, this.remote.rewritePolicy(sandboxPolicy, world));
|
|
245
|
+
}
|
|
246
|
+
async watch(target, changed, signal) {
|
|
247
|
+
const { fs } = await this.backendOf(target);
|
|
248
|
+
return fs.watch(target, changed, signal);
|
|
249
|
+
}
|
|
250
|
+
};
|
|
251
|
+
//#endregion
|
|
252
|
+
export { TransparentFileSystem as default };
|