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 🙏

© 2024 – Pkg Stats / Ryan Hefner

filexplorer

v2.2.6

Published

A lightweight highly extensible, and highly configurable NodeJS web-based file explorer and utility kit.

Downloads

22

Readme

Filexplorer

A lightweight highly extensible, and highly configurable NodeJS web-based file explorer and utility kit.

Included features

The included plugins provide the following features:

  • Directory listings with file/folder information
  • Intelligent file type resolving
  • Full web interface for viewing files
    • Markdown rendered in browser
    • Syntax highlighting for text files
    • Embedded image, video and audio files
  • Ability to serve raw files, and falls back to doing so
  • Ability to upload files
  • Live scratchpad
  • Breadcrumb navigation
  • Dark mode
  • Non-browser clients are always served raw files

For more information, please read about each of the plugins below.

Screenshot showing this readme with markdown plugin

Installation

⚠️ Note that the package makes use of experimental node features and requires Node >= 18.

Standalone

Clone this repo and run the following to install dependencies and compile:

yarn start
yarn build

Run using yarn start. Alternatively you can start using node directly:

node --experimental-wasm-modules --experimental-import-meta-resolve lib

NPM Package

Filexplorer can be installed as an NPM package, which is useful if you plan to embed it or develop a plugin.

npm i filexplorer --save
# or
yarn add filexplorer

The package also includes a CLI which can be used for impromptu serving:

Note the CLI does not load the appListing, upload, or scratchpad plugins by default.

λ fe help
  Usage: fe [options] [command]
  
  Commands:
    help     Display help
  
  Options:
    -H, --help            Output usage information
    -h, --hostname        The host address to bind to
    -P, --plugins         The plugins to load, comma separated list
    -p, --port            The port to bind to
    -s, --serveDirectory  The path to the directory on disk to serve

Docker

A docker image is available and can be run like so:

docker run \
  -p 5000:5000 \
  -v config.corn:/opt/filexplorer/config.corn \ # Passing a config is optional
  -v data.db:/data.db \ # necessary to persist plugin data
  -v path/to/files:/srv/http \
  jakestanger/filexplorer

Configuration

The app works out of the box without any configuration, and by default all plugins are enabled.

To override the default configuration, create a config file using one of the following supported formats:

  • config.js, config.mjs, config.cjs
  • config.json
  • config.yaml, config.yml
  • config.toml
  • config.corn (useful for environment variables! see here)

Plugins may provide their own configuration options, which are namespaced under the plugin name. For example, the showHidden option for the directoryListing plugin should be set at directoryListing.showHidden.

| Name | Type | Default | Description | |------------------|----------|----------------------------------------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------| | hostname | string | 127.0.0.1 | Host address to listen on | | port | number | 5000 | Port to listen on | | cors | boolean | false | Whether to enable CORS support | | serveDirectory | string | . | Path on disk to the directory to serve | | baseUrl | string | / | URL path to use as 'root' | | caseSensitive | boolean | true | Whether file route handling should be case sensitive. Disable on Windows or on case-insensitive file systems. | | databasePath | string | data.db | Path to create/load database at | | plugins | string[] | ["directoryListing", "appListing", "markdown", "textFile", "mediaFile", "raw", "upload", "scratchpad"] | List of plugins to load, in the order they should be loaded |

The following environment variables are also respected and will override the configuration file:

  • HOSTNAME
  • PORT
  • SERVE_DIRECTORY
  • DATABASE_PATH

Example

An example config file in yaml is shown below, overriding the port, serve directory and directoryListing plugin options.

port: 5202
serveDirectory: '/srv/http/public'

directoryListing:
  showHidden = true
  relativeDates = false

Included plugins

The following plugins are

directoryListing

Shows a table of files and folders inside a directory. Each row has a link to the item, file size, and created/modified dates.

Directory listing plugin showing root of this repo

| Name | Type | Default | Description | |-----------------|---------|---------|--------------------------------------------------------------| | showHidden | boolean | false | Show hidden files and folders | | relativeDates | boolean | true | Display created/modified dates as relative from current time |

textFile

Shows the contents of plain text files in the web interface. Provides a link to the raw file (requires raw), a direct download, and the ability to copy to clipboard.

The file is syntax highlighted using highlight.js.

Text file plugin showing this package.json

| Name | Type | Default | Description | |----------------------|---------|-----------|----------------------------------------------------------------------------------------------------------------------------------------| | highlightTheme | string | default | The highlight.js theme to use for light mode. See here for a list | | highlightThemeDark | string | dark | The highlight.js theme to use for dark mode. See here for a list | | autoHighlight | boolean | false | Whether highlight.js should try to automatically detect syntax highlighting if the language could not be determined from the extension | | maxHighlightKb | number | 50 | The maximum file size in kB that should be highlighted | | handleSvg | boolean | false | Whether SVGs should be handled as text |

