opencode-readseek 0.6.8 → 0.6.10
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/index.ts +46 -2
- package/package.json +2 -2
package/index.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// SPDX-License-Identifier: Apache-2.0
|
|
2
2
|
// Copyright (C) Jarkko Sakkinen 2026
|
|
3
3
|
|
|
4
|
-
import { lstat, mkdir, readFile, realpath, stat, writeFile } from "node:fs/promises";
|
|
4
|
+
import { lstat, mkdir, readFile, readlink, realpath, stat, writeFile } from "node:fs/promises";
|
|
5
5
|
import { createRequire } from "node:module";
|
|
6
6
|
import path from "node:path";
|
|
7
7
|
|
|
@@ -116,12 +116,56 @@ function containsPath(directory: string, filePath: string): boolean {
|
|
|
116
116
|
return relative === "" || (!relative.startsWith(`..${path.sep}`) && relative !== ".." && !path.isAbsolute(relative));
|
|
117
117
|
}
|
|
118
118
|
|
|
119
|
+
async function resolveSymlinks(filePath: string): Promise<string> {
|
|
120
|
+
let unresolved = path.resolve(filePath);
|
|
121
|
+
let symlinks = 0;
|
|
122
|
+
|
|
123
|
+
while (true) {
|
|
124
|
+
const parsed = path.parse(unresolved);
|
|
125
|
+
const parts = unresolved.slice(parsed.root.length).split(path.sep).filter(Boolean);
|
|
126
|
+
let resolved = parsed.root;
|
|
127
|
+
let restart = false;
|
|
128
|
+
|
|
129
|
+
for (let index = 0; index < parts.length; index++) {
|
|
130
|
+
const candidate = path.join(resolved, parts[index]);
|
|
131
|
+
const info = await lstat(candidate);
|
|
132
|
+
if (!info.isSymbolicLink()) {
|
|
133
|
+
resolved = candidate;
|
|
134
|
+
continue;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
symlinks++;
|
|
138
|
+
if (symlinks > 40) {
|
|
139
|
+
const error = new Error(`too many symbolic links: ${filePath}`) as NodeJS.ErrnoException;
|
|
140
|
+
error.code = "ELOOP";
|
|
141
|
+
throw error;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
const target = await readlink(candidate);
|
|
145
|
+
unresolved = path.resolve(path.dirname(candidate), target, ...parts.slice(index + 1));
|
|
146
|
+
restart = true;
|
|
147
|
+
break;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
if (!restart) return resolved;
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
async function portableRealpath(filePath: string): Promise<string> {
|
|
155
|
+
try {
|
|
156
|
+
return await realpath(filePath);
|
|
157
|
+
} catch (error) {
|
|
158
|
+
if ((error as NodeJS.ErrnoException).code !== "EACCES") throw error;
|
|
159
|
+
return resolveSymlinks(filePath);
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
|
|
119
163
|
async function canonicalPath(filePath: string): Promise<string> {
|
|
120
164
|
const missing: string[] = [];
|
|
121
165
|
let existing = filePath;
|
|
122
166
|
while (true) {
|
|
123
167
|
try {
|
|
124
|
-
return path.join(await
|
|
168
|
+
return path.join(await portableRealpath(existing), ...missing.reverse());
|
|
125
169
|
} catch (error) {
|
|
126
170
|
if ((error as NodeJS.ErrnoException).code !== "ENOENT") throw error;
|
|
127
171
|
const parent = path.dirname(existing);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "opencode-readseek",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.10",
|
|
4
4
|
"description": "OpenCode plugin for readseek-backed structural code navigation",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./index.ts",
|
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
"node": ">=20.0.0"
|
|
31
31
|
},
|
|
32
32
|
"dependencies": {
|
|
33
|
-
"@jarkkojs/readseek": "^0.6.
|
|
33
|
+
"@jarkkojs/readseek": "^0.6.10",
|
|
34
34
|
"@opencode-ai/plugin": "^1.17.20"
|
|
35
35
|
},
|
|
36
36
|
"devDependencies": {
|