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

foldnize

v1.0.1

Published

Organize photos and videos by their embedded EXIF/QuickTime original date — three renaming modes, optional Year/Month folder sorting, dry-run preview.

Readme

foldnize

Organize photos and videos by their embedded EXIF/QuickTime original date, programmatically or from the command line.

  • Three renaming modes: prefix · replace · custom
  • Optional Year/Month folder sorting (<root>/YYYY/MM/)
  • Dry-run preview before touching disk
  • Streamed log of every action via callback
  • 100% local — no network, no telemetry
  • Written in TypeScript, ships compiled JS + .d.ts types, zero runtime dependencies
  • Powers the Foldnize desktop app

Install

npm install foldnize

System tools (optional but recommended)

foldnize shells out to read embedded metadata. Install one or both:

brew install exiftool       # photos, audio, and most video metadata
brew install ffmpeg         # ffprobe — fallback for .mp4 and .mov video files

Supported formats: .jpeg, .jpg, .mov, .mp3, .mp4, .png

Files without parseable date metadata are silently skipped — never crash.

Library usage

import {
  organizeFolder,
  type OrganizeOptions,
  type OrganizeSummary,
  type Mode,
} from "foldnize";
// CommonJS works too: const { organizeFolder } = require("foldnize");

const summary: OrganizeSummary = organizeFolder({
  root: "/Users/you/Pictures/2023",
  mode: Mode.CUSTOM, // Mode.PREFIX | Mode.REPLACE | Mode.CUSTOM
  customName: "vacation", // required when mode === Mode.CUSTOM
  organizeIntoYearMonth: true, // move files into <root>/YYYY/MM/
  scanSubfolders: true, // recurse (default); false = top-level only
  dryRun: true, // preview only — no disk writes
  onLog: ({ level, message }) => console.log(`[${level}] ${message}`),
});

console.log(summary);
// {
//   found: 12,
//   renamed: 8,
//   moved: 4,
//   skipped: 4,
// }

A file can appear in both renamed and moved counts if it changes name AND directory.

Modes

| Mode | Result | Example | | --------- | --------------------------------------------- | ----------------------------------------------- | | prefix | Keep original name, add YYYYMMDD- in front. | IMG_1234.jpg20230715-IMG_1234.jpg | | replace | Fully rename to YYYYMMDD-HHMMSS.ext. | IMG_1234.jpg20230715-142310.jpg | | custom | Fully rename to {name}-YYYYMMDD-HHMMSS.ext. | IMG_1234.jpgvacation-20230715-142310.jpg |

Log levels

onLog receives { level, message } for every step:

| Level | Meaning | | --------- | ------------------------------------------------------- | | info | Configuration banner before scanning starts. | | renamed | File was renamed in place (same directory). | | moved | File was moved (possibly renamed too). | | dry | Dry-run preview line. | | skip | File was untouched (no metadata, already formatted, …). | | error | Something went wrong with a specific file. | | done | Final summary line. |

Other exports

import {
  organizeFolder,
  sanitizeCustomName, // (unknown) => string — same rules as in CLI
  getOriginalFileDateParts, // (filePath: string) => DateParts | null
  formatDateToParts, // (dateString: string | null) => DateParts | null
  VALID_EXTENSIONS, // ReadonlySet — see formatSupportedExtensions()
  formatSupportedExtensions, // () => ".jpeg", ".jpg", ".mov", …
  type DateParts,
  type Mode,
  type LogEntry,
  type LogLevel,
  type OrganizeOptions,
  type OrganizeSummary,
} from "foldnize";

CLI usage

The package ships a CLI you can run without installing globally:

npx foldnize --root=./photos --mode=prefix --dry-run
npx foldnize --root=./photos --mode=replace --year-month
npx foldnize --root=./photos --mode=custom --custom-name=vacation
npx foldnize --root=./photos --year-month --no-subfolders

Options

--root=PATH               Folder to scan (default: current directory)
--mode=prefix|replace|custom
--custom-name=NAME        Required when --mode=custom
--year-month              Move files into <root>/YYYY/MM/
--no-subfolders           Don't recurse — only top-level files
--dry-run                 Preview without touching disk
--help, -h
--version, -v

Behaviour notes

  • macOS junk files (._*) are always skipped.
  • Collisions are handled by appending -1, -2, … to the target name.
  • Already-formatted files are detected and skipped for renames; they still get moved if --year-month is on and their date metadata points to a different folder than where they currently sit.
  • Empty source folders left behind after moves are NOT deleted. That's intentionally non-destructive.

Requirements

  • Node.js 22+

Publishing

Releases to npm are automated via GitHub Actions when you publish a GitHub Release. See .github/PUBLISHING.md for the NPM_TOKEN secret, environment setup, and release tags like foldnize-v1.0.0.

Development

git clone https://github.com/matheuschignolli/foldnize.git
cd foldnize/library
npm install

npm run build       # compile TypeScript → dist/
npm run build:watch # incremental rebuilds
npm run typecheck   # type-check tests too (no emit)
npm test            # run the test suite (via tsx, no separate compile step)
npm run clean       # remove dist/

Source lives in src/ (TypeScript). Compiled output lands in dist/ and is the only thing that ships to npm.

License

MIT