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

@appgeist/storage

v1.5.4

Published

An opinionated Express-based storage server featuring assets uploading and on-demand image-resizing, like a self-hosted Cloudinary

Downloads

96

Readme

@appgeist/storage

NPM version License

AppGeist Storage

An opinionated Express-based storage server featuring assets uploading and on-demand image-resizing. Like a self-hosted Cloudinary.

Uses ImageMagick, multer and UUID.

Requires ImageMagick with WebP support. Most linux distributions provide it by default and brew install imagemagick is everything you need to run to install it on macOS.

Why

Because:

  • Sometimes you want your assets to be stored on your own server;
  • Most browsers can display WebP images and you should definitely use the new format whenever possible instead of jpg, png or gif;
  • You need your pictures in various sizes and/or formats for different screen resolutions, sizes and device capabilities, but you don't always know all the possible combinations a priori.

Usage

Simple, with default options:

const storage = require("@appgeist/storage");

storage().listen(3000, err => {
  if (err) throw err;
  // eslint-disable-next-line no-console
  console.log("Storage server running...");
});

As Express middleware, with custom config options:

const express = require("express");
const storage = require("@appgeist/storage");

const app = express();
app.use(
  "/assets",
  storage({
    storageDir: "./files",
    tmpDir: "./temp-uploads",
    maxUploadSize: 1024 * 1024 * 50, // 50 megabytes
    pictureQuality: 90,
    maxPicturePixels: 3840 * 2160 // 4K
  })
);

app.listen(3000, err => {
  if (err) throw err;
  // eslint-disable-next-line no-console
  console.log("Server running...");
});

See @appgeist/example-storage-simple and @appgeist/example-storage-with-auth for more.

Default config options

Have a look at index.js to see the default config options; JSDoc comments are provided for IDE support.

Uploading files

Request payload

Files can be uploaded by POSTing to the mountpoint or a subfolder (i.e. POST /assets or POST /assets/a/subfolder/to/store/the/uploaded/files) with the following body payload:

{
  file: fileData;
}

...where file represents the file multipart/form-data (provided, for instance by an <input type="file" /> tag, see multer docs for more info).

Instead of simply uploading a file, the server can be instructed to dowload it from an accesible remote location by POSTing a URL instead of file data:

{
  url: "http://example.com/catz.jpg";
}

The uploaded file will end up in ${storageDir}/assets or a subfolder, such as ${storageDir}/assets/a/subfolder/to/store/the/uploaded/files.

A UUID/v4-based name will be generated for the uploaded file.

If the uploaded file is an image (jpg/webp/png/gif), it will be converted to webp using ImageMagick library and resized to maxPicturePixels, otherwise it will simply be stored in the original format.

Examples:

  • uploading catz.jpg to /assets will generate a file like /assets/9752d427-e6e2-4868-8abf-720db82421c2.webp;
  • uploading doc.pdf to /assets/docs will generate a file like /assets/docs/9752d427-e6e2-4868-8abf-720db82421c2.pdf;

Server response

When succesfully uploading catz.jpg to /assets/pics/animals, the server will respond with the following JSON:

{
  "path": "/pics/animals",
  "uuid": "9752d427-e6e2-4868-8abf-720db82421c2",
  "isPicture": true,
  "originalName": "catz.jpg",
  "aspectRatio": 1.77778
}

...where:

  • path is where the the image was uploaded;
  • uuid is a RFC-4122 unique identifier generated by UUID/v4;
  • isPicture is true (and false for non-picture uploads);
  • originalName is the original file name (or URL);
  • aspectRatio is the picture aspect ratio (determined by ImageMagick identify utility; this property is only present for picture file uploads).

Serving files

Stored picture files can be served in multiple formats, resized/centered/cropped to a specified size.

Assuming a 9752d427-e6e2-4868-8abf-720db82421c2 uuid was issued by a previous picture upload, new files will be generated and served to GET requests like so:

  • /9752d427-e6e2-4868-8abf-720db82421c2.webp will serve the original picture;
  • /9752d427-e6e2-4868-8abf-720db82421c2-w800-h600.webp will serve the picture resized/centered/cropped to a width of 800px and a height of 600px;
  • /9752d427-e6e2-4868-8abf-720db82421c2-w50-h50-lq.webp will serve a low-quality picture resized/centered/cropped to 50x50 pixels (useful for LQIPs).

Cropping and resizing only work for pictures. Other types of assets will only be served in the original format.

Caution

Files generated for different sizes and formats are never deleted. This can quickly eat up your server space. Make sure to implement your own mechanism to delete old/unnecessary files!!!

License

The ISC License.