Skip to content

Commit

Permalink
breaking: remove polyfills & top level await (#41)
Browse files Browse the repository at this point in the history
* breaking: make fetch-blob an optional dependency

also lazy load fetch-blob when necessary

* breaking: now depend on built-in DOMException

* remove all polyfills

* breaking summary
  • Loading branch information
jimmywarting authored Nov 24, 2022
1 parent 7826ab1 commit 5d3d0d4
Show file tree
Hide file tree
Showing 9 changed files with 103 additions and 42 deletions.
29 changes: 29 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,35 @@ It's not trying to interfere with the changing spec by using other properties th
( The current minium supported browser I have chosen to support is the ones that can handle import/export )<br>
( Some parts are lazy loaded when needed )

### Updating from 2.x to 3.x
v3 removed all top level await that conditionally loaded polyfills like
WritableStream, DOMException, and Blob/File. considering that now all latest
up to date env have this built in globally on `globalThis` namespace. This makes
the file system adapter lighter for ppl who want a smaller bundle and supports
newer engines.

But if you still need to provide polyfills for older environments
then you can provide your own polyfill and set it up with our config before any
other script is evaluated

```js

import config from 'native-file-system-adapter/config.js'
// This is the default config that you could override as needed.
Object.assign(config, {
ReadableStream: globalThis.ReadableStream,
WritableStream: globalThis.WritableStream,
TransformStream: globalThis.TransformStream,
DOMException: globalThis.DOMException,
Blob: globalThis.Blob,
File: globalThis.File
})
// continue like normal.
import xyz from 'native-file-system-adapter'
```



### ES import in browser

```html
Expand Down
28 changes: 15 additions & 13 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 2 additions & 6 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "native-file-system-adapter",
"version": "2.0.3",
"version": "3.0.0",
"description": "Native File System API",
"main": "src/es6.js",
"module": "./src/es6.js",
Expand Down Expand Up @@ -49,11 +49,7 @@
],
"homepage": "https://github.com/jimmywarting/native-file-system-adapter#readme",
"optionalDependencies": {
"web-streams-polyfill": "^3.1.1"
},
"dependencies": {
"fetch-blob": "^3.1.5",
"node-domexception": "^1.0.0"
"fetch-blob": "^3.2.0"
},
"standard": {
"globals": [
Expand Down
8 changes: 4 additions & 4 deletions src/FileSystemWritableFileStream.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
/** @type {typeof WritableStream} */
const ws = globalThis.WritableStream || await import('https://cdn.jsdelivr.net/npm/web-streams-polyfill@3/dist/ponyfill.es2018.mjs').then(r => r.WritableStream).catch(() => import('web-streams-polyfill').then(r => r.WritableStream))
import config from './config.js'

// TODO: add types for ws
class FileSystemWritableFileStream extends ws {
const { WritableStream } = config

class FileSystemWritableFileStream extends WritableStream {
constructor (...args) {
super(...args)

Expand Down
16 changes: 8 additions & 8 deletions src/adapters/downloader.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,18 @@
/* global Blob, DOMException, Response, MessageChannel */

import { errors } from '../util.js'
import config from '../config.js'

const {
WritableStream,
TransformStream,
DOMException,
Blob
} = config

const { GONE } = errors
// @ts-ignore
const isSafari = /constructor/i.test(window.HTMLElement) || window.safari || window.WebKitPoint
let TransformStream = globalThis.TransformStream
let WritableStream = globalThis.WritableStream

export class FileHandle {
constructor (name = 'unkown') {
Expand All @@ -26,12 +32,6 @@ export class FileHandle {
* @param {object} [options={}]
*/
async createWritable (options = {}) {
if (!TransformStream) {
// @ts-ignore
const ponyfill = await import('https://cdn.jsdelivr.net/npm/web-streams-polyfill@3/dist/ponyfill.es2018.mjs')
TransformStream = ponyfill.TransformStream
WritableStream = ponyfill.WritableStream
}
const sw = await navigator.serviceWorker?.getRegistration()
const link = document.createElement('a')
const ts = new TransformStream()
Expand Down
6 changes: 2 additions & 4 deletions src/adapters/memory.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
import { errors } from '../util.js'
/** @type {typeof window.File} */
const File = globalThis.File || await import('fetch-blob/file.js').then(m => m.File)
/** @type {typeof window.Blob} */
const Blob = globalThis.Blob || await import('fetch-blob').then(m => m.Blob)
import config from '../config.js'

const { File, Blob, DOMException } = config
const { INVALID, GONE, MISMATCH, MOD_ERR, SYNTAX, SECURITY, DISALLOWED } = errors

export class Sink {
Expand Down
34 changes: 28 additions & 6 deletions src/adapters/node.js
Original file line number Diff line number Diff line change
@@ -1,15 +1,34 @@
import fs from 'node:fs/promises'
import { join } from 'node:path'
import 'node-domexception'
import Blob from 'fetch-blob'
import { fileFrom } from 'fetch-blob/from.js'
import { errors } from '../util.js'
// import mime from 'mime-types'

import config from '../config.js'

const {
DOMException
} = config

const { INVALID, GONE, MISMATCH, MOD_ERR, SYNTAX } = errors

export class Sink {
/**
* @see https://github.com/node-fetch/fetch-blob/blob/0455796ede330ecffd9eb6b9fdf206cc15f90f3e/index.js#L232
* @param {*} object
* @returns {object is Blob}
*/
function isBlob (object) {
return (
object &&
typeof object === 'object' &&
typeof object.constructor === 'function' &&
(
typeof object.stream === 'function' ||
typeof object.arrayBuffer === 'function'
) &&
/^(Blob|File)$/.test(object[Symbol.toStringTag])
)
}

export class Sink {
/**
* @param {fs.FileHandle} fileHandle
* @param {number} size
Expand Down Expand Up @@ -65,7 +84,7 @@ export class Sink {
chunk = new Uint8Array(chunk)
} else if (typeof chunk === 'string') {
chunk = Buffer.from(chunk)
} else if (chunk instanceof Blob) {
} else if (isBlob(chunk)) {
for await (const data of chunk.stream()) {
const res = await this._fileHandle.writev([data], this._position)
this._position += res.bytesWritten
Expand Down Expand Up @@ -101,6 +120,9 @@ export class FileHandle {
await fs.stat(this._path).catch(err => {
if (err.code === 'ENOENT') throw new DOMException(...GONE)
})

// TODO: replace once https://github.com/nodejs/node/issues/37340 is fixed
const { fileFrom } = await import('fetch-blob/from.js')
return fileFrom(this._path)
}

Expand Down
10 changes: 10 additions & 0 deletions src/config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
const config = {
ReadableStream: globalThis.ReadableStream,
WritableStream: globalThis.WritableStream,
TransformStream: globalThis.TransformStream,
DOMException: globalThis.DOMException,
Blob: globalThis.Blob,
File: globalThis.File,
}

export default config
6 changes: 5 additions & 1 deletion test/test-node.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import { existsSync, mkdirSync, rmdirSync } from 'node:fs'
import { getOriginPrivateDirectory } from '../src/es6.js'
import config from '../src/config.js'
import steps from './test.js'
import File from 'fetch-blob/file.js'
import { getOriginPrivateDirectory } from '../src/es6.js'
import { cleanupSandboxedFileSystem } from '../test/util.js'

let hasFailures = false
Expand All @@ -12,6 +14,7 @@ async function test (fs, step, root) {
console.log(`[OK]: ${fs} ${step.desc}`)
} catch (err) {
console.log(`[ERR]: ${fs} ${step.desc}\n\t-> ${err.message}`)
console.error(err.stack)
hasFailures = true
}
}
Expand All @@ -21,6 +24,7 @@ async function start () {
if (!existsSync(testFolderPath)) {
mkdirSync(testFolderPath)
}
config.File = File
const root = await getOriginPrivateDirectory(import('../src/adapters/node.js'), './testfolder')
const memory = await getOriginPrivateDirectory(import('../src/adapters/memory.js'))

Expand Down

0 comments on commit 5d3d0d4

Please sign in to comment.