@axiom-lattice/core 3.1.1 → 3.1.2
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/dist/index.d.mts +4 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.js +54 -49
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +54 -49
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.d.mts
CHANGED
|
@@ -6527,6 +6527,8 @@ declare class FilesystemBackend implements BackendProtocol {
|
|
|
6527
6527
|
*/
|
|
6528
6528
|
private resolvePath;
|
|
6529
6529
|
private assertVirtualParentContained;
|
|
6530
|
+
private assertVirtualOpenedFileContained;
|
|
6531
|
+
private readFileBuffer;
|
|
6530
6532
|
private validateDeleteTarget;
|
|
6531
6533
|
/**
|
|
6532
6534
|
* List files and directories in the specified directory (non-recursive).
|
|
@@ -6552,6 +6554,8 @@ declare class FilesystemBackend implements BackendProtocol {
|
|
|
6552
6554
|
* @returns Raw file content as FileData
|
|
6553
6555
|
*/
|
|
6554
6556
|
readRaw(filePath: string): Promise<FileData>;
|
|
6557
|
+
/** Read file content as raw bytes without following symbolic links. */
|
|
6558
|
+
readBinary(filePath: string): Promise<Buffer>;
|
|
6555
6559
|
/**
|
|
6556
6560
|
* Create a new file with content.
|
|
6557
6561
|
* Returns WriteResult. External storage sets filesUpdate=null.
|
package/dist/index.d.ts
CHANGED
|
@@ -6527,6 +6527,8 @@ declare class FilesystemBackend implements BackendProtocol {
|
|
|
6527
6527
|
*/
|
|
6528
6528
|
private resolvePath;
|
|
6529
6529
|
private assertVirtualParentContained;
|
|
6530
|
+
private assertVirtualOpenedFileContained;
|
|
6531
|
+
private readFileBuffer;
|
|
6530
6532
|
private validateDeleteTarget;
|
|
6531
6533
|
/**
|
|
6532
6534
|
* List files and directories in the specified directory (non-recursive).
|
|
@@ -6552,6 +6554,8 @@ declare class FilesystemBackend implements BackendProtocol {
|
|
|
6552
6554
|
* @returns Raw file content as FileData
|
|
6553
6555
|
*/
|
|
6554
6556
|
readRaw(filePath: string): Promise<FileData>;
|
|
6557
|
+
/** Read file content as raw bytes without following symbolic links. */
|
|
6558
|
+
readBinary(filePath: string): Promise<Buffer>;
|
|
6555
6559
|
/**
|
|
6556
6560
|
* Create a new file with content.
|
|
6557
6561
|
* Returns WriteResult. External storage sets filesUpdate=null.
|
package/dist/index.js
CHANGED
|
@@ -18861,6 +18861,51 @@ var FilesystemBackend = class {
|
|
|
18861
18861
|
throw new Error(`Path: ${resolvedPath} outside root directory: ${this.cwd}`);
|
|
18862
18862
|
}
|
|
18863
18863
|
}
|
|
18864
|
+
async assertVirtualOpenedFileContained(resolvedPath, openedStat) {
|
|
18865
|
+
if (!this.virtualMode) {
|
|
18866
|
+
return;
|
|
18867
|
+
}
|
|
18868
|
+
const [rootPath, realFilePath] = await Promise.all([
|
|
18869
|
+
fs2.realpath(this.cwd),
|
|
18870
|
+
fs2.realpath(resolvedPath)
|
|
18871
|
+
]);
|
|
18872
|
+
const relative4 = path4.relative(rootPath, realFilePath);
|
|
18873
|
+
if (relative4 === ".." || relative4.startsWith(`..${path4.sep}`) || path4.isAbsolute(relative4)) {
|
|
18874
|
+
throw new Error(`Path: ${resolvedPath} outside root directory: ${this.cwd}`);
|
|
18875
|
+
}
|
|
18876
|
+
const realPathStat = await fs2.stat(realFilePath);
|
|
18877
|
+
if (realPathStat.dev !== openedStat.dev || realPathStat.ino !== openedStat.ino) {
|
|
18878
|
+
throw new Error(`File changed during secure read: ${resolvedPath}`);
|
|
18879
|
+
}
|
|
18880
|
+
}
|
|
18881
|
+
async readFileBuffer(filePath) {
|
|
18882
|
+
const resolvedPath = this.resolvePath(filePath);
|
|
18883
|
+
await this.assertVirtualParentContained(resolvedPath);
|
|
18884
|
+
if (!SUPPORTS_NOFOLLOW) {
|
|
18885
|
+
const initialStat = await fs2.lstat(resolvedPath);
|
|
18886
|
+
if (initialStat.isSymbolicLink()) {
|
|
18887
|
+
throw new Error(`Symlinks are not allowed: ${filePath}`);
|
|
18888
|
+
}
|
|
18889
|
+
}
|
|
18890
|
+
const flags = SUPPORTS_NOFOLLOW ? fsSync.constants.O_RDONLY | fsSync.constants.O_NOFOLLOW : fsSync.constants.O_RDONLY;
|
|
18891
|
+
const fd = await fs2.open(resolvedPath, flags);
|
|
18892
|
+
try {
|
|
18893
|
+
const stat4 = await fd.stat();
|
|
18894
|
+
if (!stat4.isFile()) {
|
|
18895
|
+
throw new Error(`File '${filePath}' not found`);
|
|
18896
|
+
}
|
|
18897
|
+
await this.assertVirtualOpenedFileContained(resolvedPath, stat4);
|
|
18898
|
+
if (!SUPPORTS_NOFOLLOW) {
|
|
18899
|
+
const finalStat = await fs2.lstat(resolvedPath);
|
|
18900
|
+
if (finalStat.isSymbolicLink() || finalStat.dev !== stat4.dev || finalStat.ino !== stat4.ino) {
|
|
18901
|
+
throw new Error(`File changed during secure read: ${resolvedPath}`);
|
|
18902
|
+
}
|
|
18903
|
+
}
|
|
18904
|
+
return { content: await fd.readFile(), stat: stat4 };
|
|
18905
|
+
} finally {
|
|
18906
|
+
await fd.close();
|
|
18907
|
+
}
|
|
18908
|
+
}
|
|
18864
18909
|
validateDeleteTarget(filePath, stat4) {
|
|
18865
18910
|
if (stat4.isSymbolicLink()) {
|
|
18866
18911
|
return `Error: Cannot delete '${filePath}': symlinks are not allowed`;
|
|
@@ -18960,32 +19005,8 @@ var FilesystemBackend = class {
|
|
|
18960
19005
|
*/
|
|
18961
19006
|
async read(filePath, offset = 0, limit = 2e3) {
|
|
18962
19007
|
try {
|
|
18963
|
-
const
|
|
18964
|
-
|
|
18965
|
-
if (SUPPORTS_NOFOLLOW) {
|
|
18966
|
-
const stat4 = await fs2.stat(resolvedPath);
|
|
18967
|
-
if (!stat4.isFile()) {
|
|
18968
|
-
return `Error: File '${filePath}' not found`;
|
|
18969
|
-
}
|
|
18970
|
-
const fd = await fs2.open(
|
|
18971
|
-
resolvedPath,
|
|
18972
|
-
fsSync.constants.O_RDONLY | fsSync.constants.O_NOFOLLOW
|
|
18973
|
-
);
|
|
18974
|
-
try {
|
|
18975
|
-
content = await fd.readFile({ encoding: "utf-8" });
|
|
18976
|
-
} finally {
|
|
18977
|
-
await fd.close();
|
|
18978
|
-
}
|
|
18979
|
-
} else {
|
|
18980
|
-
const stat4 = await fs2.lstat(resolvedPath);
|
|
18981
|
-
if (stat4.isSymbolicLink()) {
|
|
18982
|
-
return `Error: Symlinks are not allowed: ${filePath}`;
|
|
18983
|
-
}
|
|
18984
|
-
if (!stat4.isFile()) {
|
|
18985
|
-
return `Error: File '${filePath}' not found`;
|
|
18986
|
-
}
|
|
18987
|
-
content = await fs2.readFile(resolvedPath, "utf-8");
|
|
18988
|
-
}
|
|
19008
|
+
const { content: buffer2 } = await this.readFileBuffer(filePath);
|
|
19009
|
+
const content = buffer2.toString("utf-8");
|
|
18989
19010
|
const emptyMsg = checkEmptyContent(content);
|
|
18990
19011
|
if (emptyMsg) {
|
|
18991
19012
|
return emptyMsg;
|
|
@@ -19009,35 +19030,19 @@ var FilesystemBackend = class {
|
|
|
19009
19030
|
* @returns Raw file content as FileData
|
|
19010
19031
|
*/
|
|
19011
19032
|
async readRaw(filePath) {
|
|
19012
|
-
const
|
|
19013
|
-
|
|
19014
|
-
let stat4;
|
|
19015
|
-
if (SUPPORTS_NOFOLLOW) {
|
|
19016
|
-
stat4 = await fs2.stat(resolvedPath);
|
|
19017
|
-
if (!stat4.isFile()) throw new Error(`File '${filePath}' not found`);
|
|
19018
|
-
const fd = await fs2.open(
|
|
19019
|
-
resolvedPath,
|
|
19020
|
-
fsSync.constants.O_RDONLY | fsSync.constants.O_NOFOLLOW
|
|
19021
|
-
);
|
|
19022
|
-
try {
|
|
19023
|
-
content = await fd.readFile({ encoding: "utf-8" });
|
|
19024
|
-
} finally {
|
|
19025
|
-
await fd.close();
|
|
19026
|
-
}
|
|
19027
|
-
} else {
|
|
19028
|
-
stat4 = await fs2.lstat(resolvedPath);
|
|
19029
|
-
if (stat4.isSymbolicLink()) {
|
|
19030
|
-
throw new Error(`Symlinks are not allowed: ${filePath}`);
|
|
19031
|
-
}
|
|
19032
|
-
if (!stat4.isFile()) throw new Error(`File '${filePath}' not found`);
|
|
19033
|
-
content = await fs2.readFile(resolvedPath, "utf-8");
|
|
19034
|
-
}
|
|
19033
|
+
const { content: buffer2, stat: stat4 } = await this.readFileBuffer(filePath);
|
|
19034
|
+
const content = buffer2.toString("utf-8");
|
|
19035
19035
|
return {
|
|
19036
19036
|
content: content.split("\n"),
|
|
19037
19037
|
created_at: stat4.ctime.toISOString(),
|
|
19038
19038
|
modified_at: stat4.mtime.toISOString()
|
|
19039
19039
|
};
|
|
19040
19040
|
}
|
|
19041
|
+
/** Read file content as raw bytes without following symbolic links. */
|
|
19042
|
+
async readBinary(filePath) {
|
|
19043
|
+
const { content } = await this.readFileBuffer(filePath);
|
|
19044
|
+
return content;
|
|
19045
|
+
}
|
|
19041
19046
|
/**
|
|
19042
19047
|
* Create a new file with content.
|
|
19043
19048
|
* Returns WriteResult. External storage sets filesUpdate=null.
|