diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 6ffb118b..09fd2c5d 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -11,6 +11,10 @@ on: jobs: linux: + strategy: + fail-fast: false + matrix: + arch: [x64, arm64] runs-on: ubuntu-22.04 permissions: contents: write @@ -20,24 +24,23 @@ jobs: with: # needed for git commit history changelog fetch-depth: 0 - - name: Setup Node.js v20 - uses: actions/setup-node@v2 - with: - node-version: 20 - - name: Install dependencies (with Node v20) - run: yarn install --frozen-lockfile --ignore-engines - # make sure the ipfs executable is executable - - name: Download IPFS and set permissions (with Node v20) - run: node electron/download-ipfs && sudo chmod +x bin/linux/ipfs - - - name: Setup Node.js v22 for Electron build + - name: Setup Node.js v22 uses: actions/setup-node@v2 with: node-version: 22 + - name: Install dependencies (with Node v22) + run: yarn install --frozen-lockfile --ignore-engines + # make sure the ipfs executable is executable + - name: Download IPFS and set permissions (with Node v22) + run: node electron/download-ipfs && sudo chmod +x bin/linux/ipfs - name: Build React app (with Node v22) - run: CI='' yarn build - - name: Build Electron app for Linux (with Node v22) - run: yarn electron:build:linux + run: CI='' NODE_ENV=production yarn build + - name: Build Electron app for Linux (arm64) + if: ${{ matrix.arch == 'arm64' }} + run: yarn electron:build:linux:arm64 + - name: Build Electron app for Linux (x64) + if: ${{ matrix.arch == 'x64' }} + run: yarn electron:build:linux:x64 - name: List dist directory run: ls dist @@ -46,14 +49,22 @@ jobs: run: node scripts/release-body > release-body.txt - uses: ncipollo/release-action@v1 with: - artifacts: 'dist/5chan*.AppImage,dist/5chan-html*.zip' + artifacts: 'dist/5chan*.AppImage,dist/5chan*-arm64.AppImage,dist/5chan-html*.zip' token: ${{ secrets.GITHUB_TOKEN }} replacesArtifacts: true - bodyFile: "release-body.txt" + omitBody: true allowUpdates: true mac: - runs-on: macos-15 + strategy: + fail-fast: false + matrix: + include: + - runner: macos-15-intel # Intel x64 + arch: x64 + - runner: macos-latest # Apple Silicon arm64 + arch: arm64 + runs-on: ${{ matrix.runner }} permissions: contents: write steps: @@ -62,10 +73,14 @@ jobs: with: # needed for git commit history changelog fetch-depth: 0 - - name: Setup Node.js v20 + - name: Setup Node.js v22 uses: actions/setup-node@v2 with: - node-version: 20 + node-version: 22 + - name: Setup Python 3.12 + uses: actions/setup-python@v5 + with: + python-version: '3.12' # install missing dep for sqlite (use setup-python to avoid PEP 668 externally-managed-environment error) - uses: actions/setup-python@v5 @@ -73,20 +88,22 @@ jobs: python-version: '3.12' - run: pip install setuptools - - name: Install dependencies (with Node v20) + - name: Install dependencies (with Node v22) run: yarn install --frozen-lockfile --ignore-engines # make sure the ipfs executable is executable - - name: Download IPFS and set permissions (with Node v20) + - name: Download IPFS and set permissions (with Node v22) run: node electron/download-ipfs && sudo chmod +x bin/mac/ipfs - - - name: Setup Node.js v22 for Electron build - uses: actions/setup-node@v2 - with: - node-version: 22 - name: Build React app (with Node v22) - run: CI='' yarn build + run: CI='' NODE_ENV=production yarn build - name: Build Electron app for Mac (with Node v22) - run: yarn electron:build:mac + env: + CSC_IDENTITY_AUTO_DISCOVERY: 'false' + run: | + if [ "${{ matrix.arch }}" = "arm64" ]; then + yarn electron:build:mac:arm64 + else + yarn electron:build:mac:x64 + fi - name: List dist directory run: ls dist @@ -95,10 +112,10 @@ jobs: run: node scripts/release-body > release-body.txt - uses: ncipollo/release-action@v1 with: - artifacts: 'dist/5chan*.dmg' + artifacts: 'dist/5chan*.dmg,dist/5chan*-arm64.dmg' token: ${{ secrets.GITHUB_TOKEN }} replacesArtifacts: true - bodyFile: "release-body.txt" + omitBody: true allowUpdates: true windows: @@ -118,8 +135,8 @@ jobs: - name: Install dependencies (with Node v22) # --network-timeout and --network-concurrency are yarn v1 flags. run: yarn install --frozen-lockfile --network-timeout 100000 --network-concurrency 1 - name: Build React app (with Node v22) - run: yarn build - - name: Build Electron app for Windows (with Node v22) + run: npx cross-env NODE_ENV=production yarn build + - name: Build Electron app for Windows (x64) run: yarn electron:build:windows - name: List dist directory run: dir dist @@ -132,7 +149,7 @@ jobs: artifacts: 'dist/5chan*.exe' token: ${{ secrets.GITHUB_TOKEN }} replacesArtifacts: true - bodyFile: "release-body.txt" + omitBody: true allowUpdates: true android: @@ -153,14 +170,14 @@ jobs: gradle-version: 8.9 - uses: actions/setup-node@v2 with: - node-version: 20 + node-version: 22 - run: sudo apt install -y apksigner zipalign # install all dependencies (including devDependencies needed for React build) - - name: Install dependencies (with Node v20) + - name: Install dependencies (with Node v22) run: yarn install --frozen-lockfile --ignore-engines # build react app - - run: CI='' yarn build + - run: CI='' NODE_ENV=production yarn build # set android versionCode and versionName - run: sed -i "s/versionCode 1/versionCode $(git tag | wc -l)/" ./android/app/build.gradle - run: sed -i "s/versionName \"1.0\"/versionName \"$(node -e "console.log(require('./package.json').version)")\"/" ./android/app/build.gradle @@ -168,7 +185,7 @@ jobs: # build apk - run: npx cap sync android - run: cd android && gradle bundle - - run: cd android && ./gradlew assembleRelease + - run: cd android && ./gradlew assembleRelease --stacktrace # optimize apk - run: cd android/app/build/outputs/apk/release && zipalign 4 app-release-unsigned.apk app-release-unsigned-zip.apk # sign apk @@ -185,5 +202,31 @@ jobs: artifacts: 'dist/5chan*.apk' token: ${{ secrets.GITHUB_TOKEN }} replacesArtifacts: true - bodyFile: "release-body.txt" + omitBody: true allowUpdates: true + + finalize-release: + runs-on: ubuntu-22.04 + needs: [linux, mac, windows, android] + steps: + - uses: actions/checkout@v2 + with: + fetch-depth: 0 + - name: Setup Node.js v22 + uses: actions/setup-node@v2 + with: + node-version: 22 + - name: Install dependencies + run: yarn install --frozen-lockfile --ignore-engines + - name: Generate final release body from GitHub assets + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + GITHUB_REPOSITORY: ${{ github.repository }} + GITHUB_REF_NAME: ${{ github.ref_name }} + run: node scripts/release-body > release-body.txt + - name: Update release body only + uses: ncipollo/release-action@v1 + with: + token: ${{ secrets.GITHUB_TOKEN }} + allowUpdates: true + bodyFile: "release-body.txt" diff --git a/package.json b/package.json index 258fe314..abc5ddf7 100644 --- a/package.json +++ b/package.json @@ -46,6 +46,7 @@ "zustand": "4.4.3" }, "scripts": { + "postinstall": "node scripts/fix-bonfida-imports.js", "generate:assets": "node scripts/generate-asset-manifest.js", "prebuild": "yarn generate:assets", "prestart": "yarn generate:assets", @@ -61,8 +62,12 @@ "electron:start": "concurrently \"cross-env BROWSER=none yarn start\" \"wait-on http://localhost:3000 && yarn electron\"", "electron:start:no-delete-data": "concurrently \"cross-env BROWSER=none yarn start\" \"wait-on http://localhost:3000 && yarn electron:no-delete-data\"", "electron:build:linux": "yarn build && yarn build:preload && electron-builder build --publish never -l", + "electron:build:linux:x64": "yarn build:preload && electron-builder build --publish never -l --x64", + "electron:build:linux:arm64": "yarn build:preload && electron-builder build --publish never -l --arm64", "electron:build:windows": "yarn build && yarn build:preload && electron-builder build --publish never -w", "electron:build:mac": "yarn build && yarn build:preload && electron-builder build --publish never -m", + "electron:build:mac:x64": "yarn build:preload && electron-builder build --publish never -m --x64", + "electron:build:mac:arm64": "yarn build:preload && electron-builder build --publish never -m --arm64", "electron:before": "yarn electron-rebuild && yarn electron:before:download-ipfs && yarn electron:before:delete-data", "electron:before:download-ipfs": "node electron/download-ipfs", "electron:before:delete-data": "rimraf .plebbit", @@ -114,6 +119,7 @@ "isomorphic-fetch": "3.0.0", "jsdom": "27.3.0", "lint-staged": "12.3.8", + "node-fetch": "3.3.2", "oxfmt": "0.20.0", "oxlint": "1.35.0", "progress": "2.0.3", @@ -127,6 +133,8 @@ "wait-on": "9.0.3" }, "resolutions": { + "@bonfida/spl-name-service": "3.0.16", + "@bonfida/sns-records": "0.0.1", "js-yaml": "4.1.1", "baseline-browser-mapping": "^2.9.11", "vite": "npm:rolldown-vite@7.3.1", @@ -153,12 +161,11 @@ "appId": "5chan.desktop", "productName": "5chan", "icon": "public/icon.png", + "asarUnpack": [ + "**/*.node" + ], "beforePack": "electron/before-pack.js", "afterAllArtifactBuild": "electron/after-all-artifact-build.cjs", - "asarUnpack": [ - "node_modules/@bonfida/**/*", - "node_modules/@solana/**/*" - ], "extraResources": [ { "from": "bin/${os}", diff --git a/scripts/fix-bonfida-imports.js b/scripts/fix-bonfida-imports.js new file mode 100644 index 00000000..d5b5b829 --- /dev/null +++ b/scripts/fix-bonfida-imports.js @@ -0,0 +1,140 @@ +#!/usr/bin/env node +// Fix broken ESM imports in @bonfida/spl-name-service +// The package ships with hardcoded ../node_modules/ paths that break in electron asar + +import fs from 'fs'; +import path from 'path'; +import { fileURLToPath } from 'url'; + +const __dirname = path.dirname(fileURLToPath(import.meta.url)); +const rootDir = path.join(__dirname, '..'); +const bonfidaEsmDir = path.join(rootDir, 'node_modules/@bonfida/spl-name-service/dist/esm'); +const bonfidaCjsDir = path.join(rootDir, 'node_modules/@bonfida/spl-name-service/dist/cjs'); + +// Map of known packages to their correct import paths +const packageMappings = { + '@noble/hashes': (subpath) => { + // ../node_modules/@noble/hashes/esm/sha256.js -> @noble/hashes/sha256 + if (subpath.includes('/sha256')) return '@noble/hashes/sha256'; + if (subpath.includes('/sha512')) return '@noble/hashes/sha512'; + return '@noble/hashes'; + }, + '@noble/curves': (subpath) => { + // ../node_modules/@noble/curves/esm/ed25519.js -> @noble/curves/ed25519 + if (subpath.includes('/ed25519')) return '@noble/curves/ed25519'; + if (subpath.includes('/secp256k1')) return '@noble/curves/secp256k1'; + return '@noble/curves'; + }, + '@solana/spl-token': () => '@solana/spl-token', + '@solana/web3.js': () => '@solana/web3.js', + '@bonfida/sns-records': () => '@bonfida/sns-records', + '@scure/base': () => '@scure/base', + buffer: () => 'buffer', + borsh: () => 'borsh', + graphemesplit: () => 'graphemesplit', + bs58: () => 'bs58', + 'ipaddr.js': () => 'ipaddr.js', + punycode: () => 'punycode', +}; + +// Generic function to fix node_modules imports +function fixImportsInContent(content) { + // Match patterns like from"../node_modules/PACKAGE/..." or from"./node_modules/PACKAGE/..." + const importPattern = /from\s*["'](\.\.?\/node_modules\/((?:@[^\/]+\/[^\/]+|[^\/]+))([^"']*))["']/g; + const sideEffectPattern = /import\s*["'](\.\.?\/node_modules\/((?:@[^\/]+\/[^\/]+|[^\/]+))([^"']*))["']/g; + const requirePattern = /require\s*\(\s*["'](\.\.?\/node_modules\/((?:@[^\/]+\/[^\/]+|[^\/]+))([^"']*))["']\s*\)/g; + + let modified = false; + + const replaceImport = (match, fullPath, packageName, subpath) => { + modified = true; + const mapper = packageMappings[packageName]; + const correctImport = mapper ? mapper(subpath) : packageName; + return `from"${correctImport}"`; + }; + + const replaceSideEffect = (match, fullPath, packageName, subpath) => { + modified = true; + const mapper = packageMappings[packageName]; + const correctImport = mapper ? mapper(subpath) : packageName; + return `import"${correctImport}"`; + }; + + const replaceRequire = (match, fullPath, packageName, subpath) => { + modified = true; + const mapper = packageMappings[packageName]; + const correctImport = mapper ? mapper(subpath) : packageName; + return `require("${correctImport}")`; + }; + + let result = content; + result = result.replace(importPattern, replaceImport); + result = result.replace(sideEffectPattern, replaceSideEffect); + result = result.replace(requirePattern, replaceRequire); + + return { content: result, modified }; +} + +function fixFile(filePath) { + if (!fs.existsSync(filePath)) return false; + + const content = fs.readFileSync(filePath, 'utf8'); + const result = fixImportsInContent(content); + + if (result.modified) { + fs.writeFileSync(filePath, result.content); + return true; + } + return false; +} + +function fixDirectory(dir) { + if (!fs.existsSync(dir)) { + console.log(`Directory not found: ${dir}`); + return; + } + + let fixedCount = 0; + + function walk(currentDir) { + const entries = fs.readdirSync(currentDir, { withFileTypes: true }); + + for (const entry of entries) { + const fullPath = path.join(currentDir, entry.name); + + if (entry.isDirectory() && entry.name !== 'node_modules') { + walk(fullPath); + } else if (entry.isFile() && /\.(m?js|cjs)$/.test(entry.name)) { + if (fixFile(fullPath)) { + fixedCount++; + } + } + } + } + + walk(dir); + return fixedCount; +} + +console.log('Fixing @bonfida/spl-name-service broken imports...'); + +const esmFixed = fixDirectory(bonfidaEsmDir); +const cjsFixed = fixDirectory(bonfidaCjsDir); + +console.log(`Fixed ${esmFixed} ESM files and ${cjsFixed} CJS files`); + +// Also remove the nested node_modules that are no longer needed +const nestedEsm = path.join(bonfidaEsmDir, 'node_modules'); +const nestedCjs = path.join(bonfidaCjsDir, 'node_modules'); + +if (fs.existsSync(nestedEsm)) { + fs.rmSync(nestedEsm, { recursive: true }); + console.log('Removed nested ESM node_modules'); +} + +if (fs.existsSync(nestedCjs)) { + fs.rmSync(nestedCjs, { recursive: true }); + console.log('Removed nested CJS node_modules'); +} + +console.log('Done!'); diff --git a/scripts/release-body.js b/scripts/release-body.js index e086ce45..50d30790 100644 --- a/scripts/release-body.js +++ b/scripts/release-body.js @@ -1,34 +1,118 @@ -import {execSync} from 'child_process' -import path from 'path' -import {fileURLToPath} from 'url' -import {readFileSync} from 'fs' +import { execSync } from 'child_process'; +import path from 'path'; +import { fileURLToPath } from 'url'; +import { readFileSync, readdirSync } from 'fs'; +import fetch from 'node-fetch'; -const dirname = path.join(path.dirname(fileURLToPath(import.meta.url))) -const conventionalChangelog = path.join(dirname, '..', 'node_modules', '.bin', 'conventional-changelog') -const packageJsonPath = path.join(dirname, '..', 'package.json') -const packageJson = JSON.parse(readFileSync(packageJsonPath, 'utf8')) -const version = packageJson.version +const dirname = path.join(path.dirname(fileURLToPath(import.meta.url))); +const conventionalChangelog = path.join(dirname, '..', 'node_modules', '.bin', 'conventional-changelog'); +const version = JSON.parse(readFileSync(path.join(dirname, '..', 'package.json'), 'utf8')).version; -// sometimes release-count 1 is empty -let releaseChangelog = - execSync(`${conventionalChangelog} --preset angular --release-count 1`).toString() || - execSync(`${conventionalChangelog} --preset angular --release-count 2`).toString() +// changelog (use last non-empty) +let releaseChangelog = + execSync(`${conventionalChangelog} --preset angular --release-count 1`).toString() || + execSync(`${conventionalChangelog} --preset angular --release-count 2`).toString(); +releaseChangelog = releaseChangelog.trim().replace(/\n\n+/g, '\n\n'); -// format -releaseChangelog = releaseChangelog.trim().replace(/\n\n+/g, '\n\n') +// discover artifacts +const distDir = path.join(dirname, '..', 'dist'); +let files = []; +try { + files = readdirSync(distDir); +} catch {} + +// In CI finalization, dist is empty. Prefer GitHub release assets when available. +const getReleaseAssetNames = async () => { + try { + const token = process.env.GITHUB_TOKEN; + const repo = process.env.GITHUB_REPOSITORY; // owner/repo + const tag = process.env.GITHUB_REF_NAME || `v${version}`; + if (!token || !repo || !tag) return []; + const res = await fetch(`https://api.github.com/repos/${repo}/releases/tags/${tag}`, { + headers: { + Authorization: `Bearer ${token}`, + 'User-Agent': '5chan-release-notes', + 'X-GitHub-Api-Version': '2022-11-28', + Accept: 'application/vnd.github+json', + }, + }); + if (!res.ok) return []; + const data = await res.json(); + return (data.assets || []).map((a) => a.name).filter(Boolean); + } catch (e) { + return []; + } +}; + +const remoteFiles = await getReleaseAssetNames(); +if (remoteFiles.length) { + files = remoteFiles; +} + +const linkTo = (file) => `https://github.com/plebbit/5chan/releases/download/v${version}/${file}`; +const has = (s, sub) => s.toLowerCase().includes(sub); +const isArm = (s) => has(s, 'arm64') || has(s, 'aarch64'); +const isX64 = (s) => has(s, 'x64') || has(s, 'x86_64') || !isArm(s); + +// buckets +const androidApk = files.find((f) => f.endsWith('.apk')); +const htmlZip = files.find((f) => f.includes('5chan-html') && f.endsWith('.zip')); + +const linux = files.filter((f) => f.endsWith('.AppImage')); +const mac = files.filter((f) => f.endsWith('.dmg')); +const win = files.filter((f) => f.toLowerCase().endsWith('.exe')); + +const linuxArm = linux.find(isArm); +const linuxX64 = linux.find(isX64); +const macArm = mac.find(isArm); +const macX64 = mac.find(isX64); + +const winSetupX64 = win.find((f) => has(f, 'setup') && isX64(f)); +const winPortableX64 = win.find((f) => has(f, 'portable') && isX64(f)); + +// small section builder without push() +const section = (title, lines) => { + const body = lines.filter(Boolean).join('\n'); + return body ? `### ${title}\n${body}` : ''; +}; + +const macSection = section('macOS', [ + macArm && `- Apple Silicon (arm64): [Download DMG](${linkTo(macArm)})`, + macX64 && `- Intel (x64): [Download DMG](${linkTo(macX64)})`, + mac.length > 0 && + `- If macOS shows "5chan.app is damaged and can't be opened. You should move it to the Trash.", run this in Terminal to fix it: \`xattr -dr com.apple.quarantine "/Applications/5chan.app"\` then open the app again.`, +]); + +const winSection = section('Windows', [ + winSetupX64 && `- Installer (x64): [Download EXE](${linkTo(winSetupX64)})`, + winPortableX64 && `- Portable (x64): [Download EXE](${linkTo(winPortableX64)})`, + win.length > 0 && + `- If Windows shows "Windows protected your PC" (SmartScreen), click "More info" then "Run anyway". To permanently allow, right-click the .exe → Properties → check "Unblock", or run in PowerShell: \`Unblock-File -Path .\\path\\to\\file.exe\`.`, +]); + +const linuxSection = section('Linux', [ + linuxArm && `- AppImage (arm64): [Download](${linkTo(linuxArm)})`, + linuxX64 && `- AppImage (x64): [Download](${linkTo(linuxX64)})`, +]); + +const androidSection = section('Android', [androidApk && `- APK: [Download](${linkTo(androidApk)})`]); + +const htmlSection = section('Static HTML build', [htmlZip && `- 5chan-html (zip): [Download](${linkTo(htmlZip)})`]); + +const downloads = [macSection, winSection, linuxSection, androidSection, htmlSection].filter(Boolean).join('\n\n'); const releaseBody = `This version rebrands the app to 5chan, introducing a set of new features and several performance improvements. - Web app: https://5chan.app -- Decentralized web app: https://5chan.eth (only works on [Brave Browser](https://brave.com/) or via [IPFS Companion](https://docs.ipfs.tech/install/ipfs-companion/#prerequisites)) +- Decentralized web app via IPFS/IPNS gateways (works on any browser): [5chan.eth.limo](https://5chan.eth.limo), [5chan.eth.link](https://5chan.eth.link), [dweb.link/ipfs.io](https://dweb.link/ipns/5chan.eth) +- Decentralized web app via IPFS node you run: https://5chan.eth (works on [Brave Browser](https://brave.com/) or use [IPFS Companion](https://docs.ipfs.tech/install/ipfs-companion/#prerequisites)) ## Downloads -- Android app: [Download APK](https://github.com/plebbit/5chan/releases/download/v${version}/5chan-${version}.apk) -- Linux app: [Download AppImage](https://github.com/plebbit/5chan/releases/download/v${version}/5chan-${version}.AppImage) -- macOS app: [Download DMG](https://github.com/plebbit/5chan/releases/download/v${version}/5chan-${version}.dmg) -- Windows app: [Download EXE](https://github.com/plebbit/5chan/releases/download/v${version}/5chan.Setup.${version}.exe) +${downloads} -${releaseChangelog}` +## Changes -console.log(releaseBody) \ No newline at end of file +${releaseChangelog}`; + +console.log(releaseBody); diff --git a/yarn.lock b/yarn.lock index a2e302bb..f3a30a8f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1017,18 +1017,18 @@ bs58 "5.0.0" buffer "^6.0.3" -"@bonfida/spl-name-service@3.0.10": - version "3.0.10" - resolved "https://registry.yarnpkg.com/@bonfida/spl-name-service/-/spl-name-service-3.0.10.tgz#883f2e077eef7d91147f44ae383990a82479d5f8" - integrity sha512-CrqlEDz43K9fPIVaUXn29OiMWZUOs3+sxU7zHrlPjjdXn9GrJSVao5gjmflfK6tcwLxSSGC4F4GOg5erSfyR/A== +"@bonfida/spl-name-service@3.0.10", "@bonfida/spl-name-service@3.0.16": + version "3.0.16" + resolved "https://registry.yarnpkg.com/@bonfida/spl-name-service/-/spl-name-service-3.0.16.tgz#5ebcadbb1908af9348ff15c20a4e4fdc8a1408da" + integrity sha512-Y47inKaoGYQ2gxykZsLepc0fNPMLWd5ycGQ6k2FiHvIzlY4trHijc7zr9TyDhB/eI9c3XTy5ItM01Izy5pIZ/A== dependencies: "@bonfida/sns-records" "0.0.1" - "@noble/curves" "^1.4.0" - "@scure/base" "^1.1.6" + "@noble/curves" "^1.9.1" + "@scure/base" "^1.2.5" "@solana/spl-token" "0.4.6" borsh "2.0.0" buffer "^6.0.3" - graphemesplit "^2.4.4" + graphemesplit "^2.6.0" ipaddr.js "^2.2.0" punycode "^2.3.1" @@ -3732,7 +3732,7 @@ dependencies: "@noble/hashes" "1.8.0" -"@noble/curves@^1.4.0", "@noble/curves@^1.4.2", "@noble/curves@~1.9.0": +"@noble/curves@^1.4.0", "@noble/curves@^1.4.2", "@noble/curves@^1.9.1", "@noble/curves@~1.9.0": version "1.9.7" resolved "https://registry.yarnpkg.com/@noble/curves/-/curves-1.9.7.tgz#79d04b4758a43e4bca2cbdc62e7771352fa6b951" integrity sha512-gbKGcRUYIjA3/zCCNaWDciTMFI0dCkvou3TL8Zmy5Nc7sJ47a0jtOeZoTaMxkuqRo9cRhjOdZJXegxYE5FN/xw== @@ -4403,7 +4403,7 @@ estree-walker "^2.0.2" picomatch "^4.0.2" -"@scure/base@^1.1.6", "@scure/base@~1.2.5": +"@scure/base@^1.2.5", "@scure/base@~1.2.5": version "1.2.6" resolved "https://registry.yarnpkg.com/@scure/base/-/base-1.2.6.tgz#ca917184b8231394dd8847509c67a0be522e59f6" integrity sha512-g/nm5FgUa//MCj1gV09zTJTaM6KBAHqLN907YVQqf7zC49+DcO4B1so4ZX07Ef10Twr6nuqYEH9GEggFXA4Fmg== @@ -6863,6 +6863,11 @@ dargs@^8.0.0: resolved "https://registry.yarnpkg.com/dargs/-/dargs-8.1.0.tgz#a34859ea509cbce45485e5aa356fef70bfcc7272" integrity sha512-wAV9QHOsNbwnWdNW2FYvE1P56wtgSbM+3SZcdGiWQILwVjACCXDCI3Ai8QlCjMDB8YK5zySiXZYBiwGmNY3lnw== +data-uri-to-buffer@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/data-uri-to-buffer/-/data-uri-to-buffer-4.0.1.tgz#d8feb2b2881e6a4f58c2e08acfd0e2834e26222e" + integrity sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A== + data-urls@^6.0.0: version "6.0.0" resolved "https://registry.yarnpkg.com/data-urls/-/data-urls-6.0.0.tgz#95a7943c8ac14c1d563b771f2621cc50e8ec7744" @@ -7960,6 +7965,14 @@ fdir@^6.5.0: resolved "https://registry.yarnpkg.com/fdir/-/fdir-6.5.0.tgz#ed2ab967a331ade62f18d077dae192684d50d350" integrity sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg== +fetch-blob@^3.1.2, fetch-blob@^3.1.4: + version "3.2.0" + resolved "https://registry.yarnpkg.com/fetch-blob/-/fetch-blob-3.2.0.tgz#f09b8d4bbd45adc6f0c20b7e787e793e309dcce9" + integrity sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ== + dependencies: + node-domexception "^1.0.0" + web-streams-polyfill "^3.0.3" + figures@^3.0.0: version "3.2.0" resolved "https://registry.yarnpkg.com/figures/-/figures-3.2.0.tgz#625c18bd293c604dc4a8ddb2febf0c88341746af" @@ -8086,6 +8099,13 @@ form-data@^4.0.0, form-data@^4.0.4: hasown "^2.0.2" mime-types "^2.1.12" +formdata-polyfill@^4.0.10: + version "4.0.10" + resolved "https://registry.yarnpkg.com/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz#24807c31c9d402e002ab3d8c720144ceb8848423" + integrity sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g== + dependencies: + fetch-blob "^3.1.2" + freeport-promise@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/freeport-promise/-/freeport-promise-2.0.0.tgz#11e4f81e24d680b88a20c15b2103551f4b6663d8" @@ -8425,7 +8445,7 @@ graceful-fs@^4.1.10, graceful-fs@^4.1.6, graceful-fs@^4.2.0, graceful-fs@^4.2.11 resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.11.tgz#4183e4e8bf08bb6e05bbb2f7d2e0c8f712ca40e3" integrity sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ== -graphemesplit@^2.4.4: +graphemesplit@^2.6.0: version "2.6.0" resolved "https://registry.yarnpkg.com/graphemesplit/-/graphemesplit-2.6.0.tgz#548ec986e83dcdfec31adf5c98b282985077ce46" integrity sha512-rG9w2wAfkpg0DILa1pjnjNfucng3usON360shisqIMUBw/87pojcBSrHmeE4UwryAuBih7g8m1oilf5/u8EWdQ== @@ -11466,6 +11486,20 @@ node-datachannel@^0.29.0: dependencies: prebuild-install "^7.1.3" +node-domexception@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/node-domexception/-/node-domexception-1.0.0.tgz#6888db46a1f71c0b76b3f7555016b63fe64766e5" + integrity sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ== + +node-fetch@3.3.2: + version "3.3.2" + resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-3.3.2.tgz#d1e889bacdf733b4ff3b2b243eb7a12866a0b78b" + integrity sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA== + dependencies: + data-uri-to-buffer "^4.0.0" + fetch-blob "^3.1.4" + formdata-polyfill "^4.0.10" + node-fetch@^2.6.1, node-fetch@^2.6.11, node-fetch@^2.6.7, node-fetch@^2.7.0: version "2.7.0" resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.7.0.tgz#d0f0fa6e3e2dc1d27efcd8ad99d550bda94d187d" @@ -14904,6 +14938,11 @@ web-namespaces@^2.0.0: resolved "https://registry.yarnpkg.com/web-namespaces/-/web-namespaces-2.0.1.tgz#1010ff7c650eccb2592cebeeaf9a1b253fd40692" integrity sha512-bKr1DkiNa2krS7qxNtdrtHAmzuYGFQLiQ13TsorsdT6ULTkPLKuu5+GsFpDlg6JFjUTwX2DyhMPG2be8uPrqsQ== +web-streams-polyfill@^3.0.3: + version "3.3.3" + resolved "https://registry.yarnpkg.com/web-streams-polyfill/-/web-streams-polyfill-3.3.3.tgz#2073b91a2fdb1fbfbd401e7de0ac9f8214cecb4b" + integrity sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw== + webcrypto-core@^1.8.0: version "1.8.1" resolved "https://registry.yarnpkg.com/webcrypto-core/-/webcrypto-core-1.8.1.tgz#09d5bd8a9c48e9fbcaf412e06b1ff1a57514ce86"