@nystik/foundry-file-utils
v0.7.3
Published
A utility library for interfacing with Foundry's filesystem
Readme
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-utilsOtherwise 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'),
})
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, useforgevttto target the assets storage).path: the path to the directory. Parent directories are created if they do not exist.options(optional): Ifsourceequalss3, 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, useforgevttto target the assets storage).path: path to the target directory.file: a File object.options(optional): Ifsourceequalss3, 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, useforgevttto target the assets storage).path: path to the target directory.file: a File object.options(optional): Ifsourceequalss3, 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.pngconst 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 directoryactiveSource: the source identifier. e.g:data,publics3; additionally on the forge:forge-bazaarandforgevtt.bucket: name of the s3 bucket, ornullif source isn'ts3
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'
},
})
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.
