From fd5afd70aa2d01f39d100c2c1da52ad80818fbbe Mon Sep 17 00:00:00 2001 From: Carbon Date: Thu, 1 Oct 2026 20:02:37 +0800 Subject: [PATCH] docs: clarify installation, release scope and workload selection --- docs/app/layout.jsx | 2 +- docs/content/api/index.mdx | 29 ++++--- docs/content/benchmarks.mdx | 13 +++ docs/content/guide/_meta.js | 3 +- docs/content/guide/migration.mdx | 42 ++++++---- docs/content/guide/quick-start.mdx | 110 +++++++++++++++++-------- docs/content/guide/troubleshooting.mdx | 66 +++++++++++++++ docs/content/guide/use-cases.mdx | 17 +++- docs/content/index.mdx | 17 +++- 9 files changed, 230 insertions(+), 69 deletions(-) create mode 100644 docs/content/guide/troubleshooting.mdx diff --git a/docs/app/layout.jsx b/docs/app/layout.jsx index e3f5385..041c98e 100644 --- a/docs/app/layout.jsx +++ b/docs/app/layout.jsx @@ -4,7 +4,7 @@ import 'nextra-theme-docs/style.css' import './globals.css' export const metadata = { - metadataBase: new URL('https://github.com/vooyajs/fs'), + metadataBase: new URL('https://rush-fs-docs.vercel.app'), title: { template: '%s | Vooya FS' }, description: 'Native batch filesystem operations for Node.js, powered by Rust and measured at explicit workload boundaries.', diff --git a/docs/content/api/index.mdx b/docs/content/api/index.mdx index 8afe488..c522e94 100644 --- a/docs/content/api/index.mdx +++ b/docs/content/api/index.mdx @@ -11,7 +11,10 @@ marketing. Core batch APIs accept string, Buffer and file URL paths. A public compatibility layer uses Node for options outside the measured native path. Other exports retain their documented subsets; callback API forms remain absent. -See the [Node compatibility backlog](/api/compatibility) for remaining API and behavioral gaps. +This page describes main, including unreleased changes. See [Quick Start](/guide/quick-start) +for the release boundary and installation instructions. + +See the [Node compatibility policy](/api/compatibility) for remaining API and behavioral gaps. ## Batch extensions @@ -28,7 +31,7 @@ See the [Node compatibility backlog](/api/compatibility) for remaining API and b | -------------------------------------------- | ------ | ----------------------------------------------------------------------------------- | | `readdir` | ✅ | `withFileTypes`, `recursive`; adds `concurrency` | | `glob` | ✅ | rooted patterns, `cwd`, `exclude`, `withFileTypes`; adds `concurrency`, `gitIgnore` | -| `readFile` / `writeFile` / `appendFile` | ✅ | string paths, documented encodings and flags | +| `readFile` / `writeFile` / `appendFile` | ✅ | `readFile` supports core path/options routing; writes retain documented subsets | | `copyFile` / `cp` | ✅ | recursive copy options; `cp` adds `concurrency` | | `mkdir` / `rm` / `rmdir` | ✅ | recursive options; `rm` adds `concurrency` | | `stat` / `lstat` | ✅ | `Stats` dates and type methods | @@ -38,20 +41,22 @@ See the [Node compatibility backlog](/api/compatibility) for remaining API and b | `chmod` / `chown` / `utimes` | ✅ | platform filesystem semantics | | `mkdtemp` | ✅ | string prefix | +`exists` is a Vooya Promise extension; Node has no Promise `exists` method. + All APIs above provide promise and sync variants, for example `readdir` and -`readdirSync`. Async calls run their Rust task away from the JavaScript event-loop -thread; sync calls block like their Node counterparts. +`readdirSync`. Native async routes run Rust work away from the JavaScript event-loop +thread; other routes use Node. Sync calls block like their Node counterparts. ## Deliberately not implemented -| Surface | Reason / current alternative | -| -------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------- | -| `open`, `close`, `read`, `write`, `fstat`, `ftruncate` | A safe cross-boundary file-descriptor lifecycle is a separate design problem. Use `node:fs` for fd workflows. | -| `opendir` | Native directory iterator lifetime and backpressure are not part of the current batch surface. Use `readdir`. | -| `watch`, `watchFile` | Cross-platform event delivery needs a long-lived event bridge. Use Node watchers. | -| `createReadStream`, `createWriteStream` | Streams require Node-native backpressure and piping semantics. Use Node streams. | -| callback APIs | The current library is promise-first plus synchronous APIs. | -| `URL` / `Buffer` paths outside core batches outside the core batch surface | Check each operation; core batch APIs support these through the public entry. | +| Surface | Reason / current alternative | +| ------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------- | +| `open`, `close`, `read`, `write`, `fstat`, `ftruncate` | A safe cross-boundary file-descriptor lifecycle is a separate design problem. Use `node:fs` for fd workflows. | +| `opendir` | Native directory iterator lifetime and backpressure are not part of the current batch surface. Use `readdir`. | +| `watch`, `watchFile` | Cross-platform event delivery needs a long-lived event bridge. Use Node watchers. | +| `createReadStream`, `createWriteStream` | Streams require Node-native backpressure and piping semantics. Use Node streams. | +| callback APIs | The current library is promise-first plus synchronous APIs. | +| `URL` / `Buffer` paths outside the core batch surface | Check each operation; core batch APIs support these through the public entry. | The SDDs in `test/conformance` record the precise oracle, functional matrix, known gaps, and documentation obligations for each supported API. diff --git a/docs/content/benchmarks.mdx b/docs/content/benchmarks.mdx index 888ff6b..155e0d0 100644 --- a/docs/content/benchmarks.mdx +++ b/docs/content/benchmarks.mdx @@ -21,6 +21,19 @@ on each evidence page and include every sample, runtime/library versions, fixtur options, CPU/memory observations and source/native-binary identity. Evidence is a snapshot of the recorded revision and configuration, not a universal speed claim. +## Find an API table + +Open the table for the operation you use. On narrow screens, swipe horizontally +inside a table to reach the remaining implementations; the times are milliseconds +for a complete workload, and lower is better. Keep the runtime, mode, options and +execution route matched when comparing rows. + +- Discovery: [readdir](/guide/all-api-evidence#readdir), [glob](/guide/all-api-evidence#glob), [scan](/guide/all-api-evidence#scan). +- File contents: [readFile](/guide/all-api-evidence#readfile), [writeFile](/guide/all-api-evidence#writefile), [appendFile](/guide/all-api-evidence#appendfile), [truncate](/guide/all-api-evidence#truncate). +- Copy and removal: [copyFile](/guide/all-api-evidence#copyfile), [cp](/guide/all-api-evidence#cp), [rm](/guide/all-api-evidence#rm), [rmdir](/guide/all-api-evidence#rmdir), [unlink](/guide/all-api-evidence#unlink). +- Paths and directories: [mkdir](/guide/all-api-evidence#mkdir), [mkdtemp](/guide/all-api-evidence#mkdtemp), [rename](/guide/all-api-evidence#rename), [realpath](/guide/all-api-evidence#realpath), [readlink](/guide/all-api-evidence#readlink), [link](/guide/all-api-evidence#link), [symlink](/guide/all-api-evidence#symlink). +- Metadata: [stat](/guide/all-api-evidence#stat), [lstat](/guide/all-api-evidence#lstat), [access](/guide/all-api-evidence#access), [exists](/guide/all-api-evidence#exists), [chmod](/guide/all-api-evidence#chmod), [chown](/guide/all-api-evidence#chown), [utimes](/guide/all-api-evidence#utimes). + ## Reproduce the complete matrix From a fresh checkout, install the locked dependencies and build the release diff --git a/docs/content/guide/_meta.js b/docs/content/guide/_meta.js index 222cad0..7124779 100644 --- a/docs/content/guide/_meta.js +++ b/docs/content/guide/_meta.js @@ -1,11 +1,12 @@ export default { 'quick-start': 'Quick Start', + 'use-cases': 'Choose an API', + troubleshooting: 'Troubleshooting & FAQ', 'what-is-vooya-fs': 'What is Vooya FS', 'execution-model': 'Execution Model', 'batch-evidence': 'Batch Evidence', 'native-overheads': 'Native Overhead Evidence', 'competitor-evidence': 'Competitor Evidence', 'all-api-evidence': 'All API Comparisons', - 'use-cases': 'Use Cases', migration: 'Migration from Rush-FS', } diff --git a/docs/content/guide/migration.mdx b/docs/content/guide/migration.mdx index cfc460f..f126d1e 100644 --- a/docs/content/guide/migration.mdx +++ b/docs/content/guide/migration.mdx @@ -3,30 +3,30 @@ The project and repository are now **Vooya FS**. The canonical npm package is `@vooya/fs`. -## Planned import change +## Change the dependency and import ```diff - import { glob, readdir } from '@rush-fs/core' + import { glob, readdir } from '@vooya/fs' ``` -The Rust crate becomes `vooya_fs`, and the native binary basename becomes -`vooya-fs`. Repository and documentation links move to +Require Node.js 22 or newer, install `@vooya/fs`, and remove the legacy dependency +once your application tests pass. Update imports from `rush-fs` in the same way. +See [Quick Start](/guide/quick-start) to choose the published release or main. + +The Rust crate is `vooya_fs`, and the native binary basename is +`vooya-fs`. The canonical repository is `https://github.com/vooyajs/fs`. -## Package transition +## Release boundary -1. Publish `@vooya/fs` only after CI, conformance, package installation, and - platform artifact checks pass. -2. Verify fresh installs of the published package before changing legacy package - metadata. -3. Mark `@rush-fs/core` and `rush-fs` deprecated with a direct migration message, - while keeping every existing version installable. +`@vooya/fs@0.1.0` is published. This site follows main and also documents newer, +unreleased compatibility fixes. Do not assume those fixes are present in 0.1.0; +check the [release source](https://github.com/vooyajs/fs/tree/fs-v0.1.0). -npm deprecation displays a warning; it does not redirect one package name to -another. We do not publish a compatibility wrapper because the legacy packages -support Node.js 18 while `@vooya/fs` requires Node.js 22 or newer. A wrapper would -silently change the runtime requirement for users who update the old package. +Legacy versions remain separate packages. npm deprecation, if applied, displays a +warning; it does not redirect imports or install a replacement. The old packages +support Node.js 18, while Vooya FS requires Node.js 22 or newer. ## Behavioral review @@ -34,3 +34,17 @@ The intended API surface remains familiar, but migration is not a promise of tot Node `fs` parity. Review the [API overview](/api), especially the per-operation path support, missing callback/file-descriptor/stream APIs, and Vooya-only options such as `concurrency`, `gitIgnore`, `lines`, and `scan`. + +## Validate the migration + +1. Replace selected imports, without aliasing or patching `node:fs` globally. +2. Run application tests for path forms, encodings, errors, symlinks and mutation + options you actually use. Consult the per-API contract rather than assuming + complete Node compatibility. +3. Measure the same workload and options before and after the change. Check small + inputs as well as production scale, memory cost and application responsiveness. +4. Keep the original Node implementation for operations where it performs better. + +Promise methods are direct exports. `glob` on main is awaitable and async iterable, +but materializes a full result array. Code relying on Node's incremental iterator +memory behavior should keep Node's implementation. Callback APIs are not provided. diff --git a/docs/content/guide/quick-start.mdx b/docs/content/guide/quick-start.mdx index 52b7389..8516ff3 100644 --- a/docs/content/guide/quick-start.mdx +++ b/docs/content/guide/quick-start.mdx @@ -1,54 +1,92 @@ # Quick Start -The published package is `@vooya/fs@0.1.0`. This checkout's compatibility iteration -is not yet published. To test it, use the working tree or review branch containing -these changes and build locally: +This site documents **main, including changes not yet released to npm**. The +published package is [`@vooya/fs@0.1.0`](https://www.npmjs.com/package/@vooya/fs). +Its [release source](https://github.com/vooyajs/fs/tree/fs-v0.1.0) is the reference +for that version. The current compatibility policy and benchmark tables describe +the newer checkout; installing 0.1.0 does not install those changes. -```bash -git clone https://github.com/vooyajs/fs.git -cd fs -corepack pnpm install --frozen-lockfile -corepack pnpm build +## Requirements + +Use Node.js **22 or newer**; the current conformance matrix checks Node 22 and 24. +Prebuilt 0.1.0 packages cover macOS arm64/x64, Linux x64 with glibc, and Windows +x64. Rust is needed to build a checkout, not to use a supported prebuilt package. +Linux arm64 and Alpine/musl do not have published binaries in this release. + +## Install the published release + +```sh +npm install @vooya/fs@0.1.0 +# Or: pnpm add @vooya/fs@0.1.0 ``` -## Choose the right side of the boundary +Keep optional dependencies enabled: the package manager selects the native binary +for your platform. See [installation troubleshooting](/guide/troubleshooting) if +the module cannot load. + +## Run your first scan -Keep tiny, isolated operations in `node:fs`: +Save this as `scan.mjs` in the project where you installed the package. This +string-path example works with 0.1.0 and the current checkout: -```ts -import { existsSync } from 'node:fs' +```js +import { scan } from '@vooya/fs' -if (existsSync('./package.json')) { - // The native bridge would add work here, not remove it. +try { + const entries = await scan('.', { + include: ['**/*.{js,ts,rs}'], + exclude: ['**/node_modules/**', '**/dist/**'], + skipHidden: true, + concurrency: 4, + }) + console.table(entries.slice(0, 10)) + console.log(`${entries.length} matching entries`) +} catch (error) { + console.error(error) + process.exitCode = 1 } ``` -Use Vooya FS when one call represents substantial or combined work: +```sh +node scan.mjs +``` -```ts -import { glob, readdir, scan } from '@vooya/fs' +`scan` returns an array of metadata objects sorted by relative path. An empty +array is valid when no files match. It is a Vooya extension, not a Node API. +Four workers are an explicit starting point for this example, not a universal +optimum; tiny trees can be slower than Node. Read the [scan contract](/api/scan) +and [workload guide](/guide/use-cases) before applying it to a hot path. -const entries = await readdir('./node_modules', { recursive: true }) -const manifests = await glob('**/package.json', { cwd: './node_modules' }) -const sources = await scan('./packages', { - include: ['**/*.{js,ts,rs}'], - exclude: ['**/dist/**'], -}) -``` +For CommonJS, use `const { scan } = require('@vooya/fs')` and call it inside an +async function or with `.then()`. Promise methods are exported directly from +`@vooya/fs`; there is no `@vooya/fs/promises` entry. Synchronous variants such as +`scanSync` block the JavaScript thread. -Every supported operation also has a synchronous variant such as `scanSync` or -`readdirSync`. Prefer async APIs in servers and interactive applications so native -work does not block the JavaScript thread. +## Try the current source -## Verify a local checkout +To use the compatibility fixes and reproduce the published benchmark evidence, +install Git, Rust stable and pnpm 9, then build a release binding: -```bash -corepack pnpm typecheck -corepack pnpm lint -cargo clippy --all-targets --all-features -- -D warnings -corepack pnpm test -corepack pnpm doc:build +```sh +git clone https://github.com/vooyajs/fs.git +cd fs +pnpm install --frozen-lockfile +pnpm build +node --input-type=module -e "import { scan } from '@vooya/fs'; console.log((await scan('src')).length)" ``` -Continue with the [execution model](/guide/execution-model) before selecting -operations solely from headline benchmark ratios. +Run that command from the repository root: the package's self-reference resolves +the local public entry. Record `git rev-parse HEAD` when comparing results. The +checkout still carries version 0.1.0 until the next release, so the version string +alone does not identify its behavior. + +## Adopt one operation at a time + +Keep Node streams, watchers and fd workflows in `node:fs`. For each candidate, +check its [supported options and execution route](/api/compatibility), verify your +application's outputs/errors, then measure an equivalent workload. Importing Vooya +FS does not patch Node or replace filesystem calls made by your dependencies. + +Continue with [use cases](/guide/use-cases), [migration](/guide/migration), or the +[reproducible benchmark matrix](/benchmarks). Contributor checks are documented in +[CONTRIBUTING.md](https://github.com/vooyajs/fs/blob/main/CONTRIBUTING.md). diff --git a/docs/content/guide/troubleshooting.mdx b/docs/content/guide/troubleshooting.mdx new file mode 100644 index 0000000..8444ec1 --- /dev/null +++ b/docs/content/guide/troubleshooting.mdx @@ -0,0 +1,66 @@ +# Troubleshooting and FAQ + +## Which version does this site describe? + +The site follows main. npm currently provides `@vooya/fs@0.1.0`; main includes +additional compatibility fixes and newer measurements. Use the +[release source](https://github.com/vooyajs/fs/tree/fs-v0.1.0) for 0.1.0 and the +[checkout instructions](/guide/quick-start#try-the-current-source) to try main. + +## Cannot find the native binding + +Check the runtime, architecture and installed package from your application: + +```sh +node -p "process.version + ' ' + process.platform + '/' + process.arch" +npm ls @vooya/fs +``` + +Version 0.1.0 ships binaries for macOS arm64/x64, Linux x64 glibc and Windows x64. +The architecture is that of the Node process, which can differ from the host under +emulation. Ensure your package manager installs optional dependencies and install +on the target platform; copying `node_modules` from a different OS is not portable. + +There is no WASM fallback or automatic Node-only fallback when the addon is missing. +For a source checkout, run `pnpm install --frozen-lockfile` and `pnpm build` with +Rust stable installed. Source builds on other targets are not a promise of support. + +## Can I replace every Node fs import? + +Adopt supported operations individually. There is no global patch, callback API, +`@vooya/fs/promises` entry, or replacement for streams/watchers/fd lifecycle. +[Core methods](/api/compatibility) support more path and option combinations than +some of the smaller exports; check the specific API page. `exists` is an async +extension, while Node provides `existsSync` and a legacy callback `exists`. + +## Why is Rust slower on my workload? + +Native scheduling, argument conversion and result construction are part of the +cost. Tiny calls may not do enough work to recover that cost. More workers can +increase startup and contention. Compare the same output, options and side effects +using a release build, and measure both the default and explicit worker counts. +The [per-API tables](/guide/all-api-evidence) include losses, and +[Benchmarks](/benchmarks) provides repeatable commands and raw samples. + +## Does async mean streaming or bounded memory? + +No. Promise operations return complete results. In particular, main's `glob` +iterator still materializes the full array; `scan` returns sorted metadata for all +matches. Prefer Node streams or iterators when incremental consumption and +backpressure are the requirement. Async native work runs off the JavaScript +thread, but conversion and consumption of a large result can still affect it. + +## Why does a supported option use Node? + +The public entry selects Node for combinations outside a native fast path, such +as copy filters or some glob patterns. This preserves the documented behavior. +On main, `cpSync` and `rmSync` always use Node. A successful call or a speed ratio +alone is not proof of Rust acceleration; consult the +[execution policy](/api/compatibility). + +## Report a mismatch or performance regression + +Open an [issue](https://github.com/vooyajs/fs/issues) with Node/package versions, +OS/architecture, checkout commit if applicable, exact options, a minimal fixture, +and expected versus actual results. For performance, include release-build raw +samples, workload sizes, worker count and the equivalent Node/peer baseline. diff --git a/docs/content/guide/use-cases.mdx b/docs/content/guide/use-cases.mdx index e834cfc..32e8d51 100644 --- a/docs/content/guide/use-cases.mdx +++ b/docs/content/guide/use-cases.mdx @@ -3,7 +3,22 @@ Use Vooya FS when the unit of work is a tree or a batch, and keep ordinary one-off calls in `node:fs`. -## Strong candidates +## Choose by the result you need + +These are candidates to measure against your existing implementation. Evidence +below comes from the unreleased checkout on macOS; it is not a speed guarantee for +npm 0.1.0 or another operating system. + +| Needed result | Candidate | Check before adopting | +| ------------------------------- | ---------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| Names from a directory tree | [readdir](/api/readdir) | Compare with fdir as well as Node; [worker count matters](/guide/competitor-evidence#focused-readdir-concurrency-diagnostic). | +| Paths matching patterns | [glob](/api/glob) | Pattern and symlink semantics may select Node; [async does not lead every peer](/guide/competitor-evidence). | +| Paths plus metadata and filters | [scan](/api/scan) | Avoid repeated JS metadata calls, but [tiny trees lose](/guide/all-api-evidence#scan). | +| Whole-file Buffer or text | [readFile](/api/read-file) | Compare your sizes and encodings; [batch results differ from single calls](/guide/all-api-evidence#readfile). | +| Copy or delete a tree | [cp](/api/cp), [rm](/api/rm) | Measure worker counts and required options; sync forms on main use Node. [cp](/guide/all-api-evidence#cp) and [rm](/guide/all-api-evidence#rm) include losses. | +| Streams, watchers, open handles | Node | Retain Node's lifecycle, backpressure and event APIs. | + +## Workload examples ### Repository and monorepo indexing diff --git a/docs/content/index.mdx b/docs/content/index.mdx index 4bac589..f9c218f 100644 --- a/docs/content/index.mdx +++ b/docs/content/index.mdx @@ -2,11 +2,20 @@ Vooya FS is a Rust-powered execution engine for **batch filesystem work in Node.js**. It continues the former Rush-FS project under the Vooya name, with a narrower and -more honest promise: keep Node-compatible APIs where useful, and cross into Rust -only when a recursive or fused operation can amortize the native boundary. +focused promise: keep familiar Node APIs and prioritize native optimizations +where substantial I/O, recursive or fused work can amortize the boundary cost. -> The `@vooya/fs` rename and the APIs on this development branch have not been -> published to npm. +> **Documentation version: main (unreleased changes).** `@vooya/fs@0.1.0` is +> available on npm. The compatibility fixes and benchmark results on this site +> describe the newer source checkout, not that published package. +> [Install the release or try main](/guide/quick-start). + +## Start here + +- [Install and run your first scan](/guide/quick-start) +- [Choose an API for your workload](/guide/use-cases) +- [Compare all 26 APIs with Node and peers](/guide/all-api-evidence) +- [Resolve installation and compatibility questions](/guide/troubleshooting) ## One boundary, one batch