diff --git a/.changeset/thick-rings-punch.md b/.changeset/thick-rings-punch.md new file mode 100644 index 0000000..b4cc4df --- /dev/null +++ b/.changeset/thick-rings-punch.md @@ -0,0 +1,5 @@ +--- +"@swc/cli": patch +--- + +Skip the write when emitted output is byte-identical, and write through a temp file plus rename so watch consumers never read a partially written file diff --git a/packages/cli/package.json b/packages/cli/package.json index e3dbfaa..7402570 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -55,7 +55,8 @@ "semver": "^7.3.8", "slash": "3.0.0", "source-map": "^0.7.3", - "tinyglobby": "^0.2.13" + "tinyglobby": "^0.2.13", + "write-file-atomic": "^7.0.1" }, "devDependencies": { "@swc/cli": "0.8.0", @@ -65,6 +66,7 @@ "@types/jest": "^29.5.0", "@types/node": "^20.11.5", "@types/semver": "^7.3.13", + "@types/write-file-atomic": "^4.0.3", "chokidar": "^5.0.0", "deepmerge": "^4.2.2", "jest": "^29.5.0", diff --git a/packages/cli/src/swc/__tests__/atomicWrite.test.ts b/packages/cli/src/swc/__tests__/atomicWrite.test.ts new file mode 100644 index 0000000..2d0ea88 --- /dev/null +++ b/packages/cli/src/swc/__tests__/atomicWrite.test.ts @@ -0,0 +1,387 @@ +import { + chmodSync, + lstatSync, + mkdirSync, + mkdtempSync, + readdirSync, + promises, + readFileSync, + rmSync, + statSync, + symlinkSync, + writeFileSync, +} from "fs"; +import { join } from "path"; +import { tmpdir } from "os"; +import { + copyFileAtomicallyIfChanged, + writeFileAtomicallyIfChanged, + writeFileAtomicallyIfChangedSync, +} from "../util"; + +// Windows has no POSIX permission bits: mode always reads back as 0o666. +const itPosix = process.platform === "win32" ? it.skip : it; +// Permission bits do not constrain root, so those cases cannot be exercised. +const itUnprivileged = + process.platform === "win32" || process.getuid?.() === 0 ? it.skip : it; + +let dir: string; + +beforeEach(() => { + dir = mkdtempSync(join(tmpdir(), "swc-cli-atomic-")); +}); + +afterEach(() => { + rmSync(dir, { recursive: true, force: true }); +}); + +function identity(path: string) { + const { mtimeMs, ino } = statSync(path); + return { mtimeMs, ino }; +} + +async function tmpFiles() { + const entries = await promises.readdir(dir); + return entries.filter(entry => entry.endsWith(".tmp")); +} + +describe("writeFileAtomicallyIfChanged", () => { + it("skips the write when the content is identical", async () => { + const dest = join(dir, "out.js"); + await writeFileAtomicallyIfChanged(dest, "content"); + const before = identity(dest); + + await writeFileAtomicallyIfChanged(dest, "content"); + + expect(identity(dest)).toEqual(before); + expect(await tmpFiles()).toEqual([]); + }); + + it("writes when the content changed", async () => { + const dest = join(dir, "out.js"); + await writeFileAtomicallyIfChanged(dest, "old"); + + await writeFileAtomicallyIfChanged(dest, "new"); + + expect(readFileSync(dest, "utf8")).toBe("new"); + expect(await tmpFiles()).toEqual([]); + }); + + itPosix("applies the given mode", async () => { + const dest = join(dir, "out.js"); + await writeFileAtomicallyIfChanged(dest, "content", { mode: 0o640 }); + + expect(statSync(dest).mode & 0o777).toBe(0o640); + }); +}); + +describe("writeFileAtomicallyIfChangedSync", () => { + it("skips the write when the content is identical", async () => { + const dest = join(dir, "out.js"); + writeFileAtomicallyIfChangedSync(dest, "content"); + const before = identity(dest); + + writeFileAtomicallyIfChangedSync(dest, "content"); + + expect(identity(dest)).toEqual(before); + expect(await tmpFiles()).toEqual([]); + }); + + it("writes when the content changed", async () => { + const dest = join(dir, "out.js"); + writeFileAtomicallyIfChangedSync(dest, "old"); + + writeFileAtomicallyIfChangedSync(dest, "new"); + + expect(readFileSync(dest, "utf8")).toBe("new"); + expect(await tmpFiles()).toEqual([]); + }); +}); + +describe("copyFileAtomicallyIfChanged", () => { + it("skips the copy when the files are identical", async () => { + const src = join(dir, "src.bin"); + const dest = join(dir, "dest.bin"); + await promises.writeFile(src, Buffer.from([0, 1, 2, 255])); + await copyFileAtomicallyIfChanged(src, dest); + const before = identity(dest); + + await copyFileAtomicallyIfChanged(src, dest); + + expect(identity(dest)).toEqual(before); + expect(await tmpFiles()).toEqual([]); + }); + + it("copies when the source changed", async () => { + const src = join(dir, "src.bin"); + const dest = join(dir, "dest.bin"); + await promises.writeFile(src, Buffer.from([0, 1, 2, 255])); + await copyFileAtomicallyIfChanged(src, dest); + + const changed = Buffer.from([3, 4, 5, 254]); + await promises.writeFile(src, changed); + await copyFileAtomicallyIfChanged(src, dest); + + expect(await promises.readFile(dest)).toEqual(changed); + expect(await tmpFiles()).toEqual([]); + }); +}); + +describe("write-file-atomic behaviour", () => { + itPosix("keeps the destination's existing mode", async () => { + const dest = join(dir, "out.js"); + writeFileSync(dest, "old"); + chmodSync(dest, 0o755); + + await writeFileAtomicallyIfChanged(dest, "new"); + + expect(statSync(dest).mode & 0o777).toBe(0o755); + }); + + itPosix("writes through a symlinked destination", async () => { + const target = join(dir, "target.js"); + const link = join(dir, "link.js"); + writeFileSync(target, "old"); + symlinkSync(target, link); + + await writeFileAtomicallyIfChanged(link, "new"); + + expect(lstatSync(link).isSymbolicLink()).toBe(true); + expect(readFileSync(target, "utf8")).toBe("new"); + }); + + it("leaves no temp file behind when the write fails", async () => { + const dest = join(dir, "adir"); + mkdirSync(dest); + + await expect( + writeFileAtomicallyIfChanged(dest, "content") + ).rejects.toThrow(); + + expect(await tmpFiles()).toEqual([]); + }); + + it("compares bytes rather than decoded text", async () => { + const dest = join(dir, "malformed.js"); + writeFileSync(dest, Buffer.from([0xff])); + + await writeFileAtomicallyIfChanged(dest, "\uFFFD"); + + expect([...readFileSync(dest)]).toEqual([0xef, 0xbf, 0xbd]); + }); + + it("survives concurrent writes to the same destination", async () => { + const dest = join(dir, "out.js"); + + await Promise.all([ + writeFileAtomicallyIfChanged(dest, "a".repeat(100)), + writeFileAtomicallyIfChanged(dest, "b".repeat(100)), + ]); + + expect(readFileSync(dest, "utf8")).toHaveLength(100); + expect(await tmpFiles()).toEqual([]); + }); + + itPosix("copies when only the source mode changed", async () => { + const src = join(dir, "script.sh"); + const dest = join(dir, "out.sh"); + writeFileSync(src, "#!/bin/sh\n"); + await copyFileAtomicallyIfChanged(src, dest); + + chmodSync(src, 0o755); + await copyFileAtomicallyIfChanged(src, dest); + + expect(statSync(dest).mode & 0o777).toBe(0o755); + }); +}); + +describe("copy edge cases", () => { + itPosix("copies through a symlinked destination", async () => { + const src = join(dir, "src.txt"); + const target = join(dir, "target.txt"); + const link = join(dir, "link.txt"); + writeFileSync(src, "new"); + writeFileSync(target, "old"); + symlinkSync(target, link); + + await copyFileAtomicallyIfChanged(src, link); + + expect(lstatSync(link).isSymbolicLink()).toBe(true); + expect(readFileSync(target, "utf8")).toBe("new"); + expect(await tmpFiles()).toEqual([]); + }); + + itPosix( + "closes the source when the destination vanishes mid-compare", + async () => { + const openFds = () => readdirSync("/dev/fd").length; + const before = openFds(); + + for (let i = 0; i < 20; i++) { + const src = join(dir, `src${i}`); + const dest = join(dir, `dest${i}`); + writeFileSync(src, "same"); + writeFileSync(dest, "same"); + + const copy = copyFileAtomicallyIfChanged(src, dest); + rmSync(dest, { force: true }); + await copy.catch(() => {}); + } + + expect(openFds() - before).toBeLessThan(10); + } + ); +}); + +describe("unusual destinations", () => { + itPosix("writes through a dangling symlink", async () => { + const target = join(dir, "not-yet.js"); + const link = join(dir, "link.js"); + symlinkSync(target, link); + + await writeFileAtomicallyIfChanged(link, "content"); + + expect(lstatSync(link).isSymbolicLink()).toBe(true); + expect(readFileSync(target, "utf8")).toBe("content"); + }); + + itPosix("writes through a dangling symlink synchronously", () => { + const target = join(dir, "not-yet-sync.js"); + const link = join(dir, "link-sync.js"); + symlinkSync(target, link); + + writeFileAtomicallyIfChangedSync(link, "content"); + + expect(lstatSync(link).isSymbolicLink()).toBe(true); + expect(readFileSync(target, "utf8")).toBe("content"); + }); + + itPosix("copies through a dangling symlink", async () => { + const src = join(dir, "src.txt"); + const target = join(dir, "not-yet.txt"); + const link = join(dir, "link.txt"); + writeFileSync(src, "payload"); + symlinkSync(target, link); + + await copyFileAtomicallyIfChanged(src, link); + + expect(lstatSync(link).isSymbolicLink()).toBe(true); + expect(readFileSync(target, "utf8")).toBe("payload"); + }); + + it("copies to a destination whose name fills a path component", async () => { + const src = join(dir, "src.txt"); + const dest = join(dir, `${"z".repeat(250)}.txt`); + writeFileSync(src, "payload"); + + await copyFileAtomicallyIfChanged(src, dest); + + expect(readFileSync(dest, "utf8")).toBe("payload"); + expect(await tmpFiles()).toEqual([]); + }); + + itUnprivileged( + "writes when the directory cannot host a temp file", + async () => { + const locked = join(dir, "locked"); + const dest = join(locked, "out.js"); + mkdirSync(locked); + writeFileSync(dest, "old"); + chmodSync(dest, 0o666); + chmodSync(locked, 0o555); + + try { + await writeFileAtomicallyIfChanged(dest, "async"); + expect(readFileSync(dest, "utf8")).toBe("async"); + + writeFileAtomicallyIfChangedSync(dest, "sync"); + expect(readFileSync(dest, "utf8")).toBe("sync"); + } finally { + chmodSync(locked, 0o755); + } + } + ); + + itUnprivileged( + "still fails when the destination itself is read only", + async () => { + const locked = join(dir, "read-only"); + const dest = join(locked, "out.js"); + mkdirSync(locked); + writeFileSync(dest, "old"); + chmodSync(dest, 0o444); + chmodSync(locked, 0o555); + + try { + await expect( + writeFileAtomicallyIfChanged(dest, "new") + ).rejects.toThrow(); + } finally { + chmodSync(locked, 0o755); + } + } + ); + + itPosix("writes directly to a non-regular destination", () => { + writeFileAtomicallyIfChangedSync("/dev/null", "payload"); + + expect(statSync("/dev/null").isCharacterDevice()).toBe(true); + }); +}); + +describe("symlink chains", () => { + const chain = (name: string) => { + const target = join(dir, `${name}-target`); + const middle = join(dir, `${name}-middle`); + const top = join(dir, `${name}-top`); + symlinkSync(target, middle); + symlinkSync(middle, top); + return { target, middle, top }; + }; + + const loop = (name: string) => { + const first = join(dir, `${name}-first`); + const second = join(dir, `${name}-second`); + symlinkSync(second, first); + symlinkSync(first, second); + return first; + }; + + itPosix("writes through a chain of dangling links", async () => { + const { target, middle, top } = chain("write"); + + await writeFileAtomicallyIfChanged(top, "content"); + + expect(lstatSync(middle).isSymbolicLink()).toBe(true); + expect(readFileSync(target, "utf8")).toBe("content"); + }); + + itPosix("writes through a chain synchronously", () => { + const { target, middle, top } = chain("sync"); + + writeFileAtomicallyIfChangedSync(top, "content"); + + expect(lstatSync(middle).isSymbolicLink()).toBe(true); + expect(readFileSync(target, "utf8")).toBe("content"); + }); + + itPosix("copies through a chain of dangling links", async () => { + const src = join(dir, "src.txt"); + writeFileSync(src, "content"); + const { target, middle, top } = chain("copy"); + + await copyFileAtomicallyIfChanged(src, top); + + expect(lstatSync(middle).isSymbolicLink()).toBe(true); + expect(readFileSync(target, "utf8")).toBe("content"); + }); + + itPosix("reports a link loop instead of replacing the link", async () => { + const first = loop("write"); + + await expect( + writeFileAtomicallyIfChanged(first, "content") + ).rejects.toMatchObject({ code: "ELOOP" }); + expect(lstatSync(first).isSymbolicLink()).toBe(true); + }); +}); diff --git a/packages/cli/src/swc/compile.ts b/packages/cli/src/swc/compile.ts index 7441e14..8c71ede 100644 --- a/packages/cli/src/swc/compile.ts +++ b/packages/cli/src/swc/compile.ts @@ -3,8 +3,9 @@ import { promises } from "fs"; import { dirname, relative } from "path"; import { transformFile, transformFileSync } from "@swc/core"; import type { Options, Output } from "@swc/core"; +import { writeFileAtomicallyIfChanged } from "./util"; -const { mkdir, stat, writeFile } = promises; +const { mkdir, stat } = promises; function withSourceMap( output: Output, @@ -78,14 +79,14 @@ export async function outputResult({ const { mode } = await stat(sourceFile); const dtsPromise = dts - ? writeFile(destDtsFile, dts, { mode }) + ? writeFileAtomicallyIfChanged(destDtsFile, dts, { mode }) : Promise.resolve(); const sourceMapPromise = sourceMap - ? writeFile(destSourcemapFile, sourceMap, { mode }) + ? writeFileAtomicallyIfChanged(destSourcemapFile, sourceMap, { mode }) : Promise.resolve(); await Promise.all([ - writeFile(destFile, sourceCode, { mode }), + writeFileAtomicallyIfChanged(destFile, sourceCode, { mode }), dtsPromise, sourceMapPromise, ]); diff --git a/packages/cli/src/swc/dir.ts b/packages/cli/src/swc/dir.ts index 78733ca..9a9e175 100644 --- a/packages/cli/src/swc/dir.ts +++ b/packages/cli/src/swc/dir.ts @@ -5,7 +5,7 @@ import { stderr } from "process"; import { format } from "util"; import { CompileStatus } from "./constants"; import { Callbacks, CliOptions } from "./options"; -import { exists, getDest, mapTsExt } from "./util"; +import { copyFileAtomicallyIfChanged, exists, getDest, mapTsExt } from "./util"; import handleCompile from "./dirWorker"; import { globSources, @@ -26,7 +26,7 @@ declare module "fs" { } } -const { mkdir, rmdir, rm, copyFile, unlink } = promises; +const { mkdir, rmdir, rm, unlink } = promises; const recursive = { recursive: true }; @@ -39,7 +39,7 @@ async function handleCopy( const dir = dirname(dest); await mkdir(dir, recursive); - await copyFile(filename, dest); + await copyFileAtomicallyIfChanged(filename, dest); return CompileStatus.Copied; } diff --git a/packages/cli/src/swc/util.ts b/packages/cli/src/swc/util.ts index e6efca4..37bb475 100644 --- a/packages/cli/src/swc/util.ts +++ b/packages/cli/src/swc/util.ts @@ -1,7 +1,16 @@ import * as swc from "@swc/core"; import slash from "slash"; -import { mkdirSync, writeFileSync, promises } from "fs"; -import { dirname, extname, join, relative } from "path"; +import writeFileAtomic from "write-file-atomic"; +import { + mkdirSync, + readFileSync, + readlinkSync, + realpathSync, + statSync, + writeFileSync, + promises, +} from "fs"; +import { dirname, extname, join, relative, resolve } from "path"; import { stderr } from "process"; export async function exists(path: string): Promise { @@ -90,10 +99,240 @@ export function outputFile( const mapLoc = filename + ".map"; code += "\n//# sourceMappingURL=" + slash(relative(fileDirName, mapLoc)); - writeFileSync(mapLoc, output.map); + writeFileAtomicallyIfChangedSync(mapLoc, output.map); } - writeFileSync(filename, code); + writeFileAtomicallyIfChangedSync(filename, code); +} + +// Watch consumers (bundler child compilers) read these files the moment they +// change: never truncate-write in place, and skip identical content so a +// recompile of unchanged sources causes no downstream rebuilds. +export async function writeFileAtomicallyIfChanged( + filename: string, + content: string, + options?: { mode?: number } +): Promise { + // A FIFO or device such as /dev/null has to be written directly: reading it + // can block, and renaming over it would replace the special file. + if (!isRegularFile(filename)) { + await promises.writeFile(filename, content, options); + return; + } + + if (await hasContent(filename, content)) { + return; + } + + // write-file-atomic follows a symlinked destination, but falls back to the + // link itself when the target does not exist yet. Resolve that case here so + // a dangling link keeps pointing at a file the write creates. + const target = await resolveLink(filename); + + try { + await writeFileAtomic(target, content, { ...options, fsync: false }); + } catch (err: any) { + // An output directory that does not allow new files cannot host the + // temporary file, but the output itself may still be writable. + if (err.code !== "EACCES") { + throw err; + } + await promises.writeFile(target, content, options); + } +} + +export function writeFileAtomicallyIfChangedSync( + filename: string, + content: string +): void { + // A FIFO or device such as /dev/null has to be written directly: reading it + // can block, and renaming over it would replace the special file. + if (!isRegularFile(filename)) { + writeFileSync(filename, content); + return; + } + + try { + if (readFileSync(filename).equals(Buffer.from(content))) { + return; + } + } catch {} + + const target = resolveLinkSync(filename); + + try { + writeFileAtomic.sync(target, content, { fsync: false }); + } catch (err: any) { + if (err.code !== "EACCES") { + throw err; + } + writeFileSync(target, content); + } +} + +function isRegularFile(filename: string) { + try { + return statSync(filename).isFile(); + } catch { + // A destination that does not exist yet is created as a regular file. + return true; + } +} + +export async function copyFileAtomicallyIfChanged( + src: string, + dest: string +): Promise { + if (await isSameFile(src, dest)) { + return; + } + + const target = await resolveLink(dest); + + // Copies can be arbitrarily large binaries, so they go through copyFile + // rather than a buffer. The temporary file must live next to the + // destination: rename is only atomic within a single filesystem. Its name + // does not extend the destination's, which can already be at the length a + // single path component allows. + const tmpDest = join( + dirname(target), + `.swc-${process.pid}-${++copies}.tmp` + ); + try { + await promises.copyFile(src, tmpDest); + await promises.rename(tmpDest, target); + } catch (err: any) { + await promises.unlink(tmpDest).catch(() => {}); + throw err; + } +} + +let copies = 0; + +// Follow a symlinked destination rather than replacing the link, which is what +// copyFile did and what write-file-atomic does for generated output. realpath +// rejects on a link whose target does not exist yet, so fall back to the link +// text, which copyFile would have created. +async function resolveLink(dest: string) { + try { + return await promises.realpath(dest); + } catch {} + + // realpath only fails once the chain ends somewhere that does not exist. + // Walk the rest of it by hand, as a plain write would have. + let target = dest; + for (let hop = 0; hop < maxLinkDepth; hop++) { + let link; + try { + link = await promises.readlink(target); + } catch { + return target; + } + target = resolve(dirname(target), link); + } + + throw tooManyLinks(dest); +} + +function resolveLinkSync(dest: string) { + try { + return realpathSync(dest); + } catch {} + + let target = dest; + for (let hop = 0; hop < maxLinkDepth; hop++) { + let link; + try { + link = readlinkSync(target); + } catch { + return target; + } + target = resolve(dirname(target), link); + } + + throw tooManyLinks(dest); +} + +const maxLinkDepth = 40; + +// A chain this long is a loop in practice. A plain write reported ELOOP and +// left the link alone, and renaming over it silently would not. +function tooManyLinks(dest: string) { + return Object.assign( + new Error(`ELOOP: too many symbolic links encountered, open '${dest}'`), + { code: "ELOOP", path: dest } + ); +} + +async function hasContent(filename: string, content: string) { + try { + const existing = await promises.readFile(filename); + return existing.equals(Buffer.from(content)); + } catch { + return false; + } +} + +// Compare size and mode before reading anything: a differing size rules out +// identical content, and copyFile applies the source mode, so a chmod-only +// change still has to be copied. +async function isSameFile(src: string, dest: string) { + try { + const [srcStats, destStats] = await Promise.all([ + promises.stat(src), + promises.stat(dest), + ]); + if ( + srcStats.size !== destStats.size || + srcStats.mode !== destStats.mode + ) { + return false; + } + + return await hasSameBytes(src, dest); + } catch { + return false; + } +} + +// Read in chunks rather than with readFile: a copied asset can be larger than +// the 2 GiB a single buffer holds. +async function hasSameBytes(src: string, dest: string) { + const chunkSize = 64 * 1024; + const srcFile = await promises.open(src, "r"); + let destFile; + try { + destFile = await promises.open(dest, "r"); + } catch (err: any) { + await srcFile.close(); + throw err; + } + + try { + const srcChunk = Buffer.allocUnsafe(chunkSize); + const destChunk = Buffer.allocUnsafe(chunkSize); + + for (;;) { + const [srcRead, destRead] = await Promise.all([ + srcFile.read(srcChunk, 0, chunkSize), + destFile.read(destChunk, 0, chunkSize), + ]); + if (srcRead.bytesRead !== destRead.bytesRead) { + return false; + } + if (srcRead.bytesRead === 0) { + return true; + } + const read = srcRead.bytesRead; + if ( + !srcChunk.subarray(0, read).equals(destChunk.subarray(0, read)) + ) { + return false; + } + } + } finally { + await Promise.all([srcFile.close(), destFile.close()]); + } } export function assertCompilationResult( diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 85be910..391cab7 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -31,7 +31,7 @@ importers: version: 13.2.3(enquirer@2.4.1) prettier: specifier: ^2 - version: 2.0.0 + version: 2.8.8 packages/cli: dependencies: @@ -46,56 +46,62 @@ importers: version: 8.3.0 minimatch: specifier: ^9.0.3 - version: 9.0.3 + version: 9.0.5 piscina: specifier: ^4.3.1 - version: 4.3.1 + version: 4.9.2 semver: specifier: ^7.3.8 - version: 7.3.8 + version: 7.7.2 slash: specifier: 3.0.0 version: 3.0.0 source-map: specifier: ^0.7.3 - version: 0.7.3 + version: 0.7.4 tinyglobby: specifier: ^0.2.13 version: 0.2.13 + write-file-atomic: + specifier: ^7.0.1 + version: 7.0.1 devDependencies: '@swc/cli': specifier: 0.8.0 - version: 0.8.0(@swc/core@1.6.4)(chokidar@5.0.0) + version: 0.8.0(@swc/core@1.11.24)(chokidar@5.0.0) '@swc/core': specifier: ^1.6.4 - version: 1.6.4 + version: 1.11.24 '@swc/jest': specifier: workspace:^ version: link:../jest '@swc/types': specifier: ^0.1.9 - version: 0.1.9 + version: 0.1.21 '@types/jest': specifier: ^29.5.0 version: 29.5.0 '@types/node': specifier: ^20.11.5 - version: 20.11.16 + version: 20.17.32 '@types/semver': specifier: ^7.3.13 - version: 7.3.13 + version: 7.7.0 + '@types/write-file-atomic': + specifier: ^4.0.3 + version: 4.0.3 chokidar: specifier: ^5.0.0 version: 5.0.0 deepmerge: specifier: ^4.2.2 - version: 4.2.2 + version: 4.3.1 jest: specifier: ^29.5.0 - version: 29.5.0(@types/node@20.11.16) + version: 29.5.0(@types/node@20.17.32) ts-jest: specifier: ^29.0.5 - version: 29.0.5(@babel/core@7.27.1)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.27.1))(jest@29.5.0(@types/node@20.11.16))(typescript@5.8.3) + version: 29.0.5(@babel/core@7.27.1)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.27.1))(jest@29.5.0(@types/node@20.17.32))(typescript@5.8.3) typescript: specifier: ~5.8.3 version: 5.8.3 @@ -140,7 +146,7 @@ importers: version: 30.0.4 '@swc/core': specifier: ^1.6.4 - version: 1.6.4 + version: 1.11.24 '@types/node': specifier: ^16.11.12 version: 16.11.12 @@ -164,13 +170,13 @@ importers: devDependencies: '@swc/core': specifier: ^1.6.4 - version: 1.6.4 + version: 1.11.24 packages/swc-info: devDependencies: '@types/node': specifier: ^20.11.16 - version: 20.11.16 + version: 20.17.32 typescript: specifier: ^5.8.3 version: 5.8.3 @@ -183,10 +189,10 @@ importers: devDependencies: '@swc/core': specifier: ^1.6.4 - version: 1.6.4 + version: 1.11.24 webpack: specifier: ^5.69.1 - version: 5.69.1(@swc/core@1.6.4) + version: 5.69.1(@swc/core@1.11.24) packages: @@ -855,6 +861,7 @@ packages: '@lerna/create@8.0.2': resolution: {integrity: sha512-AueSlfiYXqEmy9/EIc17mjlaHFuv734dfgVBegyoefIA7hdeoExtsXnACWf8Tw5af6gwyTL3KAp6QQyc1sTuZQ==} engines: {node: '>=18.0.0'} + deprecated: This package is an implementation detail of Lerna and is no longer published separately. '@manypkg/find-root@1.1.0': resolution: {integrity: sha512-mki5uBvhHzO8kYYix/WRy2WX8S3B5wdVSc9D6KcU5lQNglP2yt58/VfLuAK49glRXChosY8ap2oJ1qgma3GUVA==} @@ -1248,120 +1255,60 @@ packages: cpu: [arm64] os: [darwin] - '@swc/core-darwin-arm64@1.6.4': - resolution: {integrity: sha512-3gyal/qjiGN3ek4kIFCk/XdF/WP1ZkFmU6ork4qz+x/1HEhmU9c8z/MdbaBdLx2wxOOD7ZARj+T2TI92QEcXqQ==} - engines: {node: '>=10'} - cpu: [arm64] - os: [darwin] - '@swc/core-darwin-x64@1.11.24': resolution: {integrity: sha512-H/3cPs8uxcj2Fe3SoLlofN5JG6Ny5bl8DuZ6Yc2wr7gQFBmyBkbZEz+sPVgsID7IXuz7vTP95kMm1VL74SO5AQ==} engines: {node: '>=10'} cpu: [x64] os: [darwin] - '@swc/core-darwin-x64@1.6.4': - resolution: {integrity: sha512-7MRkx09zGmgpknjTEeH7gk7od2WFtaHnwdiw9BCu809/1Py44yC8FEPSU7iquJTGZZcfvhe+aPlKceMO506gBA==} - engines: {node: '>=10'} - cpu: [x64] - os: [darwin] - '@swc/core-linux-arm-gnueabihf@1.11.24': resolution: {integrity: sha512-PHJgWEpCsLo/NGj+A2lXZ2mgGjsr96ULNW3+T3Bj2KTc8XtMUkE8tmY2Da20ItZOvPNC/69KroU7edyo1Flfbw==} engines: {node: '>=10'} cpu: [arm] os: [linux] - '@swc/core-linux-arm-gnueabihf@1.6.4': - resolution: {integrity: sha512-SC0+zirvX/GMDTNL0J4XrItU66J3f61Pu/GjiiLy1KpIIDzisog27VJkS4noSnwr+6dytTQTHvUIuivlLI4Bgg==} - engines: {node: '>=10'} - cpu: [arm] - os: [linux] - '@swc/core-linux-arm64-gnu@1.11.24': resolution: {integrity: sha512-C2FJb08+n5SD4CYWCTZx1uR88BN41ZieoHvI8A55hfVf2woT8+6ZiBzt74qW2g+ntZ535Jts5VwXAKdu41HpBg==} engines: {node: '>=10'} cpu: [arm64] os: [linux] - '@swc/core-linux-arm64-gnu@1.6.4': - resolution: {integrity: sha512-Z1wlQU9Ncie55rnrq97OOdH7Y540JGFclzfEbqIE0bN68sOxxE1M+sPAet/9LNtwA822BVM+CB1Z53C/osAFtg==} - engines: {node: '>=10'} - cpu: [arm64] - os: [linux] - '@swc/core-linux-arm64-musl@1.11.24': resolution: {integrity: sha512-ypXLIdszRo0re7PNNaXN0+2lD454G8l9LPK/rbfRXnhLWDBPURxzKlLlU/YGd2zP98wPcVooMmegRSNOKfvErw==} engines: {node: '>=10'} cpu: [arm64] os: [linux] - '@swc/core-linux-arm64-musl@1.6.4': - resolution: {integrity: sha512-xrZFXX4aQk/ENz2szl11pPgPH3QVj3CnuGXKj8exZwGwuz0g5JbUxJgW7lShm6l2hp67fy90yQcP4DCipI3ykw==} - engines: {node: '>=10'} - cpu: [arm64] - os: [linux] - '@swc/core-linux-x64-gnu@1.11.24': resolution: {integrity: sha512-IM7d+STVZD48zxcgo69L0yYptfhaaE9cMZ+9OoMxirNafhKKXwoZuufol1+alEFKc+Wbwp+aUPe/DeWC/Lh3dg==} engines: {node: '>=10'} cpu: [x64] os: [linux] - '@swc/core-linux-x64-gnu@1.6.4': - resolution: {integrity: sha512-5hVhC65J9kM3CH5uk90LuRokG7xutO+5t92yNAY4c1raHkh7ZLgDTHeYNTwqdkApGlf7Dj0/2X7vLOy/9qVXLg==} - engines: {node: '>=10'} - cpu: [x64] - os: [linux] - '@swc/core-linux-x64-musl@1.11.24': resolution: {integrity: sha512-DZByJaMVzSfjQKKQn3cqSeqwy6lpMaQDQQ4HPlch9FWtDx/dLcpdIhxssqZXcR2rhaQVIaRQsCqwV6orSDGAGw==} engines: {node: '>=10'} cpu: [x64] os: [linux] - '@swc/core-linux-x64-musl@1.6.4': - resolution: {integrity: sha512-FPdeyL+4GnEqZ0MSkJuT6E+1PAr0JEAxfOuyHgD96yZDFPVEvs9IvLtF9+mfpCePl+LZATN/xridY97uxc167g==} - engines: {node: '>=10'} - cpu: [x64] - os: [linux] - '@swc/core-win32-arm64-msvc@1.11.24': resolution: {integrity: sha512-Q64Ytn23y9aVDKN5iryFi8mRgyHw3/kyjTjT4qFCa8AEb5sGUuSj//AUZ6c0J7hQKMHlg9do5Etvoe61V98/JQ==} engines: {node: '>=10'} cpu: [arm64] os: [win32] - '@swc/core-win32-arm64-msvc@1.6.4': - resolution: {integrity: sha512-HlPKfrkqS0j6V58/fOwbZOOiW0q+SjviB2FROdply/twwuTRkGxG460nU0bRdtA/S8FH7X+HN7dLTr9ANdPMRw==} - engines: {node: '>=10'} - cpu: [arm64] - os: [win32] - '@swc/core-win32-ia32-msvc@1.11.24': resolution: {integrity: sha512-9pKLIisE/Hh2vJhGIPvSoTK4uBSPxNVyXHmOrtdDot4E1FUUI74Vi8tFdlwNbaj8/vusVnb8xPXsxF1uB0VgiQ==} engines: {node: '>=10'} cpu: [ia32] os: [win32] - '@swc/core-win32-ia32-msvc@1.6.4': - resolution: {integrity: sha512-42zn2s15H6mkbcuWATqSl9qC6Iuj7mY0KhkkeuQFcpF8IQFHZJ58Fi83C8ANG0cvlZGyISIwJD4ElIyp3PGZkQ==} - engines: {node: '>=10'} - cpu: [ia32] - os: [win32] - '@swc/core-win32-x64-msvc@1.11.24': resolution: {integrity: sha512-sybnXtOsdB+XvzVFlBVGgRHLqp3yRpHK7CrmpuDKszhj/QhmsaZzY/GHSeALlMtLup13M0gqbcQvsTNlAHTg3w==} engines: {node: '>=10'} cpu: [x64] os: [win32] - '@swc/core-win32-x64-msvc@1.6.4': - resolution: {integrity: sha512-gZlvqabopveGR5WnuiGLKFsBrBGbSTYb87FpO3emL+skcAYyFWOWxq3PhxAsDC+XrtEbhaqAKyVo2gwfznQ+LQ==} - engines: {node: '>=10'} - cpu: [x64] - os: [win32] - '@swc/core@1.11.24': resolution: {integrity: sha512-MaQEIpfcEMzx3VWWopbofKJvaraqmL6HbLlw2bFZ7qYqYw3rkhM0cQVEgyzbHtTWwCwPMFZSC2DUbhlZgrMfLg==} engines: {node: '>=10'} @@ -1371,24 +1318,12 @@ packages: '@swc/helpers': optional: true - '@swc/core@1.6.4': - resolution: {integrity: sha512-DgoGwes0tq5m0xrygccCMs1fQ7OBPDvB2gf7c0v2FlzRC8tSsNs24zIFhLxwLzzf2IRr0M3b5Ex1JXENe+Fs3w==} - engines: {node: '>=10'} - peerDependencies: - '@swc/helpers': '*' - peerDependenciesMeta: - '@swc/helpers': - optional: true - '@swc/counter@0.1.3': resolution: {integrity: sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ==} '@swc/types@0.1.21': resolution: {integrity: sha512-2YEtj5HJVbKivud9N4bpPBAyZhj4S2Ipe5LkUG94alTpr7in/GU/EARgPAd3BwU+YOmFVJC2+kjqhGRi3r0ZpQ==} - '@swc/types@0.1.9': - resolution: {integrity: sha512-qKnCno++jzcJ4lM4NTfYifm1EFSCeIfKiAHAfkENZAV5Kl9PjJIyd2yeeVv6c/2CckuLyv2NmRC5pv6pm2WQBg==} - '@szmarczak/http-timer@5.0.1': resolution: {integrity: sha512-+PmQX0PiAYPMeVYe237LJAYvOMYW1j2rH5YROyS3b4CTVJum34HfRvKvAzozHAQG0TnHNdUfY9nCeUyRAs//cw==} engines: {node: '>=14.16'} @@ -1481,24 +1416,21 @@ packages: '@types/node@16.11.12': resolution: {integrity: sha512-+2Iggwg7PxoO5Kyhvsq9VarmPbIelXP070HMImEpbtGCoyWNINQj4wzjbQCXzdHTRXnqufutJb5KAURZANNBAw==} - '@types/node@20.11.16': - resolution: {integrity: sha512-gKb0enTmRCzXSSUJDq6/sPcqrfCv2mkkG6Jt/clpn5eiCbKTY+SgZUxo+p8ZKMof5dCp9vHQUAB7wOUTod22wQ==} - '@types/node@20.17.32': resolution: {integrity: sha512-zeMXFn8zQ+UkjK4ws0RiOC9EWByyW1CcVmLe+2rQocXRsGEDxUCwPEIVgpsGcLHS/P8JkT0oa3839BRABS0oPw==} '@types/normalize-package-data@2.4.4': resolution: {integrity: sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA==} - '@types/semver@7.3.13': - resolution: {integrity: sha512-21cFJr9z3g5dW8B0CVI9g2O9beqaThGQ6ZFBqHfwhzLDKUxaqTIy3vnfah/UPkfOiF2pLq+tGz+W8RyCskuslw==} - '@types/semver@7.7.0': resolution: {integrity: sha512-k107IF4+Xr7UHjwDc7Cfd6PRQfbdkiRabXGRjo07b4WyPahFBZCZ1sE+BNxYIJPPg73UkfOsVOLwqVc/6ETrIA==} '@types/stack-utils@2.0.3': resolution: {integrity: sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw==} + '@types/write-file-atomic@4.0.3': + resolution: {integrity: sha512-qdo+vZRchyJIHNeuI1nrpsLw+hnkgqP/8mlaN6Wle/NKhydHmUN9l4p3ZE8yP90AJNJW4uB8HQhedb4f1vNayQ==} + '@types/yargs-parser@21.0.3': resolution: {integrity: sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==} @@ -1555,6 +1487,7 @@ packages: '@ungap/structured-clone@1.3.0': resolution: {integrity: sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g==} + deprecated: Potential CWE-502 - Update to 1.3.1 or higher '@unrs/resolver-binding-android-arm-eabi@1.11.0': resolution: {integrity: sha512-LRw5BW29sYj9NsQC6QoqeLVQhEa+BwVINYyMlcve+6stwdBsSt5UB7zw4UZB4+4PNqIVilHoMaPWCb/KhABHQw==} @@ -2339,6 +2272,7 @@ packages: conventional-changelog-core@5.0.1: resolution: {integrity: sha512-Rvi5pH+LvgsqGwZPZ3Cq/tz4ty7mjijhr3qR4m9IBXNbxGGYgTVVO+duXzz9aArmHxFtwZ+LRkrNIMDQzgoY4A==} engines: {node: '>=14'} + deprecated: Deprecated and no longer maintained. Please use conventional-changelog instead. conventional-changelog-preset-loader@3.0.0: resolution: {integrity: sha512-qy9XbdSLmVnwnvzEisjxdDiLA4OmV3o8db+Zdg4WiFw14fP3B6XNz98X0swPPpkTd/pc1K7+adKgEDM1JCUMiA==} @@ -2522,10 +2456,6 @@ packages: deep-is@0.1.4: resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==} - deepmerge@4.2.2: - resolution: {integrity: sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg==} - engines: {node: '>=0.10.0'} - deepmerge@4.3.1: resolution: {integrity: sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==} engines: {node: '>=0.10.0'} @@ -3084,6 +3014,7 @@ packages: git-raw-commits@3.0.0: resolution: {integrity: sha512-b5OHmZ3vAgGrDn/X0kS+9qCfNKWe4K/jFnhwzVWWg0/k5eLa3060tZShrRg8Dja5kPc+YjS0Gc6y7cRr44Lpjw==} engines: {node: '>=14'} + deprecated: Deprecated and no longer maintained. Use @conventional-changelog/git-client instead. hasBin: true git-remote-origin-url@2.0.0: @@ -3093,6 +3024,7 @@ packages: git-semver-tags@5.0.1: resolution: {integrity: sha512-hIvOeZwRbQ+7YEUmCkHqo8FOLQZCEn18yevLHADlFPZY02KJGsu5FZt9YW/lybfK2uhWFI7Qg/07LekJiTv7iA==} engines: {node: '>=14'} + deprecated: Deprecated and no longer maintained. Use @conventional-changelog/git-client instead. hasBin: true git-up@7.0.0: @@ -3117,20 +3049,22 @@ packages: glob@10.4.5: resolution: {integrity: sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==} + deprecated: Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me hasBin: true glob@7.2.3: resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==} - deprecated: Glob versions prior to v9 are no longer supported + deprecated: Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me glob@8.1.0: resolution: {integrity: sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==} engines: {node: '>=12'} - deprecated: Glob versions prior to v9 are no longer supported + deprecated: Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me glob@9.3.5: resolution: {integrity: sha512-e1LleDykUz2Iu+MTYdkSsuWX8lvAjAcs0Xef0lNIu0S2wOAzuTxCJtcd9S3cijlwYF18EsU3rzb8jPVobxDh9Q==} engines: {node: '>=16 || 14 >=14.17'} + deprecated: Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me global-dirs@0.1.1: resolution: {integrity: sha512-NknMLn7F2J7aflwFOlGdNIuCDpN3VGoSoB+aap3KABFWbHVn1TCgFC+np23J8W2BiZbjfEw3BFBycSMv1AFblg==} @@ -4291,13 +4225,6 @@ packages: neo-async@2.6.2: resolution: {integrity: sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==} - nice-napi@1.0.2: - resolution: {integrity: sha512-px/KnJAJZf5RuBGcfD+Sp2pAKq0ytz8j+1NehvgIGFkvtvFrDM3T8E4x/JJODXK9WZow8RRGrbA9QQ3hs+pDhA==} - os: ['!win32'] - - node-addon-api@3.2.1: - resolution: {integrity: sha512-mmcei9JghVNDYydghQmeDX8KoAm0FAiYyIcUt/N4nhyAipB17pllZQDOJD2fotxABnt4Mdz+dKTO7eftLg4d0A==} - node-fetch@2.6.7: resolution: {integrity: sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==} engines: {node: 4.x || >=6.0.0} @@ -4316,10 +4243,6 @@ packages: encoding: optional: true - node-gyp-build@4.8.4: - resolution: {integrity: sha512-LA4ZjwlnUblHVgq0oBF3Jl/6h/Nvs5fzBLwdEF4nuxnFdsfajde4WfxtJr3CaiH+F6ewcIB/q4jQ4UzPyid+CQ==} - hasBin: true - node-gyp@10.3.1: resolution: {integrity: sha512-Pp3nFHBThHzVtNY7U6JfPjvT/DTE8+o/4xKsLQtBoU+j2HLsGlhcfzflAoUreaJbNmYnX+LlLi0qjV8kpyO6xQ==} engines: {node: ^16.14.0 || >=18.0.0} @@ -4695,9 +4618,6 @@ packages: resolution: {integrity: sha512-TfySrs/5nm8fQJDcBDuUng3VOUKsd7S+zqvbOTiGXHfxX4wK31ard+hoNuvkicM/2YFzlpDgABOevKSsB4G/FA==} engines: {node: '>= 6'} - piscina@4.3.1: - resolution: {integrity: sha512-MBj0QYm3hJQ/C/wIXTN1OCYC8uQ4BBJ4LVele2P4ZwVQAH04vkk8E1SpDbuemLAL1dZorbuOob9rYqJeWCcCRg==} - piscina@4.9.2: resolution: {integrity: sha512-Fq0FERJWFEUpB4eSY59wSNwXD4RYqR+nR/WiEVcZW8IWfVBxJJafcgTEZDQo8k3w0sUarJ8RyVbbUF4GQ2LGbQ==} @@ -4717,11 +4637,6 @@ packages: resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==} engines: {node: '>= 0.8.0'} - prettier@2.0.0: - resolution: {integrity: sha512-vI55PC+GFLOVtpwr2di1mYhJF36v+kztJov8sx3AmqbfdA+2Dhozxb+3e1hTgoV9lyhnVJFF3Z8GCVeMBOS1bA==} - engines: {node: '>=10.13.0'} - hasBin: true - prettier@2.8.8: resolution: {integrity: sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==} engines: {node: '>=10.13.0'} @@ -5022,11 +4937,6 @@ packages: resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==} hasBin: true - semver@7.3.8: - resolution: {integrity: sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==} - engines: {node: '>=10'} - hasBin: true - semver@7.7.1: resolution: {integrity: sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==} engines: {node: '>=10'} @@ -5169,10 +5079,6 @@ packages: resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==} engines: {node: '>=0.10.0'} - source-map@0.7.3: - resolution: {integrity: sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==} - engines: {node: '>= 8'} - source-map@0.7.4: resolution: {integrity: sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==} engines: {node: '>= 8'} @@ -5349,10 +5255,12 @@ packages: tar@6.1.11: resolution: {integrity: sha512-an/KZQzQUkZCkuoAA64hM92X0Urb6VpRhAFllDzz44U2mcD5scmT3zBc4VgVpkugF580+DQn8eAFSyoQt0tznA==} engines: {node: '>= 10'} + deprecated: Old versions of tar are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me tar@6.2.1: resolution: {integrity: sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==} engines: {node: '>=10'} + deprecated: Old versions of tar are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me temp-dir@1.0.0: resolution: {integrity: sha512-xZFXEGbG7SNC3itwBzI3RYjq/cEhBkx2hJuKGIUOcEULmkQExXiHat2z/qkISYsuR+IKumhEfKKbV5qXmhICFQ==} @@ -5570,9 +5478,6 @@ packages: unbzip2-stream@1.4.3: resolution: {integrity: sha512-mlExGW4w71ebDJviH16lQLtZS32VKqsSfk80GCfUlwT/4/hNRFsoscrF/c++9xinkMzECL1uL9DDwXqFWkruPg==} - undici-types@5.26.5: - resolution: {integrity: sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==} - undici-types@6.19.8: resolution: {integrity: sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==} @@ -5627,6 +5532,7 @@ packages: uuid@9.0.1: resolution: {integrity: sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==} + deprecated: uuid@10 and below is no longer supported. For ESM codebases, update to uuid@latest. For CommonJS codebases, use uuid@11 (but be aware this version will likely be deprecated in 2028). hasBin: true v8-compile-cache@2.4.0: @@ -5761,6 +5667,10 @@ packages: resolution: {integrity: sha512-+QU2zd6OTD8XWIJCbffaiQeH9U73qIqafo1x6V1snCWYGJf6cVE0cDR4D8xRzcEnfI21IFrUPzPGtcPf8AC+Rw==} engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + write-file-atomic@7.0.1: + resolution: {integrity: sha512-OTIk8iR8/aCRWBqvxrzxR0hgxWpnYBblY1S5hDWBQfk/VFmJwzmJgQFN3WsoUKHISv2eAwe+PpbUzyL1CKTLXg==} + engines: {node: ^20.17.0 || >=22.9.0} + write-json-file@3.2.0: resolution: {integrity: sha512-3xZqT7Byc2uORAatYiP3DHUUAVEkNOswEWNs9H5KXiicRTvzYzYqKjYc4G7p+8pltvAw641lVByKVtMpf+4sYQ==} engines: {node: '>=6'} @@ -6569,7 +6479,7 @@ snapshots: '@jest/console@29.7.0': dependencies: '@jest/types': 29.6.3 - '@types/node': 20.11.16 + '@types/node': 20.17.32 chalk: 4.1.2 jest-message-util: 29.7.0 jest-util: 29.7.0 @@ -6591,14 +6501,14 @@ snapshots: '@jest/test-result': 29.7.0 '@jest/transform': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 20.11.16 + '@types/node': 20.17.32 ansi-escapes: 4.3.2 chalk: 4.1.2 ci-info: 3.9.0 exit: 0.1.2 graceful-fs: 4.2.11 jest-changed-files: 29.7.0 - jest-config: 29.7.0(@types/node@20.11.16) + jest-config: 29.7.0(@types/node@20.17.32) jest-haste-map: 29.7.0 jest-message-util: 29.7.0 jest-regex-util: 29.6.3 @@ -6748,7 +6658,7 @@ snapshots: '@jest/transform': 29.7.0 '@jest/types': 29.6.3 '@jridgewell/trace-mapping': 0.3.25 - '@types/node': 20.11.16 + '@types/node': 20.17.32 chalk: 4.1.2 collect-v8-coverage: 1.0.2 exit: 0.1.2 @@ -6897,7 +6807,7 @@ snapshots: '@jest/schemas': 29.6.3 '@types/istanbul-lib-coverage': 2.0.6 '@types/istanbul-reports': 3.0.4 - '@types/node': 20.11.16 + '@types/node': 20.17.32 '@types/yargs': 17.0.33 chalk: 4.1.2 @@ -7396,9 +7306,9 @@ snapshots: dependencies: '@sinonjs/commons': 3.0.1 - '@swc/cli@0.8.0(@swc/core@1.6.4)(chokidar@5.0.0)': + '@swc/cli@0.8.0(@swc/core@1.11.24)(chokidar@5.0.0)': dependencies: - '@swc/core': 1.6.4 + '@swc/core': 1.11.24 '@swc/counter': 0.1.3 '@xhmikosr/bin-wrapper': 13.0.5 commander: 8.3.0 @@ -7419,10 +7329,11 @@ snapshots: commander: 8.3.0 minimatch: 9.0.5 piscina: 4.9.2 - semver: 7.7.1 + semver: 7.7.2 slash: 3.0.0 source-map: 0.7.4 tinyglobby: 0.2.13 + write-file-atomic: 7.0.1 optionalDependencies: chokidar: 5.0.0 transitivePeerDependencies: @@ -7431,63 +7342,33 @@ snapshots: '@swc/core-darwin-arm64@1.11.24': optional: true - '@swc/core-darwin-arm64@1.6.4': - optional: true - '@swc/core-darwin-x64@1.11.24': optional: true - '@swc/core-darwin-x64@1.6.4': - optional: true - '@swc/core-linux-arm-gnueabihf@1.11.24': optional: true - '@swc/core-linux-arm-gnueabihf@1.6.4': - optional: true - '@swc/core-linux-arm64-gnu@1.11.24': optional: true - '@swc/core-linux-arm64-gnu@1.6.4': - optional: true - '@swc/core-linux-arm64-musl@1.11.24': optional: true - '@swc/core-linux-arm64-musl@1.6.4': - optional: true - '@swc/core-linux-x64-gnu@1.11.24': optional: true - '@swc/core-linux-x64-gnu@1.6.4': - optional: true - '@swc/core-linux-x64-musl@1.11.24': optional: true - '@swc/core-linux-x64-musl@1.6.4': - optional: true - '@swc/core-win32-arm64-msvc@1.11.24': optional: true - '@swc/core-win32-arm64-msvc@1.6.4': - optional: true - '@swc/core-win32-ia32-msvc@1.11.24': optional: true - '@swc/core-win32-ia32-msvc@1.6.4': - optional: true - '@swc/core-win32-x64-msvc@1.11.24': optional: true - '@swc/core-win32-x64-msvc@1.6.4': - optional: true - '@swc/core@1.11.24': dependencies: '@swc/counter': 0.1.3 @@ -7504,32 +7385,12 @@ snapshots: '@swc/core-win32-ia32-msvc': 1.11.24 '@swc/core-win32-x64-msvc': 1.11.24 - '@swc/core@1.6.4': - dependencies: - '@swc/counter': 0.1.3 - '@swc/types': 0.1.9 - optionalDependencies: - '@swc/core-darwin-arm64': 1.6.4 - '@swc/core-darwin-x64': 1.6.4 - '@swc/core-linux-arm-gnueabihf': 1.6.4 - '@swc/core-linux-arm64-gnu': 1.6.4 - '@swc/core-linux-arm64-musl': 1.6.4 - '@swc/core-linux-x64-gnu': 1.6.4 - '@swc/core-linux-x64-musl': 1.6.4 - '@swc/core-win32-arm64-msvc': 1.6.4 - '@swc/core-win32-ia32-msvc': 1.6.4 - '@swc/core-win32-x64-msvc': 1.6.4 - '@swc/counter@0.1.3': {} '@swc/types@0.1.21': dependencies: '@swc/counter': 0.1.3 - '@swc/types@0.1.9': - dependencies: - '@swc/counter': 0.1.3 - '@szmarczak/http-timer@5.0.1': dependencies: defer-to-connect: 2.0.1 @@ -7630,22 +7491,20 @@ snapshots: '@types/node@16.11.12': {} - '@types/node@20.11.16': - dependencies: - undici-types: 5.26.5 - '@types/node@20.17.32': dependencies: undici-types: 6.19.8 '@types/normalize-package-data@2.4.4': {} - '@types/semver@7.3.13': {} - '@types/semver@7.7.0': {} '@types/stack-utils@2.0.3': {} + '@types/write-file-atomic@4.0.3': + dependencies: + '@types/node': 20.17.32 + '@types/yargs-parser@21.0.3': {} '@types/yargs@17.0.33': @@ -7662,7 +7521,7 @@ snapshots: functional-red-black-tree: 1.0.1 ignore: 5.3.2 regexpp: 3.2.0 - semver: 7.7.1 + semver: 7.7.2 tsutils: 3.21.0(typescript@5.8.3) optionalDependencies: typescript: 5.8.3 @@ -8711,13 +8570,13 @@ snapshots: optionalDependencies: typescript: 5.8.3 - create-jest@29.7.0(@types/node@20.11.16): + create-jest@29.7.0(@types/node@20.17.32): dependencies: '@jest/types': 29.6.3 chalk: 4.1.2 exit: 0.1.2 graceful-fs: 4.2.11 - jest-config: 29.7.0(@types/node@20.11.16) + jest-config: 29.7.0(@types/node@20.17.32) jest-util: 29.7.0 prompts: 2.4.2 transitivePeerDependencies: @@ -8890,8 +8749,6 @@ snapshots: deep-is@0.1.4: {} - deepmerge@4.2.2: {} - deepmerge@4.3.1: {} defaults@1.0.4: @@ -9146,7 +9003,7 @@ snapshots: optionator: 0.9.4 progress: 2.0.3 regexpp: 3.2.0 - semver: 7.7.1 + semver: 7.7.2 strip-ansi: 6.0.1 strip-json-comments: 3.1.1 text-table: 0.2.0 @@ -10187,16 +10044,16 @@ snapshots: - babel-plugin-macros - supports-color - jest-cli@29.7.0(@types/node@20.11.16): + jest-cli@29.7.0(@types/node@20.17.32): dependencies: '@jest/core': 29.7.0 '@jest/test-result': 29.7.0 '@jest/types': 29.6.3 chalk: 4.1.2 - create-jest: 29.7.0(@types/node@20.11.16) + create-jest: 29.7.0(@types/node@20.17.32) exit: 0.1.2 import-local: 3.2.0 - jest-config: 29.7.0(@types/node@20.11.16) + jest-config: 29.7.0(@types/node@20.17.32) jest-util: 29.7.0 jest-validate: 29.7.0 yargs: 17.7.2 @@ -10225,7 +10082,7 @@ snapshots: - supports-color - ts-node - jest-config@29.7.0(@types/node@20.11.16): + jest-config@29.7.0(@types/node@20.17.32): dependencies: '@babel/core': 7.27.1 '@jest/test-sequencer': 29.7.0 @@ -10233,7 +10090,7 @@ snapshots: babel-jest: 29.7.0(@babel/core@7.27.1) chalk: 4.1.2 ci-info: 3.9.0 - deepmerge: 4.2.2 + deepmerge: 4.3.1 glob: 7.2.3 graceful-fs: 4.2.11 jest-circus: 29.7.0 @@ -10250,7 +10107,7 @@ snapshots: slash: 3.0.0 strip-json-comments: 3.1.1 optionalDependencies: - '@types/node': 20.11.16 + '@types/node': 20.17.32 transitivePeerDependencies: - babel-plugin-macros - supports-color @@ -10382,7 +10239,7 @@ snapshots: dependencies: '@jest/types': 29.6.3 '@types/graceful-fs': 4.1.9 - '@types/node': 20.11.16 + '@types/node': 20.17.32 anymatch: 3.1.3 fb-watchman: 2.0.2 graceful-fs: 4.2.11 @@ -10525,7 +10382,7 @@ snapshots: '@jest/test-result': 29.7.0 '@jest/transform': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 20.11.16 + '@types/node': 20.17.32 chalk: 4.1.2 emittery: 0.13.1 graceful-fs: 4.2.11 @@ -10580,7 +10437,7 @@ snapshots: '@jest/test-result': 29.7.0 '@jest/transform': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 20.11.16 + '@types/node': 20.17.32 chalk: 4.1.2 cjs-module-lexer: 1.4.3 collect-v8-coverage: 1.0.2 @@ -10679,7 +10536,7 @@ snapshots: jest-util@29.7.0: dependencies: '@jest/types': 29.6.3 - '@types/node': 20.11.16 + '@types/node': 20.17.32 chalk: 4.1.2 ci-info: 3.9.0 graceful-fs: 4.2.11 @@ -10716,7 +10573,7 @@ snapshots: dependencies: '@jest/test-result': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 20.11.16 + '@types/node': 20.17.32 ansi-escapes: 4.3.2 chalk: 4.1.2 emittery: 0.13.1 @@ -10755,12 +10612,12 @@ snapshots: merge-stream: 2.0.0 supports-color: 8.1.1 - jest@29.5.0(@types/node@20.11.16): + jest@29.5.0(@types/node@20.17.32): dependencies: '@jest/core': 29.7.0 '@jest/types': 29.6.3 import-local: 3.2.0 - jest-cli: 29.7.0(@types/node@20.11.16) + jest-cli: 29.7.0(@types/node@20.17.32) transitivePeerDependencies: - '@types/node' - babel-plugin-macros @@ -11298,15 +11155,6 @@ snapshots: neo-async@2.6.2: {} - nice-napi@1.0.2: - dependencies: - node-addon-api: 3.2.1 - node-gyp-build: 4.8.4 - optional: true - - node-addon-api@3.2.1: - optional: true - node-fetch@2.6.7(encoding@0.1.13): dependencies: whatwg-url: 5.0.0 @@ -11319,9 +11167,6 @@ snapshots: optionalDependencies: encoding: 0.1.13 - node-gyp-build@4.8.4: - optional: true - node-gyp@10.3.1: dependencies: env-paths: 2.2.1 @@ -11776,10 +11621,6 @@ snapshots: pirates@4.0.7: {} - piscina@4.3.1: - optionalDependencies: - nice-napi: 1.0.2 - piscina@4.9.2: optionalDependencies: '@napi-rs/nice': 1.0.1 @@ -11799,8 +11640,6 @@ snapshots: prelude-ls@1.2.1: {} - prettier@2.0.0: {} - prettier@2.8.8: {} pretty-format@29.7.0: @@ -12093,10 +11932,6 @@ snapshots: semver@6.3.1: {} - semver@7.3.8: - dependencies: - lru-cache: 6.0.0 - semver@7.7.1: {} semver@7.7.2: {} @@ -12275,8 +12110,6 @@ snapshots: source-map@0.6.1: {} - source-map@0.7.3: {} - source-map@0.7.4: {} spawndamnit@2.0.0: @@ -12494,16 +12327,16 @@ snapshots: term-size@2.2.1: {} - terser-webpack-plugin@5.3.14(@swc/core@1.6.4)(webpack@5.69.1(@swc/core@1.6.4)): + terser-webpack-plugin@5.3.14(@swc/core@1.11.24)(webpack@5.69.1(@swc/core@1.11.24)): dependencies: '@jridgewell/trace-mapping': 0.3.25 jest-worker: 27.5.1 schema-utils: 4.3.2 serialize-javascript: 6.0.2 terser: 5.39.0 - webpack: 5.69.1(@swc/core@1.6.4) + webpack: 5.69.1(@swc/core@1.11.24) optionalDependencies: - '@swc/core': 1.6.4 + '@swc/core': 1.11.24 terser@5.39.0: dependencies: @@ -12564,16 +12397,16 @@ snapshots: trim-newlines@3.0.1: {} - ts-jest@29.0.5(@babel/core@7.27.1)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.27.1))(jest@29.5.0(@types/node@20.11.16))(typescript@5.8.3): + ts-jest@29.0.5(@babel/core@7.27.1)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.27.1))(jest@29.5.0(@types/node@20.17.32))(typescript@5.8.3): dependencies: bs-logger: 0.2.6 fast-json-stable-stringify: 2.1.0 - jest: 29.5.0(@types/node@20.11.16) + jest: 29.5.0(@types/node@20.17.32) jest-util: 29.7.0 json5: 2.2.3 lodash.memoize: 4.1.2 make-error: 1.3.6 - semver: 7.3.8 + semver: 7.7.2 typescript: 5.8.3 yargs-parser: 21.1.1 optionalDependencies: @@ -12702,8 +12535,6 @@ snapshots: buffer: 5.7.1 through: 2.3.8 - undici-types@5.26.5: {} - undici-types@6.19.8: {} unicorn-magic@0.3.0: {} @@ -12814,7 +12645,7 @@ snapshots: webpack-sources@3.2.3: {} - webpack@5.69.1(@swc/core@1.6.4): + webpack@5.69.1(@swc/core@1.11.24): dependencies: '@types/eslint-scope': 3.7.7 '@types/estree': 0.0.51 @@ -12837,7 +12668,7 @@ snapshots: neo-async: 2.6.2 schema-utils: 3.3.0 tapable: 2.2.1 - terser-webpack-plugin: 5.3.14(@swc/core@1.6.4)(webpack@5.69.1(@swc/core@1.6.4)) + terser-webpack-plugin: 5.3.14(@swc/core@1.11.24)(webpack@5.69.1(@swc/core@1.11.24)) watchpack: 2.4.2 webpack-sources: 3.2.3 transitivePeerDependencies: @@ -12961,6 +12792,10 @@ snapshots: imurmurhash: 0.1.4 signal-exit: 4.1.0 + write-file-atomic@7.0.1: + dependencies: + signal-exit: 4.1.0 + write-json-file@3.2.0: dependencies: detect-indent: 5.0.0