diff --git a/.gitignore b/.gitignore
index 0f2afd3..52058ce 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,3 +1,4 @@
node_modules
.turbo
-out
\ No newline at end of file
+out
+.env.*
\ No newline at end of file
diff --git a/local_packages/.codecov.yml b/local_packages/.codecov.yml
deleted file mode 100644
index 3f58de5..0000000
--- a/local_packages/.codecov.yml
+++ /dev/null
@@ -1,6 +0,0 @@
-coverage:
- round: up
- precision: 2
- parsers:
- javascript:
- enable_partials: yes
diff --git a/local_packages/.github/PULL_REQUEST_TEMPLATE.md b/local_packages/.github/PULL_REQUEST_TEMPLATE.md
deleted file mode 100644
index ea09a23..0000000
--- a/local_packages/.github/PULL_REQUEST_TEMPLATE.md
+++ /dev/null
@@ -1,23 +0,0 @@
-
-
-## The purpose of this PR is:
-...
-
-## This is what had to change:
-...
-
-## This is what like reviewers to know:
-...
-
-
--------------------------------------------------------------------------------------------------
-
-
-- [ ] I prefixed the PR-title with `docs: `, `fix(area): `, `feat(area): ` or `breaking(area): `
-- [ ] I updated the README.md
-- [ ] I Added unit test(s)
-
--------------------------------------------------------------------------------------------------
-
-
-- fix #000
diff --git a/local_packages/.github/dependabot.yml b/local_packages/.github/dependabot.yml
deleted file mode 100644
index 0b256c4..0000000
--- a/local_packages/.github/dependabot.yml
+++ /dev/null
@@ -1,25 +0,0 @@
-version: 2
-updates:
-- package-ecosystem: npm
- directory: "/"
- schedule:
- interval: daily
- open-pull-requests-limit: 10
- ignore:
- - dependency-name: get-stream
- versions:
- - 6.0.0
- - 6.0.1
- - dependency-name: typescript
- versions:
- - 4.1.3
- - 4.1.4
- - 4.1.5
- - 4.2.2
- - 4.2.3
- - 4.2.4
- - dependency-name: xo
- versions:
- - 0.37.1
- - 0.38.1
- - 0.38.2
diff --git a/local_packages/.github/workflows/ci.yml b/local_packages/.github/workflows/ci.yml
deleted file mode 100644
index a6669c1..0000000
--- a/local_packages/.github/workflows/ci.yml
+++ /dev/null
@@ -1,32 +0,0 @@
-name: CI
-
-on:
- push:
- branches: [master]
- pull_request:
- paths:
- - "**.js"
- - "package.json"
- - ".github/workflows/ci.yml"
-
-jobs:
- test:
- strategy:
- matrix:
- os: [ubuntu-latest, macos-latest, windows-latest]
- node: ["18", "20", "22"]
-
- runs-on: ${{ matrix.os }}
-
- steps:
- - uses: actions/checkout@v2
- - uses: actions/setup-node@v2
- with:
- node-version: ${{ matrix.node }}
- - run: pnpm install
- - run: pnpm test
- - run: pnpm run report -- --colors
- - name: Upload coverage to Codecov
- uses: codecov/codecov-action@v1
- with:
- file: ./coverage/coverage-final.json
diff --git a/local_packages/.gitignore b/local_packages/.gitignore
deleted file mode 100644
index 4d8cac9..0000000
--- a/local_packages/.gitignore
+++ /dev/null
@@ -1,69 +0,0 @@
-# Lock files
-
-package-lock.json
-yarn.lock
-
-# Logs
-logs
-*.log
-npm-debug.log*
-yarn-debug.log*
-yarn-error.log*
-
-# Runtime data
-pids
-*.pid
-*.seed
-*.pid.lock
-
-
-
-# Directory for instrumented libs generated by jscoverage/JSCover
-lib-cov
-
-# Coverage directory used by tools like istanbul
-coverage
-
-# nyc test coverage
-.nyc_output
-
-# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
-.grunt
-
-# Bower dependency directory (https://bower.io/)
-bower_components
-
-# node-waf configuration
-.lock-wscript
-
-# Compiled binary addons (https://nodejs.org/api/addons.html)
-build/Release
-
-# Dependency directories
-node_modules/
-jspm_packages/
-
-# TypeScript v1 declaration files
-typings/
-
-# Optional npm cache directory
-.npm
-
-# Optional cache
-.cache
-
-# Optional REPL history
-.node_repl_history
-
-# Output of 'npm pack'
-*.tgz
-
-# Yarn Integrity file
-.yarn-integrity
-
-# dotenv environment variables file
-.env
-
-*.d.ts
-*.d.cts
-.DS_Store
\ No newline at end of file
diff --git a/local_packages/LICENSE b/local_packages/LICENSE
deleted file mode 100644
index 0d31723..0000000
--- a/local_packages/LICENSE
+++ /dev/null
@@ -1,21 +0,0 @@
-MIT License
-
-Copyright (c) 2019 David Frank
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
diff --git a/local_packages/README.md b/local_packages/README.md
deleted file mode 100644
index 20d212a..0000000
--- a/local_packages/README.md
+++ /dev/null
@@ -1,133 +0,0 @@
-# fetch-blob
-
-[![npm version][npm-image]][npm-url]
-[![build status][ci-image]][ci-url]
-[![coverage status][codecov-image]][codecov-url]
-[![install size][install-size-image]][install-size-url]
-
-A Blob implementation in Node.js, originally from [node-fetch](https://github.com/node-fetch/node-fetch).
-
-Use the built-in [`Blob`](https://nodejs.org/docs/latest-v18.x/api/buffer.html#class-blob) in Node.js 18 and later.
-
-## Installation
-
-```sh
-pnpm install fetch-blob
-```
-
-
- Upgrading from 2x to 3x
-
- Updating from 2 to 3 should be a breeze since there is not many changes to the blob specification.
- The major cause of a major release is coding standards.
- - internal WeakMaps was replaced with private fields
- - internal Buffer.from was replaced with TextEncoder/Decoder
- - internal buffers was replaced with Uint8Arrays
- - CommonJS was replaced with ESM
- - The node stream returned by calling `blob.stream()` was replaced with whatwg streams
- - (Read "Differences from other blobs" for more info.)
-
-
-
- Differences from other Blobs
-
- - Unlike NodeJS `buffer.Blob` (Added in: v15.7.0) and browser native Blob this polyfilled version can't be sent via PostMessage
- - This blob version is more arbitrary, it can be constructed with blob parts that isn't a instance of itself
- it has to look and behave as a blob to be accepted as a blob part.
- - The benefit of this is that you can create other types of blobs that don't contain any internal data that has to be read in other ways, such as the `BlobDataItem` created in `from.js` that wraps a file path into a blob-like item and read lazily (nodejs plans to [implement this][fs-blobs] as well)
- - The `blob.stream()` is the most noticeable differences. It returns a WHATWG stream now. to keep it as a node stream you would have to do:
-
- ```js
- import {Readable} from 'stream'
- const stream = Readable.from(blob.stream())
- ```
-
-
-## Usage
-
-```js
-// Ways to import
-import { Blob } from 'fetch-blob'
-import { File } from 'fetch-blob/file.js'
-
-const { Blob } = await import('fetch-blob')
-
-
-// Ways to read the blob:
-const blob = new Blob(['hello, world'])
-
-await blob.text()
-await blob.arrayBuffer()
-for await (let chunk of blob.stream()) { ... }
-blob.stream().getReader().read()
-blob.stream().getReader({mode: 'byob'}).read(view)
-```
-
-### Blob part backed up by filesystem
-
-`fetch-blob/from.js` comes packed with tools to convert any filepath into either a Blob or a File
-It will not read the content into memory. It will only stat the file for last modified date and file size.
-
-```js
-// The default export is sync and use fs.stat to retrieve size & last modified as a blob
-import {File, Blob, blobFrom, blobFromSync, fileFrom, fileFromSync} from 'fetch-blob/from.js'
-
-const fsFile = fileFromSync('./2-GiB-file.bin', 'application/octet-stream')
-const fsBlob = await blobFrom('./2-GiB-file.mp4')
-
-// Not a 4 GiB memory snapshot, just holds references
-// points to where data is located on the disk
-const blob = new Blob([fsFile, fsBlob, 'memory', new Uint8Array(10)])
-console.log(blob.size) // ~4 GiB
-```
-
-`blobFrom|blobFromSync|fileFrom|fileFromSync(path, [mimetype])`
-
-### Creating a temporary file on the disk
-(requires [FinalizationRegistry] - node v14.6)
-
-When using both `createTemporaryBlob` and `createTemporaryFile`
-then you will write data to the temporary folder in their respective OS.
-The arguments can be anything that [fsPromises.writeFile] supports. NodeJS
-v14.17.0+ also supports writing (async)Iterable streams and passing in a
-AbortSignal, so both NodeJS stream and whatwg streams are supported. When the
-file have been written it will return a Blob/File handle with a references to
-this temporary location on the disk. When you no longer have a references to
-this Blob/File anymore and it have been GC then it will automatically be deleted.
-
-This files are also unlinked upon exiting the process.
-```js
-import { createTemporaryBlob, createTemporaryFile } from 'fetch-blob/from.js'
-
-const req = new Request('https://httpbin.org/image/png')
-const res = await fetch(req)
-const type = res.headers.get('content-type')
-const signal = req.signal
-let blob = await createTemporaryBlob(res.body, { type, signal })
-// const file = createTemporaryBlob(res.body, 'img.png', { type, signal })
-blob = undefined // loosing references will delete the file from disk
-```
-
-- `createTemporaryBlob(data, { type, signal })`
-- `createTemporaryFile(data, FileName, { type, signal, lastModified })`
-
-### Creating Blobs backed up by other async sources
-Our Blob & File class are more generic then any other polyfills in the way that it can accept any blob look-a-like item
-An example of this is that our blob implementation can be constructed with parts coming from [BlobDataItem](https://github.com/node-fetch/fetch-blob/blob/8ef89adad40d255a3bbd55cf38b88597c1cd5480/from.js#L32) (aka a filepath) or from [buffer.Blob](https://nodejs.org/api/buffer.html#buffer_new_buffer_blob_sources_options), It dose not have to implement all the methods - just enough that it can be read/understood by our Blob implementation. The minium requirements is that it has `Symbol.toStringTag`, `size`, `slice()`, `stream()` methods (the stream method
-can be as simple as being a sync or async iterator that yields Uint8Arrays. If you then wrap it in our Blob or File `new Blob([blobDataItem])` then you get all of the other methods that should be implemented in a blob or file (aka: text(), arrayBuffer() and type and a ReadableStream)
-
-An example of this could be to create a file or blob like item coming from a remote HTTP request. Or from a DataBase
-
-See the [MDN documentation](https://developer.mozilla.org/en-US/docs/Web/API/Blob) and [tests](https://github.com/node-fetch/fetch-blob/blob/master/test.js) for more details of how to use the Blob.
-
-[npm-image]: https://flat.badgen.net/npm/v/fetch-blob
-[npm-url]: https://www.npmjs.com/package/fetch-blob
-[ci-image]: https://github.com/node-fetch/fetch-blob/workflows/CI/badge.svg
-[ci-url]: https://github.com/node-fetch/fetch-blob/actions
-[codecov-image]: https://flat.badgen.net/codecov/c/github/node-fetch/fetch-blob/master
-[codecov-url]: https://codecov.io/gh/node-fetch/fetch-blob
-[install-size-image]: https://flat.badgen.net/packagephobia/install/fetch-blob
-[install-size-url]: https://packagephobia.now.sh/result?p=fetch-blob
-[fs-blobs]: https://github.com/nodejs/node/issues/37340
-[fsPromises.writeFile]: https://nodejs.org/dist/latest-v18.x/docs/api/fs.html#fspromiseswritefilefile-data-options
-[FinalizationRegistry]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/FinalizationRegistry
diff --git a/local_packages/fetch-blob b/local_packages/fetch-blob
deleted file mode 160000
index d5acee9..0000000
--- a/local_packages/fetch-blob
+++ /dev/null
@@ -1 +0,0 @@
-Subproject commit d5acee931e2efe00e52ca21c73e8ebec310936d5
diff --git a/local_packages/file.js b/local_packages/file.js
deleted file mode 100644
index b2739c9..0000000
--- a/local_packages/file.js
+++ /dev/null
@@ -1,48 +0,0 @@
-import { Blob } from './index.js'
-
-const _File = class File extends Blob {
- #lastModified = 0
- #name = ''
-
- /**
- * @param {*[]} fileBits
- * @param {string} fileName
- * @param {{lastModified?: number, type?: string}} options
- */// @ts-ignore
- constructor (fileBits, fileName, options = {}) {
- if (arguments.length < 2) {
- throw new TypeError(`Failed to construct 'File': 2 arguments required, but only ${arguments.length} present.`)
- }
- super(fileBits, options)
-
- if (options === null) options = {}
-
- // Simulate WebIDL type casting for NaN value in lastModified option.
- const lastModified = options.lastModified === undefined ? Date.now() : Number(options.lastModified)
- if (!Number.isNaN(lastModified)) {
- this.#lastModified = lastModified
- }
-
- this.#name = String(fileName)
- }
-
- get name () {
- return this.#name
- }
-
- get lastModified () {
- return this.#lastModified
- }
-
- get [Symbol.toStringTag] () {
- return 'File'
- }
-
- static [Symbol.hasInstance] (object) {
- return !!object && object instanceof Blob &&
- /^(File)$/.test(object[Symbol.toStringTag])
- }
-}
-
-/** @type {typeof globalThis.File} */// @ts-ignore
-export const File = _File
diff --git a/local_packages/from.js b/local_packages/from.js
deleted file mode 100644
index 325a757..0000000
--- a/local_packages/from.js
+++ /dev/null
@@ -1,165 +0,0 @@
-import {
- realpathSync,
- statSync,
- rmdirSync,
- createReadStream,
- promises as fs
-} from 'node:fs'
-import { basename, sep, join } from 'node:path'
-import { tmpdir } from 'node:os'
-import process from 'node:process'
-
-import { File } from './file.js'
-import { Blob } from './index.js'
-
-const { stat, mkdtemp } = fs
-let i = 0, tempDir, registry
-
-
-
-/**
- * @param {string} path filepath on the disk
- * @param {string} [type] mimetype to use
- */
-const blobFromSync = (path, type) => fromBlob(statSync(path), path, type)
-
-/**
- * @param {string} path filepath on the disk
- * @param {string} [type] mimetype to use
- * @returns {Promise}
- */
-const blobFrom = (path, type) => stat(path).then(stat => fromBlob(stat, path, type))
-
-/**
- * @param {string} path filepath on the disk
- * @param {string} [type] mimetype to use
- * @returns {Promise}
- */
-const fileFrom = (path, type) => stat(path).then(stat => fromFile(stat, path, type))
-
-/**
- * @param {string} path filepath on the disk
- * @param {string} [type] mimetype to use
- */
-const fileFromSync = (path, type) => fromFile(statSync(path), path, type)
-
-// @ts-ignore
-const fromBlob = (stat, path, type = '') => new Blob([new BlobDataItem({
- path,
- size: stat.size,
- lastModified: stat.mtimeMs,
- start: 0
-})], { type })
-
-// @ts-ignore
-const fromFile = (stat, path, type = '') => new File([new BlobDataItem({
- path,
- size: stat.size,
- lastModified: stat.mtimeMs,
- start: 0
-})], basename(path), { type, lastModified: stat.mtimeMs })
-
-/**
- * Creates a temporary blob backed by the filesystem.
- * NOTE: requires node.js v14 or higher to use FinalizationRegistry
- *
- * @param {*} data Same as fs.writeFile data
- * @param {BlobPropertyBag & {signal?: AbortSignal}} options
- * @param {AbortSignal} [signal] in case you wish to cancel the write operation
- * @returns {Promise}
- */
-const createTemporaryBlob = async (data, {signal, type} = {}) => {
- registry = registry || new FinalizationRegistry(fs.unlink)
- tempDir = tempDir || await mkdtemp(realpathSync(tmpdir()) + sep)
- const id = `${i++}`
- const destination = join(tempDir, id)
- if (data instanceof ArrayBuffer) data = new Uint8Array(data)
- await fs.writeFile(destination, data, { signal })
- const blob = await blobFrom(destination, type)
- registry.register(blob, destination)
- return blob
-}
-
-/**
- * Creates a temporary File backed by the filesystem.
- * Pretty much the same as constructing a new File(data, name, options)
- *
- * NOTE: requires node.js v14 or higher to use FinalizationRegistry
- * @param {*} data
- * @param {string} name
- * @param {FilePropertyBag & {signal?: AbortSignal}} opts
- * @returns {Promise}
- */
-const createTemporaryFile = async (data, name, opts) => {
- const blob = await createTemporaryBlob(data)
- return new File([blob], name, opts)
-}
-
-/**
- * This is a blob backed up by a file on the disk
- * with minium requirement. Its wrapped around a Blob as a blobPart
- * so you have no direct access to this.
- *
- * @private
- */
-class BlobDataItem {
- #path
- #start
-
- constructor (options) {
- this.#path = options.path
- this.#start = options.start
- this.size = options.size
- this.lastModified = options.lastModified
- this.originalSize = options.originalSize === undefined
- ? options.size
- : options.originalSize
- }
-
- /**
- * Slicing arguments is first validated and formatted
- * to not be out of range by Blob.prototype.slice
- */
- slice (start, end) {
- return new BlobDataItem({
- path: this.#path,
- lastModified: this.lastModified,
- originalSize: this.originalSize,
- size: end - start,
- start: this.#start + start
- })
- }
-
- async * stream () {
- const { mtimeMs, size } = await stat(this.#path)
-
- if (mtimeMs > this.lastModified || this.originalSize !== size) {
- throw new DOMException('The requested file could not be read, typically due to permission problems that have occurred after a reference to a file was acquired.', 'NotReadableError')
- }
-
- yield * createReadStream(this.#path, {
- start: this.#start,
- end: this.#start + this.size - 1
- })
- }
-
- get [Symbol.toStringTag] () {
- return 'Blob'
- }
-}
-
-process.once('exit', () => {
- tempDir && rmdirSync(tempDir, { recursive: true })
-})
-
-export default blobFromSync
-export {
- Blob,
- blobFrom,
- blobFromSync,
- createTemporaryBlob,
- File,
- fileFrom,
- fileFromSync,
- createTemporaryFile
-}
\ No newline at end of file
diff --git a/local_packages/index.js b/local_packages/index.js
deleted file mode 100644
index 0683fa5..0000000
--- a/local_packages/index.js
+++ /dev/null
@@ -1,254 +0,0 @@
-/*! fetch-blob. MIT License. Jimmy Wärting */
-
-if (!globalThis.ReadableStream) {
- try {
- const process = await import('node:process').then(m => m.default)
- const { emitWarning } = process
- try {
- process.emitWarning = () => {}
- const streams = await import('node:stream/web').then(m => m.default)
- Object.assign(globalThis, streams)
- process.emitWarning = emitWarning
- } catch (error) {
- process.emitWarning = emitWarning
- throw error
- }
- } catch (error) {}
-}
-
-// 64 KiB (same size chrome slice theirs blob into Uint8array's)
-const POOL_SIZE = 65536
-
-/**
- * @param {(Blob | Uint8Array)[]} parts
- * @param {boolean} clone
- * @returns {AsyncIterableIterator}
- */
-async function * toIterator (parts, clone) {
- for (const part of parts) {
- if (ArrayBuffer.isView(part)) {
- if (clone) {
- let position = part.byteOffset
- const end = part.byteOffset + part.byteLength
- while (position !== end) {
- const size = Math.min(end - position, POOL_SIZE)
- const chunk = part.buffer.slice(position, position + size)
- position += chunk.byteLength
- yield new Uint8Array(chunk)
- }
- } else {
- yield part
- }
- } else {
- // @ts-ignore TS Think blob.stream() returns a node:stream
- yield * part.stream()
- }
- }
-}
-
-const _Blob = class Blob {
- /** @type {Array.<(Blob|Uint8Array)>} */
- #parts = []
- #type = ''
- #size = 0
- #endings = 'transparent'
-
- /**
- * The Blob() constructor returns a new Blob object. The content
- * of the blob consists of the concatenation of the values given
- * in the parameter array.
- *
- * @param {*} blobParts
- * @param {{ type?: string, endings?: string }} [options]
- */
- constructor (blobParts = [], options = {}) {
- if (typeof blobParts !== 'object' || blobParts === null) {
- throw new TypeError('Failed to construct \'Blob\': The provided value cannot be converted to a sequence.')
- }
-
- if (typeof blobParts[Symbol.iterator] !== 'function') {
- throw new TypeError('Failed to construct \'Blob\': The object must have a callable @@iterator property.')
- }
-
- if (typeof options !== 'object' && typeof options !== 'function') {
- throw new TypeError('Failed to construct \'Blob\': parameter 2 cannot convert to dictionary.')
- }
-
- if (options === null) options = {}
-
- const encoder = new TextEncoder()
- for (const element of blobParts) {
- let part
- if (ArrayBuffer.isView(element)) {
- part = new Uint8Array(element.buffer.slice(element.byteOffset, element.byteOffset + element.byteLength))
- } else if (element instanceof ArrayBuffer) {
- part = new Uint8Array(element.slice(0))
- } else if (element instanceof Blob) {
- part = element
- } else {
- part = encoder.encode(`${element}`)
- }
-
- const size = ArrayBuffer.isView(part) ? part.byteLength : part.size
- // Avoid pushing empty parts into the array to better GC them
- if (size) {
- this.#size += size
- this.#parts.push(part)
- }
- }
-
- this.#endings = `${options.endings === undefined ? 'transparent' : options.endings}`
- const type = options.type === undefined ? '' : String(options.type)
- this.#type = /^[\x20-\x7E]*$/.test(type) ? type : ''
- }
-
- /**
- * The Blob interface's size property returns the
- * size of the Blob in bytes.
- */
- get size () {
- return this.#size
- }
-
- /**
- * The type property of a Blob object returns the MIME type of the file.
- */
- get type () {
- return this.#type
- }
-
- /**
- * The text() method in the Blob interface returns a Promise
- * that resolves with a string containing the contents of
- * the blob, interpreted as UTF-8.
- *
- * @return {Promise}
- */
- async text () {
- // More optimized than using this.arrayBuffer()
- // that requires twice as much ram
- const decoder = new TextDecoder()
- let str = ''
- for await (const part of toIterator(this.#parts, false)) {
- str += decoder.decode(part, { stream: true })
- }
- // Remaining
- str += decoder.decode()
- return str
- }
-
- /**
- * The arrayBuffer() method in the Blob interface returns a
- * Promise that resolves with the contents of the blob as
- * binary data contained in an ArrayBuffer.
- *
- * @return {Promise}
- */
- async arrayBuffer () {
- const data = new Uint8Array(this.size)
- let offset = 0
- for await (const chunk of toIterator(this.#parts, false)) {
- data.set(chunk, offset)
- offset += chunk.length
- }
-
- return data.buffer
- }
-
- stream () {
- const it = toIterator(this.#parts, true)
-
- return new globalThis.ReadableStream({
- // @ts-ignore
- type: 'bytes',
- async pull (ctrl) {
- const chunk = await it.next()
- chunk.done ? ctrl.close() : ctrl.enqueue(chunk.value)
- },
-
- async cancel () {
- await it.return()
- }
- })
- }
-
- /**
- * The Blob interface's slice() method creates and returns a
- * new Blob object which contains data from a subset of the
- * blob on which it's called.
- *
- * @param {number} [start]
- * @param {number} [end]
- * @param {string} [type]
- */
- slice (start = 0, end = this.size, type = '') {
- const { size } = this
-
- let relativeStart = start < 0 ? Math.max(size + start, 0) : Math.min(start, size)
- let relativeEnd = end < 0 ? Math.max(size + end, 0) : Math.min(end, size)
-
- const span = Math.max(relativeEnd - relativeStart, 0)
- const parts = this.#parts
- const blobParts = []
- let added = 0
-
- for (const part of parts) {
- // don't add the overflow to new blobParts
- if (added >= span) {
- break
- }
-
- const size = ArrayBuffer.isView(part) ? part.byteLength : part.size
- if (relativeStart && size <= relativeStart) {
- // Skip the beginning and change the relative
- // start & end position as we skip the unwanted parts
- relativeStart -= size
- relativeEnd -= size
- } else {
- let chunk
- if (ArrayBuffer.isView(part)) {
- chunk = part.subarray(relativeStart, Math.min(size, relativeEnd))
- added += chunk.byteLength
- } else {
- chunk = part.slice(relativeStart, Math.min(size, relativeEnd))
- added += chunk.size
- }
- relativeEnd -= size
- blobParts.push(chunk)
- relativeStart = 0 // All next sequential parts should start at 0
- }
- }
-
- const blob = new Blob([], { type: `${type}` })
- blob.#size = span
- blob.#parts = blobParts
-
- return blob
- }
-
- get [Symbol.toStringTag] () {
- return 'Blob'
- }
-
- static [Symbol.hasInstance] (object) {
- return (
- object &&
- typeof object === 'object' &&
- typeof object.constructor === 'function' &&
- (
- typeof object.stream === 'function' ||
- typeof object.arrayBuffer === 'function'
- ) &&
- /^(Blob|File)$/.test(object[Symbol.toStringTag])
- )
- }
-}
-
-Object.defineProperties(_Blob.prototype, {
- size: { enumerable: true },
- type: { enumerable: true },
- slice: { enumerable: true }
-})
-
-/** @type {typeof globalThis.Blob} */
-export const Blob = _Blob
diff --git a/local_packages/package.json b/local_packages/package.json
deleted file mode 100644
index f073185..0000000
--- a/local_packages/package.json
+++ /dev/null
@@ -1,52 +0,0 @@
-{
- "name": "fetch-blob",
- "version": "4.1.0",
- "description": "Blob & File implementation in Node.js, originally from node-fetch.",
- "main": "index.js",
- "type": "module",
- "files": [
- "from.js",
- "file.js",
- "file.d.ts",
- "index.js",
- "index.d.ts",
- "from.d.ts"
- ],
- "scripts": {
- "test": "node --experimental-loader ./test/http-loader.js ./test/test-wpt-in-node.js",
- "report": "c8 --reporter json --reporter text npm run test",
- "coverage": "pnpm run report && codecov -f coverage/coverage-final.json",
- "prepublishOnly": "tsc --declaration --emitDeclarationOnly --allowJs index.js from.js"
- },
- "repository": "https://github.com/node-fetch/fetch-blob.git",
- "keywords": [
- "blob",
- "file",
- "node-fetch"
- ],
- "engines": {
- "node": ">=18"
- },
- "author": "Jimmy Wärting (https://jimmy.warting.se)",
- "license": "MIT",
- "bugs": {
- "url": "https://github.com/node-fetch/fetch-blob/issues"
- },
- "homepage": "https://github.com/node-fetch/fetch-blob#readme",
- "devDependencies": {
- "@types/node": "^24.1.0",
- "c8": "^10.1.3",
- "typescript": "^5.8.3"
- },
- "packageManager": "pnpm@10.13.1",
- "funding": [
- {
- "type": "github",
- "url": "https://github.com/sponsors/jimmywarting"
- },
- {
- "type": "paypal",
- "url": "https://paypal.me/jimmywarting"
- }
- ]
-}
diff --git a/local_packages/pnpm-lock.yaml b/local_packages/pnpm-lock.yaml
deleted file mode 100644
index 42585f2..0000000
--- a/local_packages/pnpm-lock.yaml
+++ /dev/null
@@ -1,547 +0,0 @@
-lockfileVersion: '9.0'
-
-settings:
- autoInstallPeers: true
- excludeLinksFromLockfile: false
-
-importers:
-
- .:
- devDependencies:
- '@types/node':
- specifier: ^24.1.0
- version: 24.1.0
- c8:
- specifier: ^10.1.3
- version: 10.1.3
- typescript:
- specifier: ^5.8.3
- version: 5.8.3
-
-packages:
-
- '@bcoe/v8-coverage@1.0.2':
- resolution: {integrity: sha512-6zABk/ECA/QYSCQ1NGiVwwbQerUCZ+TQbp64Q3AgmfNvurHH0j8TtXa1qbShXA6qqkpAj4V5W8pP6mLe1mcMqA==}
- engines: {node: '>=18'}
-
- '@isaacs/cliui@8.0.2':
- resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==}
- engines: {node: '>=12'}
-
- '@istanbuljs/schema@0.1.3':
- resolution: {integrity: sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==}
- engines: {node: '>=8'}
-
- '@jridgewell/resolve-uri@3.1.2':
- resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==}
- engines: {node: '>=6.0.0'}
-
- '@jridgewell/sourcemap-codec@1.5.4':
- resolution: {integrity: sha512-VT2+G1VQs/9oz078bLrYbecdZKs912zQlkelYpuf+SXF+QvZDYJlbx/LSx+meSAwdDFnF8FVXW92AVjjkVmgFw==}
-
- '@jridgewell/trace-mapping@0.3.29':
- resolution: {integrity: sha512-uw6guiW/gcAGPDhLmd77/6lW8QLeiV5RUTsAX46Db6oLhGaVj4lhnPwb184s1bkc8kdVg/+h988dro8GRDpmYQ==}
-
- '@pkgjs/parseargs@0.11.0':
- resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==}
- engines: {node: '>=14'}
-
- '@types/istanbul-lib-coverage@2.0.6':
- resolution: {integrity: sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w==}
-
- '@types/node@24.1.0':
- resolution: {integrity: sha512-ut5FthK5moxFKH2T1CUOC6ctR67rQRvvHdFLCD2Ql6KXmMuCrjsSsRI9UsLCm9M18BMwClv4pn327UvB7eeO1w==}
-
- ansi-regex@5.0.1:
- resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==}
- engines: {node: '>=8'}
-
- ansi-regex@6.1.0:
- resolution: {integrity: sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==}
- engines: {node: '>=12'}
-
- ansi-styles@4.3.0:
- resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==}
- engines: {node: '>=8'}
-
- ansi-styles@6.2.1:
- resolution: {integrity: sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==}
- engines: {node: '>=12'}
-
- balanced-match@1.0.2:
- resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==}
-
- brace-expansion@2.0.2:
- resolution: {integrity: sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==}
-
- c8@10.1.3:
- resolution: {integrity: sha512-LvcyrOAaOnrrlMpW22n690PUvxiq4Uf9WMhQwNJ9vgagkL/ph1+D4uvjvDA5XCbykrc0sx+ay6pVi9YZ1GnhyA==}
- engines: {node: '>=18'}
- hasBin: true
- peerDependencies:
- monocart-coverage-reports: ^2
- peerDependenciesMeta:
- monocart-coverage-reports:
- optional: true
-
- cliui@8.0.1:
- resolution: {integrity: sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==}
- engines: {node: '>=12'}
-
- color-convert@2.0.1:
- resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==}
- engines: {node: '>=7.0.0'}
-
- color-name@1.1.4:
- resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==}
-
- convert-source-map@2.0.0:
- resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==}
-
- cross-spawn@7.0.6:
- resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==}
- engines: {node: '>= 8'}
-
- eastasianwidth@0.2.0:
- resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==}
-
- emoji-regex@8.0.0:
- resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==}
-
- emoji-regex@9.2.2:
- resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==}
-
- escalade@3.2.0:
- resolution: {integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==}
- engines: {node: '>=6'}
-
- find-up@5.0.0:
- resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==}
- engines: {node: '>=10'}
-
- foreground-child@3.3.1:
- resolution: {integrity: sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==}
- engines: {node: '>=14'}
-
- get-caller-file@2.0.5:
- resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==}
- engines: {node: 6.* || 8.* || >= 10.*}
-
- glob@10.4.5:
- resolution: {integrity: sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==}
- hasBin: true
-
- has-flag@4.0.0:
- resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==}
- engines: {node: '>=8'}
-
- html-escaper@2.0.2:
- resolution: {integrity: sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==}
-
- is-fullwidth-code-point@3.0.0:
- resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==}
- engines: {node: '>=8'}
-
- isexe@2.0.0:
- resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==}
-
- istanbul-lib-coverage@3.2.2:
- resolution: {integrity: sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==}
- engines: {node: '>=8'}
-
- istanbul-lib-report@3.0.1:
- resolution: {integrity: sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==}
- engines: {node: '>=10'}
-
- istanbul-reports@3.1.7:
- resolution: {integrity: sha512-BewmUXImeuRk2YY0PVbxgKAysvhRPUQE0h5QRM++nVWyubKGV0l8qQ5op8+B2DOmwSe63Jivj0BjkPQVf8fP5g==}
- engines: {node: '>=8'}
-
- jackspeak@3.4.3:
- resolution: {integrity: sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==}
-
- locate-path@6.0.0:
- resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==}
- engines: {node: '>=10'}
-
- lru-cache@10.4.3:
- resolution: {integrity: sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==}
-
- make-dir@4.0.0:
- resolution: {integrity: sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==}
- engines: {node: '>=10'}
-
- minimatch@9.0.5:
- resolution: {integrity: sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==}
- engines: {node: '>=16 || 14 >=14.17'}
-
- minipass@7.1.2:
- resolution: {integrity: sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==}
- engines: {node: '>=16 || 14 >=14.17'}
-
- p-limit@3.1.0:
- resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==}
- engines: {node: '>=10'}
-
- p-locate@5.0.0:
- resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==}
- engines: {node: '>=10'}
-
- package-json-from-dist@1.0.1:
- resolution: {integrity: sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==}
-
- path-exists@4.0.0:
- resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==}
- engines: {node: '>=8'}
-
- path-key@3.1.1:
- resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==}
- engines: {node: '>=8'}
-
- path-scurry@1.11.1:
- resolution: {integrity: sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==}
- engines: {node: '>=16 || 14 >=14.18'}
-
- require-directory@2.1.1:
- resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==}
- engines: {node: '>=0.10.0'}
-
- semver@7.7.2:
- resolution: {integrity: sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==}
- engines: {node: '>=10'}
- hasBin: true
-
- shebang-command@2.0.0:
- resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==}
- engines: {node: '>=8'}
-
- shebang-regex@3.0.0:
- resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==}
- engines: {node: '>=8'}
-
- signal-exit@4.1.0:
- resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==}
- engines: {node: '>=14'}
-
- string-width@4.2.3:
- resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==}
- engines: {node: '>=8'}
-
- string-width@5.1.2:
- resolution: {integrity: sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==}
- engines: {node: '>=12'}
-
- strip-ansi@6.0.1:
- resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==}
- engines: {node: '>=8'}
-
- strip-ansi@7.1.0:
- resolution: {integrity: sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==}
- engines: {node: '>=12'}
-
- supports-color@7.2.0:
- resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==}
- engines: {node: '>=8'}
-
- test-exclude@7.0.1:
- resolution: {integrity: sha512-pFYqmTw68LXVjeWJMST4+borgQP2AyMNbg1BpZh9LbyhUeNkeaPF9gzfPGUAnSMV3qPYdWUwDIjjCLiSDOl7vg==}
- engines: {node: '>=18'}
-
- typescript@5.8.3:
- resolution: {integrity: sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ==}
- engines: {node: '>=14.17'}
- hasBin: true
-
- undici-types@7.8.0:
- resolution: {integrity: sha512-9UJ2xGDvQ43tYyVMpuHlsgApydB8ZKfVYTsLDhXkFL/6gfkp+U8xTGdh8pMJv1SpZna0zxG1DwsKZsreLbXBxw==}
-
- v8-to-istanbul@9.3.0:
- resolution: {integrity: sha512-kiGUalWN+rgBJ/1OHZsBtU4rXZOfj/7rKQxULKlIzwzQSvMJUUNgPwJEEh7gU6xEVxC0ahoOBvN2YI8GH6FNgA==}
- engines: {node: '>=10.12.0'}
-
- which@2.0.2:
- resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==}
- engines: {node: '>= 8'}
- hasBin: true
-
- wrap-ansi@7.0.0:
- resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==}
- engines: {node: '>=10'}
-
- wrap-ansi@8.1.0:
- resolution: {integrity: sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==}
- engines: {node: '>=12'}
-
- y18n@5.0.8:
- resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==}
- engines: {node: '>=10'}
-
- yargs-parser@21.1.1:
- resolution: {integrity: sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==}
- engines: {node: '>=12'}
-
- yargs@17.7.2:
- resolution: {integrity: sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==}
- engines: {node: '>=12'}
-
- yocto-queue@0.1.0:
- resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==}
- engines: {node: '>=10'}
-
-snapshots:
-
- '@bcoe/v8-coverage@1.0.2': {}
-
- '@isaacs/cliui@8.0.2':
- dependencies:
- string-width: 5.1.2
- string-width-cjs: string-width@4.2.3
- strip-ansi: 7.1.0
- strip-ansi-cjs: strip-ansi@6.0.1
- wrap-ansi: 8.1.0
- wrap-ansi-cjs: wrap-ansi@7.0.0
-
- '@istanbuljs/schema@0.1.3': {}
-
- '@jridgewell/resolve-uri@3.1.2': {}
-
- '@jridgewell/sourcemap-codec@1.5.4': {}
-
- '@jridgewell/trace-mapping@0.3.29':
- dependencies:
- '@jridgewell/resolve-uri': 3.1.2
- '@jridgewell/sourcemap-codec': 1.5.4
-
- '@pkgjs/parseargs@0.11.0':
- optional: true
-
- '@types/istanbul-lib-coverage@2.0.6': {}
-
- '@types/node@24.1.0':
- dependencies:
- undici-types: 7.8.0
-
- ansi-regex@5.0.1: {}
-
- ansi-regex@6.1.0: {}
-
- ansi-styles@4.3.0:
- dependencies:
- color-convert: 2.0.1
-
- ansi-styles@6.2.1: {}
-
- balanced-match@1.0.2: {}
-
- brace-expansion@2.0.2:
- dependencies:
- balanced-match: 1.0.2
-
- c8@10.1.3:
- dependencies:
- '@bcoe/v8-coverage': 1.0.2
- '@istanbuljs/schema': 0.1.3
- find-up: 5.0.0
- foreground-child: 3.3.1
- istanbul-lib-coverage: 3.2.2
- istanbul-lib-report: 3.0.1
- istanbul-reports: 3.1.7
- test-exclude: 7.0.1
- v8-to-istanbul: 9.3.0
- yargs: 17.7.2
- yargs-parser: 21.1.1
-
- cliui@8.0.1:
- dependencies:
- string-width: 4.2.3
- strip-ansi: 6.0.1
- wrap-ansi: 7.0.0
-
- color-convert@2.0.1:
- dependencies:
- color-name: 1.1.4
-
- color-name@1.1.4: {}
-
- convert-source-map@2.0.0: {}
-
- cross-spawn@7.0.6:
- dependencies:
- path-key: 3.1.1
- shebang-command: 2.0.0
- which: 2.0.2
-
- eastasianwidth@0.2.0: {}
-
- emoji-regex@8.0.0: {}
-
- emoji-regex@9.2.2: {}
-
- escalade@3.2.0: {}
-
- find-up@5.0.0:
- dependencies:
- locate-path: 6.0.0
- path-exists: 4.0.0
-
- foreground-child@3.3.1:
- dependencies:
- cross-spawn: 7.0.6
- signal-exit: 4.1.0
-
- get-caller-file@2.0.5: {}
-
- glob@10.4.5:
- dependencies:
- foreground-child: 3.3.1
- jackspeak: 3.4.3
- minimatch: 9.0.5
- minipass: 7.1.2
- package-json-from-dist: 1.0.1
- path-scurry: 1.11.1
-
- has-flag@4.0.0: {}
-
- html-escaper@2.0.2: {}
-
- is-fullwidth-code-point@3.0.0: {}
-
- isexe@2.0.0: {}
-
- istanbul-lib-coverage@3.2.2: {}
-
- istanbul-lib-report@3.0.1:
- dependencies:
- istanbul-lib-coverage: 3.2.2
- make-dir: 4.0.0
- supports-color: 7.2.0
-
- istanbul-reports@3.1.7:
- dependencies:
- html-escaper: 2.0.2
- istanbul-lib-report: 3.0.1
-
- jackspeak@3.4.3:
- dependencies:
- '@isaacs/cliui': 8.0.2
- optionalDependencies:
- '@pkgjs/parseargs': 0.11.0
-
- locate-path@6.0.0:
- dependencies:
- p-locate: 5.0.0
-
- lru-cache@10.4.3: {}
-
- make-dir@4.0.0:
- dependencies:
- semver: 7.7.2
-
- minimatch@9.0.5:
- dependencies:
- brace-expansion: 2.0.2
-
- minipass@7.1.2: {}
-
- p-limit@3.1.0:
- dependencies:
- yocto-queue: 0.1.0
-
- p-locate@5.0.0:
- dependencies:
- p-limit: 3.1.0
-
- package-json-from-dist@1.0.1: {}
-
- path-exists@4.0.0: {}
-
- path-key@3.1.1: {}
-
- path-scurry@1.11.1:
- dependencies:
- lru-cache: 10.4.3
- minipass: 7.1.2
-
- require-directory@2.1.1: {}
-
- semver@7.7.2: {}
-
- shebang-command@2.0.0:
- dependencies:
- shebang-regex: 3.0.0
-
- shebang-regex@3.0.0: {}
-
- signal-exit@4.1.0: {}
-
- string-width@4.2.3:
- dependencies:
- emoji-regex: 8.0.0
- is-fullwidth-code-point: 3.0.0
- strip-ansi: 6.0.1
-
- string-width@5.1.2:
- dependencies:
- eastasianwidth: 0.2.0
- emoji-regex: 9.2.2
- strip-ansi: 7.1.0
-
- strip-ansi@6.0.1:
- dependencies:
- ansi-regex: 5.0.1
-
- strip-ansi@7.1.0:
- dependencies:
- ansi-regex: 6.1.0
-
- supports-color@7.2.0:
- dependencies:
- has-flag: 4.0.0
-
- test-exclude@7.0.1:
- dependencies:
- '@istanbuljs/schema': 0.1.3
- glob: 10.4.5
- minimatch: 9.0.5
-
- typescript@5.8.3: {}
-
- undici-types@7.8.0: {}
-
- v8-to-istanbul@9.3.0:
- dependencies:
- '@jridgewell/trace-mapping': 0.3.29
- '@types/istanbul-lib-coverage': 2.0.6
- convert-source-map: 2.0.0
-
- which@2.0.2:
- dependencies:
- isexe: 2.0.0
-
- wrap-ansi@7.0.0:
- dependencies:
- ansi-styles: 4.3.0
- string-width: 4.2.3
- strip-ansi: 6.0.1
-
- wrap-ansi@8.1.0:
- dependencies:
- ansi-styles: 6.2.1
- string-width: 5.1.2
- strip-ansi: 7.1.0
-
- y18n@5.0.8: {}
-
- yargs-parser@21.1.1: {}
-
- yargs@17.7.2:
- dependencies:
- cliui: 8.0.1
- escalade: 3.2.0
- get-caller-file: 2.0.5
- require-directory: 2.1.1
- string-width: 4.2.3
- y18n: 5.0.8
- yargs-parser: 21.1.1
-
- yocto-queue@0.1.0: {}
diff --git a/local_packages/test/http-loader.js b/local_packages/test/http-loader.js
deleted file mode 100644
index 5910a7a..0000000
--- a/local_packages/test/http-loader.js
+++ /dev/null
@@ -1,59 +0,0 @@
-import { Buffer } from 'node:buffer'
-import fs from 'node:fs'
-import { get } from 'node:https'
-
-const fetch = url => new Promise(rs => get(url, rs))
-const cache = new URL('./.cache/', import.meta.url)
-
-export function resolve(specifier, context, nextResolve) {
- const { parentURL = null } = context;
-
- // Normally Node.js would error on specifiers starting with 'https://', so
- // this hook intercepts them and converts them into absolute URLs to be
- // passed along to the later hooks below.
- if (specifier.startsWith('https://')) {
- return {
- shortCircuit: true,
- url: specifier,
- };
- } else if (parentURL && parentURL.startsWith('https://')) {
- return {
- shortCircuit: true,
- url: new URL(specifier, parentURL).href,
- };
- }
-
- // Let Node.js handle all other specifiers.
- return nextResolve(specifier);
-}
-
-export async function load(url, context, nextLoad) {
- // For JavaScript to be loaded over the network, we need to fetch and
- // return it.
- if (url.startsWith('https://')) {
- const uuid = Buffer.from(url).toString('hex')
- const cachedFile = new URL(uuid, cache)
- let data = ''
-
- // cache remote files for 1h
- if (fs.existsSync(cachedFile) && fs.statSync(cachedFile).mtimeMs > Date.now() - 1000 * 60 * 60) {
- data = fs.readFileSync(cachedFile, 'utf8')
- } else {
- const res = await fetch(url).catch(err => err)
- for await (const chunk of res) data += chunk
- fs.mkdirSync(cache, { recursive: true })
- fs.writeFileSync(cachedFile, data)
- }
-
- // This example assumes all network-provided JavaScript is ES module
- // code.
- return {
- format: 'module',
- shortCircuit: true,
- source: data,
- }
- }
-
- // Let Node.js handle all other URLs.
- return nextLoad(url);
-}
\ No newline at end of file
diff --git a/local_packages/test/own-misc-test.js b/local_packages/test/own-misc-test.js
deleted file mode 100644
index c0fb425..0000000
--- a/local_packages/test/own-misc-test.js
+++ /dev/null
@@ -1,257 +0,0 @@
-// @ts-nocheck
-// @ts-ignore
-
-import fs from 'node:fs'
-import buffer from 'node:buffer'
-import syncBlob, {
- blobFromSync,
- blobFrom,
- fileFromSync,
- fileFrom,
- createTemporaryBlob,
- createTemporaryFile
-} from '../from.js'
-
-const license = fs.readFileSync('./LICENSE')
-
-test_blob(() => new Blob([
- 'a',
- new Uint8Array([98]),
- new Uint16Array([25699]),
- new Uint8Array([101]).buffer,
- Buffer.from('f'),
- new Blob(['g']),
- {},
- new URLSearchParams('foo')
-]), {
- desc: 'Blob ctor parts',
- expected: 'abcdefg[object Object]foo=',
- type: '',
- length: 26
-})
-
-promise_test(async () => {
- assert_equals(fileFromSync('./LICENSE').name, 'LICENSE')
- assert_equals((await fileFrom('./LICENSE')).name, 'LICENSE')
-}, 'file from returns the same name')
-
-// Could not find similar test on WPT
-test(() => {
- const now = new Date()
- assert_equals(new File([], '', { lastModified: now }).lastModified, +now)
- assert_equals(new File([], '', { lastModified: +now }).lastModified, +now)
- assert_equals(new File([], '', { lastModified: 100 }).lastModified, 100)
- assert_equals(new File([], '', { lastModified: '200' }).lastModified, 200)
- assert_equals(new File([], '', { lastModified: true }).lastModified, 1)
- assert_equals(new File([], '', { lastModified: false }).lastModified, 0)
- assert_approx_equals(new File([], '').lastModified, Date.now(), 0.020)
- assert_approx_equals(new File([], '', { lastModified: undefined }).lastModified, Date.now(), 0.020)
-}, 'File sets current time')
-
-// Could not find similar test on WPT
-test(() => {
- const values = ['Not a Number', [], {}, null]
- // I can't really see anything about this in the spec,
- // but this is how browsers handle type casting for this option...
- for (const lastModified of values) {
- const file = new File([], '', { lastModified })
- assert_equals(file.lastModified, 0)
- }
-}, 'Interprets NaN value in lastModified option as 0')
-
-test(() => {
- assert_equals(blobFromSync, syncBlob)
-}, 'default export is named exported blobFromSync')
-
-// This was necessary to avoid large ArrayBuffer clones (slice)
-promise_test(async t => {
- const buf = new Uint8Array(65590)
- const blob = new Blob([buf])
- let i = 0
- // eslint-disable-next-line no-unused-vars
- for await (const chunk of blob.stream()) {
- i++
- }
-
- assert_equals(i, 2)
-}, 'Large chunks are divided into smaller chunks')
-
-// Couldn't find a test for this on WPT
-promise_test(async () => {
- const buf = new Uint8Array([97])
- const blob = new Blob([buf])
- const chunk = await blob.stream().getReader().read()
- assert_equals(chunk.value[0], 97)
- chunk.value[0] = 98
- assert_equals(await blob.text(), 'a')
-}, 'Blobs are immutable')
-
-/**
- * Deviation from WPT: it's important to keep boundary value
- * so we don't lowercase the type
- * @see https://github.com/w3c/FileAPI/issues/43
- */
-test(() => {
- const type = 'multipart/form-data; boundary=----WebKitFormBoundaryTKqdrVt01qOBltBd'
- assert_equals(new Blob([], { type }).type, type)
- assert_equals(new File([], '', { type }).type, type)
-}, 'Dose not lowercase the type')
-
-
-test( // Because we have symbol.hasInstance it's best to test it...
- () => (assert_false(null instanceof Blob), assert_false(null instanceof File)),
- 'Instanceof check returns false for nullish values'
-)
-
-test( // Because browser normally never tries things taken for granted
- () => assert_equals(new Blob().toString(), '[object Blob]'),
- 'blob.toString() returns [object Blob]'
-)
-
-test( // Because browser normally never tries things taken for granted
- () => assert_equals(new File([], '').toString(), '[object File]'),
- 'file.toString() returns [object File]'
-)
-
-// fetch-blob uniques is that it supports arbitrary blobs too
-test(() => {
- class File {
- stream () {}
- get [Symbol.toStringTag] () { return 'File' }
- }
- assert_true(new File() instanceof Blob)
-}, 'Blob-ish class is an instance of Blob')
-
-// fetch-blob uniques is that it supports arbitrary blobs too
-if (buffer.Blob) {
- test_blob(() => new Blob([new buffer.Blob(['blob part'])]), {
- desc: 'Can wrap buffer.Blob to a fetch-blob',
- expected: 'blob part',
- type: '',
- })
-}
-
-/**
- * Test if Blob can be constructed with BOM and keep it when casted to string
- * Test if blob.text() can correctly remove BOM - `buffer.toString()` is bad
- */
-promise_test(async () => {
- const text = '{"foo": "bar"}'
- const blob = new Blob([`\uFEFF${text}`])
- assert_equals(blob.size, 17)
- assert_equals(await blob.text(), text)
- const ab = await blob.slice(0, 3).arrayBuffer()
- assert_equals_typed_array(new Uint8Array(ab), new Uint8Array([0xEF, 0xBB, 0xBF]))
-}, 'Can wrap buffer.Blob to a fetch-blob')
-
-// Here to make sure our `toIterator` is working as intended
-promise_test(async () => {
- const stream = new Blob(['Some content']).stream()
-
- // Cancel the stream before start reading, or this will throw an error
- await stream.cancel()
- const reader = stream.getReader()
- const { done, value: chunk } = await reader.read()
-
- assert_true(done)
- assert_equals(chunk, undefined)
-}, 'Blob stream() can be cancelled')
-
-/******************************************************************************/
-/* */
-/* Test Blobs backed up by the filesystem */
-/* */
-/******************************************************************************/
-
-promise_test(async () => {
- assert_equals(fileFromSync('./LICENSE', 'text/plain').type, 'text/plain')
- assert_equals(fileFromSync('./LICENSE').type, '')
-
- assert_equals(blobFromSync('./LICENSE', 'text/plain').type, 'text/plain')
- assert_equals(blobFromSync('./LICENSE').type, '')
-
- assert_equals((await fileFrom('./LICENSE', 'text/plain')).type, 'text/plain')
- assert_equals((await fileFrom('./LICENSE')).type, '')
-
- assert_equals((await blobFrom('./LICENSE', 'text/plain')).type, 'text/plain')
- assert_equals((await blobFrom('./LICENSE')).type, '')
-}, 'from utilities sets correct type')
-
-promise_test(async () => {
- assert_equals(await blobFromSync('./LICENSE').text(), license.toString())
- assert_equals(await fileFromSync('./LICENSE').text(), license.toString())
- assert_equals(await (await blobFrom('./LICENSE')).text(), license.toString())
- assert_equals(await (await fileFrom('./LICENSE')).text(), license.toString())
-}, 'blob part backed up by filesystem can be read')
-
-promise_test(async () => {
- assert_equals(await blobFromSync('./LICENSE').text(), license.toString())
- assert_equals(await fileFromSync('./LICENSE').text(), license.toString())
- assert_equals(await (await blobFrom('./LICENSE')).text(), license.toString())
- assert_equals(await (await fileFrom('./LICENSE')).text(), license.toString())
-}, 'blob part backed up by filesystem slice correctly')
-
-promise_test(async () => {
- let blob
- // Can construct a temporary blob from a string
- blob = await createTemporaryBlob(license.toString())
- assert_equals(await blob.text(), license.toString())
-
- // Can construct a temporary blob from a async iterator
- blob = await createTemporaryBlob(blob.stream())
- assert_equals(await blob.text(), license.toString())
-
- // Can construct a temporary file from a arrayBuffer
- blob = await createTemporaryBlob(await blob.arrayBuffer())
- assert_equals(await blob.text(), license.toString())
-
- // Can construct a temporary file from a arrayBufferView
- blob = await createTemporaryBlob(await blob.arrayBuffer().then(ab => new Uint8Array(ab)))
- assert_equals(await blob.text(), license.toString())
-
- // Can specify a mime type
- blob = await createTemporaryBlob('abc', { type: 'text/plain' })
- assert_equals(blob.type, 'text/plain')
-
- // Can create files too
- let file = await createTemporaryFile('abc', 'abc.txt', {
- type: 'text/plain',
- lastModified: 123
- })
- assert_equals(file.name, 'abc.txt')
- assert_equals(file.size, 3)
- assert_equals(file.lastModified, 123)
-}, 'creating temporary blob/file backed up by filesystem')
-
-promise_test(async () => {
- fs.writeFileSync('temp', '')
- await blobFromSync('./temp').text()
- fs.unlinkSync('./temp')
-}, 'can read empty files')
-
-test(async () => {
- const blob = blobFromSync('./LICENSE')
- await new Promise(resolve => setTimeout(resolve, 2000))
- const now = new Date()
- // Change modified time
- fs.utimesSync('./LICENSE', now, now)
- const error = await blob.text().then(assert_unreached, e => e)
- assert_equals(error.constructor.name, 'DOMException')
- assert_equals(error instanceof Error, true)
- assert_equals(error.name, 'NotReadableError')
-
- const file = fileFromSync('./LICENSE')
- // Above test updates the last modified date to now
- assert_equals(typeof file.lastModified, 'number')
- // The lastModifiedDate is deprecated and removed from spec
- assert_false('lastModifiedDate' in file)
- assert_approx_equals(file.lastModified, +now, 1000)
-}, 'Reading after modified should fail')
-
-promise_test(async () => {
- assert_equals(await blobFromSync('./LICENSE').slice(0, 0).text(), '')
- assert_equals(await blobFromSync('./LICENSE').slice(0, 3).text(), license.slice(0, 3).toString())
- assert_equals(await blobFromSync('./LICENSE').slice(4, 11).text(), license.slice(4, 11).toString())
- assert_equals(await blobFromSync('./LICENSE').slice(-11).text(), license.slice(-11).toString())
- assert_equals(await blobFromSync('./LICENSE').slice(4, 11).slice(2, 5).text(), license.slice(4, 11).slice(2, 5).toString())
-}, 'slicing blobs backed up by filesystem returns correct string')
diff --git a/local_packages/test/test-wpt-in-node.js b/local_packages/test/test-wpt-in-node.js
deleted file mode 100644
index a58a690..0000000
--- a/local_packages/test/test-wpt-in-node.js
+++ /dev/null
@@ -1,146 +0,0 @@
-// Don't want to use the FileReader, don't want to lowerCase the type either
-// import from 'https://wpt.live/resources/testharnessreport.js'
-import('https://wpt.live/FileAPI/file/File-constructor.any.js')
-import('https://wpt.live/FileAPI/blob/Blob-constructor.any.js')
-import('https://wpt.live/FileAPI/blob/Blob-array-buffer.any.js')
-import('https://wpt.live/FileAPI/blob/Blob-slice-overflow.any.js')
-import('https://wpt.live/FileAPI/blob/Blob-slice.any.js')
-import('https://wpt.live/FileAPI/blob/Blob-stream.any.js')
-import('https://wpt.live/FileAPI/blob/Blob-text.any.js')
-import('./own-misc-test.js')
-import { File, Blob } from '../from.js'
-
-let hasFailed
-globalThis.self = globalThis
-await import('https://wpt.live/resources/testharness.js')
-
-setup({
- explicit_timeout: true,
- explicit_done: true
-})
-
-function test_blob (fn, expectations) {
- const expected = expectations.expected
- const type = expectations.type
- const desc = expectations.desc
- const length = expectations.length
-
- const t = async_test(desc)
- t.step(async function () {
- const blob = fn()
- assert_true(blob instanceof Blob)
- assert_false(blob instanceof File)
- assert_equals(blob.type.toLowerCase(), type.toLowerCase())
- assert_equals(await blob.text(), expected)
- t.done()
- })
-}
-
-function test_blob_binary (fn, expectations) {
- const expected = expectations.expected
- const type = expectations.type
- const desc = expectations.desc
-
- const t = async_test(desc)
- t.step(async function () {
- const blob = fn()
- assert_true(blob instanceof Blob)
- assert_false(blob instanceof File)
- assert_equals(blob.type.toLowerCase(), type)
- const result = await blob.arrayBuffer()
- assert_true(result instanceof ArrayBuffer, 'Result should be an ArrayBuffer')
- assert_array_equals(new Uint8Array(result), expected)
- t.done()
- })
-}
-
-// Assert that two TypedArray objects have the same byte values
-globalThis.assert_equals_typed_array = (array1, array2) => {
- const [view1, view2] = [array1, array2].map((array) => {
- assert_true(array.buffer instanceof ArrayBuffer,
- 'Expect input ArrayBuffers to contain field `buffer`')
- return new DataView(array.buffer, array.byteOffset, array.byteLength)
- })
-
- assert_equals(view1.byteLength, view2.byteLength,
- 'Expect both arrays to be of the same byte length')
-
- const byteLength = view1.byteLength
-
- for (let i = 0; i < byteLength; ++i) {
- assert_equals(view1.getUint8(i), view2.getUint8(i),
- `Expect byte at buffer position ${i} to be equal`)
- }
-}
-
-globalThis.add_result_callback((test, ...args) => {
- if ([
- 'Blob with type "A"',
- 'Blob with type "TEXT/HTML"',
- 'Getters and value conversions should happen in order until an exception is thrown.',
- 'Using type in File constructor: TEXT/PLAIN',
- 'Using type in File constructor: text/plain;charset=UTF-8'
- ].includes(test.name)) return
-
- const INDENT_SIZE = 2
- const reporter = {}
-
- reporter.startSuite = name => console.log(`\n ${(name)}\n`)
-
- reporter.pass = message => console.log((indent(('√ ') + message, INDENT_SIZE)))
-
- reporter.fail = message => console.log((indent('\u00D7 ' + message, INDENT_SIZE)))
-
- reporter.reportStack = stack => console.log((indent(stack, INDENT_SIZE * 2)))
-
- function indent (string, times) {
- const prefix = ' '.repeat(times)
- return string.split('\n').map(l => prefix + l).join('\n')
- }
-
- if (test.status === 0) {
- reporter.pass(test.name)
- } else if (test.status === 1) {
- reporter.fail(`${test.name}\n`)
- reporter.reportStack(`${test.message}\n${test.stack}`)
- hasFailed = true
- } else if (test.status === 2) {
- reporter.fail(`${test.name} (timeout)\n`)
- reporter.reportStack(`${test.message}\n${test.stack}`)
- hasFailed = true
- } else if (test.status === 3) {
- reporter.fail(`${test.name} (incomplete)\n`)
- reporter.reportStack(`${test.message}\n${test.stack}`)
- hasFailed = true
- } else if (test.status === 4) {
- reporter.fail(`${test.name} (precondition failed)\n`)
- reporter.reportStack(`${test.message}\n${test.stack}`)
- hasFailed = true
- } else {
- reporter.fail(`unknown test status: ${test.status}`)
- hasFailed = true
- }
-})
-
-globalThis.File = File
-globalThis.Blob = Blob
-globalThis.garbageCollect = () => {}
-globalThis.test_blob = test_blob
-globalThis.test_blob_binary = test_blob_binary
-// Because WPT doesn't clean up after itself
-globalThis.MessageChannel = class extends MessageChannel {
- constructor () {
- super()
- setTimeout(() => {
- this.port1.close()
- this.port2.close()
- this.port1.onmessage = this.port2.onmessage = null
- }, 100)
- }
-}
-
-
-if (hasFailed) {
- console.log('Tests failed')
- process.exit(1)
-}
\ No newline at end of file
diff --git a/package.json b/package.json
index 738c346..7e3b4bd 100644
--- a/package.json
+++ b/package.json
@@ -21,8 +21,10 @@
"dependencies": {
"@apollo/client": "^3.13.8",
"@cloudamqp/amqp-client": "^3.2.1",
+ "dotenv": "^17.2.1",
"graphql": "^16.11.0",
- "lightsaver": "workspace:*"
+ "lightsaver": "workspace:*",
+ "next-auth": "^4.24.11"
},
"devDependencies": {
"@graphql-codegen/cli": "^5.0.7",
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 7416a39..9fec001 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -17,12 +17,18 @@ importers:
'@cloudamqp/amqp-client':
specifier: ^3.2.1
version: 3.2.1
+ dotenv:
+ specifier: ^17.2.1
+ version: 17.2.1
graphql:
specifier: ^16.11.0
version: 16.11.0
lightsaver:
specifier: workspace:*
version: 'link:'
+ next-auth:
+ specifier: ^4.24.11
+ version: 4.24.11(next@15.3.5(@babel/core@7.28.0)(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
devDependencies:
'@graphql-codegen/cli':
specifier: ^5.0.7
@@ -97,6 +103,9 @@ importers:
services/auth:
dependencies:
+ '@ory/client-fetch':
+ specifier: ^1.21.0
+ version: 1.21.0
apollo-server-express:
specifier: ^3.13.0
version: 3.13.0(express@5.1.0)(graphql@16.11.0)
@@ -894,6 +903,12 @@ packages:
resolution: {integrity: sha512-nn5ozdjYQpUCZlWGuxcJY/KpxkWQs4DcbMCmKojjyrYDEAGy4Ce19NN4v5MduafTwJlbKc99UA8YhSVqq9yPZA==}
engines: {node: '>=12.4.0'}
+ '@ory/client-fetch@1.21.0':
+ resolution: {integrity: sha512-Df6sSTxZDM9Z4XeL7pkg6u/PIOYk8pN9lfWnk98blbUsN0/x8CvjtoxTL1ZG4ObN06LX0vInsUkVO4DzbroDPA==}
+
+ '@panva/hkdf@1.2.1':
+ resolution: {integrity: sha512-6oclG6Y3PiDFcoyk8srjLfVKyMfVCKJ27JwNPViuXziFpmdz+MZnZN/aKY0JGXgYuO/VghU0jcOAZgWXZ1Dmrw==}
+
'@parcel/watcher-android-arm64@2.5.1':
resolution: {integrity: sha512-KF8+j9nNbUN8vzOFDpRMsaKBHZ/mcjEjMToVMJOhTozkDonQFFrRcfdLWn6yWKCmJKmdVxSgHiYvTCef4/qcBA==}
engines: {node: '>= 10.0.0'}
@@ -1891,6 +1906,10 @@ packages:
resolution: {integrity: sha512-uBq4egWHTcTt33a72vpSG0z3HnPuIl6NqYcTrKEg2azoEyl2hpW0zqlxysq2pK9HlDIHyHyakeYaYnSAwd8bow==}
engines: {node: '>=12'}
+ dotenv@17.2.1:
+ resolution: {integrity: sha512-kQhDYKZecqnM0fCnzI5eIv5L4cAe/iRI+HqMbO/hbRdTAeXDG+M9FjipUxNfbARuEg4iHIbhnhs78BCHNbSxEQ==}
+ engines: {node: '>=12'}
+
dset@3.1.4:
resolution: {integrity: sha512-2QF/g9/zTaPDc3BjNcVTGoBbXBgYfMTTceLaYcFJ/W9kggFUkhxD/hMEeuLKbugyef9SqAx8cpgwlIP/jinUTA==}
engines: {node: '>=4'}
@@ -2579,6 +2598,9 @@ packages:
resolution: {integrity: sha512-NWDAhdnATItTnRhip9VTd8oXDjVcbhetRN6YzckApnXGxpGUooKMAaf0KVvlZG0+KlJMGkeLElVn4M1ReuxKUQ==}
hasBin: true
+ jose@4.15.9:
+ resolution: {integrity: sha512-1vUQX+IdDMVPj4k8kOxgUqlcK518yluMuGZwqlr44FS1ppZB/5GWh4rZG89erpOBOJjU/OBsnCVFfapsRz6nEA==}
+
jose@5.10.0:
resolution: {integrity: sha512-s+3Al/p9g32Iq+oqXxkW//7jk2Vig6FF1CFqzVXoTUXt2qz89YWbL+OwS17NFYEvxC35n0FKeGO2LGYSxeM2Gg==}
@@ -2878,6 +2900,20 @@ packages:
resolution: {integrity: sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg==}
engines: {node: '>= 0.6'}
+ next-auth@4.24.11:
+ resolution: {integrity: sha512-pCFXzIDQX7xmHFs4KVH4luCjaCbuPRtZ9oBUjUhOk84mZ9WVPf94n87TxYI4rSRf9HmfHEF8Yep3JrYDVOo3Cw==}
+ peerDependencies:
+ '@auth/core': 0.34.2
+ next: ^12.2.5 || ^13 || ^14 || ^15
+ nodemailer: ^6.6.5
+ react: ^17.0.2 || ^18 || ^19
+ react-dom: ^17.0.2 || ^18 || ^19
+ peerDependenciesMeta:
+ '@auth/core':
+ optional: true
+ nodemailer:
+ optional: true
+
next@15.3.5:
resolution: {integrity: sha512-RkazLBMMDJSJ4XZQ81kolSpwiCt907l0xcgcpF4xC2Vml6QVcPNXW0NQRwQ80FFtSn7UM52XN0anaw8TEJXaiw==}
engines: {node: ^18.18.0 || ^19.8.0 || >= 20.0.0}
@@ -2943,10 +2979,17 @@ packages:
nullthrows@1.1.1:
resolution: {integrity: sha512-2vPPEi+Z7WqML2jZYddDIfy5Dqb0r2fze2zTxNNknZaFpVHU3mFB3R+DWeJWGVx0ecvttSGlJTI+WG+8Z4cDWw==}
+ oauth@0.9.15:
+ resolution: {integrity: sha512-a5ERWK1kh38ExDEfoO6qUHJb32rd7aYmPHuyCu3Fta/cnICvYmgd2uhuKXvPD+PXB+gCEYYEaQdIRAjCOwAKNA==}
+
object-assign@4.1.1:
resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==}
engines: {node: '>=0.10.0'}
+ object-hash@2.2.0:
+ resolution: {integrity: sha512-gScRMn0bS5fH+IuwyIFgnh9zBdo4DV+6GhygmWM9HyNJSgS0hScp1f5vjtm7oIIOiT9trXrShAkLFSc2IqKNgw==}
+ engines: {node: '>= 6'}
+
object-inspect@1.13.4:
resolution: {integrity: sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==}
engines: {node: '>= 0.4'}
@@ -2975,6 +3018,10 @@ packages:
resolution: {integrity: sha512-gXah6aZrcUxjWg2zR2MwouP2eHlCBzdV4pygudehaKXSGW4v2AsRQUK+lwwXhii6KFZcunEnmSUoYp5CXibxtA==}
engines: {node: '>= 0.4'}
+ oidc-token-hash@5.1.0:
+ resolution: {integrity: sha512-y0W+X7Ppo7oZX6eovsRkuzcSM40Bicg2JEJkDJ4irIt1wsYAP5MLSNv+QAogO8xivMffw/9OvV3um1pxXgt1uA==}
+ engines: {node: ^10.13.0 || >=12.0.0}
+
on-finished@2.4.1:
resolution: {integrity: sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==}
engines: {node: '>= 0.8'}
@@ -2986,6 +3033,9 @@ packages:
resolution: {integrity: sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==}
engines: {node: '>=6'}
+ openid-client@5.7.1:
+ resolution: {integrity: sha512-jDBPgSVfTnkIh71Hg9pRvtJc6wTwqjRkN88+gCFtYWrlP4Yx2Dsrow8uPi3qLr/aeymPF3o2+dS+wOpglK04ew==}
+
optimism@0.18.1:
resolution: {integrity: sha512-mLXNwWPa9dgFyDqkNi54sjDyNJ9/fTI6WGBLgnXku1vdKY/jovHfZT5r+aiVeFFLOz+foPNOm5YJ4mqgld2GBQ==}
@@ -3097,10 +3147,21 @@ packages:
resolution: {integrity: sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==}
engines: {node: ^10 || ^12 || >=14}
+ preact-render-to-string@5.2.6:
+ resolution: {integrity: sha512-JyhErpYOvBV1hEPwIxc/fHWXPfnEGdRKxc8gFdAZ7XV4tlzyzG847XAyEZqoDnynP88akM4eaHcSOzNcLWFguw==}
+ peerDependencies:
+ preact: '>=10'
+
+ preact@10.26.9:
+ resolution: {integrity: sha512-SSjF9vcnF27mJK1XyFMNJzFd5u3pQiATFqoaDy03XuN00u4ziveVVEGt5RKJrDR8MHE/wJo9Nnad56RLzS2RMA==}
+
prelude-ls@1.2.1:
resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==}
engines: {node: '>= 0.8.0'}
+ pretty-format@3.8.0:
+ resolution: {integrity: sha512-WuxUnVtlWL1OfZFQFuqvnvs6MiAGk9UNsBostyBOB0Is9wb5uRESevA6rnl/rkksXaGX3GzZhPup5d6Vp1nFew==}
+
promise@7.3.1:
resolution: {integrity: sha512-nolQXZ/4L+bP/UGlkfaIujX9BKxGwmQ9OT4mOt5yvy8iK1h3wqTEJCijzGANTCCl9nWjY41juyAn2K3Q1hLLTg==}
@@ -3687,6 +3748,10 @@ packages:
util-deprecate@1.0.2:
resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==}
+ uuid@8.3.2:
+ resolution: {integrity: sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==}
+ hasBin: true
+
uuid@9.0.1:
resolution: {integrity: sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==}
hasBin: true
@@ -4832,6 +4897,10 @@ snapshots:
'@nolyfill/is-core-module@1.0.39': {}
+ '@ory/client-fetch@1.21.0': {}
+
+ '@panva/hkdf@1.2.1': {}
+
'@parcel/watcher-android-arm64@2.5.1':
optional: true
@@ -5890,6 +5959,8 @@ snapshots:
dotenv@16.6.1: {}
+ dotenv@17.2.1: {}
+
dset@3.1.4: {}
dunder-proto@1.0.1:
@@ -6773,6 +6844,8 @@ snapshots:
jiti@2.5.0: {}
+ jose@4.15.9: {}
+
jose@5.10.0: {}
js-tokens@4.0.0: {}
@@ -7005,6 +7078,21 @@ snapshots:
negotiator@1.0.0: {}
+ next-auth@4.24.11(next@15.3.5(@babel/core@7.28.0)(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(react-dom@19.1.0(react@19.1.0))(react@19.1.0):
+ dependencies:
+ '@babel/runtime': 7.27.6
+ '@panva/hkdf': 1.2.1
+ cookie: 0.7.2
+ jose: 4.15.9
+ next: 15.3.5(@babel/core@7.28.0)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
+ oauth: 0.9.15
+ openid-client: 5.7.1
+ preact: 10.26.9
+ preact-render-to-string: 5.2.6(preact@10.26.9)
+ react: 19.1.0
+ react-dom: 19.1.0(react@19.1.0)
+ uuid: 8.3.2
+
next@15.3.5(@babel/core@7.28.0)(react-dom@19.1.0(react@19.1.0))(react@19.1.0):
dependencies:
'@next/env': 15.3.5
@@ -7074,8 +7162,12 @@ snapshots:
nullthrows@1.1.1: {}
+ oauth@0.9.15: {}
+
object-assign@4.1.1: {}
+ object-hash@2.2.0: {}
+
object-inspect@1.13.4: {}
object-keys@1.1.1: {}
@@ -7116,6 +7208,8 @@ snapshots:
define-properties: 1.2.1
es-object-atoms: 1.1.1
+ oidc-token-hash@5.1.0: {}
+
on-finished@2.4.1:
dependencies:
ee-first: 1.1.1
@@ -7128,6 +7222,13 @@ snapshots:
dependencies:
mimic-fn: 2.1.0
+ openid-client@5.7.1:
+ dependencies:
+ jose: 4.15.9
+ lru-cache: 6.0.0
+ object-hash: 2.2.0
+ oidc-token-hash: 5.1.0
+
optimism@0.18.1:
dependencies:
'@wry/caches': 1.0.1
@@ -7248,8 +7349,17 @@ snapshots:
picocolors: 1.1.1
source-map-js: 1.2.1
+ preact-render-to-string@5.2.6(preact@10.26.9):
+ dependencies:
+ preact: 10.26.9
+ pretty-format: 3.8.0
+
+ preact@10.26.9: {}
+
prelude-ls@1.2.1: {}
+ pretty-format@3.8.0: {}
+
promise@7.3.1:
dependencies:
asap: 2.0.6
@@ -7947,6 +8057,8 @@ snapshots:
util-deprecate@1.0.2: {}
+ uuid@8.3.2: {}
+
uuid@9.0.1: {}
v8-compile-cache-lib@3.0.1: {}
diff --git a/services/auth/.env b/services/auth/.env
new file mode 100644
index 0000000..e69de29
diff --git a/services/auth/kratos/kratos.yml b/services/auth/kratos/kratos.yml
new file mode 100644
index 0000000..20bde5a
--- /dev/null
+++ b/services/auth/kratos/kratos.yml
@@ -0,0 +1,23 @@
+version: v0.11.0
+identity:
+ schemas:
+ - id: default
+ url: file:///etc/config/kratos/identity.schema.json
+dsn: postgres://postgres:secret@kratos-postgres:5432/kratos?sslmode=disable
+serve:
+ public:
+ base_url: http://localhost:4433/
+ cors:
+ enabled: true
+ admin:
+ base_url: http://localhost:4434/
+selfservice:
+ default_browser_return_url: http://localhost:3000/
+ flows:
+ login: {}
+ registration: {}
+ methods:
+ password:
+ enabled: true
+log:
+ level: debug
\ No newline at end of file
diff --git a/services/auth/package.json b/services/auth/package.json
index a2f2b6a..f9ef5e2 100644
--- a/services/auth/package.json
+++ b/services/auth/package.json
@@ -12,6 +12,7 @@
"license": "ISC",
"packageManager": "pnpm@10.13.1",
"dependencies": {
+ "@ory/client-fetch": "^1.21.0",
"apollo-server-express": "^3.13.0",
"express": "^5.1.0",
"graphql": "^16.11.0"