Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

@lix-js/fs

Package Overview
Dependencies
Maintainers
2
Versions
10
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@lix-js/fs - npm Package Compare versions

Comparing version 0.6.0 to 1.0.0

4

dist/memoryFs.d.ts
import type { NodeishFilesystem } from "./NodeishFilesystemApi.js";
export type Snapshot = {
fsMap: {
[key: string]: string[] | string;
[key: string]: string[] | string | {
placeholder: true;
};
};

@@ -6,0 +8,0 @@ fsStats: {

@@ -6,6 +6,16 @@ import { FilesystemError } from "./errors/FilesystemError.js";

fsMap: Object.fromEntries([...fs._state.fsMap].map(([path, content]) => {
let serializedContent;
if (content instanceof Set) {
serializedContent = [...content].sort();
}
else if (content.placeholder) {
serializedContent = content;
}
else {
serializedContent = content.toString("base64");
}
return [
path,
// requires node buffers, but no web standard method exists
content instanceof Set ? [...content].sort() : content.toString("base64"),
serializedContent,
// Alternative to try:

@@ -45,3 +55,7 @@ // onst binaryData = new Uint8Array([255, 116, 79, 99 /*...*/]);

return [pathPrefix + path, data];
// @ts-ignore
}
else if (content?.placeholder) {
return [pathPrefix + path, content];
}
return [pathPrefix + path, new Set(content)];

@@ -90,2 +104,3 @@ }));

}
// lstat is like stat, but does not follow symlinks
async function lstat(path) {

@@ -102,2 +117,27 @@ path = normalPath(path);

_state: state,
_createPlaceholder: async function (path, options) {
path = normalPath(path);
const dirName = getDirname(path);
const baseName = getBasename(path);
let parentDir = state.fsMap.get(dirName);
if (!(parentDir instanceof Set)) {
await this.mkdir(dirName, { recursive: true });
parentDir = state.fsMap.get(dirName);
if (!(parentDir instanceof Set)) {
throw new FilesystemError("ENOENT", path, "writeFile");
}
}
parentDir.add(baseName);
const isSymbolicLink = options?.mode === 120000;
newStatEntry(path, state.fsStats, isSymbolicLink ? 2 : 0, options?.mode ?? 0o644);
state.fsMap.set(path, { placeholder: true });
},
_isPlaceholder: function (path) {
path = normalPath(path);
const entry = state.fsMap.get(path);
if (entry && "placeholder" in entry) {
return true;
}
return false;
},
writeFile: async function (path, data, options) {

@@ -137,2 +177,4 @@ path = normalPath(path);

throw new FilesystemError("ENOENT", path, "readFile");
if ("placeholder" in file)
throw new FilesystemError("EPLACEHOLDER", path, "readFile");
if (!(options?.encoding || typeof options === "string"))

@@ -156,3 +198,3 @@ return file;

const parentDir = state.fsMap.get(dirName);
if (typeof parentDir === "string") {
if (typeof parentDir === "string" || (parentDir && "palceholder" in parentDir)) {
throw new FilesystemError("ENOTDIR", path, "mkdir");

@@ -162,3 +204,8 @@ }

if (state.fsMap.has(path)) {
throw new FilesystemError("EEXIST", path, "mkdir");
if (!options?.recursive) {
throw new FilesystemError("EEXIST", path, "mkdir");
}
else {
return undefined;
}
}

@@ -173,6 +220,7 @@ parentDir.add(baseName);

}
if (options?.recursive) {
const firstPath = await mkdir(getDirname(path), options);
else if (options?.recursive) {
const parent = getDirname(path);
const parentRes = await mkdir(parent, options);
await mkdir(path, options);
return firstPath;
return parentRes;
}

@@ -189,8 +237,10 @@ throw new FilesystemError("ENOENT", path, "mkdir");

throw new FilesystemError("ENOENT", path, "rm");
if (parentDir instanceof Uint8Array)
if (parentDir instanceof Uint8Array || "placeholder" in parentDir) {
throw new FilesystemError("ENOTDIR", path, "rm");
if (target instanceof Uint8Array) {
}
if (target instanceof Uint8Array || "placeholder" in target) {
parentDir.delete(baseName);
state.fsStats.delete(path);
state.fsMap.delete(path);
// TODO: check if placeholder should skip firing
for (const listener of listeners) {

@@ -223,3 +273,3 @@ listener({ eventType: "rename", filename: dirName + baseName });

const watchDir = getDirname(path);
const watchPath = watchDir + watchName;
const watchPath = watchName === "/" ? watchDir : watchDir + watchName;
// @ts-ignore

@@ -236,3 +286,7 @@ if (options?.persistent || options?.encoding) {

});
const listener = (event) => {
const listener = ({ eventType, filename }) => {
const event = {
eventType,
filename,
};
if (event.filename === null) {

@@ -248,4 +302,4 @@ throw new Error("Internal watcher error: missing filename");

}
else if (changeDir === watchPath + "/") {
event.filename = event.filename.replace(watchPath + "/", "") || changeName;
else if (changeDir === `${watchPath}/`) {
event.filename = event.filename.replace(`${watchPath}/`, "") || changeName;
queue.push(event);

@@ -255,4 +309,3 @@ setTimeout(() => handleNext(undefined), 0);

else if (options?.recursive && event.filename.startsWith(watchPath)) {
// console.log(event.filename, { watchPath, changeDir, changeName })
event.filename = event.filename.replace(watchPath + "/", "") || changeName;
event.filename = event.filename.replace(`${watchPath}/`, "") || changeName;
queue.push(event);

@@ -274,3 +327,4 @@ setTimeout(() => handleNext(undefined), 0);

}
return (async function* () {
// inline async definition like "return (async function* () {" are not supported by the figma api
const asyncIterator = async function* () {
while (!options?.signal?.aborted) {

@@ -281,3 +335,5 @@ if (queue.length > 0) {

else {
// eslint-disable-next-line no-await-in-loop
await changeEvent;
// eslint-disable-next-line @typescript-eslint/no-loop-func
changeEvent = new Promise((resolve, reject) => {

@@ -289,3 +345,4 @@ handleNext = resolve;

}
})();
};
return asyncIterator();
},

@@ -302,2 +359,5 @@ rmdir: async function (path) {

throw new FilesystemError("ENOTDIR", path, "rmdir");
if ("placeholder" in parentDir || "placeholder" in target) {
throw new FilesystemError("ENOTDIR", path, "rmdir");
}
if (target.size)

@@ -320,8 +380,8 @@ throw new FilesystemError("ENOTEMPTY", path, "rmdir");

}
if (parentDir instanceof Uint8Array) {
throw new FilesystemError("ENOTDIR", path, "symlink", target);
}
if (parentDir === undefined) {
throw new FilesystemError("ENOENT", path, "symlink", target);
}
if (parentDir instanceof Uint8Array || "placeholder" in parentDir) {
throw new FilesystemError("ENOTDIR", path, "symlink", target);
}
if (targetInode !== undefined) {

@@ -340,3 +400,3 @@ state.fsMap.set(path, targetInode);

throw new FilesystemError("ENOENT", path, "unlink");
if (parentDir instanceof Uint8Array) {
if (parentDir instanceof Uint8Array || "placeholder" in parentDir) {
throw new FilesystemError("ENOTDIR", path, "unlink");

@@ -343,0 +403,0 @@ }

{
"name": "@lix-js/fs",
"version": "0.6.0",
"version": "1.0.0",
"type": "module",

@@ -5,0 +5,0 @@ "publishConfig": {

@@ -69,2 +69,6 @@ import { test, expect, afterAll, describe } from "vitest"

)
// should not throw
await fs.mkdir(`${tempDir}/home/user1/documents/`, { recursive: true })
expect(await fs.mkdir(`${tempDir}/home/user1/downloads/`, { recursive: true })).toMatch(

@@ -271,2 +275,37 @@ /^.*\/home\/user1\/downloads\/?$/

test.skipIf(isNodeFs)("placeholders", async () => {
const placeholderPath = `/placeholders/subdir`
await fs.mkdir(placeholderPath, { recursive: true })
await fs.writeFile(`${placeholderPath}/file`, "")
await fs._createPlaceholder(placeholderPath + "/test")
expect(fs._isPlaceholder(placeholderPath + "/test")).toBe(true)
expect(fs._isPlaceholder(placeholderPath + "/noexists")).toBe(false)
expect(fs._isPlaceholder(placeholderPath + "/file")).toBe(false)
const dirents = await fs.readdir(`/placeholders/subdir`)
expect(dirents).toStrictEqual(["file", "test"])
await expect(async () => await fs.readFile(`${placeholderPath}/test`)).rejects.toThrow(
/EPLACEHOLDER/
)
await fs.rm("/placeholders", { recursive: true })
const finalDirents = await fs.readdir(`/`)
expect(finalDirents).toStrictEqual([
"home",
"file2",
"file3",
"file1.link",
"file3.link",
"user1.link",
])
})
test("unlink", async () => {

@@ -273,0 +312,0 @@ await fs.unlink(`${tempDir}/user1.link`)

@@ -5,7 +5,7 @@ import type { NodeishFilesystem, NodeishStats, FileChangeInfo } from "./NodeishFilesystemApi.js"

type Inode = Uint8Array | Set<string>
type Inode = Uint8Array | Set<string> | { placeholder: true }
export type Snapshot = {
fsMap: {
[key: string]: string[] | string
[key: string]: string[] | string | { placeholder: true }
}

@@ -30,6 +30,14 @@ fsStats: {

[...fs._state.fsMap].map(([path, content]) => {
let serializedContent
if (content instanceof Set) {
serializedContent = [...content].sort()
} else if (content.placeholder) {
serializedContent = content
} else {
serializedContent = content.toString("base64")
}
return [
path,
// requires node buffers, but no web standard method exists
content instanceof Set ? [...content].sort() : content.toString("base64"),
serializedContent,

@@ -79,2 +87,6 @@ // Alternative to try:

return [pathPrefix + path, data]
// @ts-ignore
} else if (content?.placeholder) {
return [pathPrefix + path, content]
}

@@ -144,2 +156,3 @@

// lstat is like stat, but does not follow symlinks
async function lstat(path: Parameters<NodeishFilesystem["lstat"]>[0]) {

@@ -155,2 +168,36 @@ path = normalPath(path)

_state: state,
_createPlaceholder: async function (
path: Parameters<NodeishFilesystem["writeFile"]>[0],
options?: Parameters<NodeishFilesystem["writeFile"]>[2]
) {
path = normalPath(path)
const dirName = getDirname(path)
const baseName = getBasename(path)
let parentDir: Inode | undefined = state.fsMap.get(dirName)
if (!(parentDir instanceof Set)) {
await this.mkdir(dirName, { recursive: true })
parentDir = state.fsMap.get(dirName)
if (!(parentDir instanceof Set)) {
throw new FilesystemError("ENOENT", path, "writeFile")
}
}
parentDir.add(baseName)
const isSymbolicLink = options?.mode === 120000
newStatEntry(path, state.fsStats, isSymbolicLink ? 2 : 0, options?.mode ?? 0o644)
state.fsMap.set(path, { placeholder: true })
},
_isPlaceholder: function (path: Parameters<NodeishFilesystem["writeFile"]>[0]) {
path = normalPath(path)
const entry = state.fsMap.get(path)
if (entry && "placeholder" in entry) {
return true
}
return false
},
writeFile: async function (

@@ -202,2 +249,3 @@ path: Parameters<NodeishFilesystem["writeFile"]>[0],

if (file === undefined) throw new FilesystemError("ENOENT", path, "readFile")
if ("placeholder" in file) throw new FilesystemError("EPLACEHOLDER", path, "readFile")
if (!(options?.encoding || typeof options === "string")) return file

@@ -225,3 +273,3 @@

if (typeof parentDir === "string") {
if (typeof parentDir === "string" || (parentDir && "palceholder" in parentDir)) {
throw new FilesystemError("ENOTDIR", path, "mkdir")

@@ -232,8 +280,14 @@ }

if (state.fsMap.has(path)) {
throw new FilesystemError("EEXIST", path, "mkdir")
if (!options?.recursive) {
throw new FilesystemError("EEXIST", path, "mkdir")
} else {
return undefined
}
}
parentDir.add(baseName)
newStatEntry(path, state.fsStats, 1, 0o755)
state.fsMap.set(path, new Set())
for (const listener of listeners) {

@@ -243,8 +297,7 @@ listener({ eventType: "rename", filename: dirName + baseName })

return path
}
if (options?.recursive) {
const firstPath = await mkdir(getDirname(path), options)
} else if (options?.recursive) {
const parent = getDirname(path)
const parentRes = await mkdir(parent, options)
await mkdir(path, options)
return firstPath
return parentRes
}

@@ -268,8 +321,11 @@

if (parentDir instanceof Uint8Array) throw new FilesystemError("ENOTDIR", path, "rm")
if (parentDir instanceof Uint8Array || "placeholder" in parentDir) {
throw new FilesystemError("ENOTDIR", path, "rm")
}
if (target instanceof Uint8Array) {
if (target instanceof Uint8Array || "placeholder" in target) {
parentDir.delete(baseName)
state.fsStats.delete(path)
state.fsMap.delete(path)
// TODO: check if placeholder should skip firing
for (const listener of listeners) {

@@ -312,3 +368,3 @@ listener({ eventType: "rename", filename: dirName + baseName })

const watchDir = getDirname(path)
const watchPath = watchDir + watchName
const watchPath = watchName === "/" ? watchDir : watchDir + watchName

@@ -329,3 +385,8 @@ // @ts-ignore

const listener = (event: FileChangeInfo) => {
const listener = ({ eventType, filename }: FileChangeInfo) => {
const event: FileChangeInfo = {
eventType,
filename,
}
if (event.filename === null) {

@@ -341,9 +402,8 @@ throw new Error("Internal watcher error: missing filename")

setTimeout(() => handleNext(undefined), 0)
} else if (changeDir === watchPath + "/") {
event.filename = event.filename.replace(watchPath + "/", "") || changeName
} else if (changeDir === `${watchPath}/`) {
event.filename = event.filename.replace(`${watchPath}/`, "") || changeName
queue.push(event)
setTimeout(() => handleNext(undefined), 0)
} else if (options?.recursive && event.filename.startsWith(watchPath)) {
// console.log(event.filename, { watchPath, changeDir, changeName })
event.filename = event.filename.replace(watchPath + "/", "") || changeName
event.filename = event.filename.replace(`${watchPath}/`, "") || changeName
queue.push(event)

@@ -371,3 +431,4 @@ setTimeout(() => handleNext(undefined), 0)

return (async function* () {
// inline async definition like "return (async function* () {" are not supported by the figma api
const asyncIterator = async function* () {
while (!options?.signal?.aborted) {

@@ -377,3 +438,5 @@ if (queue.length > 0) {

} else {
// eslint-disable-next-line no-await-in-loop
await changeEvent
// eslint-disable-next-line @typescript-eslint/no-loop-func
changeEvent = new Promise((resolve, reject) => {

@@ -385,3 +448,5 @@ handleNext = resolve

}
})()
}
return asyncIterator()
},

@@ -402,2 +467,6 @@

if ("placeholder" in parentDir || "placeholder" in target) {
throw new FilesystemError("ENOTDIR", path, "rmdir")
}
if (target.size) throw new FilesystemError("ENOTEMPTY", path, "rmdir")

@@ -427,6 +496,2 @@

if (parentDir instanceof Uint8Array) {
throw new FilesystemError("ENOTDIR", path, "symlink", target)
}
if (parentDir === undefined) {

@@ -436,2 +501,6 @@ throw new FilesystemError("ENOENT", path, "symlink", target)

if (parentDir instanceof Uint8Array || "placeholder" in parentDir) {
throw new FilesystemError("ENOTDIR", path, "symlink", target)
}
if (targetInode !== undefined) {

@@ -454,3 +523,3 @@ state.fsMap.set(path, targetInode)

if (parentDir instanceof Uint8Array) {
if (parentDir instanceof Uint8Array || "placeholder" in parentDir) {
throw new FilesystemError("ENOTDIR", path, "unlink")

@@ -457,0 +526,0 @@ }

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc