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

sanity-plugin-digital-ocean-files

v1.0.1

Published

Store Sanity media files in Digital Ocean Spaces

Downloads

162

Readme

Sanity.io plugin for storing large files in Digital Ocean Spaces

Allows uploading, referencing and deleting files to DigitalOcean directly from your Sanity studio. Is a flavor of sanity-plugin-external-files.

Screenshot of the plugin

Installing

Start by installing the plugin:

npm i sanity-plugin-digital-ocean-files
# or yarn add / pnpm i

Then, include the plugin in your sanity.config.(js|ts):

import { digitalOceanFiles } from 'sanity-plugin-digital-ocean-files'
import { defineConfig } from 'sanity'

export default defineConfig({
  // ...
  plugins: [
    digitalOceanFiles({
      toolTitle: 'Media Library',
      // If you want to restrict file types library-wide:
      // defaultAccept: {
      //   'application/pdf': ['pdf'],
      //   'video/*': ['mp4', 'mov', 'webm'],
      // },

      // 2 ways to set credentials, one being through code
      credentials: {
        bucketKey: 'my-space-name',
        bucketRegion: 'region1',
        // ...
      },
    }),
    // ...
  ],
})

And use its digital-ocean-files.media type in schemas you want to use DigitalOcean files from:

// Example of usage in a Sanity schema
export default {
  name: 'caseStudy',
  type: 'document',
  fields: [
    // ...
    {
      name: 'featuredVideo',
      type: 'digital-ocean-files.media',
      options: {
        // Optional: set which file types are accepted in a field
        accept: {
          'video/*': ['mp4', 'webm', 'mov'],
        },

        // Optional: obfuscate original file names
        storeOriginalFilename: false,
      },
    },
  ],
}

Note: if you've customized schemaPrefix in your plugin's configuration, the schema name will be ${schemaPrefix}.media instead of digital-ocean-files.media.

Configuring the DigitalOcean Space

The rest of the work must be done inside DigitalOcean's console:

  • Create a public Digital Ocean Space (or use an existing one)
  • Configure CORS for your Space to accept the origins your studio will be hosted in (including localhost)
  • To use the Spaces API, you need to create an access key and secret key for your Space from the API page in the control panel.
  • Create server endpoints for creating the pre-signed URLs we'll use to post objects to DigitalOcean and deleting objects
    • The implementation is up to you: use traditional serverless functions like AWS Lambda, API routes from metaframeworks like NextJS, Remix and SvelteKit, traditional stateful servers like Express or even write these in other languages.
    • As long as they return the pre-signed URL and delete the requested object, they're valid.
    • For a minimal Javascript example, refer to do.getSignedUrl.js and do.deleteObject.js

With these in hand, fill-in the plugin's configuration form where you'll fill in the bucket key (ex: my-sanity-bucket), the Space region (ex: nyc3), the URL for both server endpoints and an secret for validating input in functions. See below:

Adding configuration to the plugin

You can add the configuration via code in the credentials of the digitalOceanFiles plugin function or inside of the studio inside the settings dialog. You can also do a mix of both if you want the convenience of code-hosted values with the security of Sanity-stored values. For example:

digitalOceanFiles({
  // Store public-facing info in code, which will show up in the JS bundle
  credentials: {
    bucketKey: 'my-space-name',
    bucketRegion: 'region1',
    folder: 'custom-assets/folder',
    subdomain: undefined,

    // But leave sensitive info like `getSignedUrlEndpoint`, `deleteObjectEndpoint` and `secretForValidating` to be stored as a private document in the Sanity dataset
  },
}),

Of course, if you're making strong security guarantees in your endpoints, you can store these credentials in code without an issue.

Data structure & querying

Each media item is a Sanity document that holds information of the object stored in DigitalOcean, like its fileURL, contentType and fileSize. It's analogous to Sanity's sanity.imageAsset and sanity.fileAsset: they're pointers to the actual blob, not the files themselves.

These files' type is digital-ocean-files.storedFile (or ${schemaPrefix}.media if you've customized schemaPrefix).

When selected by other document types, media is stored as references to these file documents. You can get the URL of the actual assets by following references in GROQ:

*[_type == 'caseStudy'] {
  ...,
  // Example of fetching the file in a `featuredVideo` field
  featuredVideo-> {
    fileSize,
    fileURL,
    digitalOcean {
      key,
      originURL,
    },
  },
}

Contributing, roadmap & acknowledgments

Refer to sanity-plugin-external-files for those :)