diff --git a/.githooks/pre-commit b/.githooks/pre-commit
index 22e87dc5..1ecaa050 100755
--- a/.githooks/pre-commit
+++ b/.githooks/pre-commit
@@ -9,5 +9,5 @@ if ! command -v pnpm >/dev/null 2>&1; then
exit 1
fi
-echo "pre-commit: running the full CI gate"
-pnpm run ci
+echo "pre-commit: checking changelog, formatting, and lint"
+pnpm run precommit
diff --git a/.oxfmtrc.json b/.oxfmtrc.json
new file mode 100644
index 00000000..41ed2515
--- /dev/null
+++ b/.oxfmtrc.json
@@ -0,0 +1,25 @@
+{
+ "$schema": "./node_modules/oxfmt/configuration_schema.json",
+ "useTabs": true,
+ "singleQuote": true,
+ "trailingComma": "none",
+ "printWidth": 100,
+ "sortPackageJson": false,
+ "sortTailwindcss": {
+ "stylesheet": "./apps/web/src/routes/layout.css"
+ },
+ "svelte": {},
+ "ignorePatterns": [
+ "package-lock.json",
+ "pnpm-lock.yaml",
+ "yarn.lock",
+ "bun.lock",
+ "bun.lockb",
+ "/static/",
+ "**/.svelte-kit/",
+ "**/dist/",
+ "packages/motion-gpu/benchmarks/results/",
+ "packages/motion-gpu/coverage/",
+ "packages/motion-gpu/test-results/"
+ ]
+}
diff --git a/.prettierignore b/.prettierignore
deleted file mode 100644
index 889b2848..00000000
--- a/.prettierignore
+++ /dev/null
@@ -1,11 +0,0 @@
-# Package Managers
-package-lock.json
-pnpm-lock.yaml
-yarn.lock
-bun.lock
-bun.lockb
-
-# Miscellaneous
-/static/
-**/.svelte-kit/
-**/dist/
diff --git a/.prettierrc b/.prettierrc
deleted file mode 100644
index 7ddca92d..00000000
--- a/.prettierrc
+++ /dev/null
@@ -1,16 +0,0 @@
-{
- "useTabs": true,
- "singleQuote": true,
- "trailingComma": "none",
- "printWidth": 100,
- "plugins": ["prettier-plugin-svelte", "prettier-plugin-tailwindcss"],
- "overrides": [
- {
- "files": "*.svelte",
- "options": {
- "parser": "svelte"
- }
- }
- ],
- "tailwindStylesheet": "./apps/web/src/routes/layout.css"
-}
diff --git a/apps/web/package.json b/apps/web/package.json
index db64a5b7..2f376949 100644
--- a/apps/web/package.json
+++ b/apps/web/package.json
@@ -22,8 +22,7 @@
"github-slugger": "^2.0.0",
"globals": "^17.11.0",
"mdsvex": "^0.12.6",
- "prettier": "catalog:",
- "prettier-plugin-svelte": "^3.5.2",
+ "oxfmt": "catalog:",
"rehype-pretty-code": "^0.14.1",
"rehype-slug": "^6.0.0",
"shiki": "^4.0.1",
@@ -55,8 +54,8 @@
"test:watch": "vitest",
"lint": "eslint . && pnpm run lint:config",
"lint:config": "node --test ../../scripts/eslint/shared-preset.test.mjs ./scripts/lint/config-coverage.test.mjs && node ./scripts/lint/config-coverage.mjs",
- "format": "prettier --write .",
- "format:check": "prettier --check ."
+ "format": "oxfmt",
+ "format:check": "oxfmt --check"
},
"type": "module",
"dependencies": {
diff --git a/apps/web/src/routes/+layout.svelte b/apps/web/src/routes/+layout.svelte
index 63e05942..ea8e7c9d 100644
--- a/apps/web/src/routes/+layout.svelte
+++ b/apps/web/src/routes/+layout.svelte
@@ -99,7 +99,7 @@
-
+
{homeStructuredData}
{:else if !currentSection}
diff --git a/apps/web/src/routes/[section]/+layout.svelte b/apps/web/src/routes/[section]/+layout.svelte
index 9789440e..d467a629 100644
--- a/apps/web/src/routes/[section]/+layout.svelte
+++ b/apps/web/src/routes/[section]/+layout.svelte
@@ -177,12 +177,12 @@
{#if docStructuredData}
-
+
{docStructuredData}
{/if}
{#if breadcrumbStructuredData}
-
+
{breadcrumbStructuredData}
{/if}
diff --git a/package.json b/package.json
index d492dad7..39fd75fe 100644
--- a/package.json
+++ b/package.json
@@ -43,20 +43,18 @@
"lint": "pnpm run lint:motion-gpu && pnpm run lint:web",
"lint:web": "pnpm --dir apps/web run lint",
"lint:motion-gpu": "pnpm --dir packages/motion-gpu run lint",
- "format": "pnpm --dir apps/web run format && pnpm --dir packages/motion-gpu run format",
- "format:check:root": "pnpm exec prettier --check package.json CONTRIBUTING.md scripts .github",
- "format:check": "pnpm run format:check:root && pnpm --dir apps/web run format:check && pnpm --dir packages/motion-gpu exec prettier --check .",
+ "format": "pnpm run format:root && pnpm --dir apps/web run format && pnpm --dir packages/motion-gpu run format",
+ "format:root": "oxfmt .oxfmtrc.json pnpm-workspace.yaml package.json CONTRIBUTING.md scripts .github .githooks",
+ "format:check:root": "oxfmt --check .oxfmtrc.json pnpm-workspace.yaml package.json CONTRIBUTING.md scripts .github .githooks",
+ "format:check": "pnpm run format:check:root && pnpm --dir apps/web run format:check && pnpm --dir packages/motion-gpu run format:check",
+ "precommit": "pnpm run docs:changelog:check && pnpm run format:check && pnpm run lint",
"ci:quality": "pnpm run docs:changelog:check && pnpm run format:check && pnpm run lint && pnpm run build && pnpm run check:motion-gpu && pnpm run check:motion-gpu:consumers && pnpm run check:motion-gpu:consumers:peers && pnpm run check:web && pnpm run test:motion-gpu:coverage && pnpm run test:motion-gpu:perf-tools && pnpm --dir apps/web test --passWithNoTests",
"ci:e2e": "pnpm --dir packages/motion-gpu run test:e2e",
"ci": "pnpm run ci:quality && pnpm run ci:e2e",
"prepare": "node ./scripts/setup-git-hooks.mjs"
},
- "dependencies": {
- "prettier-plugin-tailwindcss": "catalog:"
- },
"devDependencies": {
- "prettier": "catalog:",
- "prettier-plugin-svelte": "^3.5.2"
+ "oxfmt": "catalog:"
},
"pnpm": {
"onlyBuiltDependencies": [
diff --git a/packages/motion-gpu/.prettierignore b/packages/motion-gpu/.prettierignore
deleted file mode 100644
index e905a368..00000000
--- a/packages/motion-gpu/.prettierignore
+++ /dev/null
@@ -1,5 +0,0 @@
-dist
-.svelte-kit
-benchmarks/results
-coverage
-test-results
diff --git a/packages/motion-gpu/package.json b/packages/motion-gpu/package.json
index 323f8cba..b6eb2538 100644
--- a/packages/motion-gpu/package.json
+++ b/packages/motion-gpu/package.json
@@ -111,11 +111,12 @@
"perf:renderer": "tsx ./scripts/perf/real-renderer-benchmark.ts",
"perf:renderer:baseline": "tsx ./scripts/perf/real-renderer-benchmark.ts --update-baseline",
"perf:renderer:headed": "tsx ./scripts/perf/real-renderer-benchmark.ts --headed",
- "lint": "prettier --check . && pnpm run lint:oxlint && eslint . --max-warnings 0 && pnpm run lint:config && pnpm run lint:imports",
+ "lint": "pnpm run lint:oxlint && eslint . --max-warnings 0 && pnpm run lint:config && pnpm run lint:imports",
"lint:config": "node --test ./scripts/lint/config-coverage.test.mjs && node ./scripts/lint/config-coverage.mjs",
"lint:imports": "node --test ./scripts/lint/import-boundaries.test.mjs && node ./scripts/lint/import-boundaries.mjs",
"lint:oxlint": "oxlint --deny-warnings src/lib && oxlint --type-aware -A all -D typescript/await-thenable -D typescript/no-floating-promises -D typescript/no-misused-promises --deny-warnings src/lib && node --test ./scripts/lint/oxlint-equivalence.test.mjs && node ./scripts/lint/oxlint-equivalence.mjs",
- "format": "prettier --write ."
+ "format": "oxfmt",
+ "format:check": "oxfmt --check"
},
"peerDependencies": {
"react": "^19.0.0",
@@ -163,9 +164,7 @@
"happy-dom": "^20.11.2",
"oxlint": "^1.78.0",
"oxlint-tsgolint": "^7.0.2001",
- "prettier": "catalog:",
- "prettier-plugin-svelte": "^3.5.2",
- "prettier-plugin-tailwindcss": "catalog:",
+ "oxfmt": "catalog:",
"publint": "^0.3.23",
"react": "^19.2.8",
"react-dom": "^19.2.8",
diff --git a/packages/motion-gpu/src/lib/core/frame-registry.ts b/packages/motion-gpu/src/lib/core/frame-registry.ts
index ac02c6cf..d9c9a97a 100644
--- a/packages/motion-gpu/src/lib/core/frame-registry.ts
+++ b/packages/motion-gpu/src/lib/core/frame-registry.ts
@@ -75,7 +75,8 @@ export interface UseFrameOptions {
* Invalidation token value or resolver.
*/
export type FrameTaskInvalidationToken =
- FrameInvalidationToken | (() => FrameInvalidationToken | null | undefined);
+ | FrameInvalidationToken
+ | (() => FrameInvalidationToken | null | undefined);
/**
* Explicit task invalidation policy.
diff --git a/packages/motion-gpu/src/lib/core/types.ts b/packages/motion-gpu/src/lib/core/types.ts
index 1633720a..6175b3b3 100644
--- a/packages/motion-gpu/src/lib/core/types.ts
+++ b/packages/motion-gpu/src/lib/core/types.ts
@@ -398,7 +398,9 @@ export interface ComputeExternalSamplerReference {
/** Material texture key or a borrowed WebGPU texture/view reference. */
export type ComputeTextureReference =
- string | ComputeExternalTextureReference | ComputeExternalTextureViewReference;
+ | string
+ | ComputeExternalTextureReference
+ | ComputeExternalTextureViewReference;
/** Material storage-buffer key or a borrowed WebGPU buffer reference. */
export type ComputeBufferReference = string | ComputeExternalBufferReference;
@@ -477,7 +479,11 @@ export type OutputEncoding = 'srgb' | 'linear';
* Final tone mapper applied by the private presentation pass.
*/
export type ToneMapping =
- 'none' | 'khronos-pbr-neutral' | 'uncharted2-filmic' | 'aces-hill' | 'gran-turismo';
+ | 'none'
+ | 'khronos-pbr-neutral'
+ | 'uncharted2-filmic'
+ | 'aces-hill'
+ | 'gran-turismo';
/**
* Requested display dynamic range for final canvas presentation.
diff --git a/packages/motion-gpu/src/tests/FragCanvas.runtime.test.ts b/packages/motion-gpu/src/tests/FragCanvas.runtime.test.ts
index f2ee3d96..6950afae 100644
--- a/packages/motion-gpu/src/tests/FragCanvas.runtime.test.ts
+++ b/packages/motion-gpu/src/tests/FragCanvas.runtime.test.ts
@@ -738,7 +738,8 @@ describe('FragCanvas runtime', () => {
});
const firstRenderInput = created[0]?.render.mock.calls[0]?.[0] as
- { uniforms: Record; textures: Record } | undefined;
+ | { uniforms: Record; textures: Record }
+ | undefined;
expect(firstRenderInput?.uniforms['uGain']).toBe(0.75);
expect(firstRenderInput?.textures['uTex']).toBeTruthy();
@@ -757,7 +758,8 @@ describe('FragCanvas runtime', () => {
});
const secondRenderInput = created[1]?.render.mock.calls[0]?.[0] as
- { uniforms: Record; textures: Record } | undefined;
+ | { uniforms: Record; textures: Record }
+ | undefined;
expect('uGain' in (secondRenderInput?.uniforms ?? {})).toBe(false);
expect('uTex' in (secondRenderInput?.textures ?? {})).toBe(false);
});
@@ -844,7 +846,8 @@ describe('FragCanvas runtime', () => {
await flushFrame(32);
await waitFor(() => {
const latest = onErrorHistory.mock.calls[onErrorHistory.mock.calls.length - 1]?.[0] as
- Array<{ rawMessage: string }> | undefined;
+ | Array<{ rawMessage: string }>
+ | undefined;
expect(latest).toHaveLength(1);
expect(latest?.[0]?.rawMessage).toContain('Unknown uniform "uMissing"');
});
@@ -859,7 +862,8 @@ describe('FragCanvas runtime', () => {
await flushFrame(48);
await waitFor(() => {
const latest = onErrorHistory.mock.calls[onErrorHistory.mock.calls.length - 1]?.[0] as
- Array<{ rawMessage: string }> | undefined;
+ | Array<{ rawMessage: string }>
+ | undefined;
expect(latest).toHaveLength(2);
expect(latest?.[0]?.rawMessage).toContain('Unknown uniform "uMissing"');
expect(latest?.[1]?.rawMessage).toContain('Unknown texture "uMissing"');
@@ -875,7 +879,8 @@ describe('FragCanvas runtime', () => {
await flushFrame(64);
await waitFor(() => {
const latest = onErrorHistory.mock.calls[onErrorHistory.mock.calls.length - 1]?.[0] as
- Array<{ rawMessage: string }> | undefined;
+ | Array<{ rawMessage: string }>
+ | undefined;
expect(latest).toHaveLength(2);
expect(latest?.[0]?.rawMessage).toContain('Unknown texture "uMissing"');
expect(latest?.[1]?.rawMessage).toContain('Unknown uniform "uMissing"');
diff --git a/packages/motion-gpu/src/tests/core/compute-comprehensive.test.ts b/packages/motion-gpu/src/tests/core/compute-comprehensive.test.ts
index 8df11b49..0063f35a 100644
--- a/packages/motion-gpu/src/tests/core/compute-comprehensive.test.ts
+++ b/packages/motion-gpu/src/tests/core/compute-comprehensive.test.ts
@@ -895,7 +895,8 @@ fn compute(@builtin(global_invocation_id) id: vec3u) {
input.entries.length === 2 &&
input.entries.every((entry) => {
const resource = entry.resource as
- { textureDescriptor?: GPUTextureDescriptor } | undefined;
+ | { textureDescriptor?: GPUTextureDescriptor }
+ | undefined;
return Boolean(
resource && typeof resource === 'object' && 'textureDescriptor' in resource
);
diff --git a/packages/motion-gpu/src/tests/core/passes.test.ts b/packages/motion-gpu/src/tests/core/passes.test.ts
index a43f07e8..5af156d1 100644
--- a/packages/motion-gpu/src/tests/core/passes.test.ts
+++ b/packages/motion-gpu/src/tests/core/passes.test.ts
@@ -155,7 +155,8 @@ fn shade(inputColor: vec4f, uv: vec2f) -> vec4f {
pass.render(context);
const descriptor = device.createShaderModule.mock.calls[0]?.[0] as
- GPUShaderModuleDescriptor | undefined;
+ | GPUShaderModuleDescriptor
+ | undefined;
const source = String(descriptor?.code ?? '');
expect(source).toContain('var motiongpuFragment: MotionGPUFragment;');
expect(source).toContain('return motiongpuFragment.uv;');
diff --git a/packages/motion-gpu/src/tests/core/renderer.test.ts b/packages/motion-gpu/src/tests/core/renderer.test.ts
index 7584f648..febcdd1b 100644
--- a/packages/motion-gpu/src/tests/core/renderer.test.ts
+++ b/packages/motion-gpu/src/tests/core/renderer.test.ts
@@ -1145,7 +1145,8 @@ describe('createRenderer', () => {
});
const viewB = textureB?.createView.mock.results[0]?.value as GPUTextureView | undefined;
const latestBindGroup = runtime.device.createBindGroup.mock.calls.at(-1)?.[0] as
- GPUBindGroupDescriptor | undefined;
+ | GPUBindGroupDescriptor
+ | undefined;
expect(runtime.device.createBindGroup.mock.calls.length).toBe(bindGroupCountAfterA + 1);
expect(
Array.from(latestBindGroup?.entries ?? []).some((entry) => entry.resource === viewB)
@@ -1245,7 +1246,8 @@ describe('createRenderer', () => {
const pipelinesAfterInit = runtime.device.createRenderPipeline.mock.calls.length;
const bindGroupsAfterInit = runtime.device.createBindGroup.mock.calls.length;
const initialBindGroupDescriptor = runtime.device.createBindGroup.mock.calls.at(-1)?.[0] as
- GPUBindGroupDescriptor | undefined;
+ | GPUBindGroupDescriptor
+ | undefined;
const initialTextureView = Array.from(initialBindGroupDescriptor?.entries ?? []).find(
(entry) => entry.binding === 3
)?.resource;
@@ -1288,7 +1290,8 @@ describe('createRenderer', () => {
expect(runtime.device.createBindGroup).toHaveBeenCalledTimes(bindGroupsAfterUpload + 1);
expect(runtime.device.createRenderPipeline).toHaveBeenCalledTimes(pipelinesAfterInit);
const restoredBindGroupDescriptor = runtime.device.createBindGroup.mock.calls.at(-1)?.[0] as
- GPUBindGroupDescriptor | undefined;
+ | GPUBindGroupDescriptor
+ | undefined;
expect(
Array.from(restoredBindGroupDescriptor?.entries ?? []).find((entry) => entry.binding === 3)
?.resource
@@ -1463,7 +1466,8 @@ describe('createRenderer', () => {
expect(runtime.renderPasses[0]?.setPipeline).toHaveBeenCalledWith(directCanvasPipeline);
const descriptor = runtime.commandEncoders[0]?.beginRenderPass.mock.calls[0]?.[0] as
- GPURenderPassDescriptor | undefined;
+ | GPURenderPassDescriptor
+ | undefined;
const attachment = Array.from(descriptor?.colorAttachments ?? [])[0];
expect(attachment?.clearValue).toEqual({ r: 0.25, g: 0, b: 0, a: 0.25 });
});
@@ -1666,7 +1670,8 @@ describe('createRenderer', () => {
const canvasTexture = runtime.context.getCurrentTexture.mock.results[0]?.value;
const passRender = pass.render as ReturnType;
const passContext = passRender.mock.calls[0]?.[0] as
- Parameters>[0] | undefined;
+ | Parameters>[0]
+ | undefined;
expect(passContext).toEqual(
expect.objectContaining({
output: expect.objectContaining({ width: 10, height: 10, format: 'rgba8unorm' }),
@@ -2169,9 +2174,11 @@ describe('createRenderer', () => {
expect(runtime.commandEncoders[0]?.beginComputePass).toHaveBeenCalledTimes(2);
const computeEncoder = runtime.computePasses[0];
const firstPipeline = runtime.device.createComputePipeline.mock.calls[0]?.[0] as
- GPUComputePipelineDescriptor | undefined;
+ | GPUComputePipelineDescriptor
+ | undefined;
const secondPipeline = runtime.device.createComputePipeline.mock.calls[1]?.[0] as
- GPUComputePipelineDescriptor | undefined;
+ | GPUComputePipelineDescriptor
+ | undefined;
const firstCode = (firstPipeline?.compute.module as unknown as { code?: string })?.code;
const secondCode = (secondPipeline?.compute.module as unknown as { code?: string })?.code;
expect(firstCode).toContain('var sourceTex: texture_2d');
diff --git a/packages/motion-gpu/src/tests/fixtures/MotionGPUUserTypedNamespaceProbe.svelte b/packages/motion-gpu/src/tests/fixtures/MotionGPUUserTypedNamespaceProbe.svelte
index 3f8ecf3b..f7dcd17e 100644
--- a/packages/motion-gpu/src/tests/fixtures/MotionGPUUserTypedNamespaceProbe.svelte
+++ b/packages/motion-gpu/src/tests/fixtures/MotionGPUUserTypedNamespaceProbe.svelte
@@ -17,7 +17,7 @@
let { onProbe }: Props = $props();
const pluginStore = useMotionGPUUserContext('plugin');
- const assertType = (value: T): void => {
+ const assertType = (value: T): void => {
void value;
};
setMotionGPUUserContext('plugin', () => ({ enabled: true }), {
diff --git a/packages/motion-gpu/src/tests/react-frag-canvas.runtime.test.tsx b/packages/motion-gpu/src/tests/react-frag-canvas.runtime.test.tsx
index 0c9a7774..7cdbbc52 100644
--- a/packages/motion-gpu/src/tests/react-frag-canvas.runtime.test.tsx
+++ b/packages/motion-gpu/src/tests/react-frag-canvas.runtime.test.tsx
@@ -805,7 +805,8 @@ describe('React FragCanvas runtime', () => {
});
const firstRenderInput = created[0]?.render.mock.calls[0]?.[0] as
- { uniforms: Record; textures: Record } | undefined;
+ | { uniforms: Record; textures: Record }
+ | undefined;
expect(firstRenderInput?.uniforms['uGain']).toBe(0.75);
expect(firstRenderInput?.textures['uTex']).toBeTruthy();
@@ -822,7 +823,8 @@ describe('React FragCanvas runtime', () => {
});
const secondRenderInput = created[1]?.render.mock.calls[0]?.[0] as
- { uniforms: Record; textures: Record } | undefined;
+ | { uniforms: Record; textures: Record }
+ | undefined;
expect('uGain' in (secondRenderInput?.uniforms ?? {})).toBe(false);
expect('uTex' in (secondRenderInput?.textures ?? {})).toBe(false);
});
@@ -909,7 +911,8 @@ describe('React FragCanvas runtime', () => {
await flushFrame(32);
await waitFor(() => {
const latest = onErrorHistory.mock.calls[onErrorHistory.mock.calls.length - 1]?.[0] as
- Array<{ rawMessage: string }> | undefined;
+ | Array<{ rawMessage: string }>
+ | undefined;
expect(latest).toHaveLength(1);
expect(latest?.[0]?.rawMessage).toContain('Unknown uniform "uMissing"');
});
@@ -926,7 +929,8 @@ describe('React FragCanvas runtime', () => {
await flushFrame(48);
await waitFor(() => {
const latest = onErrorHistory.mock.calls[onErrorHistory.mock.calls.length - 1]?.[0] as
- Array<{ rawMessage: string }> | undefined;
+ | Array<{ rawMessage: string }>
+ | undefined;
expect(latest).toHaveLength(2);
expect(latest?.[0]?.rawMessage).toContain('Unknown uniform "uMissing"');
expect(latest?.[1]?.rawMessage).toContain('Unknown texture "uMissing"');
@@ -944,7 +948,8 @@ describe('React FragCanvas runtime', () => {
await flushFrame(64);
await waitFor(() => {
const latest = onErrorHistory.mock.calls[onErrorHistory.mock.calls.length - 1]?.[0] as
- Array<{ rawMessage: string }> | undefined;
+ | Array<{ rawMessage: string }>
+ | undefined;
expect(latest).toHaveLength(2);
expect(latest?.[0]?.rawMessage).toContain('Unknown texture "uMissing"');
expect(latest?.[1]?.rawMessage).toContain('Unknown uniform "uMissing"');
diff --git a/packages/motion-gpu/src/tests/vue-frag-canvas.runtime.test.ts b/packages/motion-gpu/src/tests/vue-frag-canvas.runtime.test.ts
index f2083bd9..cfa32d21 100644
--- a/packages/motion-gpu/src/tests/vue-frag-canvas.runtime.test.ts
+++ b/packages/motion-gpu/src/tests/vue-frag-canvas.runtime.test.ts
@@ -909,7 +909,8 @@ describe('Vue FragCanvas runtime', () => {
});
const firstRenderInput = created[0]?.render.mock.calls[0]?.[0] as
- { uniforms: Record; textures: Record } | undefined;
+ | { uniforms: Record; textures: Record }
+ | undefined;
expect(firstRenderInput?.uniforms['uGain']).toBe(0.75);
expect(firstRenderInput?.textures['uTex']).toBeTruthy();
@@ -928,7 +929,8 @@ describe('Vue FragCanvas runtime', () => {
});
const secondRenderInput = created[1]?.render.mock.calls[0]?.[0] as
- { uniforms: Record; textures: Record } | undefined;
+ | { uniforms: Record; textures: Record }
+ | undefined;
expect('uGain' in (secondRenderInput?.uniforms ?? {})).toBe(false);
expect('uTex' in (secondRenderInput?.textures ?? {})).toBe(false);
});
@@ -1016,7 +1018,8 @@ describe('Vue FragCanvas runtime', () => {
await flushFrame(32);
await waitFor(() => {
const latest = onErrorHistory.mock.calls[onErrorHistory.mock.calls.length - 1]?.[0] as
- Array<{ rawMessage: string }> | undefined;
+ | Array<{ rawMessage: string }>
+ | undefined;
expect(latest).toHaveLength(1);
expect(latest?.[0]?.rawMessage).toContain('Unknown uniform "uMissing"');
});
@@ -1032,7 +1035,8 @@ describe('Vue FragCanvas runtime', () => {
await flushFrame(48);
await waitFor(() => {
const latest = onErrorHistory.mock.calls[onErrorHistory.mock.calls.length - 1]?.[0] as
- Array<{ rawMessage: string }> | undefined;
+ | Array<{ rawMessage: string }>
+ | undefined;
expect(latest).toHaveLength(2);
expect(latest?.[0]?.rawMessage).toContain('Unknown uniform "uMissing"');
expect(latest?.[1]?.rawMessage).toContain('Unknown texture "uMissing"');
@@ -1049,7 +1053,8 @@ describe('Vue FragCanvas runtime', () => {
await flushFrame(64);
await waitFor(() => {
const latest = onErrorHistory.mock.calls[onErrorHistory.mock.calls.length - 1]?.[0] as
- Array<{ rawMessage: string }> | undefined;
+ | Array<{ rawMessage: string }>
+ | undefined;
expect(latest).toHaveLength(2);
expect(latest?.[0]?.rawMessage).toContain('Unknown texture "uMissing"');
expect(latest?.[1]?.rawMessage).toContain('Unknown uniform "uMissing"');
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index ea1e724b..4fd50547 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -15,12 +15,9 @@ catalogs:
eslint-config-prettier:
specifier: ^10.1.8
version: 10.1.8
- prettier:
- specifier: ^3.9.6
- version: 3.9.6
- prettier-plugin-tailwindcss:
- specifier: ^0.7.4
- version: 0.7.4
+ oxfmt:
+ specifier: ^0.63.0
+ version: 0.63.0
typescript:
specifier: ^5.9.3
version: 5.9.3
@@ -28,17 +25,10 @@ catalogs:
importers:
.:
- dependencies:
- prettier-plugin-tailwindcss:
- specifier: 'catalog:'
- version: 0.7.4(prettier-plugin-svelte@3.5.2(prettier@3.9.6)(svelte@5.56.9(@typescript-eslint/types@8.67.0)))(prettier@3.9.6)
devDependencies:
- prettier:
+ oxfmt:
specifier: 'catalog:'
- version: 3.9.6
- prettier-plugin-svelte:
- specifier: ^3.5.2
- version: 3.5.2(prettier@3.9.6)(svelte@5.56.9(@typescript-eslint/types@8.67.0))
+ version: 0.63.0(svelte@5.56.9(@typescript-eslint/types@8.67.0))
apps/web:
dependencies:
@@ -193,12 +183,9 @@ importers:
mdsvex:
specifier: ^0.12.6
version: 0.12.7(svelte@5.56.9(@typescript-eslint/types@8.67.0))
- prettier:
+ oxfmt:
specifier: 'catalog:'
- version: 3.9.6
- prettier-plugin-svelte:
- specifier: ^3.5.2
- version: 3.5.2(prettier@3.9.6)(svelte@5.56.9(@typescript-eslint/types@8.67.0))
+ version: 0.63.0(svelte@5.56.9(@typescript-eslint/types@8.67.0))
rehype-pretty-code:
specifier: ^0.14.1
version: 0.14.3(shiki@4.0.2)
@@ -299,21 +286,15 @@ importers:
happy-dom:
specifier: ^20.11.2
version: 20.11.2
+ oxfmt:
+ specifier: 'catalog:'
+ version: 0.63.0(svelte@5.56.9(@typescript-eslint/types@8.67.0))
oxlint:
specifier: ^1.78.0
version: 1.78.0(oxlint-tsgolint@7.0.2001)
oxlint-tsgolint:
specifier: ^7.0.2001
version: 7.0.2001
- prettier:
- specifier: 'catalog:'
- version: 3.9.6
- prettier-plugin-svelte:
- specifier: ^3.5.2
- version: 3.5.2(prettier@3.9.6)(svelte@5.56.9(@typescript-eslint/types@8.67.0))
- prettier-plugin-tailwindcss:
- specifier: 'catalog:'
- version: 0.7.4(prettier-plugin-svelte@3.5.2(prettier@3.9.6)(svelte@5.56.9(@typescript-eslint/types@8.67.0)))(prettier@3.9.6)
publint:
specifier: ^0.3.23
version: 0.3.23
@@ -1094,6 +1075,120 @@ packages:
'@oxc-project/types@0.143.0':
resolution: {integrity: sha512-u6JZdLBTLotrNC9Vd6vPssINdzcCzleKAH6EJKImQb7GtYvX5keN2dxkoK44stCc4tffE6QQRtZTXVSzsLUlWA==}
+ '@oxfmt/binding-android-arm-eabi@0.63.0':
+ resolution: {integrity: sha512-YmRth4ZPGgEXcgmkhvANbC9uD67dxmSobW7DQuyt5tOBOKvPnIpk5SVHBj88E+7wMNRI2FhqaDbOhQFBix+b8A==}
+ engines: {node: ^20.19.0 || >=22.12.0}
+ cpu: [arm]
+ os: [android]
+
+ '@oxfmt/binding-android-arm64@0.63.0':
+ resolution: {integrity: sha512-icbahX8X2X3sRamOMecvdYeZXWjPDazRDIfvWfy7Ca1nc/ZDT2Y9k5Nt7s46EqFd7NQPdgk+CM3/SgIT5LPCaQ==}
+ engines: {node: ^20.19.0 || >=22.12.0}
+ cpu: [arm64]
+ os: [android]
+
+ '@oxfmt/binding-darwin-arm64@0.63.0':
+ resolution: {integrity: sha512-WV+Ze5v5gI2qoj8jpAovt8KBTW8pjEz/AiMXXjeTQS+Bmf/MmZXTS40S8xNPDszX+W8WDv2Bbk6qKrMTtUGu1A==}
+ engines: {node: ^20.19.0 || >=22.12.0}
+ cpu: [arm64]
+ os: [darwin]
+
+ '@oxfmt/binding-darwin-x64@0.63.0':
+ resolution: {integrity: sha512-CJGSBdDxXOWIpoFXHpverimCvz084KA7L483rqJ44c3jDtzv6d4qOSoR/V9ywSHfV+Ks1lwIj2P49BFhunLNAA==}
+ engines: {node: ^20.19.0 || >=22.12.0}
+ cpu: [x64]
+ os: [darwin]
+
+ '@oxfmt/binding-freebsd-x64@0.63.0':
+ resolution: {integrity: sha512-BDfKY+KhL2078cgswBBFQPAYuxCy93bS/iC5frdSeSbTLcGrR6VC2hsuPTanoJmg84+wSyWl0wWC1eR+uTnkRg==}
+ engines: {node: ^20.19.0 || >=22.12.0}
+ cpu: [x64]
+ os: [freebsd]
+
+ '@oxfmt/binding-linux-arm-gnueabihf@0.63.0':
+ resolution: {integrity: sha512-Ov1cQEXT4mj7cojAokWSS1eoxkoyvbDfAbxNsGIKY2o36kvdAaFzPxRN6NxFRk9fD72B8oCoTTX/NuYTUWlpsg==}
+ engines: {node: ^20.19.0 || >=22.12.0}
+ cpu: [arm]
+ os: [linux]
+
+ '@oxfmt/binding-linux-arm-musleabihf@0.63.0':
+ resolution: {integrity: sha512-0LE7ro3+6L79jcMANycAZfRaC7zxr9YZ2+vEL5uMD9QlEep+rS/r1kSJsnuLl991NXJZD60euh0PC1GHrR20vw==}
+ engines: {node: ^20.19.0 || >=22.12.0}
+ cpu: [arm]
+ os: [linux]
+
+ '@oxfmt/binding-linux-arm64-gnu@0.63.0':
+ resolution: {integrity: sha512-izPk+2Z4gjuZK32Fqh5qXoMpT/2NXzLh++ob57HiEiVSQZ1iYXu8EKMzb+K5AvWyIEXhdDIt7ADjGGtFhkT9Bw==}
+ engines: {node: ^20.19.0 || >=22.12.0}
+ cpu: [arm64]
+ os: [linux]
+
+ '@oxfmt/binding-linux-arm64-musl@0.63.0':
+ resolution: {integrity: sha512-alPmbOuWXFXiSo+lOtv6X71C7SYMEDW2WVvywOvf9BwKgEhSNGhMTLeFVSjKUMCamcjbbgVdsWF8GN1uy8xshg==}
+ engines: {node: ^20.19.0 || >=22.12.0}
+ cpu: [arm64]
+ os: [linux]
+
+ '@oxfmt/binding-linux-ppc64-gnu@0.63.0':
+ resolution: {integrity: sha512-BdzCPvolJc4AWZ+YMzgUDJcDzbQWrFjYuqBHoNHNqP1aCaluQRJNs4k3vNU5IG7vTpjf9zeD73D7MFM1TecZpg==}
+ engines: {node: ^20.19.0 || >=22.12.0}
+ cpu: [ppc64]
+ os: [linux]
+
+ '@oxfmt/binding-linux-riscv64-gnu@0.63.0':
+ resolution: {integrity: sha512-7sIgfLzqtNKSkMGsGVyRpHwpjNezRg2XONvUOheFZs95TSZpM0JAuPpA8KrQFsWc4wPU95roX2O69JgH8igOgw==}
+ engines: {node: ^20.19.0 || >=22.12.0}
+ cpu: [riscv64]
+ os: [linux]
+
+ '@oxfmt/binding-linux-riscv64-musl@0.63.0':
+ resolution: {integrity: sha512-9Tcg0y0WcVa6Mm9AgcgFMseDS+VkFJZpKZ8We9SpDY4gg5jewSwln+0sO04QLcTS1BtfDl9MwR+NfID8L7PUTg==}
+ engines: {node: ^20.19.0 || >=22.12.0}
+ cpu: [riscv64]
+ os: [linux]
+
+ '@oxfmt/binding-linux-s390x-gnu@0.63.0':
+ resolution: {integrity: sha512-qWKC1pEOpx1qYhXaugPhHUeXwSfqEOk2wJH2LqVXGPV5iQYfdAZdt+d2XDiX4DTSWA2QDMUcFB+wEORh3Xn/sA==}
+ engines: {node: ^20.19.0 || >=22.12.0}
+ cpu: [s390x]
+ os: [linux]
+
+ '@oxfmt/binding-linux-x64-gnu@0.63.0':
+ resolution: {integrity: sha512-S9wXYOiGSqYGS4Fx/TFsY+xDd/7dE5s+rUgbA4TsHiVF9e8J3ZcKmP7dsP/7iqLI9Wz7Ic7TzEr3mdthRCTdrA==}
+ engines: {node: ^20.19.0 || >=22.12.0}
+ cpu: [x64]
+ os: [linux]
+
+ '@oxfmt/binding-linux-x64-musl@0.63.0':
+ resolution: {integrity: sha512-5eGyTJuMZNwBSHCivXt8Yuta6GeTYksOPXRk2MIhajiyFGQx7bjaHIwY+ZusAoFHhT157A9x6sktLjYo9D5oMQ==}
+ engines: {node: ^20.19.0 || >=22.12.0}
+ cpu: [x64]
+ os: [linux]
+
+ '@oxfmt/binding-openharmony-arm64@0.63.0':
+ resolution: {integrity: sha512-Rz7hx+Dv3DoW/S6pwVAyjfFXp7/trdQ1zg+vNmsdsdDNlUccugp4XNqambSuEAeP0DaG9k72AtNyfDXCEg0AGw==}
+ engines: {node: ^20.19.0 || >=22.12.0}
+ cpu: [arm64]
+ os: [openharmony]
+
+ '@oxfmt/binding-win32-arm64-msvc@0.63.0':
+ resolution: {integrity: sha512-T/IuizKN9mr4Xw6YYnptkXRNdLkyIlUZ7c8zfTOBpoytZyJ1BAsMUvsMDEx0X4YvSMpaivm+DR8112rQfzC25g==}
+ engines: {node: ^20.19.0 || >=22.12.0}
+ cpu: [arm64]
+ os: [win32]
+
+ '@oxfmt/binding-win32-ia32-msvc@0.63.0':
+ resolution: {integrity: sha512-XjrO5FJ5Wl9vsAxtCP1G/eaeT6y1K2s9CICUHGE42cEjou32/J6S+B1KnrOAboj6E7uhJnwPbRSvznWcxNdA0g==}
+ engines: {node: ^20.19.0 || >=22.12.0}
+ cpu: [ia32]
+ os: [win32]
+
+ '@oxfmt/binding-win32-x64-msvc@0.63.0':
+ resolution: {integrity: sha512-sgsHCQy432OTQH4Ikk3tZptp3GqwnhwUDuY0loBH41zyHWfMZY9v8Dy78wsnSofHejvFozZGgJgBB1A0LQRwMQ==}
+ engines: {node: ^20.19.0 || >=22.12.0}
+ cpu: [x64]
+ os: [win32]
+
'@oxlint-tsgolint/darwin-arm64@7.0.2001':
resolution: {integrity: sha512-CUJEdbSZ54+Xy9OXqOhWLTKZKV0BBiV7C2i/ygyVmXtkUNXx5YCzN8DpSSshTAKktoL7S+tnQ/ftFG/i7X896w==}
cpu: [arm64]
@@ -2956,6 +3051,19 @@ packages:
resolution: {integrity: sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==}
engines: {node: '>= 0.8.0'}
+ oxfmt@0.63.0:
+ resolution: {integrity: sha512-kgdDwv35wvVf6554U2Ab8Jnd0zTM+TsEQWwaB70RAjK3gICFAFGO+2Hd3Be27GMoXj3XRL9IKSNRVl7KBQL6iw==}
+ engines: {node: ^20.19.0 || >=22.12.0}
+ hasBin: true
+ peerDependencies:
+ svelte: ^5.0.0
+ vite-plus: '*'
+ peerDependenciesMeta:
+ svelte:
+ optional: true
+ vite-plus:
+ optional: true
+
oxlint-tsgolint@7.0.2001:
resolution: {integrity: sha512-KjK/XLcXr1DSyonKhsuFqJRiuKqcyG9j3LJ8nkOsrLzGvodBPqzHOKauy10asLMDI0sUpvb+1sxlzff3udZvfg==}
hasBin: true
@@ -3075,72 +3183,6 @@ packages:
resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==}
engines: {node: '>= 0.8.0'}
- prettier-plugin-svelte@3.5.2:
- resolution: {integrity: sha512-ItFouLvzSFE3ulNl4DKoWM3BGcbDCNVpIyy/Y3F2gC3aNiGLxtFUdffVqO5Z5hhYG+DFT5KULWaxmeFFpdbvaQ==}
- peerDependencies:
- prettier: ^3.0.0
- svelte: ^3.2.0 || ^4.0.0-next.0 || ^5.0.0-next.0
-
- prettier-plugin-tailwindcss@0.7.4:
- resolution: {integrity: sha512-UKii4RjY05SNt/WQi6/NcOn/LsT0/ILLXsxygjbRg5/YZelsSu5jTqorYHPDGq4nZy5q5hpCu+XdGZ1xaJEQgw==}
- engines: {node: '>=20.19'}
- peerDependencies:
- '@ianvs/prettier-plugin-sort-imports': '*'
- '@prettier/plugin-hermes': '*'
- '@prettier/plugin-oxc': '*'
- '@prettier/plugin-pug': '*'
- '@shopify/prettier-plugin-liquid': '*'
- '@trivago/prettier-plugin-sort-imports': '*'
- '@zackad/prettier-plugin-twig': '*'
- prettier: ^3.0
- prettier-plugin-astro: '*'
- prettier-plugin-css-order: '*'
- prettier-plugin-jsdoc: '*'
- prettier-plugin-marko: '*'
- prettier-plugin-multiline-arrays: '*'
- prettier-plugin-organize-attributes: '*'
- prettier-plugin-organize-imports: '*'
- prettier-plugin-sort-imports: '*'
- prettier-plugin-svelte: '*'
- peerDependenciesMeta:
- '@ianvs/prettier-plugin-sort-imports':
- optional: true
- '@prettier/plugin-hermes':
- optional: true
- '@prettier/plugin-oxc':
- optional: true
- '@prettier/plugin-pug':
- optional: true
- '@shopify/prettier-plugin-liquid':
- optional: true
- '@trivago/prettier-plugin-sort-imports':
- optional: true
- '@zackad/prettier-plugin-twig':
- optional: true
- prettier-plugin-astro:
- optional: true
- prettier-plugin-css-order:
- optional: true
- prettier-plugin-jsdoc:
- optional: true
- prettier-plugin-marko:
- optional: true
- prettier-plugin-multiline-arrays:
- optional: true
- prettier-plugin-organize-attributes:
- optional: true
- prettier-plugin-organize-imports:
- optional: true
- prettier-plugin-sort-imports:
- optional: true
- prettier-plugin-svelte:
- optional: true
-
- prettier@3.9.6:
- resolution: {integrity: sha512-OpN0zzVdiaiAhxpuuj5efpIS4sY9j7bY6uR5mnj5yPzGkdkjNKSJeUThPb60Jw29QuAZgA4o+/iB49kFiaBX6g==}
- engines: {node: '>=14'}
- hasBin: true
-
pretty-format@27.5.1:
resolution: {integrity: sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==}
engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0}
@@ -3412,6 +3454,10 @@ packages:
resolution: {integrity: sha512-wXR/dYpcqKmfWpEdZjiKJOwCNFndD0DMnrW/cYjVGttEkBfVgcLFHoNrlj47mjOVic9yyNu65alsgF4NQyTa2g==}
engines: {node: '>=12.0.0'}
+ tinypool@2.1.0:
+ resolution: {integrity: sha512-Pugqs6M0m7Lv1I7FtxN4aoyToKg1C4tu+/381vH35y8oENM/Ai7f7C4StcoK4/+BSw9ebcS8jRiVrORFKCALLw==}
+ engines: {node: ^20.0.0 || >=22.0.0}
+
tinyrainbow@3.1.0:
resolution: {integrity: sha512-Bf+ILmBgretUrdJxzXM0SgXLZ3XfiaUuOj/IKQHuTXip+05Xn+uyEYdVg0kYDipTBcLrCVyUzAPz7QmArb0mmw==}
engines: {node: '>=14.0.0'}
@@ -4394,6 +4440,63 @@ snapshots:
'@oxc-project/types@0.143.0': {}
+ '@oxfmt/binding-android-arm-eabi@0.63.0':
+ optional: true
+
+ '@oxfmt/binding-android-arm64@0.63.0':
+ optional: true
+
+ '@oxfmt/binding-darwin-arm64@0.63.0':
+ optional: true
+
+ '@oxfmt/binding-darwin-x64@0.63.0':
+ optional: true
+
+ '@oxfmt/binding-freebsd-x64@0.63.0':
+ optional: true
+
+ '@oxfmt/binding-linux-arm-gnueabihf@0.63.0':
+ optional: true
+
+ '@oxfmt/binding-linux-arm-musleabihf@0.63.0':
+ optional: true
+
+ '@oxfmt/binding-linux-arm64-gnu@0.63.0':
+ optional: true
+
+ '@oxfmt/binding-linux-arm64-musl@0.63.0':
+ optional: true
+
+ '@oxfmt/binding-linux-ppc64-gnu@0.63.0':
+ optional: true
+
+ '@oxfmt/binding-linux-riscv64-gnu@0.63.0':
+ optional: true
+
+ '@oxfmt/binding-linux-riscv64-musl@0.63.0':
+ optional: true
+
+ '@oxfmt/binding-linux-s390x-gnu@0.63.0':
+ optional: true
+
+ '@oxfmt/binding-linux-x64-gnu@0.63.0':
+ optional: true
+
+ '@oxfmt/binding-linux-x64-musl@0.63.0':
+ optional: true
+
+ '@oxfmt/binding-openharmony-arm64@0.63.0':
+ optional: true
+
+ '@oxfmt/binding-win32-arm64-msvc@0.63.0':
+ optional: true
+
+ '@oxfmt/binding-win32-ia32-msvc@0.63.0':
+ optional: true
+
+ '@oxfmt/binding-win32-x64-msvc@0.63.0':
+ optional: true
+
'@oxlint-tsgolint/darwin-arm64@7.0.2001':
optional: true
@@ -6259,6 +6362,31 @@ snapshots:
type-check: 0.4.0
word-wrap: 1.2.5
+ oxfmt@0.63.0(svelte@5.56.9(@typescript-eslint/types@8.67.0)):
+ dependencies:
+ tinypool: 2.1.0
+ optionalDependencies:
+ '@oxfmt/binding-android-arm-eabi': 0.63.0
+ '@oxfmt/binding-android-arm64': 0.63.0
+ '@oxfmt/binding-darwin-arm64': 0.63.0
+ '@oxfmt/binding-darwin-x64': 0.63.0
+ '@oxfmt/binding-freebsd-x64': 0.63.0
+ '@oxfmt/binding-linux-arm-gnueabihf': 0.63.0
+ '@oxfmt/binding-linux-arm-musleabihf': 0.63.0
+ '@oxfmt/binding-linux-arm64-gnu': 0.63.0
+ '@oxfmt/binding-linux-arm64-musl': 0.63.0
+ '@oxfmt/binding-linux-ppc64-gnu': 0.63.0
+ '@oxfmt/binding-linux-riscv64-gnu': 0.63.0
+ '@oxfmt/binding-linux-riscv64-musl': 0.63.0
+ '@oxfmt/binding-linux-s390x-gnu': 0.63.0
+ '@oxfmt/binding-linux-x64-gnu': 0.63.0
+ '@oxfmt/binding-linux-x64-musl': 0.63.0
+ '@oxfmt/binding-openharmony-arm64': 0.63.0
+ '@oxfmt/binding-win32-arm64-msvc': 0.63.0
+ '@oxfmt/binding-win32-ia32-msvc': 0.63.0
+ '@oxfmt/binding-win32-x64-msvc': 0.63.0
+ svelte: 5.56.9(@typescript-eslint/types@8.67.0)
+
oxlint-tsgolint@7.0.2001:
optionalDependencies:
'@oxlint-tsgolint/darwin-arm64': 7.0.2001
@@ -6368,19 +6496,6 @@ snapshots:
prelude-ls@1.2.1: {}
- prettier-plugin-svelte@3.5.2(prettier@3.9.6)(svelte@5.56.9(@typescript-eslint/types@8.67.0)):
- dependencies:
- prettier: 3.9.6
- svelte: 5.56.9(@typescript-eslint/types@8.67.0)
-
- prettier-plugin-tailwindcss@0.7.4(prettier-plugin-svelte@3.5.2(prettier@3.9.6)(svelte@5.56.9(@typescript-eslint/types@8.67.0)))(prettier@3.9.6):
- dependencies:
- prettier: 3.9.6
- optionalDependencies:
- prettier-plugin-svelte: 3.5.2(prettier@3.9.6)(svelte@5.56.9(@typescript-eslint/types@8.67.0))
-
- prettier@3.9.6: {}
-
pretty-format@27.5.1:
dependencies:
ansi-regex: 5.0.1
@@ -6737,6 +6852,8 @@ snapshots:
fdir: 6.5.0(picomatch@4.0.5)
picomatch: 4.0.5
+ tinypool@2.1.0: {}
+
tinyrainbow@3.1.0: {}
totalist@3.0.1: {}
diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml
index ad7803f4..6afc112e 100644
--- a/pnpm-workspace.yaml
+++ b/pnpm-workspace.yaml
@@ -8,6 +8,5 @@ catalog:
'@eslint/js': ^10.0.1
eslint: ^10.8.1
eslint-config-prettier: ^10.1.8
- prettier: ^3.9.6
- prettier-plugin-tailwindcss: ^0.7.4
+ oxfmt: ^0.63.0
typescript: ^5.9.3