mediaFile

Shows the contents of images, videos and audio in the web interface. Provides a link to the raw file (requires raw) and a direct download.

Media file plugin showing emoji of a cake

This plugin provides no configuration options.

markdown

⚠ This plugin must be loaded before textFile

Renders markdown files in the web interface. Supports GFM and syntax highlighting.

Markdown plugin showing this readme

| Name | Type | Default | Description | |----------------------|---------|-----------|---------------------------------------------------------------------------------------------------------------------------------------| | highlight | boolean | true | Whether code blocks should be highlighted | | highlightTheme | string | default | The highlight.js theme to use for light mode. See here for a list | | highlightThemeDark | string | dark | The highlight.js theme to use for dark mode. See here for a list | | gfm | boolean | true | Whether to use Github Flavored Markdown |

raw

⚠ This plugin must be loaded after any other file handling plugins

Serves files statically without the web interface, letting the browser handle them.

If a file's type cannot be determined, the plugin will test if is a text file and force-serve it as one.

This plugin provides no configuration options.

appListing

App URL: /_/

Shows a list of available app plugins with the ability to navigate to each one.

This plugin provides no configuration options.

upload

App URL: /_/upload

Provides the ability to upload files. This can be done programmatically or via the web interface. Files are automatically given random names according to a chosen scheme.

For example to upload using cURL:

curl -F "file=@Pictures/Cake.png" -H "Authorization: 1234" http://localhost:5000

Upload plugin web interface

| Name | Type | Default | Description | |-----------------|-----------------------------------------------------|---------|-----------------------------------------------------------------------------------| | maxFileSize | number | null | Maximum allowed file size | | authorization | string | null | Expected HTTP Authorization header value. Leave blank to disable authorization. | | path | string | / | Path relative to served root to upload files to. | | nameScheme | hex \| uuid \| cuid \| adjective-adjective-animal | hex | Naming scheme to use for generating random names for uploaded files. |

scratchpad

App URL: /_/scratch

Provides a live scratchpad which can be used for quickly sharing text. Any client with the same URL will see the same content and will see changes apply near-instantly.

There are controls for instantly copying the scratchpad contents and URL.

Scratchpad plugin, including interface breadcrumbs, showing text in the pad

This plugin provides no configuration options.

Use as a library

⚠ This is very experimental still. Any issues discussing bugs/improvements are very welcome.

import { App } from 'filexplorer/lib/App.js';

// the promise will not resolve until the server receives a shutdown signal
// you can optionally pass a config
await App.init({ port: 5678 })

// close the server once you're done with it
App.server.close();

Developing plugins

⚠ This is very experimental still. Any issues discussing bugs/improvements are very welcome.

Plugins can be loaded from inside this codebase or as a standalone npm package.

A very basic example plugin is shown below:

import {
  InitEvent,
  MiddlewarePlugin,
  PluginManager,
} from '../../pluginManager.js';

interface IExampleConfig {
  // put your plugin config options here
  greeting: string;
}

// init hooks are called just before the web server starts
// and are useful for configuring any required modules based on the app config
const init: InitEvent<'example', IExampleConfig> = async ({ config }) => {
  // do init things!
  console.log(config.example.greeting ?? 'hello', 'world');
};

// middleware can be used for handling files/directories
// this is just express.js middleware under the hood
const exampleMiddeware: MiddlewarePlugin<'example', IExampleConfig> = async ({
                                                                               req,
                                                                               res,
                                                                               next
                                                                             }) => {
  res.send('hello from example');
};

// other available features for plugins:
// - `withAppMiddleware`: register middleware on a specific route to create an app
// - `withSocketIO`: passes a socket to a callback when the socket connects
// - `withDatabaseTable`: Ensures a database table exists with the provided schema
PluginManager.register('example').onInit(init).withMiddleware(markdown);

Your plugin can be loaded by adding it to the plugins config option. More information on this below:

Embedded

Create a new folder in src/plugins that matches your plugin name. This folder must contain an index.ts (or .js or .mts or .mjs) file.

Handlebars templates should be placed in the resources/plugins folder in the root of this repo.

To load an embedded plugin, add the plugin directory name to plugins config option.

Separate package

Create a new package. If necessary add filexplorer as a dev/peer dependency for development. Ensure your package has a main entrypoint set in the package.json.

Handlebars templates should be placed in the resources/plugins folder in the root of your package.

To load separate-package plugins, add the plugin package name to the plugins config option.

Theming

The app makes use of modern CSS features like custom properties to make theming as easy as possible. To make global CSS changes, apply these in public/index.css. For plugin-specific changes, these should be placed in the appropriate head.hbs template.