Skip to content

Commit

Permalink
fix(typing): Imporve typing (#21)
Browse files Browse the repository at this point in the history
* only return true when fail

* fix nodes keepData option

* do lazy import

* lazy import when needed

* better jsdoc + lazy import

* better jsdoc + lazy import

* seperated fromInput to two fn (dir and file)

* fix jsdoc
  • Loading branch information
jimmywarting authored Oct 2, 2021
1 parent 7d90f6f commit 741be20
Show file tree
Hide file tree
Showing 9 changed files with 65 additions and 64 deletions.
9 changes: 6 additions & 3 deletions src/FileSystemDirectoryHandle.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import FileSystemHandle from './FileSystemHandle.js'
import FileSystemFileHandle from './FileSystemFileHandle.js'

const kAdapter = Symbol('adapter')

Expand All @@ -25,14 +24,17 @@ class FileSystemDirectoryHandle extends FileSystemHandle {
return new FileSystemDirectoryHandle(await this[kAdapter].getDirectoryHandle(name, options))
}

/** @returns {AsyncGenerator<[string, FileSystemHandle]>} */
/** @returns {AsyncGenerator<[string, FileSystemHandle | FileSystemDirectoryHandle]>} */
async * entries () {
const {FileSystemFileHandle} = await import('./FileSystemFileHandle.js')

for await (const [_, entry] of this[kAdapter].entries())
yield [entry.name, entry.kind === 'file' ? new FileSystemFileHandle(entry) : new FileSystemDirectoryHandle(entry)]
}

/** @deprecated use .entries() instead */
async * getEntries() {
const {FileSystemFileHandle} = await import('./FileSystemFileHandle.js')
console.warn('deprecated, use .entries() instead')
for await (let entry of this[kAdapter].entries())
yield entry.kind === 'file' ? new FileSystemFileHandle(entry) : new FileSystemDirectoryHandle(entry)
Expand All @@ -42,9 +44,9 @@ class FileSystemDirectoryHandle extends FileSystemHandle {
* @param {string} name Name of the file
* @param {object} [options]
* @param {boolean} [options.create] create the file if don't exist
* @returns {Promise<FileSystemFileHandle>}
*/
async getFileHandle (name, options = {}) {
const {FileSystemFileHandle} = await import('./FileSystemFileHandle.js')
if (name === '') throw new TypeError(`Name can't be an empty string.`)
if (name === '.' || name === '..' || name.includes('/')) throw new TypeError(`Name contains invalid characters.`)
options.create = !!options.create
Expand All @@ -63,6 +65,7 @@ class FileSystemDirectoryHandle extends FileSystemHandle {
return this[kAdapter].removeEntry(name, options)
}

// TODO: jsdoc
async resolve (possibleDescendant) {
if (await possibleDescendant.isSameEntry(this)) {
return []
Expand Down
2 changes: 1 addition & 1 deletion src/adapters/deno.js
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ export class FileHandle {
return this.#path
}

/** @param {{ keepExistingData: any; }} opts */
/** @param {{ keepExistingData: boolean; }} opts */
async createWritable (opts) {
const fileHandle = await Deno.open(this.#path, { write: true, truncate: !opts.keepExistingData }).catch(err => {
if (err.name === 'NotFound') throw new DOMException(...GONE)
Expand Down
5 changes: 3 additions & 2 deletions src/adapters/node.js
Original file line number Diff line number Diff line change
Expand Up @@ -112,8 +112,9 @@ export class FileHandle {
return this._path
}

async createWritable () {
const fileHandle = await fs.open(this._path, 'r+').catch(err => {
/** @param {{ keepExistingData: boolean; }} opts */
async createWritable (opts) {
const fileHandle = await fs.open(this._path, opts.keepExistingData ? 'r+' : 'w+').catch(err => {
if (err.code === 'ENOENT') throw new DOMException(...GONE)
throw err
})
Expand Down
5 changes: 2 additions & 3 deletions src/getOriginPrivateDirectory.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
/* global DataTransfer, DataTransferItem */

import FileSystemDirectoryHandle from './FileSystemDirectoryHandle.js'
/** @typedef {import('./FileSystemDirectoryHandle.js').default} FileSystemDirectoryHandle */

if (globalThis.DataTransferItem && !DataTransferItem.prototype.getAsFileSystemHandle) {
DataTransferItem.prototype.getAsFileSystemHandle = async function () {
Expand Down Expand Up @@ -34,6 +32,7 @@ async function getOriginPrivateDirectory (driver, options = {}) {
if (!driver) {
return globalThis.navigator?.storage?.getDirectory() || globalThis.getOriginPrivateDirectory()
}
const {FileSystemDirectoryHandle} = await import('./FileSystemDirectoryHandle.js')
const module = await driver
const sandbox = module.default ? await module.default(options) : module(options)
return new FileSystemDirectoryHandle(sandbox)
Expand Down
19 changes: 9 additions & 10 deletions src/showDirectoryPicker.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
/** @typedef {import('./FileSystemDirectoryHandle.js').default} FileSystemDirectoryHandle */

const native = globalThis.showDirectoryPicker

/**
* @param {Object} [options]
* @param {boolean} [options._preferPolyfill] If you rather want to use the polyfill instead of the native
* @returns Promise<FileSystemDirectoryHandle>
* @returns {Promise<FileSystemDirectoryHandle>}
*/
async function showDirectoryPicker (options = {}) {
if (native && !options._preferPolyfill) {
Expand All @@ -26,18 +28,15 @@ async function showDirectoryPicker (options = {}) {

input.webkitdirectory = true

// Lazy load while the user is choosing the directory
const p = import('./util.js')

return new Promise(resolve => {
// Lazy load while the user is choosing the directory
const p = import('./util.js').then(m => m.fromInput)

input.addEventListener('change', () => {
resolve(p.then(fn => fn(input)))
document.body.removeChild(input)
})

await new Promise(resolve => {
input.addEventListener('change', resolve)
input.click()
})

return p.then(mod => mod.getDirHandlesFromInput(input))
}

export default showDirectoryPicker
Expand Down
21 changes: 10 additions & 11 deletions src/showOpenFilePicker.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
const def = {
accepts: []
}
/** @typedef {import('./FileSystemFileHandle.js').default} FileSystemFileHandle */

const def = { accepts: [] }
const native = globalThis.showOpenFilePicker

/**
Expand All @@ -9,7 +9,7 @@ const native = globalThis.showOpenFilePicker
* @param {boolean} [options.excludeAcceptAllOption=false] Prevent user for selecting any
* @param {Object[]} [options.accepts] Files you want to accept
* @param {boolean} [options._preferPolyfill] If you rather want to use the polyfill instead of the native
* @returns Promise<FileSystemDirectoryHandle>
* @returns {Promise<FileSystemFileHandle[]>}
*/
async function showOpenFilePicker (options = {}) {
const opts = { ...def, ...options }
Expand All @@ -35,16 +35,15 @@ async function showOpenFilePicker (options = {}) {
input.style.left = '-100000px'
document.body.appendChild(input)

return new Promise(resolve => {
// Lazy load while the user is choosing the directory
const p = import('./util.js').then(m => m.fromInput)

input.addEventListener('change', () => {
resolve(p.then(fn => fn(input)))
})
// Lazy load while the user is choosing the directory
const p = import('./util.js')

await new Promise(resolve => {
input.addEventListener('change', resolve)
input.click()
})

return p.then(m => m.getFileHandlesFromInput(input))
}

export default showOpenFilePicker
Expand Down
6 changes: 4 additions & 2 deletions src/showSaveFilePicker.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
/** @typedef {import('./FileSystemFileHandle.js').default} FileSystemFileHandle */

const native = globalThis.showSaveFilePicker

/**
Expand All @@ -7,7 +9,7 @@ const native = globalThis.showSaveFilePicker
* @param {string} [options.suggestedName] the name to fall back to when using polyfill
* @param {string} [options._name] the name to fall back to when using polyfill
* @param {boolean} [options._preferPolyfill] If you rather want to use the polyfill instead of the native
* @returns Promise<FileSystemDirectoryHandle>
* @return {Promise<FileSystemFileHandle>}
*/
async function showSaveFilePicker (options = {}) {
if (native && !options._preferPolyfill) {
Expand All @@ -19,7 +21,7 @@ async function showSaveFilePicker (options = {}) {
options.suggestedName = options._name
}

const FileSystemFileHandle = await import('./FileSystemFileHandle.js').then(d => d.default)
const { FileSystemFileHandle } = await import('./FileSystemFileHandle.js')
const { FileHandle } = await import('./adapters/downloader.js')
return new FileSystemFileHandle(new FileHandle(options.suggestedName))
}
Expand Down
59 changes: 29 additions & 30 deletions src/util.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,36 +29,35 @@ export async function fromDataTransfer (entries) {
return new fs.FileSystemDirectoryHandle(folder)
}

export async function fromInput (input) {
export async function getDirHandlesFromInput (input) {
const { FolderHandle, FileHandle } = await import('./adapters/memory.js')
const dir = await import('./FileSystemDirectoryHandle.js')
const file = await import('./FileSystemFileHandle.js')
const FileSystemDirectoryHandle = dir.default
const FileSystemFileHandle = file.default
const { FileSystemDirectoryHandle } = await import('./FileSystemDirectoryHandle.js')

const files = [...input.files]
if (input.webkitdirectory) {
const rootName = files[0].webkitRelativePath.split('/', 1)[0]
const root = new FolderHandle(rootName, false)
files.forEach(file => {
const path = file.webkitRelativePath.split('/')
path.shift()
const name = path.pop()
const dir = path.reduce((dir, path) => {
if (!dir._entries[path]) dir._entries[path] = new FolderHandle(path, false)
return dir._entries[path]
}, root)
dir._entries[name] = new FileHandle(file.name, file, false)
})
return new FileSystemDirectoryHandle(root)
} else {
const files = Array.from(input.files).map(file =>
new FileSystemFileHandle(new FileHandle(file.name, file, false))
)
if (input.multiple) {
return files
} else {
return files[0]
}
}
const files = Array.from(input.files)
const rootName = files[0].webkitRelativePath.split('/', 1)[0]
const root = new FolderHandle(rootName, false)

files.forEach(file => {
const path = file.webkitRelativePath.split('/')
path.shift()
const name = path.pop()

const dir = path.reduce((dir, path) => {
if (!dir._entries[path]) dir._entries[path] = new FolderHandle(path, false)
return dir._entries[path]
}, root)

dir._entries[name] = new FileHandle(file.name, file, false)
})

return new FileSystemDirectoryHandle(root)
}

export async function getFileHandlesFromInput (input) {
const { FileHandle } = await import('./adapters/memory.js')
const { FileSystemFileHandle } = await import('./FileSystemFileHandle.js')

return Array.from(input.files).map(file =>
new FileSystemFileHandle(new FileHandle(file.name, file, false))
)
}
3 changes: 1 addition & 2 deletions test/test-deno.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,9 @@ async function test (fs, step, root) {
await cleanupSandboxedFileSystem(root)
await step.fn(root)
console.log(`[OK]: ${fs} ${step.desc}`)
return true
} catch (err) {
console.log(`[ERR]: ${fs} ${step.desc}`)
return false
return true
}
}

Expand Down

0 comments on commit 741be20

Please sign in to comment.