
Security News
npm Adopts OIDC for Trusted Publishing in CI/CD Workflows
npm now supports Trusted Publishing with OIDC, enabling secure package publishing directly from CI/CD workflows without relying on long-lived tokens.
@synstack/fs
Advanced tools
File system operations made easy
This package provides a strongly-typed, chainable, and immutable API for file system operations with support for multiple formats and advanced path manipulation.
Turn verbose file operations into chainable, immutable, and strongly-typed commands:
// Chain directory and file operations
const srcDir = dir("./src");
// Recursively create directories
await srcDir.to("dist/assets/images").make();
// Validate data files with zod schemas
const configFile = srcDir.file("config.json").schema(configSchema);
await configFile.write.prettyJson({
name: "my-app",
version: "1.0.0",
settings: {
port: 3000,
debug: true,
},
});
const config = await configFile.read.json(); // A fully typed json object
// Chain file operations from directory
const config = await srcDir
.file("config.json")
.schema(configSchema)
.read.json(); // A fully typed json object
// Chain directory traversal and file operations
const buttonCss = await srcDir
.to("components") // Navigate to subdirectory
.file("Button.tsx")
.dir() // Get parent directory
.file("Button.css") // Get sibling file
.read.text();
// Chain directory creation and file operations
await srcDir
.to("dist/assets/images") // Navigate to nested path
.file("logo.png") // Reference file in new directory
.write.base64(imageData);
# Using npm
npm install @synstack/fs
# Using yarn
yarn add @synstack/fs
# Using pnpm
pnpm add @synstack/fs
Create and work with files using the file()
function:
import { file } from "@synstack/fs";
// Create a file instance
const myFile = file("/path/to/file.txt");
// Check file existence
await myFile.exists(); // Promise<boolean>
myFile.existsSync(); // boolean
// Delete file
await myFile.remove();
myFile.removeSync();
// Move file
await myFile.move("/new/path/file.txt");
myFile.moveSync("/new/path/file.txt");
// Get file metadata
await myFile.creationDate(); // Promise<Date>
myFile.creationDateSync(); // Date
const myFile = file("/path/to/file.txt");
// Get path information
myFile.path; // "/path/to/file.txt"
myFile.dirPath(); // "/path/to"
myFile.dir(); // FsDir instance
myFile.fileName(); // "file.txt"
myFile.fileExtension(); // ".txt"
myFile.fileNameWithoutExtension(); // "file"
myFile.mimeType(); // "text/plain"
// Path manipulation
myFile.toFile("../other.txt"); // New FsFile instance
myFile.toDir("../other"); // New FsDir instance
myFile.relativePathFrom(otherFile); // Relative path from other file
myFile.relativePathTo(otherFile); // Relative path to other file
myFile.isInDir(someDir); // Check if file is in directory
// Text reading
await myFile.read.text(); // string
myFile.read.textSync(); // string
await myFile.read.str(); // Enhanced string
myFile.read.strSync(); // Enhanced string
// Structured data
await myFile.read.json<T>(); // T
myFile.read.jsonSync<T>(); // T
await myFile.read.yaml<T>(); // T
myFile.read.yamlSync<T>(); // T
await myFile.read.xml<T>(); // T
myFile.read.xmlSync<T>(); // T
// Binary data
await myFile.read.base64(); // string
myFile.read.base64Sync(); // string
await myFile.read.base64Data(); // Base64Data
myFile.read.base64DataSync(); // Base64Data
[!NOTE] Any write operation will create the parent directories recursively if they do not exist. No need to call
make()
on the parent directory beforehand.
// Text writing
await myFile.write.text("content");
myFile.write.textSync("content");
// Structured data
await myFile.write.json({ data: true });
myFile.write.jsonSync({ data: true });
await myFile.write.prettyJson({ data: true });
myFile.write.prettyJsonSync({ data: true });
await myFile.write.yaml({ data: true });
myFile.write.yamlSync({ data: true });
// Binary data
await myFile.write.base64(base64String);
myFile.write.base64Sync(base64String);
// Write mode
await myFile.write.mode("preserve").text("content"); // Skip if file exists
await myFile.write.mode("overwrite").text("content"); // Default behavior
import { z } from "zod";
const schema = z.object({ name: z.string() });
const configFile = file("config.json").schema(schema);
// Read with validation
const config = await configFile.read.json();
// Write with validation
await configFile.write.json({ name: "test" });
Work with directories using the dir()
function:
import { dir } from "@synstack/fs";
const myDir = dir("/path/to/directory");
// Check existence
await myDir.exists(); // Promise<boolean>
myDir.existsSync(); // boolean
// Create directory
await myDir.make();
myDir.makeSync();
// Remove directory
await myDir.rm();
myDir.rmSync();
// Move directory
await myDir.move("/new/path");
myDir.moveSync("/new/path");
// Get directory information
myDir.path; // "/path/to/directory"
myDir.name(); // "directory"
// Navigate directories
myDir.to("subdirectory"); // New FsDir instance
myDir.toFile("file.txt"); // New FsFile instance
// Relative paths
myDir.relativePathTo(otherDir); // Relative path from this directory to another directory
myDir.relativePathFrom(otherDir); // Relative path from another directory to this directory
// Find files using glob patterns
await myDir.glob("**/*.ts", "!**/*.test.ts"); // FsFileArray
myDir.globSync(["**/*.ts", "!**/*.test.ts"]); // FsFileArray
// Get git tracked, modified, and untracked files
await myDir.gitLs();
await myDir.exec`echo "Hello, world!"`;
Work with collections of files using powerful array methods:
import { dir, files } from "@synstack/fs";
// Create from directory
const sourceDir = dir("./src");
const fileArray = await sourceDir.glob("**/*");
// Create from paths
const customArray = files(["/path/to/file1.txt", "/path/to/file2.txt"]);
// Filtering
fileArray.filter((file) => file.fileExtension() === ".ts");
fileArray.filterGlobs("**/*.ts", "!**/*.test.ts");
fileArray.filterMimeTypes("text/plain", "application/json");
fileArray.filterDir(someDir);
// Path operations
fileArray.toPaths(); // Array<string>
fileArray.relativePathsTo(someDir); // Array<string>
FAQs
File system operations made easy
We found that @synstack/fs demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 0 open source maintainers collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
npm now supports Trusted Publishing with OIDC, enabling secure package publishing directly from CI/CD workflows without relying on long-lived tokens.
Research
/Security News
A RubyGems malware campaign used 60 malicious packages posing as automation tools to steal credentials from social media and marketing tool users.
Security News
The CNA Scorecard ranks CVE issuers by data completeness, revealing major gaps in patch info and software identifiers across thousands of vulnerabilities.