From 5223d3d8d7c23e4f303376e4b638e1a49355fdaa Mon Sep 17 00:00:00 2001 From: Matthias Meister Date: Fri, 3 Apr 2026 21:26:24 +0200 Subject: [PATCH] fix(canvas): refresh sync engine hook dependencies --- .../use-canvas-sync-engine-hook.test.tsx | 173 +++++++++ .../__tests__/use-canvas-sync-engine.test.ts | 12 +- components/canvas/use-canvas-sync-engine.ts | 131 ++++--- package.json | 1 + pnpm-lock.yaml | 330 ++++++++++++++++-- vitest.config.ts | 1 + 6 files changed, 570 insertions(+), 78 deletions(-) create mode 100644 components/canvas/__tests__/use-canvas-sync-engine-hook.test.tsx diff --git a/components/canvas/__tests__/use-canvas-sync-engine-hook.test.tsx b/components/canvas/__tests__/use-canvas-sync-engine-hook.test.tsx new file mode 100644 index 0000000..680681d --- /dev/null +++ b/components/canvas/__tests__/use-canvas-sync-engine-hook.test.tsx @@ -0,0 +1,173 @@ +// @vitest-environment jsdom + +import { act, useEffect, useRef, useState } from "react"; +import { createRoot, type Root } from "react-dom/client"; +import type { Edge as RFEdge, Node as RFNode } from "@xyflow/react"; +import { afterEach, describe, expect, it, vi } from "vitest"; + +import type { Id } from "@/convex/_generated/dataModel"; + +const mocks = vi.hoisted(() => ({ + enqueueCanvasSyncOp: vi.fn(async () => ({ replacedIds: [] as string[] })), + countCanvasSyncOps: vi.fn(async () => 0), + listCanvasSyncOps: vi.fn(async () => []), + mutationMocks: new Map>(), +})); + +vi.mock("@/convex/_generated/api", () => ({ + api: { + nodes: { + move: "nodes.move", + resize: "nodes.resize", + updateData: "nodes.updateData", + create: "nodes.create", + createWithEdgeFromSource: "nodes.createWithEdgeFromSource", + createWithEdgeToTarget: "nodes.createWithEdgeToTarget", + createWithEdgeSplit: "nodes.createWithEdgeSplit", + batchRemove: "nodes.batchRemove", + splitEdgeAtExistingNode: "nodes.splitEdgeAtExistingNode", + }, + edges: { + create: "edges.create", + remove: "edges.remove", + }, + }, +})); + +vi.mock("convex/react", () => ({ + useConvexConnectionState: () => ({ isWebSocketConnected: true }), + useMutation: (key: unknown) => { + let mutation = mocks.mutationMocks.get(key); + if (!mutation) { + mutation = vi.fn(async () => undefined); + Object.assign(mutation, { + withOptimisticUpdate: () => mutation, + }); + mocks.mutationMocks.set(key, mutation); + } + return mutation; + }, +})); + +vi.mock("@/lib/canvas-op-queue", () => ({ + ackCanvasSyncOp: vi.fn(async () => undefined), + countCanvasSyncOps: mocks.countCanvasSyncOps, + dropCanvasSyncOpsByClientRequestIds: vi.fn(async () => []), + dropCanvasSyncOpsByEdgeIds: vi.fn(async () => []), + dropCanvasSyncOpsByNodeIds: vi.fn(async () => []), + dropExpiredCanvasSyncOps: vi.fn(async () => []), + enqueueCanvasSyncOp: mocks.enqueueCanvasSyncOp, + listCanvasSyncOps: mocks.listCanvasSyncOps, + markCanvasSyncOpFailed: vi.fn(async () => undefined), + remapCanvasSyncNodeId: vi.fn(async () => 0), +})); + +vi.mock("@/lib/canvas-local-persistence", () => ({ + dropCanvasOpsByClientRequestIds: vi.fn(() => []), + dropCanvasOpsByEdgeIds: vi.fn(() => []), + dropCanvasOpsByNodeIds: vi.fn(() => []), + enqueueCanvasOp: vi.fn(() => "op-1"), + remapCanvasOpNodeId: vi.fn(() => 0), + resolveCanvasOp: vi.fn(() => undefined), + resolveCanvasOps: vi.fn(() => undefined), +})); + +vi.mock("@/lib/toast", () => ({ + toast: { + info: vi.fn(), + warning: vi.fn(), + }, +})); + +import { useCanvasSyncEngine } from "@/components/canvas/use-canvas-sync-engine"; + +const asCanvasId = (id: string): Id<"canvases"> => id as Id<"canvases">; +const asNodeId = (id: string): Id<"nodes"> => id as Id<"nodes">; + +const latestHookValueRef: { + current: ReturnType | null; +} = { current: null }; + +(globalThis as typeof globalThis & { IS_REACT_ACT_ENVIRONMENT?: boolean }).IS_REACT_ACT_ENVIRONMENT = true; + +function HookHarness({ canvasId }: { canvasId: Id<"canvases"> }) { + const [, setNodes] = useState([]); + const [edges, setEdges] = useState([]); + const edgesRef = useRef(edges); + const deletingNodeIds = useRef(new Set()); + const [, setAssetBrowserTargetNodeId] = useState(null); + const [, setEdgeSyncNonce] = useState(0); + + useEffect(() => { + edgesRef.current = edges; + }, [edges]); + + const hookValue = useCanvasSyncEngine({ + canvasId, + setNodes, + setEdges, + edgesRef, + setAssetBrowserTargetNodeId, + setEdgeSyncNonce, + deletingNodeIds, + }); + + useEffect(() => { + latestHookValueRef.current = hookValue; + }, [hookValue]); + + return null; +} + +describe("useCanvasSyncEngine hook wiring", () => { + let container: HTMLDivElement | null = null; + let root: Root | null = null; + + afterEach(async () => { + latestHookValueRef.current = null; + mocks.mutationMocks.clear(); + vi.clearAllMocks(); + if (root) { + await act(async () => { + root?.unmount(); + }); + } + container?.remove(); + root = null; + container = null; + }); + + it("uses the latest canvas id after rerendering the mounted hook", async () => { + container = document.createElement("div"); + document.body.appendChild(container); + root = createRoot(container); + + await act(async () => { + root?.render(); + }); + + await act(async () => { + root?.render(); + }); + + await act(async () => { + await latestHookValueRef.current?.actions.resizeNode({ + nodeId: asNodeId("node-1"), + width: 480, + height: 320, + }); + }); + + expect(mocks.enqueueCanvasSyncOp).toHaveBeenLastCalledWith( + expect.objectContaining({ + canvasId: "canvas-2", + type: "resizeNode", + payload: { + nodeId: "node-1", + width: 480, + height: 320, + }, + }), + ); + }); +}); diff --git a/components/canvas/__tests__/use-canvas-sync-engine.test.ts b/components/canvas/__tests__/use-canvas-sync-engine.test.ts index 4c78c42..1778e8a 100644 --- a/components/canvas/__tests__/use-canvas-sync-engine.test.ts +++ b/components/canvas/__tests__/use-canvas-sync-engine.test.ts @@ -14,9 +14,9 @@ describe("useCanvasSyncEngine", () => { const controller = createCanvasSyncEngineController({ canvasId: asCanvasId("canvas-1"), isSyncOnline: true, - enqueueSyncMutation, - runBatchRemoveNodes, - runSplitEdgeAtExistingNode, + getEnqueueSyncMutation: () => enqueueSyncMutation, + getRunBatchRemoveNodes: () => runBatchRemoveNodes, + getRunSplitEdgeAtExistingNode: () => runSplitEdgeAtExistingNode, }); controller.pendingMoveAfterCreateRef.current.set("req-1", { @@ -48,9 +48,9 @@ describe("useCanvasSyncEngine", () => { const controller = createCanvasSyncEngineController({ canvasId: asCanvasId("canvas-1"), isSyncOnline: true, - enqueueSyncMutation, - runBatchRemoveNodes: vi.fn(async () => undefined), - runSplitEdgeAtExistingNode: vi.fn(async () => undefined), + getEnqueueSyncMutation: () => enqueueSyncMutation, + getRunBatchRemoveNodes: () => vi.fn(async () => undefined), + getRunSplitEdgeAtExistingNode: () => vi.fn(async () => undefined), }); await controller.queueNodeResize({ diff --git a/components/canvas/use-canvas-sync-engine.ts b/components/canvas/use-canvas-sync-engine.ts index 07e23e7..019ea72 100644 --- a/components/canvas/use-canvas-sync-engine.ts +++ b/components/canvas/use-canvas-sync-engine.ts @@ -51,6 +51,12 @@ type QueueSyncMutation = ( payload: CanvasSyncOpPayloadByType[TType], ) => Promise; +type DynamicValue = T | (() => T); + +function resolveDynamicValue(value: DynamicValue): T { + return typeof value === "function" ? (value as () => T)() : value; +} + type RunMoveNodeMutation = (args: { nodeId: Id<"nodes">; positionX: number; @@ -75,16 +81,18 @@ type RunSplitEdgeAtExistingNodeMutation = (args: { }) => Promise; type CanvasSyncEngineControllerParams = { - canvasId: Id<"canvases">; - isSyncOnline: boolean | (() => boolean); - enqueueSyncMutation: QueueSyncMutation; - runMoveNodeMutation?: RunMoveNodeMutation; - runBatchRemoveNodes?: RunBatchRemoveNodesMutation; - runSplitEdgeAtExistingNode?: RunSplitEdgeAtExistingNodeMutation; - setAssetBrowserTargetNodeId?: Dispatch>; - setNodes?: Dispatch>; - setEdges?: Dispatch>; - deletingNodeIds?: MutableRefObject>; + canvasId: DynamicValue>; + isSyncOnline: DynamicValue; + getEnqueueSyncMutation: () => QueueSyncMutation; + getRunMoveNodeMutation?: () => RunMoveNodeMutation | undefined; + getRunBatchRemoveNodes?: () => RunBatchRemoveNodesMutation | undefined; + getRunSplitEdgeAtExistingNode?: () => RunSplitEdgeAtExistingNodeMutation | undefined; + getSetAssetBrowserTargetNodeId?: () => + | Dispatch> + | undefined; + getSetNodes?: () => Dispatch> | undefined; + getSetEdges?: () => Dispatch> | undefined; + getDeletingNodeIds?: () => MutableRefObject> | undefined; }; type UseCanvasSyncEngineParams = { @@ -165,17 +173,17 @@ function summarizeResizePayload(payload: unknown): Record { export function createCanvasSyncEngineController({ canvasId, isSyncOnline, - enqueueSyncMutation, - runMoveNodeMutation, - runBatchRemoveNodes, - runSplitEdgeAtExistingNode, - setAssetBrowserTargetNodeId, - setNodes, - setEdges, - deletingNodeIds, + getEnqueueSyncMutation, + getRunMoveNodeMutation, + getRunBatchRemoveNodes, + getRunSplitEdgeAtExistingNode, + getSetAssetBrowserTargetNodeId, + getSetNodes, + getSetEdges, + getDeletingNodeIds, }: CanvasSyncEngineControllerParams) { - const getIsSyncOnline = () => - typeof isSyncOnline === "function" ? isSyncOnline() : isSyncOnline; + const getCanvasId = () => resolveDynamicValue(canvasId); + const getIsSyncOnline = () => resolveDynamicValue(isSyncOnline); const pendingMoveAfterCreateRef = { current: new Map(), @@ -206,7 +214,7 @@ export function createCanvasSyncEngineController({ const pendingResize = pendingResizeAfterCreateRef.current.get(clientRequestId); if (!pendingResize) return; pendingResizeAfterCreateRef.current.delete(clientRequestId); - await enqueueSyncMutation("resizeNode", { + await getEnqueueSyncMutation()("resizeNode", { nodeId: realId, width: pendingResize.width, height: pendingResize.height, @@ -220,7 +228,7 @@ export function createCanvasSyncEngineController({ if (!pendingDataAfterCreateRef.current.has(clientRequestId)) return; const pendingData = pendingDataAfterCreateRef.current.get(clientRequestId); pendingDataAfterCreateRef.current.delete(clientRequestId); - await enqueueSyncMutation("updateData", { + await getEnqueueSyncMutation()("updateData", { nodeId: realId, data: pendingData, }); @@ -233,7 +241,7 @@ export function createCanvasSyncEngineController({ }): Promise => { const rawNodeId = args.nodeId as string; if (!isOptimisticNodeId(rawNodeId) || !getIsSyncOnline()) { - await enqueueSyncMutation("resizeNode", args); + await getEnqueueSyncMutation()("resizeNode", args); return; } @@ -243,7 +251,7 @@ export function createCanvasSyncEngineController({ : undefined; if (resolvedRealId) { - await enqueueSyncMutation("resizeNode", { + await getEnqueueSyncMutation()("resizeNode", { nodeId: resolvedRealId, width: args.width, height: args.height, @@ -265,7 +273,7 @@ export function createCanvasSyncEngineController({ }): Promise => { const rawNodeId = args.nodeId as string; if (!isOptimisticNodeId(rawNodeId) || !getIsSyncOnline()) { - await enqueueSyncMutation("updateData", args); + await getEnqueueSyncMutation()("updateData", args); return; } @@ -275,7 +283,7 @@ export function createCanvasSyncEngineController({ : undefined; if (resolvedRealId) { - await enqueueSyncMutation("updateData", { + await getEnqueueSyncMutation()("updateData", { nodeId: resolvedRealId, data: args.data, }); @@ -308,6 +316,9 @@ export function createCanvasSyncEngineController({ resolvedRealIdByClientRequestRef.current.delete(clientRequestId); const realNodeId = realId as string; + const deletingNodeIds = getDeletingNodeIds?.(); + const setNodes = getSetNodes?.(); + const setEdges = getSetEdges?.(); deletingNodeIds?.current.add(realNodeId); setNodes?.((current) => current.filter((node) => node.id !== realNodeId)); setEdges?.((current) => @@ -315,13 +326,15 @@ export function createCanvasSyncEngineController({ (edge) => edge.source !== realNodeId && edge.target !== realNodeId, ), ); - if (runBatchRemoveNodes) { - await runBatchRemoveNodes({ nodeIds: [realId] }); + const batchRemoveNodes = getRunBatchRemoveNodes?.(); + if (batchRemoveNodes) { + await batchRemoveNodes({ nodeIds: [realId] }); } return; } const optimisticNodeId = `${OPTIMISTIC_NODE_PREFIX}${clientRequestId}`; + const setAssetBrowserTargetNodeId = getSetAssetBrowserTargetNodeId?.(); setAssetBrowserTargetNodeId?.((current) => current === optimisticNodeId ? (realId as string) : current, ); @@ -336,9 +349,10 @@ export function createCanvasSyncEngineController({ pendingMoveAfterCreateRef.current.delete(clientRequestId); } resolvedRealIdByClientRequestRef.current.delete(clientRequestId); - if (runSplitEdgeAtExistingNode) { - await runSplitEdgeAtExistingNode({ - canvasId, + const splitEdgeAtExistingNode = getRunSplitEdgeAtExistingNode?.(); + if (splitEdgeAtExistingNode) { + await splitEdgeAtExistingNode({ + canvasId: getCanvasId(), splitEdgeId: splitPayload.intersectedEdgeId, middleNodeId: realId, splitSourceHandle: splitPayload.intersectedSourceHandle, @@ -361,14 +375,15 @@ export function createCanvasSyncEngineController({ x: pendingMove.positionX, y: pendingMove.positionY, }); - if (runMoveNodeMutation) { - await runMoveNodeMutation({ + const moveNodeMutation = getRunMoveNodeMutation?.(); + if (moveNodeMutation) { + await moveNodeMutation({ nodeId: realId, positionX: pendingMove.positionX, positionY: pendingMove.positionY, }); } else { - await enqueueSyncMutation("moveNode", { + await getEnqueueSyncMutation()("moveNode", { nodeId: realId, positionX: pendingMove.positionX, positionY: pendingMove.positionY, @@ -396,9 +411,10 @@ export function createCanvasSyncEngineController({ const splitPayload = pendingEdgeSplitByClientRequestRef.current.get(clientRequestId); if (splitPayload) { pendingEdgeSplitByClientRequestRef.current.delete(clientRequestId); - if (runSplitEdgeAtExistingNode) { - await runSplitEdgeAtExistingNode({ - canvasId, + const splitEdgeAtExistingNode = getRunSplitEdgeAtExistingNode?.(); + if (splitEdgeAtExistingNode) { + await splitEdgeAtExistingNode({ + canvasId: getCanvasId(), splitEdgeId: splitPayload.intersectedEdgeId, middleNodeId: resolvedRealId, splitSourceHandle: splitPayload.intersectedSourceHandle, @@ -417,14 +433,15 @@ export function createCanvasSyncEngineController({ x: pendingMove.positionX, y: pendingMove.positionY, }); - if (runMoveNodeMutation) { - await runMoveNodeMutation({ + const moveNodeMutation = getRunMoveNodeMutation?.(); + if (moveNodeMutation) { + await moveNodeMutation({ nodeId: resolvedRealId, positionX: pendingMove.positionX, positionY: pendingMove.positionY, }); } else { - await enqueueSyncMutation("moveNode", { + await getEnqueueSyncMutation()("moveNode", { nodeId: resolvedRealId, positionX: pendingMove.positionX, positionY: pendingMove.positionY, @@ -477,9 +494,21 @@ export function useCanvasSyncEngine({ const isSyncOnline = isBrowserOnline === true && connectionState.isWebSocketConnected === true; + const canvasIdRef = useRef(canvasId); + canvasIdRef.current = canvasId; const isSyncOnlineRef = useRef(isSyncOnline); isSyncOnlineRef.current = isSyncOnline; + const setNodesRef = useRef(setNodes); + setNodesRef.current = setNodes; + const setEdgesRef = useRef(setEdges); + setEdgesRef.current = setEdges; + const setAssetBrowserTargetNodeIdRef = useRef(setAssetBrowserTargetNodeId); + setAssetBrowserTargetNodeIdRef.current = setAssetBrowserTargetNodeId; + const deletingNodeIdsRef = useRef(deletingNodeIds); + deletingNodeIdsRef.current = deletingNodeIds; + const enqueueSyncMutationRef = useRef(async () => undefined); + const runMoveNodeMutationRef = useRef(async () => undefined); const runBatchRemoveNodesMutationRef = useRef( async () => {}, ); @@ -514,6 +543,7 @@ export function useCanvasSyncEngine({ }, [canvasId, refreshPendingSyncCount], ); + enqueueSyncMutationRef.current = enqueueSyncMutation; const runMoveNodeMutation = useCallback( async (args) => { @@ -521,6 +551,7 @@ export function useCanvasSyncEngine({ }, [enqueueSyncMutation], ); + runMoveNodeMutationRef.current = runMoveNodeMutation; const runBatchMoveNodesMutation = useCallback( async (args: { @@ -748,20 +779,22 @@ export function useCanvasSyncEngine({ const controllerRef = useRef(null); if (controllerRef.current === null) { controllerRef.current = createCanvasSyncEngineController({ - canvasId, + canvasId: () => canvasIdRef.current, isSyncOnline: () => isSyncOnlineRef.current, - enqueueSyncMutation, - runMoveNodeMutation, - runBatchRemoveNodes: async (args) => { + getEnqueueSyncMutation: () => enqueueSyncMutationRef.current, + getRunMoveNodeMutation: () => runMoveNodeMutationRef.current, + getRunBatchRemoveNodes: () => async (args: { nodeIds: Id<"nodes">[] }) => { await runBatchRemoveNodesMutationRef.current(args); }, - runSplitEdgeAtExistingNode: async (args) => { + getRunSplitEdgeAtExistingNode: () => async ( + args: Parameters[0], + ) => { await runSplitEdgeAtExistingNodeMutationRef.current(args); }, - setAssetBrowserTargetNodeId, - setNodes, - setEdges, - deletingNodeIds, + getSetAssetBrowserTargetNodeId: () => setAssetBrowserTargetNodeIdRef.current, + getSetNodes: () => setNodesRef.current, + getSetEdges: () => setEdgesRef.current, + getDeletingNodeIds: () => deletingNodeIdsRef.current, }); } const controller = controllerRef.current; diff --git a/package.json b/package.json index 9601f0a..8efea08 100644 --- a/package.json +++ b/package.json @@ -57,6 +57,7 @@ "@types/react-dom": "^19", "eslint": "^9", "eslint-config-next": "16.2.1", + "jsdom": "^29.0.1", "tailwindcss": "^4", "typescript": "^5", "vitest": "^3.2.4" diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index a32b6e4..ca26f37 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -10,10 +10,10 @@ importers: dependencies: '@convex-dev/better-auth': specifier: ^0.11.3 - version: 0.11.3(@standard-schema/spec@1.1.0)(better-auth@1.5.6(@opentelemetry/api@1.9.0)(next@16.2.1(@babel/core@7.29.0)(@opentelemetry/api@1.9.0)(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(vitest@3.2.4(@types/node@20.19.37)(jiti@2.6.1)(lightningcss@1.32.0)(msw@2.12.14(@types/node@20.19.37)(typescript@5.9.3))(terser@5.46.1)))(convex@1.34.0(react@19.2.4))(hono@4.12.9)(react@19.2.4)(typescript@5.9.3) + version: 0.11.3(@standard-schema/spec@1.1.0)(better-auth@1.5.6(@opentelemetry/api@1.9.0)(next@16.2.1(@babel/core@7.29.0)(@opentelemetry/api@1.9.0)(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(vitest@3.2.4(@types/node@20.19.37)(jiti@2.6.1)(jsdom@29.0.1(@noble/hashes@2.0.1))(lightningcss@1.32.0)(msw@2.12.14(@types/node@20.19.37)(typescript@5.9.3))(terser@5.46.1)))(convex@1.34.0(react@19.2.4))(hono@4.12.9)(react@19.2.4)(typescript@5.9.3) '@daveyplate/better-auth-ui': specifier: ^3.4.0 - version: 3.4.0(43fe9e8f7c24dd7a61ee43b650bb480d) + version: 3.4.0(33090e10f4680aa961584df50b0a91cd) '@dnd-kit/core': specifier: ^6.3.1 version: 6.3.1(react-dom@19.2.4(react@19.2.4))(react@19.2.4) @@ -25,7 +25,7 @@ importers: version: 0.1.97 '@polar-sh/better-auth': specifier: ^1.8.3 - version: 1.8.3(@polar-sh/sdk@0.46.7)(@stripe/react-stripe-js@4.0.2(@stripe/stripe-js@7.9.0)(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(@stripe/stripe-js@7.9.0)(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(better-auth@1.5.6(@opentelemetry/api@1.9.0)(next@16.2.1(@babel/core@7.29.0)(@opentelemetry/api@1.9.0)(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(vitest@3.2.4(@types/node@20.19.37)(jiti@2.6.1)(lightningcss@1.32.0)(msw@2.12.14(@types/node@20.19.37)(typescript@5.9.3))(terser@5.46.1)))(react-dom@19.2.4(react@19.2.4))(react-is@16.13.1)(react@19.2.4)(redux@5.0.1)(zod@4.3.6) + version: 1.8.3(@polar-sh/sdk@0.46.7)(@stripe/react-stripe-js@4.0.2(@stripe/stripe-js@7.9.0)(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(@stripe/stripe-js@7.9.0)(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(better-auth@1.5.6(@opentelemetry/api@1.9.0)(next@16.2.1(@babel/core@7.29.0)(@opentelemetry/api@1.9.0)(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(vitest@3.2.4(@types/node@20.19.37)(jiti@2.6.1)(jsdom@29.0.1(@noble/hashes@2.0.1))(lightningcss@1.32.0)(msw@2.12.14(@types/node@20.19.37)(typescript@5.9.3))(terser@5.46.1)))(react-dom@19.2.4(react@19.2.4))(react-is@16.13.1)(react@19.2.4)(redux@5.0.1)(zod@4.3.6) '@polar-sh/sdk': specifier: ^0.46.7 version: 0.46.7 @@ -40,7 +40,7 @@ importers: version: 12.10.1(@types/react@19.2.14)(immer@11.1.4)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) better-auth: specifier: ^1.5.6 - version: 1.5.6(@opentelemetry/api@1.9.0)(next@16.2.1(@babel/core@7.29.0)(@opentelemetry/api@1.9.0)(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(vitest@3.2.4(@types/node@20.19.37)(jiti@2.6.1)(lightningcss@1.32.0)(msw@2.12.14(@types/node@20.19.37)(typescript@5.9.3))(terser@5.46.1)) + version: 1.5.6(@opentelemetry/api@1.9.0)(next@16.2.1(@babel/core@7.29.0)(@opentelemetry/api@1.9.0)(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(vitest@3.2.4(@types/node@20.19.37)(jiti@2.6.1)(jsdom@29.0.1(@noble/hashes@2.0.1))(lightningcss@1.32.0)(msw@2.12.14(@types/node@20.19.37)(typescript@5.9.3))(terser@5.46.1)) class-variance-authority: specifier: ^0.7.1 version: 0.7.1 @@ -138,6 +138,9 @@ importers: eslint-config-next: specifier: 16.2.1 version: 16.2.1(@typescript-eslint/parser@8.57.2(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3) + jsdom: + specifier: ^29.0.1 + version: 29.0.1(@noble/hashes@2.0.1) tailwindcss: specifier: ^4 version: 4.2.2 @@ -146,7 +149,7 @@ importers: version: 5.9.3 vitest: specifier: ^3.2.4 - version: 3.2.4(@types/node@20.19.37)(jiti@2.6.1)(lightningcss@1.32.0)(msw@2.12.14(@types/node@20.19.37)(typescript@5.9.3))(terser@5.46.1) + version: 3.2.4(@types/node@20.19.37)(jiti@2.6.1)(jsdom@29.0.1(@noble/hashes@2.0.1))(lightningcss@1.32.0)(msw@2.12.14(@types/node@20.19.37)(typescript@5.9.3))(terser@5.46.1) packages: @@ -154,6 +157,17 @@ packages: resolution: {integrity: sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==} engines: {node: '>=10'} + '@asamuzakjp/css-color@5.1.4': + resolution: {integrity: sha512-503MoTEmPSyEJ7zQ+5vlkwPtkyxDhbDwR9ajk/jpPGrCLiUFHzgEG4iViUPKdGlZPRT1mWSPSbDL2qkOoLU4vg==} + engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0} + + '@asamuzakjp/dom-selector@7.0.4': + resolution: {integrity: sha512-jXR6x4AcT3eIrS2fSNAwJpwirOkGcd+E7F7CP3zjdTqz9B/2huHOL8YJZBgekKwLML+u7qB/6P1LXQuMScsx0w==} + engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0} + + '@asamuzakjp/nwsapi@2.3.9': + resolution: {integrity: sha512-n8GuYSrI9bF7FFZ/SjhwevlHc8xaVlb/7HmHelnc/PZXBD2ZR49NnN9sMMuDdEGPeeRQ5d0hqlSlEpgCX3Wl0Q==} + '@babel/code-frame@7.29.0': resolution: {integrity: sha512-9NhCeYjq9+3uxgdtp20LSiJXJvN0FeCtNGpJxuMFZ1Kv3cWUNb6DOhJwUvcVCzKGR66cw4njwM6hrJLqgOwbcw==} engines: {node: '>=6.9.0'} @@ -375,6 +389,10 @@ packages: '@better-fetch/fetch@1.1.21': resolution: {integrity: sha512-/ImESw0sskqlVR94jB+5+Pxjf+xBwDZF/N5+y2/q4EqD7IARUTSpPfIo8uf39SYpCxyOCtbyYpUrZ3F/k0zT4A==} + '@bramus/specificity@2.4.2': + resolution: {integrity: sha512-ctxtJ/eA+t+6q2++vj5j7FYX3nRu311q1wfYH3xjlLOsczhlhxAg2FWNUXhpGvAw3BWo1xBcvOV6/YLc2r5FJw==} + hasBin: true + '@captchafox/react@1.11.0': resolution: {integrity: sha512-/oF/PahBiNwk/ZVC0XQBl9hHwwRo7Eg8k6tz0U835jH15OJpIZvGHPN4xZ5cRTct+sXAdVcMqfuEP0bsg4yTBw==} peerDependencies: @@ -391,6 +409,42 @@ packages: convex: ^1.25.0 react: ^18.3.1 || ^19.0.0 + '@csstools/color-helpers@6.0.2': + resolution: {integrity: sha512-LMGQLS9EuADloEFkcTBR3BwV/CGHV7zyDxVRtVDTwdI2Ca4it0CCVTT9wCkxSgokjE5Ho41hEPgb8OEUwoXr6Q==} + engines: {node: '>=20.19.0'} + + '@csstools/css-calc@3.1.1': + resolution: {integrity: sha512-HJ26Z/vmsZQqs/o3a6bgKslXGFAungXGbinULZO3eMsOyNJHeBBZfup5FiZInOghgoM4Hwnmw+OgbJCNg1wwUQ==} + engines: {node: '>=20.19.0'} + peerDependencies: + '@csstools/css-parser-algorithms': ^4.0.0 + '@csstools/css-tokenizer': ^4.0.0 + + '@csstools/css-color-parser@4.0.2': + resolution: {integrity: sha512-0GEfbBLmTFf0dJlpsNU7zwxRIH0/BGEMuXLTCvFYxuL1tNhqzTbtnFICyJLTNK4a+RechKP75e7w42ClXSnJQw==} + engines: {node: '>=20.19.0'} + peerDependencies: + '@csstools/css-parser-algorithms': ^4.0.0 + '@csstools/css-tokenizer': ^4.0.0 + + '@csstools/css-parser-algorithms@4.0.0': + resolution: {integrity: sha512-+B87qS7fIG3L5h3qwJ/IFbjoVoOe/bpOdh9hAjXbvx0o8ImEmUsGXN0inFOnk2ChCFgqkkGFQ+TpM5rbhkKe4w==} + engines: {node: '>=20.19.0'} + peerDependencies: + '@csstools/css-tokenizer': ^4.0.0 + + '@csstools/css-syntax-patches-for-csstree@1.1.2': + resolution: {integrity: sha512-5GkLzz4prTIpoyeUiIu3iV6CSG3Plo7xRVOFPKI7FVEJ3mZ0A8SwK0XU3Gl7xAkiQ+mDyam+NNp875/C5y+jSA==} + peerDependencies: + css-tree: ^3.2.1 + peerDependenciesMeta: + css-tree: + optional: true + + '@csstools/css-tokenizer@4.0.0': + resolution: {integrity: sha512-QxULHAm7cNu72w97JUNCBFODFaXpbDg+dP8b/oWFAZ2MTRppA3U00Y2L1HqaS4J6yBqxwa/Y3nMBaxVKbB/NsA==} + engines: {node: '>=20.19.0'} + '@date-fns/tz@1.4.1': resolution: {integrity: sha512-P5LUNhtbj6YfI3iJjw5EL9eUAG6OitD0W3fWQcpQjDRc/QIsL0tRNuO1PcDvPccWL1fSTXXdE1ds+l95DV/OFA==} @@ -671,6 +725,15 @@ packages: resolution: {integrity: sha512-43/qtrDUokr7LJqoF2c3+RInu/t4zfrpYdoSDfYyhg52rwLV6TnOvdG4fXm7IkSB3wErkcmJS9iEhjVtOSEjjA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@exodus/bytes@1.15.0': + resolution: {integrity: sha512-UY0nlA+feH81UGSHv92sLEPLCeZFjXOuHhrIo0HQydScuQc8s0A7kL/UdgwgDq8g8ilksmuoF35YVTNphV2aBQ==} + engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0} + peerDependencies: + '@noble/hashes': ^1.8.0 || ^2.0.0 + peerDependenciesMeta: + '@noble/hashes': + optional: true + '@fastify/otel@0.17.1': resolution: {integrity: sha512-K4wyxfUZx2ux5o+b6BtTqouYFVILohLZmSbA2tKUueJstNcBnoGPVhllCaOvbQ3ZrXdUxUC/fyrSWSCqHhdOPg==} peerDependencies: @@ -3732,6 +3795,9 @@ packages: zod: optional: true + bidi-js@1.0.3: + resolution: {integrity: sha512-RKshQI1R3YQ+n9YJz2QQ147P66ELpa1FQEg20Dk8oW9t2KgLbpDLLp9aGZ7y8WHSshDknG0bknqGw5/tyCs5tw==} + bmp-ts@1.0.9: resolution: {integrity: sha512-cTEHk2jLrPyi+12M3dhpEbnnPOsaZuq7C45ylbbQIiWgDFZq4UVYPEY5mlqjvsj/6gJv9qX5sa+ebDzLXT28Vw==} @@ -3982,6 +4048,10 @@ packages: resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==} engines: {node: '>= 8'} + css-tree@3.2.1: + resolution: {integrity: sha512-X7sjQzceUhu1u7Y/ylrRZFU2FS6LRiFVp6rKLPg23y3x3c3DOKAwuXGDp+PAGjh6CSnCjYeAul8pcT8bAl+lSA==} + engines: {node: ^10 || ^12.20.0 || ^14.13.0 || >=15.0.0} + cssesc@3.0.0: resolution: {integrity: sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==} engines: {node: '>=4'} @@ -4063,6 +4133,10 @@ packages: resolution: {integrity: sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==} engines: {node: '>= 12'} + data-urls@7.0.0: + resolution: {integrity: sha512-23XHcCF+coGYevirZceTVD7NdJOqVn+49IHyxgszm+JIiHLoB2TkmPtsYkNWT1pvRSGkc35L6NHs0yHkN2SumA==} + engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0} + data-view-buffer@1.0.2: resolution: {integrity: sha512-EmKO5V3OLXh1rtK2wgXRansaK1/mtVdTUEiEI0W8RkvgT05kfxaH29PliLnpLP73yYO6142Q72QNa8Wx/A5CqQ==} engines: {node: '>= 0.4'} @@ -4101,6 +4175,9 @@ packages: decimal.js-light@2.5.1: resolution: {integrity: sha512-qIMFpTMZmny+MMIitAB6D7iVPEorVw6YQRWkvarTkT4tBeSLLiHzcwj6q0MmYSFCiVpiqPJTJEYIrpcPzVEIvg==} + decimal.js@10.6.0: + resolution: {integrity: sha512-YpgQiITW3JXGntzdUmyUR1V812Hn8T1YVXhCu+wO3OpS4eU9l4YdD3qjyiKdV6mvV29zapkMeD390UVEf2lkUg==} + dedent@1.7.2: resolution: {integrity: sha512-WzMx3mW98SN+zn3hgemf4OzdmyNhhhKz5Ay0pUfQiMQ3e1g+xmTJWp/pKdwKVXhdSkAEGIIzqeuWrL3mV/AXbA==} peerDependencies: @@ -4228,6 +4305,10 @@ packages: resolution: {integrity: sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==} engines: {node: '>=0.12'} + entities@6.0.1: + resolution: {integrity: sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g==} + engines: {node: '>=0.12'} + env-paths@2.2.1: resolution: {integrity: sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==} engines: {node: '>=6'} @@ -4753,6 +4834,10 @@ packages: resolution: {integrity: sha512-wy3T8Zm2bsEvxKZM5w21VdHDDcwVS1yUFFY6i8UobSsKfFceT7TOwhbhfKsDyx7tYQlmRM5FLpIuYvNFyjctiA==} engines: {node: '>=16.9.0'} + html-encoding-sniffer@6.0.0: + resolution: {integrity: sha512-CV9TW3Y3f8/wT0BRFc1/KAVQ3TUHiXmaAb6VW9vtiMFf7SLoMd1PdAc4W3KFOFETBJUb90KatHqlsZMWV+R9Gg==} + engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0} + html-to-text@9.0.5: resolution: {integrity: sha512-qY60FjREgVZL03vJU6IfMV4GDjGBIoOyvuFdpBDIX9yTlDw0TjxVBQp+P8NvpdIXNJvfWBTNul7fsAQJq2FNpg==} engines: {node: '>=14'} @@ -4960,6 +5045,9 @@ packages: resolution: {integrity: sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==} engines: {node: '>=12'} + is-potential-custom-element-name@1.0.1: + resolution: {integrity: sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==} + is-promise@4.0.0: resolution: {integrity: sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ==} @@ -5075,6 +5163,15 @@ packages: resolution: {integrity: sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==} hasBin: true + jsdom@29.0.1: + resolution: {integrity: sha512-z6JOK5gRO7aMybVq/y/MlIpKh8JIi68FBKMUtKkK2KH/wMSRlCxQ682d08LB9fYXplyY/UXG8P4XXTScmdjApg==} + engines: {node: ^20.19.0 || ^22.13.0 || >=24.0.0} + peerDependencies: + canvas: ^3.0.0 + peerDependenciesMeta: + canvas: + optional: true + jsesc@3.1.0: resolution: {integrity: sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==} engines: {node: '>=6'} @@ -5292,6 +5389,9 @@ packages: resolution: {integrity: sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==} engines: {node: '>= 0.4'} + mdn-data@2.27.1: + resolution: {integrity: sha512-9Yubnt3e8A0OKwxYSXyhLymGW4sCufcLG6VdiDdUGVkPhpqLxlvP5vl1983gQjJl3tqbrM731mjaZaP68AgosQ==} + media-typer@1.1.0: resolution: {integrity: sha512-aisnrDP4GNe06UcKFnV5bfMNPBUw4jsLGaWwWfnH3v02GnBuXX2MCVn5RbrWo0j3pczUilYblq7fQ7Nw2t5XKw==} engines: {node: '>= 0.8'} @@ -5603,6 +5703,9 @@ packages: resolution: {integrity: sha512-TXfryirbmq34y8QBwgqCVLi+8oA3oWx2eAnSn62ITyEhEYaWRlVZ2DvMM9eZbMs/RfxPu/PK/aBLyGj4IrqMHw==} engines: {node: '>=18'} + parse5@8.0.0: + resolution: {integrity: sha512-9m4m5GSgXjL4AjumKzq1Fgfp3Z8rsvjRNbnkVwfu2ImRqE5D0LnY2QfDen18FSY9C573YU5XxSapdHZTZ2WolA==} + parseley@0.12.1: resolution: {integrity: sha512-e6qHKe3a9HWr0oMRVDTRhKce+bRO8VGQR3NyVwcjwrbhMmFCX9KszEV35+rn4AdilFAq9VPxP/Fe1wC9Qjd2lw==} @@ -6058,6 +6161,10 @@ packages: resolution: {integrity: sha512-6R3J5M4AcbtLUdZmRv2SygeVaM7IhrLXu9BmnOGmmACak8fiUtOsYNWUS4uK7upbmHIBbLBeFeI//477BKLBzA==} engines: {node: '>=11.0.0'} + saxes@6.0.0: + resolution: {integrity: sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA==} + engines: {node: '>=v12.22.7'} + scheduler@0.27.0: resolution: {integrity: sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q==} @@ -6310,6 +6417,9 @@ packages: resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} engines: {node: '>= 0.4'} + symbol-tree@3.2.4: + resolution: {integrity: sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==} + tagged-tag@1.0.0: resolution: {integrity: sha512-yEFYrVhod+hdNyx7g5Bnkkb0G6si8HJurOoOEgC8B/O0uXLHlaey/65KRv6cuWBNhBgHKAROVpc7QyYqE5gFng==} engines: {node: '>=20'} @@ -6402,6 +6512,10 @@ packages: tr46@0.0.3: resolution: {integrity: sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==} + tr46@6.0.0: + resolution: {integrity: sha512-bLVMLPtstlZ4iMQHpFHTR7GAGj2jxi8Dg0s2h2MafAE4uSWF98FC/3MomU51iQAMf8/qDUbKWf5GxuvvVcXEhw==} + engines: {node: '>=20'} + ts-api-utils@2.5.0: resolution: {integrity: sha512-OJ/ibxhPlqrMM0UiNHJ/0CKQkoKF243/AEmplt3qpRgkW8VG7IfOS41h7V8TjITqdByHzrjcS/2si+y4lIh8NA==} engines: {node: '>=18.12'} @@ -6489,6 +6603,10 @@ packages: undici-types@6.21.0: resolution: {integrity: sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==} + undici@7.24.7: + resolution: {integrity: sha512-H/nlJ/h0ggGC+uRL3ovD+G0i4bqhvsDOpbDv7At5eFLlj2b41L8QliGbnl2H7SnDiYhENphh1tQFJZf+MyfLsQ==} + engines: {node: '>=20.18.1'} + unicorn-magic@0.3.0: resolution: {integrity: sha512-+QBBXBCvifc56fsbuxZQ6Sic3wqqc3WWaqxs58gvJrcOuN83HGTCwz3oS5phzU9LthRNE9VrJCFCLUgHeeFnfA==} engines: {node: '>=18'} @@ -6650,6 +6768,10 @@ packages: jsdom: optional: true + w3c-xmlserializer@5.0.0: + resolution: {integrity: sha512-o8qghlI8NZHU1lLPrpi2+Uq7abh4GGPpYANlalzWxyWteJOCsr/P+oPBA49TOLu5FTZO4d3F9MnWJfiMo4BkmA==} + engines: {node: '>=18'} + warning@4.0.3: resolution: {integrity: sha512-rpJyN222KWIvHJ/F53XSZv0Zl/accqHR8et1kpaMTD/fLCRxtV8iX8czMzY7sVZupTI3zcUTg8eycS2kNF9l6w==} @@ -6667,6 +6789,10 @@ packages: webidl-conversions@3.0.1: resolution: {integrity: sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==} + webidl-conversions@8.0.1: + resolution: {integrity: sha512-BMhLD/Sw+GbJC21C/UgyaZX41nPt8bUTg+jWyDeg7e7YN4xOM05YPSIXceACnXVtqyEw/LMClUQMtMZ+PGGpqQ==} + engines: {node: '>=20'} + webpack-sources@3.3.4: resolution: {integrity: sha512-7tP1PdV4vF+lYPnkMR0jMY5/la2ub5Fc/8VQrrU+lXkiM6C4TjVfGw7iKfyhnTQOsD+6Q/iKw0eFciziRgD58Q==} engines: {node: '>=10.13.0'} @@ -6681,6 +6807,14 @@ packages: webpack-cli: optional: true + whatwg-mimetype@5.0.0: + resolution: {integrity: sha512-sXcNcHOC51uPGF0P/D4NVtrkjSU2fNsm9iog4ZvZJsL3rjoDAzXZhkm2MWt1y+PUdggKAYVoMAIYcs78wJ51Cw==} + engines: {node: '>=20'} + + whatwg-url@16.0.1: + resolution: {integrity: sha512-1to4zXBxmXHV3IiSSEInrreIlu02vUOvrhxJJH5vcxYTBDAx51cqZiKdyTxlecdKNSjj8EcxGBxNf6Vg+945gw==} + engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0} + whatwg-url@5.0.0: resolution: {integrity: sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==} @@ -6746,6 +6880,10 @@ packages: resolution: {integrity: sha512-g/eziiSUNBSsdDJtCLB8bdYEUMj4jR7AGeUo96p/3dTafgjHhpF4RiCFPiRILwjQoDXx5MqkBr4fwWtR3Ky4Wg==} engines: {node: '>=20'} + xml-name-validator@5.0.0: + resolution: {integrity: sha512-EvGK8EJ3DhaHfbRlETOWAS5pO9MZITeauHKJyb8wyajUfQUenkIg2MvLDTZ4T/TgIcm3HU0TFBgWWboAZ30UHg==} + engines: {node: '>=18'} + xml-parse-from-string@1.0.1: resolution: {integrity: sha512-ErcKwJTF54uRzzNMXq2X5sMIy88zJvfN2DmdoQvy7PAFJ+tPRU6ydWuOKNMyfmOjdyBQTFREi60s0Y0SyI0G0g==} @@ -6757,6 +6895,9 @@ packages: resolution: {integrity: sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==} engines: {node: '>=4.0'} + xmlchars@2.2.0: + resolution: {integrity: sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==} + xtend@4.0.2: resolution: {integrity: sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==} engines: {node: '>=0.4'} @@ -6824,6 +6965,24 @@ snapshots: '@alloc/quick-lru@5.2.0': {} + '@asamuzakjp/css-color@5.1.4': + dependencies: + '@csstools/css-calc': 3.1.1(@csstools/css-parser-algorithms@4.0.0(@csstools/css-tokenizer@4.0.0))(@csstools/css-tokenizer@4.0.0) + '@csstools/css-color-parser': 4.0.2(@csstools/css-parser-algorithms@4.0.0(@csstools/css-tokenizer@4.0.0))(@csstools/css-tokenizer@4.0.0) + '@csstools/css-parser-algorithms': 4.0.0(@csstools/css-tokenizer@4.0.0) + '@csstools/css-tokenizer': 4.0.0 + lru-cache: 11.2.7 + + '@asamuzakjp/dom-selector@7.0.4': + dependencies: + '@asamuzakjp/nwsapi': 2.3.9 + bidi-js: 1.0.3 + css-tree: 3.2.1 + is-potential-custom-element-name: 1.0.1 + lru-cache: 11.2.7 + + '@asamuzakjp/nwsapi@2.3.9': {} + '@babel/code-frame@7.29.0': dependencies: '@babel/helper-validator-identifier': 7.28.5 @@ -7010,11 +7169,11 @@ snapshots: '@babel/helper-string-parser': 7.27.1 '@babel/helper-validator-identifier': 7.28.5 - '@better-auth/api-key@1.5.6(@better-auth/core@1.5.6(@better-auth/utils@0.3.1)(@better-fetch/fetch@1.1.21)(@opentelemetry/api@1.9.0)(better-call@1.3.2(zod@4.3.6))(jose@6.2.2)(kysely@0.28.14)(nanostores@1.2.0))(@better-auth/utils@0.3.1)(better-auth@1.5.6(@opentelemetry/api@1.9.0)(next@16.2.1(@babel/core@7.29.0)(@opentelemetry/api@1.9.0)(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(vitest@3.2.4(@types/node@20.19.37)(jiti@2.6.1)(lightningcss@1.32.0)(msw@2.12.14(@types/node@20.19.37)(typescript@5.9.3))(terser@5.46.1)))': + '@better-auth/api-key@1.5.6(@better-auth/core@1.5.6(@better-auth/utils@0.3.1)(@better-fetch/fetch@1.1.21)(@opentelemetry/api@1.9.0)(better-call@1.3.2(zod@4.3.6))(jose@6.2.2)(kysely@0.28.14)(nanostores@1.2.0))(@better-auth/utils@0.3.1)(better-auth@1.5.6(@opentelemetry/api@1.9.0)(next@16.2.1(@babel/core@7.29.0)(@opentelemetry/api@1.9.0)(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(vitest@3.2.4(@types/node@20.19.37)(jiti@2.6.1)(jsdom@29.0.1(@noble/hashes@2.0.1))(lightningcss@1.32.0)(msw@2.12.14(@types/node@20.19.37)(typescript@5.9.3))(terser@5.46.1)))': dependencies: '@better-auth/core': 1.5.6(@better-auth/utils@0.3.1)(@better-fetch/fetch@1.1.21)(@opentelemetry/api@1.9.0)(better-call@1.3.2(zod@4.3.6))(jose@6.2.2)(kysely@0.28.14)(nanostores@1.2.0) '@better-auth/utils': 0.3.1 - better-auth: 1.5.6(@opentelemetry/api@1.9.0)(next@16.2.1(@babel/core@7.29.0)(@opentelemetry/api@1.9.0)(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(vitest@3.2.4(@types/node@20.19.37)(jiti@2.6.1)(lightningcss@1.32.0)(msw@2.12.14(@types/node@20.19.37)(typescript@5.9.3))(terser@5.46.1)) + better-auth: 1.5.6(@opentelemetry/api@1.9.0)(next@16.2.1(@babel/core@7.29.0)(@opentelemetry/api@1.9.0)(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(vitest@3.2.4(@types/node@20.19.37)(jiti@2.6.1)(jsdom@29.0.1(@noble/hashes@2.0.1))(lightningcss@1.32.0)(msw@2.12.14(@types/node@20.19.37)(typescript@5.9.3))(terser@5.46.1)) zod: 4.3.6 '@better-auth/core@1.5.6(@better-auth/utils@0.3.1)(@better-fetch/fetch@1.1.21)(@opentelemetry/api@1.9.0)(better-call@1.3.2(zod@4.3.6))(jose@6.2.2)(kysely@0.28.14)(nanostores@1.2.0)': @@ -7052,14 +7211,14 @@ snapshots: '@better-auth/core': 1.5.6(@better-auth/utils@0.3.1)(@better-fetch/fetch@1.1.21)(@opentelemetry/api@1.9.0)(better-call@1.3.2(zod@4.3.6))(jose@6.2.2)(kysely@0.28.14)(nanostores@1.2.0) '@better-auth/utils': 0.3.1 - '@better-auth/passkey@1.5.6(@better-auth/core@1.5.6(@better-auth/utils@0.3.1)(@better-fetch/fetch@1.1.21)(@opentelemetry/api@1.9.0)(better-call@1.3.2(zod@4.3.6))(jose@6.2.2)(kysely@0.28.14)(nanostores@1.2.0))(@better-auth/utils@0.3.1)(@better-fetch/fetch@1.1.21)(better-auth@1.5.6(@opentelemetry/api@1.9.0)(next@16.2.1(@babel/core@7.29.0)(@opentelemetry/api@1.9.0)(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(vitest@3.2.4(@types/node@20.19.37)(jiti@2.6.1)(lightningcss@1.32.0)(msw@2.12.14(@types/node@20.19.37)(typescript@5.9.3))(terser@5.46.1)))(better-call@1.3.2(zod@4.3.6))(nanostores@1.2.0)': + '@better-auth/passkey@1.5.6(@better-auth/core@1.5.6(@better-auth/utils@0.3.1)(@better-fetch/fetch@1.1.21)(@opentelemetry/api@1.9.0)(better-call@1.3.2(zod@4.3.6))(jose@6.2.2)(kysely@0.28.14)(nanostores@1.2.0))(@better-auth/utils@0.3.1)(@better-fetch/fetch@1.1.21)(better-auth@1.5.6(@opentelemetry/api@1.9.0)(next@16.2.1(@babel/core@7.29.0)(@opentelemetry/api@1.9.0)(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(vitest@3.2.4(@types/node@20.19.37)(jiti@2.6.1)(jsdom@29.0.1(@noble/hashes@2.0.1))(lightningcss@1.32.0)(msw@2.12.14(@types/node@20.19.37)(typescript@5.9.3))(terser@5.46.1)))(better-call@1.3.2(zod@4.3.6))(nanostores@1.2.0)': dependencies: '@better-auth/core': 1.5.6(@better-auth/utils@0.3.1)(@better-fetch/fetch@1.1.21)(@opentelemetry/api@1.9.0)(better-call@1.3.2(zod@4.3.6))(jose@6.2.2)(kysely@0.28.14)(nanostores@1.2.0) '@better-auth/utils': 0.3.1 '@better-fetch/fetch': 1.1.21 '@simplewebauthn/browser': 13.3.0 '@simplewebauthn/server': 13.3.0 - better-auth: 1.5.6(@opentelemetry/api@1.9.0)(next@16.2.1(@babel/core@7.29.0)(@opentelemetry/api@1.9.0)(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(vitest@3.2.4(@types/node@20.19.37)(jiti@2.6.1)(lightningcss@1.32.0)(msw@2.12.14(@types/node@20.19.37)(typescript@5.9.3))(terser@5.46.1)) + better-auth: 1.5.6(@opentelemetry/api@1.9.0)(next@16.2.1(@babel/core@7.29.0)(@opentelemetry/api@1.9.0)(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(vitest@3.2.4(@types/node@20.19.37)(jiti@2.6.1)(jsdom@29.0.1(@noble/hashes@2.0.1))(lightningcss@1.32.0)(msw@2.12.14(@types/node@20.19.37)(typescript@5.9.3))(terser@5.46.1)) better-call: 1.3.2(zod@4.3.6) nanostores: 1.2.0 zod: 4.3.6 @@ -7079,6 +7238,10 @@ snapshots: '@better-fetch/fetch@1.1.21': {} + '@bramus/specificity@2.4.2': + dependencies: + css-tree: 3.2.1 + '@captchafox/react@1.11.0(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': dependencies: '@captchafox/types': 1.4.0 @@ -7087,10 +7250,10 @@ snapshots: '@captchafox/types@1.4.0': {} - '@convex-dev/better-auth@0.11.3(@standard-schema/spec@1.1.0)(better-auth@1.5.6(@opentelemetry/api@1.9.0)(next@16.2.1(@babel/core@7.29.0)(@opentelemetry/api@1.9.0)(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(vitest@3.2.4(@types/node@20.19.37)(jiti@2.6.1)(lightningcss@1.32.0)(msw@2.12.14(@types/node@20.19.37)(typescript@5.9.3))(terser@5.46.1)))(convex@1.34.0(react@19.2.4))(hono@4.12.9)(react@19.2.4)(typescript@5.9.3)': + '@convex-dev/better-auth@0.11.3(@standard-schema/spec@1.1.0)(better-auth@1.5.6(@opentelemetry/api@1.9.0)(next@16.2.1(@babel/core@7.29.0)(@opentelemetry/api@1.9.0)(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(vitest@3.2.4(@types/node@20.19.37)(jiti@2.6.1)(jsdom@29.0.1(@noble/hashes@2.0.1))(lightningcss@1.32.0)(msw@2.12.14(@types/node@20.19.37)(typescript@5.9.3))(terser@5.46.1)))(convex@1.34.0(react@19.2.4))(hono@4.12.9)(react@19.2.4)(typescript@5.9.3)': dependencies: '@better-fetch/fetch': 1.1.21 - better-auth: 1.5.6(@opentelemetry/api@1.9.0)(next@16.2.1(@babel/core@7.29.0)(@opentelemetry/api@1.9.0)(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(vitest@3.2.4(@types/node@20.19.37)(jiti@2.6.1)(lightningcss@1.32.0)(msw@2.12.14(@types/node@20.19.37)(typescript@5.9.3))(terser@5.46.1)) + better-auth: 1.5.6(@opentelemetry/api@1.9.0)(next@16.2.1(@babel/core@7.29.0)(@opentelemetry/api@1.9.0)(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(vitest@3.2.4(@types/node@20.19.37)(jiti@2.6.1)(jsdom@29.0.1(@noble/hashes@2.0.1))(lightningcss@1.32.0)(msw@2.12.14(@types/node@20.19.37)(typescript@5.9.3))(terser@5.46.1)) common-tags: 1.8.2 convex: 1.34.0(react@19.2.4) convex-helpers: 0.1.114(@standard-schema/spec@1.1.0)(convex@1.34.0(react@19.2.4))(hono@4.12.9)(react@19.2.4)(typescript@5.9.3)(zod@4.3.6) @@ -7105,23 +7268,47 @@ snapshots: - hono - typescript + '@csstools/color-helpers@6.0.2': {} + + '@csstools/css-calc@3.1.1(@csstools/css-parser-algorithms@4.0.0(@csstools/css-tokenizer@4.0.0))(@csstools/css-tokenizer@4.0.0)': + dependencies: + '@csstools/css-parser-algorithms': 4.0.0(@csstools/css-tokenizer@4.0.0) + '@csstools/css-tokenizer': 4.0.0 + + '@csstools/css-color-parser@4.0.2(@csstools/css-parser-algorithms@4.0.0(@csstools/css-tokenizer@4.0.0))(@csstools/css-tokenizer@4.0.0)': + dependencies: + '@csstools/color-helpers': 6.0.2 + '@csstools/css-calc': 3.1.1(@csstools/css-parser-algorithms@4.0.0(@csstools/css-tokenizer@4.0.0))(@csstools/css-tokenizer@4.0.0) + '@csstools/css-parser-algorithms': 4.0.0(@csstools/css-tokenizer@4.0.0) + '@csstools/css-tokenizer': 4.0.0 + + '@csstools/css-parser-algorithms@4.0.0(@csstools/css-tokenizer@4.0.0)': + dependencies: + '@csstools/css-tokenizer': 4.0.0 + + '@csstools/css-syntax-patches-for-csstree@1.1.2(css-tree@3.2.1)': + optionalDependencies: + css-tree: 3.2.1 + + '@csstools/css-tokenizer@4.0.0': {} + '@date-fns/tz@1.4.1': {} - '@daveyplate/better-auth-tanstack@1.3.6(@tanstack/query-core@5.95.2)(@tanstack/react-query@5.95.2(react@19.2.4))(better-auth@1.5.6(@opentelemetry/api@1.9.0)(next@16.2.1(@babel/core@7.29.0)(@opentelemetry/api@1.9.0)(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(vitest@3.2.4(@types/node@20.19.37)(jiti@2.6.1)(lightningcss@1.32.0)(msw@2.12.14(@types/node@20.19.37)(typescript@5.9.3))(terser@5.46.1)))(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': + '@daveyplate/better-auth-tanstack@1.3.6(@tanstack/query-core@5.95.2)(@tanstack/react-query@5.95.2(react@19.2.4))(better-auth@1.5.6(@opentelemetry/api@1.9.0)(next@16.2.1(@babel/core@7.29.0)(@opentelemetry/api@1.9.0)(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(vitest@3.2.4(@types/node@20.19.37)(jiti@2.6.1)(jsdom@29.0.1(@noble/hashes@2.0.1))(lightningcss@1.32.0)(msw@2.12.14(@types/node@20.19.37)(typescript@5.9.3))(terser@5.46.1)))(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': dependencies: '@tanstack/query-core': 5.95.2 '@tanstack/react-query': 5.95.2(react@19.2.4) - better-auth: 1.5.6(@opentelemetry/api@1.9.0)(next@16.2.1(@babel/core@7.29.0)(@opentelemetry/api@1.9.0)(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(vitest@3.2.4(@types/node@20.19.37)(jiti@2.6.1)(lightningcss@1.32.0)(msw@2.12.14(@types/node@20.19.37)(typescript@5.9.3))(terser@5.46.1)) + better-auth: 1.5.6(@opentelemetry/api@1.9.0)(next@16.2.1(@babel/core@7.29.0)(@opentelemetry/api@1.9.0)(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(vitest@3.2.4(@types/node@20.19.37)(jiti@2.6.1)(jsdom@29.0.1(@noble/hashes@2.0.1))(lightningcss@1.32.0)(msw@2.12.14(@types/node@20.19.37)(typescript@5.9.3))(terser@5.46.1)) react: 19.2.4 react-dom: 19.2.4(react@19.2.4) - '@daveyplate/better-auth-ui@3.4.0(43fe9e8f7c24dd7a61ee43b650bb480d)': + '@daveyplate/better-auth-ui@3.4.0(33090e10f4680aa961584df50b0a91cd)': dependencies: - '@better-auth/api-key': 1.5.6(@better-auth/core@1.5.6(@better-auth/utils@0.3.1)(@better-fetch/fetch@1.1.21)(@opentelemetry/api@1.9.0)(better-call@1.3.2(zod@4.3.6))(jose@6.2.2)(kysely@0.28.14)(nanostores@1.2.0))(@better-auth/utils@0.3.1)(better-auth@1.5.6(@opentelemetry/api@1.9.0)(next@16.2.1(@babel/core@7.29.0)(@opentelemetry/api@1.9.0)(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(vitest@3.2.4(@types/node@20.19.37)(jiti@2.6.1)(lightningcss@1.32.0)(msw@2.12.14(@types/node@20.19.37)(typescript@5.9.3))(terser@5.46.1))) - '@better-auth/passkey': 1.5.6(@better-auth/core@1.5.6(@better-auth/utils@0.3.1)(@better-fetch/fetch@1.1.21)(@opentelemetry/api@1.9.0)(better-call@1.3.2(zod@4.3.6))(jose@6.2.2)(kysely@0.28.14)(nanostores@1.2.0))(@better-auth/utils@0.3.1)(@better-fetch/fetch@1.1.21)(better-auth@1.5.6(@opentelemetry/api@1.9.0)(next@16.2.1(@babel/core@7.29.0)(@opentelemetry/api@1.9.0)(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(vitest@3.2.4(@types/node@20.19.37)(jiti@2.6.1)(lightningcss@1.32.0)(msw@2.12.14(@types/node@20.19.37)(typescript@5.9.3))(terser@5.46.1)))(better-call@1.3.2(zod@4.3.6))(nanostores@1.2.0) + '@better-auth/api-key': 1.5.6(@better-auth/core@1.5.6(@better-auth/utils@0.3.1)(@better-fetch/fetch@1.1.21)(@opentelemetry/api@1.9.0)(better-call@1.3.2(zod@4.3.6))(jose@6.2.2)(kysely@0.28.14)(nanostores@1.2.0))(@better-auth/utils@0.3.1)(better-auth@1.5.6(@opentelemetry/api@1.9.0)(next@16.2.1(@babel/core@7.29.0)(@opentelemetry/api@1.9.0)(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(vitest@3.2.4(@types/node@20.19.37)(jiti@2.6.1)(jsdom@29.0.1(@noble/hashes@2.0.1))(lightningcss@1.32.0)(msw@2.12.14(@types/node@20.19.37)(typescript@5.9.3))(terser@5.46.1))) + '@better-auth/passkey': 1.5.6(@better-auth/core@1.5.6(@better-auth/utils@0.3.1)(@better-fetch/fetch@1.1.21)(@opentelemetry/api@1.9.0)(better-call@1.3.2(zod@4.3.6))(jose@6.2.2)(kysely@0.28.14)(nanostores@1.2.0))(@better-auth/utils@0.3.1)(@better-fetch/fetch@1.1.21)(better-auth@1.5.6(@opentelemetry/api@1.9.0)(next@16.2.1(@babel/core@7.29.0)(@opentelemetry/api@1.9.0)(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(vitest@3.2.4(@types/node@20.19.37)(jiti@2.6.1)(jsdom@29.0.1(@noble/hashes@2.0.1))(lightningcss@1.32.0)(msw@2.12.14(@types/node@20.19.37)(typescript@5.9.3))(terser@5.46.1)))(better-call@1.3.2(zod@4.3.6))(nanostores@1.2.0) '@better-fetch/fetch': 1.1.21 '@captchafox/react': 1.11.0(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@daveyplate/better-auth-tanstack': 1.3.6(@tanstack/query-core@5.95.2)(@tanstack/react-query@5.95.2(react@19.2.4))(better-auth@1.5.6(@opentelemetry/api@1.9.0)(next@16.2.1(@babel/core@7.29.0)(@opentelemetry/api@1.9.0)(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(vitest@3.2.4(@types/node@20.19.37)(jiti@2.6.1)(lightningcss@1.32.0)(msw@2.12.14(@types/node@20.19.37)(typescript@5.9.3))(terser@5.46.1)))(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@daveyplate/better-auth-tanstack': 1.3.6(@tanstack/query-core@5.95.2)(@tanstack/react-query@5.95.2(react@19.2.4))(better-auth@1.5.6(@opentelemetry/api@1.9.0)(next@16.2.1(@babel/core@7.29.0)(@opentelemetry/api@1.9.0)(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(vitest@3.2.4(@types/node@20.19.37)(jiti@2.6.1)(jsdom@29.0.1(@noble/hashes@2.0.1))(lightningcss@1.32.0)(msw@2.12.14(@types/node@20.19.37)(typescript@5.9.3))(terser@5.46.1)))(react-dom@19.2.4(react@19.2.4))(react@19.2.4) '@hcaptcha/react-hcaptcha': 2.0.2 '@hookform/resolvers': 5.2.2(react-hook-form@7.72.0(react@19.2.4)) '@instantdb/react': 0.22.169(react@19.2.4) @@ -7146,7 +7333,7 @@ snapshots: '@triplit/client': 1.0.50(typescript@5.9.3) '@triplit/react': 1.0.51(react@19.2.4)(typescript@5.9.3) '@wojtekmaj/react-recaptcha-v3': 0.1.4(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - better-auth: 1.5.6(@opentelemetry/api@1.9.0)(next@16.2.1(@babel/core@7.29.0)(@opentelemetry/api@1.9.0)(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(vitest@3.2.4(@types/node@20.19.37)(jiti@2.6.1)(lightningcss@1.32.0)(msw@2.12.14(@types/node@20.19.37)(typescript@5.9.3))(terser@5.46.1)) + better-auth: 1.5.6(@opentelemetry/api@1.9.0)(next@16.2.1(@babel/core@7.29.0)(@opentelemetry/api@1.9.0)(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(vitest@3.2.4(@types/node@20.19.37)(jiti@2.6.1)(jsdom@29.0.1(@noble/hashes@2.0.1))(lightningcss@1.32.0)(msw@2.12.14(@types/node@20.19.37)(typescript@5.9.3))(terser@5.46.1)) better-call: 2.0.2(zod@4.3.6) bowser: 2.14.1 class-variance-authority: 0.7.1 @@ -7343,6 +7530,10 @@ snapshots: '@eslint/core': 0.17.0 levn: 0.4.1 + '@exodus/bytes@1.15.0(@noble/hashes@2.0.1)': + optionalDependencies: + '@noble/hashes': 2.0.1 + '@fastify/otel@0.17.1(@opentelemetry/api@1.9.0)': dependencies: '@opentelemetry/api': 1.9.0 @@ -8360,11 +8551,11 @@ snapshots: tslib: 2.8.1 tsyringe: 4.10.0 - '@polar-sh/better-auth@1.8.3(@polar-sh/sdk@0.46.7)(@stripe/react-stripe-js@4.0.2(@stripe/stripe-js@7.9.0)(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(@stripe/stripe-js@7.9.0)(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(better-auth@1.5.6(@opentelemetry/api@1.9.0)(next@16.2.1(@babel/core@7.29.0)(@opentelemetry/api@1.9.0)(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(vitest@3.2.4(@types/node@20.19.37)(jiti@2.6.1)(lightningcss@1.32.0)(msw@2.12.14(@types/node@20.19.37)(typescript@5.9.3))(terser@5.46.1)))(react-dom@19.2.4(react@19.2.4))(react-is@16.13.1)(react@19.2.4)(redux@5.0.1)(zod@4.3.6)': + '@polar-sh/better-auth@1.8.3(@polar-sh/sdk@0.46.7)(@stripe/react-stripe-js@4.0.2(@stripe/stripe-js@7.9.0)(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(@stripe/stripe-js@7.9.0)(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(better-auth@1.5.6(@opentelemetry/api@1.9.0)(next@16.2.1(@babel/core@7.29.0)(@opentelemetry/api@1.9.0)(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(vitest@3.2.4(@types/node@20.19.37)(jiti@2.6.1)(jsdom@29.0.1(@noble/hashes@2.0.1))(lightningcss@1.32.0)(msw@2.12.14(@types/node@20.19.37)(typescript@5.9.3))(terser@5.46.1)))(react-dom@19.2.4(react@19.2.4))(react-is@16.13.1)(react@19.2.4)(redux@5.0.1)(zod@4.3.6)': dependencies: '@polar-sh/checkout': 0.2.0(@stripe/react-stripe-js@4.0.2(@stripe/stripe-js@7.9.0)(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(@stripe/stripe-js@7.9.0)(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react-is@16.13.1)(react@19.2.4)(redux@5.0.1) '@polar-sh/sdk': 0.46.7 - better-auth: 1.5.6(@opentelemetry/api@1.9.0)(next@16.2.1(@babel/core@7.29.0)(@opentelemetry/api@1.9.0)(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(vitest@3.2.4(@types/node@20.19.37)(jiti@2.6.1)(lightningcss@1.32.0)(msw@2.12.14(@types/node@20.19.37)(typescript@5.9.3))(terser@5.46.1)) + better-auth: 1.5.6(@opentelemetry/api@1.9.0)(next@16.2.1(@babel/core@7.29.0)(@opentelemetry/api@1.9.0)(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(vitest@3.2.4(@types/node@20.19.37)(jiti@2.6.1)(jsdom@29.0.1(@noble/hashes@2.0.1))(lightningcss@1.32.0)(msw@2.12.14(@types/node@20.19.37)(typescript@5.9.3))(terser@5.46.1)) zod: 4.3.6 transitivePeerDependencies: - '@stripe/react-stripe-js' @@ -10471,7 +10662,7 @@ snapshots: baseline-browser-mapping@2.10.10: {} - better-auth@1.5.6(@opentelemetry/api@1.9.0)(next@16.2.1(@babel/core@7.29.0)(@opentelemetry/api@1.9.0)(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(vitest@3.2.4(@types/node@20.19.37)(jiti@2.6.1)(lightningcss@1.32.0)(msw@2.12.14(@types/node@20.19.37)(typescript@5.9.3))(terser@5.46.1)): + better-auth@1.5.6(@opentelemetry/api@1.9.0)(next@16.2.1(@babel/core@7.29.0)(@opentelemetry/api@1.9.0)(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(vitest@3.2.4(@types/node@20.19.37)(jiti@2.6.1)(jsdom@29.0.1(@noble/hashes@2.0.1))(lightningcss@1.32.0)(msw@2.12.14(@types/node@20.19.37)(typescript@5.9.3))(terser@5.46.1)): dependencies: '@better-auth/core': 1.5.6(@better-auth/utils@0.3.1)(@better-fetch/fetch@1.1.21)(@opentelemetry/api@1.9.0)(better-call@1.3.2(zod@4.3.6))(jose@6.2.2)(kysely@0.28.14)(nanostores@1.2.0) '@better-auth/drizzle-adapter': 1.5.6(@better-auth/core@1.5.6(@better-auth/utils@0.3.1)(@better-fetch/fetch@1.1.21)(@opentelemetry/api@1.9.0)(better-call@1.3.2(zod@4.3.6))(jose@6.2.2)(kysely@0.28.14)(nanostores@1.2.0))(@better-auth/utils@0.3.1) @@ -10494,7 +10685,7 @@ snapshots: next: 16.2.1(@babel/core@7.29.0)(@opentelemetry/api@1.9.0)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) react: 19.2.4 react-dom: 19.2.4(react@19.2.4) - vitest: 3.2.4(@types/node@20.19.37)(jiti@2.6.1)(lightningcss@1.32.0)(msw@2.12.14(@types/node@20.19.37)(typescript@5.9.3))(terser@5.46.1) + vitest: 3.2.4(@types/node@20.19.37)(jiti@2.6.1)(jsdom@29.0.1(@noble/hashes@2.0.1))(lightningcss@1.32.0)(msw@2.12.14(@types/node@20.19.37)(typescript@5.9.3))(terser@5.46.1) transitivePeerDependencies: - '@cloudflare/workers-types' - '@opentelemetry/api' @@ -10517,6 +10708,10 @@ snapshots: optionalDependencies: zod: 4.3.6 + bidi-js@1.0.3: + dependencies: + require-from-string: 2.0.2 + bmp-ts@1.0.9: {} body-parser@2.2.2: @@ -10736,6 +10931,11 @@ snapshots: shebang-command: 2.0.0 which: 2.0.2 + css-tree@3.2.1: + dependencies: + mdn-data: 2.27.1 + source-map-js: 1.2.1 + cssesc@3.0.0: {} csstype@3.2.3: {} @@ -10808,6 +11008,13 @@ snapshots: data-uri-to-buffer@4.0.1: {} + data-urls@7.0.0(@noble/hashes@2.0.1): + dependencies: + whatwg-mimetype: 5.0.0 + whatwg-url: 16.0.1(@noble/hashes@2.0.1) + transitivePeerDependencies: + - '@noble/hashes' + data-view-buffer@1.0.2: dependencies: call-bound: 1.0.4 @@ -10840,6 +11047,8 @@ snapshots: decimal.js-light@2.5.1: {} + decimal.js@10.6.0: {} + dedent@1.7.2: {} deep-eql@5.0.2: {} @@ -10943,6 +11152,8 @@ snapshots: entities@4.5.0: {} + entities@6.0.1: {} + env-paths@2.2.1: {} error-ex@1.3.4: @@ -11658,6 +11869,12 @@ snapshots: hono@4.12.9: {} + html-encoding-sniffer@6.0.0(@noble/hashes@2.0.1): + dependencies: + '@exodus/bytes': 1.15.0(@noble/hashes@2.0.1) + transitivePeerDependencies: + - '@noble/hashes' + html-to-text@9.0.5: dependencies: '@selderee/plugin-htmlparser2': 0.11.0 @@ -11876,6 +12093,8 @@ snapshots: is-plain-obj@4.1.0: {} + is-potential-custom-element-name@1.0.1: {} + is-promise@4.0.0: {} is-reference@1.2.1: @@ -12004,6 +12223,32 @@ snapshots: dependencies: argparse: 2.0.1 + jsdom@29.0.1(@noble/hashes@2.0.1): + dependencies: + '@asamuzakjp/css-color': 5.1.4 + '@asamuzakjp/dom-selector': 7.0.4 + '@bramus/specificity': 2.4.2 + '@csstools/css-syntax-patches-for-csstree': 1.1.2(css-tree@3.2.1) + '@exodus/bytes': 1.15.0(@noble/hashes@2.0.1) + css-tree: 3.2.1 + data-urls: 7.0.0(@noble/hashes@2.0.1) + decimal.js: 10.6.0 + html-encoding-sniffer: 6.0.0(@noble/hashes@2.0.1) + is-potential-custom-element-name: 1.0.1 + lru-cache: 11.2.7 + parse5: 8.0.0 + saxes: 6.0.0 + symbol-tree: 3.2.4 + tough-cookie: 6.0.1 + undici: 7.24.7 + w3c-xmlserializer: 5.0.0 + webidl-conversions: 8.0.1 + whatwg-mimetype: 5.0.0 + whatwg-url: 16.0.1(@noble/hashes@2.0.1) + xml-name-validator: 5.0.0 + transitivePeerDependencies: + - '@noble/hashes' + jsesc@3.1.0: {} json-buffer@3.0.1: {} @@ -12171,6 +12416,8 @@ snapshots: math-intrinsics@1.1.0: {} + mdn-data@2.27.1: {} + media-typer@1.1.0: {} merge-descriptors@2.0.0: {} @@ -12490,6 +12737,10 @@ snapshots: parse-ms@4.0.0: {} + parse5@8.0.0: + dependencies: + entities: 6.0.1 + parseley@0.12.1: dependencies: leac: 0.6.0 @@ -13009,6 +13260,10 @@ snapshots: sax@1.6.0: {} + saxes@6.0.0: + dependencies: + xmlchars: 2.2.0 + scheduler@0.27.0: {} schema-utils@4.3.3: @@ -13364,6 +13619,8 @@ snapshots: supports-preserve-symlinks-flag@1.0.0: {} + symbol-tree@3.2.4: {} + tagged-tag@1.0.0: {} tailwind-merge@3.5.0: {} @@ -13431,6 +13688,10 @@ snapshots: tr46@0.0.3: {} + tr46@6.0.0: + dependencies: + punycode: 2.3.1 + ts-api-utils@2.5.0(typescript@5.9.3): dependencies: typescript: 5.9.3 @@ -13538,6 +13799,8 @@ snapshots: undici-types@6.21.0: {} + undici@7.24.7: {} + unicorn-magic@0.3.0: {} universalify@2.0.1: {} @@ -13683,7 +13946,7 @@ snapshots: lightningcss: 1.32.0 terser: 5.46.1 - vitest@3.2.4(@types/node@20.19.37)(jiti@2.6.1)(lightningcss@1.32.0)(msw@2.12.14(@types/node@20.19.37)(typescript@5.9.3))(terser@5.46.1): + vitest@3.2.4(@types/node@20.19.37)(jiti@2.6.1)(jsdom@29.0.1(@noble/hashes@2.0.1))(lightningcss@1.32.0)(msw@2.12.14(@types/node@20.19.37)(typescript@5.9.3))(terser@5.46.1): dependencies: '@types/chai': 5.2.3 '@vitest/expect': 3.2.4 @@ -13710,6 +13973,7 @@ snapshots: why-is-node-running: 2.3.0 optionalDependencies: '@types/node': 20.19.37 + jsdom: 29.0.1(@noble/hashes@2.0.1) transitivePeerDependencies: - jiti - less @@ -13724,6 +13988,10 @@ snapshots: - tsx - yaml + w3c-xmlserializer@5.0.0: + dependencies: + xml-name-validator: 5.0.0 + warning@4.0.3: dependencies: loose-envify: 1.4.0 @@ -13739,6 +14007,8 @@ snapshots: webidl-conversions@3.0.1: {} + webidl-conversions@8.0.1: {} + webpack-sources@3.3.4: {} webpack@5.105.4: @@ -13773,6 +14043,16 @@ snapshots: - esbuild - uglify-js + whatwg-mimetype@5.0.0: {} + + whatwg-url@16.0.1(@noble/hashes@2.0.1): + dependencies: + '@exodus/bytes': 1.15.0(@noble/hashes@2.0.1) + tr46: 6.0.0 + webidl-conversions: 8.0.1 + transitivePeerDependencies: + - '@noble/hashes' + whatwg-url@5.0.0: dependencies: tr46: 0.0.3 @@ -13855,6 +14135,8 @@ snapshots: is-wsl: 3.1.1 powershell-utils: 0.1.0 + xml-name-validator@5.0.0: {} + xml-parse-from-string@1.0.1: {} xml2js@0.5.0: @@ -13864,6 +14146,8 @@ snapshots: xmlbuilder@11.0.1: {} + xmlchars@2.2.0: {} + xtend@4.0.2: {} y18n@5.0.8: {} diff --git a/vitest.config.ts b/vitest.config.ts index 090d874..70f9b7d 100644 --- a/vitest.config.ts +++ b/vitest.config.ts @@ -13,6 +13,7 @@ export default defineConfig({ "tests/**/*.test.ts", "components/canvas/__tests__/canvas-flow-reconciliation-helpers.test.ts", "components/canvas/__tests__/use-canvas-sync-engine.test.ts", + "components/canvas/__tests__/use-canvas-sync-engine-hook.test.tsx", ], }, });