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"