dsh-explorer 0.1.0 → 0.1.1
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/lib/client.js +817 -2772
- package/lib/index.js +124 -17
- package/package.json +1 -2
- package/src/client/ExplorerView.tsx +494 -652
- package/src/client/{ExplorerContextMenu.tsx → components/ExplorerContextMenu.tsx} +2 -4
- package/src/client/components/ExplorerDeleteModal.tsx +124 -0
- package/src/client/components/ExplorerEmptyContextMenu.tsx +125 -0
- package/src/client/{ExplorerHeader.tsx → components/ExplorerHeader.tsx} +18 -12
- package/src/client/{ExplorerOptionsModal.tsx → components/ExplorerOptionsModal.tsx} +2 -15
- package/src/client/{ExplorerRow.tsx → components/ExplorerRow.tsx} +45 -27
- package/src/client/{ExplorerSearch.tsx → components/ExplorerSearch.tsx} +18 -5
- package/src/client/components/TreeNode.tsx +384 -0
- package/src/client/explorer.module.css +215 -10
- package/src/client/hooks/useKeyboardNav.ts +89 -0
- package/src/client/hooks/useLiveSync.ts +81 -0
- package/src/client/index.tsx +82 -4
- package/src/client/{api.ts → utils/api.ts} +133 -3
- package/src/client/{conversation-draft.ts → utils/conversation-draft.ts} +38 -29
- package/src/client/utils/open-tab.ts +69 -0
- package/src/fs-search.ts +116 -0
- package/src/git-status.ts +19 -13
- package/src/index.ts +12 -0
- /package/src/client/{drag-drop.ts → utils/drag-drop.ts} +0 -0
- /package/src/client/{options.ts → utils/options.ts} +0 -0
- /package/src/client/{vscode-theme.tsx → utils/vscode-theme.tsx} +0 -0
package/src/git-status.ts
CHANGED
|
@@ -52,7 +52,6 @@ function parsePorcelainLines(stdout: string, prefix = ''): { branch?: string; en
|
|
|
52
52
|
if (p.startsWith('"') && p.endsWith('"')) {
|
|
53
53
|
p = p.slice(1, -1)
|
|
54
54
|
}
|
|
55
|
-
// Handle renamed files: "R old -> new"
|
|
56
55
|
if (xy.startsWith('R') || xy.endsWith('R')) {
|
|
57
56
|
const arrowIdx = p.indexOf(' -> ')
|
|
58
57
|
if (arrowIdx !== -1) {
|
|
@@ -62,8 +61,9 @@ function parsePorcelainLines(stdout: string, prefix = ''): { branch?: string; en
|
|
|
62
61
|
}
|
|
63
62
|
}
|
|
64
63
|
}
|
|
65
|
-
const cleanPath = p.replace(/\\/g, '/')
|
|
66
|
-
const
|
|
64
|
+
const cleanPath = p.replace(/\\/g, '/').replace(/^\.\//, '')
|
|
65
|
+
const cleanPrefix = prefix ? prefix.replace(/\\/g, '/').replace(/\/+$/, '').replace(/^\.\//, '') : ''
|
|
66
|
+
const finalPath = cleanPrefix ? `${cleanPrefix}/${cleanPath}` : cleanPath
|
|
67
67
|
entries.push({ path: finalPath, xy })
|
|
68
68
|
}
|
|
69
69
|
|
|
@@ -87,7 +87,6 @@ function findSubRepos(root: string, depth = 1, maxDepth = 3): string[] {
|
|
|
87
87
|
}
|
|
88
88
|
}
|
|
89
89
|
} catch {
|
|
90
|
-
// Ignore read errors
|
|
91
90
|
}
|
|
92
91
|
return repos
|
|
93
92
|
}
|
|
@@ -99,13 +98,23 @@ export async function getGitStatus(cwd: string): Promise<GitStatusResult> {
|
|
|
99
98
|
return cached.data
|
|
100
99
|
}
|
|
101
100
|
|
|
102
|
-
// 1. Try running git directly in cwd
|
|
103
101
|
try {
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
102
|
+
let stdout = ''
|
|
103
|
+
try {
|
|
104
|
+
const res = await execFileAsync(
|
|
105
|
+
'git',
|
|
106
|
+
['status', '--porcelain', '-b', '-unormal', '--ignored=matching'],
|
|
107
|
+
{ cwd, maxBuffer: 10 * 1024 * 1024, timeout: 3500 }
|
|
108
|
+
)
|
|
109
|
+
stdout = res.stdout
|
|
110
|
+
} catch {
|
|
111
|
+
const res = await execFileAsync(
|
|
112
|
+
'git',
|
|
113
|
+
['status', '--porcelain', '-b', '-unormal'],
|
|
114
|
+
{ cwd, maxBuffer: 10 * 1024 * 1024, timeout: 3500 }
|
|
115
|
+
)
|
|
116
|
+
stdout = res.stdout
|
|
117
|
+
}
|
|
109
118
|
|
|
110
119
|
const parsed = parsePorcelainLines(stdout)
|
|
111
120
|
const data: GitStatusResult = {
|
|
@@ -116,10 +125,8 @@ export async function getGitStatus(cwd: string): Promise<GitStatusResult> {
|
|
|
116
125
|
gitCache.set(cwd, { at: now, data })
|
|
117
126
|
return data
|
|
118
127
|
} catch {
|
|
119
|
-
// cwd is not a git repo or direct command failed. Check for nested/sub repositories.
|
|
120
128
|
}
|
|
121
129
|
|
|
122
|
-
// 2. Discover sub-repositories within cwd (for workspaces containing multiple repos)
|
|
123
130
|
try {
|
|
124
131
|
const subRepos = findSubRepos(cwd)
|
|
125
132
|
if (subRepos.length > 0) {
|
|
@@ -152,7 +159,6 @@ export async function getGitStatus(cwd: string): Promise<GitStatusResult> {
|
|
|
152
159
|
return data
|
|
153
160
|
}
|
|
154
161
|
} catch {
|
|
155
|
-
// Ignore
|
|
156
162
|
}
|
|
157
163
|
|
|
158
164
|
const fallback: GitStatusResult = { isRepo: false, entries: [] }
|
package/src/index.ts
CHANGED
|
@@ -3,6 +3,7 @@ import type { Duplex } from 'node:stream'
|
|
|
3
3
|
import { Config, type ExplorerConfig } from './config.ts'
|
|
4
4
|
import { createFsWatcherServer } from './fs-watch.ts'
|
|
5
5
|
import { listDirectory, listDirectoryBatch } from './fs-tree.ts'
|
|
6
|
+
import { searchDirectory } from './fs-search.ts'
|
|
6
7
|
import { createDirectory, createNewFile, readFileText, removeEntry, renameEntry, writeUpload } from './fs-operations.ts'
|
|
7
8
|
import { getGitStatus } from './git-status.ts'
|
|
8
9
|
import { resolveTarget } from './path-security.ts'
|
|
@@ -102,6 +103,17 @@ export function apply(ctx: Context, config?: ExplorerConfig): void {
|
|
|
102
103
|
return true
|
|
103
104
|
}
|
|
104
105
|
|
|
106
|
+
if (pathname === '/dsh-explorer/api/search') {
|
|
107
|
+
const sessionId = url.searchParams.get('sessionId') ?? undefined
|
|
108
|
+
const cwd = resolveSessionCwd(ctx, sessionId)
|
|
109
|
+
const dirParam = url.searchParams.get('dir')
|
|
110
|
+
const q = url.searchParams.get('q') ?? ''
|
|
111
|
+
const targetDir = resolveTarget(cwd, dirParam ?? cwd)
|
|
112
|
+
const result = await searchDirectory(targetDir, q)
|
|
113
|
+
writeOk(res, { result })
|
|
114
|
+
return true
|
|
115
|
+
}
|
|
116
|
+
|
|
105
117
|
if (pathname === '/dsh-explorer/api/read-file') {
|
|
106
118
|
const pathParam = url.searchParams.get('path')
|
|
107
119
|
if (!pathParam) {
|
|
File without changes
|
|
File without changes
|
|
File without changes
|