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

@prefabs.tech/fastify-s3

v0.93.1

Published

Fastify S3 plugin

Readme

@prefabs.tech/fastify-s3

A Fastify plugin that provides an easy integration of S3 in a fastify API.

Requirements

Installation

Install with npm:

npm install @prefabs.tech/fastify-config @prefabs.tech/fastify-slonik @prefabs.tech/fastify-s3

Install with pnpm:

pnpm add --filter "@scope/project" @prefabs.tech/fastify-config @prefabs.tech/fastify-slonik @prefabs.tech/fastify-s3

Usage

Permission

When using AWS S3, you are required to enable the following permissions:

Required Permission:

  • GetObject Permission
  • GetObjectAttributes Permission
  • PutObject Permission

Optional Permissions:

  • ListBucket Permission
    • If you choose the add-suffix option for FilenameResolutionStrategy when dealing with duplicate files, then you have to enable this permission.
  • DeleteObject Permission
    • If you use the deleteFile method from the file service, you will need this permission

Sample S3 Permission:

  {
      "Version": "2012-10-17",
      "Statement": [
          {
              "Effect": "Allow",
               "Principal": "*",
              "Action": [
                  "s3:ListBucket"
              ],
              "Resource": "arn:aws:s3:::your-bucket"
          },
          {
              "Effect": "Allow",
              "Principal": "*",
              "Action": [
                  "s3:DeleteObject",
                  "s3:GetObject",
                  "s3:GetObjectAttributes",
                  "s3:PutObject"
              ],
              "Resource": "arn:aws:s3:::your-bucket/*"
          }
      ]
  }

Register plugin

Register the file fastify-s3 package with your Fastify instance:

import configPlugin from "@prefabs.tech/fastify-config";
import s3Plugin, { multipartParserPlugin } from "@prefabs.tech/fastify-s3";
import slonikPlugin from "@prefabs.tech/fastify-slonik";
import Fastify from "fastify";

import config from "./config";

const start = async () => {
  // Create fastify instance
  const fastify = Fastify({
    logger: config.logger,
  });

  // Register config plugin
  await fastify.register(configPlugin, { config });

  // Register database plugin
  await fastify.register(slonikPlugin, config.slonik);
  
  // Register fastify-s3 plugin
  await fastify.register(s3Plugin);
  
  await fastify.listen({
    port: config.port,
    host: "0.0.0.0",
  });
}

start();

Configuration

To initialize Client:

AWS S3 Config

const config: ApiConfig = {
  // ... other configurations
  
  s3: {
    //... AWS S3 client config
    clientConfig: {
      credentials: {
        accessKeyId: "accessKey",   // Replace with your AWS access key
        secretAccessKey: "secretKey",   // Replace with your AWS secret key
      },
      region: "ap-southeast-1" // Replace with your AWS region
    },
    bucket: "" | { key: "value" }, // Specify your S3 bucket
  }
};

Credentials on EC2 (IAM Role)

If your application is running on an EC2 instance (or ECS, Lambda, or any AWS environment with an IAM Role attached), you do not need to provide AWS credentials explicitly.

The AWS SDK for JavaScript automatically retrieves temporary credentials from the Instance Metadata Service (IMDS).

As long as your EC2 instance has an IAM Role with the correct S3 permissions (e.g., s3:GetObject, s3:PutObject), the SDK will handle authentication for you.

Minio Service Config

const config: ApiConfig = {
  // ... other configurations
  
  s3: {
    clientConfig: {
      credentials: {
        accessKeyId: "yourMinioAccessKey",
        secretAccessKey: "yourMinioSecretKey",
      },
      endpoint: "http://your-minio-server-url:port", // Replace with your Minio server URL
      forcePathStyle: true, // Set to true if your Minio server uses path-style URLs
      region: "" // For Minio, you can leave the region empty or specify it based on your setup
    },
    bucket: "yourMinioBucketName",
  }
};

To add a custom table name:

