diff --git a/.changeset/ninety-lights-occur.md b/.changeset/ninety-lights-occur.md new file mode 100644 index 0000000..dc4ad19 --- /dev/null +++ b/.changeset/ninety-lights-occur.md @@ -0,0 +1,5 @@ +--- +"@webiny/stdlib": patch +--- + +Add BrowserWindow abstraction to decouple browser features from the global `window` object, with real and null implementations. Replace silent `void` returns with `Result` pattern across `DirectoryTool.create`, `FileTool.writeFile`/`copy`, `JsonFileTool.writeJson`, and `PackageJsonFileTool.write`. Add `createOrThrow` to DirectoryTool. New typed errors: `DirectoryCreateError`, `FileWriteError`, `FileCopyError`. diff --git a/README.md b/README.md index a724a48..06a0e89 100644 --- a/README.md +++ b/README.md @@ -58,10 +58,11 @@ The package is ESM-only and ships three subpath exports. Because each is a separ ## `@webiny/stdlib/browser` — Browser -| Feature | Description | -| -------------------------- | ----------------------------------------------------------------------------------------------------------------- | -| `LocalStorageCacheFeature` | `Cache` implementation backed by `window.localStorage` — [docs](src/browser/features/LocalStorageCache/README.md) | -| `BrowserEnvFeature` | `Env` implementation backed by an injected variables object — [docs](src/browser/features/BrowserEnv/README.md) | +| Feature | Description | +| -------------------------- | -------------------------------------------------------------------------------------------------------------------------------------- | +| `BrowserWindowFeature` | Abstraction over the browser `window` object with real and null implementations — [docs](src/browser/features/BrowserWindow/README.md) | +| `LocalStorageCacheFeature` | `Cache` implementation backed by `window.localStorage` — [docs](src/browser/features/LocalStorageCache/README.md) | +| `BrowserEnvFeature` | `Env` implementation backed by an injected variables object — [docs](src/browser/features/BrowserEnv/README.md) | --- diff --git a/__tests__/browser/BrowserWindow.test.ts b/__tests__/browser/BrowserWindow.test.ts new file mode 100644 index 0000000..e6a96ea --- /dev/null +++ b/__tests__/browser/BrowserWindow.test.ts @@ -0,0 +1,58 @@ +// @vitest-environment happy-dom +import { Container } from "@webiny/di"; +import { describe, it, expect } from "vitest"; +import { BrowserWindow } from "../../src/browser/features/BrowserWindow/abstractions/BrowserWindow.js"; +import { + BrowserWindow as BrowserWindowImpl, + createBrowserWindow +} from "../../src/browser/features/BrowserWindow/BrowserWindow.js"; +import { + NullBrowserWindow, + createNullBrowserWindow +} from "../../src/browser/features/BrowserWindow/NullBrowserWindow.js"; +import { BrowserWindowFeature } from "../../src/browser/features/BrowserWindow/feature.js"; +import { NullBrowserWindowFeature } from "../../src/browser/features/BrowserWindow/nullFeature.js"; + +describe("BrowserWindow", () => { + describe("real implementation", () => { + it("exposes localStorage from the global window", () => { + const container = new Container(); + container.register(BrowserWindowImpl).inSingletonScope(); + const bw = container.resolve(BrowserWindow); + expect(bw.localStorage).toBe(window.localStorage); + }); + + it("resolves via BrowserWindowFeature", () => { + const container = new Container(); + BrowserWindowFeature.register(container); + const bw = container.resolve(BrowserWindow); + expect(bw.localStorage).toBe(window.localStorage); + }); + + it("creates via factory function", () => { + const bw = createBrowserWindow(); + expect(bw.localStorage).toBe(window.localStorage); + }); + }); + + describe("null implementation", () => { + it("returns null for localStorage", () => { + const container = new Container(); + container.register(NullBrowserWindow).inSingletonScope(); + const bw = container.resolve(BrowserWindow); + expect(bw.localStorage).toBeNull(); + }); + + it("resolves via NullBrowserWindowFeature", () => { + const container = new Container(); + NullBrowserWindowFeature.register(container); + const bw = container.resolve(BrowserWindow); + expect(bw.localStorage).toBeNull(); + }); + + it("creates via factory function", () => { + const bw = createNullBrowserWindow(); + expect(bw.localStorage).toBeNull(); + }); + }); +}); diff --git a/__tests__/browser/LocalStorageCache.test.ts b/__tests__/browser/LocalStorageCache.test.ts index a04558a..365194e 100644 --- a/__tests__/browser/LocalStorageCache.test.ts +++ b/__tests__/browser/LocalStorageCache.test.ts @@ -1,6 +1,7 @@ // @vitest-environment happy-dom import { Container } from "@webiny/di"; import { describe, it, expect, beforeEach, afterEach, vi } from "vitest"; +import { BrowserWindow as BrowserWindowImpl } from "../../src/browser/features/BrowserWindow/BrowserWindow.js"; import { LocalStorageCache } from "../../src/browser/features/LocalStorageCache/LocalStorageCache.js"; import { Cache } from "../../src/index.js"; import { @@ -11,6 +12,7 @@ import { function makeCache(): Cache.Interface { const container = new Container(); + container.register(BrowserWindowImpl).inSingletonScope(); container.register(LocalStorageCache).inSingletonScope(); return container.resolve(Cache); } diff --git a/__tests__/node/DirectoryTool.test.ts b/__tests__/node/DirectoryTool.test.ts index 3247f8f..7da2af6 100644 --- a/__tests__/node/DirectoryTool.test.ts +++ b/__tests__/node/DirectoryTool.test.ts @@ -1,10 +1,11 @@ import { afterEach, beforeEach, describe, expect, it } from "vitest"; -import { existsSync, mkdirSync, rmSync, writeFileSync } from "node:fs"; +import { existsSync, mkdirSync, rmSync, writeFileSync, chmodSync } from "node:fs"; import { join } from "node:path"; import { tmpdir } from "node:os"; import { Container } from "@webiny/di"; import { DirectoryTool, + DirectoryCreateError, DirectoryToolFeature, createDirectoryTool } from "../../src/node/features/DirectoryTool/index.js"; @@ -45,21 +46,58 @@ describe("DirectoryTool", () => { }); describe("create", () => { - it("creates a new directory", () => { + it("creates a new directory and returns ok", () => { const dir = join(tmpDir, "new-dir"); - tool.create(dir); + const result = tool.create(dir); + expect(result.isOk()).toBe(true); expect(existsSync(dir)).toBe(true); }); it("creates nested directories", () => { const dir = join(tmpDir, "a", "b", "c"); - tool.create(dir); + const result = tool.create(dir); + expect(result.isOk()).toBe(true); expect(existsSync(dir)).toBe(true); }); it("is idempotent on existing directories", () => { - tool.create(tmpDir); - expect(() => tool.create(tmpDir)).not.toThrow(); + const result = tool.create(tmpDir); + expect(result.isOk()).toBe(true); + }); + + it("returns a failure Result when creation is impossible", () => { + const blocked = join(tmpDir, "blocked"); + mkdirSync(blocked, { mode: 0o000 }); + try { + const result = tool.create(join(blocked, "child", "deep")); + expect(result.isFail()).toBe(true); + if (result.isFail()) { + expect(result.error).toBeInstanceOf(DirectoryCreateError); + expect(result.error.data.path).toBe(join(blocked, "child", "deep")); + } + } finally { + chmodSync(blocked, 0o755); + } + }); + }); + + describe("createOrThrow", () => { + it("creates a new directory without throwing", () => { + const dir = join(tmpDir, "new-dir-throw"); + tool.createOrThrow(dir); + expect(existsSync(dir)).toBe(true); + }); + + it("throws DirectoryCreateError when creation is impossible", () => { + const blocked = join(tmpDir, "blocked"); + mkdirSync(blocked, { mode: 0o000 }); + try { + expect(() => tool.createOrThrow(join(blocked, "child", "deep"))).toThrow( + DirectoryCreateError + ); + } finally { + chmodSync(blocked, 0o755); + } }); }); @@ -115,12 +153,40 @@ describe("DirectoryTool", () => { it("does not throw when source is missing", () => { expect(() => tool.copy(join(tmpDir, "missing"), join(tmpDir, "dest"))).not.toThrow(); }); + + it("does not throw when target directory cannot be created", () => { + const src = join(tmpDir, "src"); + mkdirSync(src, { recursive: true }); + writeFileSync(join(src, "file.txt"), "content"); + const blocked = join(tmpDir, "blocked"); + mkdirSync(blocked, { mode: 0o000 }); + try { + expect(() => tool.copy(src, join(blocked, "child", "dest"))).not.toThrow(); + } finally { + chmodSync(blocked, 0o755); + } + }); }); describe("copyOrThrow", () => { it("throws when source is missing", () => { expect(() => tool.copyOrThrow(join(tmpDir, "missing"), join(tmpDir, "dest"))).toThrow(); }); + + it("throws when target directory cannot be created", () => { + const src = join(tmpDir, "src"); + mkdirSync(src, { recursive: true }); + writeFileSync(join(src, "file.txt"), "content"); + const blocked = join(tmpDir, "blocked"); + mkdirSync(blocked, { mode: 0o000 }); + try { + expect(() => tool.copyOrThrow(src, join(blocked, "child", "dest"))).toThrow( + DirectoryCreateError + ); + } finally { + chmodSync(blocked, 0o755); + } + }); }); describe("glob", () => { @@ -198,7 +264,8 @@ describe("createDirectoryTool", () => { it("creates a working tool without arguments", () => { const tool = createDirectoryTool(); const dir = join(tmpDir, "factory-dir"); - tool.create(dir); + const result = tool.create(dir); + expect(result.isOk()).toBe(true); expect(existsSync(dir)).toBe(true); }); diff --git a/__tests__/node/FileTool.test.ts b/__tests__/node/FileTool.test.ts index b379db7..40e8803 100644 --- a/__tests__/node/FileTool.test.ts +++ b/__tests__/node/FileTool.test.ts @@ -1,10 +1,12 @@ import { afterEach, beforeEach, describe, expect, it } from "vitest"; -import { existsSync, mkdirSync, rmSync, writeFileSync } from "node:fs"; +import { existsSync, mkdirSync, rmSync, writeFileSync, chmodSync } from "node:fs"; import { join } from "node:path"; import { tmpdir } from "node:os"; import { Container } from "@webiny/di"; import { FileTool, + FileWriteError, + FileCopyError, FileToolFeature, createFileTool } from "../../src/node/features/FileTool/index.js"; @@ -76,24 +78,43 @@ describe("FileTool", () => { }); describe("writeFile", () => { - it("creates a file with the given content", () => { + it("returns ok and creates a file with the given content", () => { const file = join(tmpDir, "new.txt"); - tool.writeFile(file, "written"); + const result = tool.writeFile(file, "written"); + expect(result.isOk()).toBe(true); expect(tool.readFile(file)).toBe("written"); }); it("creates parent directories as needed", () => { const file = join(tmpDir, "nested", "deep", "file.txt"); - tool.writeFile(file, "deep content"); + const result = tool.writeFile(file, "deep content"); + expect(result.isOk()).toBe(true); expect(existsSync(file)).toBe(true); }); it("overwrites existing content", () => { const file = join(tmpDir, "file.txt"); writeFileSync(file, "old"); - tool.writeFile(file, "new"); + const result = tool.writeFile(file, "new"); + expect(result.isOk()).toBe(true); expect(tool.readFile(file)).toBe("new"); }); + + it("returns a failure Result when parent directory cannot be created", () => { + const blocked = join(tmpDir, "blocked"); + mkdirSync(blocked, { mode: 0o000 }); + try { + const file = join(blocked, "child", "file.txt"); + const result = tool.writeFile(file, "x"); + expect(result.isFail()).toBe(true); + if (result.isFail()) { + expect(result.error).toBeInstanceOf(FileWriteError); + expect(result.error.data.path).toBe(file); + } + } finally { + chmodSync(blocked, 0o755); + } + }); }); describe("writeFileOrThrow", () => { @@ -102,6 +123,18 @@ describe("FileTool", () => { tool.writeFileOrThrow(file, "content"); expect(tool.readFile(file)).toBe("content"); }); + + it("throws when parent directory cannot be created", () => { + const blocked = join(tmpDir, "blocked"); + mkdirSync(blocked, { mode: 0o000 }); + try { + expect(() => + tool.writeFileOrThrow(join(blocked, "child", "file.txt"), "x") + ).toThrow(); + } finally { + chmodSync(blocked, 0o755); + } + }); }); describe("remove", () => { @@ -118,11 +151,12 @@ describe("FileTool", () => { }); describe("copy", () => { - it("duplicates a file", () => { + it("returns ok and duplicates a file", () => { const src = join(tmpDir, "src.txt"); const dest = join(tmpDir, "dest.txt"); writeFileSync(src, "content"); - tool.copy(src, dest); + const result = tool.copy(src, dest); + expect(result.isOk()).toBe(true); expect(tool.readFile(dest)).toBe("content"); }); @@ -130,14 +164,34 @@ describe("FileTool", () => { const src = join(tmpDir, "src.txt"); const dest = join(tmpDir, "nested", "dest.txt"); writeFileSync(src, "content"); - tool.copy(src, dest); + const result = tool.copy(src, dest); + expect(result.isOk()).toBe(true); expect(existsSync(dest)).toBe(true); }); - it("does not throw when source is missing", () => { - expect(() => - tool.copy(join(tmpDir, "missing.txt"), join(tmpDir, "dest.txt")) - ).not.toThrow(); + it("returns a failure Result when source is missing", () => { + const result = tool.copy(join(tmpDir, "missing.txt"), join(tmpDir, "dest.txt")); + expect(result.isFail()).toBe(true); + if (result.isFail()) { + expect(result.error).toBeInstanceOf(FileCopyError); + expect(result.error.data.source).toBe(join(tmpDir, "missing.txt")); + } + }); + + it("returns a failure Result when destination directory cannot be created", () => { + const src = join(tmpDir, "src.txt"); + writeFileSync(src, "content"); + const blocked = join(tmpDir, "blocked"); + mkdirSync(blocked, { mode: 0o000 }); + try { + const result = tool.copy(src, join(blocked, "child", "dest.txt")); + expect(result.isFail()).toBe(true); + if (result.isFail()) { + expect(result.error).toBeInstanceOf(FileCopyError); + } + } finally { + chmodSync(blocked, 0o755); + } }); }); @@ -147,6 +201,18 @@ describe("FileTool", () => { tool.copyOrThrow(join(tmpDir, "missing.txt"), join(tmpDir, "dest.txt")) ).toThrow(); }); + + it("throws when destination directory cannot be created", () => { + const src = join(tmpDir, "src.txt"); + writeFileSync(src, "content"); + const blocked = join(tmpDir, "blocked"); + mkdirSync(blocked, { mode: 0o000 }); + try { + expect(() => tool.copyOrThrow(src, join(blocked, "child", "dest.txt"))).toThrow(); + } finally { + chmodSync(blocked, 0o755); + } + }); }); }); @@ -165,7 +231,8 @@ describe("createFileTool", () => { it("creates a working tool without arguments", () => { const tool = createFileTool(); const file = join(tmpDir, "factory.txt"); - tool.writeFile(file, "hello"); + const result = tool.writeFile(file, "hello"); + expect(result.isOk()).toBe(true); expect(tool.readFile(file)).toBe("hello"); }); @@ -190,7 +257,8 @@ describe("createFileTool", () => { const directoryTool = createDirectoryTool(); const tool = createFileTool({ directoryTool }); const file = join(tmpDir, "nested", "custom.txt"); - tool.writeFile(file, "content"); + const result = tool.writeFile(file, "content"); + expect(result.isOk()).toBe(true); expect(tool.readFile(file)).toBe("content"); }); }); diff --git a/__tests__/node/JsonFileTool.test.ts b/__tests__/node/JsonFileTool.test.ts index e86077b..0a6c936 100644 --- a/__tests__/node/JsonFileTool.test.ts +++ b/__tests__/node/JsonFileTool.test.ts @@ -1,5 +1,5 @@ import { afterEach, beforeEach, describe, expect, it } from "vitest"; -import { mkdirSync, readFileSync, rmSync, writeFileSync } from "node:fs"; +import { mkdirSync, readFileSync, rmSync, writeFileSync, chmodSync } from "node:fs"; import { join } from "node:path"; import { tmpdir } from "node:os"; import { Container } from "@webiny/di"; @@ -9,7 +9,11 @@ import { createJsonFileTool, type JsonSchema } from "../../src/node/features/JsonFileTool/index.js"; -import { FileTool, FileToolFeature } from "../../src/node/features/FileTool/index.js"; +import { + FileTool, + FileWriteError, + FileToolFeature +} from "../../src/node/features/FileTool/index.js"; import { DirectoryToolFeature } from "../../src/node/features/DirectoryTool/index.js"; import { PinoLoggerConfig, PinoLoggerFeature } from "../../src/node/features/PinoLogger/index.js"; @@ -86,14 +90,14 @@ describe("JsonFileTool", () => { it("throws when schema rejects the data", () => { const file = join(tmpDir, "data.json"); writeFileSync(file, JSON.stringify({ count: 42 })); - const schema = makeSchema<{ name: string }>(_ => { + const schema = makeSchema<{ name: string }>(() => { throw new Error("schema error"); }); expect(() => tool.readJson(file, { schema })).toThrow("schema error"); }); it("returns null (not schema error) when file is missing and schema is provided", () => { - const schema = makeSchema<{ name: string }>(_ => { + const schema = makeSchema<{ name: string }>(() => { throw new Error("should not be called"); }); expect(tool.readJson(join(tmpDir, "missing.json"), { schema })).toBeNull(); @@ -127,7 +131,7 @@ describe("JsonFileTool", () => { it("throws when schema rejects the data", () => { const file = join(tmpDir, "data.json"); writeFileSync(file, JSON.stringify({ wrong: true })); - const schema = makeSchema<{ count: number }>(_ => { + const schema = makeSchema<{ count: number }>(() => { throw new Error("validation failed"); }); expect(() => tool.readJsonOrThrow(file, { schema })).toThrow("validation failed"); @@ -135,31 +139,50 @@ describe("JsonFileTool", () => { }); describe("writeJson", () => { - it("writes JSON with 2-space indentation", () => { + it("returns ok and writes JSON with 2-space indentation", () => { const file = join(tmpDir, "out.json"); - tool.writeJson(file, { key: "value" }); + const result = tool.writeJson(file, { key: "value" }); + expect(result.isOk()).toBe(true); expect(readFileSync(file, "utf-8")).toBe(JSON.stringify({ key: "value" }, null, 2)); }); it("creates parent directories as needed", () => { const file = join(tmpDir, "nested", "deep", "out.json"); - tool.writeJson(file, { ok: true }); + const result = tool.writeJson(file, { ok: true }); + expect(result.isOk()).toBe(true); expect(tool.readJson(file)).toEqual({ ok: true }); }); it("overwrites existing content", () => { const file = join(tmpDir, "out.json"); writeFileSync(file, JSON.stringify({ old: true })); - tool.writeJson(file, { new: true }); + const result = tool.writeJson(file, { new: true }); + expect(result.isOk()).toBe(true); expect(tool.readJson(file)).toEqual({ new: true }); }); it("round-trips data written with readJson", () => { const file = join(tmpDir, "rt.json"); const data = { a: 1, b: ["x", "y"], c: { nested: true } }; - tool.writeJson(file, data); + const result = tool.writeJson(file, data); + expect(result.isOk()).toBe(true); expect(tool.readJson(file)).toEqual(data); }); + + it("returns a failure Result when parent directory cannot be created", () => { + const blocked = join(tmpDir, "blocked"); + mkdirSync(blocked, { mode: 0o000 }); + try { + const file = join(blocked, "child", "out.json"); + const result = tool.writeJson(file, { fail: true }); + expect(result.isFail()).toBe(true); + if (result.isFail()) { + expect(result.error).toBeInstanceOf(FileWriteError); + } + } finally { + chmodSync(blocked, 0o755); + } + }); }); describe("writeJsonOrThrow", () => { diff --git a/__tests__/node/PackageJsonFileTool.test.ts b/__tests__/node/PackageJsonFileTool.test.ts index 1acd352..0214bc4 100644 --- a/__tests__/node/PackageJsonFileTool.test.ts +++ b/__tests__/node/PackageJsonFileTool.test.ts @@ -1,5 +1,5 @@ import { afterEach, beforeEach, describe, expect, it } from "vitest"; -import { mkdirSync, rmSync, writeFileSync } from "node:fs"; +import { mkdirSync, rmSync, writeFileSync, chmodSync } from "node:fs"; import { join } from "node:path"; import { tmpdir } from "node:os"; import { Container } from "@webiny/di"; @@ -9,7 +9,7 @@ import { PackageJsonFile, createPackageJsonFileTool } from "../../src/node/features/PackageJsonFileTool/index.js"; -import { FileToolFeature } from "../../src/node/features/FileTool/index.js"; +import { FileToolFeature, FileWriteError } from "../../src/node/features/FileTool/index.js"; import { DirectoryToolFeature } from "../../src/node/features/DirectoryTool/index.js"; import { PinoLoggerConfig, PinoLoggerFeature } from "../../src/node/features/PinoLogger/index.js"; @@ -105,9 +105,10 @@ describe("PackageJsonFileTool", () => { }); describe("write(path, data)", () => { - it("writes formatted JSON to the given path", () => { + it("returns ok and writes formatted JSON to the given path", () => { const file = join(tmpDir, "package.json"); - tool.write(file, { name: "written-pkg", version: "1.0.0" }); + const result = tool.write(file, { name: "written-pkg", version: "1.0.0" }); + expect(result.isOk()).toBe(true); expect(tool.readOrThrow(file).raw).toMatchObject({ name: "written-pkg", version: "1.0.0" @@ -116,13 +117,29 @@ describe("PackageJsonFileTool", () => { it("creates parent directories as needed", () => { const file = join(tmpDir, "nested", "dir", "package.json"); - tool.write(file, { name: "nested-pkg" }); + const result = tool.write(file, { name: "nested-pkg" }); + expect(result.isOk()).toBe(true); expect(tool.readOrThrow(file).raw).toMatchObject({ name: "nested-pkg" }); }); + + it("returns a failure Result when parent directory cannot be created", () => { + const blocked = join(tmpDir, "blocked"); + mkdirSync(blocked, { mode: 0o000 }); + try { + const file = join(blocked, "child", "package.json"); + const result = tool.write(file, { name: "fail" }); + expect(result.isFail()).toBe(true); + if (result.isFail()) { + expect(result.error).toBeInstanceOf(FileWriteError); + } + } finally { + chmodSync(blocked, 0o755); + } + }); }); describe("write(file)", () => { - it("uses path and raw from the PackageJsonFile instance", () => { + it("returns ok and uses path and raw from the PackageJsonFile instance", () => { const filePath = join(tmpDir, "package.json"); const pkgFile = tool.readOrThrow( (() => { @@ -131,7 +148,8 @@ describe("PackageJsonFileTool", () => { })() ); pkgFile.set("name", "mutated"); - tool.write(pkgFile); + const result = tool.write(pkgFile); + expect(result.isOk()).toBe(true); expect(tool.readOrThrow(filePath).raw.name).toBe("mutated"); }); @@ -144,7 +162,8 @@ describe("PackageJsonFileTool", () => { const pkgFile = tool.readOrThrow(filePath); pkgFile.setDependency("zod", "^4.0.0"); pkgFile.removeDependency("lodash"); - tool.write(pkgFile); + const result = tool.write(pkgFile); + expect(result.isOk()).toBe(true); const reloaded = tool.readOrThrow(filePath); expect(reloaded.getDependency("zod")).toBe("^4.0.0"); expect(reloaded.getDependency("lodash")).toBeNull(); diff --git a/package.json b/package.json index 81333a6..d1fb1d7 100644 --- a/package.json +++ b/package.json @@ -40,24 +40,25 @@ "@webiny/di": "^1.0.2", "bson-objectid": "^2.0.4", "dot-prop": "^10.2.0", - "nanoid": "^6.0.0", + "nanoid": "^6.0.1", "nanoid-dictionary": "^5.0.0", "pino": "^10.3.1", "pino-pretty": "^13.1.3", "tinyglobby": "^0.2.17", - "type-fest": "^5.8.0", - "zod": "^4.4.3" + "type-fest": "^5.9.0", + "zod": "^4.5.4" }, "devDependencies": { "@changesets/cli": "^2.31.1", - "@types/node": "^26.1.2", - "@vitest/coverage-v8": "^4.1.10", + "@types/node": "^26.4.1", + "@vitest/coverage-v8": "^5.0.0", "adio": "^3.0.1", - "happy-dom": "^20.11.1", - "oxfmt": "^0.61.0", - "oxlint": "^1.76.0", + "happy-dom": "^20.14.0", + "oxfmt": "^0.66.0", + "oxlint": "^1.81.0", "typescript": "^7.0.2", - "vitest": "^4.1.10" + "vite": "^8.2.2", + "vitest": "^5.0.0" }, "scripts": { "clean": "rm -rf dist", diff --git a/src/browser/features/BrowserWindow/BrowserWindow.ts b/src/browser/features/BrowserWindow/BrowserWindow.ts new file mode 100644 index 0000000..549a9cc --- /dev/null +++ b/src/browser/features/BrowserWindow/BrowserWindow.ts @@ -0,0 +1,19 @@ +import { BrowserWindow as BrowserWindowAbstraction } from "./abstractions/BrowserWindow.js"; + +class BrowserWindowImpl implements BrowserWindowAbstraction.Interface { + public readonly localStorage: Storage | null; + + public constructor() { + this.localStorage = + typeof window !== "undefined" && window?.localStorage ? window.localStorage : null; + } +} + +export const BrowserWindow = BrowserWindowAbstraction.createImplementation({ + implementation: BrowserWindowImpl, + dependencies: [] +}); + +export function createBrowserWindow(): BrowserWindowAbstraction.Interface { + return new BrowserWindowImpl(); +} diff --git a/src/browser/features/BrowserWindow/NullBrowserWindow.ts b/src/browser/features/BrowserWindow/NullBrowserWindow.ts new file mode 100644 index 0000000..db8e10a --- /dev/null +++ b/src/browser/features/BrowserWindow/NullBrowserWindow.ts @@ -0,0 +1,14 @@ +import { BrowserWindow as BrowserWindowAbstraction } from "./abstractions/BrowserWindow.js"; + +class NullBrowserWindowImpl implements BrowserWindowAbstraction.Interface { + public readonly localStorage: Storage | null = null; +} + +export const NullBrowserWindow = BrowserWindowAbstraction.createImplementation({ + implementation: NullBrowserWindowImpl, + dependencies: [] +}); + +export function createNullBrowserWindow(): BrowserWindowAbstraction.Interface { + return new NullBrowserWindowImpl(); +} diff --git a/src/browser/features/BrowserWindow/README.md b/src/browser/features/BrowserWindow/README.md new file mode 100644 index 0000000..6687648 --- /dev/null +++ b/src/browser/features/BrowserWindow/README.md @@ -0,0 +1,46 @@ +# BrowserWindow + +Abstraction over the browser `window` object. Provides injectable access to browser-specific APIs (`localStorage`, etc.) without coupling consumers directly to the global. The real implementation captures references at construction time; the null implementation returns `null` for all APIs, suitable for SSR or testing. + +## Interface + +```ts +interface IBrowserWindow { + /** Returns the localStorage instance, or null if unavailable. */ + readonly localStorage: Storage | null; +} +``` + +## Usage + +### DI container wiring + +```ts +import { Container } from "@webiny/di"; +import { + BrowserWindow, + BrowserWindowFeature, + NullBrowserWindowFeature +} from "@webiny/stdlib/browser"; + +// Real — captures from the global window +const container = new Container(); +BrowserWindowFeature.register(container); +const bw = container.resolve(BrowserWindow); +console.log(bw.localStorage); // Storage or null + +// Null — all APIs return null +const ssrContainer = new Container(); +NullBrowserWindowFeature.register(ssrContainer); +const nullBw = ssrContainer.resolve(BrowserWindow); +console.log(nullBw.localStorage); // null +``` + +### Factory functions + +```ts +import { createBrowserWindow, createNullBrowserWindow } from "@webiny/stdlib/browser"; + +const bw = createBrowserWindow(); +const nullBw = createNullBrowserWindow(); +``` diff --git a/src/browser/features/BrowserWindow/abstractions/BrowserWindow.ts b/src/browser/features/BrowserWindow/abstractions/BrowserWindow.ts new file mode 100644 index 0000000..3b3ac1a --- /dev/null +++ b/src/browser/features/BrowserWindow/abstractions/BrowserWindow.ts @@ -0,0 +1,17 @@ +import { createAbstraction } from "~/common/index.js"; + +/** + * Abstraction over the browser `window` object. + * Provides access to browser-specific APIs (localStorage, etc.) + * without coupling consumers directly to the global. + */ +export interface IBrowserWindow { + /** Returns the localStorage instance, or null if unavailable. */ + readonly localStorage: Storage | null; +} + +export const BrowserWindow = createAbstraction("Browser/BrowserWindow"); + +export namespace BrowserWindow { + export type Interface = IBrowserWindow; +} diff --git a/src/browser/features/BrowserWindow/abstractions/index.ts b/src/browser/features/BrowserWindow/abstractions/index.ts new file mode 100644 index 0000000..5ecb922 --- /dev/null +++ b/src/browser/features/BrowserWindow/abstractions/index.ts @@ -0,0 +1 @@ +export { BrowserWindow } from "./BrowserWindow.js"; diff --git a/src/browser/features/BrowserWindow/feature.ts b/src/browser/features/BrowserWindow/feature.ts new file mode 100644 index 0000000..c4fa5bf --- /dev/null +++ b/src/browser/features/BrowserWindow/feature.ts @@ -0,0 +1,10 @@ +import { createFeature } from "~/common/index.js"; +import { BrowserWindow } from "./BrowserWindow.js"; + +/** Registers the real BrowserWindow that captures from the global `window`. */ +export const BrowserWindowFeature = createFeature({ + name: "Browser/BrowserWindowFeature", + register(container) { + container.register(BrowserWindow).inSingletonScope(); + } +}); diff --git a/src/browser/features/BrowserWindow/index.ts b/src/browser/features/BrowserWindow/index.ts new file mode 100644 index 0000000..0f6aa06 --- /dev/null +++ b/src/browser/features/BrowserWindow/index.ts @@ -0,0 +1,5 @@ +export { BrowserWindow } from "./abstractions/index.js"; +export { BrowserWindowFeature } from "./feature.js"; +export { NullBrowserWindowFeature } from "./nullFeature.js"; +export { createBrowserWindow } from "./BrowserWindow.js"; +export { createNullBrowserWindow } from "./NullBrowserWindow.js"; diff --git a/src/browser/features/BrowserWindow/nullFeature.ts b/src/browser/features/BrowserWindow/nullFeature.ts new file mode 100644 index 0000000..eaba33d --- /dev/null +++ b/src/browser/features/BrowserWindow/nullFeature.ts @@ -0,0 +1,10 @@ +import { createFeature } from "~/common/index.js"; +import { NullBrowserWindow } from "./NullBrowserWindow.js"; + +/** Registers a null BrowserWindow where all APIs return null. */ +export const NullBrowserWindowFeature = createFeature({ + name: "Browser/NullBrowserWindowFeature", + register(container) { + container.register(NullBrowserWindow).inSingletonScope(); + } +}); diff --git a/src/browser/features/LocalStorageCache/LocalStorageCache.ts b/src/browser/features/LocalStorageCache/LocalStorageCache.ts index 1b5f030..d44906b 100644 --- a/src/browser/features/LocalStorageCache/LocalStorageCache.ts +++ b/src/browser/features/LocalStorageCache/LocalStorageCache.ts @@ -1,5 +1,6 @@ import { Result } from "~/common/index.js"; import { Cache as CacheAbstraction } from "~/common/index.js"; +import { BrowserWindow } from "../BrowserWindow/abstractions/BrowserWindow.js"; import { LocalStorageParseError, LocalStorageQuotaExceededError, @@ -16,13 +17,12 @@ class LocalStorageCacheImpl implements CacheAbstraction.Interface { private readonly localStorage: Storage | null; - public constructor() { - this.localStorage = - typeof window !== "undefined" && window?.localStorage ? window.localStorage : null; + public constructor(private readonly browserWindow: BrowserWindow.Interface) { + this.localStorage = browserWindow.localStorage; } - private static fromPrefix(prefix: string): LocalStorageCacheImpl { - const instance = new LocalStorageCacheImpl(); + private createPrefixed(prefix: string): LocalStorageCacheImpl { + const instance = new LocalStorageCacheImpl(this.browserWindow); instance.prefix = prefix; return instance; } @@ -174,15 +174,17 @@ class LocalStorageCacheImpl implements CacheAbstraction.Interface { public byPrefix(prefix: string): CacheAbstraction.Interface { const combined = this.prefix ? `${this.prefix}.${prefix}` : prefix; - return LocalStorageCacheImpl.fromPrefix(combined); + return this.createPrefixed(combined); } } export const LocalStorageCache = CacheAbstraction.createImplementation({ implementation: LocalStorageCacheImpl, - dependencies: [] + dependencies: [BrowserWindow] }); -export function createLocalStorageCache(): CacheAbstraction.Interface { - return new LocalStorageCacheImpl(); +export function createLocalStorageCache( + browserWindow: BrowserWindow.Interface +): CacheAbstraction.Interface { + return new LocalStorageCacheImpl(browserWindow); } diff --git a/src/browser/index.ts b/src/browser/index.ts index bbfd67d..969d2f8 100644 --- a/src/browser/index.ts +++ b/src/browser/index.ts @@ -1,3 +1,10 @@ +export { + BrowserWindow, + BrowserWindowFeature, + NullBrowserWindowFeature, + createBrowserWindow, + createNullBrowserWindow +} from "./features/BrowserWindow/index.js"; export { BrowserEnvFeature, createBrowserEnv, diff --git a/src/node/features/DirectoryTool/DirectoryTool.ts b/src/node/features/DirectoryTool/DirectoryTool.ts index eacffc2..07b1b48 100644 --- a/src/node/features/DirectoryTool/DirectoryTool.ts +++ b/src/node/features/DirectoryTool/DirectoryTool.ts @@ -9,8 +9,10 @@ import { constants } from "node:fs"; import { dirname } from "node:path"; +import { Result } from "~/common/index.js"; import { DirectoryTool as DirectoryToolAbstraction } from "./abstractions/DirectoryTool.js"; import type { GlobOptions } from "./abstractions/DirectoryTool.js"; +import { DirectoryCreateError } from "./errors.js"; import { Logger, ConsoleLogger } from "~/common/features/Logger/index.js"; import { createGlobTool, GlobTool } from "../GlobTool/index.js"; @@ -24,7 +26,7 @@ class DirectoryToolImpl implements DirectoryToolAbstraction.Interface { return existsSync(path); } - public create(path: string): void { + public create(path: string): Result { try { if (existsSync(path)) { try { @@ -32,11 +34,24 @@ class DirectoryToolImpl implements DirectoryToolAbstraction.Interface { } catch { chmodSync(path, 0o755); } - return; + return Result.ok(); } mkdirSync(path, { recursive: true, mode: 0o755 }); + return Result.ok(); } catch (error) { - this.logger.warn(`Failed to create directory "${path}": ${error}`); + return Result.fail( + new DirectoryCreateError({ + message: `Failed to create directory "${path}": ${error}`, + data: { path } + }) + ); + } + } + + public createOrThrow(path: string): void { + const result = this.create(path); + if (result.isFail()) { + throw result.error; } } @@ -64,7 +79,11 @@ class DirectoryToolImpl implements DirectoryToolAbstraction.Interface { this.logger.warn(`Source directory not found: "${source}"`); return; } - this.create(dirname(target)); + const dirResult = this.create(dirname(target)); + if (dirResult.isFail()) { + this.logger.warn(dirResult.error.message); + return; + } cpSync(source, target, { recursive: true }); } @@ -72,7 +91,7 @@ class DirectoryToolImpl implements DirectoryToolAbstraction.Interface { if (!existsSync(source)) { throw new Error(`Source directory not found: "${source}"`); } - this.create(dirname(target)); + this.createOrThrow(dirname(target)); cpSync(source, target, { recursive: true }); } diff --git a/src/node/features/DirectoryTool/README.md b/src/node/features/DirectoryTool/README.md index 473c0a0..c3d28a4 100644 --- a/src/node/features/DirectoryTool/README.md +++ b/src/node/features/DirectoryTool/README.md @@ -6,7 +6,7 @@ context: node # DirectoryTool -Creates, reads, copies, removes, and globs directories on the local filesystem. All paths must be absolute. `create` is idempotent — it calls `mkdirSync` with `recursive: true` and is safe to call on an existing path. Methods without `OrThrow` log a warning and return `null` / `void` on failure; `OrThrow` variants throw. +Creates, reads, copies, removes, and globs directories on the local filesystem. All paths must be absolute. `create` is idempotent — it calls `mkdirSync` with `recursive: true` and is safe to call on an existing path. `create` returns a `Result` so the caller can handle failures; `createOrThrow` throws a `DirectoryCreateError` instead. Methods without `OrThrow` log a warning and return `null` / `void` on failure; `OrThrow` variants throw. ## Interface @@ -14,8 +14,10 @@ Creates, reads, copies, removes, and globs directories on the local filesystem. interface IDirectoryTool { /** Returns true if the directory exists. */ exists(path: string): boolean; - /** Creates the directory (and any missing parents). Idempotent. */ - create(path: string): void; + /** Creates the directory (and any missing parents). Returns a failure Result if the operation fails. */ + create(path: string): Result; + /** Creates the directory (and any missing parents). Throws if the operation fails. */ + createOrThrow(path: string): void; /** Returns the names of entries in the directory. Returns null if it does not exist. */ readDir(path: string): string[] | null; /** Returns the names of entries in the directory. Throws if it does not exist. */ @@ -43,6 +45,10 @@ interface GlobOptions { } ``` +## Errors + +- `DirectoryCreateError` — the directory could not be created (permissions, read-only filesystem, etc.). Data: `{ path: string }`. + ## Usage ### With DI @@ -56,7 +62,15 @@ PinoLoggerFeature.register(container); DirectoryToolFeature.register(container); const dir = container.resolve(DirectoryTool); -dir.create("/tmp/my-output"); + +// Result-based — caller decides how to handle failure +const result = dir.create("/tmp/my-output"); +if (result.isFail()) { + console.error(result.error.message); +} + +// Throwing variant +dir.createOrThrow("/tmp/my-output"); console.log(dir.readDirOrThrow("/tmp/my-output")); // [] ``` @@ -66,7 +80,7 @@ console.log(dir.readDirOrThrow("/tmp/my-output")); // [] import { createDirectoryTool } from "@webiny/stdlib/node"; const dir = createDirectoryTool(); -dir.create("/tmp/my-output"); +dir.createOrThrow("/tmp/my-output"); // list all .ts files recursively const files = dir.glob("/my/project/src", "**/*.ts"); diff --git a/src/node/features/DirectoryTool/abstractions/DirectoryTool.ts b/src/node/features/DirectoryTool/abstractions/DirectoryTool.ts index fb32727..159a6c4 100644 --- a/src/node/features/DirectoryTool/abstractions/DirectoryTool.ts +++ b/src/node/features/DirectoryTool/abstractions/DirectoryTool.ts @@ -1,4 +1,6 @@ import { createAbstraction } from "~/common/index.js"; +import type { Result } from "~/common/index.js"; +import type { DirectoryCreateError } from "../errors.js"; export interface GlobOptions { /** Include dotfiles (default: false). */ @@ -15,7 +17,10 @@ export interface GlobOptions { export interface IDirectoryTool { exists(path: string): boolean; - create(path: string): void; + /** Creates the directory (and parents). Returns a failure Result if the operation fails. */ + create(path: string): Result; + /** Creates the directory (and parents). Throws if the operation fails. */ + createOrThrow(path: string): void; readDir(path: string): string[] | null; readDirOrThrow(path: string): string[]; remove(path: string): void; diff --git a/src/node/features/DirectoryTool/errors.ts b/src/node/features/DirectoryTool/errors.ts new file mode 100644 index 0000000..f30db6f --- /dev/null +++ b/src/node/features/DirectoryTool/errors.ts @@ -0,0 +1,14 @@ +import { BaseError } from "~/common/index.js"; +import type { ErrorInput } from "~/common/index.js"; + +interface DirectoryCreateData { + path: string; +} + +/** The directory could not be created (permissions, read-only filesystem, etc.). */ +export class DirectoryCreateError extends BaseError { + public readonly code = "DIRECTORY_CREATE_FAILED" as const; + public constructor(input: ErrorInput) { + super(input); + } +} diff --git a/src/node/features/DirectoryTool/index.ts b/src/node/features/DirectoryTool/index.ts index ead55bc..8fd5a5d 100644 --- a/src/node/features/DirectoryTool/index.ts +++ b/src/node/features/DirectoryTool/index.ts @@ -1,3 +1,4 @@ export { DirectoryTool, type GlobOptions } from "./abstractions/index.js"; +export { DirectoryCreateError } from "./errors.js"; export { DirectoryToolFeature } from "./feature.js"; export { createDirectoryTool, type CreateDirectoryToolParams } from "./DirectoryTool.js"; diff --git a/src/node/features/FileTool/FileTool.ts b/src/node/features/FileTool/FileTool.ts index 20f8703..793149a 100644 --- a/src/node/features/FileTool/FileTool.ts +++ b/src/node/features/FileTool/FileTool.ts @@ -1,6 +1,8 @@ import { existsSync, readFileSync, writeFileSync, rmSync, copyFileSync } from "node:fs"; import { dirname } from "node:path"; +import { Result } from "~/common/index.js"; import { FileTool as FileToolAbstraction } from "./abstractions/FileTool.js"; +import { FileWriteError, FileCopyError } from "./errors.js"; import { DirectoryTool } from "../DirectoryTool/abstractions/DirectoryTool.js"; import { createDirectoryTool } from "../DirectoryTool/DirectoryTool.js"; import { Logger, ConsoleLogger } from "~/common/index.js"; @@ -30,17 +32,31 @@ class FileToolImpl implements FileToolAbstraction.Interface { return readFileSync(path, "utf-8"); } - public writeFile(path: string, content: string): void { + public writeFile(path: string, content: string): Result { try { - this.directoryTool.create(dirname(path)); + const dirResult = this.directoryTool.create(dirname(path)); + if (dirResult.isFail()) { + return Result.fail( + new FileWriteError({ + message: dirResult.error.message, + data: { path } + }) + ); + } writeFileSync(path, content, "utf-8"); + return Result.ok(); } catch (error) { - this.logger.warn(`Failed to write file "${path}": ${error}`); + return Result.fail( + new FileWriteError({ + message: `Failed to write file "${path}": ${error}`, + data: { path } + }) + ); } } public writeFileOrThrow(path: string, content: string): void { - this.directoryTool.create(dirname(path)); + this.directoryTool.createOrThrow(dirname(path)); writeFileSync(path, content, "utf-8"); } @@ -48,20 +64,42 @@ class FileToolImpl implements FileToolAbstraction.Interface { rmSync(path, { force: true }); } - public copy(source: string, target: string): void { + public copy(source: string, target: string): Result { if (!existsSync(source)) { - this.logger.warn(`Source file not found: "${source}"`); - return; + return Result.fail( + new FileCopyError({ + message: `Source file not found: "${source}"`, + data: { source, target } + }) + ); + } + try { + const dirResult = this.directoryTool.create(dirname(target)); + if (dirResult.isFail()) { + return Result.fail( + new FileCopyError({ + message: dirResult.error.message, + data: { source, target } + }) + ); + } + copyFileSync(source, target); + return Result.ok(); + } catch (error) { + return Result.fail( + new FileCopyError({ + message: `Failed to copy file "${source}" to "${target}": ${error}`, + data: { source, target } + }) + ); } - this.directoryTool.create(dirname(target)); - copyFileSync(source, target); } public copyOrThrow(source: string, target: string): void { if (!existsSync(source)) { throw new Error(`Source file not found: "${source}"`); } - this.directoryTool.create(dirname(target)); + this.directoryTool.createOrThrow(dirname(target)); copyFileSync(source, target); } } diff --git a/src/node/features/FileTool/README.md b/src/node/features/FileTool/README.md index 34a48c7..fff7f0b 100644 --- a/src/node/features/FileTool/README.md +++ b/src/node/features/FileTool/README.md @@ -6,7 +6,7 @@ context: node # FileTool -Reads, writes, copies, and removes files on the local filesystem. All paths must be absolute. Write operations automatically create missing parent directories. Methods without `OrThrow` log a warning and return `null` / `void` on failure; `OrThrow` variants throw. +Reads, writes, copies, and removes files on the local filesystem. All paths must be absolute. Write operations automatically create missing parent directories. `writeFile` and `copy` return a `Result` so the caller can handle failures; `writeFileOrThrow` and `copyOrThrow` throw instead. `readFile` returns `null` if the file does not exist. ## Interface @@ -18,19 +18,24 @@ interface IFileTool { readFile(path: string): string | null; /** Reads the file as UTF-8. Throws if the file does not exist. */ readFileOrThrow(path: string): string; - /** Writes UTF-8 content, creating parent directories as needed. Logs on failure. */ - writeFile(path: string, content: string): void; + /** Writes UTF-8 content, creating parent directories as needed. */ + writeFile(path: string, content: string): Result; /** Writes UTF-8 content, creating parent directories as needed. Throws on failure. */ writeFileOrThrow(path: string, content: string): void; /** Removes the file. No-op if the file does not exist. */ remove(path: string): void; - /** Copies source to target, creating parent directories as needed. Logs if source is missing. */ - copy(source: string, target: string): void; + /** Copies source to target, creating parent directories as needed. */ + copy(source: string, target: string): Result; /** Copies source to target, creating parent directories as needed. Throws if source is missing. */ copyOrThrow(source: string, target: string): void; } ``` +## Errors + +- `FileWriteError` — the file could not be written (directory creation failure, permissions, disk full, etc.). Data: `{ path: string }`. +- `FileCopyError` — the file could not be copied (source not found, permissions, directory creation failure, etc.). Data: `{ source: string; target: string }`. + ## Usage ### With DI @@ -50,6 +55,14 @@ DirectoryToolFeature.register(container); FileToolFeature.register(container); const file = container.resolve(FileTool); + +// Result-based — caller decides how to handle failure +const result = file.writeFile("/tmp/hello.txt", "hello world"); +if (result.isFail()) { + console.error(result.error.message); +} + +// Throwing variant file.writeFileOrThrow("/tmp/hello.txt", "hello world"); console.log(file.readFileOrThrow("/tmp/hello.txt")); // "hello world" ``` diff --git a/src/node/features/FileTool/abstractions/FileTool.ts b/src/node/features/FileTool/abstractions/FileTool.ts index 3d1088b..82c6506 100644 --- a/src/node/features/FileTool/abstractions/FileTool.ts +++ b/src/node/features/FileTool/abstractions/FileTool.ts @@ -1,13 +1,17 @@ import { createAbstraction } from "~/common/index.js"; +import type { Result } from "~/common/index.js"; +import type { FileWriteError, FileCopyError } from "../errors.js"; export interface IFileTool { exists(path: string): boolean; readFile(path: string): string | null; readFileOrThrow(path: string): string; - writeFile(path: string, content: string): void; + /** Writes content to the file, creating parent directories as needed. */ + writeFile(path: string, content: string): Result; writeFileOrThrow(path: string, content: string): void; remove(path: string): void; - copy(source: string, target: string): void; + /** Copies the file from source to target, creating parent directories as needed. */ + copy(source: string, target: string): Result; copyOrThrow(source: string, target: string): void; } diff --git a/src/node/features/FileTool/errors.ts b/src/node/features/FileTool/errors.ts new file mode 100644 index 0000000..c4769f4 --- /dev/null +++ b/src/node/features/FileTool/errors.ts @@ -0,0 +1,27 @@ +import { BaseError } from "~/common/index.js"; +import type { ErrorInput } from "~/common/index.js"; + +interface FileWriteData { + path: string; +} + +interface FileCopyData { + source: string; + target: string; +} + +/** The file could not be written (directory creation failure, permissions, disk full, etc.). */ +export class FileWriteError extends BaseError { + public readonly code = "FILE_WRITE_FAILED" as const; + public constructor(input: ErrorInput) { + super(input); + } +} + +/** The file could not be copied (source not found, permissions, directory creation failure, etc.). */ +export class FileCopyError extends BaseError { + public readonly code = "FILE_COPY_FAILED" as const; + public constructor(input: ErrorInput) { + super(input); + } +} diff --git a/src/node/features/FileTool/index.ts b/src/node/features/FileTool/index.ts index afd3e27..389c530 100644 --- a/src/node/features/FileTool/index.ts +++ b/src/node/features/FileTool/index.ts @@ -1,3 +1,4 @@ export { FileTool } from "./abstractions/index.js"; +export { FileWriteError, FileCopyError } from "./errors.js"; export { FileToolFeature } from "./feature.js"; export { createFileTool, type CreateFileToolParams } from "./FileTool.js"; diff --git a/src/node/features/JsonFileTool/JsonFileTool.ts b/src/node/features/JsonFileTool/JsonFileTool.ts index f9da58f..8494814 100644 --- a/src/node/features/JsonFileTool/JsonFileTool.ts +++ b/src/node/features/JsonFileTool/JsonFileTool.ts @@ -1,8 +1,10 @@ +import type { Result } from "~/common/index.js"; import { JsonFileTool as JsonFileToolAbstraction, type ReadJsonParams } from "./abstractions/JsonFileTool.js"; import { FileTool } from "../FileTool/abstractions/FileTool.js"; +import type { FileWriteError } from "../FileTool/errors.js"; import { createFileTool } from "../FileTool/FileTool.js"; class JsonFileToolImpl implements JsonFileToolAbstraction.Interface { @@ -29,8 +31,8 @@ class JsonFileToolImpl implements JsonFileToolAbstraction.Interface { return parsed as T; } - public writeJson(path: string, data: unknown): void { - this.fileTool.writeFile(path, JSON.stringify(data, null, 2)); + public writeJson(path: string, data: unknown): Result { + return this.fileTool.writeFile(path, JSON.stringify(data, null, 2)); } public writeJsonOrThrow(path: string, data: unknown): void { diff --git a/src/node/features/JsonFileTool/README.md b/src/node/features/JsonFileTool/README.md index 5af5b0a..a11ae7e 100644 --- a/src/node/features/JsonFileTool/README.md +++ b/src/node/features/JsonFileTool/README.md @@ -6,7 +6,7 @@ context: node # JsonFileTool -Reads and writes JSON files on the local filesystem. Optionally validates the parsed value through a schema (any object with a `.parse(unknown): T` method — compatible with Zod, Valibot, and similar). Methods without `OrThrow` return `null` on failure; `OrThrow` variants throw. +Reads and writes JSON files on the local filesystem. Optionally validates the parsed value through a schema (any object with a `.parse(unknown): T` method — compatible with Zod, Valibot, and similar). `readJson` returns `null` when the file is missing; `writeJson` returns a `Result` so the caller can handle failures. `OrThrow` variants throw. ## Interface @@ -16,8 +16,8 @@ interface IJsonFileTool { readJson(path: string, params?: ReadJsonParams): T | null; /** Parses and returns the JSON file contents. Throws if missing, unparseable, or schema validation fails. */ readJsonOrThrow(path: string, params?: ReadJsonParams): T; - /** Serialises data to JSON and writes it. Creates parent directories as needed. Logs on failure. */ - writeJson(path: string, data: unknown): void; + /** Serialises data to JSON and writes it. Creates parent directories as needed. */ + writeJson(path: string, data: unknown): Result; /** Serialises data to JSON and writes it. Creates parent directories as needed. Throws on failure. */ writeJsonOrThrow(path: string, data: unknown): void; } diff --git a/src/node/features/JsonFileTool/abstractions/JsonFileTool.ts b/src/node/features/JsonFileTool/abstractions/JsonFileTool.ts index 29e62d0..58f78bc 100644 --- a/src/node/features/JsonFileTool/abstractions/JsonFileTool.ts +++ b/src/node/features/JsonFileTool/abstractions/JsonFileTool.ts @@ -1,4 +1,6 @@ import { createAbstraction } from "~/common/index.js"; +import type { Result } from "~/common/index.js"; +import type { FileWriteError } from "../../FileTool/errors.js"; export interface JsonSchema { parse(data: unknown): T; @@ -11,7 +13,8 @@ export interface ReadJsonParams { export interface IJsonFileTool { readJson(path: string, params?: ReadJsonParams): T | null; readJsonOrThrow(path: string, params?: ReadJsonParams): T; - writeJson(path: string, data: unknown): void; + /** Serializes data as formatted JSON and writes it to path. */ + writeJson(path: string, data: unknown): Result; writeJsonOrThrow(path: string, data: unknown): void; } diff --git a/src/node/features/PackageJsonFileTool/PackageJsonFileTool.ts b/src/node/features/PackageJsonFileTool/PackageJsonFileTool.ts index 3dc5044..5457d2d 100644 --- a/src/node/features/PackageJsonFileTool/PackageJsonFileTool.ts +++ b/src/node/features/PackageJsonFileTool/PackageJsonFileTool.ts @@ -1,8 +1,10 @@ import { z } from "zod"; import type { PackageJson } from "type-fest"; +import type { Result } from "~/common/index.js"; import { PackageJsonFileTool as PackageJsonFileToolAbstraction } from "./abstractions/PackageJsonFileTool.js"; import { PackageJsonFile } from "./PackageJsonFile.js"; import { FileTool } from "../FileTool/abstractions/FileTool.js"; +import type { FileWriteError } from "../FileTool/errors.js"; import { createFileTool } from "../FileTool/FileTool.js"; const dependencyRecord = z.record(z.string(), z.string()).optional(); @@ -52,14 +54,16 @@ class PackageJsonFileToolImpl implements PackageJsonFileToolAbstraction.Interfac return new PackageJsonFile(path, raw); } - public write(path: string, data: PackageJson): void; - public write(file: PackageJsonFile.Interface): void; - public write(pathOrFile: string | PackageJsonFile.Interface, data?: PackageJson): void { + public write(path: string, data: PackageJson): Result; + public write(file: PackageJsonFile.Interface): Result; + public write( + pathOrFile: string | PackageJsonFile.Interface, + data?: PackageJson + ): Result { if (typeof pathOrFile === "string") { - this.fileTool.writeFile(pathOrFile, serialize(data!)); - } else { - this.fileTool.writeFile(pathOrFile.path, serialize(pathOrFile.raw)); + return this.fileTool.writeFile(pathOrFile, serialize(data!)); } + return this.fileTool.writeFile(pathOrFile.path, serialize(pathOrFile.raw)); } public writeOrThrow(path: string, data: PackageJson): void; diff --git a/src/node/features/PackageJsonFileTool/README.md b/src/node/features/PackageJsonFileTool/README.md index c794197..74106dc 100644 --- a/src/node/features/PackageJsonFileTool/README.md +++ b/src/node/features/PackageJsonFileTool/README.md @@ -26,11 +26,11 @@ interface IPackageJsonFileTool { readOrThrow(path: string): PackageJsonFile.Interface; /** Serialize and write to `path`. Creates parent directories as needed. */ - write(path: string, data: PackageJson): void; + write(path: string, data: PackageJson): Result; /** Serialize the file's own path and data back to disk. */ - write(file: PackageJsonFile.Interface): void; + write(file: PackageJsonFile.Interface): Result; - /** Like `write`, but throws on failure instead of logging. */ + /** Like `write`, but throws on failure. */ writeOrThrow(path: string, data: PackageJson): void; writeOrThrow(file: PackageJsonFile.Interface): void; } diff --git a/src/node/features/PackageJsonFileTool/abstractions/PackageJsonFileTool.ts b/src/node/features/PackageJsonFileTool/abstractions/PackageJsonFileTool.ts index 29070c5..5270025 100644 --- a/src/node/features/PackageJsonFileTool/abstractions/PackageJsonFileTool.ts +++ b/src/node/features/PackageJsonFileTool/abstractions/PackageJsonFileTool.ts @@ -1,5 +1,7 @@ import { createAbstraction } from "~/common/index.js"; +import type { Result } from "~/common/index.js"; import type { PackageJson } from "type-fest"; +import type { FileWriteError } from "../../FileTool/errors.js"; import type { PackageJsonFile } from "../PackageJsonFile.js"; export interface IPackageJsonFileTool { @@ -18,14 +20,14 @@ export interface IPackageJsonFileTool { /** * Serialize `data` as formatted JSON and write it to `path`. - * Creates parent directories as needed. Logs a warning and returns without throwing on failure. + * Creates parent directories as needed. */ - write(path: string, data: PackageJson): void; + write(path: string, data: PackageJson): Result; /** * Serialize `file.raw` as formatted JSON and write it to `file.path`. - * Creates parent directories as needed. Logs a warning and returns without throwing on failure. + * Creates parent directories as needed. */ - write(file: PackageJsonFile.Interface): void; + write(file: PackageJsonFile.Interface): Result; /** * Serialize `data` as formatted JSON and write it to `path`. diff --git a/src/node/index.ts b/src/node/index.ts index 2ef982a..13f2b23 100644 --- a/src/node/index.ts +++ b/src/node/index.ts @@ -1,5 +1,6 @@ export { DirectoryTool, + DirectoryCreateError, DirectoryToolFeature, createDirectoryTool, type CreateDirectoryToolParams, @@ -7,6 +8,8 @@ export { } from "./features/DirectoryTool/index.js"; export { FileTool, + FileWriteError, + FileCopyError, FileToolFeature, createFileTool, type CreateFileToolParams diff --git a/yarn.lock b/yarn.lock index 3a3ef11..f8ea18a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -337,11 +337,11 @@ __metadata: linkType: hard "@hono/node-server@npm:^1.19.9 || ^2.0.5": - version: 2.0.12 - resolution: "@hono/node-server@npm:2.0.12" + version: 2.1.1 + resolution: "@hono/node-server@npm:2.1.1" peerDependencies: hono: ^4 - checksum: 10c0/c3f56e286ddf81394cab02f74391ebead7d601c1140f2bbcafe24e09b49ceb77519982965b0e069b0c2c9ad1840cba088ac67844a6c98b356f7eedf28801db0d + checksum: 10c0/7ef810ca647c56d8d9386fd81609e18443b3a5634aa5ecabdf357e7ca724613c535e863c15ded9b7ae89b935a073040fb11e6d59041f3b1c3e153d8ecb699880 languageName: node linkType: hard @@ -377,13 +377,13 @@ __metadata: linkType: hard "@jridgewell/sourcemap-codec@npm:^1.4.14, @jridgewell/sourcemap-codec@npm:^1.5.5": - version: 1.5.5 - resolution: "@jridgewell/sourcemap-codec@npm:1.5.5" - checksum: 10c0/f9e538f302b63c0ebc06eecb1dd9918dd4289ed36147a0ddce35d6ea4d7ebbda243cda7b2213b6a5e1d8087a298d5cf630fb2bd39329cdecb82017023f6081a0 + version: 1.6.0 + resolution: "@jridgewell/sourcemap-codec@npm:1.6.0" + checksum: 10c0/b5be700e45a775f218589c3466c4ffea630582b4988657652da464e5ab8a7d18bf928ee4fd2363fb346ede4bea9c6ff0bae05a538358c4565ece6199531b5f72 languageName: node linkType: hard -"@jridgewell/trace-mapping@npm:^0.3.31": +"@jridgewell/trace-mapping@npm:0.3.31, @jridgewell/trace-mapping@npm:^0.3.31": version: 0.3.31 resolution: "@jridgewell/trace-mapping@npm:0.3.31" dependencies: @@ -453,14 +453,14 @@ __metadata: linkType: hard "@napi-rs/wasm-runtime@npm:^1.1.4": - version: 1.2.2 - resolution: "@napi-rs/wasm-runtime@npm:1.2.2" + version: 1.2.3 + resolution: "@napi-rs/wasm-runtime@npm:1.2.3" dependencies: "@tybys/wasm-util": "npm:^0.10.3" peerDependencies: - "@emnapi/core": ^1.7.1 || ^2.0.0-alpha.3 - "@emnapi/runtime": ^1.7.1 || ^2.0.0-alpha.3 - checksum: 10c0/670ff8359761660f58d95a29fe22ac959d2c295675144fe9bc35118b0e723d1e0ac192df9896ba428eb13930cf0893b632606b70ccaea259fd6eca1836c2eb09 + "@emnapi/core": ^1.7.1 || ^2.0.0-alpha.4 + "@emnapi/runtime": ^1.7.1 || ^2.0.0-alpha.4 + checksum: 10c0/6da0a4bf9df79e9abfb3e3d462f6a5d42889be39426040038c9dd5925865585d7dbd06dd439c2ffc20f49ef2751412da5bd748cfb3c5b049142d72c0550f6f79 languageName: node linkType: hard @@ -635,10 +635,10 @@ __metadata: languageName: node linkType: hard -"@oxc-project/types@npm:=0.142.0": - version: 0.142.0 - resolution: "@oxc-project/types@npm:0.142.0" - checksum: 10c0/e4fa60b8fe1a77b0db6b9a2dcbc78d9a5a18ef64dffde01d909108f3ddbc562b876c568cb01e297ba71a256fc8aaafc928d4562475a9b2a25b276fee5bf635c3 +"@oxc-project/types@npm:=0.148.0": + version: 0.148.0 + resolution: "@oxc-project/types@npm:0.148.0" + checksum: 10c0/23700196086ec996dcaf8cb494d0d378257a4f6f8ac4dfa0ee732bdf9a8a519da535cb33c8654ee6ea771872ae5801f9963c9d402767a4d13c2fa128cf7c42d2 languageName: node linkType: hard @@ -649,268 +649,268 @@ __metadata: languageName: node linkType: hard -"@oxfmt/binding-android-arm-eabi@npm:0.61.0": - version: 0.61.0 - resolution: "@oxfmt/binding-android-arm-eabi@npm:0.61.0" +"@oxfmt/binding-android-arm-eabi@npm:0.66.0": + version: 0.66.0 + resolution: "@oxfmt/binding-android-arm-eabi@npm:0.66.0" conditions: os=android & cpu=arm languageName: node linkType: hard -"@oxfmt/binding-android-arm64@npm:0.61.0": - version: 0.61.0 - resolution: "@oxfmt/binding-android-arm64@npm:0.61.0" +"@oxfmt/binding-android-arm64@npm:0.66.0": + version: 0.66.0 + resolution: "@oxfmt/binding-android-arm64@npm:0.66.0" conditions: os=android & cpu=arm64 languageName: node linkType: hard -"@oxfmt/binding-darwin-arm64@npm:0.61.0": - version: 0.61.0 - resolution: "@oxfmt/binding-darwin-arm64@npm:0.61.0" +"@oxfmt/binding-darwin-arm64@npm:0.66.0": + version: 0.66.0 + resolution: "@oxfmt/binding-darwin-arm64@npm:0.66.0" conditions: os=darwin & cpu=arm64 languageName: node linkType: hard -"@oxfmt/binding-darwin-x64@npm:0.61.0": - version: 0.61.0 - resolution: "@oxfmt/binding-darwin-x64@npm:0.61.0" +"@oxfmt/binding-darwin-x64@npm:0.66.0": + version: 0.66.0 + resolution: "@oxfmt/binding-darwin-x64@npm:0.66.0" conditions: os=darwin & cpu=x64 languageName: node linkType: hard -"@oxfmt/binding-freebsd-x64@npm:0.61.0": - version: 0.61.0 - resolution: "@oxfmt/binding-freebsd-x64@npm:0.61.0" +"@oxfmt/binding-freebsd-x64@npm:0.66.0": + version: 0.66.0 + resolution: "@oxfmt/binding-freebsd-x64@npm:0.66.0" conditions: os=freebsd & cpu=x64 languageName: node linkType: hard -"@oxfmt/binding-linux-arm-gnueabihf@npm:0.61.0": - version: 0.61.0 - resolution: "@oxfmt/binding-linux-arm-gnueabihf@npm:0.61.0" +"@oxfmt/binding-linux-arm-gnueabihf@npm:0.66.0": + version: 0.66.0 + resolution: "@oxfmt/binding-linux-arm-gnueabihf@npm:0.66.0" conditions: os=linux & cpu=arm languageName: node linkType: hard -"@oxfmt/binding-linux-arm-musleabihf@npm:0.61.0": - version: 0.61.0 - resolution: "@oxfmt/binding-linux-arm-musleabihf@npm:0.61.0" +"@oxfmt/binding-linux-arm-musleabihf@npm:0.66.0": + version: 0.66.0 + resolution: "@oxfmt/binding-linux-arm-musleabihf@npm:0.66.0" conditions: os=linux & cpu=arm languageName: node linkType: hard -"@oxfmt/binding-linux-arm64-gnu@npm:0.61.0": - version: 0.61.0 - resolution: "@oxfmt/binding-linux-arm64-gnu@npm:0.61.0" +"@oxfmt/binding-linux-arm64-gnu@npm:0.66.0": + version: 0.66.0 + resolution: "@oxfmt/binding-linux-arm64-gnu@npm:0.66.0" conditions: os=linux & cpu=arm64 & libc=glibc languageName: node linkType: hard -"@oxfmt/binding-linux-arm64-musl@npm:0.61.0": - version: 0.61.0 - resolution: "@oxfmt/binding-linux-arm64-musl@npm:0.61.0" +"@oxfmt/binding-linux-arm64-musl@npm:0.66.0": + version: 0.66.0 + resolution: "@oxfmt/binding-linux-arm64-musl@npm:0.66.0" conditions: os=linux & cpu=arm64 & libc=musl languageName: node linkType: hard -"@oxfmt/binding-linux-ppc64-gnu@npm:0.61.0": - version: 0.61.0 - resolution: "@oxfmt/binding-linux-ppc64-gnu@npm:0.61.0" +"@oxfmt/binding-linux-ppc64-gnu@npm:0.66.0": + version: 0.66.0 + resolution: "@oxfmt/binding-linux-ppc64-gnu@npm:0.66.0" conditions: os=linux & cpu=ppc64 & libc=glibc languageName: node linkType: hard -"@oxfmt/binding-linux-riscv64-gnu@npm:0.61.0": - version: 0.61.0 - resolution: "@oxfmt/binding-linux-riscv64-gnu@npm:0.61.0" +"@oxfmt/binding-linux-riscv64-gnu@npm:0.66.0": + version: 0.66.0 + resolution: "@oxfmt/binding-linux-riscv64-gnu@npm:0.66.0" conditions: os=linux & cpu=riscv64 & libc=glibc languageName: node linkType: hard -"@oxfmt/binding-linux-riscv64-musl@npm:0.61.0": - version: 0.61.0 - resolution: "@oxfmt/binding-linux-riscv64-musl@npm:0.61.0" +"@oxfmt/binding-linux-riscv64-musl@npm:0.66.0": + version: 0.66.0 + resolution: "@oxfmt/binding-linux-riscv64-musl@npm:0.66.0" conditions: os=linux & cpu=riscv64 & libc=musl languageName: node linkType: hard -"@oxfmt/binding-linux-s390x-gnu@npm:0.61.0": - version: 0.61.0 - resolution: "@oxfmt/binding-linux-s390x-gnu@npm:0.61.0" +"@oxfmt/binding-linux-s390x-gnu@npm:0.66.0": + version: 0.66.0 + resolution: "@oxfmt/binding-linux-s390x-gnu@npm:0.66.0" conditions: os=linux & cpu=s390x & libc=glibc languageName: node linkType: hard -"@oxfmt/binding-linux-x64-gnu@npm:0.61.0": - version: 0.61.0 - resolution: "@oxfmt/binding-linux-x64-gnu@npm:0.61.0" +"@oxfmt/binding-linux-x64-gnu@npm:0.66.0": + version: 0.66.0 + resolution: "@oxfmt/binding-linux-x64-gnu@npm:0.66.0" conditions: os=linux & cpu=x64 & libc=glibc languageName: node linkType: hard -"@oxfmt/binding-linux-x64-musl@npm:0.61.0": - version: 0.61.0 - resolution: "@oxfmt/binding-linux-x64-musl@npm:0.61.0" +"@oxfmt/binding-linux-x64-musl@npm:0.66.0": + version: 0.66.0 + resolution: "@oxfmt/binding-linux-x64-musl@npm:0.66.0" conditions: os=linux & cpu=x64 & libc=musl languageName: node linkType: hard -"@oxfmt/binding-openharmony-arm64@npm:0.61.0": - version: 0.61.0 - resolution: "@oxfmt/binding-openharmony-arm64@npm:0.61.0" +"@oxfmt/binding-openharmony-arm64@npm:0.66.0": + version: 0.66.0 + resolution: "@oxfmt/binding-openharmony-arm64@npm:0.66.0" conditions: os=openharmony & cpu=arm64 languageName: node linkType: hard -"@oxfmt/binding-win32-arm64-msvc@npm:0.61.0": - version: 0.61.0 - resolution: "@oxfmt/binding-win32-arm64-msvc@npm:0.61.0" +"@oxfmt/binding-win32-arm64-msvc@npm:0.66.0": + version: 0.66.0 + resolution: "@oxfmt/binding-win32-arm64-msvc@npm:0.66.0" conditions: os=win32 & cpu=arm64 languageName: node linkType: hard -"@oxfmt/binding-win32-ia32-msvc@npm:0.61.0": - version: 0.61.0 - resolution: "@oxfmt/binding-win32-ia32-msvc@npm:0.61.0" +"@oxfmt/binding-win32-ia32-msvc@npm:0.66.0": + version: 0.66.0 + resolution: "@oxfmt/binding-win32-ia32-msvc@npm:0.66.0" conditions: os=win32 & cpu=ia32 languageName: node linkType: hard -"@oxfmt/binding-win32-x64-msvc@npm:0.61.0": - version: 0.61.0 - resolution: "@oxfmt/binding-win32-x64-msvc@npm:0.61.0" +"@oxfmt/binding-win32-x64-msvc@npm:0.66.0": + version: 0.66.0 + resolution: "@oxfmt/binding-win32-x64-msvc@npm:0.66.0" conditions: os=win32 & cpu=x64 languageName: node linkType: hard -"@oxlint/binding-android-arm-eabi@npm:1.76.0": - version: 1.76.0 - resolution: "@oxlint/binding-android-arm-eabi@npm:1.76.0" +"@oxlint/binding-android-arm-eabi@npm:1.81.0": + version: 1.81.0 + resolution: "@oxlint/binding-android-arm-eabi@npm:1.81.0" conditions: os=android & cpu=arm languageName: node linkType: hard -"@oxlint/binding-android-arm64@npm:1.76.0": - version: 1.76.0 - resolution: "@oxlint/binding-android-arm64@npm:1.76.0" +"@oxlint/binding-android-arm64@npm:1.81.0": + version: 1.81.0 + resolution: "@oxlint/binding-android-arm64@npm:1.81.0" conditions: os=android & cpu=arm64 languageName: node linkType: hard -"@oxlint/binding-darwin-arm64@npm:1.76.0": - version: 1.76.0 - resolution: "@oxlint/binding-darwin-arm64@npm:1.76.0" +"@oxlint/binding-darwin-arm64@npm:1.81.0": + version: 1.81.0 + resolution: "@oxlint/binding-darwin-arm64@npm:1.81.0" conditions: os=darwin & cpu=arm64 languageName: node linkType: hard -"@oxlint/binding-darwin-x64@npm:1.76.0": - version: 1.76.0 - resolution: "@oxlint/binding-darwin-x64@npm:1.76.0" +"@oxlint/binding-darwin-x64@npm:1.81.0": + version: 1.81.0 + resolution: "@oxlint/binding-darwin-x64@npm:1.81.0" conditions: os=darwin & cpu=x64 languageName: node linkType: hard -"@oxlint/binding-freebsd-x64@npm:1.76.0": - version: 1.76.0 - resolution: "@oxlint/binding-freebsd-x64@npm:1.76.0" +"@oxlint/binding-freebsd-x64@npm:1.81.0": + version: 1.81.0 + resolution: "@oxlint/binding-freebsd-x64@npm:1.81.0" conditions: os=freebsd & cpu=x64 languageName: node linkType: hard -"@oxlint/binding-linux-arm-gnueabihf@npm:1.76.0": - version: 1.76.0 - resolution: "@oxlint/binding-linux-arm-gnueabihf@npm:1.76.0" +"@oxlint/binding-linux-arm-gnueabihf@npm:1.81.0": + version: 1.81.0 + resolution: "@oxlint/binding-linux-arm-gnueabihf@npm:1.81.0" conditions: os=linux & cpu=arm languageName: node linkType: hard -"@oxlint/binding-linux-arm-musleabihf@npm:1.76.0": - version: 1.76.0 - resolution: "@oxlint/binding-linux-arm-musleabihf@npm:1.76.0" +"@oxlint/binding-linux-arm-musleabihf@npm:1.81.0": + version: 1.81.0 + resolution: "@oxlint/binding-linux-arm-musleabihf@npm:1.81.0" conditions: os=linux & cpu=arm languageName: node linkType: hard -"@oxlint/binding-linux-arm64-gnu@npm:1.76.0": - version: 1.76.0 - resolution: "@oxlint/binding-linux-arm64-gnu@npm:1.76.0" +"@oxlint/binding-linux-arm64-gnu@npm:1.81.0": + version: 1.81.0 + resolution: "@oxlint/binding-linux-arm64-gnu@npm:1.81.0" conditions: os=linux & cpu=arm64 & libc=glibc languageName: node linkType: hard -"@oxlint/binding-linux-arm64-musl@npm:1.76.0": - version: 1.76.0 - resolution: "@oxlint/binding-linux-arm64-musl@npm:1.76.0" +"@oxlint/binding-linux-arm64-musl@npm:1.81.0": + version: 1.81.0 + resolution: "@oxlint/binding-linux-arm64-musl@npm:1.81.0" conditions: os=linux & cpu=arm64 & libc=musl languageName: node linkType: hard -"@oxlint/binding-linux-ppc64-gnu@npm:1.76.0": - version: 1.76.0 - resolution: "@oxlint/binding-linux-ppc64-gnu@npm:1.76.0" +"@oxlint/binding-linux-ppc64-gnu@npm:1.81.0": + version: 1.81.0 + resolution: "@oxlint/binding-linux-ppc64-gnu@npm:1.81.0" conditions: os=linux & cpu=ppc64 & libc=glibc languageName: node linkType: hard -"@oxlint/binding-linux-riscv64-gnu@npm:1.76.0": - version: 1.76.0 - resolution: "@oxlint/binding-linux-riscv64-gnu@npm:1.76.0" +"@oxlint/binding-linux-riscv64-gnu@npm:1.81.0": + version: 1.81.0 + resolution: "@oxlint/binding-linux-riscv64-gnu@npm:1.81.0" conditions: os=linux & cpu=riscv64 & libc=glibc languageName: node linkType: hard -"@oxlint/binding-linux-riscv64-musl@npm:1.76.0": - version: 1.76.0 - resolution: "@oxlint/binding-linux-riscv64-musl@npm:1.76.0" +"@oxlint/binding-linux-riscv64-musl@npm:1.81.0": + version: 1.81.0 + resolution: "@oxlint/binding-linux-riscv64-musl@npm:1.81.0" conditions: os=linux & cpu=riscv64 & libc=musl languageName: node linkType: hard -"@oxlint/binding-linux-s390x-gnu@npm:1.76.0": - version: 1.76.0 - resolution: "@oxlint/binding-linux-s390x-gnu@npm:1.76.0" +"@oxlint/binding-linux-s390x-gnu@npm:1.81.0": + version: 1.81.0 + resolution: "@oxlint/binding-linux-s390x-gnu@npm:1.81.0" conditions: os=linux & cpu=s390x & libc=glibc languageName: node linkType: hard -"@oxlint/binding-linux-x64-gnu@npm:1.76.0": - version: 1.76.0 - resolution: "@oxlint/binding-linux-x64-gnu@npm:1.76.0" +"@oxlint/binding-linux-x64-gnu@npm:1.81.0": + version: 1.81.0 + resolution: "@oxlint/binding-linux-x64-gnu@npm:1.81.0" conditions: os=linux & cpu=x64 & libc=glibc languageName: node linkType: hard -"@oxlint/binding-linux-x64-musl@npm:1.76.0": - version: 1.76.0 - resolution: "@oxlint/binding-linux-x64-musl@npm:1.76.0" +"@oxlint/binding-linux-x64-musl@npm:1.81.0": + version: 1.81.0 + resolution: "@oxlint/binding-linux-x64-musl@npm:1.81.0" conditions: os=linux & cpu=x64 & libc=musl languageName: node linkType: hard -"@oxlint/binding-openharmony-arm64@npm:1.76.0": - version: 1.76.0 - resolution: "@oxlint/binding-openharmony-arm64@npm:1.76.0" +"@oxlint/binding-openharmony-arm64@npm:1.81.0": + version: 1.81.0 + resolution: "@oxlint/binding-openharmony-arm64@npm:1.81.0" conditions: os=openharmony & cpu=arm64 languageName: node linkType: hard -"@oxlint/binding-win32-arm64-msvc@npm:1.76.0": - version: 1.76.0 - resolution: "@oxlint/binding-win32-arm64-msvc@npm:1.76.0" +"@oxlint/binding-win32-arm64-msvc@npm:1.81.0": + version: 1.81.0 + resolution: "@oxlint/binding-win32-arm64-msvc@npm:1.81.0" conditions: os=win32 & cpu=arm64 languageName: node linkType: hard -"@oxlint/binding-win32-ia32-msvc@npm:1.76.0": - version: 1.76.0 - resolution: "@oxlint/binding-win32-ia32-msvc@npm:1.76.0" +"@oxlint/binding-win32-ia32-msvc@npm:1.81.0": + version: 1.81.0 + resolution: "@oxlint/binding-win32-ia32-msvc@npm:1.81.0" conditions: os=win32 & cpu=ia32 languageName: node linkType: hard -"@oxlint/binding-win32-x64-msvc@npm:1.76.0": - version: 1.76.0 - resolution: "@oxlint/binding-win32-x64-msvc@npm:1.76.0" +"@oxlint/binding-win32-x64-msvc@npm:1.81.0": + version: 1.81.0 + resolution: "@oxlint/binding-win32-x64-msvc@npm:1.81.0" conditions: os=win32 & cpu=x64 languageName: node linkType: hard @@ -922,100 +922,107 @@ __metadata: languageName: node linkType: hard -"@rolldown/binding-android-arm64@npm:1.2.2": - version: 1.2.2 - resolution: "@rolldown/binding-android-arm64@npm:1.2.2" +"@rolldown/binding-android-arm-eabi@npm:1.2.7": + version: 1.2.7 + resolution: "@rolldown/binding-android-arm-eabi@npm:1.2.7" + conditions: os=android & cpu=arm + languageName: node + linkType: hard + +"@rolldown/binding-android-arm64@npm:1.2.7": + version: 1.2.7 + resolution: "@rolldown/binding-android-arm64@npm:1.2.7" conditions: os=android & cpu=arm64 languageName: node linkType: hard -"@rolldown/binding-darwin-arm64@npm:1.2.2": - version: 1.2.2 - resolution: "@rolldown/binding-darwin-arm64@npm:1.2.2" +"@rolldown/binding-darwin-arm64@npm:1.2.7": + version: 1.2.7 + resolution: "@rolldown/binding-darwin-arm64@npm:1.2.7" conditions: os=darwin & cpu=arm64 languageName: node linkType: hard -"@rolldown/binding-darwin-x64@npm:1.2.2": - version: 1.2.2 - resolution: "@rolldown/binding-darwin-x64@npm:1.2.2" +"@rolldown/binding-darwin-x64@npm:1.2.7": + version: 1.2.7 + resolution: "@rolldown/binding-darwin-x64@npm:1.2.7" conditions: os=darwin & cpu=x64 languageName: node linkType: hard -"@rolldown/binding-freebsd-x64@npm:1.2.2": - version: 1.2.2 - resolution: "@rolldown/binding-freebsd-x64@npm:1.2.2" +"@rolldown/binding-freebsd-x64@npm:1.2.7": + version: 1.2.7 + resolution: "@rolldown/binding-freebsd-x64@npm:1.2.7" conditions: os=freebsd & cpu=x64 languageName: node linkType: hard -"@rolldown/binding-linux-arm-gnueabihf@npm:1.2.2": - version: 1.2.2 - resolution: "@rolldown/binding-linux-arm-gnueabihf@npm:1.2.2" +"@rolldown/binding-linux-arm-gnueabihf@npm:1.2.7": + version: 1.2.7 + resolution: "@rolldown/binding-linux-arm-gnueabihf@npm:1.2.7" conditions: os=linux & cpu=arm languageName: node linkType: hard -"@rolldown/binding-linux-arm64-gnu@npm:1.2.2": - version: 1.2.2 - resolution: "@rolldown/binding-linux-arm64-gnu@npm:1.2.2" +"@rolldown/binding-linux-arm64-gnu@npm:1.2.7": + version: 1.2.7 + resolution: "@rolldown/binding-linux-arm64-gnu@npm:1.2.7" conditions: os=linux & cpu=arm64 & libc=glibc languageName: node linkType: hard -"@rolldown/binding-linux-arm64-musl@npm:1.2.2": - version: 1.2.2 - resolution: "@rolldown/binding-linux-arm64-musl@npm:1.2.2" +"@rolldown/binding-linux-arm64-musl@npm:1.2.7": + version: 1.2.7 + resolution: "@rolldown/binding-linux-arm64-musl@npm:1.2.7" conditions: os=linux & cpu=arm64 & libc=musl languageName: node linkType: hard -"@rolldown/binding-linux-ppc64-gnu@npm:1.2.2": - version: 1.2.2 - resolution: "@rolldown/binding-linux-ppc64-gnu@npm:1.2.2" +"@rolldown/binding-linux-ppc64-gnu@npm:1.2.7": + version: 1.2.7 + resolution: "@rolldown/binding-linux-ppc64-gnu@npm:1.2.7" conditions: os=linux & cpu=ppc64 & libc=glibc languageName: node linkType: hard -"@rolldown/binding-linux-s390x-gnu@npm:1.2.2": - version: 1.2.2 - resolution: "@rolldown/binding-linux-s390x-gnu@npm:1.2.2" +"@rolldown/binding-linux-s390x-gnu@npm:1.2.7": + version: 1.2.7 + resolution: "@rolldown/binding-linux-s390x-gnu@npm:1.2.7" conditions: os=linux & cpu=s390x & libc=glibc languageName: node linkType: hard -"@rolldown/binding-linux-x64-gnu@npm:1.2.2": - version: 1.2.2 - resolution: "@rolldown/binding-linux-x64-gnu@npm:1.2.2" +"@rolldown/binding-linux-x64-gnu@npm:1.2.7": + version: 1.2.7 + resolution: "@rolldown/binding-linux-x64-gnu@npm:1.2.7" conditions: os=linux & cpu=x64 & libc=glibc languageName: node linkType: hard -"@rolldown/binding-linux-x64-musl@npm:1.2.2": - version: 1.2.2 - resolution: "@rolldown/binding-linux-x64-musl@npm:1.2.2" +"@rolldown/binding-linux-x64-musl@npm:1.2.7": + version: 1.2.7 + resolution: "@rolldown/binding-linux-x64-musl@npm:1.2.7" conditions: os=linux & cpu=x64 & libc=musl languageName: node linkType: hard -"@rolldown/binding-openharmony-arm64@npm:1.2.2": - version: 1.2.2 - resolution: "@rolldown/binding-openharmony-arm64@npm:1.2.2" +"@rolldown/binding-openharmony-arm64@npm:1.2.7": + version: 1.2.7 + resolution: "@rolldown/binding-openharmony-arm64@npm:1.2.7" conditions: os=openharmony & cpu=arm64 languageName: node linkType: hard -"@rolldown/binding-win32-arm64-msvc@npm:1.2.2": - version: 1.2.2 - resolution: "@rolldown/binding-win32-arm64-msvc@npm:1.2.2" +"@rolldown/binding-win32-arm64-msvc@npm:1.2.7": + version: 1.2.7 + resolution: "@rolldown/binding-win32-arm64-msvc@npm:1.2.7" conditions: os=win32 & cpu=arm64 languageName: node linkType: hard -"@rolldown/binding-win32-x64-msvc@npm:1.2.2": - version: 1.2.2 - resolution: "@rolldown/binding-win32-x64-msvc@npm:1.2.2" +"@rolldown/binding-win32-x64-msvc@npm:1.2.7": + version: 1.2.7 + resolution: "@rolldown/binding-win32-x64-msvc@npm:1.2.7" conditions: os=win32 & cpu=x64 languageName: node linkType: hard @@ -1027,13 +1034,6 @@ __metadata: languageName: node linkType: hard -"@standard-schema/spec@npm:^1.1.0": - version: 1.1.0 - resolution: "@standard-schema/spec@npm:1.1.0" - checksum: 10c0/d90f55acde4b2deb983529c87e8025fa693de1a5e8b49ecc6eb84d1fd96328add0e03d7d551442156c7432fd78165b2c26ff561b970a9a881f046abb78d6a526 - languageName: node - linkType: hard - "@tybys/wasm-util@npm:^0.10.3": version: 0.10.3 resolution: "@tybys/wasm-util@npm:0.10.3" @@ -1067,12 +1067,12 @@ __metadata: languageName: node linkType: hard -"@types/node@npm:*, @types/node@npm:>=20.0.0, @types/node@npm:^26.1.2": - version: 26.1.2 - resolution: "@types/node@npm:26.1.2" +"@types/node@npm:*, @types/node@npm:>=20.0.0, @types/node@npm:^26.4.1": + version: 26.4.1 + resolution: "@types/node@npm:26.4.1" dependencies: undici-types: "npm:~8.3.0" - checksum: 10c0/a45503222c7db8f374afd5c9381db63dd95b6b1f703abea0890dd3d4a09eeb41da489e08a1a45baf18fe89fb77fbf310ff2789f680c490b04dafc41a60800a86 + checksum: 10c0/29568336db8bc67740744782492af0e81ab1f88d86eaa07e38cf0a4c8bae7250a7b4b85c80ac1014fc98b2bc6d4bcac872b2c494ee0671b3880eada7c1fdbc94 languageName: node linkType: hard @@ -1239,51 +1239,52 @@ __metadata: languageName: node linkType: hard -"@vitest/coverage-v8@npm:^4.1.10": - version: 4.1.10 - resolution: "@vitest/coverage-v8@npm:4.1.10" +"@vitest/coverage-v8@npm:^5.0.0": + version: 5.0.0 + resolution: "@vitest/coverage-v8@npm:5.0.0" dependencies: "@bcoe/v8-coverage": "npm:^1.0.2" - "@vitest/utils": "npm:4.1.10" - ast-v8-to-istanbul: "npm:^1.0.0" - istanbul-lib-coverage: "npm:^3.2.2" - istanbul-lib-report: "npm:^3.0.1" - istanbul-reports: "npm:^3.2.0" - magicast: "npm:^0.5.2" - obug: "npm:^2.1.1" - std-env: "npm:^4.0.0-rc.1" - tinyrainbow: "npm:^3.1.0" + "@vitest/istanbul-lib-coverage": "npm:^1.0.0" + "@vitest/istanbul-lib-report": "npm:^1.0.0" + ast-v8-to-istanbul: "npm:^1.0.5" + magicast: "npm:^0.5.4" + obug: "npm:^2.1.4" + std-env: "npm:^4.2.0" + tinyrainbow: "npm:^3.1.1" peerDependencies: - "@vitest/browser": 4.1.10 - vitest: 4.1.10 + "@vitest/browser": 5.0.0 + vitest: 5.0.0 peerDependenciesMeta: "@vitest/browser": optional: true - checksum: 10c0/f607ab5610ba93ff586d1680bc6d574ee42606ddafd33d5dca14d568e1ff110bf7aea0c82d87b69003b10604d78ccdb535948704e26bbdbfdda6b27edf524486 + checksum: 10c0/6d7f102af8f11f69df21ba343b4d101fbdb39ce5568bd2686c72cdf44e03934889328df297ebe4e12dbe1bc5e0a6d565bb9dfaf2fbca1958bf5e7770c7dc9675 + languageName: node + linkType: hard + +"@vitest/istanbul-lib-coverage@npm:1.0.1, @vitest/istanbul-lib-coverage@npm:^1.0.0": + version: 1.0.1 + resolution: "@vitest/istanbul-lib-coverage@npm:1.0.1" + checksum: 10c0/5259767db6c748a018c39554951e19818268fb6f72f74b74d2370471c7d83df990c3371247caea7d38f8e315df6dd461427dc242a1e7f5071e4b28863524f354 languageName: node linkType: hard -"@vitest/expect@npm:4.1.10": - version: 4.1.10 - resolution: "@vitest/expect@npm:4.1.10" +"@vitest/istanbul-lib-report@npm:^1.0.0": + version: 1.0.1 + resolution: "@vitest/istanbul-lib-report@npm:1.0.1" dependencies: - "@standard-schema/spec": "npm:^1.1.0" - "@types/chai": "npm:^5.2.2" - "@vitest/spy": "npm:4.1.10" - "@vitest/utils": "npm:4.1.10" - chai: "npm:^6.2.2" - tinyrainbow: "npm:^3.1.0" - checksum: 10c0/a817ad0d9bd6a039776a7228d54fb8319c17e4af15917407f5566ac61781a8511f591d302519d6999217399915bc3c0290028189fc73f5c38f80cb01b6f19c8d + "@vitest/istanbul-lib-coverage": "npm:1.0.1" + checksum: 10c0/1a76d4cd4c6284da0b897230d672769a5191235b3a0df41a3c861e3e12659d1790012705df6bad0f540e3f14b7b017f3611f99c9b9eb96972f8b55a3fb9270fe languageName: node linkType: hard -"@vitest/mocker@npm:4.1.10": - version: 4.1.10 - resolution: "@vitest/mocker@npm:4.1.10" +"@vitest/mocker@npm:5.0.0": + version: 5.0.0 + resolution: "@vitest/mocker@npm:5.0.0" dependencies: - "@vitest/spy": "npm:4.1.10" + "@jridgewell/trace-mapping": "npm:0.3.31" + "@vitest/spy": "npm:5.0.0" estree-walker: "npm:^3.0.3" - magic-string: "npm:^0.30.21" + magic-string: "npm:^1.2.3" peerDependencies: msw: ^2.4.9 vite: ^6.0.0 || ^7.0.0 || ^8.0.0 @@ -1292,56 +1293,14 @@ __metadata: optional: true vite: optional: true - checksum: 10c0/4aa70b0df58681652e2e28093437fb2e8f4d02a6d03f5619abc266ac1c5ae5f43326148061d13ae6e071e0f6cfcf7634659af63644de8ce098a7c98949a3d1ad + checksum: 10c0/b1dde0ef270e8f9401204cb19c798114de416c3cf31e1d44d0029c4281b33e9a799251e3015aaaa2bdf5858c97a56857812dcf1e04dcfd4ebeedf194e6bcf3e6 languageName: node linkType: hard -"@vitest/pretty-format@npm:4.1.10": - version: 4.1.10 - resolution: "@vitest/pretty-format@npm:4.1.10" - dependencies: - tinyrainbow: "npm:^3.1.0" - checksum: 10c0/1a5daba730ffe23f2000bff484b4b2842f3b178d93663cb487b215516b8d3b62caa3e2bb2a3c63307b61a9fe58fb9bfff38559bc0c5e49d8aa403d6803a1d918 - languageName: node - linkType: hard - -"@vitest/runner@npm:4.1.10": - version: 4.1.10 - resolution: "@vitest/runner@npm:4.1.10" - dependencies: - "@vitest/utils": "npm:4.1.10" - pathe: "npm:^2.0.3" - checksum: 10c0/554b72639de9694271b99be8ae273fe12ec793093ec91cce143816cd1187d40b7138a4d9d4de4f456cfca9567de986825bff97e107c05b9eb4abc130e854286d - languageName: node - linkType: hard - -"@vitest/snapshot@npm:4.1.10": - version: 4.1.10 - resolution: "@vitest/snapshot@npm:4.1.10" - dependencies: - "@vitest/pretty-format": "npm:4.1.10" - "@vitest/utils": "npm:4.1.10" - magic-string: "npm:^0.30.21" - pathe: "npm:^2.0.3" - checksum: 10c0/e71398725f51af5fd0c07bb4b957d0f987daf9b4c564ac24cb2a4d1afde1a6939f535ac17761a32dcc41b0a1e6d4088af66dc44df89fdebebb92aabed1a92b5f - languageName: node - linkType: hard - -"@vitest/spy@npm:4.1.10": - version: 4.1.10 - resolution: "@vitest/spy@npm:4.1.10" - checksum: 10c0/e5c08012560af6727fd66741c5cda25560d7c5442103d0c83e4276a9b0dd90b9da6cdf823a461195229a16c6ff87768ce788a68d0fa29dea73ee285618668178 - languageName: node - linkType: hard - -"@vitest/utils@npm:4.1.10": - version: 4.1.10 - resolution: "@vitest/utils@npm:4.1.10" - dependencies: - "@vitest/pretty-format": "npm:4.1.10" - convert-source-map: "npm:^2.0.0" - tinyrainbow: "npm:^3.1.0" - checksum: 10c0/05b0ecec6997ec22fc08377e57dbd8fa37992e05961f3a7a916d98b1ab56d15c2a87dbd83d392b628242bdc156b1705e7fa60a3bf0c54bdb51158c153e05fc5d +"@vitest/spy@npm:5.0.0": + version: 5.0.0 + resolution: "@vitest/spy@npm:5.0.0" + checksum: 10c0/7521b4ef803bc89974a738cead7d3fcd789af805f3ea3f496108fc802b2bc09b22fe8e7a3cc0be3f92b647427aea528657e3e87dd0201e432f56e62f84f25ba8 languageName: node linkType: hard @@ -1361,24 +1320,25 @@ __metadata: "@11ty/gray-matter": "npm:^3.0.0" "@changesets/cli": "npm:^2.31.1" "@modelcontextprotocol/sdk": "npm:^1.30.0" - "@types/node": "npm:^26.1.2" - "@vitest/coverage-v8": "npm:^4.1.10" + "@types/node": "npm:^26.4.1" + "@vitest/coverage-v8": "npm:^5.0.0" "@webiny/di": "npm:^1.0.2" adio: "npm:^3.0.1" bson-objectid: "npm:^2.0.4" dot-prop: "npm:^10.2.0" - happy-dom: "npm:^20.11.1" - nanoid: "npm:^6.0.0" + happy-dom: "npm:^20.14.0" + nanoid: "npm:^6.0.1" nanoid-dictionary: "npm:^5.0.0" - oxfmt: "npm:^0.61.0" - oxlint: "npm:^1.76.0" + oxfmt: "npm:^0.66.0" + oxlint: "npm:^1.81.0" pino: "npm:^10.3.1" pino-pretty: "npm:^13.1.3" tinyglobby: "npm:^0.2.17" - type-fest: "npm:^5.8.0" + type-fest: "npm:^5.9.0" typescript: "npm:^7.0.2" - vitest: "npm:^4.1.10" - zod: "npm:^4.4.3" + vite: "npm:^8.2.2" + vitest: "npm:^5.0.0" + zod: "npm:^4.5.4" bin: stdlib-mcp: ./dist/mcp/cli.js languageName: unknown @@ -1485,7 +1445,7 @@ __metadata: languageName: node linkType: hard -"ast-v8-to-istanbul@npm:^1.0.0": +"ast-v8-to-istanbul@npm:^1.0.5": version: 1.0.5 resolution: "ast-v8-to-istanbul@npm:1.0.5" dependencies: @@ -1667,17 +1627,10 @@ __metadata: languageName: node linkType: hard -"content-type@npm:^2.0.0": - version: 2.0.0 - resolution: "content-type@npm:2.0.0" - checksum: 10c0/491539fff707d7594b0ca4fabcc084bef2a31ffa754ff0a4f80c4377e3963cff0394317f9271c24087596c97fa675bc123d61fa34ffe65b4904e7d3d3098de72 - languageName: node - linkType: hard - -"convert-source-map@npm:^2.0.0": - version: 2.0.0 - resolution: "convert-source-map@npm:2.0.0" - checksum: 10c0/8f2f7a27a1a011cc6cc88cc4da2d7d0cfa5ee0369508baae3d98c260bb3ac520691464e5bbe4ae7cdf09860c1d69ecc6f70c63c6e7c7f7e3f18ec08484dc7d9b +"content-type@npm:^2.0.0, content-type@npm:^2.1.0": + version: 2.1.0 + resolution: "content-type@npm:2.1.0" + checksum: 10c0/f5d420f55fd0c7a7f7cbae9637777ce67a074aa79b489d8d9fee8599089592b5f8bb194e1d6885741fee20271034baca0d68d5419535b52d070c4f7e39f4b448 languageName: node linkType: hard @@ -1872,10 +1825,10 @@ __metadata: languageName: node linkType: hard -"es-module-lexer@npm:^2.0.0": - version: 2.3.1 - resolution: "es-module-lexer@npm:2.3.1" - checksum: 10c0/ada8b222772b5b8ea92eb6054c383233207418621855a07b480fdd36979b658a41414be09e793fcdd8a67a182741475f47830a01ff2ebd4353d7f6965c7c45f9 +"es-module-lexer@npm:^2.3.2": + version: 2.3.2 + resolution: "es-module-lexer@npm:2.3.2" + checksum: 10c0/5e7389424c43478439f12f9a6aca1750f6f99afa384fc3de329f4a45f152ab156671055008adaafc74960877abf8cc338aeebf6bed8c21297b146fd6eb7a22f8 languageName: node linkType: hard @@ -1922,9 +1875,9 @@ __metadata: linkType: hard "eventsource-parser@npm:^3.0.0, eventsource-parser@npm:^3.0.1": - version: 3.1.0 - resolution: "eventsource-parser@npm:3.1.0" - checksum: 10c0/5ab4c6c9a2a042be0b387b6d03810eb580bac4ce90e299ede56458125a97ffe3af8145b2740089fc898a96cfa5aae792ee79f2a06257fba2776b0e7bce037071 + version: 3.1.1 + resolution: "eventsource-parser@npm:3.1.1" + checksum: 10c0/dd3236c61140587253dcaaf947de528ac0e7371caffdc53c77afaeee36a17661f00e251a6ea16af56c99be5ac138303e67b5d750630e7c41b02e3564e8ad8c44 languageName: node linkType: hard @@ -1937,7 +1890,7 @@ __metadata: languageName: node linkType: hard -"expect-type@npm:^1.3.0": +"expect-type@npm:^1.4.0": version: 1.4.0 resolution: "expect-type@npm:1.4.0" checksum: 10c0/d40d76b8570695d36587beb3cc28494da2ca3ec8f04e67f5622ed2d372d850e401a9adef19c6835e1a8173903f157c79540b34c7b3fbd7cd8ce726cc903c57b7 @@ -1952,14 +1905,14 @@ __metadata: linkType: hard "express-rate-limit@npm:^8.2.1": - version: 8.6.1 - resolution: "express-rate-limit@npm:8.6.1" + version: 8.7.0 + resolution: "express-rate-limit@npm:8.7.0" dependencies: debug: "npm:^4.4.3" ip-address: "npm:^10.2.0" peerDependencies: express: ">= 4.11" - checksum: 10c0/cb0e30283ef48925d8fe9efce6337a5877bb9a581f32f2594b08303dc075c24f1a52187e403c7f9889888d99eaabd9ac22182d2dadbd0b8acf3725e818131052 + checksum: 10c0/a83aca1af73280e07695bcb989d40835691b3cbec411782ac56a49d20555008acdcfedd8235c2df63ad8fd60288a9e1a73760a10bba3b3a8160b270f417b05b8 languageName: node linkType: hard @@ -2016,9 +1969,9 @@ __metadata: linkType: hard "fast-copy@npm:^4.0.0": - version: 4.0.4 - resolution: "fast-copy@npm:4.0.4" - checksum: 10c0/8c4e0951e46f0ddf1410ae5c3e5b1b37da86cc2db6c2ba603245a74ad7db585061b6ac8ffa9de0d90d779919b5fe2046af760251eddee0e1974df041db057a94 + version: 4.1.1 + resolution: "fast-copy@npm:4.1.1" + checksum: 10c0/e3faed6802b77cad753be49ab4f74d6ef0e39669701a254efc32dca93b40ca399012aae228f2bbd6848c07410d1270fde5729d3dfdaad1625e92853d0570cbe8 languageName: node linkType: hard @@ -2050,18 +2003,18 @@ __metadata: linkType: hard "fast-uri@npm:^3.0.1": - version: 3.1.5 - resolution: "fast-uri@npm:3.1.5" - checksum: 10c0/2bf60eb800dd610c65e17be436425dcb21c92aff3a87d442a8bccab0b7b071e88cf1a5d7d1ea946370b937e6fc0375c405c0296c10587e57de4f78be4646d1d0 + version: 3.1.7 + resolution: "fast-uri@npm:3.1.7" + checksum: 10c0/ca2baa4bde48fc7322bdc692c6636975943ebe4f6dd97e07d70b14e0ab85af2ff30de90f550f5ec2956684fe208e150d85d6cb5f3c74438c8ac1bf86bd435c13 languageName: node linkType: hard "fastq@npm:^1.6.0": - version: 1.20.1 - resolution: "fastq@npm:1.20.1" + version: 1.20.3 + resolution: "fastq@npm:1.20.3" dependencies: reusify: "npm:^1.0.4" - checksum: 10c0/e5dd725884decb1f11e5c822221d76136f239d0236f176fab80b7b8f9e7619ae57e6b4e5b73defc21e6b9ef99437ee7b545cff8e6c2c337819633712fa9d352e + checksum: 10c0/ad055a1b50f7ec9142d2e13699ad6c4d1fa9fea1d947fff89de1b5ea3825223e9a626c359b3a0f21aefbe093cc2a9e92a91e068f982a2b176af16b9ea430ffc5 languageName: node linkType: hard @@ -2258,9 +2211,9 @@ __metadata: languageName: node linkType: hard -"happy-dom@npm:^20.11.1": - version: 20.11.1 - resolution: "happy-dom@npm:20.11.1" +"happy-dom@npm:^20.14.0": + version: 20.14.0 + resolution: "happy-dom@npm:20.14.0" dependencies: "@types/node": "npm:>=20.0.0" "@types/whatwg-mimetype": "npm:^3.0.2" @@ -2269,14 +2222,7 @@ __metadata: entities: "npm:^7.0.1" whatwg-mimetype: "npm:^3.0.0" ws: "npm:^8.21.0" - checksum: 10c0/f2335e8b87f1917c3725051c22dd7dafef13229af0dde9412d146fbaa961713a81ca4dcc741ecef8bf5fb64ea4182e3886305ac93ecb822dec7be028a6f7c51e - languageName: node - linkType: hard - -"has-flag@npm:^4.0.0": - version: 4.0.0 - resolution: "has-flag@npm:4.0.0" - checksum: 10c0/2e789c61b7888d66993e14e8331449e525ef42aac53c627cc53d1c3334e768bcb6abdc4f5f0de1478a25beec6f0bd62c7549058b7ac53e924040d4f301f02fd1 + checksum: 10c0/087522c27a8ad0e95eadd29282cd90ba15fd69b2a8f15f2ac676b6912d8cb9cb6bbfb8d2483d060994fe3f8938647cd925496f585ff742579ae7a6179752a709 languageName: node linkType: hard @@ -2304,16 +2250,9 @@ __metadata: linkType: hard "hono@npm:^4.11.4": - version: 4.12.34 - resolution: "hono@npm:4.12.34" - checksum: 10c0/9d184cb95bc630622d3a8885706feb8e98170556650ce139f09e54c96b9429b3194a296ad4fb0791e7b642a21a03acbf592cb0d19d906ab5e8b78a13337d61bc - languageName: node - linkType: hard - -"html-escaper@npm:^2.0.0": - version: 2.0.2 - resolution: "html-escaper@npm:2.0.2" - checksum: 10c0/208e8a12de1a6569edbb14544f4567e6ce8ecc30b9394fcaa4e7bb1e60c12a7c9a1ed27e31290817157e8626f3a4f29e76c8747030822eb84a6abb15c255f0a0 + version: 4.13.7 + resolution: "hono@npm:4.13.7" + checksum: 10c0/29672a94a4f2be7f3f4d959ad69808dd3bbc220909ca4f9660997022ff45d48ae71e42a460e417d808809d68110196f19359aaab2b14ae6a750331d789601b5a languageName: node linkType: hard @@ -2331,11 +2270,11 @@ __metadata: linkType: hard "human-id@npm:^4.1.1": - version: 4.2.0 - resolution: "human-id@npm:4.2.0" + version: 4.2.1 + resolution: "human-id@npm:4.2.1" bin: human-id: dist/cli.js - checksum: 10c0/80071f3b785b2e91080b5f9aa2d079c2e9a464e009ea12c035255b61d1b70beefe7eda42209dff9c1bb9a9fa58e50ada38c1b314ba3a23266a72cd5e9a453e1f + checksum: 10c0/e7a6f89843fc10c3827d856f862b6b65678de22d97336524ff61ad0ff9414e9c6c8414bbcf7ccb329bdb7651db65666fa84aeac4b48aa3891f3ed8f0178a70c6 languageName: node linkType: hard @@ -2373,9 +2312,9 @@ __metadata: linkType: hard "ip-address@npm:^10.2.0": - version: 10.4.0 - resolution: "ip-address@npm:10.4.0" - checksum: 10c0/d7b0bd2624fd861afbae6e49036a9b56f9506eaff7ff38592b7b4492dd5c272b53f5356dc8cc019e318acf29a96c90a3d1af1df761960267d23efa96858270fa + version: 10.7.0 + resolution: "ip-address@npm:10.7.0" + checksum: 10c0/bb6f514708b84ec75ad4d8156f3d571a5b8e592a15359386100f4f8d7366a4b7723d54b88a30d80b3f51ca5f4dee239e94ef4b53765b9c41a8ea46b421307d14 languageName: node linkType: hard @@ -2460,38 +2399,10 @@ __metadata: languageName: node linkType: hard -"istanbul-lib-coverage@npm:^3.0.0, istanbul-lib-coverage@npm:^3.2.2": - version: 3.2.2 - resolution: "istanbul-lib-coverage@npm:3.2.2" - checksum: 10c0/6c7ff2106769e5f592ded1fb418f9f73b4411fd5a084387a5410538332b6567cd1763ff6b6cadca9b9eb2c443cce2f7ea7d7f1b8d315f9ce58539793b1e0922b - languageName: node - linkType: hard - -"istanbul-lib-report@npm:^3.0.0, istanbul-lib-report@npm:^3.0.1": - version: 3.0.1 - resolution: "istanbul-lib-report@npm:3.0.1" - dependencies: - istanbul-lib-coverage: "npm:^3.0.0" - make-dir: "npm:^4.0.0" - supports-color: "npm:^7.1.0" - checksum: 10c0/84323afb14392de8b6a5714bd7e9af845cfbd56cfe71ed276cda2f5f1201aea673c7111901227ee33e68e4364e288d73861eb2ed48f6679d1e69a43b6d9b3ba7 - languageName: node - linkType: hard - -"istanbul-reports@npm:^3.2.0": - version: 3.2.0 - resolution: "istanbul-reports@npm:3.2.0" - dependencies: - html-escaper: "npm:^2.0.0" - istanbul-lib-report: "npm:^3.0.0" - checksum: 10c0/d596317cfd9c22e1394f22a8d8ba0303d2074fe2e971887b32d870e4b33f8464b10f8ccbe6847808f7db485f084eba09e6c2ed706b3a978e4b52f07085b8f9bc - languageName: node - linkType: hard - "jose@npm:^6.1.3": - version: 6.2.7 - resolution: "jose@npm:6.2.7" - checksum: 10c0/276edc76b4b1c6056e4c4181f3039d659d5ca7e15b971d61b3b65f78b3585ac422c62452a04d6838dbb2e085083a916841b8a75dd29f28e7c281a875a2587e67 + version: 6.2.12 + resolution: "jose@npm:6.2.12" + checksum: 10c0/e8582b946fabcae228819982dda4849908c353e9cb098f02f773635aa0d2f4917f17484c7441b8d526e564013b4cf96951455c94f81d0a39ee765bad44ce293d languageName: node linkType: hard @@ -2517,36 +2428,36 @@ __metadata: linkType: hard "js-yaml@npm:^3.6.1": - version: 3.15.1 - resolution: "js-yaml@npm:3.15.1" + version: 3.15.2 + resolution: "js-yaml@npm:3.15.2" dependencies: argparse: "npm:^1.0.7" esprima: "npm:^4.0.0" bin: js-yaml: bin/js-yaml.js - checksum: 10c0/6c693b8c59ffe12021df3b36994b090df19d920826dd810baab81652b40861e1974509dd11fe92225ab4c00cc14de053300c94db015c2c0e211edea39b118737 + checksum: 10c0/e341df211dece9d4b784849647ad7568b5b6a58a9ee58ead750482316d83276387343649fe4b71522705dc6c76acf97718588f23dc19443833ef3e75033af967 languageName: node linkType: hard "js-yaml@npm:^4.1.0, js-yaml@npm:^4.1.1": - version: 4.3.1 - resolution: "js-yaml@npm:4.3.1" + version: 4.3.2 + resolution: "js-yaml@npm:4.3.2" dependencies: argparse: "npm:^2.0.1" bin: js-yaml: bin/js-yaml.js - checksum: 10c0/13c500ca322e0c3f8c81686e6ecda96d2ea37b45247a420c17c7db36932d6965cc27391abc2d1a104501600e7f0d947a5f8b7be6db619c4fefa87901b3512807 + checksum: 10c0/dedd34c2e8fef1d504687f1bc94ed0ee1311a1f78770fa2800352c6d59c635ccf555009d74e9afe529ae62199da2b1ccef30e53dc84dcd8d2d8187c22574bc97 languageName: node linkType: hard "js-yaml@npm:^5.2.2": - version: 5.2.3 - resolution: "js-yaml@npm:5.2.3" + version: 5.4.1 + resolution: "js-yaml@npm:5.4.1" dependencies: argparse: "npm:^2.0.1" bin: js-yaml: bin/js-yaml.mjs - checksum: 10c0/55cd6310c8eee88d432ae038d451ac9d6aa0eb9e5d38a94df3d6c4a4015d08c9dad7c18669e0e8854e4173a615d6b6b7448bd0aac408773f8a46122ffd863c69 + checksum: 10c0/efe9dfaf222809694d375ad5ecca825561d2432eb55bc0f628911c0dfa4dbce98a71dcbc3252f630208bbdf5f4e9ac363847e4a7f49845b577ae2548b8fcf147 languageName: node linkType: hard @@ -2740,16 +2651,16 @@ __metadata: languageName: node linkType: hard -"magic-string@npm:^0.30.21": - version: 0.30.21 - resolution: "magic-string@npm:0.30.21" +"magic-string@npm:^1.2.3": + version: 1.2.3 + resolution: "magic-string@npm:1.2.3" dependencies: "@jridgewell/sourcemap-codec": "npm:^1.5.5" - checksum: 10c0/299378e38f9a270069fc62358522ddfb44e94244baa0d6a8980ab2a9b2490a1d03b236b447eee309e17eb3bddfa482c61259d47960eb018a904f0ded52780c4a + checksum: 10c0/541ecb30ec96e4d9b76ca65aed00124592dca26739aeee86e01d7fbce227b3fce43c9d2f0b9495dc9077c30794c967b1e091445614e2e45722ea4c128be60a93 languageName: node linkType: hard -"magicast@npm:^0.5.2": +"magicast@npm:^0.5.4": version: 0.5.4 resolution: "magicast@npm:0.5.4" dependencies: @@ -2760,15 +2671,6 @@ __metadata: languageName: node linkType: hard -"make-dir@npm:^4.0.0": - version: 4.0.0 - resolution: "make-dir@npm:4.0.0" - dependencies: - semver: "npm:^7.5.3" - checksum: 10c0/69b98a6c0b8e5c4fe9acb61608a9fbcfca1756d910f51e5dbe7a9e5cfb74fca9b8a0c8a0ffdf1294a740826c1ab4871d5bf3f62f72a3049e5eac6541ddffed68 - languageName: node - linkType: hard - "math-intrinsics@npm:^1.1.0": version: 1.1.0 resolution: "math-intrinsics@npm:1.1.0" @@ -2876,34 +2778,36 @@ __metadata: languageName: node linkType: hard -"nanoid@npm:^3.3.16": - version: 3.3.17 - resolution: "nanoid@npm:3.3.17" +"nanoid@npm:^3.3.18": + version: 3.3.18 + resolution: "nanoid@npm:3.3.18" bin: nanoid: bin/nanoid.cjs - checksum: 10c0/06f7949c7cce5c92c6aea66022f29a1eae7f56e05acbfddf1e049e819b4bf234c44a765cc44da7163482b111677948514012e27acdfa56f95309295768bdae32 + checksum: 10c0/b994b4e396730f8be2520923284e2040d61eaee55cc6d4935ef6d38d34bafdc46133eda4d3faea5073bda545aa6079d82b886caeac5c731cf9ac18bcc1301425 languageName: node linkType: hard -"nanoid@npm:^6.0.0": - version: 6.0.0 - resolution: "nanoid@npm:6.0.0" +"nanoid@npm:^6.0.1": + version: 6.0.1 + resolution: "nanoid@npm:6.0.1" bin: nanoid: bin/nanoid.js - checksum: 10c0/45bc79b7fc3f8f7110986fee7ac8acc2dc673b4c9ebe0c28a05fd0b2c2bb7a0b9942e43a558e39ea3c41a7fb74c7de1a0f8b73263b025f82e87cdb4a769188c3 + checksum: 10c0/5b362ad9822388dfebdf655849c76d3539e074d1003fbe6eb5dff8687faf93a9abbb19bdc5d134b9b8599f875f9b091feacfd7099b34b5fef23bc3f5be41dd10 languageName: node linkType: hard "negotiator@npm:^1.0.0": - version: 1.0.0 - resolution: "negotiator@npm:1.0.0" - checksum: 10c0/4c559dd52669ea48e1914f9d634227c561221dd54734070791f999c52ed0ff36e437b2e07d5c1f6e32909fc625fe46491c16e4a8f0572567d4dd15c3a4fda04b + version: 1.1.0 + resolution: "negotiator@npm:1.1.0" + dependencies: + content-type: "npm:^2.1.0" + checksum: 10c0/656fa57de02f1a0c4c09f9e17eb78e8182547c07093e810ff8f16249b6ae31f2c546a3d457905e94f3276b25f0e2741ea1a3bc3912192932ed7e493adfea535e languageName: node linkType: hard "node-gyp@npm:latest": - version: 13.0.1 - resolution: "node-gyp@npm:13.0.1" + version: 13.0.2 + resolution: "node-gyp@npm:13.0.2" dependencies: env-paths: "npm:^2.2.0" exponential-backoff: "npm:^3.1.1" @@ -2917,7 +2821,7 @@ __metadata: which: "npm:^7.0.0" bin: node-gyp: bin/node-gyp.js - checksum: 10c0/424077bc9e9bbe953a8e86db473ba818cbc6a121714008c977fd589e21e5f0c811fbf22faac730dc7182450b5e52df301811d01ae3373898658d999b7710f4e6 + checksum: 10c0/29d33ccf47ffeeb5e7af925550b416f698a26a72eb10975c7eb5775c1d0cecacd76d164a4aa45503d3ddcece209db65c712be00423c69381a4cd14e2e6540559 languageName: node linkType: hard @@ -2946,7 +2850,7 @@ __metadata: languageName: node linkType: hard -"obug@npm:^2.1.1": +"obug@npm:^2.1.4": version: 2.1.4 resolution: "obug@npm:2.1.4" checksum: 10c0/34a0ee97cd88573cfd97d384c2a79f07118ae5680d7e45d1de6e99c74eddefe145e8ca27a2db02195a1ee5fded5aa22b924869c842728c201b9f109a27d0ef19 @@ -3055,29 +2959,29 @@ __metadata: languageName: node linkType: hard -"oxfmt@npm:^0.61.0": - version: 0.61.0 - resolution: "oxfmt@npm:0.61.0" - dependencies: - "@oxfmt/binding-android-arm-eabi": "npm:0.61.0" - "@oxfmt/binding-android-arm64": "npm:0.61.0" - "@oxfmt/binding-darwin-arm64": "npm:0.61.0" - "@oxfmt/binding-darwin-x64": "npm:0.61.0" - "@oxfmt/binding-freebsd-x64": "npm:0.61.0" - "@oxfmt/binding-linux-arm-gnueabihf": "npm:0.61.0" - "@oxfmt/binding-linux-arm-musleabihf": "npm:0.61.0" - "@oxfmt/binding-linux-arm64-gnu": "npm:0.61.0" - "@oxfmt/binding-linux-arm64-musl": "npm:0.61.0" - "@oxfmt/binding-linux-ppc64-gnu": "npm:0.61.0" - "@oxfmt/binding-linux-riscv64-gnu": "npm:0.61.0" - "@oxfmt/binding-linux-riscv64-musl": "npm:0.61.0" - "@oxfmt/binding-linux-s390x-gnu": "npm:0.61.0" - "@oxfmt/binding-linux-x64-gnu": "npm:0.61.0" - "@oxfmt/binding-linux-x64-musl": "npm:0.61.0" - "@oxfmt/binding-openharmony-arm64": "npm:0.61.0" - "@oxfmt/binding-win32-arm64-msvc": "npm:0.61.0" - "@oxfmt/binding-win32-ia32-msvc": "npm:0.61.0" - "@oxfmt/binding-win32-x64-msvc": "npm:0.61.0" +"oxfmt@npm:^0.66.0": + version: 0.66.0 + resolution: "oxfmt@npm:0.66.0" + dependencies: + "@oxfmt/binding-android-arm-eabi": "npm:0.66.0" + "@oxfmt/binding-android-arm64": "npm:0.66.0" + "@oxfmt/binding-darwin-arm64": "npm:0.66.0" + "@oxfmt/binding-darwin-x64": "npm:0.66.0" + "@oxfmt/binding-freebsd-x64": "npm:0.66.0" + "@oxfmt/binding-linux-arm-gnueabihf": "npm:0.66.0" + "@oxfmt/binding-linux-arm-musleabihf": "npm:0.66.0" + "@oxfmt/binding-linux-arm64-gnu": "npm:0.66.0" + "@oxfmt/binding-linux-arm64-musl": "npm:0.66.0" + "@oxfmt/binding-linux-ppc64-gnu": "npm:0.66.0" + "@oxfmt/binding-linux-riscv64-gnu": "npm:0.66.0" + "@oxfmt/binding-linux-riscv64-musl": "npm:0.66.0" + "@oxfmt/binding-linux-s390x-gnu": "npm:0.66.0" + "@oxfmt/binding-linux-x64-gnu": "npm:0.66.0" + "@oxfmt/binding-linux-x64-musl": "npm:0.66.0" + "@oxfmt/binding-openharmony-arm64": "npm:0.66.0" + "@oxfmt/binding-win32-arm64-msvc": "npm:0.66.0" + "@oxfmt/binding-win32-ia32-msvc": "npm:0.66.0" + "@oxfmt/binding-win32-x64-msvc": "npm:0.66.0" tinypool: "npm:2.1.0" peerDependencies: svelte: ^5.0.0 @@ -3128,33 +3032,33 @@ __metadata: optional: true bin: oxfmt: bin/oxfmt - checksum: 10c0/619e28af6c63cd1c0dedfb2da1c27557507e67ebad32479d237036b6a278e801fccb48bcc9b388b8db40f7b5918834580573e0e1f1d268ef7c865b7f3a61a67e - languageName: node - linkType: hard - -"oxlint@npm:^1.76.0": - version: 1.76.0 - resolution: "oxlint@npm:1.76.0" - dependencies: - "@oxlint/binding-android-arm-eabi": "npm:1.76.0" - "@oxlint/binding-android-arm64": "npm:1.76.0" - "@oxlint/binding-darwin-arm64": "npm:1.76.0" - "@oxlint/binding-darwin-x64": "npm:1.76.0" - "@oxlint/binding-freebsd-x64": "npm:1.76.0" - "@oxlint/binding-linux-arm-gnueabihf": "npm:1.76.0" - "@oxlint/binding-linux-arm-musleabihf": "npm:1.76.0" - "@oxlint/binding-linux-arm64-gnu": "npm:1.76.0" - "@oxlint/binding-linux-arm64-musl": "npm:1.76.0" - "@oxlint/binding-linux-ppc64-gnu": "npm:1.76.0" - "@oxlint/binding-linux-riscv64-gnu": "npm:1.76.0" - "@oxlint/binding-linux-riscv64-musl": "npm:1.76.0" - "@oxlint/binding-linux-s390x-gnu": "npm:1.76.0" - "@oxlint/binding-linux-x64-gnu": "npm:1.76.0" - "@oxlint/binding-linux-x64-musl": "npm:1.76.0" - "@oxlint/binding-openharmony-arm64": "npm:1.76.0" - "@oxlint/binding-win32-arm64-msvc": "npm:1.76.0" - "@oxlint/binding-win32-ia32-msvc": "npm:1.76.0" - "@oxlint/binding-win32-x64-msvc": "npm:1.76.0" + checksum: 10c0/add0d810b6bd62ecf7da74479d65e9f44e490ce4ed79670bdb80a3e0ecc7611192c92f3692790929003d2f8bead6d45b8457211cc3ba01e27af693233702189e + languageName: node + linkType: hard + +"oxlint@npm:^1.81.0": + version: 1.81.0 + resolution: "oxlint@npm:1.81.0" + dependencies: + "@oxlint/binding-android-arm-eabi": "npm:1.81.0" + "@oxlint/binding-android-arm64": "npm:1.81.0" + "@oxlint/binding-darwin-arm64": "npm:1.81.0" + "@oxlint/binding-darwin-x64": "npm:1.81.0" + "@oxlint/binding-freebsd-x64": "npm:1.81.0" + "@oxlint/binding-linux-arm-gnueabihf": "npm:1.81.0" + "@oxlint/binding-linux-arm-musleabihf": "npm:1.81.0" + "@oxlint/binding-linux-arm64-gnu": "npm:1.81.0" + "@oxlint/binding-linux-arm64-musl": "npm:1.81.0" + "@oxlint/binding-linux-ppc64-gnu": "npm:1.81.0" + "@oxlint/binding-linux-riscv64-gnu": "npm:1.81.0" + "@oxlint/binding-linux-riscv64-musl": "npm:1.81.0" + "@oxlint/binding-linux-s390x-gnu": "npm:1.81.0" + "@oxlint/binding-linux-x64-gnu": "npm:1.81.0" + "@oxlint/binding-linux-x64-musl": "npm:1.81.0" + "@oxlint/binding-openharmony-arm64": "npm:1.81.0" + "@oxlint/binding-win32-arm64-msvc": "npm:1.81.0" + "@oxlint/binding-win32-ia32-msvc": "npm:1.81.0" + "@oxlint/binding-win32-x64-msvc": "npm:1.81.0" peerDependencies: oxlint-tsgolint: ">=7.0.2001" vite-plus: "*" @@ -3204,7 +3108,7 @@ __metadata: optional: true bin: oxlint: bin/oxlint - checksum: 10c0/1ac237eee14e7ff9fc8cfb5f506ed2da0171027e567031c117613e035d98390a8cbefc211f1e63400a24ecfa10ba8555ae3688ce08773bbeb6425a165f5c4120 + checksum: 10c0/547027fc2dae81851b61819886f36d95a694a12c457e0b740708756005da23602fbbb9579ea133341f3a45656e7d0821a042423e26267be5a1630492a88e8691 languageName: node linkType: hard @@ -3324,13 +3228,6 @@ __metadata: languageName: node linkType: hard -"pathe@npm:^2.0.3": - version: 2.0.3 - resolution: "pathe@npm:2.0.3" - checksum: 10c0/c118dc5a8b5c4166011b2b70608762e260085180bb9e33e80a50dcdb1e78c010b1624f4280c492c92b05fc276715a4c357d1f9edc570f8f1b3d90b6839ebaca1 - languageName: node - linkType: hard - "picocolors@npm:^1.1.0, picocolors@npm:^1.1.1": version: 1.1.1 resolution: "picocolors@npm:1.1.1" @@ -3345,10 +3242,10 @@ __metadata: languageName: node linkType: hard -"picomatch@npm:^4.0.3, picomatch@npm:^4.0.4, picomatch@npm:^4.0.5": - version: 4.0.5 - resolution: "picomatch@npm:4.0.5" - checksum: 10c0/947bc6b6e1ff1e6c5aaf95b107a0839d12802f4f7b867663f67d47accba939ca1cb582cf99dfc30438efa1c4648ac5990967e783e8929c36b03e8440704ef1bd +"picomatch@npm:^4.0.4, picomatch@npm:^4.0.5, picomatch@npm:^4.0.7": + version: 4.0.7 + resolution: "picomatch@npm:4.0.7" + checksum: 10c0/beb6ae02c43ae44e84883b90830196d9046b1726ead292adcf7f57945e0bb0d992d68563d87e03b484b6f3c9a5c6defda7523477f047d7f0e663f126cc01787f languageName: node linkType: hard @@ -3426,14 +3323,14 @@ __metadata: languageName: node linkType: hard -"postcss@npm:^8.5.23": - version: 8.5.25 - resolution: "postcss@npm:8.5.25" +"postcss@npm:^8.5.26": + version: 8.5.28 + resolution: "postcss@npm:8.5.28" dependencies: - nanoid: "npm:^3.3.16" + nanoid: "npm:^3.3.18" picocolors: "npm:^1.1.1" source-map-js: "npm:^1.2.1" - checksum: 10c0/0a12c1e74b456c57122e81f684e02fd98ff4d57526f794d10c996df1147158808f5ae373ac82b988c8de6cbbaa82dbd7b13803b14f5dd3cf7cc6a42ccad5c9f2 + checksum: 10c0/9fe44215a6628d89c8a75184b92f5b2f77e16f9e5b13b39b9009bb7e8e6eccddf82c8854bae922db1f17ace6ef3445073fe38abff513caeb03e5285b1b55620a languageName: node linkType: hard @@ -3481,12 +3378,12 @@ __metadata: linkType: hard "qs@npm:^6.14.0, qs@npm:^6.15.2": - version: 6.15.3 - resolution: "qs@npm:6.15.3" + version: 6.16.0 + resolution: "qs@npm:6.16.0" dependencies: es-define-property: "npm:^1.0.1" side-channel: "npm:^1.1.1" - checksum: 10c0/8f3f6e45ece255347d57696628401cde29e9ec649fff698b53bd3150dea7cefdf33036e1bc1826b9f110bfa7cb0ec4ab9f5297eca628ce216c55af82c304e08e + checksum: 10c0/eb3e31992fbd70e31a1791e571ed817d70975de7d3bfcbbbec93d77d1dd305877e9e8fdbcc62303c228ee5c3606685622cd6231c042dbc4790bb4e7c65fcbe18 languageName: node linkType: hard @@ -3591,27 +3488,30 @@ __metadata: languageName: node linkType: hard -"rolldown@npm:~1.2.0": - version: 1.2.2 - resolution: "rolldown@npm:1.2.2" - dependencies: - "@oxc-project/types": "npm:=0.142.0" - "@rolldown/binding-android-arm64": "npm:1.2.2" - "@rolldown/binding-darwin-arm64": "npm:1.2.2" - "@rolldown/binding-darwin-x64": "npm:1.2.2" - "@rolldown/binding-freebsd-x64": "npm:1.2.2" - "@rolldown/binding-linux-arm-gnueabihf": "npm:1.2.2" - "@rolldown/binding-linux-arm64-gnu": "npm:1.2.2" - "@rolldown/binding-linux-arm64-musl": "npm:1.2.2" - "@rolldown/binding-linux-ppc64-gnu": "npm:1.2.2" - "@rolldown/binding-linux-s390x-gnu": "npm:1.2.2" - "@rolldown/binding-linux-x64-gnu": "npm:1.2.2" - "@rolldown/binding-linux-x64-musl": "npm:1.2.2" - "@rolldown/binding-openharmony-arm64": "npm:1.2.2" - "@rolldown/binding-win32-arm64-msvc": "npm:1.2.2" - "@rolldown/binding-win32-x64-msvc": "npm:1.2.2" +"rolldown@npm:~1.2.4": + version: 1.2.7 + resolution: "rolldown@npm:1.2.7" + dependencies: + "@oxc-project/types": "npm:=0.148.0" + "@rolldown/binding-android-arm-eabi": "npm:1.2.7" + "@rolldown/binding-android-arm64": "npm:1.2.7" + "@rolldown/binding-darwin-arm64": "npm:1.2.7" + "@rolldown/binding-darwin-x64": "npm:1.2.7" + "@rolldown/binding-freebsd-x64": "npm:1.2.7" + "@rolldown/binding-linux-arm-gnueabihf": "npm:1.2.7" + "@rolldown/binding-linux-arm64-gnu": "npm:1.2.7" + "@rolldown/binding-linux-arm64-musl": "npm:1.2.7" + "@rolldown/binding-linux-ppc64-gnu": "npm:1.2.7" + "@rolldown/binding-linux-s390x-gnu": "npm:1.2.7" + "@rolldown/binding-linux-x64-gnu": "npm:1.2.7" + "@rolldown/binding-linux-x64-musl": "npm:1.2.7" + "@rolldown/binding-openharmony-arm64": "npm:1.2.7" + "@rolldown/binding-win32-arm64-msvc": "npm:1.2.7" + "@rolldown/binding-win32-x64-msvc": "npm:1.2.7" "@rolldown/pluginutils": "npm:^1.0.0" dependenciesMeta: + "@rolldown/binding-android-arm-eabi": + optional: true "@rolldown/binding-android-arm64": optional: true "@rolldown/binding-darwin-arm64": @@ -3642,7 +3542,7 @@ __metadata: optional: true bin: rolldown: ./bin/cli.mjs - checksum: 10c0/78a804b9d0947d0569aac5f78ae789b107d097ef94df2ee04b0d89621ca0b62f5336037e6fc1e24209ece2f1d7cbf0d66b27db10b8022684eaf5bea89b9aa97e + checksum: 10c0/e3b73addf51981d8b8430990ff59c14197994cfe9e1aae443dce47d353b409e7ffd478946185a15769588ab2e3d504557319fd58ab650ac9ac37c299384da10a languageName: node linkType: hard @@ -3885,7 +3785,7 @@ __metadata: languageName: node linkType: hard -"std-env@npm:^4.0.0-rc.1": +"std-env@npm:^4.2.0": version: 4.2.0 resolution: "std-env@npm:4.2.0" checksum: 10c0/40ac525ce7b7c556abc332a7376f14356eeb1a7f17f6ff9a003eb9f52326ff1f3745d3e1b43452675b1ec6fcc319f1b1d6f3b0d386cf3f91058479ad883cff69 @@ -3915,15 +3815,6 @@ __metadata: languageName: node linkType: hard -"supports-color@npm:^7.1.0": - version: 7.2.0 - resolution: "supports-color@npm:7.2.0" - dependencies: - has-flag: "npm:^4.0.0" - checksum: 10c0/afb4c88521b8b136b5f5f95160c98dee7243dc79d5432db7efc27efb219385bbc7d9427398e43dd6cc730a0f87d5085ce1652af7efbe391327bc0a7d0f7fc124 - languageName: node - linkType: hard - "tagged-tag@npm:^1.0.0": version: 1.0.0 resolution: "tagged-tag@npm:1.0.0" @@ -3960,21 +3851,21 @@ __metadata: languageName: node linkType: hard -"tinybench@npm:^2.9.0": - version: 2.9.0 - resolution: "tinybench@npm:2.9.0" - checksum: 10c0/c3500b0f60d2eb8db65250afe750b66d51623057ee88720b7f064894a6cb7eb93360ca824a60a31ab16dab30c7b1f06efe0795b352e37914a9d4bad86386a20c +"tinybench@npm:6.1.4": + version: 6.1.4 + resolution: "tinybench@npm:6.1.4" + checksum: 10c0/7a815318a02270a98247298ddd289b75c841725606c977f0b74749bc5ec811a44998267ccb60bd3deb23b551dbfaf4d979eb08e9b04fbc87ff571f9b39cc61c3 languageName: node linkType: hard -"tinyexec@npm:^1.0.2": +"tinyexec@npm:1.3.0": version: 1.3.0 resolution: "tinyexec@npm:1.3.0" checksum: 10c0/e9b89f97489d2aab2cef408da279e6b32547e738d1275032ccb8fd0028a006d93eb70fc51c6cffd9fc2f5aca6c2a273d8b6f73b52d46ee5116da6b94969ef958 languageName: node linkType: hard -"tinyglobby@npm:^0.2.12, tinyglobby@npm:^0.2.15, tinyglobby@npm:^0.2.17": +"tinyglobby@npm:^0.2.12, tinyglobby@npm:^0.2.17": version: 0.2.17 resolution: "tinyglobby@npm:0.2.17" dependencies: @@ -3991,7 +3882,7 @@ __metadata: languageName: node linkType: hard -"tinyrainbow@npm:^3.1.0": +"tinyrainbow@npm:^3.1.1": version: 3.1.1 resolution: "tinyrainbow@npm:3.1.1" checksum: 10c0/f9d2743832c6191f753408f36224fe817620b8abcef572b2e570204c673a901d753ff84ca8e7b88f9c79e934295b3ffc6fcbc56a06f126e24e1ec6186dcad40d @@ -4021,12 +3912,12 @@ __metadata: languageName: node linkType: hard -"type-fest@npm:^5.0.0, type-fest@npm:^5.8.0": - version: 5.8.0 - resolution: "type-fest@npm:5.8.0" +"type-fest@npm:^5.0.0, type-fest@npm:^5.9.0": + version: 5.9.0 + resolution: "type-fest@npm:5.9.0" dependencies: tagged-tag: "npm:^1.0.0" - checksum: 10c0/c8aae118a763d550a9552a511dff6b71840a23dab4edf693cf1c4df22596942794e6f6723389bd9036a90182249d915158bacf0815a1ae87f05f901b1d5f574e + checksum: 10c0/9bf14a49454b9b40d9fe85e563a4cf90990bbe7c75958665b72660b4197a905f247be682a7757cac7c8fa60fc0eae32cc8cf51f80a88e15f0a3d4a8ec07eb5b6 languageName: node linkType: hard @@ -4191,9 +4082,9 @@ __metadata: linkType: hard "undici@npm:^8.4.1": - version: 8.9.0 - resolution: "undici@npm:8.9.0" - checksum: 10c0/e3d9fa35a9aa8360d9f56e66bd372f451ee053e25066a97fd9fab3816267035660f67870c6d709a58a5411551657af78c4475be5b31c113b04f70251309900d0 + version: 8.10.2 + resolution: "undici@npm:8.10.2" + checksum: 10c0/66d7fc69149207cab570d6abbc9e965b6afe1ae889a7d46945b431165c973d6a56f3dd8b70a856e7ae1e550b6366a1cde6f06e68640587f0dadca38de72995ee languageName: node linkType: hard @@ -4218,19 +4109,19 @@ __metadata: languageName: node linkType: hard -"vite@npm:^6.0.0 || ^7.0.0 || ^8.0.0": - version: 8.2.0 - resolution: "vite@npm:8.2.0" +"vite@npm:^8.2.2": + version: 8.2.2 + resolution: "vite@npm:8.2.2" dependencies: fsevents: "npm:~2.3.3" lightningcss: "npm:^1.33.0" picomatch: "npm:^4.0.5" - postcss: "npm:^8.5.23" - rolldown: "npm:~1.2.0" + postcss: "npm:^8.5.26" + rolldown: "npm:~1.2.4" tinyglobby: "npm:^0.2.17" peerDependencies: "@types/node": ^20.19.0 || >=22.12.0 - "@vitejs/devtools": ^0.4.0 + "@vitejs/devtools": ^0.4.0 || ^0.5.0 esbuild: ^0.27.0 || ^0.28.0 jiti: ">=1.21.0" less: ^4.0.0 @@ -4271,47 +4162,40 @@ __metadata: optional: true bin: vite: bin/vite.js - checksum: 10c0/bd6a5e7b28973bac06f0e8e54833800e16d1bf38a8aef2acbfea5bbaed6d8fc715fd7cc9b0ec75ef1adbde149bb9167b085c17fe7edcd3a190b4eda16d474e5c - languageName: node - linkType: hard - -"vitest@npm:^4.1.10": - version: 4.1.10 - resolution: "vitest@npm:4.1.10" - dependencies: - "@vitest/expect": "npm:4.1.10" - "@vitest/mocker": "npm:4.1.10" - "@vitest/pretty-format": "npm:4.1.10" - "@vitest/runner": "npm:4.1.10" - "@vitest/snapshot": "npm:4.1.10" - "@vitest/spy": "npm:4.1.10" - "@vitest/utils": "npm:4.1.10" - es-module-lexer: "npm:^2.0.0" - expect-type: "npm:^1.3.0" - magic-string: "npm:^0.30.21" - obug: "npm:^2.1.1" - pathe: "npm:^2.0.3" - picomatch: "npm:^4.0.3" - std-env: "npm:^4.0.0-rc.1" - tinybench: "npm:^2.9.0" - tinyexec: "npm:^1.0.2" - tinyglobby: "npm:^0.2.15" - tinyrainbow: "npm:^3.1.0" - vite: "npm:^6.0.0 || ^7.0.0 || ^8.0.0" + checksum: 10c0/94cbbbdc38ad500dcb86b6202ddd14aa41d05c80739766cada9bbe250b410d1a27be433c9c491ed39744019471ac1e27a59908616a88c42f9787bdb6bdca49d2 + languageName: node + linkType: hard + +"vitest@npm:^5.0.0": + version: 5.0.0 + resolution: "vitest@npm:5.0.0" + dependencies: + "@types/chai": "npm:^5.2.2" + "@vitest/mocker": "npm:5.0.0" + chai: "npm:^6.2.2" + es-module-lexer: "npm:^2.3.2" + expect-type: "npm:^1.4.0" + magic-string: "npm:^1.2.3" + obug: "npm:^2.1.4" + picomatch: "npm:^4.0.7" + std-env: "npm:^4.2.0" + tinybench: "npm:6.1.4" + tinyexec: "npm:1.3.0" + tinyglobby: "npm:^0.2.17" why-is-node-running: "npm:^2.3.0" peerDependencies: "@edge-runtime/vm": "*" "@opentelemetry/api": ^1.9.0 - "@types/node": ^20.0.0 || ^22.0.0 || >=24.0.0 - "@vitest/browser-playwright": 4.1.10 - "@vitest/browser-preview": 4.1.10 - "@vitest/browser-webdriverio": 4.1.10 - "@vitest/coverage-istanbul": 4.1.10 - "@vitest/coverage-v8": 4.1.10 - "@vitest/ui": 4.1.10 + "@types/node": ^22.0.0 || >=24.0.0 + "@vitest/browser-playwright": 5.0.0 + "@vitest/browser-preview": 5.0.0 + "@vitest/browser-webdriverio": ^5.0.0-beta.5 || >=5.0.0 + "@vitest/coverage-istanbul": 5.0.0 + "@vitest/coverage-v8": 5.0.0 + "@vitest/ui": 5.0.0 happy-dom: "*" jsdom: "*" - vite: ^6.0.0 || ^7.0.0 || ^8.0.0 + vite: ^6.4.0 || ^7.0.0 || ^8.0.0 peerDependenciesMeta: "@edge-runtime/vm": optional: true @@ -4339,7 +4223,7 @@ __metadata: optional: false bin: vitest: ./vitest.mjs - checksum: 10c0/ff07294a57f9c62f3b503f7cf88a52ee0753ed26389a49cda430387a3898f39d80af47180b0af19e27acab5bd11ae95706bd4b44ce8befc97d3ae49af6ca4fc1 + checksum: 10c0/de56a0f2e989949e42cdf31150ef5c0c138c04950d14b158f618f8bd4dc9b7f1e9a20c98a2763c9fef0d2b5a97d86456a73dd18ebb8b2b99dd0837efd8688634 languageName: node linkType: hard @@ -4392,8 +4276,8 @@ __metadata: linkType: hard "ws@npm:^8.21.0": - version: 8.21.1 - resolution: "ws@npm:8.21.1" + version: 8.21.3 + resolution: "ws@npm:8.21.3" peerDependencies: bufferutil: ^4.0.1 utf-8-validate: ">=5.0.2" @@ -4402,7 +4286,7 @@ __metadata: optional: true utf-8-validate: optional: true - checksum: 10c0/c4c6f1d95f6d465262de2037c57c715725d67e078dd49420ede4e19115668aba159cb64d85c5e89c06eb2826be599e62e5095860ad6cc54ff42e8bd7684e1db8 + checksum: 10c0/7b28dc2863ea0e2cece68d142a3eee90361021b73f750431e6d8076bb7dede5fdfdb75b3d29534b62f411261147b76b1bc80fb5cc63ab0aabd467280e85b22e0 languageName: node linkType: hard @@ -4422,9 +4306,9 @@ __metadata: languageName: node linkType: hard -"zod@npm:^3.25 || ^4.0, zod@npm:^4.4.3": - version: 4.4.3 - resolution: "zod@npm:4.4.3" - checksum: 10c0/7ea31b558e88f9faf44f31dd185e2e1cbf51fed3081787fb96cc2534749b50c0acfc6da7f0922a7353ed092dd358c7d50c28ea96c94d04af64191bd33152eca3 +"zod@npm:^3.25 || ^4.0, zod@npm:^4.5.4": + version: 4.5.4 + resolution: "zod@npm:4.5.4" + checksum: 10c0/511a2a4d1a6f875dfdd70a1586989a8b14ef126776cd6218a2c760b9f65f14ef389ec20d92ee1aa4fcb4566d4ff3fa012956044f9dc503510d82e4c756a8ba92 languageName: node linkType: hard