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 🙏

© 2025 – Pkg Stats / Ryan Hefner

@opsimathically/dirmap

v1.0.6

Published

Recurses through all files and directories from a provided base directory, and provides information and utility.

Readme

dirmap

Recurse through the filesystem, stat and map individual files, directories, and devices, and store them within relevant maps as a file-info type, containing relevant permissions information for the current user, other users, etc. Developers determine what to map using callbacks; if no callback is provided, everything found will be mapped.

Map some, map none, map all, or just operate on individual files via callbacks individually. This code is useful for finding things like bad security permissions which could lead to system security problems, finding arbitrary files, finding files of certain sizes, md5 hashing files, etc. Subsequent runs on multiple directories will compound the maps so that one object can store multiple directory recursions.

To empty all the maps, reset state, and start fresh, use the dirmap.reset() method. Call dirmap.stop() from within found/fail callback to stop recursing. This code was designed to work on Linux.

Install

npm install @opsimathically/dirmap

Building from source

This package is intended to be run via npm, but if you'd like to build from source, clone this repo, enter directory, and run npm install for dev dependencies, then run npm run build.

Usage

import { DirMap, file_info_t } from '@opsimathically/dirmap';

(async function () {
  /*
  Entries are mapped via a filesystem absolute path as key and can be 
  accessed via individual maps shown below.  Maps are separated by type
  to reduce the work a developer would need to do to make this code 
  useful for their specific tasks.
  
  // this map holds all entries of all types
  dirmap.result_map

  // these maps hold only specific types
  dirmap.directory_map
  dirmap.block_dev_map
  dirmap.char_dev_map
  dirmap.fifo_map
  dirmap.file_map
  dirmap.socket_map
  dirmap.symlink_map
  dirmap.other_map
  */

  // create a new dirmap, execute it against the etc directory, map
  // all files and create md5 hashes.  No callback provided.
  const dirmap = new DirMap();
  await dirmap.run({
    base_dir: '/etc/',
    options: {
      generate_file_md5s: true
    }
  });

  // run dirmap again against /dev/ without resetting.  The results of
  // both runs will be within the dirmap map sets.  This time we do not
  // md5 discovered files since the option was not provided.
  await dirmap.run({
    base_dir: '/dev/'
  });

  // reset the maps to empty them all out and start fresh
  dirmap.reset();

  // run dirmap using a found callback.  This allows us to filter
  // what gets mapped and what doesn't.  In this case, we're just looking
  // for the /etc/hosts file.  Since we return true from the callback,
  // only on this file, all of our maps will only contain this single entry.
  // You an filter any file(s) you'd like, just return true when a file
  // matches your desired criteria, and it will be mapped.
  //
  // We use this.stop() to stop recursion after the file is found.
  //
  await dirmap.run({
    base_dir: '/etc/',
    onfoundcb: async function (this: DirMap, file_info: file_info_t) {
      if (file_info.absolute_path === '/etc/hosts') {
        this.stop();
        return true;
      }
      return false;
    }
  });

  // You can also supply a fail callback, that will let you determine
  // what failed to map due to whatever error.  We use any for the error
  // as we can get arbitrary error codes from arbitrary systems.
  await dirmap.run({
    base_dir: '/root/',
    onfoundcb: async function (this: DirMap, file_info: file_info_t) {
      return false;
    },
    onfailcb: async function (this: DirMap, absolute_path: string, err: any) {
      console.log(`Could not map: ${absolute_path}`);
      return false;
    }
  });
})();

Example File Entry Data

Each file mapped will correspond a file_info_t object, which will appear as follows.

// example object output for /etc/hosts
{
  name: 'hosts',
  raw_stats: {
    dev: 66306,
    mode: 33188,
    nlink: 1,
    uid: 0,
    gid: 0,
    rdev: 0,
    blksize: 4096,
    ino: 28708018,
    size: 315,
    blocks: 8,
    atimeMs: 1742196218432.5286,
    mtimeMs: 1737011996644.207,
    ctimeMs: 1737011996645.207,
    birthtimeMs: 1737011996644.207
  },
  type_info: {
    is_dir: false,
    is_block_dev: false,
    is_char_dev: false,
    is_fifo: false,
    is_file: true,
    is_socket: false,
    is_symlink: false
  },
  file_md5: undefined,
  permissions: {
    owner: {
      readable: true,
      writable: true,
      executable: false,
      suid: false,
      guid: false,
      sticky: false
    },
    group: {
      readable: true,
      writable: false,
      executable: false,
      suid: false,
      guid: false,
      sticky: false
    },
    others: {
      readable: true,
      writable: false,
      executable: false,
      suid: false,
      guid: false,
      sticky: false
    },
    processUser: {
      readable: true,
      writable: false,
      executable: false,
      suid: false,
      guid: false,
      sticky: false
    },
    sticky: false
  },
  absolute_path: '/etc/hosts',
  relative_path: '/hosts',
  base_path: '/etc',
  file_or_dir_path: '/etc',
  owner: { uid: 0, gid: 0 },
  process: { uid: 1000, gid: 1000 },
  extra: {}
}