npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@caesarloo/simple-svn-client

v0.1.3

Published

SVN CLI wrapper for Node.js — wraps the system svn executable with Windows GBK-safe decoding, binary discovery and error reporting

Readme

@caesarloo/simple-svn-client

SVN CLI wrapper for Node.js — wraps the system svn executable. Designed for and shared by the vault-svn and ai-pm-tool Obsidian plugins, but usable in any Node.js project.

⚠️ Requirements

This package does not bundle svn. It shells out to the system svn executable, which must be installed and available on PATH (or configured via svnBinaryPath):

  • Windows: TortoiseSVN (check "command line client tools" during install), SlikSvn or VisualSVN Server binaries
  • macOS: brew install subversion
  • Linux: apt install subversion / dnf install subversion

When svn is missing, methods throw an error listing the candidates it tried and install hints.

Features

  • Windows GBK output decoding with multi-encoding heuristic + mojibake repair (the differentiator)
  • Automatic binary discovery: configured path → PATH (where/which) → common install locations
  • Command-injection / path-traversal input validation; --password masking in debug logs
  • High-level ops: status / update / diff / add / delete / revert / resolve / commit (with optional auto-add retry), log / logRange / diffSummarize / cat
  • Domain ops: diffFrontmatterFields / collectChanges / runSync / isSvnWorkingCopy, frontmatter parsing, change-summary generation
  • Zero Obsidian dependency; pure Node (node builtins + iconv-lite)

Install

npm install @caesarloo/simple-svn-client

Usage

import { SvnClient, runSync } from "@caesarloo/simple-svn-client";

const client = new SvnClient("C:/work/vault", { svnBinaryPath: "" });

if (await client.isAvailable()) {
  const entries = await client.status();
  const result = await client.update();
  const items = await client.collectChanges("5", "6");
}

// 完整同步流程(update + 变更收集)
const sync = await runSync("C:/work/vault", "产品需求");
console.log(sync.message, sync.snapshot);

Error semantics

  • status / update / diff / add / delete / revert / resolve / commit throw on failure, with the decoded stderr as the message.
  • log / logRange / diffSummarize / cat return empty/null on failure (read-oriented, lenient).
  • execSvn (low-level) never throws; check the returned code.
  • isAvailable() returns false (no throw) when svn is missing.

API

| Export | Description | | --- | --- | | SvnClient | High-level client; see below | | execSvn(args, cwd, timeoutMs?) | Low-level exec, never throws, returns {stdout, stderr, code} | | SvnError | Error with stderr + code | | isSvnWorkingCopy(cwd) | Whether a directory is an SVN working copy | | runSync(cwd, repoDir) | Full sync: availability → base revision → update → collect changes; auto-detects the real working-copy root via svn info --show-item wc-root (probes cwd then cwd/repoDir), so SVN checkouts living in a vault subdirectory sync correctly | | parseFrontmatter(text) / extractFrontmatterBlock(text) | Simplified YAML frontmatter parsing | | generateSummaryWithFallback(entries, diffProvider?) | Natural-language change summary + file list | | toSummaryDiffLines(lines) | Adapt DiffLine[] to SummaryDiffLine[] |

SvnClient methods

| Method | Description | | --- | --- | | constructor(workingCopyPath, options?) | options: { svnBinaryPath?, enableDebugLog?, timeoutMs?, fileContentReader? } (default timeout 60s, 0 = none; fileContentReader: (relativePath) => Promise<Buffer \| null> reads unversioned/added file content for diff preview — the client does not depend on Node fs) | | isAvailable() / ensureAvailable() | Check svn --version; boolean vs throw | | getRevision() | svn info --show-item revisionstring \| null | | isWorkingCopy() | svn info success check | | status() | svn status --xmlSvnStatusEntry[] (sorted) | | update() | svn update → parsed UpdateResult | | diff(file, compareWithPrevious?, updateStatus?) | Single-file diff with normalization | | add/delete/revert/resolve(paths) | Write ops (throw on failure) | | commit(paths, message, {autoAdd?}) | Commit; auto-add unversioned files when autoAdd: true | | log(limit?) / logRange(old, new) | svn log --xml / --xml -vLogEntry[] | | diffSummarize(old, new) | svn diff --summarize → changed paths | | cat(rev, path) | File content at revision → string \| null | | diffFrontmatterFields(path, old, new) | Frontmatter field diffs between two revisions | | collectChanges(old, new) | { items: ChangeItem[], changedFiles: string[] } with author/revision attribution |

Development

npm install
npm test        # jest
npm run typecheck
npm run build   # tsc → dist (also runs on `npm install` via prepare)

License

MIT