test: add vitest baseline for critical payment and auth guards

This commit is contained in:
2026-04-03 18:15:18 +02:00
parent 2542748e82
commit 68416ed9de
12 changed files with 730 additions and 75 deletions
+9
View File
@@ -0,0 +1,9 @@
type NodeCanvasRef = {
canvasId: string;
};
export function assertNodeBelongsToCanvasOrThrow(node: NodeCanvasRef, canvasId: string): void {
if (node.canvasId !== canvasId) {
throw new Error("Node does not belong to canvas");
}
}
+2 -3
View File
@@ -12,6 +12,7 @@ import {
IMAGE_MODELS, IMAGE_MODELS,
} from "./openrouter"; } from "./openrouter";
import type { Id } from "./_generated/dataModel"; import type { Id } from "./_generated/dataModel";
import { assertNodeBelongsToCanvasOrThrow } from "./ai-utils";
const MAX_IMAGE_RETRIES = 2; const MAX_IMAGE_RETRIES = 2;
@@ -526,9 +527,7 @@ export const generateImage = action({
if (!node) { if (!node) {
throw new Error("Node not found"); throw new Error("Node not found");
} }
if (node.canvasId !== args.canvasId) { assertNodeBelongsToCanvasOrThrow(node, args.canvasId);
throw new Error("Node does not belong to canvas");
}
const userId = canvas.ownerId; const userId = canvas.ownerId;
const verifiedCanvasId = canvas._id; const verifiedCanvasId = canvas._id;
+49
View File
@@ -0,0 +1,49 @@
import type { Id } from "./_generated/dataModel";
type BatchNodeRecord = {
_id: Id<"nodes">;
canvasId: Id<"canvases">;
};
type BatchCanvasRecord = {
_id: Id<"canvases">;
ownerId: string;
};
type ValidateBatchArgs<N extends BatchNodeRecord> = {
userId: string;
nodeIds: Id<"nodes">[];
getNodeById: (nodeId: Id<"nodes">) => Promise<N | null>;
getCanvasById: (canvasId: Id<"canvases">) => Promise<BatchCanvasRecord | null>;
};
export async function validateBatchNodesForUserOrThrow<N extends BatchNodeRecord>(
args: ValidateBatchArgs<N>,
): Promise<{ canvasId: Id<"canvases">; nodes: N[] }> {
if (args.nodeIds.length === 0) {
throw new Error("Batch must contain at least one node id");
}
const nodes: N[] = [];
for (const nodeId of args.nodeIds) {
const node = await args.getNodeById(nodeId);
if (!node) {
throw new Error("Node not found");
}
nodes.push(node);
}
const canvasId = nodes[0].canvasId;
for (const node of nodes) {
if (node.canvasId !== canvasId) {
throw new Error("All nodes must belong to the same canvas");
}
}
const canvas = await args.getCanvasById(canvasId);
if (!canvas || canvas.ownerId !== args.userId) {
throw new Error("Canvas not found");
}
return { canvasId, nodes };
}
+7 -23
View File
@@ -3,6 +3,7 @@ import { v } from "convex/values";
import { requireAuth } from "./helpers"; import { requireAuth } from "./helpers";
import type { Doc, Id } from "./_generated/dataModel"; import type { Doc, Id } from "./_generated/dataModel";
import { isAdjustmentNodeType } from "../lib/canvas-node-types"; import { isAdjustmentNodeType } from "../lib/canvas-node-types";
import { validateBatchNodesForUserOrThrow } from "./batch-validation-utils";
import { import {
getCanvasConnectionValidationMessage, getCanvasConnectionValidationMessage,
validateCanvasConnectionPolicy, validateCanvasConnectionPolicy,
@@ -45,29 +46,12 @@ async function getValidatedBatchNodesOrThrow(
userId: string, userId: string,
nodeIds: Id<"nodes">[], nodeIds: Id<"nodes">[],
): Promise<{ canvasId: Id<"canvases">; nodes: Doc<"nodes">[] }> { ): Promise<{ canvasId: Id<"canvases">; nodes: Doc<"nodes">[] }> {
if (nodeIds.length === 0) { return await validateBatchNodesForUserOrThrow({
throw new Error("Batch must contain at least one node id"); userId,
} nodeIds,
getNodeById: (nodeId) => ctx.db.get(nodeId),
const nodes: Doc<"nodes">[] = []; getCanvasById: (canvasId) => ctx.db.get(canvasId),
for (const nodeId of nodeIds) { });
const node = await ctx.db.get(nodeId);
if (!node) {
throw new Error("Node not found");
}
nodes.push(node);
}
const canvasId = nodes[0].canvasId;
for (const node of nodes) {
if (node.canvasId !== canvasId) {
throw new Error("All nodes must belong to the same canvas");
}
}
await getCanvasOrThrow(ctx, canvasId, userId);
return { canvasId, nodes };
} }
type NodeCreateMutationName = type NodeCreateMutationName =
+71
View File
@@ -0,0 +1,71 @@
type IdempotencyScope =
| "topup_paid"
| "subscription_activated_cycle"
| "subscription_revoked";
type RegisterWebhookEventArgs = {
provider: "polar";
scope: IdempotencyScope;
idempotencyKey: string;
userId: string;
polarOrderId?: string;
polarSubscriptionId?: string;
};
type ExistingEventLookup = {
provider: "polar";
idempotencyKey: string;
};
type ExistingEventRecord = {
_id: string;
};
export type WebhookEventRepo = {
findByProviderAndKey: (
lookup: ExistingEventLookup,
) => Promise<ExistingEventRecord | null>;
insert: (args: RegisterWebhookEventArgs & { createdAt: number }) => Promise<void>;
};
export function buildSubscriptionCycleIdempotencyKey(args: {
polarSubscriptionId: string;
currentPeriodStart: number;
currentPeriodEnd: number;
}): string {
return `polar:subscription_cycle:${args.polarSubscriptionId}:${args.currentPeriodStart}:${args.currentPeriodEnd}`;
}
export function buildSubscriptionRevokedIdempotencyKey(args: {
userId: string;
polarSubscriptionId?: string;
}): string {
return args.polarSubscriptionId
? `polar:subscription_revoked:${args.polarSubscriptionId}`
: `polar:subscription_revoked:user:${args.userId}`;
}
export function buildTopUpPaidIdempotencyKey(polarOrderId: string): string {
return `polar:order_paid:${polarOrderId}`;
}
export async function registerWebhookEventOnce(
repo: WebhookEventRepo,
args: RegisterWebhookEventArgs,
now: () => number = Date.now,
): Promise<boolean> {
const existing = await repo.findByProviderAndKey({
provider: args.provider,
idempotencyKey: args.idempotencyKey,
});
if (existing) {
return false;
}
await repo.insert({
...args,
createdAt: now(),
});
return true;
}
+44 -19
View File
@@ -1,6 +1,12 @@
import { v } from "convex/values"; import { v } from "convex/values";
import { internalMutation, type MutationCtx } from "./_generated/server"; import { internalMutation, type MutationCtx } from "./_generated/server";
import {
buildSubscriptionCycleIdempotencyKey,
buildSubscriptionRevokedIdempotencyKey,
buildTopUpPaidIdempotencyKey,
registerWebhookEventOnce,
} from "./polar-utils";
type DbCtx = Pick<MutationCtx, "db">; type DbCtx = Pick<MutationCtx, "db">;
@@ -65,7 +71,11 @@ export async function applySubscriptionActivated(ctx: DbCtx, args: ActivatedArgs
}); });
} }
const cycleKey = `polar:subscription_cycle:${args.polarSubscriptionId}:${args.currentPeriodStart}:${args.currentPeriodEnd}`; const cycleKey = buildSubscriptionCycleIdempotencyKey({
polarSubscriptionId: args.polarSubscriptionId,
currentPeriodStart: args.currentPeriodStart,
currentPeriodEnd: args.currentPeriodEnd,
});
const isFirstCycleEvent = await registerWebhookEvent(ctx, { const isFirstCycleEvent = await registerWebhookEvent(ctx, {
provider: "polar", provider: "polar",
scope: "subscription_activated_cycle", scope: "subscription_activated_cycle",
@@ -145,9 +155,10 @@ export async function applySubscriptionRevoked(ctx: DbCtx, args: RevokedArgs) {
}); });
} }
const revokedKey = args.polarSubscriptionId const revokedKey = buildSubscriptionRevokedIdempotencyKey({
? `polar:subscription_revoked:${args.polarSubscriptionId}` userId: args.userId,
: `polar:subscription_revoked:user:${args.userId}`; polarSubscriptionId: args.polarSubscriptionId,
});
const isFirstRevokedEvent = await registerWebhookEvent(ctx, { const isFirstRevokedEvent = await registerWebhookEvent(ctx, {
provider: "polar", provider: "polar",
scope: "subscription_revoked", scope: "subscription_revoked",
@@ -175,7 +186,7 @@ export async function applyTopUpPaid(ctx: DbCtx, args: TopUpArgs) {
const isFirstTopUpEvent = await registerWebhookEvent(ctx, { const isFirstTopUpEvent = await registerWebhookEvent(ctx, {
provider: "polar", provider: "polar",
scope: "topup_paid", scope: "topup_paid",
idempotencyKey: `polar:order_paid:${args.polarOrderId}`, idempotencyKey: buildTopUpPaidIdempotencyKey(args.polarOrderId),
userId: args.userId, userId: args.userId,
polarOrderId: args.polarOrderId, polarOrderId: args.polarOrderId,
}); });
@@ -218,28 +229,42 @@ async function registerWebhookEvent(
polarSubscriptionId?: string; polarSubscriptionId?: string;
} }
) { ) {
return await registerWebhookEventOnce(
{
findByProviderAndKey: async ({ provider, idempotencyKey }) => {
const existing = await ctx.db const existing = await ctx.db
.query("webhookIdempotencyEvents") .query("webhookIdempotencyEvents")
.withIndex("by_provider_key", (q) => .withIndex("by_provider_key", (q) =>
q.eq("provider", args.provider).eq("idempotencyKey", args.idempotencyKey) q.eq("provider", provider).eq("idempotencyKey", idempotencyKey)
) )
.first(); .first();
if (!existing) {
if (existing) { return null;
return false;
} }
return { _id: existing._id };
},
insert: async ({
provider,
scope,
idempotencyKey,
userId,
polarOrderId,
polarSubscriptionId,
createdAt,
}) => {
await ctx.db.insert("webhookIdempotencyEvents", { await ctx.db.insert("webhookIdempotencyEvents", {
provider: args.provider, provider,
scope: args.scope, scope,
idempotencyKey: args.idempotencyKey, idempotencyKey,
userId: args.userId, userId,
polarOrderId: args.polarOrderId, polarOrderId,
polarSubscriptionId: args.polarSubscriptionId, polarSubscriptionId,
createdAt: Date.now(), createdAt,
}); });
},
return true; },
args,
);
} }
export const handleSubscriptionActivated = internalMutation({ export const handleSubscriptionActivated = internalMutation({
+5 -2
View File
@@ -7,7 +7,9 @@
"dev:strict": "next dev", "dev:strict": "next dev",
"build": "next build", "build": "next build",
"start": "next start", "start": "next start",
"lint": "eslint" "lint": "eslint",
"test": "vitest run",
"test:watch": "vitest"
}, },
"dependencies": { "dependencies": {
"@convex-dev/better-auth": "^0.11.3", "@convex-dev/better-auth": "^0.11.3",
@@ -56,6 +58,7 @@
"eslint": "^9", "eslint": "^9",
"eslint-config-next": "16.2.1", "eslint-config-next": "16.2.1",
"tailwindcss": "^4", "tailwindcss": "^4",
"typescript": "^5" "typescript": "^5",
"vitest": "^3.2.4"
} }
} }
+394 -20
View File
@@ -10,10 +10,10 @@ importers:
dependencies: dependencies:
'@convex-dev/better-auth': '@convex-dev/better-auth':
specifier: ^0.11.3 specifier: ^0.11.3
version: 0.11.3(@standard-schema/[email protected])([email protected](@opentelemetry/[email protected])([email protected](@babel/[email protected])(@opentelemetry/[email protected])([email protected]([email protected]))([email protected]))([email protected]([email protected]))([email protected]))([email protected]([email protected]))([email protected])([email protected])([email protected]) version: 0.11.3(@standard-schema/[email protected])([email protected](@opentelemetry/[email protected])([email protected](@babel/[email protected])(@opentelemetry/[email protected])([email protected]([email protected]))([email protected]))([email protected]([email protected]))([email protected])([email protected](@types/[email protected])([email protected])([email protected])([email protected](@types/[email protected])([email protected]))([email protected])))([email protected]([email protected]))([email protected])([email protected])([email protected])
'@daveyplate/better-auth-ui': '@daveyplate/better-auth-ui':
specifier: ^3.4.0 specifier: ^3.4.0
version: 3.4.0(aed41ba285ba33af5b1a54a1a4efb176) version: 3.4.0(43fe9e8f7c24dd7a61ee43b650bb480d)
'@dnd-kit/core': '@dnd-kit/core':
specifier: ^6.3.1 specifier: ^6.3.1
version: 6.3.1([email protected]([email protected]))([email protected]) version: 6.3.1([email protected]([email protected]))([email protected])
@@ -25,7 +25,7 @@ importers:
version: 0.1.97 version: 0.1.97
'@polar-sh/better-auth': '@polar-sh/better-auth':
specifier: ^1.8.3 specifier: ^1.8.3
version: 1.8.3(@polar-sh/[email protected])(@stripe/[email protected](@stripe/[email protected])([email protected]([email protected]))([email protected]))(@stripe/[email protected])(@types/[email protected](@types/[email protected]))(@types/[email protected])([email protected](@opentelemetry/[email protected])([email protected](@babel/[email protected])(@opentelemetry/[email protected])([email protected]([email protected]))([email protected]))([email protected]([email protected]))([email protected]))([email protected]([email protected]))([email protected])([email protected])([email protected])([email protected]) version: 1.8.3(@polar-sh/[email protected])(@stripe/[email protected](@stripe/[email protected])([email protected]([email protected]))([email protected]))(@stripe/[email protected])(@types/[email protected](@types/[email protected]))(@types/[email protected])([email protected](@opentelemetry/[email protected])([email protected](@babel/[email protected])(@opentelemetry/[email protected])([email protected]([email protected]))([email protected]))([email protected]([email protected]))([email protected])([email protected](@types/[email protected])([email protected])([email protected])([email protected](@types/[email protected])([email protected]))([email protected])))([email protected]([email protected]))([email protected])([email protected])([email protected])([email protected])
'@polar-sh/sdk': '@polar-sh/sdk':
specifier: ^0.46.7 specifier: ^0.46.7
version: 0.46.7 version: 0.46.7
@@ -40,7 +40,7 @@ importers:
version: 12.10.1(@types/[email protected])([email protected])([email protected]([email protected]))([email protected]) version: 12.10.1(@types/[email protected])([email protected])([email protected]([email protected]))([email protected])
better-auth: better-auth:
specifier: ^1.5.6 specifier: ^1.5.6
version: 1.5.6(@opentelemetry/[email protected])([email protected](@babel/[email protected])(@opentelemetry/[email protected])([email protected]([email protected]))([email protected]))([email protected]([email protected]))([email protected]) version: 1.5.6(@opentelemetry/[email protected])([email protected](@babel/[email protected])(@opentelemetry/[email protected])([email protected]([email protected]))([email protected]))([email protected]([email protected]))([email protected])([email protected](@types/[email protected])([email protected])([email protected])([email protected](@types/[email protected])([email protected]))([email protected]))
class-variance-authority: class-variance-authority:
specifier: ^0.7.1 specifier: ^0.7.1
version: 0.7.1 version: 0.7.1
@@ -144,6 +144,9 @@ importers:
typescript: typescript:
specifier: ^5 specifier: ^5
version: 5.9.3 version: 5.9.3
vitest:
specifier: ^3.2.4
version: 3.2.4(@types/[email protected])([email protected])([email protected])([email protected](@types/[email protected])([email protected]))([email protected])
packages: packages:
@@ -3112,6 +3115,9 @@ packages:
'@tybys/[email protected]': '@tybys/[email protected]':
resolution: {integrity: sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg==} resolution: {integrity: sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg==}
'@types/[email protected]':
resolution: {integrity: sha512-Mw558oeA9fFbv65/y4mHtXDs9bPnFMZAL/jxdPFUpOHHIXX91mcgEHbS5Lahr+pwZFR8A7GQleRWeI6cGFC2UA==}
'@types/[email protected]': '@types/[email protected]':
resolution: {integrity: sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==} resolution: {integrity: sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==}
@@ -3154,6 +3160,9 @@ packages:
'@types/[email protected]': '@types/[email protected]':
resolution: {integrity: sha512-iqMC4/YlFCSlO8+2Ii1GGGliCAY4XdeG748w5vQUbevlbDu0zSjH/+jojorQVBK/se0j6DUFNPBGSqD3YWYnDw==} resolution: {integrity: sha512-iqMC4/YlFCSlO8+2Ii1GGGliCAY4XdeG748w5vQUbevlbDu0zSjH/+jojorQVBK/se0j6DUFNPBGSqD3YWYnDw==}
'@types/[email protected]':
resolution: {integrity: sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw==}
'@types/[email protected]': '@types/[email protected]':
resolution: {integrity: sha512-MzMFlSLBqNF2gcHWO0G1vP/YQyfvrxZ0bF+u7mzUdZ1/xK4A4sru+nraZz5i3iEIk1l1uyicaDVTB4QbbEkAYg==} resolution: {integrity: sha512-MzMFlSLBqNF2gcHWO0G1vP/YQyfvrxZ0bF+u7mzUdZ1/xK4A4sru+nraZz5i3iEIk1l1uyicaDVTB4QbbEkAYg==}
@@ -3374,6 +3383,35 @@ packages:
cpu: [x64] cpu: [x64]
os: [win32] os: [win32]
'@vitest/[email protected]':
resolution: {integrity: sha512-Io0yyORnB6sikFlt8QW5K7slY4OjqNX9jmJQ02QDda8lyM6B5oNgVWoSoKPac8/kgnCUzuHQKrSLtu/uOqqrig==}
'@vitest/[email protected]':
resolution: {integrity: sha512-46ryTE9RZO/rfDd7pEqFl7etuyzekzEhUbTW3BvmeO/BcCMEgq59BKhek3dXDWgAj4oMK6OZi+vRr1wPW6qjEQ==}
peerDependencies:
msw: ^2.4.9
vite: ^5.0.0 || ^6.0.0 || ^7.0.0-0
peerDependenciesMeta:
msw:
optional: true
vite:
optional: true
'@vitest/[email protected]':
resolution: {integrity: sha512-IVNZik8IVRJRTr9fxlitMKeJeXFFFN0JaB9PHPGQ8NKQbGpfjlTx9zO4RefN8gp7eqjNy8nyK3NZmBzOPeIxtA==}
'@vitest/[email protected]':
resolution: {integrity: sha512-oukfKT9Mk41LreEW09vt45f8wx7DordoWUZMYdY/cyAk7w5TWkTRCNZYF7sX7n2wB7jyGAl74OxgwhPgKaqDMQ==}
'@vitest/[email protected]':
resolution: {integrity: sha512-dEYtS7qQP2CjU27QBC5oUOxLE/v5eLkGqPE0ZKEIDGMs4vKWe7IjgLOeauHsR0D5YuuycGRO5oSRXnwnmA78fQ==}
'@vitest/[email protected]':
resolution: {integrity: sha512-vAfasCOe6AIK70iP5UD11Ac4siNUNJ9i/9PZ3NKx07sG6sUxeag1LWdNrMWeKKYBLlzuK+Gn65Yd5nyL6ds+nw==}
'@vitest/[email protected]':
resolution: {integrity: sha512-fB2V0JFrQSMsCo9HiSq3Ezpdv4iYaXRG1Sx8edX3MwxfyNn83mKiGzOcH+Fkxt4MHxr3y42fQi1oeAInqgX2QA==}
'@webassemblyjs/[email protected]': '@webassemblyjs/[email protected]':
resolution: {integrity: sha512-nuBEDgQfm1ccRp/8bCQrx1frohyufl4JlbMMZ4P1wpeOfDhF6FQkxZJ1b/e+PLwr6X1Nhw6OLme5usuBWYBvuQ==} resolution: {integrity: sha512-nuBEDgQfm1ccRp/8bCQrx1frohyufl4JlbMMZ4P1wpeOfDhF6FQkxZJ1b/e+PLwr6X1Nhw6OLme5usuBWYBvuQ==}
@@ -3570,6 +3608,10 @@ packages:
resolution: {integrity: sha512-uLvq6KJu04qoQM6gvBfKFjlh6Gl0vOKQuR5cJMDHQkmwfMOQeN3F3SHCv9SNYSL+CRoHvOGFfllDlVz03GQjvQ==} resolution: {integrity: sha512-uLvq6KJu04qoQM6gvBfKFjlh6Gl0vOKQuR5cJMDHQkmwfMOQeN3F3SHCv9SNYSL+CRoHvOGFfllDlVz03GQjvQ==}
engines: {node: '>=12.0.0'} engines: {node: '>=12.0.0'}
[email protected]:
resolution: {integrity: sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==}
engines: {node: '>=12'}
[email protected]: [email protected]:
resolution: {integrity: sha512-OH/2E5Fg20h2aPrbe+QL8JZQFko0YZaF+j4mnQ7BGhfavO7OpSLa8a0y9sBwomHdSbkhTS8TQNayBfnW5DwbvQ==} resolution: {integrity: sha512-OH/2E5Fg20h2aPrbe+QL8JZQFko0YZaF+j4mnQ7BGhfavO7OpSLa8a0y9sBwomHdSbkhTS8TQNayBfnW5DwbvQ==}
@@ -3730,6 +3772,10 @@ packages:
resolution: {integrity: sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==} resolution: {integrity: sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==}
engines: {node: '>= 0.8'} engines: {node: '>= 0.8'}
[email protected]:
resolution: {integrity: sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==}
engines: {node: '>=8'}
[email protected]: [email protected]:
resolution: {integrity: sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==} resolution: {integrity: sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==}
engines: {node: '>= 0.4'} engines: {node: '>= 0.4'}
@@ -3749,6 +3795,10 @@ packages:
[email protected]: [email protected]:
resolution: {integrity: sha512-RdwNCyMsNBftLjW6w01z8bKEvT6e/5tpPVEgtn22TiLGlstHOVecsX2KHFkD5e/vRnIE4EGzpuIODb3mtswtkw==} resolution: {integrity: sha512-RdwNCyMsNBftLjW6w01z8bKEvT6e/5tpPVEgtn22TiLGlstHOVecsX2KHFkD5e/vRnIE4EGzpuIODb3mtswtkw==}
[email protected]:
resolution: {integrity: sha512-4zNhdJD/iOjSH0A05ea+Ke6MU5mmpQcbQsSOkgdaUMJ9zTlDTD/GYlwohmIE2u0gaxHYiVHEn1Fw9mZ/ktJWgw==}
engines: {node: '>=18'}
[email protected]: [email protected]:
resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==}
engines: {node: '>=10'} engines: {node: '>=10'}
@@ -3757,6 +3807,10 @@ packages:
resolution: {integrity: sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA==} resolution: {integrity: sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA==}
engines: {node: ^12.17.0 || ^14.13 || >=16.0.0} engines: {node: ^12.17.0 || ^14.13 || >=16.0.0}
[email protected]:
resolution: {integrity: sha512-PAJdDJusoxnwm1VwW07VWwUN1sl7smmC3OKggvndJFadxxDRyFJBX/ggnu/KE4kQAB7a3Dp8f/YXC1FlUprWmA==}
engines: {node: '>= 16'}
[email protected]: [email protected]:
resolution: {integrity: sha512-rNjApaLzuwaOTjCiT8lSDdGN1APCiqkChLMJxJPWLunPAt5fy8xgU9/jNOchV84wfIxrA0lRQB7oCT8jrn/wrQ==} resolution: {integrity: sha512-rNjApaLzuwaOTjCiT8lSDdGN1APCiqkChLMJxJPWLunPAt5fy8xgU9/jNOchV84wfIxrA0lRQB7oCT8jrn/wrQ==}
engines: {node: '>=6.0'} engines: {node: '>=6.0'}
@@ -4055,6 +4109,10 @@ packages:
babel-plugin-macros: babel-plugin-macros:
optional: true optional: true
[email protected]:
resolution: {integrity: sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q==}
engines: {node: '>=6'}
[email protected]: [email protected]:
resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==} resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==}
@@ -4193,6 +4251,9 @@ packages:
resolution: {integrity: sha512-zWwRvqWiuBPr0muUG/78cW3aHROFCNIQ3zpmYDpwdbnt2m+xlNyRWpHBpa2lJjSBit7BQ+RXA1iwbSmu5yJ/EQ==} resolution: {integrity: sha512-zWwRvqWiuBPr0muUG/78cW3aHROFCNIQ3zpmYDpwdbnt2m+xlNyRWpHBpa2lJjSBit7BQ+RXA1iwbSmu5yJ/EQ==}
engines: {node: '>= 0.4'} engines: {node: '>= 0.4'}
[email protected]:
resolution: {integrity: sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA==}
[email protected]: [email protected]:
resolution: {integrity: sha512-5POEcUuZybH7IdmGsD8wlf0AI55wMecM9rVBTI/qEAy2c1kTOm3DjFYjrBdI2K3BaJjJYfYFeRtM0t9ssnRuxw==} resolution: {integrity: sha512-5POEcUuZybH7IdmGsD8wlf0AI55wMecM9rVBTI/qEAy2c1kTOm3DjFYjrBdI2K3BaJjJYfYFeRtM0t9ssnRuxw==}
@@ -4363,6 +4424,9 @@ packages:
[email protected]: [email protected]:
resolution: {integrity: sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==} resolution: {integrity: sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==}
[email protected]:
resolution: {integrity: sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==}
[email protected]: [email protected]:
resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==} resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==}
engines: {node: '>=0.10.0'} engines: {node: '>=0.10.0'}
@@ -4408,6 +4472,10 @@ packages:
[email protected]: [email protected]:
resolution: {integrity: sha512-c2bQfLNbMzLPmzQuOr8fy0csy84WmwnER81W88DzTp9CYNPJ6yzOj2EZAh9pywYpqHnshVLHQJ8WzldAyfY+Iw==} resolution: {integrity: sha512-c2bQfLNbMzLPmzQuOr8fy0csy84WmwnER81W88DzTp9CYNPJ6yzOj2EZAh9pywYpqHnshVLHQJ8WzldAyfY+Iw==}
[email protected]:
resolution: {integrity: sha512-knvyeauYhqjOYvQ66MznSMs83wmHrCycNEN6Ao+2AeYEfxUIkuiVxdEa1qlGEPK+We3n0THiDciYSsCcgW/DoA==}
engines: {node: '>=12.0.0'}
[email protected]: [email protected]:
resolution: {integrity: sha512-D1dKN+cmyPWuvB+G2SREQDzPY1agpBIcTa9sJxOPMCNeH3gwzhqJRDWCXW3gg0y//+LQ/8j52JbMROWyrKdMdw==} resolution: {integrity: sha512-D1dKN+cmyPWuvB+G2SREQDzPY1agpBIcTa9sJxOPMCNeH3gwzhqJRDWCXW3gg0y//+LQ/8j52JbMROWyrKdMdw==}
engines: {node: '>= 16'} engines: {node: '>= 16'}
@@ -5000,6 +5068,9 @@ packages:
[email protected]: [email protected]:
resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==}
[email protected]:
resolution: {integrity: sha512-mxa9E9ITFOt0ban3j6L5MpjwegGz6lBQmM1IJkWeBZGcMxto50+eWdjC/52xDbS2vy0k7vIMK0Fe2wfL9OQSpQ==}
[email protected]: [email protected]:
resolution: {integrity: sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==} resolution: {integrity: sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==}
hasBin: true hasBin: true
@@ -5180,6 +5251,9 @@ packages:
resolution: {integrity: sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==} resolution: {integrity: sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==}
hasBin: true hasBin: true
[email protected]:
resolution: {integrity: sha512-CdzqowRJCeLU72bHvWqwRBBlLcMEtIvGrlvef74kMnV2AolS9Y8xUv1I0U/MNAWMhBlKIoyuEgoJ0t/bbwHbLQ==}
[email protected]: [email protected]:
resolution: {integrity: sha512-aY/R+aEsRelme17KGQa/1ZSIpLpNYYrhcrepKTZgE+W3WM16YMCaPwOHLHsmopZHELU0Ojin1lPVxKR0MihncA==} resolution: {integrity: sha512-aY/R+aEsRelme17KGQa/1ZSIpLpNYYrhcrepKTZgE+W3WM16YMCaPwOHLHsmopZHELU0Ojin1lPVxKR0MihncA==}
engines: {node: 20 || >=22} engines: {node: 20 || >=22}
@@ -5564,6 +5638,13 @@ packages:
[email protected]: [email protected]:
resolution: {integrity: sha512-7jdwVIRtsP8MYpdXSwOS0YdD0Du+qOoF/AEPIt88PcCFrZCzx41oxku1jD88hZBwbNUIEfpqvuhjFaMAqMTWnA==} resolution: {integrity: sha512-7jdwVIRtsP8MYpdXSwOS0YdD0Du+qOoF/AEPIt88PcCFrZCzx41oxku1jD88hZBwbNUIEfpqvuhjFaMAqMTWnA==}
[email protected]:
resolution: {integrity: sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==}
[email protected]:
resolution: {integrity: sha512-//nshmD55c46FuFw26xV/xFAaB5HF9Xdap7HJBBnrKdAd6/GxDBaNA1870O79+9ueg61cZLSVc+OaFlfmObYVQ==}
engines: {node: '>= 14.16'}
[email protected]: [email protected]:
resolution: {integrity: sha512-XIxfHpEuSJbITd1H3EeQwpcZbTLHc+VVr8ANI9t5sit565tsI4/xK3KWTUFE2e6QiangUkh3B0jihzmGnNrRsQ==} resolution: {integrity: sha512-XIxfHpEuSJbITd1H3EeQwpcZbTLHc+VVr8ANI9t5sit565tsI4/xK3KWTUFE2e6QiangUkh3B0jihzmGnNrRsQ==}
@@ -6057,6 +6138,9 @@ packages:
resolution: {integrity: sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==} resolution: {integrity: sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==}
engines: {node: '>= 0.4'} engines: {node: '>= 0.4'}
[email protected]:
resolution: {integrity: sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==}
[email protected]: [email protected]:
resolution: {integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==} resolution: {integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==}
@@ -6094,6 +6178,9 @@ packages:
[email protected]: [email protected]:
resolution: {integrity: sha512-+L3ccpzibovGXFK+Ap/f8LOS0ahMrHTf3xu7mMLSpEGU0EO9ucaysSylKo9eRDFNhWve/y275iPmIZ4z39a9iA==} resolution: {integrity: sha512-+L3ccpzibovGXFK+Ap/f8LOS0ahMrHTf3xu7mMLSpEGU0EO9ucaysSylKo9eRDFNhWve/y275iPmIZ4z39a9iA==}
[email protected]:
resolution: {integrity: sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==}
[email protected]: [email protected]:
resolution: {integrity: sha512-WjlahMgHmCJpqzU8bIBy4qtsZdU9lRlcZE3Lvyej6t4tuOuv1vk57OW3MBrj6hXBFx/nNoC9MPMTcr5YA7NQbg==} resolution: {integrity: sha512-WjlahMgHmCJpqzU8bIBy4qtsZdU9lRlcZE3Lvyej6t4tuOuv1vk57OW3MBrj6hXBFx/nNoC9MPMTcr5YA7NQbg==}
engines: {node: '>=6'} engines: {node: '>=6'}
@@ -6108,6 +6195,9 @@ packages:
resolution: {integrity: sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==} resolution: {integrity: sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==}
engines: {node: '>= 0.8'} engines: {node: '>= 0.8'}
[email protected]:
resolution: {integrity: sha512-5GS12FdOZNliM5mAOxFRg7Ir0pWz8MdpYm6AY6VPkGpbA7ZzmbzNcBJQ0GPvvyWgcY7QAhCgf9Uy89I03faLkg==}
[email protected]: [email protected]:
resolution: {integrity: sha512-UhDfHmA92YAlNnCfhmq0VeNL5bDbiZGg7sZ2IvPsXubGkiNa9EC+tUTsjBRsYUAz87btI6/1wf4XoVvQ3uRnmQ==} resolution: {integrity: sha512-UhDfHmA92YAlNnCfhmq0VeNL5bDbiZGg7sZ2IvPsXubGkiNa9EC+tUTsjBRsYUAz87btI6/1wf4XoVvQ3uRnmQ==}
engines: {node: '>=18'} engines: {node: '>=18'}
@@ -6184,6 +6274,9 @@ packages:
resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==}
engines: {node: '>=8'} engines: {node: '>=8'}
[email protected]:
resolution: {integrity: sha512-8r3mkIM/2+PpjHoOtiAW8Rg3jJLHaV7xPwG+YRGrv6FP0wwk/toTpATxWYOW0BKdWwl82VT2tFYi5DlROa0Mxg==}
[email protected]: [email protected]:
resolution: {integrity: sha512-fZtbhtvI9I48xDSywd/somNqgUHl2L2cstmXCCif0itOf96jeW18MBSyrLuNicYQVkvpOxkZtkzujiTJ9LW5Jw==} resolution: {integrity: sha512-fZtbhtvI9I48xDSywd/somNqgUHl2L2cstmXCCif0itOf96jeW18MBSyrLuNicYQVkvpOxkZtkzujiTJ9LW5Jw==}
engines: {node: '>=10'} engines: {node: '>=10'}
@@ -6258,13 +6351,31 @@ packages:
[email protected]: [email protected]:
resolution: {integrity: sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg==} resolution: {integrity: sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg==}
[email protected]:
resolution: {integrity: sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==}
[email protected]: [email protected]:
resolution: {integrity: sha512-XPaBkWQJdsf3pLKJV9p4qN/S+fm2Oj8AIPo1BTUhg5oxkvm9+SVEGFdhyOz7tTdUTfvxMiAs4sp6/eZO2Ew+pw==} resolution: {integrity: sha512-XPaBkWQJdsf3pLKJV9p4qN/S+fm2Oj8AIPo1BTUhg5oxkvm9+SVEGFdhyOz7tTdUTfvxMiAs4sp6/eZO2Ew+pw==}
[email protected]:
resolution: {integrity: sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA==}
[email protected]: [email protected]:
resolution: {integrity: sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==} resolution: {integrity: sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==}
engines: {node: '>=12.0.0'} engines: {node: '>=12.0.0'}
[email protected]:
resolution: {integrity: sha512-Zba82s87IFq9A9XmjiX5uZA/ARWDrB03OHlq+Vw1fSdt0I+4/Kutwy8BP4Y/y/aORMo61FQ0vIb5j44vSo5Pkg==}
engines: {node: ^18.0.0 || >=20.0.0}
[email protected]:
resolution: {integrity: sha512-op4nsTR47R6p0vMUUoYl/a+ljLFVtlfaXkLQmqfLR1qHma1h/ysYk4hEXZ880bf2CYgTskvTa/e196Vd5dDQXw==}
engines: {node: '>=14.0.0'}
[email protected]:
resolution: {integrity: sha512-azl+t0z7pw/z958Gy9svOTuzqIk6xq+NSheJzn5MMWtWTFywIacg2wUlzKFGtt3cthx0r2SxMK0yzJOR0IES7Q==}
engines: {node: '>=14.0.0'}
[email protected]: [email protected]:
resolution: {integrity: sha512-YQ7uPjgWUibIK6DW5lrKujGwUKhLevU4hcGbP5O6TcIUb+oTjJYJVWPS4nZsIHrEEEG6myk/oqAJUEQmpZrHsg==} resolution: {integrity: sha512-YQ7uPjgWUibIK6DW5lrKujGwUKhLevU4hcGbP5O6TcIUb+oTjJYJVWPS4nZsIHrEEEG6myk/oqAJUEQmpZrHsg==}
@@ -6466,6 +6577,79 @@ packages:
[email protected]: [email protected]:
resolution: {integrity: sha512-SbPDPdDBYp+5MJHhBCAyI7wKM3d5ivekigc2Dk2s7pgbZ9wIgIBYGVw4zGHBml/qTFbexrofXW6Gu4noGxrOwQ==} resolution: {integrity: sha512-SbPDPdDBYp+5MJHhBCAyI7wKM3d5ivekigc2Dk2s7pgbZ9wIgIBYGVw4zGHBml/qTFbexrofXW6Gu4noGxrOwQ==}
[email protected]:
resolution: {integrity: sha512-EbKSKh+bh1E1IFxeO0pg1n4dvoOTt0UDiXMd/qn++r98+jPO1xtJilvXldeuQ8giIB5IkpjCgMleHMNEsGH6pg==}
engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0}
hasBin: true
[email protected]:
resolution: {integrity: sha512-w+N7Hifpc3gRjZ63vYBXA56dvvRlNWRczTdmCBBa+CotUzAPf5b7YMdMR/8CQoeYE5LX3W4wj6RYTgonm1b9DA==}
engines: {node: ^20.19.0 || >=22.12.0}
hasBin: true
peerDependencies:
'@types/node': ^20.19.0 || >=22.12.0
jiti: '>=1.21.0'
less: ^4.0.0
lightningcss: ^1.21.0
sass: ^1.70.0
sass-embedded: ^1.70.0
stylus: '>=0.54.8'
sugarss: ^5.0.0
terser: ^5.16.0
tsx: ^4.8.1
yaml: ^2.4.2
peerDependenciesMeta:
'@types/node':
optional: true
jiti:
optional: true
less:
optional: true
lightningcss:
optional: true
sass:
optional: true
sass-embedded:
optional: true
stylus:
optional: true
sugarss:
optional: true
terser:
optional: true
tsx:
optional: true
yaml:
optional: true
[email protected]:
resolution: {integrity: sha512-LUCP5ev3GURDysTWiP47wRRUpLKMOfPh+yKTx3kVIEiu5KOMeqzpnYNsKyOoVrULivR8tLcks4+lga33Whn90A==}
engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0}
hasBin: true
peerDependencies:
'@edge-runtime/vm': '*'
'@types/debug': ^4.1.12
'@types/node': ^18.0.0 || ^20.0.0 || >=22.0.0
'@vitest/browser': 3.2.4
'@vitest/ui': 3.2.4
happy-dom: '*'
jsdom: '*'
peerDependenciesMeta:
'@edge-runtime/vm':
optional: true
'@types/debug':
optional: true
'@types/node':
optional: true
'@vitest/browser':
optional: true
'@vitest/ui':
optional: true
happy-dom:
optional: true
jsdom:
optional: true
[email protected]: [email protected]:
resolution: {integrity: sha512-rpJyN222KWIvHJ/F53XSZv0Zl/accqHR8et1kpaMTD/fLCRxtV8iX8czMzY7sVZupTI3zcUTg8eycS2kNF9l6w==} resolution: {integrity: sha512-rpJyN222KWIvHJ/F53XSZv0Zl/accqHR8et1kpaMTD/fLCRxtV8iX8czMzY7sVZupTI3zcUTg8eycS2kNF9l6w==}
@@ -6526,6 +6710,11 @@ packages:
engines: {node: ^16.13.0 || >=18.0.0} engines: {node: ^16.13.0 || >=18.0.0}
hasBin: true hasBin: true
[email protected]:
resolution: {integrity: sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==}
engines: {node: '>=8'}
hasBin: true
[email protected]: [email protected]:
resolution: {integrity: sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==} resolution: {integrity: sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==}
engines: {node: '>=0.10.0'} engines: {node: '>=0.10.0'}
@@ -6821,11 +7010,11 @@ snapshots:
'@babel/helper-string-parser': 7.27.1 '@babel/helper-string-parser': 7.27.1
'@babel/helper-validator-identifier': 7.28.5 '@babel/helper-validator-identifier': 7.28.5
'@better-auth/[email protected](@better-auth/[email protected](@better-auth/[email protected])(@better-fetch/[email protected])(@opentelemetry/[email protected])([email protected]([email protected]))([email protected])([email protected])([email protected]))(@better-auth/[email protected])([email protected](@opentelemetry/[email protected])([email protected](@babel/[email protected])(@opentelemetry/[email protected])([email protected]([email protected]))([email protected]))([email protected]([email protected]))([email protected]))': '@better-auth/[email protected](@better-auth/[email protected](@better-auth/[email protected])(@better-fetch/[email protected])(@opentelemetry/[email protected])([email protected]([email protected]))([email protected])([email protected])([email protected]))(@better-auth/[email protected])([email protected](@opentelemetry/[email protected])([email protected](@babel/[email protected])(@opentelemetry/[email protected])([email protected]([email protected]))([email protected]))([email protected]([email protected]))([email protected])([email protected](@types/[email protected])([email protected])([email protected])([email protected](@types/[email protected])([email protected]))([email protected])))':
dependencies: dependencies:
'@better-auth/core': 1.5.6(@better-auth/[email protected])(@better-fetch/[email protected])(@opentelemetry/[email protected])([email protected]([email protected]))([email protected])([email protected])([email protected]) '@better-auth/core': 1.5.6(@better-auth/[email protected])(@better-fetch/[email protected])(@opentelemetry/[email protected])([email protected]([email protected]))([email protected])([email protected])([email protected])
'@better-auth/utils': 0.3.1 '@better-auth/utils': 0.3.1
better-auth: 1.5.6(@opentelemetry/[email protected])([email protected](@babel/[email protected])(@opentelemetry/[email protected])([email protected]([email protected]))([email protected]))([email protected]([email protected]))([email protected]) better-auth: 1.5.6(@opentelemetry/[email protected])([email protected](@babel/[email protected])(@opentelemetry/[email protected])([email protected]([email protected]))([email protected]))([email protected]([email protected]))([email protected])([email protected](@types/[email protected])([email protected])([email protected])([email protected](@types/[email protected])([email protected]))([email protected]))
zod: 4.3.6 zod: 4.3.6
'@better-auth/[email protected](@better-auth/[email protected])(@better-fetch/[email protected])(@opentelemetry/[email protected])([email protected]([email protected]))([email protected])([email protected])([email protected])': '@better-auth/[email protected](@better-auth/[email protected])(@better-fetch/[email protected])(@opentelemetry/[email protected])([email protected]([email protected]))([email protected])([email protected])([email protected])':
@@ -6863,14 +7052,14 @@ snapshots:
'@better-auth/core': 1.5.6(@better-auth/[email protected])(@better-fetch/[email protected])(@opentelemetry/[email protected])([email protected]([email protected]))([email protected])([email protected])([email protected]) '@better-auth/core': 1.5.6(@better-auth/[email protected])(@better-fetch/[email protected])(@opentelemetry/[email protected])([email protected]([email protected]))([email protected])([email protected])([email protected])
'@better-auth/utils': 0.3.1 '@better-auth/utils': 0.3.1
'@better-auth/[email protected](@better-auth/[email protected](@better-auth/[email protected])(@better-fetch/[email protected])(@opentelemetry/[email protected])([email protected]([email protected]))([email protected])([email protected])([email protected]))(@better-auth/[email protected])(@better-fetch/[email protected])([email protected](@opentelemetry/[email protected])([email protected](@babel/[email protected])(@opentelemetry/[email protected])([email protected]([email protected]))([email protected]))([email protected]([email protected]))([email protected]))([email protected]([email protected]))([email protected])': '@better-auth/[email protected](@better-auth/[email protected](@better-auth/[email protected])(@better-fetch/[email protected])(@opentelemetry/[email protected])([email protected]([email protected]))([email protected])([email protected])([email protected]))(@better-auth/[email protected])(@better-fetch/[email protected])([email protected](@opentelemetry/[email protected])([email protected](@babel/[email protected])(@opentelemetry/[email protected])([email protected]([email protected]))([email protected]))([email protected]([email protected]))([email protected])([email protected](@types/[email protected])([email protected])([email protected])([email protected](@types/[email protected])([email protected]))([email protected])))([email protected]([email protected]))([email protected])':
dependencies: dependencies:
'@better-auth/core': 1.5.6(@better-auth/[email protected])(@better-fetch/[email protected])(@opentelemetry/[email protected])([email protected]([email protected]))([email protected])([email protected])([email protected]) '@better-auth/core': 1.5.6(@better-auth/[email protected])(@better-fetch/[email protected])(@opentelemetry/[email protected])([email protected]([email protected]))([email protected])([email protected])([email protected])
'@better-auth/utils': 0.3.1 '@better-auth/utils': 0.3.1
'@better-fetch/fetch': 1.1.21 '@better-fetch/fetch': 1.1.21
'@simplewebauthn/browser': 13.3.0 '@simplewebauthn/browser': 13.3.0
'@simplewebauthn/server': 13.3.0 '@simplewebauthn/server': 13.3.0
better-auth: 1.5.6(@opentelemetry/[email protected])([email protected](@babel/[email protected])(@opentelemetry/[email protected])([email protected]([email protected]))([email protected]))([email protected]([email protected]))([email protected]) better-auth: 1.5.6(@opentelemetry/[email protected])([email protected](@babel/[email protected])(@opentelemetry/[email protected])([email protected]([email protected]))([email protected]))([email protected]([email protected]))([email protected])([email protected](@types/[email protected])([email protected])([email protected])([email protected](@types/[email protected])([email protected]))([email protected]))
better-call: 1.3.2([email protected]) better-call: 1.3.2([email protected])
nanostores: 1.2.0 nanostores: 1.2.0
zod: 4.3.6 zod: 4.3.6
@@ -6898,10 +7087,10 @@ snapshots:
'@captchafox/[email protected]': {} '@captchafox/[email protected]': {}
'@convex-dev/[email protected](@standard-schema/[email protected])([email protected](@opentelemetry/[email protected])([email protected](@babel/[email protected])(@opentelemetry/[email protected])([email protected]([email protected]))([email protected]))([email protected]([email protected]))([email protected]))([email protected]([email protected]))([email protected])([email protected])([email protected])': '@convex-dev/[email protected](@standard-schema/[email protected])([email protected](@opentelemetry/[email protected])([email protected](@babel/[email protected])(@opentelemetry/[email protected])([email protected]([email protected]))([email protected]))([email protected]([email protected]))([email protected])([email protected](@types/[email protected])([email protected])([email protected])([email protected](@types/[email protected])([email protected]))([email protected])))([email protected]([email protected]))([email protected])([email protected])([email protected])':
dependencies: dependencies:
'@better-fetch/fetch': 1.1.21 '@better-fetch/fetch': 1.1.21
better-auth: 1.5.6(@opentelemetry/[email protected])([email protected](@babel/[email protected])(@opentelemetry/[email protected])([email protected]([email protected]))([email protected]))([email protected]([email protected]))([email protected]) better-auth: 1.5.6(@opentelemetry/[email protected])([email protected](@babel/[email protected])(@opentelemetry/[email protected])([email protected]([email protected]))([email protected]))([email protected]([email protected]))([email protected])([email protected](@types/[email protected])([email protected])([email protected])([email protected](@types/[email protected])([email protected]))([email protected]))
common-tags: 1.8.2 common-tags: 1.8.2
convex: 1.34.0([email protected]) convex: 1.34.0([email protected])
convex-helpers: 0.1.114(@standard-schema/[email protected])([email protected]([email protected]))([email protected])([email protected])([email protected])([email protected]) convex-helpers: 0.1.114(@standard-schema/[email protected])([email protected]([email protected]))([email protected])([email protected])([email protected])([email protected])
@@ -6918,21 +7107,21 @@ snapshots:
'@date-fns/[email protected]': {} '@date-fns/[email protected]': {}
'@daveyplate/[email protected](@tanstack/[email protected])(@tanstack/[email protected]([email protected]))([email protected](@opentelemetry/[email protected])([email protected](@babel/[email protected])(@opentelemetry/[email protected])([email protected]([email protected]))([email protected]))([email protected]([email protected]))([email protected]))([email protected]([email protected]))([email protected])': '@daveyplate/[email protected](@tanstack/[email protected])(@tanstack/[email protected]([email protected]))([email protected](@opentelemetry/[email protected])([email protected](@babel/[email protected])(@opentelemetry/[email protected])([email protected]([email protected]))([email protected]))([email protected]([email protected]))([email protected])([email protected](@types/[email protected])([email protected])([email protected])([email protected](@types/[email protected])([email protected]))([email protected])))([email protected]([email protected]))([email protected])':
dependencies: dependencies:
'@tanstack/query-core': 5.95.2 '@tanstack/query-core': 5.95.2
'@tanstack/react-query': 5.95.2([email protected]) '@tanstack/react-query': 5.95.2([email protected])
better-auth: 1.5.6(@opentelemetry/[email protected])([email protected](@babel/[email protected])(@opentelemetry/[email protected])([email protected]([email protected]))([email protected]))([email protected]([email protected]))([email protected]) better-auth: 1.5.6(@opentelemetry/[email protected])([email protected](@babel/[email protected])(@opentelemetry/[email protected])([email protected]([email protected]))([email protected]))([email protected]([email protected]))([email protected])([email protected](@types/[email protected])([email protected])([email protected])([email protected](@types/[email protected])([email protected]))([email protected]))
react: 19.2.4 react: 19.2.4
react-dom: 19.2.4([email protected]) react-dom: 19.2.4([email protected])
'@daveyplate/[email protected](aed41ba285ba33af5b1a54a1a4efb176)': '@daveyplate/[email protected](43fe9e8f7c24dd7a61ee43b650bb480d)':
dependencies: dependencies:
'@better-auth/api-key': 1.5.6(@better-auth/[email protected](@better-auth/[email protected])(@better-fetch/[email protected])(@opentelemetry/[email protected])([email protected]([email protected]))([email protected])([email protected])([email protected]))(@better-auth/[email protected])([email protected](@opentelemetry/[email protected])([email protected](@babel/[email protected])(@opentelemetry/[email protected])([email protected]([email protected]))([email protected]))([email protected]([email protected]))([email protected])) '@better-auth/api-key': 1.5.6(@better-auth/[email protected](@better-auth/[email protected])(@better-fetch/[email protected])(@opentelemetry/[email protected])([email protected]([email protected]))([email protected])([email protected])([email protected]))(@better-auth/[email protected])([email protected](@opentelemetry/[email protected])([email protected](@babel/[email protected])(@opentelemetry/[email protected])([email protected]([email protected]))([email protected]))([email protected]([email protected]))([email protected])([email protected](@types/[email protected])([email protected])([email protected])([email protected](@types/[email protected])([email protected]))([email protected])))
'@better-auth/passkey': 1.5.6(@better-auth/[email protected](@better-auth/[email protected])(@better-fetch/[email protected])(@opentelemetry/[email protected])([email protected]([email protected]))([email protected])([email protected])([email protected]))(@better-auth/[email protected])(@better-fetch/[email protected])([email protected](@opentelemetry/[email protected])([email protected](@babel/[email protected])(@opentelemetry/[email protected])([email protected]([email protected]))([email protected]))([email protected]([email protected]))([email protected]))([email protected]([email protected]))([email protected]) '@better-auth/passkey': 1.5.6(@better-auth/[email protected](@better-auth/[email protected])(@better-fetch/[email protected])(@opentelemetry/[email protected])([email protected]([email protected]))([email protected])([email protected])([email protected]))(@better-auth/[email protected])(@better-fetch/[email protected])([email protected](@opentelemetry/[email protected])([email protected](@babel/[email protected])(@opentelemetry/[email protected])([email protected]([email protected]))([email protected]))([email protected]([email protected]))([email protected])([email protected](@types/[email protected])([email protected])([email protected])([email protected](@types/[email protected])([email protected]))([email protected])))([email protected]([email protected]))([email protected])
'@better-fetch/fetch': 1.1.21 '@better-fetch/fetch': 1.1.21
'@captchafox/react': 1.11.0([email protected]([email protected]))([email protected]) '@captchafox/react': 1.11.0([email protected]([email protected]))([email protected])
'@daveyplate/better-auth-tanstack': 1.3.6(@tanstack/[email protected])(@tanstack/[email protected]([email protected]))([email protected](@opentelemetry/[email protected])([email protected](@babel/[email protected])(@opentelemetry/[email protected])([email protected]([email protected]))([email protected]))([email protected]([email protected]))([email protected]))([email protected]([email protected]))([email protected]) '@daveyplate/better-auth-tanstack': 1.3.6(@tanstack/[email protected])(@tanstack/[email protected]([email protected]))([email protected](@opentelemetry/[email protected])([email protected](@babel/[email protected])(@opentelemetry/[email protected])([email protected]([email protected]))([email protected]))([email protected]([email protected]))([email protected])([email protected](@types/[email protected])([email protected])([email protected])([email protected](@types/[email protected])([email protected]))([email protected])))([email protected]([email protected]))([email protected])
'@hcaptcha/react-hcaptcha': 2.0.2 '@hcaptcha/react-hcaptcha': 2.0.2
'@hookform/resolvers': 5.2.2([email protected]([email protected])) '@hookform/resolvers': 5.2.2([email protected]([email protected]))
'@instantdb/react': 0.22.169([email protected]) '@instantdb/react': 0.22.169([email protected])
@@ -6957,7 +7146,7 @@ snapshots:
'@triplit/client': 1.0.50([email protected]) '@triplit/client': 1.0.50([email protected])
'@triplit/react': 1.0.51([email protected])([email protected]) '@triplit/react': 1.0.51([email protected])([email protected])
'@wojtekmaj/react-recaptcha-v3': 0.1.4(@types/[email protected])([email protected]([email protected]))([email protected]) '@wojtekmaj/react-recaptcha-v3': 0.1.4(@types/[email protected])([email protected]([email protected]))([email protected])
better-auth: 1.5.6(@opentelemetry/[email protected])([email protected](@babel/[email protected])(@opentelemetry/[email protected])([email protected]([email protected]))([email protected]))([email protected]([email protected]))([email protected]) better-auth: 1.5.6(@opentelemetry/[email protected])([email protected](@babel/[email protected])(@opentelemetry/[email protected])([email protected]([email protected]))([email protected]))([email protected]([email protected]))([email protected])([email protected](@types/[email protected])([email protected])([email protected])([email protected](@types/[email protected])([email protected]))([email protected]))
better-call: 2.0.2([email protected]) better-call: 2.0.2([email protected])
bowser: 2.14.1 bowser: 2.14.1
class-variance-authority: 0.7.1 class-variance-authority: 0.7.1
@@ -8171,11 +8360,11 @@ snapshots:
tslib: 2.8.1 tslib: 2.8.1
tsyringe: 4.10.0 tsyringe: 4.10.0
'@polar-sh/[email protected](@polar-sh/[email protected])(@stripe/[email protected](@stripe/[email protected])([email protected]([email protected]))([email protected]))(@stripe/[email protected])(@types/[email protected](@types/[email protected]))(@types/[email protected])([email protected](@opentelemetry/[email protected])([email protected](@babel/[email protected])(@opentelemetry/[email protected])([email protected]([email protected]))([email protected]))([email protected]([email protected]))([email protected]))([email protected]([email protected]))([email protected])([email protected])([email protected])([email protected])': '@polar-sh/[email protected](@polar-sh/[email protected])(@stripe/[email protected](@stripe/[email protected])([email protected]([email protected]))([email protected]))(@stripe/[email protected])(@types/[email protected](@types/[email protected]))(@types/[email protected])([email protected](@opentelemetry/[email protected])([email protected](@babel/[email protected])(@opentelemetry/[email protected])([email protected]([email protected]))([email protected]))([email protected]([email protected]))([email protected])([email protected](@types/[email protected])([email protected])([email protected])([email protected](@types/[email protected])([email protected]))([email protected])))([email protected]([email protected]))([email protected])([email protected])([email protected])([email protected])':
dependencies: dependencies:
'@polar-sh/checkout': 0.2.0(@stripe/[email protected](@stripe/[email protected])([email protected]([email protected]))([email protected]))(@stripe/[email protected])(@types/[email protected](@types/[email protected]))(@types/[email protected])([email protected]([email protected]))([email protected])([email protected])([email protected]) '@polar-sh/checkout': 0.2.0(@stripe/[email protected](@stripe/[email protected])([email protected]([email protected]))([email protected]))(@stripe/[email protected])(@types/[email protected](@types/[email protected]))(@types/[email protected])([email protected]([email protected]))([email protected])([email protected])([email protected])
'@polar-sh/sdk': 0.46.7 '@polar-sh/sdk': 0.46.7
better-auth: 1.5.6(@opentelemetry/[email protected])([email protected](@babel/[email protected])(@opentelemetry/[email protected])([email protected]([email protected]))([email protected]))([email protected]([email protected]))([email protected]) better-auth: 1.5.6(@opentelemetry/[email protected])([email protected](@babel/[email protected])(@opentelemetry/[email protected])([email protected]([email protected]))([email protected]))([email protected]([email protected]))([email protected])([email protected](@types/[email protected])([email protected])([email protected])([email protected](@types/[email protected])([email protected]))([email protected]))
zod: 4.3.6 zod: 4.3.6
transitivePeerDependencies: transitivePeerDependencies:
- '@stripe/react-stripe-js' - '@stripe/react-stripe-js'
@@ -9687,6 +9876,11 @@ snapshots:
tslib: 2.8.1 tslib: 2.8.1
optional: true optional: true
'@types/[email protected]':
dependencies:
'@types/deep-eql': 4.0.2
assertion-error: 2.0.1
'@types/[email protected]': '@types/[email protected]':
dependencies: dependencies:
'@types/node': 20.19.37 '@types/node': 20.19.37
@@ -9730,6 +9924,8 @@ snapshots:
'@types/d3-interpolate': 3.0.4 '@types/d3-interpolate': 3.0.4
'@types/d3-selection': 3.0.11 '@types/d3-selection': 3.0.11
'@types/[email protected]': {}
'@types/[email protected]': '@types/[email protected]':
dependencies: dependencies:
'@types/eslint': 9.6.1 '@types/eslint': 9.6.1
@@ -9944,6 +10140,49 @@ snapshots:
'@unrs/[email protected]': '@unrs/[email protected]':
optional: true optional: true
'@vitest/[email protected]':
dependencies:
'@types/chai': 5.2.3
'@vitest/spy': 3.2.4
'@vitest/utils': 3.2.4
chai: 5.3.3
tinyrainbow: 2.0.0
'@vitest/[email protected]([email protected](@types/[email protected])([email protected]))([email protected](@types/[email protected])([email protected])([email protected])([email protected]))':
dependencies:
'@vitest/spy': 3.2.4
estree-walker: 3.0.3
magic-string: 0.30.21
optionalDependencies:
msw: 2.12.14(@types/[email protected])([email protected])
vite: 7.3.1(@types/[email protected])([email protected])([email protected])([email protected])
'@vitest/[email protected]':
dependencies:
tinyrainbow: 2.0.0
'@vitest/[email protected]':
dependencies:
'@vitest/utils': 3.2.4
pathe: 2.0.3
strip-literal: 3.1.0
'@vitest/[email protected]':
dependencies:
'@vitest/pretty-format': 3.2.4
magic-string: 0.30.21
pathe: 2.0.3
'@vitest/[email protected]':
dependencies:
tinyspy: 4.0.4
'@vitest/[email protected]':
dependencies:
'@vitest/pretty-format': 3.2.4
loupe: 3.2.1
tinyrainbow: 2.0.0
'@webassemblyjs/[email protected]': '@webassemblyjs/[email protected]':
dependencies: dependencies:
'@webassemblyjs/helper-numbers': 1.13.2 '@webassemblyjs/helper-numbers': 1.13.2
@@ -10204,6 +10443,8 @@ snapshots:
pvutils: 1.1.5 pvutils: 1.1.5
tslib: 2.8.1 tslib: 2.8.1
[email protected]: {}
[email protected]: {} [email protected]: {}
[email protected]: [email protected]:
@@ -10230,7 +10471,7 @@ snapshots:
[email protected]: {} [email protected]: {}
[email protected](@opentelemetry/[email protected])([email protected](@babel/[email protected])(@opentelemetry/[email protected])([email protected]([email protected]))([email protected]))([email protected]([email protected]))([email protected]): [email protected](@opentelemetry/[email protected])([email protected](@babel/[email protected])(@opentelemetry/[email protected])([email protected]([email protected]))([email protected]))([email protected]([email protected]))([email protected])([email protected](@types/[email protected])([email protected])([email protected])([email protected](@types/[email protected])([email protected]))([email protected])):
dependencies: dependencies:
'@better-auth/core': 1.5.6(@better-auth/[email protected])(@better-fetch/[email protected])(@opentelemetry/[email protected])([email protected]([email protected]))([email protected])([email protected])([email protected]) '@better-auth/core': 1.5.6(@better-auth/[email protected])(@better-fetch/[email protected])(@opentelemetry/[email protected])([email protected]([email protected]))([email protected])([email protected])([email protected])
'@better-auth/drizzle-adapter': 1.5.6(@better-auth/[email protected](@better-auth/[email protected])(@better-fetch/[email protected])(@opentelemetry/[email protected])([email protected]([email protected]))([email protected])([email protected])([email protected]))(@better-auth/[email protected]) '@better-auth/drizzle-adapter': 1.5.6(@better-auth/[email protected](@better-auth/[email protected])(@better-fetch/[email protected])(@opentelemetry/[email protected])([email protected]([email protected]))([email protected])([email protected])([email protected]))(@better-auth/[email protected])
@@ -10253,6 +10494,7 @@ snapshots:
next: 16.2.1(@babel/[email protected])(@opentelemetry/[email protected])([email protected]([email protected]))([email protected]) next: 16.2.1(@babel/[email protected])(@opentelemetry/[email protected])([email protected]([email protected]))([email protected])
react: 19.2.4 react: 19.2.4
react-dom: 19.2.4([email protected]) react-dom: 19.2.4([email protected])
vitest: 3.2.4(@types/[email protected])([email protected])([email protected])([email protected](@types/[email protected])([email protected]))([email protected])
transitivePeerDependencies: transitivePeerDependencies:
- '@cloudflare/workers-types' - '@cloudflare/workers-types'
- '@opentelemetry/api' - '@opentelemetry/api'
@@ -10327,6 +10569,8 @@ snapshots:
[email protected]: {} [email protected]: {}
[email protected]: {}
[email protected]: [email protected]:
dependencies: dependencies:
es-errors: 1.3.0 es-errors: 1.3.0
@@ -10348,6 +10592,14 @@ snapshots:
[email protected]: {} [email protected]: {}
[email protected]:
dependencies:
assertion-error: 2.0.1
check-error: 2.1.3
deep-eql: 5.0.2
loupe: 3.2.1
pathval: 2.0.1
[email protected]: [email protected]:
dependencies: dependencies:
ansi-styles: 4.3.0 ansi-styles: 4.3.0
@@ -10355,6 +10607,8 @@ snapshots:
[email protected]: {} [email protected]: {}
[email protected]: {}
[email protected]: {} [email protected]: {}
[email protected]: {} [email protected]: {}
@@ -10588,6 +10842,8 @@ snapshots:
[email protected]: {} [email protected]: {}
[email protected]: {}
[email protected]: {} [email protected]: {}
[email protected]: {} [email protected]: {}
@@ -10774,6 +11030,8 @@ snapshots:
math-intrinsics: 1.1.0 math-intrinsics: 1.1.0
safe-array-concat: 1.1.3 safe-array-concat: 1.1.3
[email protected]: {}
[email protected]: {} [email protected]: {}
[email protected]: [email protected]:
@@ -11048,6 +11306,10 @@ snapshots:
[email protected]: {} [email protected]: {}
[email protected]:
dependencies:
'@types/estree': 1.0.8
[email protected]: {} [email protected]: {}
[email protected]: {} [email protected]: {}
@@ -11101,6 +11363,8 @@ snapshots:
[email protected]: {} [email protected]: {}
[email protected]: {}
[email protected]([email protected]): [email protected]([email protected]):
dependencies: dependencies:
express: 5.2.1 express: 5.2.1
@@ -11734,6 +11998,8 @@ snapshots:
[email protected]: {} [email protected]: {}
[email protected]: {}
[email protected]: [email protected]:
dependencies: dependencies:
argparse: 2.0.1 argparse: 2.0.1
@@ -11877,6 +12143,8 @@ snapshots:
dependencies: dependencies:
js-tokens: 4.0.0 js-tokens: 4.0.0
[email protected]: {}
[email protected]: {} [email protected]: {}
[email protected]: [email protected]:
@@ -12248,6 +12516,10 @@ snapshots:
[email protected]: {} [email protected]: {}
[email protected]: {}
[email protected]: {}
[email protected]: {} [email protected]: {}
[email protected]: {} [email protected]: {}
@@ -12916,6 +13188,8 @@ snapshots:
side-channel-map: 1.0.1 side-channel-map: 1.0.1
side-channel-weakmap: 1.0.2 side-channel-weakmap: 1.0.2
[email protected]: {}
[email protected]: {} [email protected]: {}
[email protected]: {} [email protected]: {}
@@ -12942,6 +13216,8 @@ snapshots:
[email protected]: {} [email protected]: {}
[email protected]: {}
[email protected]: [email protected]:
dependencies: dependencies:
type-fest: 0.7.1 type-fest: 0.7.1
@@ -12955,6 +13231,8 @@ snapshots:
[email protected]: {} [email protected]: {}
[email protected]: {}
[email protected]: {} [email protected]: {}
[email protected]: [email protected]:
@@ -13056,6 +13334,10 @@ snapshots:
[email protected]: {} [email protected]: {}
[email protected]:
dependencies:
js-tokens: 9.0.1
[email protected]: [email protected]:
dependencies: dependencies:
'@tokenizer/token': 0.3.0 '@tokenizer/token': 0.3.0
@@ -13109,13 +13391,23 @@ snapshots:
[email protected]: {} [email protected]: {}
[email protected]: {}
[email protected]: {} [email protected]: {}
[email protected]: {}
[email protected]: [email protected]:
dependencies: dependencies:
fdir: 6.5.0([email protected]) fdir: 6.5.0([email protected])
picomatch: 4.0.4 picomatch: 4.0.4
[email protected]: {}
[email protected]: {}
[email protected]: {}
[email protected]: {} [email protected]: {}
[email protected]: [email protected]:
@@ -13355,6 +13647,83 @@ snapshots:
d3-time: 3.1.0 d3-time: 3.1.0
d3-timer: 3.0.1 d3-timer: 3.0.1
[email protected](@types/[email protected])([email protected])([email protected])([email protected]):
dependencies:
cac: 6.7.14
debug: 4.4.3
es-module-lexer: 1.7.0
pathe: 2.0.3
vite: 7.3.1(@types/[email protected])([email protected])([email protected])([email protected])
transitivePeerDependencies:
- '@types/node'
- jiti
- less
- lightningcss
- sass
- sass-embedded
- stylus
- sugarss
- supports-color
- terser
- tsx
- yaml
[email protected](@types/[email protected])([email protected])([email protected])([email protected]):
dependencies:
esbuild: 0.27.0
fdir: 6.5.0([email protected])
picomatch: 4.0.4
postcss: 8.5.8
rollup: 4.60.0
tinyglobby: 0.2.15
optionalDependencies:
'@types/node': 20.19.37
fsevents: 2.3.3
jiti: 2.6.1
lightningcss: 1.32.0
terser: 5.46.1
[email protected](@types/[email protected])([email protected])([email protected])([email protected](@types/[email protected])([email protected]))([email protected]):
dependencies:
'@types/chai': 5.2.3
'@vitest/expect': 3.2.4
'@vitest/mocker': 3.2.4([email protected](@types/[email protected])([email protected]))([email protected](@types/[email protected])([email protected])([email protected])([email protected]))
'@vitest/pretty-format': 3.2.4
'@vitest/runner': 3.2.4
'@vitest/snapshot': 3.2.4
'@vitest/spy': 3.2.4
'@vitest/utils': 3.2.4
chai: 5.3.3
debug: 4.4.3
expect-type: 1.3.0
magic-string: 0.30.21
pathe: 2.0.3
picomatch: 4.0.4
std-env: 3.10.0
tinybench: 2.9.0
tinyexec: 0.3.2
tinyglobby: 0.2.15
tinypool: 1.1.1
tinyrainbow: 2.0.0
vite: 7.3.1(@types/[email protected])([email protected])([email protected])([email protected])
vite-node: 3.2.4(@types/[email protected])([email protected])([email protected])([email protected])
why-is-node-running: 2.3.0
optionalDependencies:
'@types/node': 20.19.37
transitivePeerDependencies:
- jiti
- less
- lightningcss
- msw
- sass
- sass-embedded
- stylus
- sugarss
- supports-color
- terser
- tsx
- yaml
[email protected]: [email protected]:
dependencies: dependencies:
loose-envify: 1.4.0 loose-envify: 1.4.0
@@ -13458,6 +13827,11 @@ snapshots:
dependencies: dependencies:
isexe: 3.1.5 isexe: 3.1.5
[email protected]:
dependencies:
siginfo: 2.0.0
stackback: 0.0.2
[email protected]: {} [email protected]: {}
[email protected]: [email protected]:
+22
View File
@@ -0,0 +1,22 @@
import { describe, expect, it } from "vitest";
import { assertNodeBelongsToCanvasOrThrow } from "@/convex/ai-utils";
describe("assertNodeBelongsToCanvasOrThrow", () => {
it("accepts matching node/canvas relation", () => {
expect(() =>
assertNodeBelongsToCanvasOrThrow(
{ canvasId: "canvas_a" },
"canvas_a",
),
).not.toThrow();
});
it("rejects mismatching node/canvas relation", () => {
expect(() =>
assertNodeBelongsToCanvasOrThrow(
{ canvasId: "canvas_b" },
"canvas_a",
),
).toThrow("Node does not belong to canvas");
});
});
@@ -0,0 +1,43 @@
import { describe, expect, it } from "vitest";
import type { Id } from "@/convex/_generated/dataModel";
import { validateBatchNodesForUserOrThrow } from "@/convex/batch-validation-utils";
describe("validateBatchNodesForUserOrThrow", () => {
it("rejects mixed canvas ids in one batch", async () => {
const nodeA = {
_id: "node_a" as Id<"nodes">,
canvasId: "canvas_a" as Id<"canvases">,
};
const nodeB = {
_id: "node_b" as Id<"nodes">,
canvasId: "canvas_b" as Id<"canvases">,
};
await expect(
validateBatchNodesForUserOrThrow({
userId: "user_1",
nodeIds: [nodeA._id, nodeB._id],
getNodeById: async (nodeId) => {
if (nodeId === nodeA._id) return nodeA;
if (nodeId === nodeB._id) return nodeB;
return null;
},
getCanvasById: async () => ({ _id: "canvas_a" as Id<"canvases">, ownerId: "user_1" }),
}),
).rejects.toThrow("All nodes must belong to the same canvas");
});
it("rejects foreign canvas ownership", async () => {
const canvasId = "canvas_a" as Id<"canvases">;
const node = { _id: "node_a" as Id<"nodes">, canvasId };
await expect(
validateBatchNodesForUserOrThrow({
userId: "user_1",
nodeIds: [node._id],
getNodeById: async () => node,
getCanvasById: async () => ({ _id: canvasId, ownerId: "other_user" }),
}),
).rejects.toThrow("Canvas not found");
});
});
+62
View File
@@ -0,0 +1,62 @@
import { describe, expect, it } from "vitest";
import {
buildSubscriptionCycleIdempotencyKey,
buildSubscriptionRevokedIdempotencyKey,
buildTopUpPaidIdempotencyKey,
registerWebhookEventOnce,
type WebhookEventRepo,
} from "@/convex/polar-utils";
describe("polar idempotency helpers", () => {
it("builds stable idempotency keys", () => {
expect(
buildSubscriptionCycleIdempotencyKey({
polarSubscriptionId: "sub_123",
currentPeriodStart: 100,
currentPeriodEnd: 200,
}),
).toBe("polar:subscription_cycle:sub_123:100:200");
expect(
buildSubscriptionRevokedIdempotencyKey({
userId: "user_1",
polarSubscriptionId: "sub_123",
}),
).toBe("polar:subscription_revoked:sub_123");
expect(
buildSubscriptionRevokedIdempotencyKey({
userId: "user_1",
}),
).toBe("polar:subscription_revoked:user:user_1");
expect(buildTopUpPaidIdempotencyKey("order_77")).toBe("polar:order_paid:order_77");
});
it("dedupes repeated webhook events by provider/key", async () => {
const seen = new Set<string>();
let inserted = 0;
const repo: WebhookEventRepo = {
findByProviderAndKey: async ({ provider, idempotencyKey }) => {
const key = `${provider}:${idempotencyKey}`;
return seen.has(key) ? { _id: "evt_1" } : null;
},
insert: async ({ provider, idempotencyKey }) => {
seen.add(`${provider}:${idempotencyKey}`);
inserted += 1;
},
};
const args = {
provider: "polar" as const,
scope: "topup_paid" as const,
idempotencyKey: "polar:order_paid:order_1",
userId: "user_1",
polarOrderId: "order_1",
};
await expect(registerWebhookEventOnce(repo, args, () => 123)).resolves.toBe(true);
await expect(registerWebhookEventOnce(repo, args, () => 123)).resolves.toBe(false);
expect(inserted).toBe(1);
});
});
+14
View File
@@ -0,0 +1,14 @@
import path from "node:path";
import { defineConfig } from "vitest/config";
export default defineConfig({
resolve: {
alias: {
"@": path.resolve(__dirname, "."),
},
},
test: {
environment: "node",
include: ["tests/**/*.test.ts"],
},
});