diff --git a/README.md b/README.md index 1de571d5..7b919cfd 100644 --- a/README.md +++ b/README.md @@ -10,6 +10,7 @@ - [With Yarn/NPM](#with-yarnnpm) - [Vanilla JS](#vanilla-js) - [RemoteResource](#remoteresource) + - [PenumbraFile](#penumbrafile) - [.get](#get) - [.encrypt](#encrypt) - [.encrypt() examples:](#encrypt-examples) @@ -134,6 +135,35 @@ type RemoteResource = { }; ``` +### PenumbraFile + +Encryption & decryption APIs work on PenumbraFile descriptors to that store file data and metadata. + +```ts +/** Penumbra file composition */ +export interface PenumbraFile extends Omit { + /** Backing stream */ + stream: ReadableStream; + /** File size (if backed by a ReadableStream) */ + size?: number; + /** Optional ID for tracking encryption completion */ + id?: number | string; + /** Last modified date */ + lastModified?: Date; +} +``` + +Native File objects can be converted for use with penumbra APIs through `penumbra.importFile(file: File, path?: string)` and can be used to encrypt and decrypt files. + +```ts +// Automatically encrypt & save files selected in a file selector +const fileSelector = document.getElementById('file-selector'); +fileSelector.addEventListener('change', (event) => { + const file = await penumbra.importFile(event.target.files[0]); + penumbra.encrypt(file).then(penumbra.save); +}); +``` + ### .get Fetch and decrypt remote files. @@ -346,7 +376,7 @@ await writer.close(); ### .setWorkerLocation -Configure the location of Penumbra's worker threads. +Configure the location of Penumbra's worker threads. This should be called before any other Penumbra methods and is not currently reconfigurable post-initialization. ```ts penumbra.setWorkerLocation(location: WorkerLocationOptions | string): Promise diff --git a/package.json b/package.json index a6627eff..5763b8b9 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@transcend-io/penumbra", - "version": "5.3.2", + "version": "5.4.1", "description": "Crypto streams for the browser.", "main": "dist/main.penumbra.js", "types": "ts-build/src/index.d.ts", diff --git a/src/API.ts b/src/API.ts index 6b20e98e..889e3747 100644 --- a/src/API.ts +++ b/src/API.ts @@ -581,9 +581,26 @@ function getTextOrURI(files: PenumbraFile[]): Promise[] { }); } +/** + * Convert HTML File object to a PenumbraFile + * + * @param file - File to import + * @param path - File path + * @returns PenumbraFile + */ +async function importFile(file: File, path?: string): Promise { + return { + stream: new Response(await file.arrayBuffer()).body as ReadableStream, + size: file.size, + mimetype: file.type, + path, + }; +} + const penumbra = { preconnect, preload, + importFile, get, encrypt, decrypt, diff --git a/src/mock.ts b/src/mock.ts index fc406bfe..90f51d97 100644 --- a/src/mock.ts +++ b/src/mock.ts @@ -9,6 +9,12 @@ const supported = (): PenumbraSupportLevel => -0; supported.levels = PenumbraSupportLevel; const MOCK_API: PenumbraAPI = { + importFile: async (file, path) => ({ + stream: new Response(await file.arrayBuffer()).body as ReadableStream, + size: file.size, + mimetype: file.type, + path, + }), get: async () => [], save: () => new AbortController(), supported,