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 🙏

© 2026 – Pkg Stats / Ryan Hefner

@nystik/foundry-file-utils

v0.7.3

Published

A utility library for interfacing with Foundry's filesystem

Readme

Latest Release) Foundry Core Supported Versions

Foundry File Utils

NOTE: This project is in initial development and the API is subject to change. The API will be considered established on version 1.0.0 as per Semantic Versioning Specification.

A collection of abstractions, helpers, and enhancements for interacting with files and directories in Foundry Virtual Tabletop

Includes:

  • A FilePicker Svelte component that displays the source (and bucket in the case of s3 storage) of the path selected.
  • A type constructor to easily use the improved FilePicker in settings, storing source, bucket, and path as json.
  • Helper functions to handle various file operations like: creating directory paths, uploading files from URLs, etc.

Installation

If you're using a bundler for your module you can use the CommonJS module available on NPM, complete with TypeScript definitions:

npm install --save-dev @nystik/foundry-file-utils

Otherwise you can set this module as a dependency in your manifest.

"dependencies": [
  {
    "name": "foundry-file-utils",
    "manifest": "https://gitlab.com/dnd-5e/foundry-vtt/foundry-file-utils/-/raw/main/src/module.json",
  }
]

Basic Usage

The library module is loaded on init and available at ready. It can be invoked in three different ways:

Using a global variable.

window.FileUtils.createDirectory('path/to/dir')

By grabbing the module.

const module = game.modules.get('foundry-file-utils')

if (module) {
  module.api.createDirectory('path/to/dir')
}

Or by using the hook fileUtilsReady.

Hooks.on('fileUtilsReady', (fileUtils) => {
  fileUtils.createDirectory('path/to/dir')
})

Using in settings

When registering settings, you can use the type constructor Types.FilePicker(type); where type is a valid type for the built-in FilePicker. If type is left undefined then the FilePicker will let you pick any file type.

A default value of this FilePicker must be an object containing the properties: path, activeSource, and bucket.

game.settings.register('my-module', 'upload-dir', {
  ...
  type: window.FileUtils.Types.FilePicker('folder'),
  default: {
    path: 'my-module/images',
    activeSource: 'data', // Can be 'data' (for user data), 'public' (for core data), or 's3' (for s3 buckets, duh)
    bucket: null
  },
})
game.settings.register('my-module', 'sound-effect', {
  ...
  type: window.FileUtils.Types.FilePicker('audio'),
})

Settings Screenshot

API reference

async createDirectory(source, path, [options])

Creates a directory path in the specified file source.

  • source: a string of type FilePicker.activeSource (if running on the Forge, use forgevtt to target the assets storage).
  • path: the path to the directory. Parent directories are created if they do not exist.
  • options (optional): If source equals s3, this parameter is required.
    • bucket: the name of the s3 bucket

Returns (Promise): true if the directory was created, otherwise returns false.

const success = await FileUtils.createDirectory('data', 'path/to/create')

// if source equals 's3' then a bucket name is required.
const success = await FileUtils.createDirectory('s3', 'path/to/create', { bucket: 'bucket-name' })

async downloadFile(url, [filename])

Download a file and save it as the specified filename. If no filename is provided, it will attempt to infer the filename from the response data and url.

  • url: url of the file.
  • filename (optional): a filename without extension.

Returns (Promise): a File object, or null on a bad response.

const file = await FileUtils.downloadFile('https://example.com/image.jpg')
// file.name == 'image.jpg'

const file = await FileUtils.downloadFile('https://example.com/image.jpg', 'download')
// file.name == 'download.jpg'

// e.g. content-type === "audio/aac"
const file = await FileUtils.downloadFile('https://example.com/birdnoise')
// file.name == 'birdnoise.aac'

async uploadFile(source, path, file, [options])

Upload a file to a specified file source and path.

  • source: a string of type FilePicker.activeSource (if running on the forge, use forgevtt to target the assets storage).
  • path: path to the target directory.
  • file: a File object.
  • options (optional): If source equals s3, this parameter is required.
    • bucket: the name of the s3 bucket.

Returns (Promise): a Response object which also contains the path of the uploaded file as response.path.

const response = await FileUtils.uploadFile('data', 'path/to/dir', file)

// if source equals 's3' then a bucket name is required.
const response = await FileUtils.uploadFile('data', 'path/to/dir', file, { bucket: 'bucket-name' })

async uploadFileFromUrl([transform])(source, path, file, [options])(url, [filename])

Function composition to download a file from a url, perform an optional transform function, and then upload the file to foundry.

  • transform: a transform function which takes a File object as a parameter, and returns a modified File object. Can be either synchronous or asynchronous.

  • source: a string of type FilePicker.activeSource (if running on the forge, use forgevtt to target the assets storage).
  • path: path to the target directory.
  • file: a File object.
  • options (optional): If source equals s3, this parameter is required.
    • bucket: the name of the s3 bucket.

  • url: url to download.
  • filename (optional): a filename without extension.

Returns (Promise): a Response object which also contains the path of the uploaded file as response.path.

const crop = (file: File) => {
  // crop image
  ...
  return file
}

const response = await FileUtils.uploadFileFromUrl(crop)(
  's3',
  'tokens/cropped',
  { bucket: 'fvtt' }
  )('https://example.com/token.png', 'cropped_token')
// uploaded to tokens/cropped/cropped_token.png
const upload = FileUtils.uploadFileFromUrl()('data', 'images/tokens')

// upload all files to 'images/tokens'
const promises = []
for (const url of links) {
  promises.push(upload(url))
}
await Promise.all(promises)

fileFromBlob(blob, filename)

Create a File object from a given blob

  • url: blob of data.
  • filename: name of the file.

Returns: a File object.


Classes.ExtendedFilePicker

A modified FilePicker class. The only difference between this picker and the built-in one is that when a file is selected (submitted) it sets the linked fields value to a json string containing path, activeSource, and bucket instead of just the path.

  • json object:
    • path: path to file or directory
    • activeSource: the source identifier. e.g: data, public s3; additionally on the forge: forge-bazaar and forgevtt.
    • bucket: name of the s3 bucket, or null if source isn't s3

Components.FilePicker

A Svelte component that displays the source of the selected path. Refer to Svelte Documentation for more details on usage.

const component = new FilePickerComponent({
  target: containerHTMLElement,
  props: {
    name: 'input-field-name',
    type: 'folder', // 'folder', 'image', 'imagevideo', 'video', 'audio' (if undefined, allows any file type).
    value: JSON.stringify({ path: 'my-module/tokens', activeSource: 'data' }), // if activeSource is 's3' you should also specify 'bucket'
  },
})

Svelte Component Screenshot


Types.FilePicker(type)

A factory function for when registering settings

  • type: a string of type FilePicker.type. If omitted the file picker will allow any file.

Returns: a named constructor function.

game.settings.register('my-module', 'sound-effect', {
  ...
  type: window.FileUtils.Types.FilePicker('audio'),
})

Types.TYPE_PREFIX

The prefix used by the type constructor, can be used in conjunction with DOM.injectComponents to inject the Svelte component into other html than just settings.


DOM.injectComponents(html)

Injects the Svelte component into DOM. It replaces any input field with data-dtype matching ${TYPE_PREFIX}_${type} where type is a FilePicker.type.

  • html: the html to inject the component into.

License

This project is licensed under the MIT license, see LICENSE for details.