const config: ApiConfig = {
  // ... other configurations
  
  s3: {
    //... AWS S3 client config
    table: {
        name: "new-table-name" // You can set a custom table name here (default: "files")
    }
  }
};

To limit the file size while uploading:

const config: ApiConfig = {
  // ... other configurations
  
  s3: {
    //... AWS S3 client config
    fileSizeLimitInBytes: 10485760
  }
};

To handle duplicate filenames:

  • FilenameResolutionStrategy: This option has three choices: override, add-suffix, and error.

    • error: If you choose the error option, it will throw an error if the file name is duplicated in the S3 bucket.
    • add-suffix: If you choose the add-suffix option, it will append -<number> to the file name if it is duplicated.For example, if the filename is example.png which is already exist on S3 bucket, the new name will be example-1.png.
    • override: This is the default option and it overrides the file if the file name already exists.
      fileService.upload({
        // ... other options
        options: {
          // ... other options
          filenameResolutionStrategy: "add-suffix",
        },
      });

Using GraphQL

This package supports integration with @prefabs.tech/fastify-graphql.

Register additional multipartParserPlugin plugin with the fastify instance as shown below:

import configPlugin from "@prefabs.tech/fastify-config";
import graphqlPlugin from "@prefabs.tech/fastify-graphql";
import s3Plugin, { multipartParserPlugin } from "@prefabs.tech/fastify-s3";
import slonikPlugin from "@prefabs.tech/fastify-slonik";
import Fastify from "fastify";

import config from "./config";

const start = async () => {
  // Create fastify instance
  const fastify = Fastify({
    logger: config.logger,
  });
  
  // Register config plugin
  await fastify.register(configPlugin, { config });
  
  // Register database plugin
  await fastify.register(slonikPlugin, config.slonik);

  // Register multipart content-type parser plugin (required for graphql file upload or if using both graphql and rest file upload)
  await fastify.register(multipartParserPlugin);

  // Register graphql plugin
  await fastify.register(graphqlPlugin, config.graphql);

  // Register fastify-s3 plugin
  await fastify.register(s3Plugin);

  await await.listen({
    port: config.port,
    host: "0.0.0.0",
  });
}

start();

Note: Register the multipartParserPlugin if you're using GraphQL or both GraphQL and REST, as it's required. Make sure to place the registration of the multipartParserPlugin above the graphqlPlugin.

JSON Schema with Swagger

If you want to use @prefabs.tech/fastify-s3 with @fastify/swagger and @fastify/swagger-ui or @prefabs.tech/swagger you must add a new type called isFile and use a custom instance of a validator compiler

import configPlugin from "@prefabs.tech/fastify-config";
import graphqlPlugin from "@prefabs.tech/fastify-graphql";
import s3Plugin, {
  ajvFilePlugin,
  multipartParserPlugin,
} from "@prefabs.tech/fastify-s3";
import slonikPlugin from "@prefabs.tech/fastify-slonik";
import Fastify from "fastify";

import config from "./config";

const start = async () => {
  // Create fastify instance
  const fastify = Fastify({
    logger: config.logger,
    // ...
    ajv: {
      plugins: [ajvFilePlugin],
    },
  });
  
  // Register config plugin
  await fastify.register(configPlugin, { config });
  
  // Register database plugin
  await fastify.register(slonikPlugin, config.slonik);

  // Register multipart content-type parser plugin (required for graphql file upload or if using both graphql and rest file upload)
  await fastify.register(multipartParserPlugin);

  // Register graphql plugin
  await fastify.register(graphqlPlugin, config.graphql);

  // Register fastify-s3 plugin
  await fastify.register(s3Plugin);

  fastify.post('/upload/file', {
    schema: {
      description: "Upload a file",
      tags: ["file"],
      consumes: ["multipart/form-data"],
      body: {
        type: "object",
        properties: {
          file: { isFile: true },
        },
      },
    }
  }, function (req, reply) {
    console.log({ body: req.body })
    reply.send('done')
  })

  await await.listen({
    port: config.port,
    host: "0.0.0.0",
  });
}

start();