diff --git a/CLAUDE.md b/CLAUDE.md index 9b9e9d12..021f3492 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -3,3 +3,6 @@ - do never commit unless you're asked to. - only commit what you're asked to commit, no adding extra changes unless asked - when person asks the question, but not asking you to do the thing, you only answer the question, you don't do the thing you're not asked to do! +- STOP before any file edit. Ask yourself: "Did they explicitly say to make changes?" If no → DO NOT EDIT. Present findings and wait. +- "find", "check", "investigate", "research", "explain", "look into" = RESEARCH ONLY. Never edit code. +- The ONLY trigger for code changes is explicit words like: "do it", "fix it", "implement", "make the change", "go ahead" diff --git a/apps/demo/package.json b/apps/demo/package.json index 0c6c9e61..ae5054ba 100644 --- a/apps/demo/package.json +++ b/apps/demo/package.json @@ -19,6 +19,7 @@ "dependencies": { "@base-ui/react": "^1.2.0", "@paykitjs/dash": "workspace:^", + "@paykitjs/polar": "workspace:*", "@paykitjs/stripe": "workspace:*", "@t3-oss/env-nextjs": "^0.12.0", "@tanstack/react-query": "^5.69.0", diff --git a/apps/demo/src/app/_components/auth-form.tsx b/apps/demo/src/app/_components/auth-form.tsx index 94a2e306..24def59e 100644 --- a/apps/demo/src/app/_components/auth-form.tsx +++ b/apps/demo/src/app/_components/auth-form.tsx @@ -13,7 +13,6 @@ export function AuthForm({ redirectTo }: { redirectTo: string }) { const router = useRouter(); const [email, setEmail] = useState(""); const [password, setPassword] = useState(""); - const [name, setName] = useState(""); const [isSignUp, setIsSignUp] = useState(false); const [error, setError] = useState(""); const [loading, setLoading] = useState(false); @@ -28,7 +27,7 @@ export function AuthForm({ redirectTo }: { redirectTo: string }) { const result = await authClient.signUp.email({ email, password, - name, + name: "Demo User", }); if (result.error) { setError(result.error.message ?? "Sign up failed"); @@ -60,17 +59,6 @@ export function AuthForm({ redirectTo }: { redirectTo: string }) {
- {isSignUp ? ( -
- - setName(event.target.value)} - placeholder="Your name" - value={name} - /> -
- ) : null}
{testClock.data.status} : null} - Advance the logged-in customer through Stripe billing cycles without leaving the demo. + Advance the logged-in customer through billing cycles without leaving the demo. @@ -191,7 +191,7 @@ function TestClockPanel() { {formatDateTime(testClock.data.frozenTime)} - Stripe time + Test clock
{actions.map((action) => ( diff --git a/apps/demo/src/app/paykit/[[...slug]]/route.ts b/apps/demo/src/app/paykit/[[...slug]]/route.ts index 810aae5f..92db7105 100644 --- a/apps/demo/src/app/paykit/[[...slug]]/route.ts +++ b/apps/demo/src/app/paykit/[[...slug]]/route.ts @@ -1,5 +1,5 @@ import { paykitHandler } from "paykitjs/handlers/next"; -import { paykit } from "@/server/paykit"; +import { paykit } from "@/lib/paykit"; export const { GET, POST } = paykitHandler(paykit); diff --git a/apps/demo/src/env.js b/apps/demo/src/env.js index 3c8acb01..4b6bae30 100644 --- a/apps/demo/src/env.js +++ b/apps/demo/src/env.js @@ -1,5 +1,5 @@ import { createEnv } from "@t3-oss/env-nextjs"; -import { z } from "zod"; +import * as z from "zod"; export const env = createEnv({ /** @@ -10,8 +10,10 @@ export const env = createEnv({ APP_URL: z.string().url(), DATABASE_URL: z.string().min(1), NODE_ENV: z.enum(["development", "test", "production"]).default("development"), - STRIPE_SECRET_KEY: z.string().min(1), - STRIPE_WEBHOOK_SECRET: z.string().min(1), + STRIPE_SECRET_KEY: z.string().min(1).optional(), + STRIPE_WEBHOOK_SECRET: z.string().min(1).optional(), + POLAR_ACCESS_TOKEN: z.string().min(1), + POLAR_WEBHOOK_SECRET: z.string().min(1), BETTER_AUTH_SECRET: z.string().min(1), AUTUMN_SECRET_KEY: z.string().min(1).optional(), }, @@ -35,6 +37,8 @@ export const env = createEnv({ NODE_ENV: process.env.NODE_ENV, STRIPE_SECRET_KEY: process.env.STRIPE_SECRET_KEY, STRIPE_WEBHOOK_SECRET: process.env.STRIPE_WEBHOOK_SECRET, + POLAR_ACCESS_TOKEN: process.env.POLAR_ACCESS_TOKEN, + POLAR_WEBHOOK_SECRET: process.env.POLAR_WEBHOOK_SECRET, BETTER_AUTH_SECRET: process.env.BETTER_AUTH_SECRET, AUTUMN_SECRET_KEY: process.env.AUTUMN_SECRET_KEY, // NEXT_PUBLIC_CLIENTVAR: process.env.NEXT_PUBLIC_CLIENTVAR, diff --git a/apps/demo/src/lib/paykit-client.ts b/apps/demo/src/lib/paykit-client.ts index f1564901..6f8c66a1 100644 --- a/apps/demo/src/lib/paykit-client.ts +++ b/apps/demo/src/lib/paykit-client.ts @@ -1,5 +1,5 @@ import { createPayKitClient } from "paykitjs/client"; -import type { paykit } from "@/server/paykit"; +import type { paykit } from "@/lib/paykit"; export const paykitClient = createPayKitClient(); diff --git a/apps/demo/src/server/plans.ts b/apps/demo/src/lib/paykit-products.ts similarity index 100% rename from apps/demo/src/server/plans.ts rename to apps/demo/src/lib/paykit-products.ts diff --git a/apps/demo/src/server/paykit.ts b/apps/demo/src/lib/paykit.ts similarity index 68% rename from apps/demo/src/server/paykit.ts rename to apps/demo/src/lib/paykit.ts index 313d3880..41f0f6b7 100644 --- a/apps/demo/src/server/paykit.ts +++ b/apps/demo/src/lib/paykit.ts @@ -1,19 +1,25 @@ import { dash } from "@paykitjs/dash"; -import { stripe } from "@paykitjs/stripe"; +import { polar } from "@paykitjs/polar"; +// import { stripe } from "@paykitjs/stripe"; import { createPayKit } from "paykitjs"; import { env } from "@/env"; import { auth } from "@/server/auth"; import { pool } from "@/server/db"; -import { free, pro, ultra } from "./plans"; +import { free, pro, ultra } from "./paykit-products"; export const paykit = createPayKit({ testing: { enabled: true }, database: pool, - provider: stripe({ - secretKey: env.STRIPE_SECRET_KEY, - webhookSecret: env.STRIPE_WEBHOOK_SECRET, + // provider: stripe({ + // secretKey: env.STRIPE_SECRET_KEY, + // webhookSecret: env.STRIPE_WEBHOOK_SECRET, + // }), + provider: polar({ + accessToken: env.POLAR_ACCESS_TOKEN, + webhookSecret: env.POLAR_WEBHOOK_SECRET, + server: "sandbox", }), plans: [pro, ultra, free], plugins: [ diff --git a/apps/demo/src/server/api/root.ts b/apps/demo/src/server/api/root.ts index 53dbfd5e..8d03d59b 100644 --- a/apps/demo/src/server/api/root.ts +++ b/apps/demo/src/server/api/root.ts @@ -1,5 +1,5 @@ import { autumnRouter } from "@/server/api/routers/autumn"; -import { paykitRouter } from "@/server/api/routers/paykit"; +import { paykitRouter } from "@/server/api/routers/paykit-route"; import { postRouter } from "@/server/api/routers/post"; import { createCallerFactory, createTRPCRouter } from "@/server/api/trpc"; diff --git a/apps/demo/src/server/api/routers/paykit.ts b/apps/demo/src/server/api/routers/paykit-route.ts similarity index 96% rename from apps/demo/src/server/api/routers/paykit.ts rename to apps/demo/src/server/api/routers/paykit-route.ts index 7624ecfb..c0615765 100644 --- a/apps/demo/src/server/api/routers/paykit.ts +++ b/apps/demo/src/server/api/routers/paykit-route.ts @@ -1,9 +1,10 @@ import { TRPCError } from "@trpc/server"; import { z } from "zod"; +import { paykit } from "@/lib/paykit"; +import type { PayKit } from "@/lib/paykit"; import { createTRPCRouter, publicProcedure } from "@/server/api/trpc"; import { auth } from "@/server/auth"; -import { paykit, type PayKit } from "@/server/paykit"; export const paykitRouter = createTRPCRouter({ createCustomer: publicProcedure.mutation(async ({ ctx }) => { diff --git a/e2e/cli/setup.ts b/e2e/cli/setup.ts index 73fcb705..8b74b8fe 100644 --- a/e2e/cli/setup.ts +++ b/e2e/cli/setup.ts @@ -2,15 +2,12 @@ import fs from "node:fs/promises"; import os from "node:os"; import path from "node:path"; -import { config } from "dotenv"; import { Pool } from "pg"; import { default as Stripe } from "stripe"; -process.env.PAYKIT_CLI = "1"; +import { env } from "../env"; -// Load env from repo root -config({ path: path.resolve(import.meta.dirname, "../../.env") }); -config({ path: path.resolve(import.meta.dirname, "../../.env.local"), override: true }); +process.env.PAYKIT_CLI = "1"; const packageRoot = path.resolve(import.meta.dirname, "../../packages/paykit"); const createPayKitPath = path.resolve(packageRoot, "src/index.ts"); @@ -29,17 +26,17 @@ export interface CliTestFixture { * Postgres DB and real Stripe. Returns everything needed for cleanup. */ export async function createCliFixture(_globalKey: string): Promise { - const secretKey = process.env.STRIPE_SECRET_KEY; - const webhookSecret = process.env.STRIPE_WEBHOOK_SECRET; + const secretKey = env.E2E_STRIPE_SK; + const webhookSecret = env.E2E_STRIPE_WHSEC; if (!secretKey || !webhookSecret) { - throw new Error("STRIPE_SECRET_KEY and STRIPE_WEBHOOK_SECRET must be set"); + throw new Error("E2E_STRIPE_SK and E2E_STRIPE_WHSEC must be set"); } const stripeClient = new Stripe(secretKey); // Create a fresh test database const dbName = `paykit_cli_${String(Date.now())}`; - const adminUrl = process.env.TEST_DATABASE_URL ?? "postgresql://localhost:5432/postgres"; + const adminUrl = env.TEST_DATABASE_URL; const adminPool = new Pool({ connectionString: adminUrl }); await adminPool.query(`CREATE DATABASE "${dbName}"`); await adminPool.end(); diff --git a/e2e/env.ts b/e2e/env.ts new file mode 100644 index 00000000..477395cd --- /dev/null +++ b/e2e/env.ts @@ -0,0 +1,25 @@ +import path from "node:path"; + +import { createEnv } from "@t3-oss/env-core"; +import { config } from "dotenv"; +import * as z from "zod"; + +config({ path: path.resolve(import.meta.dirname, "../.env"), quiet: true }); +config({ path: path.resolve(import.meta.dirname, "../.env.local"), override: true, quiet: true }); + +export const env = createEnv({ + server: { + PROVIDER: z.enum(["stripe", "polar"]).default("stripe"), + TEST_DATABASE_URL: z.string().default("postgresql://localhost:5432/postgres"), + + // Stripe + E2E_STRIPE_SK: z.string().optional(), + E2E_STRIPE_WHSEC: z.string().optional(), + + // Polar + E2E_POLAR_ACCESS_TOKEN: z.string().optional(), + E2E_POLAR_WHSEC: z.string().optional(), + }, + runtimeEnv: process.env, + emptyStringAsUndefined: true, +}); diff --git a/e2e/package.json b/e2e/package.json index af2543d5..aa2a95c7 100644 --- a/e2e/package.json +++ b/e2e/package.json @@ -4,6 +4,8 @@ "type": "module", "scripts": { "test": "vitest run --config smoke/vitest.automated.config.ts", + "test:stripe": "PROVIDER=stripe vitest run --config smoke/vitest.automated.config.ts", + "test:polar": "PROVIDER=polar vitest run --config smoke/vitest.automated.config.ts", "test:watch": "vitest --config smoke/vitest.automated.config.ts", "test:manual": "vitest run --config smoke/vitest.manual.config.ts", "test:all": "vitest run --config smoke/vitest.config.ts", @@ -12,13 +14,17 @@ "typecheck": "tsc -p tsconfig.json --noEmit" }, "devDependencies": { + "@paykitjs/polar": "workspace:*", "@paykitjs/stripe": "workspace:*", + "@t3-oss/env-core": "^0.12.0", "@types/pg": "^8.18.0", "dotenv": "^17.3.1", "drizzle-orm": "^0.45.1", "paykitjs": "workspace:*", "pg": "^8.20.0", + "playwright": "^1.52.0", "stripe": "^19.1.0", - "vitest": "^4.0.18" + "vitest": "^4.0.18", + "zod": "^4.0.0" } } diff --git a/e2e/smoke/cancel/cancel-then-upgrade.test.ts b/e2e/smoke/cancel/cancel-then-upgrade.test.ts index 320ae620..4f081d95 100644 --- a/e2e/smoke/cancel/cancel-then-upgrade.test.ts +++ b/e2e/smoke/cancel/cancel-then-upgrade.test.ts @@ -7,6 +7,7 @@ import { expectProduct, expectSingleActivePlanInGroup, expectSingleScheduledPlanInGroup, + subscribeCustomer, type TestPayKit, } from "../setup"; @@ -27,17 +28,9 @@ describe("cancel-then-upgrade: pro → free (scheduled) → ultra (upgrade)", () customerId = customer.customerId; // Setup: subscribe to Pro, then schedule downgrade to Free - await t.paykit.subscribe({ - customerId, - planId: "pro", - successUrl: "https://example.com/success", - }); + await subscribeCustomer({ t, customerId, planId: "pro" }); - await t.paykit.subscribe({ - customerId, - planId: "free", - successUrl: "https://example.com/success", - }); + await subscribeCustomer({ t, customerId, planId: "free" }); }); afterAll(async () => { @@ -67,11 +60,7 @@ describe("cancel-then-upgrade: pro → free (scheduled) → ultra (upgrade)", () }); // Action: upgrade to Ultra - await t.paykit.subscribe({ - customerId, - planId: "ultra", - successUrl: "https://example.com/success", - }); + await subscribeCustomer({ t, customerId, planId: "ultra" }); // Ultra is active await expectProduct({ diff --git a/e2e/smoke/cancel/downgrade-change-target.test.ts b/e2e/smoke/cancel/downgrade-change-target.test.ts index 6e023b83..5f047a10 100644 --- a/e2e/smoke/cancel/downgrade-change-target.test.ts +++ b/e2e/smoke/cancel/downgrade-change-target.test.ts @@ -8,6 +8,7 @@ import { expectProductNotPresent, expectSingleActivePlanInGroup, expectSingleScheduledPlanInGroup, + subscribeCustomer, type TestPayKit, } from "../setup"; @@ -28,24 +29,12 @@ describe("downgrade-change-target: ultra → pro (scheduled) → free (change ta customerId = customer.customerId; // Setup: subscribe Pro → upgrade Ultra - await t.paykit.subscribe({ - customerId, - planId: "pro", - successUrl: "https://example.com/success", - }); + await subscribeCustomer({ t, customerId, planId: "pro" }); - await t.paykit.subscribe({ - customerId, - planId: "ultra", - successUrl: "https://example.com/success", - }); + await subscribeCustomer({ t, customerId, planId: "ultra" }); // Schedule downgrade to Pro - await t.paykit.subscribe({ - customerId, - planId: "pro", - successUrl: "https://example.com/success", - }); + await subscribeCustomer({ t, customerId, planId: "pro" }); }); afterAll(async () => { @@ -75,11 +64,7 @@ describe("downgrade-change-target: ultra → pro (scheduled) → free (change ta }); // Action: change downgrade target to Free instead - await t.paykit.subscribe({ - customerId, - planId: "free", - successUrl: "https://example.com/success", - }); + await subscribeCustomer({ t, customerId, planId: "free" }); // Ultra still canceling await expectProduct({ diff --git a/e2e/smoke/entitlements/check-boolean.test.ts b/e2e/smoke/entitlements/check-boolean.test.ts index 3d6b0f68..9eb3ddd6 100644 --- a/e2e/smoke/entitlements/check-boolean.test.ts +++ b/e2e/smoke/entitlements/check-boolean.test.ts @@ -4,6 +4,7 @@ import { createTestCustomerWithPM, createTestPayKit, dumpStateOnFailure, + subscribeCustomer, type TestPayKit, } from "../setup"; @@ -35,11 +36,7 @@ describe("check-boolean: boolean feature access", () => { expect(freeCheck.allowed).toBe(false); // Subscribe to Pro (includes dashboard) - await t.paykit.subscribe({ - customerId, - planId: "pro", - successUrl: "https://example.com/success", - }); + await subscribeCustomer({ t, customerId, planId: "pro" }); // On Pro — dashboard accessible const proCheck = await t.paykit.check({ customerId, featureId: "dashboard" }); diff --git a/e2e/smoke/entitlements/check-metered.test.ts b/e2e/smoke/entitlements/check-metered.test.ts index 855c2f69..6ce5280a 100644 --- a/e2e/smoke/entitlements/check-metered.test.ts +++ b/e2e/smoke/entitlements/check-metered.test.ts @@ -5,6 +5,7 @@ import { createTestPayKit, dumpStateOnFailure, expectExactMeteredBalance, + subscribeCustomer, type TestPayKit, } from "../setup"; @@ -25,11 +26,7 @@ describe("check-metered: metered feature balance and usage reporting", () => { customerId = customer.customerId; // Subscribe to Pro (500 messages/month) - await t.paykit.subscribe({ - customerId, - planId: "pro", - successUrl: "https://example.com/success", - }); + await subscribeCustomer({ t, customerId, planId: "pro" }); }); afterAll(async () => { diff --git a/e2e/smoke/entitlements/stacked-metered.test.ts b/e2e/smoke/entitlements/stacked-metered.test.ts index 4d810e43..58504160 100644 --- a/e2e/smoke/entitlements/stacked-metered.test.ts +++ b/e2e/smoke/entitlements/stacked-metered.test.ts @@ -5,6 +5,7 @@ import { createTestPayKit, dumpStateOnFailure, expectExactMeteredBalance, + subscribeCustomer, type TestPayKit, } from "../setup"; @@ -25,18 +26,10 @@ describe("stacked-metered: cross-group entitlement aggregation", () => { customerId = customer.customerId; // Pro (base group): 500 messages/month - await t.paykit.subscribe({ - customerId, - planId: "pro", - successUrl: "https://example.com/success", - }); + await subscribeCustomer({ t, customerId, planId: "pro" }); // Extra Messages (addons group): 200 messages/month - await t.paykit.subscribe({ - customerId, - planId: "extra_messages", - successUrl: "https://example.com/success", - }); + await subscribeCustomer({ t, customerId, planId: "extra_messages" }); }); afterAll(async () => { diff --git a/e2e/smoke/harness/index.ts b/e2e/smoke/harness/index.ts new file mode 100644 index 00000000..806313a4 --- /dev/null +++ b/e2e/smoke/harness/index.ts @@ -0,0 +1,21 @@ +import { env } from "../../env"; +import { createPolarHarness } from "./polar"; +import { createStripeHarness } from "./stripe"; +import type { ProviderHarness } from "./types"; + +export type { ProviderCapabilities, ProviderHarness } from "./types"; + +export function loadHarness(): ProviderHarness { + const provider = env.PROVIDER; + + switch (provider) { + case "stripe": + return createStripeHarness(); + case "polar": + return createPolarHarness(); + default: { + const _exhaustive: never = provider; + throw new Error(`Unknown provider: ${String(_exhaustive)}`); + } + } +} diff --git a/e2e/smoke/harness/polar.ts b/e2e/smoke/harness/polar.ts new file mode 100644 index 00000000..ceb3f483 --- /dev/null +++ b/e2e/smoke/harness/polar.ts @@ -0,0 +1,77 @@ +import { polar } from "@paykitjs/polar"; +import { chromium } from "playwright"; + +import { env } from "../../env"; +import type { ProviderHarness } from "./types"; + +export function createPolarHarness(): ProviderHarness { + const accessToken = env.E2E_POLAR_ACCESS_TOKEN; + const webhookSecret = env.E2E_POLAR_WHSEC; + if (!accessToken || !webhookSecret) { + throw new Error("E2E_POLAR_ACCESS_TOKEN and E2E_POLAR_WHSEC must be set"); + } + + return { + id: "polar", + capabilities: { + testClocks: false, + directSubscription: false, + }, + + createProviderConfig() { + return polar({ accessToken, webhookSecret, server: "sandbox" }); + }, + + async setupCustomerForDirectSubscription(_providerCustomerId: string) { + // Polar doesn't support direct subscription — always goes through checkout. + // This is a no-op; tests will get a paymentUrl and call completeCheckout. + }, + + async completeCheckout(url: string) { + const browser = await chromium.launch({ headless: true }); + const page = await browser.newPage(); + + try { + await page.goto(url, { waitUntil: "networkidle" }); + + // Polar sandbox checkout — fill test card details + await page.fill( + '[data-testid="card-number"], input[name="cardNumber"], input[placeholder*="card number" i]', + "4242424242424242", + ); + await page.fill( + '[data-testid="card-expiry"], input[name="cardExpiry"], input[placeholder*="MM" i]', + "12/30", + ); + await page.fill( + '[data-testid="card-cvc"], input[name="cardCvc"], input[placeholder*="CVC" i]', + "123", + ); + + // Submit payment + const submitButton = page.locator( + 'button[type="submit"], button:has-text("Pay"), button:has-text("Subscribe")', + ); + await submitButton.click(); + + // Wait for redirect to success URL or confirmation + await page.waitForURL("**/success**", { timeout: 30_000 }).catch(() => { + // Some checkouts show a confirmation page rather than redirecting + }); + } finally { + await browser.close(); + } + }, + + async cleanup(_ctx) { + // Polar sandbox has no test clocks to clean up. + // Subscriptions in sandbox are ephemeral. + }, + + validateEnv() { + if (!env.E2E_POLAR_ACCESS_TOKEN || !env.E2E_POLAR_WHSEC) { + throw new Error("E2E_POLAR_ACCESS_TOKEN and E2E_POLAR_WHSEC must be set"); + } + }, + }; +} diff --git a/e2e/smoke/harness/stripe.ts b/e2e/smoke/harness/stripe.ts new file mode 100644 index 00000000..0e830e23 --- /dev/null +++ b/e2e/smoke/harness/stripe.ts @@ -0,0 +1,93 @@ +import { stripe } from "@paykitjs/stripe"; +import { default as Stripe } from "stripe"; + +import type { PayKitDatabase } from "../../../packages/paykit/src/database/index"; +import { syncPaymentMethodByProviderCustomer } from "../../../packages/paykit/src/payment-method/payment-method.service"; +import { env } from "../../env"; +import type { ProviderHarness } from "./types"; + +export function createStripeHarness(): ProviderHarness { + const secretKey = env.E2E_STRIPE_SK; + const webhookSecret = env.E2E_STRIPE_WHSEC; + if (!secretKey || !webhookSecret) { + throw new Error("E2E_STRIPE_SK and E2E_STRIPE_WHSEC must be set"); + } + + const stripeClient = new Stripe(secretKey); + + return { + id: "stripe", + capabilities: { + testClocks: true, + directSubscription: true, + }, + + createProviderConfig() { + return stripe({ secretKey, webhookSecret }); + }, + + async setupCustomerForDirectSubscription(providerCustomerId: string) { + const pm = await stripeClient.paymentMethods.attach("pm_card_visa", { + customer: providerCustomerId, + }); + await stripeClient.customers.update(providerCustomerId, { + invoice_settings: { default_payment_method: pm.id }, + }); + }, + + async completeCheckout(_url: string) { + throw new Error("Stripe direct-subscription tests should not need checkout completion"); + }, + + async cleanup(ctx) { + // Delete test clocks for all customers + for (const providerCustomerId of ctx.providerCustomerIds) { + try { + const customer = await stripeClient.customers.retrieve(providerCustomerId); + if ("deleted" in customer && customer.deleted) continue; + const testClockId = (customer as Stripe.Customer).test_clock; + if (testClockId && typeof testClockId === "string") { + await stripeClient.testHelpers.testClocks.del(testClockId).catch(() => {}); + } + } catch { + // Customer may already be deleted + } + } + }, + + validateEnv() { + if (!env.E2E_STRIPE_SK || !env.E2E_STRIPE_WHSEC) { + throw new Error("E2E_STRIPE_SK and E2E_STRIPE_WHSEC must be set"); + } + }, + }; +} + +/** Sync a Stripe payment method into the PayKit database. */ +export async function syncStripePaymentMethod(input: { + database: PayKitDatabase; + providerCustomerId: string; + providerId: string; + stripeClient: Stripe; +}): Promise { + const pm = await input.stripeClient.paymentMethods.list({ + customer: input.providerCustomerId, + type: "card", + limit: 1, + }); + const method = pm.data[0]; + if (!method) return; + + await syncPaymentMethodByProviderCustomer(input.database, { + paymentMethod: { + providerMethodId: method.id, + type: method.type, + last4: method.card?.last4, + expiryMonth: method.card?.exp_month, + expiryYear: method.card?.exp_year, + isDefault: true, + }, + providerCustomerId: input.providerCustomerId, + providerId: input.providerId, + }); +} diff --git a/e2e/smoke/harness/types.ts b/e2e/smoke/harness/types.ts new file mode 100644 index 00000000..68a94814 --- /dev/null +++ b/e2e/smoke/harness/types.ts @@ -0,0 +1,27 @@ +import type { PayKitProviderConfig } from "paykitjs"; + +export interface ProviderCapabilities { + testClocks: boolean; + directSubscription: boolean; +} + +export interface ProviderHarness { + id: string; + capabilities: ProviderCapabilities; + + createProviderConfig(): PayKitProviderConfig; + + /** + * Make the customer ready to subscribe without checkout (e.g., attach PM for Stripe). + * For providers that only support checkout, this is a no-op. + */ + setupCustomerForDirectSubscription(providerCustomerId: string): Promise; + + /** Complete a hosted checkout given the URL (e.g., Playwright automation). */ + completeCheckout(url: string): Promise; + + /** Provider-specific cleanup (e.g., delete test clocks). */ + cleanup(ctx: { providerCustomerIds: string[] }): Promise; + + validateEnv(): void; +} diff --git a/e2e/smoke/setup.ts b/e2e/smoke/setup.ts index d44f0f8d..7c403411 100644 --- a/e2e/smoke/setup.ts +++ b/e2e/smoke/setup.ts @@ -1,8 +1,5 @@ import { createServer, type IncomingMessage, type Server, type ServerResponse } from "node:http"; -import path from "node:path"; -import { stripe } from "@paykitjs/stripe"; -import { config } from "dotenv"; import { and, count, desc, eq, gt, inArray, isNull, or, sql } from "drizzle-orm"; import { createPayKit, feature, plan } from "paykitjs"; import { Pool } from "pg"; @@ -20,12 +17,15 @@ import { } from "../../packages/paykit/src/database/schema"; import { syncPaymentMethodByProviderCustomer } from "../../packages/paykit/src/payment-method/payment-method.service"; import { syncProducts } from "../../packages/paykit/src/product/product-sync.service"; - -config({ path: path.resolve(import.meta.dirname, "../../.env") }); -config({ path: path.resolve(import.meta.dirname, "../../.env.local"), override: true }); +import { env } from "../env"; +import { loadHarness } from "./harness/index"; +import type { ProviderHarness } from "./harness/types"; const WEBHOOK_PORT = 4567; +// Provider harness — loaded once at module init based on PROVIDER env var +export const harness: ProviderHarness = loadHarness(); + const messagesFeature = feature({ id: "messages", type: "metered" }); const dashboardFeature = feature({ id: "dashboard", type: "boolean" }); const adminFeature = feature({ id: "admin", type: "boolean" }); @@ -80,7 +80,7 @@ type SmokePayKit = ReturnType< typeof createPayKit<{ database: Pool; plans: typeof smokePlans; - provider: ReturnType; + provider: ReturnType; testing: { enabled: true }; }> >; @@ -89,7 +89,7 @@ export interface TestPayKit { paykit: SmokePayKit; database: PayKitDatabase; ctx: PayKitContext; - stripeClient: Stripe; + harness: ProviderHarness; dbPath: string; server: Server; webhookRequests: CapturedWebhookRequest[]; @@ -106,137 +106,123 @@ export interface CapturedWebhookRequest { const activeSubscriptionStatuses = ["active", "trialing", "past_due"] as const; const presentSubscriptionStatuses = [...activeSubscriptionStatuses, "scheduled"] as const; -// createTestPayKit - export async function createTestPayKit(): Promise { - const secretKey = process.env.STRIPE_SECRET_KEY; - const webhookSecret = process.env.STRIPE_WEBHOOK_SECRET; - if (!secretKey || !webhookSecret) { - throw new Error("STRIPE_SECRET_KEY and STRIPE_WEBHOOK_SECRET must be set"); - } - - const stripeClient = new Stripe(secretKey); + harness.validateEnv(); // 1. Create a fresh test database const dbName = `paykit_smoke_${String(Date.now())}`; const adminPool = new Pool({ - connectionString: process.env.TEST_DATABASE_URL ?? "postgresql://localhost:5432/postgres", + connectionString: env.TEST_DATABASE_URL, }); await adminPool.query(`CREATE DATABASE "${dbName}"`); await adminPool.end(); - const dbUrl = (process.env.TEST_DATABASE_URL ?? "postgresql://localhost:5432/postgres").replace( - /\/[^/]*$/, - `/${dbName}`, - ); + const dbUrl = env.TEST_DATABASE_URL.replace(/\/[^/]*$/, `/${dbName}`); const pool = new Pool({ connectionString: dbUrl }); // 2. Run migrations await migrateDatabase(pool); - // 3. Create PayKit instance with real Stripe - const stripeProvider = stripe({ secretKey, webhookSecret }); + // 3. Create PayKit instance with the active provider + const providerConfig = harness.createProviderConfig(); const paykit = createPayKit({ database: pool, plans: smokePlans, - provider: stripeProvider, + provider: providerConfig, testing: { enabled: true }, }); const ctx = await paykit.$context; - // Override createSubscription to use allow_incomplete. The default - // payment_behavior: "default_incomplete" requires client-side payment - // confirmation which isn't possible in automated tests. - (ctx.provider as unknown as Record).createSubscription = async (data: { - providerCustomerId: string; - providerPriceId: string; - }) => { - const sub = await stripeClient.subscriptions.create({ - customer: data.providerCustomerId, - items: [{ price: data.providerPriceId }], - payment_behavior: "allow_incomplete", - expand: ["latest_invoice"], - }); + // Stripe-specific: Override createSubscription to use allow_incomplete. + // This allows direct subscription without client-side payment confirmation. + if (harness.id === "stripe") { + const secretKey = env.E2E_STRIPE_SK!; + const stripeClient = new Stripe(secretKey); + + (ctx.provider as unknown as Record).createSubscription = async (data: { + providerCustomerId: string; + providerProduct: Record; + }) => { + const sub = await stripeClient.subscriptions.create({ + customer: data.providerCustomerId, + items: [{ price: data.providerProduct.priceId }], + payment_behavior: "allow_incomplete", + expand: ["latest_invoice"], + }); - const firstItem = sub.items.data[0]; - const periodStart = firstItem?.current_period_start ?? null; - const periodEnd = firstItem?.current_period_end ?? null; - const latestInvoice = sub.latest_invoice; - const invoice = - latestInvoice && typeof latestInvoice !== "string" - ? { - currency: latestInvoice.currency, - hostedUrl: latestInvoice.hosted_invoice_url ?? null, - periodEndAt: latestInvoice.period_end - ? new Date(latestInvoice.period_end * 1000) - : null, - periodStartAt: latestInvoice.period_start - ? new Date(latestInvoice.period_start * 1000) - : null, - providerInvoiceId: latestInvoice.id, - status: latestInvoice.status, - totalAmount: latestInvoice.total, - } - : null; - - return { - invoice, - paymentUrl: null, - subscription: { - cancelAtPeriodEnd: sub.cancel_at_period_end, - canceledAt: sub.canceled_at != null ? new Date(sub.canceled_at * 1000) : null, - currentPeriodEndAt: periodEnd != null ? new Date(periodEnd * 1000) : null, - currentPeriodStartAt: periodStart != null ? new Date(periodStart * 1000) : null, - endedAt: sub.ended_at != null ? new Date(sub.ended_at * 1000) : null, - providerSubscriptionId: sub.id, - providerSubscriptionScheduleId: null, - status: sub.status, - }, + const firstItem = sub.items.data[0]; + const periodStart = firstItem?.current_period_start ?? null; + const periodEnd = firstItem?.current_period_end ?? null; + const latestInvoice = sub.latest_invoice; + const inv = + latestInvoice && typeof latestInvoice !== "string" + ? { + currency: latestInvoice.currency, + hostedUrl: latestInvoice.hosted_invoice_url ?? null, + periodEndAt: latestInvoice.period_end + ? new Date(latestInvoice.period_end * 1000) + : null, + periodStartAt: latestInvoice.period_start + ? new Date(latestInvoice.period_start * 1000) + : null, + providerInvoiceId: latestInvoice.id, + status: latestInvoice.status, + totalAmount: latestInvoice.total, + } + : null; + + return { + invoice: inv, + paymentUrl: null, + subscription: { + cancelAtPeriodEnd: sub.cancel_at_period_end, + canceledAt: sub.canceled_at != null ? new Date(sub.canceled_at * 1000) : null, + currentPeriodEndAt: periodEnd != null ? new Date(periodEnd * 1000) : null, + currentPeriodStartAt: periodStart != null ? new Date(periodStart * 1000) : null, + endedAt: sub.ended_at != null ? new Date(sub.ended_at * 1000) : null, + providerSubscriptionId: sub.id, + providerSubscriptionScheduleId: null, + status: sub.status, + }, + }; }; - }; + } // 4. Start webhook server BEFORE syncing products — product sync - // creates Stripe products which fires webhooks immediately + // creates provider products which fires webhooks immediately const webhookRequests: CapturedWebhookRequest[] = []; - const server = startWebhookServer(paykit, webhookRequests); + const server = await startWebhookServer(paykit, webhookRequests); - // 5. Sync products to Stripe + // 5. Sync products to provider await syncProducts(ctx); return { paykit, database: ctx.database, ctx, - stripeClient, + harness, dbPath: dbUrl, server, webhookRequests, cleanup: async () => { const customerRows = await ctx.database.query.customer.findMany(); - const testClockIds = new Set(); + const idSet = new Set(); for (const row of customerRows) { - const providerMap = (row.provider ?? {}) as Record< - string, - { id: string; testClockId?: string } - >; - const testClockId = providerMap.stripe?.testClockId; - if (testClockId) { - testClockIds.add(testClockId); - } + const providerMap = (row.provider ?? {}) as Record; + const entry = providerMap[harness.id]; + if (entry?.id) idSet.add(entry.id); } - for (const testClockId of testClockIds) { - await stripeClient.testHelpers.testClocks.del(testClockId).catch(() => {}); - } + await harness.cleanup({ providerCustomerIds: [...idSet] }); // Wait for cleanup webhooks to arrive and be processed await new Promise((resolve) => setTimeout(resolve, 10_000)); - server.close(); + await new Promise((resolve) => server.close(() => resolve())); await pool.end(); // Drop the test database const cleanupPool = new Pool({ - connectionString: process.env.TEST_DATABASE_URL ?? "postgresql://localhost:5432/postgres", + connectionString: env.TEST_DATABASE_URL, }); await cleanupPool.query(`DROP DATABASE IF EXISTS "${dbName}"`).catch(() => {}); await cleanupPool.end(); @@ -245,33 +231,43 @@ export async function createTestPayKit(): Promise { } /** - * Creates a PayKit customer. In testing mode this also provisions a Stripe - * customer with a dedicated test clock. No payment method attached — first - * paid subscribe will go through checkout. + * Creates a PayKit customer. In testing mode this also provisions a provider + * customer (with a test clock for Stripe). No payment method attached. */ export async function createTestCustomer(input: { t: TestPayKit; customer: { id: string; email: string; name: string }; }): Promise<{ customerId: string; providerCustomerId: string }> { - await input.t.paykit.upsertCustomer(input.customer); + const suffix = `${Date.now()}_${Math.random().toString(36).slice(2, 8)}`; + const uniqueId = `${input.customer.id}_${suffix}`; + const uniqueEmail = input.customer.email.replace("@", `+${suffix}@`); + + await input.t.paykit.upsertCustomer({ + ...input.customer, + id: uniqueId, + email: uniqueEmail, + upsertProviderCustomer: true, + }); - // Now the provider customer ID is stored in the customer's provider JSONB column const row = await input.t.database.query.customer.findFirst({ - where: eq(customer.id, input.customer.id), + where: eq(customer.id, uniqueId), }); const providerMap = (row?.provider ?? {}) as Record; - const providerCustomerId = providerMap.stripe?.id; + const providerCustomerId = providerMap[input.t.harness.id]?.id; if (!providerCustomerId) { - throw new Error(`No Stripe provider customer ID found for customer "${input.customer.id}"`); + throw new Error( + `No ${input.t.harness.id} provider customer ID found for customer "${uniqueId}"`, + ); } - return { customerId: input.customer.id, providerCustomerId }; + return { customerId: uniqueId, providerCustomerId }; } /** - * Creates a PayKit customer with a pre-attached payment method. - * Subscribe calls will go through the direct path (no checkout). + * Creates a PayKit customer ready for direct subscription (no checkout). + * For Stripe: attaches a test payment method. + * For providers without direct subscription support, this is equivalent to createTestCustomer. */ export async function createTestCustomerWithPM(input: { t: TestPayKit; @@ -279,31 +275,69 @@ export async function createTestCustomerWithPM(input: { }): Promise<{ customerId: string; providerCustomerId: string }> { const { customerId, providerCustomerId } = await createTestCustomer(input); - // Attach test payment method to Stripe customer - const pm = await input.t.stripeClient.paymentMethods.attach("pm_card_visa", { - customer: providerCustomerId, - }); - await input.t.stripeClient.customers.update(providerCustomerId, { - invoice_settings: { default_payment_method: pm.id }, - }); + await input.t.harness.setupCustomerForDirectSubscription(providerCustomerId); - // Sync payment method into PayKit DB - await syncPaymentMethodByProviderCustomer(input.t.ctx.database, { - paymentMethod: { - providerMethodId: pm.id, - type: pm.type, - last4: pm.card?.last4, - expiryMonth: pm.card?.exp_month, - expiryYear: pm.card?.exp_year, - isDefault: true, - }, - providerCustomerId, - providerId: input.t.ctx.provider.id, - }); + // For Stripe, sync the payment method into PayKit DB + if (input.t.harness.id === "stripe") { + const secretKey = env.E2E_STRIPE_SK!; + const stripeClient = new Stripe(secretKey); + const pm = await stripeClient.paymentMethods.list({ + customer: providerCustomerId, + type: "card", + limit: 1, + }); + const method = pm.data[0]; + if (method) { + await syncPaymentMethodByProviderCustomer(input.t.ctx.database, { + paymentMethod: { + providerMethodId: method.id, + type: method.type, + last4: method.card?.last4, + expiryMonth: method.card?.exp_month, + expiryYear: method.card?.exp_year, + isDefault: true, + }, + providerCustomerId, + providerId: input.t.ctx.provider.id, + }); + } + } return { customerId, providerCustomerId }; } +/** + * Subscribe a customer to a plan, handling checkout flow if the provider requires it. + * For providers with direct subscription (Stripe with PM): returns immediately. + * For providers requiring checkout (Polar): completes checkout via Playwright and waits for webhook. + */ +export async function subscribeCustomer(input: { + t: TestPayKit; + customerId: string; + planId: Parameters[0]["planId"]; +}): Promise { + const beforeSubscribe = new Date(); + + const result = await input.t.paykit.subscribe({ + customerId: input.customerId, + planId: input.planId, + successUrl: "https://example.com/success", + }); + + if (result.paymentUrl) { + // Checkout-based flow — automate checkout completion + await input.t.harness.completeCheckout(result.paymentUrl); + + // Wait for the subscription to become active via webhook + await waitForWebhook({ + database: input.t.database, + eventType: "subscription.updated", + after: beforeSubscribe, + timeout: 60_000, + }); + } +} + export async function expectProduct(input: { database: PayKitDatabase; customerId: string; @@ -570,10 +604,10 @@ export async function expectExactMeteredBalance(input: { } } -function startWebhookServer( +async function startWebhookServer( paykit: Pick, webhookRequests: CapturedWebhookRequest[], -): Server { +): Promise { const server = createServer(async (req: IncomingMessage, res: ServerResponse) => { const chunks: Buffer[] = []; for await (const chunk of req) { @@ -610,7 +644,10 @@ function startWebhookServer( } }); - server.listen(WEBHOOK_PORT); + await new Promise((resolve, reject) => { + server.once("error", reject); + server.listen(WEBHOOK_PORT, () => resolve()); + }); return server; } diff --git a/e2e/smoke/subscribe/cancel-end-of-cycle.test.ts b/e2e/smoke/subscribe/cancel-end-of-cycle.test.ts index 6b964746..3745a781 100644 --- a/e2e/smoke/subscribe/cancel-end-of-cycle.test.ts +++ b/e2e/smoke/subscribe/cancel-end-of-cycle.test.ts @@ -11,127 +11,124 @@ import { expectNoScheduledPlanInGroup, expectProduct, expectSingleActivePlanInGroup, + harness, + subscribeCustomer, type TestPayKit, waitForWebhook, } from "../setup"; -describe("cancel-end-of-cycle: pro → free + clock advance", () => { - let t: TestPayKit; - let customerId: string; +describe.skipIf(!harness.capabilities.testClocks)( + "cancel-end-of-cycle: pro → free + clock advance", + () => { + let t: TestPayKit; + let customerId: string; - beforeAll(async () => { - t = await createTestPayKit(); - const customer = await createTestCustomerWithPM({ - t, - customer: { - id: "test_cancel_eoc", - email: "cancel-eoc@test.com", - name: "Cancel EOC Test", - }, - }); - customerId = customer.customerId; + beforeAll(async () => { + t = await createTestPayKit(); + const customer = await createTestCustomerWithPM({ + t, + customer: { + id: "test_cancel_eoc", + email: "cancel-eoc@test.com", + name: "Cancel EOC Test", + }, + }); + customerId = customer.customerId; - // Setup: subscribe to Pro, then schedule downgrade to Free - await t.paykit.subscribe({ - customerId, - planId: "pro", - successUrl: "https://example.com/success", - }); + // Setup: subscribe to Pro, then schedule downgrade to Free + await subscribeCustomer({ t, customerId, planId: "pro" }); - await t.paykit.subscribe({ - customerId, - planId: "free", - successUrl: "https://example.com/success", + await subscribeCustomer({ t, customerId, planId: "free" }); }); - }); - afterAll(async () => { - await t?.cleanup(); - }); + afterAll(async () => { + await t?.cleanup(); + }); - it("advancing past period end activates the free plan", async () => { - try { - // Get period end to advance past - const subRows = await t.database - .select({ currentPeriodEndAt: subscription.currentPeriodEndAt }) - .from(subscription) - .where(eq(subscription.customerId, customerId)) - .orderBy(desc(subscription.updatedAt)) - .limit(1); - const periodEnd = new Date(subRows[0]!.currentPeriodEndAt as unknown as string); + it("advancing past period end activates the free plan", async () => { + try { + // Get period end to advance past + const subRows = await t.database + .select({ currentPeriodEndAt: subscription.currentPeriodEndAt }) + .from(subscription) + .where(eq(subscription.customerId, customerId)) + .orderBy(desc(subscription.updatedAt)) + .limit(1); + const periodEnd = new Date(subRows[0]!.currentPeriodEndAt as unknown as string); - // Advance clock 1 day past period end - const advanceTo = new Date(periodEnd.getTime() + 86_400_000); - const beforeAdvance = new Date(); - await advanceTestClock({ - t, - customerId, - frozenTime: advanceTo, - }); - await waitForWebhook({ - after: beforeAdvance, - database: t.database, - eventType: "subscription.deleted", - timeout: 30_000, - }); + // Advance clock 1 day past period end + const advanceTo = new Date(periodEnd.getTime() + 86_400_000); + const beforeAdvance = new Date(); + await advanceTestClock({ + t, + customerId, + frozenTime: advanceTo, + }); + await waitForWebhook({ + after: beforeAdvance, + database: t.database, + eventType: "subscription.deleted", + timeout: 30_000, + }); - // Poll until Free is active after the forwarded deletion event is processed - for (let i = 0; i < 60; i++) { - const rows = await t.database - .select({ status: subscription.status }) - .from(subscription) - .innerJoin(product, eq(product.internalId, subscription.productInternalId)) - .where( - and( - eq(subscription.customerId, customerId), - eq(product.id, "free"), - eq(subscription.status, "active"), - ), - ); - if (rows.length > 0) break; - if (i === 59) throw new Error("Free plan never activated after clock advance"); - await new Promise((resolve) => setTimeout(resolve, 2000)); - } + // Poll until Free is active after the forwarded deletion event is processed + for (let i = 0; i < 60; i++) { + const rows = await t.database + .select({ status: subscription.status }) + .from(subscription) + .innerJoin(product, eq(product.internalId, subscription.productInternalId)) + .where( + and( + eq(subscription.customerId, customerId), + eq(product.id, "free"), + eq(subscription.status, "active"), + ), + ); + if (rows.length > 0) break; + if (i === 59) throw new Error("Free plan never activated after clock advance"); + await new Promise((resolve) => setTimeout(resolve, 2000)); + } - // Pro is canceled/ended - await expectProduct({ - database: t.database, - customerId, - planId: "pro", - expected: { canceled: true, status: "canceled" }, - }); + // Pro is canceled/ended + await expectProduct({ + database: t.database, + customerId, + planId: "pro", + expected: { canceled: true, status: "canceled" }, + }); - // Free is active with no period end (no billing cycle) - await expectProduct({ - database: t.database, - customerId, - planId: "free", - expected: { - status: "active", - hasPeriodEnd: false, - }, - }); - await expectSingleActivePlanInGroup({ - database: t.database, - customerId, - group: "base", - planId: "free", - }); - await expectNoScheduledPlanInGroup({ - database: t.database, - customerId, - group: "base", - }); - await expectExactMeteredBalance({ - paykit: t.paykit, - customerId, - featureId: "messages", - limit: 100, - remaining: 100, - }); - } catch (error) { - await dumpStateOnFailure(t.database, t.dbPath); - throw error; - } - }); -}); + // Free is active with no period end (no billing cycle) + await expectProduct({ + database: t.database, + customerId, + planId: "free", + expected: { + status: "active", + hasPeriodEnd: false, + }, + }); + await expectSingleActivePlanInGroup({ + database: t.database, + customerId, + group: "base", + planId: "free", + }); + await expectNoScheduledPlanInGroup({ + database: t.database, + customerId, + group: "base", + }); + await expectExactMeteredBalance({ + paykit: t.paykit, + customerId, + featureId: "messages", + limit: 100, + remaining: 100, + }); + } catch (error) { + await dumpStateOnFailure(t.database, t.dbPath); + throw error; + } + }); + }, +); diff --git a/e2e/smoke/subscribe/cancel-resume.test.ts b/e2e/smoke/subscribe/cancel-resume.test.ts index 3fa907b5..63b6c92a 100644 --- a/e2e/smoke/subscribe/cancel-resume.test.ts +++ b/e2e/smoke/subscribe/cancel-resume.test.ts @@ -9,6 +9,7 @@ import { expectSingleActivePlanInGroup, expectSingleScheduledPlanInGroup, expectSubscription, + subscribeCustomer, type TestPayKit, } from "../setup"; @@ -29,17 +30,9 @@ describe("cancel-resume: pro → free → pro (resume)", () => { customerId = customer.customerId; // Setup: subscribe to Pro, then schedule downgrade to Free - await t.paykit.subscribe({ - customerId, - planId: "pro", - successUrl: "https://example.com/success", - }); + await subscribeCustomer({ t, customerId, planId: "pro" }); - await t.paykit.subscribe({ - customerId, - planId: "free", - successUrl: "https://example.com/success", - }); + await subscribeCustomer({ t, customerId, planId: "free" }); }); afterAll(async () => { @@ -72,11 +65,7 @@ describe("cancel-resume: pro → free → pro (resume)", () => { }); // Action: resume Pro - await t.paykit.subscribe({ - customerId, - planId: "pro", - successUrl: "https://example.com/success", - }); + await subscribeCustomer({ t, customerId, planId: "pro" }); // Pro is active and no longer canceled await expectProduct({ diff --git a/e2e/smoke/subscribe/downgrade-scheduled.test.ts b/e2e/smoke/subscribe/downgrade-scheduled.test.ts index 3d25f803..a1c12b2f 100644 --- a/e2e/smoke/subscribe/downgrade-scheduled.test.ts +++ b/e2e/smoke/subscribe/downgrade-scheduled.test.ts @@ -7,6 +7,7 @@ import { expectProduct, expectSingleActivePlanInGroup, expectSingleScheduledPlanInGroup, + subscribeCustomer, type TestPayKit, } from "../setup"; @@ -27,17 +28,9 @@ describe("downgrade-scheduled: ultra → pro", () => { customerId = customer.customerId; // Setup: subscribe to Pro then upgrade to Ultra - await t.paykit.subscribe({ - customerId, - planId: "pro", - successUrl: "https://example.com/success", - }); + await subscribeCustomer({ t, customerId, planId: "pro" }); - await t.paykit.subscribe({ - customerId, - planId: "ultra", - successUrl: "https://example.com/success", - }); + await subscribeCustomer({ t, customerId, planId: "ultra" }); }); afterAll(async () => { @@ -46,11 +39,7 @@ describe("downgrade-scheduled: ultra → pro", () => { it("downgrading to a lower tier schedules the change at period end", async () => { try { - await t.paykit.subscribe({ - customerId, - planId: "pro", - successUrl: "https://example.com/success", - }); + await subscribeCustomer({ t, customerId, planId: "pro" }); // Ultra is still active but marked as canceled await expectProduct({ diff --git a/e2e/smoke/subscribe/downgrade-to-free.test.ts b/e2e/smoke/subscribe/downgrade-to-free.test.ts index 1fae9353..17a9faf1 100644 --- a/e2e/smoke/subscribe/downgrade-to-free.test.ts +++ b/e2e/smoke/subscribe/downgrade-to-free.test.ts @@ -8,6 +8,7 @@ import { expectProduct, expectSingleActivePlanInGroup, expectSingleScheduledPlanInGroup, + subscribeCustomer, type TestPayKit, } from "../setup"; @@ -28,11 +29,7 @@ describe("downgrade-to-free: pro → free", () => { customerId = customer.customerId; // Setup: subscribe to Pro - await t.paykit.subscribe({ - customerId, - planId: "pro", - successUrl: "https://example.com/success", - }); + await subscribeCustomer({ t, customerId, planId: "pro" }); }); afterAll(async () => { @@ -41,11 +38,7 @@ describe("downgrade-to-free: pro → free", () => { it("downgrading to free schedules cancellation at period end", async () => { try { - await t.paykit.subscribe({ - customerId, - planId: "free", - successUrl: "https://example.com/success", - }); + await subscribeCustomer({ t, customerId, planId: "free" }); // Pro is still active but canceled await expectProduct({ diff --git a/e2e/smoke/subscribe/renewal.test.ts b/e2e/smoke/subscribe/renewal.test.ts index 83b55c4c..adb33a62 100644 --- a/e2e/smoke/subscribe/renewal.test.ts +++ b/e2e/smoke/subscribe/renewal.test.ts @@ -10,125 +10,126 @@ import { expectExactMeteredBalance, expectProduct, expectSingleActivePlanInGroup, + harness, + subscribeCustomer, type TestPayKit, waitForWebhook, } from "../setup"; -describe("renewal: pro subscription renews after 1 month", () => { - let t: TestPayKit; - let customerId: string; +describe.skipIf(!harness.capabilities.testClocks)( + "renewal: pro subscription renews after 1 month", + () => { + let t: TestPayKit; + let customerId: string; - beforeAll(async () => { - t = await createTestPayKit(); - const customer = await createTestCustomerWithPM({ - t, - customer: { - id: "test_renewal", - email: "renewal@test.com", - name: "Renewal Test", - }, - }); - customerId = customer.customerId; + beforeAll(async () => { + t = await createTestPayKit(); + const customer = await createTestCustomerWithPM({ + t, + customer: { + id: "test_renewal", + email: "renewal@test.com", + name: "Renewal Test", + }, + }); + customerId = customer.customerId; - // Setup: subscribe to Pro - await t.paykit.subscribe({ - customerId, - planId: "pro", - successUrl: "https://example.com/success", + // Setup: subscribe to Pro + await subscribeCustomer({ t, customerId, planId: "pro" }); }); - }); - afterAll(async () => { - await t?.cleanup(); - }); - - it("advancing clock 1 month rolls period dates forward and resets usage", async () => { - try { - const usage = await t.paykit.report({ - customerId, - featureId: "messages", - amount: 37, - }); - expect(usage.success).toBe(true); - await expectExactMeteredBalance({ - paykit: t.paykit, - customerId, - featureId: "messages", - limit: 500, - remaining: 463, - }); + afterAll(async () => { + await t?.cleanup(); + }); - // Record current period end - const subRows = await t.database - .select({ currentPeriodEndAt: subscription.currentPeriodEndAt }) - .from(subscription) - .where(eq(subscription.customerId, customerId)) - .orderBy(desc(subscription.updatedAt)) - .limit(1); - const periodEnd = new Date(subRows[0]!.currentPeriodEndAt as unknown as string); + it("advancing clock 1 month rolls period dates forward and resets usage", async () => { + try { + const usage = await t.paykit.report({ + customerId, + featureId: "messages", + amount: 37, + }); + expect(usage.success).toBe(true); + await expectExactMeteredBalance({ + paykit: t.paykit, + customerId, + featureId: "messages", + limit: 500, + remaining: 463, + }); - // Advance clock 1 day past period end - const advanceTo = new Date(periodEnd.getTime() + 86_400_000); - const beforeAdvance = new Date(); - await advanceTestClock({ - t, - customerId, - frozenTime: advanceTo, - }); - await waitForWebhook({ - after: beforeAdvance, - database: t.database, - eventType: "subscription.updated", - timeout: 30_000, - }); - - // Poll until period dates change after the forwarded renewal event is processed - let newPeriodEnd = periodEnd; - for (let i = 0; i < 60; i++) { - const rows = await t.database + // Record current period end + const subRows = await t.database .select({ currentPeriodEndAt: subscription.currentPeriodEndAt }) .from(subscription) - .where(and(eq(subscription.customerId, customerId), eq(subscription.status, "active"))) + .where(eq(subscription.customerId, customerId)) .orderBy(desc(subscription.updatedAt)) .limit(1); - const row = rows[0]; - if (row?.currentPeriodEndAt) { - const end = new Date(row.currentPeriodEndAt as unknown as string); - if (end.getTime() > periodEnd.getTime()) { - newPeriodEnd = end; - break; + const periodEnd = new Date(subRows[0]!.currentPeriodEndAt as unknown as string); + + // Advance clock 1 day past period end + const advanceTo = new Date(periodEnd.getTime() + 86_400_000); + const beforeAdvance = new Date(); + await advanceTestClock({ + t, + customerId, + frozenTime: advanceTo, + }); + await waitForWebhook({ + after: beforeAdvance, + database: t.database, + eventType: "subscription.updated", + timeout: 30_000, + }); + + // Poll until period dates change after the forwarded renewal event is processed + let newPeriodEnd = periodEnd; + for (let i = 0; i < 60; i++) { + const rows = await t.database + .select({ currentPeriodEndAt: subscription.currentPeriodEndAt }) + .from(subscription) + .where(and(eq(subscription.customerId, customerId), eq(subscription.status, "active"))) + .orderBy(desc(subscription.updatedAt)) + .limit(1); + const row = rows[0]; + if (row?.currentPeriodEndAt) { + const end = new Date(row.currentPeriodEndAt as unknown as string); + if (end.getTime() > periodEnd.getTime()) { + newPeriodEnd = end; + break; + } } + if (i === 59) throw new Error("Period dates never rolled forward after clock advance"); + await new Promise((resolve) => setTimeout(resolve, 2000)); } - if (i === 59) throw new Error("Period dates never rolled forward after clock advance"); - await new Promise((resolve) => setTimeout(resolve, 2000)); - } - // Period end moved forward - expect(newPeriodEnd.getTime()).toBeGreaterThan(periodEnd.getTime()); + // Period end moved forward + expect(newPeriodEnd.getTime()).toBeGreaterThan(periodEnd.getTime()); - // Pro is still active - await expectProduct({ - database: t.database, - customerId, - planId: "pro", - expected: { status: "active" }, - }); - await expectSingleActivePlanInGroup({ - database: t.database, - customerId, - group: "base", - planId: "pro", - }); - await expectExactMeteredBalance({ - paykit: t.paykit, - customerId, - featureId: "messages", - limit: 500, - remaining: 500, - }); - } catch (error) { - await dumpStateOnFailure(t.database, t.dbPath); - throw error; - } - }); -}); + // Pro is still active + await expectProduct({ + database: t.database, + customerId, + planId: "pro", + expected: { status: "active" }, + }); + await expectSingleActivePlanInGroup({ + database: t.database, + customerId, + group: "base", + planId: "pro", + }); + await expectExactMeteredBalance({ + paykit: t.paykit, + customerId, + featureId: "messages", + limit: 500, + remaining: 500, + }); + } catch (error) { + await dumpStateOnFailure(t.database, t.dbPath); + throw error; + } + }); + }, +); diff --git a/e2e/smoke/subscribe/same-plan-noop.test.ts b/e2e/smoke/subscribe/same-plan-noop.test.ts index bed90c72..bd557450 100644 --- a/e2e/smoke/subscribe/same-plan-noop.test.ts +++ b/e2e/smoke/subscribe/same-plan-noop.test.ts @@ -9,6 +9,7 @@ import { expectExactMeteredBalance, expectNoScheduledPlanInGroup, expectSingleActivePlanInGroup, + subscribeCustomer, type TestPayKit, } from "../setup"; @@ -29,11 +30,7 @@ describe("same-plan-noop: pro → pro", () => { customerId = customer.customerId; // Setup: subscribe to Pro - await t.paykit.subscribe({ - customerId, - planId: "pro", - successUrl: "https://example.com/success", - }); + await subscribeCustomer({ t, customerId, planId: "pro" }); }); afterAll(async () => { @@ -64,11 +61,7 @@ describe("same-plan-noop: pro → pro", () => { const invoiceCountBefore = invoicesBeforeRows[0]?.count ?? 0; // Action: subscribe to same plan - await t.paykit.subscribe({ - customerId, - planId: "pro", - successUrl: "https://example.com/success", - }); + await subscribeCustomer({ t, customerId, planId: "pro" }); // Same product ID (no new row created) const afterRows = await t.database diff --git a/e2e/smoke/subscribe/subscribe-paid.test.ts b/e2e/smoke/subscribe/subscribe-paid.test.ts index 2a21fff6..3a310dbf 100644 --- a/e2e/smoke/subscribe/subscribe-paid.test.ts +++ b/e2e/smoke/subscribe/subscribe-paid.test.ts @@ -5,11 +5,11 @@ import { createTestPayKit, dumpStateOnFailure, expectExactMeteredBalance, - expectInvoiceCount, expectNoScheduledPlanInGroup, expectProduct, expectSingleActivePlanInGroup, expectSubscription, + subscribeCustomer, type TestPayKit, } from "../setup"; @@ -36,16 +36,7 @@ describe("subscribe-paid: free → pro", () => { it("subscribing to a paid plan from free creates an active subscription", async () => { try { - const result = await t.paykit.subscribe({ - customerId, - planId: "pro", - successUrl: "https://example.com/success", - }); - - // Direct path (has payment method, no checkout) - if (result.paymentUrl != null) { - throw new Error("Expected direct subscription, got checkout URL"); - } + await subscribeCustomer({ t, customerId, planId: "pro" }); // Pro is active with period dates await expectProduct({ @@ -90,13 +81,6 @@ describe("subscribe-paid: free → pro", () => { customerId, expected: { status: "active" }, }); - - // At least 1 invoice - await expectInvoiceCount({ - database: t.database, - customerId, - expectedAtLeast: 1, - }); } catch (error) { await dumpStateOnFailure(t.database, t.dbPath); throw error; diff --git a/e2e/smoke/subscribe/upgrade-immediate.test.ts b/e2e/smoke/subscribe/upgrade-immediate.test.ts index 32f6ea39..c6345682 100644 --- a/e2e/smoke/subscribe/upgrade-immediate.test.ts +++ b/e2e/smoke/subscribe/upgrade-immediate.test.ts @@ -8,6 +8,7 @@ import { expectNoScheduledPlanInGroup, expectProduct, expectSingleActivePlanInGroup, + subscribeCustomer, type TestPayKit, } from "../setup"; @@ -28,11 +29,7 @@ describe("upgrade-immediate: pro → ultra", () => { customerId = customer.customerId; // Setup: subscribe to Pro first - await t.paykit.subscribe({ - customerId, - planId: "pro", - successUrl: "https://example.com/success", - }); + await subscribeCustomer({ t, customerId, planId: "pro" }); }); afterAll(async () => { @@ -41,11 +38,7 @@ describe("upgrade-immediate: pro → ultra", () => { it("upgrading to a higher tier activates it immediately and ends the old plan", async () => { try { - await t.paykit.subscribe({ - customerId, - planId: "ultra", - successUrl: "https://example.com/success", - }); + await subscribeCustomer({ t, customerId, planId: "ultra" }); // Ultra is active with period dates await expectProduct({ diff --git a/e2e/smoke/webhook/duplicate-webhook.test.ts b/e2e/smoke/webhook/duplicate-webhook.test.ts index b9ec3535..d919ee6c 100644 --- a/e2e/smoke/webhook/duplicate-webhook.test.ts +++ b/e2e/smoke/webhook/duplicate-webhook.test.ts @@ -11,6 +11,7 @@ import { expectProduct, expectSingleActivePlanInGroup, replayWebhookRequest, + subscribeCustomer, type TestPayKit, waitForForwardedWebhookRequest, waitForWebhook, @@ -41,11 +42,7 @@ describe("duplicate-webhook: same event delivered twice", () => { try { const beforeSubscribe = new Date(); - await t.paykit.subscribe({ - customerId, - planId: "pro", - successUrl: "https://example.com/success", - }); + await subscribeCustomer({ t, customerId, planId: "pro" }); const subscriptionWebhook = await waitForWebhook({ after: beforeSubscribe, diff --git a/e2e/smoke/webhook/subscription-deleted.test.ts b/e2e/smoke/webhook/subscription-deleted.test.ts index 6725d486..b78b9a61 100644 --- a/e2e/smoke/webhook/subscription-deleted.test.ts +++ b/e2e/smoke/webhook/subscription-deleted.test.ts @@ -1,96 +1,103 @@ import { desc, eq } from "drizzle-orm"; +import { default as Stripe } from "stripe"; import { afterAll, beforeAll, describe, it } from "vitest"; import { subscription } from "../../../packages/paykit/src/database/schema"; +import { env } from "../../env"; import { createTestCustomerWithPM, createTestPayKit, dumpStateOnFailure, expectProduct, expectSingleActivePlanInGroup, + harness, + subscribeCustomer, type TestPayKit, waitForWebhook, } from "../setup"; -describe("subscription-deleted: Stripe cancels subscription directly", () => { - let t: TestPayKit; - let customerId: string; - let providerSubscriptionId: string; +describe.skipIf(harness.id !== "stripe")( + "subscription-deleted: Stripe cancels subscription directly", + () => { + let t: TestPayKit; + let customerId: string; + let providerSubscriptionId: string; + const stripeClient = new Stripe(env.E2E_STRIPE_SK!); - beforeAll(async () => { - t = await createTestPayKit(); - const customer = await createTestCustomerWithPM({ - t, - customer: { - id: "test_sub_deleted", - email: "sub-deleted@test.com", - name: "Subscription Deleted Test", - }, - }); - customerId = customer.customerId; + beforeAll(async () => { + t = await createTestPayKit(); + const customer = await createTestCustomerWithPM({ + t, + customer: { + id: "test_sub_deleted", + email: "sub-deleted@test.com", + name: "Subscription Deleted Test", + }, + }); + customerId = customer.customerId; - // Setup: subscribe to Pro - await t.paykit.subscribe({ - customerId, - planId: "pro", - successUrl: "https://example.com/success", - }); + // Setup: subscribe to Pro + await subscribeCustomer({ t, customerId, planId: "pro" }); - // Get provider subscription ID from provider_data JSONB - const subRows = await t.database - .select({ providerData: subscription.providerData }) - .from(subscription) - .where(eq(subscription.customerId, customerId)) - .orderBy(desc(subscription.updatedAt)) - .limit(1); - const providerData = subRows[0]?.providerData as { subscriptionId: string } | null; - providerSubscriptionId = providerData!.subscriptionId; - }); + // Get provider subscription ID from provider_data JSONB + const subRows = await t.database + .select({ providerData: subscription.providerData }) + .from(subscription) + .where(eq(subscription.customerId, customerId)) + .orderBy(desc(subscription.updatedAt)) + .limit(1); + const providerData = subRows[0]?.providerData as { subscriptionId: string } | null; + if (!providerData?.subscriptionId) { + throw new Error("Expected providerData with subscriptionId on subscription row"); + } + providerSubscriptionId = providerData.subscriptionId; + }); - afterAll(async () => { - await t?.cleanup(); - }); + afterAll(async () => { + await t?.cleanup(); + }); - it("when Stripe cancels a subscription directly, PayKit ends the product and activates free", async () => { - try { - const beforeCancel = new Date(); + it("when Stripe cancels a subscription directly, PayKit ends the product and activates free", async () => { + try { + const beforeCancel = new Date(); - // Cancel directly via Stripe API (simulates Stripe dashboard cancellation) - await t.stripeClient.subscriptions.cancel(providerSubscriptionId); - await waitForWebhook({ - after: beforeCancel, - database: t.database, - eventType: "subscription.deleted", - timeout: 30_000, - }); + // Cancel directly via Stripe API (simulates Stripe dashboard cancellation) + await stripeClient.subscriptions.cancel(providerSubscriptionId); + await waitForWebhook({ + after: beforeCancel, + database: t.database, + eventType: "subscription.deleted", + timeout: 30_000, + }); - // Pro should be canceled/ended - await expectProduct({ - database: t.database, - customerId, - planId: "pro", - expected: { canceled: true, status: "canceled" }, - }); + // Pro should be canceled/ended + await expectProduct({ + database: t.database, + customerId, + planId: "pro", + expected: { canceled: true, status: "canceled" }, + }); - // Free should be active (default plan activated) - await expectProduct({ - database: t.database, - customerId, - planId: "free", - expected: { - status: "active", - hasPeriodEnd: false, - }, - }); - await expectSingleActivePlanInGroup({ - database: t.database, - customerId, - group: "base", - planId: "free", - }); - } catch (error) { - await dumpStateOnFailure(t.database, t.dbPath); - throw error; - } - }); -}); + // Free should be active (default plan activated) + await expectProduct({ + database: t.database, + customerId, + planId: "free", + expected: { + status: "active", + hasPeriodEnd: false, + }, + }); + await expectSingleActivePlanInGroup({ + database: t.database, + customerId, + group: "base", + planId: "free", + }); + } catch (error) { + await dumpStateOnFailure(t.database, t.dbPath); + throw error; + } + }); + }, +); diff --git a/landing/content/docs/providers/meta.json b/landing/content/docs/providers/meta.json index d64b51ac..1778c933 100644 --- a/landing/content/docs/providers/meta.json +++ b/landing/content/docs/providers/meta.json @@ -1,4 +1,4 @@ { "title": "Providers", - "pages": ["stripe", "paypal", "creem", "polar", "paddle"] + "pages": ["stripe", "polar", "paypal", "creem", "paddle"] } diff --git a/landing/content/docs/providers/polar.mdx b/landing/content/docs/providers/polar.mdx index 17755d78..952fc1f4 100644 --- a/landing/content/docs/providers/polar.mdx +++ b/landing/content/docs/providers/polar.mdx @@ -1,35 +1,140 @@ --- title: Polar -description: Polar is on the roadmap as a future provider adapter. +description: Configure Polar for PayKit, set up webhooks, sync products, and use the customer portal. --- - - Polar is a roadmap provider. Treat this page as a placeholder for the eventual adapter docs. - +Polar is a developer-first payment platform. The `@paykitjs/polar` adapter handles all Polar API interactions, webhook processing, and product syncing. -## Why it belongs in the docs map +## Installation -Polar is a common comparison point for modern SaaS billing, so documenting the future adapter early -helps frame PayKit's provider-agnostic direction. + -## Planned setup +## Configuration -```ts -import { polar } from "paykitjs/providers/polar"; +Pass the `polar()` adapter to `createPayKit` with your access token and webhook secret. -const provider = polar({ - accessToken: process.env.POLAR_ACCESS_TOKEN!, +```ts title="paykit.ts" +import { polar } from "@paykitjs/polar"; +import { createPayKit } from "paykitjs"; + +export const paykit = createPayKit({ + // ... + provider: polar({ + accessToken: process.env.POLAR_ACCESS_TOKEN!, + webhookSecret: process.env.POLAR_WEBHOOK_SECRET!, + server: "sandbox", // or "production" + }), }); ``` -## Expected scope +## Environment variables + +Add these variables to your `.env` file: + +```bash title=".env" +POLAR_ACCESS_TOKEN=polar_oat_... +POLAR_WEBHOOK_SECRET=... +``` + +- `POLAR_ACCESS_TOKEN`: create one in [Polar Settings](https://polar.sh/settings) under **Access Tokens**. The token needs the following scopes: `products:read`, `products:write`, `customers:read`, `customers:write`, `customer_sessions:write`, `subscriptions:read`, `subscriptions:write`, `checkouts:write`, `organizations:read`, `organizations:write`. +- `POLAR_WEBHOOK_SECRET`: generated when you create a webhook endpoint. See the section below. + +## Webhook setup + +In the Polar Dashboard, go to **Settings > Webhooks** and create a new endpoint pointing to: + +``` +https://your-app.com/paykit/api/webhook/polar +``` + +Enable the following events: + +- `checkout.created`, `checkout.updated` +- `subscription.created`, `subscription.updated`, `subscription.active`, `subscription.canceled`, `subscription.uncanceled`, `subscription.revoked` + +You can also select all events. PayKit silently ignores any events it doesn't need. After saving, Polar displays the signing secret. Copy it as your `POLAR_WEBHOOK_SECRET`. + + + Polar uses the [Standard Webhooks](https://www.standardwebhooks.com) specification for signature verification and event deduplication. + + +## Local development + +Use the Polar CLI to forward webhook events to your local server: + +```bash +polar listen http://localhost:3000/paykit/api/webhook/polar +``` + +The CLI prints a webhook signing secret at startup. Use that as `POLAR_WEBHOOK_SECRET` in your local `.env`. -- hosted checkout initiation -- webhook normalization -- synced customer and charge state + + Install the Polar CLI with `curl -fsSL https://polar.sh/install.sh | bash`. You'll need to run `polar login` once to authenticate. + + +## Product syncing + +`paykitjs push` creates and updates Polar products to match your plan definitions. You don't need to touch the Polar Dashboard for product management. + + + +On every push, PayKit automatically: + +- Creates or updates products to match your plans +- Sets all products to **private** visibility (only purchasable via PayKit checkout, not the customer portal) +- Archives orphan products not managed by PayKit +- Configures your Polar organization settings (multiple subscriptions enabled, portal plan changes disabled) + + + Run this once on setup, and again every time you change your plans or pricing. + + +## Customer portal + +PayKit can open Polar's customer portal so users can view their subscriptions and invoices. + + + + ```ts + const { url } = await paykit.customerPortal({ + customerId: "user_123", + returnUrl: "https://myapp.com/billing", + }); + + // redirect the user to `url` + ``` + + + ```ts + const { url } = await paykitClient.customerPortal({ + returnUrl: window.location.href, + }); -## Expected scope + window.location.href = url; + ``` + + -- hosted checkout initiation -- webhook normalization -- synced customer and charge state + + Plan changes are disabled in the portal automatically by PayKit. Subscriptions should be managed through PayKit's API to keep state in sync. + + +## Dedicated account + +PayKit requires full ownership of your Polar account. The `push` command will block if it detects customers on Polar that are not managed by PayKit. Use a dedicated Polar organization for your PayKit integration. + +## Sandbox mode + +Pass `server: "sandbox"` to test with Polar's sandbox environment. This uses separate sandbox API endpoints and test data. + +```ts +provider: polar({ + accessToken: process.env.POLAR_ACCESS_TOKEN!, + webhookSecret: process.env.POLAR_WEBHOOK_SECRET!, + server: "sandbox", +}), +``` + + + Use a sandbox access token when testing. Sandbox and production are completely isolated in Polar. + diff --git a/landing/content/docs/providers/stripe.mdx b/landing/content/docs/providers/stripe.mdx index d42d9f31..ddb1aa7a 100644 --- a/landing/content/docs/providers/stripe.mdx +++ b/landing/content/docs/providers/stripe.mdx @@ -1,6 +1,6 @@ --- title: Stripe -description: Configure the Stripe adapter for PayKit, set up webhooks, sync products, and use the customer portal. +description: Configure Stripe for PayKit, set up webhooks, sync products, and use the customer portal. --- Stripe is PayKit's primary payment provider. The `@paykitjs/stripe` adapter handles all Stripe API interactions, webhook processing, and product syncing. @@ -43,7 +43,7 @@ STRIPE_WEBHOOK_SECRET=whsec_... In the Stripe Dashboard, go to **Developers > Webhooks** and create a new endpoint pointing to: ``` -https://your-app.com/paykit/api/webhook +https://your-app.com/paykit/api/webhook/stripe ``` Select the following events when creating the endpoint: @@ -70,7 +70,7 @@ After saving, Stripe displays the signing secret. Copy it as your `STRIPE_WEBHOO Use the Stripe CLI to forward webhook events to your local server: ```bash -stripe listen --forward-to localhost:3000/paykit/api/webhook +stripe listen --forward-to localhost:3000/paykit/api/webhook/stripe ``` The CLI prints a webhook signing secret at startup. Use that as `STRIPE_WEBHOOK_SECRET` in your local `.env`. diff --git a/landing/src/app/(marketing)/layout.tsx b/landing/src/app/(marketing)/layout.tsx index 8a2751ad..0a5bfab2 100644 --- a/landing/src/app/(marketing)/layout.tsx +++ b/landing/src/app/(marketing)/layout.tsx @@ -3,7 +3,6 @@ import type { ReactNode } from "react"; import { CommandMenuProvider } from "@/components/command-menu"; import { NavigationBar } from "@/components/layout/navigation-bar"; import { PageTransition } from "@/components/layout/page-transition"; -import { getGitHubStars } from "@/lib/github"; export default async function MarketingLayout({ children }: { children: ReactNode }) { // const stars = await getGitHubStars(); diff --git a/landing/src/app/docs/[[...slug]]/page.tsx b/landing/src/app/docs/[[...slug]]/page.tsx index befffd09..7a628707 100644 --- a/landing/src/app/docs/[[...slug]]/page.tsx +++ b/landing/src/app/docs/[[...slug]]/page.tsx @@ -12,7 +12,6 @@ import { CopyMarkdownButton } from "@/components/docs/copy-markdown-button"; import { Features } from "@/components/docs/features"; import { PackageInstall, PackageRun } from "@/components/docs/package-command"; import { TocFooter } from "@/components/docs/toc-footer"; -import { URLs } from "@/lib/consts"; import { source } from "@/lib/source"; import { cn } from "@/lib/utils"; diff --git a/landing/src/components/docs/docs-icons.tsx b/landing/src/components/docs/docs-icons.tsx index b6738512..56ec33b8 100644 --- a/landing/src/components/docs/docs-icons.tsx +++ b/landing/src/components/docs/docs-icons.tsx @@ -13,7 +13,6 @@ import { Gauge, GitCompareArrows, LayoutDashboard, - Layers, Monitor, Package, ReceiptText, @@ -81,7 +80,7 @@ const pageIcons = { skills: , } as const; -const enabledProviders = new Set(["stripe"]); +const enabledProviders = new Set(["stripe", "polar"]); const soonPages = new Set(["drizzleadapter", "prismaadapter", "dashboard"]); const providerPageIcons = { diff --git a/landing/src/components/layout/navigation-bar.tsx b/landing/src/components/layout/navigation-bar.tsx index 5f11eeaf..d5887489 100644 --- a/landing/src/components/layout/navigation-bar.tsx +++ b/landing/src/components/layout/navigation-bar.tsx @@ -80,7 +80,7 @@ const labelBase = // ─── Component ─────────────────────────────────────────────────────── -export function NavigationBar({ stars }: { stars: number | null }) { +export function NavigationBar({ stars: _stars }: { stars: number | null }) { const routerPathname = usePathname(); const [pathname, setPathname] = useState("/"); const [mobileMenuOpen, setMobileMenuOpen] = useState(false); diff --git a/packages/dash/package.json b/packages/dash/package.json index c796c5dd..3f31bdad 100644 --- a/packages/dash/package.json +++ b/packages/dash/package.json @@ -1,6 +1,6 @@ { "name": "@paykitjs/dash", - "version": "0.0.3", + "version": "0.0.4-canary.0", "private": true, "description": "Embedded dashboard plugin for PayKit", "license": "MIT", diff --git a/packages/paykit/package.json b/packages/paykit/package.json index 7d2236b0..1136dd72 100644 --- a/packages/paykit/package.json +++ b/packages/paykit/package.json @@ -1,6 +1,6 @@ { "name": "paykitjs", - "version": "0.0.3", + "version": "0.0.4-canary.0", "description": "TypeScript-first payments orchestration framework for modern SaaS", "keywords": [ "creem", diff --git a/packages/paykit/src/cli/commands/push.ts b/packages/paykit/src/cli/commands/push.ts index 2c09f05a..d143708b 100644 --- a/packages/paykit/src/cli/commands/push.ts +++ b/packages/paykit/src/cli/commands/push.ts @@ -5,7 +5,9 @@ import { Command } from "commander"; import picocolors from "picocolors"; import { + checkActiveSubscriptionsOnOtherProvider, checkProvider, + checkProviderCustomers, createPool, formatProductDiffs, loadCliDeps, @@ -60,6 +62,24 @@ async function pushAction(options: { config?: string; cwd: string; yes?: boolean const { ctx, diffs } = await loadProductDiffs(config, deps); const hasChanges = diffs.some((d) => d.action !== "unchanged"); + // Preflight checks + s.message("Running preflight checks"); + const providerId = config.options.provider.id; + const [subscriptionErrors, customerErrors] = await Promise.all([ + checkActiveSubscriptionsOnOtherProvider(ctx, providerId), + checkProviderCustomers(ctx, providerResult.customerSample), + ]); + const allErrors = [...providerResult.errors, ...subscriptionErrors, ...customerErrors]; + + if (allErrors.length > 0) { + s.stop(""); + for (const err of allErrors) { + p.log.error(err); + } + p.cancel("Push blocked by preflight checks"); + process.exit(1); + } + s.stop(""); // Render all sections diff --git a/packages/paykit/src/cli/commands/status.ts b/packages/paykit/src/cli/commands/status.ts index 851e552b..9a65dceb 100644 --- a/packages/paykit/src/cli/commands/status.ts +++ b/packages/paykit/src/cli/commands/status.ts @@ -5,8 +5,10 @@ import { Command } from "commander"; import picocolors from "picocolors"; import { + checkActiveSubscriptionsOnOtherProvider, checkDatabase, checkProvider, + checkProviderCustomers, createPool, formatProductDiffs, loadCliDeps, @@ -85,6 +87,8 @@ async function statusAction(options: { const pendingMigrations = dbResult.pendingMigrations; + let preflightErrors: string[] = [...providerResult.errors]; + let webhookStatus: string; if (providerResult.webhookEndpoints === null) { webhookStatus = `${picocolors.dim("?")} Could not check webhook status`; @@ -107,6 +111,13 @@ async function statusAction(options: { } else { const { ctx, diffs } = await loadProductDiffs(config, deps); + const providerId = config.options.provider.id; + const [subscriptionErrors, customerErrors] = await Promise.all([ + checkActiveSubscriptionsOnOtherProvider(ctx, providerId), + checkProviderCustomers(ctx, providerResult.customerSample), + ]); + preflightErrors = [...preflightErrors, ...subscriptionErrors, ...customerErrors]; + if (diffs.length === 0) { productsBlock = `Products\n ${picocolors.dim("No products defined")}`; } else { @@ -149,17 +160,26 @@ async function statusAction(options: { p.log.info(productsBlock); + if (preflightErrors.length > 0) { + const errorLines = preflightErrors.map((err) => ` ${picocolors.red("✖")} ${err}`); + p.log.error(`Preflight\n${errorLines.join("\n")}`); + } + const needsMigration = pendingMigrations > 0; - const hasIssues = needsMigration || needsSync; + const hasIssues = needsMigration || needsSync || preflightErrors.length > 0; if (hasIssues) { - const action = - needsMigration && needsSync - ? "apply migrations and sync products" - : needsMigration - ? "apply migrations" - : "sync products"; - p.outro(`Run ${picocolors.bold(pushCmd)} to ${action}`); + if (needsMigration || needsSync) { + const action = + needsMigration && needsSync + ? "apply migrations and sync products" + : needsMigration + ? "apply migrations" + : "sync products"; + p.outro(`Run ${picocolors.bold(pushCmd)} to ${action}`); + } else { + p.outro("Resolve the preflight errors above before continuing"); + } await printUpdateNotification(updateCheck, deps.getInstallCommand(pm, ["paykitjs@latest"])); if (options.throw) process.exit(1); } else { diff --git a/packages/paykit/src/cli/utils/shared.ts b/packages/paykit/src/cli/utils/shared.ts index 469192f4..9e577949 100644 --- a/packages/paykit/src/cli/utils/shared.ts +++ b/packages/paykit/src/cli/utils/shared.ts @@ -103,6 +103,8 @@ export async function checkDatabase( export interface ProviderCheckResult { account: { ok: true; displayName: string; mode: string } | { ok: false; message: string }; + customerSample: Array<{ providerEmail: string; paykitCustomerId: string | null }>; + errors: string[]; webhookEndpoints: Array<{ url: string; status: string }> | null; } @@ -116,6 +118,8 @@ export async function checkProvider( if (!result) { return { account: { ok: true, displayName: providerConfig.name, mode: "unknown" }, + customerSample: [], + errors: [], webhookEndpoints: null, }; } @@ -123,23 +127,87 @@ export async function checkProvider( if (result.ok) { return { account: { ok: true, displayName: result.displayName, mode: result.mode }, + customerSample: result.customerSample ?? [], + errors: result.errors ?? [], webhookEndpoints: result.webhookEndpoints ?? null, }; } return { account: { ok: false, message: result.error ?? "Provider check failed" }, + customerSample: [], + errors: result.errors ?? [], webhookEndpoints: null, }; } catch (error) { const message = error instanceof Error ? error.message : "Provider check failed"; return { account: { ok: false, message }, + customerSample: [], + errors: [], webhookEndpoints: null, }; } } +export async function checkProviderCustomers( + ctx: PayKitContext, + customerSample: ProviderCheckResult["customerSample"], +): Promise { + if (customerSample.length === 0) return []; + + const message = `${ctx.provider.name} account has existing customers that are not synced with PayKit. Use a fresh ${ctx.provider.name} account or remove existing customers from it before proceeding.`; + + const hasUnmanaged = customerSample.some((s) => !s.paykitCustomerId); + if (hasUnmanaged) return [message]; + + const paykitIds = [ + ...new Set( + customerSample.map((s) => s.paykitCustomerId).filter((id): id is string => id !== null), + ), + ]; + + if (paykitIds.length > 0) { + const { customer } = await import("../../database/schema"); + const { inArray } = await import("drizzle-orm"); + const rows = await ctx.database + .select({ id: customer.id }) + .from(customer) + .where(inArray(customer.id, paykitIds)); + if (rows.length < paykitIds.length) return [message]; + } + + return []; +} + +export async function checkActiveSubscriptionsOnOtherProvider( + ctx: PayKitContext, + currentProviderId: string, +): Promise { + const errors: string[] = []; + const { subscription } = await import("../../database/schema"); + const { and, ne, isNotNull, inArray, count } = await import("drizzle-orm"); + const rows = await ctx.database + .select({ count: count(), providerId: subscription.providerId }) + .from(subscription) + .where( + and( + inArray(subscription.status, ["active", "trialing", "past_due"]), + isNotNull(subscription.providerId), + ne(subscription.providerId, currentProviderId), + ), + ) + .groupBy(subscription.providerId); + for (const row of rows) { + if (row.count > 0 && row.providerId) { + errors.push( + `Found ${String(row.count)} subscription${row.count === 1 ? "" : "s"} (active, trialing, or past_due) linked to "${row.providerId}" but current provider is "${currentProviderId}". Existing subscriptions must be canceled before switching providers.`, + ); + } + } + return errors; +} + export async function loadProductDiffs( config: LoadedConfig, deps: Pick, diff --git a/packages/paykit/src/customer/__tests__/customer.service.test.ts b/packages/paykit/src/customer/__tests__/customer.service.test.ts index 92136450..4ae3d942 100644 --- a/packages/paykit/src/customer/__tests__/customer.service.test.ts +++ b/packages/paykit/src/customer/__tests__/customer.service.test.ts @@ -76,7 +76,7 @@ describe("customer/service", () => { listActiveSubscriptions: vi.fn(), resumeSubscription: vi.fn(), scheduleSubscriptionChange: vi.fn(), - syncProduct: vi.fn(), + syncProducts: vi.fn(), updateSubscription: vi.fn(), createCustomer: vi.fn().mockResolvedValue({ providerCustomer: { @@ -173,7 +173,7 @@ describe("customer/service", () => { listActiveSubscriptions: vi.fn(), resumeSubscription: vi.fn(), scheduleSubscriptionChange: vi.fn(), - syncProduct: vi.fn(), + syncProducts: vi.fn(), updateSubscription: vi.fn(), createCustomer: vi.fn().mockResolvedValue({ providerCustomer: { diff --git a/packages/paykit/src/customer/customer.api.ts b/packages/paykit/src/customer/customer.api.ts index b6884fee..d3ef8fcc 100644 --- a/packages/paykit/src/customer/customer.api.ts +++ b/packages/paykit/src/customer/customer.api.ts @@ -1,13 +1,12 @@ import * as z from "zod"; import { definePayKitMethod, returnUrl } from "../api/define-route"; -import { PayKitError, PAYKIT_ERROR_CODES } from "../core/errors"; import { getCustomerWithDetails, - getProviderCustomerIdForCustomer, hardDeleteCustomer, listCustomers, upsertCustomer as upsertCustomerService, + upsertProviderCustomer, } from "./customer.service"; const upsertCustomerSchema = z.object({ @@ -15,6 +14,7 @@ const upsertCustomerSchema = z.object({ email: z.string().optional(), name: z.string().optional(), metadata: z.record(z.string(), z.string()).optional(), + upsertProviderCustomer: z.boolean().optional(), }); const customerIdSchema = z.object({ @@ -60,15 +60,10 @@ export const customerPortal = definePayKitMethod( }, }, async (ctx) => { - const providerCustomerId = await getProviderCustomerIdForCustomer(ctx.paykit.database, { + const { providerCustomerId } = await upsertProviderCustomer(ctx.paykit, { customerId: ctx.customer.id, - providerId: ctx.paykit.provider.id, }); - if (!providerCustomerId) { - throw PayKitError.from("NOT_FOUND", PAYKIT_ERROR_CODES.PROVIDER_CUSTOMER_NOT_FOUND); - } - const { url } = await ctx.paykit.provider.createPortalSession({ providerCustomerId, returnUrl: ctx.input.returnUrl, diff --git a/packages/paykit/src/customer/customer.service.ts b/packages/paykit/src/customer/customer.service.ts index 0c107bbf..7f6dbcdc 100644 --- a/packages/paykit/src/customer/customer.service.ts +++ b/packages/paykit/src/customer/customer.service.ts @@ -184,21 +184,19 @@ export async function ensureDefaultPlansForCustomer( export async function upsertCustomer( ctx: PayKitContext, - input: Parameters[1], + input: Parameters[1] & { upsertProviderCustomer?: boolean }, ): Promise { const syncedCustomer = await syncCustomer(ctx.database, input); await ensureDefaultPlansForCustomer(ctx, syncedCustomer.id); - const { providerCustomer } = await upsertProviderCustomer(ctx, { - customerId: syncedCustomer.id, - }); - return { - ...syncedCustomer, - provider: { - ...(syncedCustomer.provider ?? {}), - [ctx.provider.id]: providerCustomer, - }, - }; + if (input.upsertProviderCustomer) { + await upsertProviderCustomer(ctx, { + customerId: syncedCustomer.id, + customerRow: syncedCustomer, + }); + } + + return syncedCustomer; } export async function getCustomerById( @@ -253,6 +251,7 @@ export async function getCustomerWithDetails( const subscriptionsByGroup = new Map(); for (const row of subRows) { + if (row.status === "scheduled") continue; const currentGroup = subscriptionsByGroup.get(row.planGroup) ?? []; currentGroup.push(row.planId); subscriptionsByGroup.set(row.planGroup, currentGroup); @@ -369,11 +368,12 @@ function providerCustomerNeedsSync( export async function upsertProviderCustomer( ctx: PayKitContext, - input: { customerId: string }, + input: { customerId: string; customerRow?: Customer }, ): Promise<{ customerId: string; providerCustomer: ProviderCustomer; providerCustomerId: string }> { const providerId = ctx.provider.id; - const existingCustomer = await getCustomerByIdOrThrow(ctx.database, input.customerId); + const existingCustomer = + input.customerRow ?? (await getCustomerByIdOrThrow(ctx.database, input.customerId)); const existingProviderCustomer = getProviderCustomer(existingCustomer, providerId); const existingProviderCustomerId = existingProviderCustomer?.id ?? null; diff --git a/packages/paykit/src/database/schema.ts b/packages/paykit/src/database/schema.ts index d26c530b..6aa0776a 100644 --- a/packages/paykit/src/database/schema.ts +++ b/packages/paykit/src/database/schema.ts @@ -64,7 +64,7 @@ export const feature = pgTable("feature", { updatedAt, }); -type ProviderProductMap = Record; +type ProviderProductMap = Record>; export const product = pgTable( "product", diff --git a/packages/paykit/src/product/product-sync.service.ts b/packages/paykit/src/product/product-sync.service.ts index a43ad0f6..47591033 100644 --- a/packages/paykit/src/product/product-sync.service.ts +++ b/packages/paykit/src/product/product-sync.service.ts @@ -95,6 +95,15 @@ export async function syncProducts(ctx: PayKitContext): Promise | null; + storedProductInternalId: string; + }> = []; + for (const plan of ctx.plans.plans) { const existing = await getLatestProductSnapshot(ctx.database, plan.id); const existingProviderProduct = existing @@ -151,24 +160,13 @@ export async function syncProducts(ctx: PayKitContext): Promise 0) { + const providerResults = await ctx.provider.syncProducts({ + products: paidPlansToSync.map((p) => ({ + existingProviderProduct: p.existingProviderProduct, + id: p.id, + name: p.name, + priceAmount: p.priceAmount, + priceInterval: p.priceInterval, + })), + }); + + const requestedIds = new Set(paidPlansToSync.map((p) => p.id)); + const resultById = new Map(); + for (const r of providerResults.results) { + if (resultById.has(r.id)) { + throw PayKitError.from( + "INTERNAL_SERVER_ERROR", + PAYKIT_ERROR_CODES.PLAN_SYNC_FAILED, + `Provider syncProducts returned duplicate mapping for id: ${r.id}`, + ); + } + resultById.set(r.id, r); + } + const missingIds = [...requestedIds].filter((id) => !resultById.has(id)); + if (missingIds.length > 0 || resultById.size !== requestedIds.size) { + throw PayKitError.from( + "INTERNAL_SERVER_ERROR", + PAYKIT_ERROR_CODES.PLAN_SYNC_FAILED, + `Provider syncProducts returned invalid mapping: missing=[${missingIds.join(", ")}], expected=${String(requestedIds.size)}, got=${String(resultById.size)}`, + ); + } + + for (const [, providerResult] of resultById) { + const plan = paidPlansToSync.find((p) => p.id === providerResult.id); + if (!plan) continue; + await upsertProviderProduct(ctx.database, { + productInternalId: plan.storedProductInternalId, + providerId, + providerProduct: providerResult.providerProduct, + }); + } + } + return results; } diff --git a/packages/paykit/src/product/product.service.ts b/packages/paykit/src/product/product.service.ts index 66f66f95..f387e2e5 100644 --- a/packages/paykit/src/product/product.service.ts +++ b/packages/paykit/src/product/product.service.ts @@ -13,23 +13,18 @@ export interface StoredProductSnapshot { } export interface StoredProductWithProvider extends StoredProduct { - providerProductId: string | null; - providerPriceId: string | null; + providerProduct: Record | null; } export function withProviderInfo( storedProduct: StoredProduct, providerId: string, ): StoredProductWithProvider { - const providerMap = (storedProduct.provider ?? {}) as Record< - string, - { productId: string; priceId: string | null } - >; + const providerMap = (storedProduct.provider ?? {}) as Record>; const providerInfo = providerMap[providerId]; return { ...storedProduct, - providerProductId: providerInfo?.productId ?? null, - providerPriceId: providerInfo?.priceId ?? null, + providerProduct: providerInfo ?? null, }; } @@ -232,13 +227,13 @@ export async function getProviderProduct( database: PayKitDatabase, productInternalId: string, providerId: string, -): Promise<{ productId: string; priceId: string | null } | null> { +): Promise | null> { const row = await database.query.product.findFirst({ where: eq(product.internalId, productInternalId), }); if (!row) return null; - const providerMap = row.provider as Record; + const providerMap = row.provider as Record>; return providerMap[providerId] ?? null; } @@ -247,8 +242,7 @@ export async function upsertProviderProduct( input: { productInternalId: string; providerId: string; - providerProductId: string; - providerPriceId?: string | null; + providerProduct: Record; }, ): Promise { const existing = await database.query.product.findFirst({ @@ -256,14 +250,8 @@ export async function upsertProviderProduct( }); if (!existing) return; - const providerMap = (existing.provider ?? {}) as Record< - string, - { productId: string; priceId: string | null } - >; - providerMap[input.providerId] = { - productId: input.providerProductId, - priceId: input.providerPriceId ?? null, - }; + const providerMap = (existing.provider ?? {}) as Record>; + providerMap[input.providerId] = input.providerProduct; await database .update(product) @@ -283,12 +271,12 @@ export async function getDefaultProductInGroup( return row ?? null; } -export async function getProductByProviderPriceId( +export async function getProductByProviderData( database: PayKitDatabase, - input: { providerId: string; providerPriceId: string }, + input: { providerId: string; key: string; value: string }, ): Promise { const row = await database.query.product.findFirst({ - where: sql`${product.provider}->${input.providerId}->>'priceId' = ${input.providerPriceId}`, + where: sql`${product.provider}->${input.providerId}->>${input.key} = ${input.value}`, }); return row ?? null; diff --git a/packages/paykit/src/providers/provider.ts b/packages/paykit/src/providers/provider.ts index ef8a2adf..f61ad4fe 100644 --- a/packages/paykit/src/providers/provider.ts +++ b/packages/paykit/src/providers/provider.ts @@ -49,7 +49,6 @@ export interface ProviderSubscription { currentPeriodEndAt?: Date | null; currentPeriodStartAt?: Date | null; endedAt?: Date | null; - providerPriceId?: string | null; providerSubscriptionId: string; providerSubscriptionScheduleId?: string | null; status: string; @@ -95,7 +94,7 @@ export interface PaymentProvider { createSubscriptionCheckout(data: { providerCustomerId: string; - providerPriceId: string; + providerProduct: Record; successUrl: string; cancelUrl?: string; metadata?: Record; @@ -103,11 +102,11 @@ export interface PaymentProvider { createSubscription(data: { providerCustomerId: string; - providerPriceId: string; + providerProduct: Record; }): Promise; updateSubscription(data: { - providerPriceId: string; + providerProduct: Record; providerSubscriptionId: string; }): Promise; @@ -118,7 +117,7 @@ export interface PaymentProvider { }): Promise; scheduleSubscriptionChange(data: { - providerPriceId?: string | null; + providerProduct?: Record | null; providerSubscriptionScheduleId?: string | null; providerSubscriptionId: string; }): Promise; @@ -140,14 +139,20 @@ export interface PaymentProvider { detachPaymentMethod(data: { providerMethodId: string }): Promise; - syncProduct(data: { - id: string; - name: string; - priceAmount: number; - priceInterval?: string | null; - existingProviderProductId?: string | null; - existingProviderPriceId?: string | null; - }): Promise<{ providerProductId: string; providerPriceId: string }>; + syncProducts(data: { + products: Array<{ + id: string; + name: string; + priceAmount: number; + priceInterval?: string | null; + existingProviderProduct?: Record | null; + }>; + }): Promise<{ + results: Array<{ + id: string; + providerProduct: Record; + }>; + }>; handleWebhook(data: { body: string; @@ -164,6 +169,8 @@ export interface PaymentProvider { displayName: string; mode: string; webhookEndpoints?: Array<{ url: string; status: string }>; + errors?: string[]; + customerSample?: Array<{ providerEmail: string; paykitCustomerId: string | null }>; error?: string; }>; } diff --git a/packages/paykit/src/subscription/subscription.service.ts b/packages/paykit/src/subscription/subscription.service.ts index 266ff039..2f2b41a0 100644 --- a/packages/paykit/src/subscription/subscription.service.ts +++ b/packages/paykit/src/subscription/subscription.service.ts @@ -15,7 +15,7 @@ import { getDefaultProductInGroup, getProductByHash, getProductByInternalId, - getProductByProviderPriceId, + getProductByProviderData, getProductFeatures, withProviderInfo, } from "../product/product.service"; @@ -114,7 +114,7 @@ export async function loadSubscribeContext(ctx: PayKitContext, input: SubscribeI const isFreeTarget = storedPlan.priceAmount === null; const isPaidTarget = !isFreeTarget; - if (isPaidTarget && !storedPlan.providerPriceId) { + if (isPaidTarget && !storedPlan.providerProduct) { throw PayKitError.from( "INTERNAL_SERVER_ERROR", PAYKIT_ERROR_CODES.PLAN_NOT_SYNCED, @@ -333,12 +333,21 @@ export async function prepareSubscribeCheckoutCompleted( productInternalId: productInternalId ?? undefined, successUrl: "https://paykit.invalid/checkout", }); - if (subCtx.storedPlan.providerPriceId !== checkoutSubscription.providerPriceId) { - throw PayKitError.from( - "BAD_REQUEST", - PAYKIT_ERROR_CODES.PROVIDER_WEBHOOK_INVALID, - `Checkout price mismatch for plan "${planId}"`, - ); + const checkoutProviderProduct = checkoutSubscription.providerProduct; + const storedProviderProduct = subCtx.storedPlan.providerProduct; + if (checkoutProviderProduct && storedProviderProduct) { + const checkoutKeys = Object.keys(checkoutProviderProduct); + const storedKeys = Object.keys(storedProviderProduct); + const mismatch = + checkoutKeys.length !== storedKeys.length || + checkoutKeys.some((key) => checkoutProviderProduct[key] !== storedProviderProduct[key]); + if (mismatch) { + throw PayKitError.from( + "BAD_REQUEST", + PAYKIT_ERROR_CODES.PROVIDER_WEBHOOK_INVALID, + `Checkout product mismatch for plan "${planId}"`, + ); + } } const completion = { @@ -531,11 +540,19 @@ export async function applySubscriptionWebhookAction( providerId: ctx.provider.id, providerSubscriptionId: action.data.subscription.providerSubscriptionId, }); - const storedProduct = action.data.subscription.providerPriceId - ? await getProductByProviderPriceId(ctx.database, { - providerId: ctx.provider.id, - providerPriceId: action.data.subscription.providerPriceId, - }) + const providerProduct = action.data.subscription.providerProduct; + const storedProduct = providerProduct + ? await (async () => { + for (const [key, value] of Object.entries(providerProduct)) { + const found = await getProductByProviderData(ctx.database, { + providerId: ctx.provider.id, + key, + value, + }); + if (found) return found; + } + return null; + })() : null; const normalizedPlan = storedProduct ? (ctx.plans.planMap.get(storedProduct.id) ?? null) : null; @@ -805,7 +822,7 @@ async function handleInitialSubscribe( const providerResult = await ctx.provider.createSubscription({ providerCustomerId: subCtx.providerCustomerId, - providerPriceId: subCtx.storedPlan.providerPriceId!, + providerProduct: subCtx.storedPlan.providerProduct!, }); await ctx.database.transaction(async (tx) => { @@ -862,7 +879,7 @@ async function handleLocalPlanSwitch( const providerResult = await ctx.provider.createSubscription({ providerCustomerId: subCtx.providerCustomerId, - providerPriceId: subCtx.storedPlan.providerPriceId!, + providerProduct: subCtx.storedPlan.providerProduct!, }); await ctx.database.transaction(async (tx) => { @@ -957,7 +974,7 @@ async function handleScheduledDowngrade( } const providerResult = await ctx.provider.scheduleSubscriptionChange({ - providerPriceId: subCtx.storedPlan.providerPriceId!, + providerProduct: subCtx.storedPlan.providerProduct!, providerSubscriptionId: activeSubscriptionRef.subscriptionId, providerSubscriptionScheduleId: activeSubscriptionRef.subscriptionScheduleId, }); @@ -1010,12 +1027,8 @@ async function handleUpgrade( throw PayKitError.from("INTERNAL_SERVER_ERROR", PAYKIT_ERROR_CODES.SUBSCRIPTION_CREATE_FAILED); } - if (subCtx.shouldUseCheckout) { - return createCheckoutSubscribe(ctx, subCtx); - } - const providerResult = await ctx.provider.updateSubscription({ - providerPriceId: subCtx.storedPlan.providerPriceId!, + providerProduct: subCtx.storedPlan.providerProduct!, providerSubscriptionId: activeSubscriptionRef.subscriptionId, }); @@ -1060,7 +1073,7 @@ async function createCheckoutSubscribe( paykit_product_internal_id: subCtx.storedPlan.internalId, }, providerCustomerId: subCtx.providerCustomerId, - providerPriceId: subCtx.storedPlan.providerPriceId!, + providerProduct: subCtx.storedPlan.providerProduct!, successUrl: subCtx.successUrl, }); @@ -1187,7 +1200,7 @@ function addResetInterval(date: Date, resetInterval: string): Date { return next; } -type ProviderProductMap = Record; +type ProviderProductMap = Record>; export async function warnOnDuplicateActiveSubscriptionGroups( ctx: PayKitContext, @@ -1241,6 +1254,7 @@ function mapJoinRowToSubscriptionWithCatalog(row: { product: typeof product.$inferSelect; }): SubscriptionWithCatalog { const providerMap = row.product.provider as ProviderProductMap | null; + const providerId = row.subscription.providerId; return { ...row.subscription, planGroup: row.product.group, @@ -1249,7 +1263,7 @@ function mapJoinRowToSubscriptionWithCatalog(row: { planName: row.product.name, priceAmount: row.product.priceAmount, priceInterval: row.product.priceInterval, - providerPriceId: Object.values(providerMap ?? {})[0]?.priceId ?? null, + providerProduct: (providerId ? providerMap?.[providerId] : null) ?? null, }; } diff --git a/packages/paykit/src/subscription/subscription.types.ts b/packages/paykit/src/subscription/subscription.types.ts index 1c7b7c52..d4fd1116 100644 --- a/packages/paykit/src/subscription/subscription.types.ts +++ b/packages/paykit/src/subscription/subscription.types.ts @@ -40,5 +40,5 @@ export interface SubscriptionWithCatalog extends StoredSubscription { planName: string; priceAmount: number | null; priceInterval: string | null; - providerPriceId: string | null; + providerProduct: Record | null; } diff --git a/packages/paykit/src/types/events.ts b/packages/paykit/src/types/events.ts index 14903a7e..a9289996 100644 --- a/packages/paykit/src/types/events.ts +++ b/packages/paykit/src/types/events.ts @@ -24,7 +24,7 @@ export interface NormalizedSubscription { currentPeriodEndAt?: Date | null; currentPeriodStartAt?: Date | null; endedAt?: Date | null; - providerPriceId?: string | null; + providerProduct?: Record | null; providerSubscriptionId: string; providerSubscriptionScheduleId?: string | null; status: string; diff --git a/packages/polar/package.json b/packages/polar/package.json new file mode 100644 index 00000000..1d94e781 --- /dev/null +++ b/packages/polar/package.json @@ -0,0 +1,40 @@ +{ + "name": "@paykitjs/polar", + "version": "0.0.4-canary.0", + "description": "Polar provider adapter for PayKit", + "license": "MIT", + "repository": { + "type": "git", + "url": "git+https://github.com/getpaykit/paykit.git" + }, + "files": [ + "dist" + ], + "type": "module", + "exports": { + ".": "./src/index.ts" + }, + "publishConfig": { + "exports": { + ".": { + "types": "./dist/index.d.ts", + "default": "./dist/index.js" + } + }, + "main": "./dist/index.js", + "types": "./dist/index.d.ts" + }, + "scripts": { + "build": "tsdown --config tsdown.config.ts", + "typecheck": "tsc --build" + }, + "dependencies": { + "@polar-sh/sdk": "^0.47.0", + "paykitjs": "workspace:*" + }, + "devDependencies": { + "tsdown": "^0.21.1", + "typescript": "^5.9.2", + "vitest": "^4.0.18" + } +} diff --git a/packages/polar/src/index.ts b/packages/polar/src/index.ts new file mode 100644 index 00000000..03f68ef3 --- /dev/null +++ b/packages/polar/src/index.ts @@ -0,0 +1,2 @@ +export { polar } from "./polar-provider"; +export type { PolarOptions } from "./polar-provider"; diff --git a/packages/polar/src/polar-provider.ts b/packages/polar/src/polar-provider.ts new file mode 100644 index 00000000..a1fa24d3 --- /dev/null +++ b/packages/polar/src/polar-provider.ts @@ -0,0 +1,556 @@ +import { Polar } from "@polar-sh/sdk"; +import { SDKValidationError } from "@polar-sh/sdk/models/errors/sdkvalidationerror"; +import { validateEvent, WebhookVerificationError } from "@polar-sh/sdk/webhooks"; +import { PayKitError, PAYKIT_ERROR_CODES } from "paykitjs"; +import type { NormalizedWebhookEvent, PayKitProviderConfig, PaymentProvider } from "paykitjs"; + +export interface PolarOptions { + accessToken: string; + webhookSecret: string; + server?: "production" | "sandbox"; +} + +type PolarWebhookEvent = ReturnType; +type PolarSubscriptionEvent = Extract; +type PolarCheckoutEvent = Extract; + +function normalizePolarSubscription(sub: PolarSubscriptionEvent["data"]) { + return { + cancelAtPeriodEnd: sub.cancelAtPeriodEnd, + canceledAt: sub.canceledAt ?? null, + currentPeriodEndAt: sub.currentPeriodEnd ?? null, + currentPeriodStartAt: sub.currentPeriodStart, + endedAt: sub.endedAt ?? null, + providerProduct: { productId: sub.productId }, + providerSubscriptionId: sub.id, + providerSubscriptionScheduleId: null, + status: sub.status, + }; +} + +function createSubscriptionEvents( + event: { type?: string; data: PolarSubscriptionEvent["data"] }, + webhookId: string, +): NormalizedWebhookEvent[] { + const sub = event.data; + + // `subscription.revoked` = immediately terminated (like Stripe delete) + // `subscription.canceled` = will cancel at period end (like Stripe cancel_at_period_end) + if (event.type === "subscription.revoked") { + return [ + { + actions: [ + { + data: { + providerCustomerId: sub.customerId, + providerSubscriptionId: sub.id, + }, + type: "subscription.delete", + }, + ], + name: "subscription.deleted", + payload: { + providerCustomerId: sub.customerId, + providerEventId: webhookId, + providerSubscriptionId: sub.id, + }, + }, + ]; + } + + const normalized = normalizePolarSubscription(sub); + return [ + { + actions: [ + { + data: { + providerCustomerId: sub.customerId, + subscription: normalized, + }, + type: "subscription.upsert", + }, + ], + name: "subscription.updated", + payload: { + providerCustomerId: sub.customerId, + providerEventId: webhookId, + subscription: normalized, + }, + }, + ]; +} + +function createCheckoutEvents( + event: { type?: string; data: PolarCheckoutEvent["data"] }, + webhookId: string, +): NormalizedWebhookEvent[] { + const checkout = event.data; + if (checkout.status !== "succeeded") return []; + + const providerCustomerId = checkout.customerId; + if (!providerCustomerId) return []; + + return [ + { + name: "checkout.completed", + payload: { + checkoutSessionId: checkout.id, + mode: "subscription", + paymentStatus: "paid", + providerCustomerId, + providerEventId: webhookId, + providerSubscriptionId: checkout.subscriptionId ?? undefined, + status: checkout.status, + metadata: checkout.metadata + ? Object.fromEntries(Object.entries(checkout.metadata).map(([k, v]) => [k, String(v)])) + : undefined, + }, + }, + ]; +} + +function notSupported(method: string): never { + throw PayKitError.from( + "BAD_REQUEST", + PAYKIT_ERROR_CODES.PROVIDER_WEBHOOK_INVALID, + `${method} is not supported by the Polar provider`, + ); +} + +export function createPolarProvider(client: Polar, options: PolarOptions): PaymentProvider { + return { + id: "polar", + name: "Polar", + + async createCustomer(data) { + if (!data.email) { + throw PayKitError.from( + "BAD_REQUEST", + PAYKIT_ERROR_CODES.CUSTOMER_CREATE_FAILED, + "Polar requires a non-empty email to create a customer", + ); + } + + const customerMetadata = { + ...data.metadata, + paykitCustomerId: data.id, + }; + + try { + const customer = await client.customers.create({ + email: data.email, + name: data.name, + metadata: customerMetadata, + }); + + return { + providerCustomer: { id: customer.id }, + }; + } catch (error) { + if (!(error instanceof SDKValidationError)) throw error; + + // Duplicate email — find and re-link the existing customer. + const list = await client.customers.list({ query: data.email, limit: 1 }); + const existing = list.result.items[0]; + + if (!existing) { + throw PayKitError.from( + "INTERNAL_SERVER_ERROR", + PAYKIT_ERROR_CODES.PROVIDER_CUSTOMER_NOT_FOUND, + "Failed to create or find customer on Polar", + ); + } + + await client.customers.update({ + id: existing.id, + customerUpdate: { + name: data.name, + metadata: customerMetadata, + }, + }); + + return { + providerCustomer: { id: existing.id }, + }; + } + }, + + async updateCustomer(data) { + await client.customers.update({ + id: data.providerCustomerId, + customerUpdate: { + email: data.email, + name: data.name, + metadata: data.metadata ?? {}, + }, + }); + }, + + async deleteCustomer(data) { + await client.customers.delete({ id: data.providerCustomerId }); + }, + + getTestClock() { + return notSupported("getTestClock"); + }, + + advanceTestClock() { + return notSupported("advanceTestClock"); + }, + + attachPaymentMethod() { + return notSupported("attachPaymentMethod"); + }, + + async createSubscriptionCheckout(data) { + const checkout = await client.checkouts.create({ + products: [data.providerProduct.productId!], + customerId: data.providerCustomerId, + successUrl: data.successUrl, + }); + + if (!checkout.url) { + throw PayKitError.from("BAD_REQUEST", PAYKIT_ERROR_CODES.PROVIDER_SESSION_INVALID); + } + + return { + paymentUrl: checkout.url, + providerCheckoutSessionId: checkout.id, + }; + }, + + createSubscription() { + return notSupported("createSubscription (use checkout instead)"); + }, + + async updateSubscription(data) { + const sub = await client.subscriptions.update({ + id: data.providerSubscriptionId, + subscriptionUpdate: { + productId: data.providerProduct.productId!, + prorationBehavior: "invoice", + }, + }); + + return { + paymentUrl: null, + subscription: { + cancelAtPeriodEnd: sub.cancelAtPeriodEnd, + currentPeriodEndAt: sub.currentPeriodEnd ? new Date(sub.currentPeriodEnd) : null, + currentPeriodStartAt: sub.currentPeriodStart ? new Date(sub.currentPeriodStart) : null, + providerSubscriptionId: sub.id, + status: sub.status, + }, + }; + }, + + createInvoice() { + return notSupported("createInvoice"); + }, + + async scheduleSubscriptionChange(data) { + const current = await client.subscriptions.get({ id: data.providerSubscriptionId }); + const wasCanceled = current.cancelAtPeriodEnd; + + // Un-cancel to allow product update (Polar rejects updates on canceled subs) + if (wasCanceled) { + await client.subscriptions.update({ + id: data.providerSubscriptionId, + subscriptionUpdate: { cancelAtPeriodEnd: false }, + }); + } + + await client.subscriptions.update({ + id: data.providerSubscriptionId, + subscriptionUpdate: { + productId: data.providerProduct!.productId!, + prorationBehavior: "next_period", + }, + }); + + // Re-cancel if it was previously canceled (preserve cancel-at-period-end intent) + if (wasCanceled) { + await client.subscriptions.update({ + id: data.providerSubscriptionId, + subscriptionUpdate: { cancelAtPeriodEnd: true }, + }); + } + + const sub = await client.subscriptions.get({ id: data.providerSubscriptionId }); + + return { + paymentUrl: null, + subscription: { + cancelAtPeriodEnd: sub.cancelAtPeriodEnd, + currentPeriodEndAt: sub.currentPeriodEnd ? new Date(sub.currentPeriodEnd) : null, + currentPeriodStartAt: sub.currentPeriodStart ? new Date(sub.currentPeriodStart) : null, + providerSubscriptionId: sub.id, + status: sub.status, + }, + }; + }, + + async cancelSubscription(data) { + const sub = await client.subscriptions.update({ + id: data.providerSubscriptionId, + subscriptionUpdate: { + cancelAtPeriodEnd: true, + }, + }); + + return { + paymentUrl: null, + subscription: { + cancelAtPeriodEnd: sub.cancelAtPeriodEnd, + currentPeriodEndAt: sub.currentPeriodEnd ? new Date(sub.currentPeriodEnd) : null, + currentPeriodStartAt: sub.currentPeriodStart ? new Date(sub.currentPeriodStart) : null, + providerSubscriptionId: sub.id, + status: sub.status, + }, + }; + }, + + async listActiveSubscriptions(data) { + const result = await client.subscriptions.list({ + customerId: data.providerCustomerId, + }); + + return (result.result.items ?? []) + .filter((sub) => sub.status === "active" || sub.status === "trialing") + .map((sub) => ({ providerSubscriptionId: sub.id })); + }, + + async resumeSubscription(data) { + const current = await client.subscriptions.get({ id: data.providerSubscriptionId }); + + // Un-cancel first if pending cancellation + if (current.cancelAtPeriodEnd) { + await client.subscriptions.update({ + id: data.providerSubscriptionId, + subscriptionUpdate: { cancelAtPeriodEnd: false }, + }); + } + + // Clear pending product change if any + const sub = current.pendingUpdate + ? await client.subscriptions.update({ + id: data.providerSubscriptionId, + subscriptionUpdate: { productId: current.productId }, + }) + : await client.subscriptions.get({ id: data.providerSubscriptionId }); + + return { + paymentUrl: null, + subscription: { + cancelAtPeriodEnd: sub.cancelAtPeriodEnd, + currentPeriodEndAt: sub.currentPeriodEnd ? new Date(sub.currentPeriodEnd) : null, + currentPeriodStartAt: sub.currentPeriodStart ? new Date(sub.currentPeriodStart) : null, + providerSubscriptionId: sub.id, + status: sub.status, + }, + }; + }, + + detachPaymentMethod() { + return notSupported("detachPaymentMethod"); + }, + + async syncProducts(data) { + const [allPolarProducts, orgs] = await Promise.all([ + client.products.list({ isArchived: false, limit: 100 }), + client.organizations.list({ limit: 1 }), + ]); + + const org = orgs.result.items?.[0]; + const polarProductMap = new Map((allPolarProducts.result.items ?? []).map((p) => [p.id, p])); + + const activeProductIds = new Set(); + + const results = await Promise.all( + data.products.map(async (product) => { + const existingProductId = product.existingProviderProduct?.productId ?? null; + const existingPolarProduct = existingProductId + ? polarProductMap.get(existingProductId) + : null; + + if (existingPolarProduct) { + const intervalMatches = + existingPolarProduct.recurringInterval === (product.priceInterval ?? null); + + if (intervalMatches) { + const updated = await client.products.update({ + id: existingPolarProduct.id, + productUpdate: { + name: product.name, + visibility: "private", + prices: [ + { + amountType: "fixed" as const, + priceAmount: product.priceAmount, + priceCurrency: "usd", + }, + ], + }, + }); + activeProductIds.add(updated.id); + return { id: product.id, providerProduct: { productId: updated.id } }; + } + + // Interval changed — archive old, create new + await client.products.update({ + id: existingPolarProduct.id, + productUpdate: { isArchived: true }, + }); + } + + const created = await client.products.create({ + name: product.name, + visibility: "private", + recurringInterval: (product.priceInterval as "month" | "year") ?? null, + prices: [ + { + amountType: "fixed" as const, + priceAmount: product.priceAmount, + priceCurrency: "usd", + }, + ], + }); + activeProductIds.add(created.id); + return { id: product.id, providerProduct: { productId: created.id } }; + }), + ); + + // Archive orphans + configure org settings in parallel + const cleanup: Promise[] = []; + + for (const [polarId] of polarProductMap) { + if (!activeProductIds.has(polarId)) { + cleanup.push( + client.products.update({ + id: polarId, + productUpdate: { isArchived: true }, + }), + ); + } + } + + if (org) { + cleanup.push( + client.organizations.update({ + id: org.id, + organizationUpdate: { + subscriptionSettings: { + allowMultipleSubscriptions: true, + allowCustomerUpdates: false, + prorationBehavior: "invoice", + benefitRevocationGracePeriod: org.subscriptionSettings.benefitRevocationGracePeriod, + preventTrialAbuse: org.subscriptionSettings.preventTrialAbuse, + }, + customerPortalSettings: { + subscription: { updateSeats: false, updatePlan: false }, + usage: org.customerPortalSettings.usage, + }, + }, + }), + ); + } + + await Promise.all(cleanup); + + return { results }; + }, + + async handleWebhook(data): Promise { + const webhookIdKey = Object.keys(data.headers).find((k) => k.toLowerCase() === "webhook-id"); + const webhookId = webhookIdKey ? data.headers[webhookIdKey]! : ""; + + let event: ReturnType; + try { + event = validateEvent(data.body, data.headers, options.webhookSecret); + } catch (error) { + if (error instanceof WebhookVerificationError) { + throw PayKitError.from( + "BAD_REQUEST", + PAYKIT_ERROR_CODES.PROVIDER_SIGNATURE_MISSING, + "Invalid Polar webhook signature", + ); + } + // Unknown event types (e.g. member.created) — ignore silently + if (error instanceof SDKValidationError) { + return []; + } + throw error; + } + + switch (event.type) { + case "subscription.created": + case "subscription.updated": + case "subscription.active": + case "subscription.uncanceled": + case "subscription.canceled": + case "subscription.revoked": + return createSubscriptionEvents(event, webhookId); + case "checkout.created": + case "checkout.updated": + return createCheckoutEvents(event, webhookId); + default: + return []; + } + }, + + async createPortalSession(data) { + const session = await client.customerSessions.create({ + customerId: data.providerCustomerId, + }); + + return { + url: session.customerPortalUrl, + }; + }, + + async check() { + try { + await client.products.list({ limit: 1 }); + + const customers = await client.customers.list({ + limit: 5, + sorting: ["created_at"], + }); + const customerSample = (customers.result.items ?? []).map((c) => ({ + providerEmail: c.email ?? "", + paykitCustomerId: (c.metadata?.paykitCustomerId as string) ?? null, + })); + + return { + ok: true, + displayName: "Polar", + mode: options.server === "sandbox" ? "sandbox" : "production", + webhookEndpoints: [], + customerSample, + }; + } catch (error) { + const message = error instanceof Error ? error.message : String(error); + return { + ok: false, + displayName: "Polar", + mode: options.server === "sandbox" ? "sandbox" : "production", + error: message, + }; + } + }, + }; +} + +export function polar(polarOptions: PolarOptions): PayKitProviderConfig { + return { + id: "polar", + name: "Polar", + createAdapter(): PaymentProvider { + const client = new Polar({ + accessToken: polarOptions.accessToken, + server: polarOptions.server ?? "production", + }); + return createPolarProvider(client, polarOptions); + }, + }; +} diff --git a/packages/polar/tsconfig.json b/packages/polar/tsconfig.json new file mode 100644 index 00000000..da8829fe --- /dev/null +++ b/packages/polar/tsconfig.json @@ -0,0 +1,7 @@ +{ + "extends": "../../tsconfig.base.json", + "compilerOptions": { + "rootDir": "src" + }, + "include": ["src"] +} diff --git a/packages/polar/tsdown.config.ts b/packages/polar/tsdown.config.ts new file mode 100644 index 00000000..7b525feb --- /dev/null +++ b/packages/polar/tsdown.config.ts @@ -0,0 +1,19 @@ +import { defineConfig } from "tsdown"; + +export default defineConfig({ + clean: true, + deps: { + onlyAllowBundle: false, + skipNodeModulesBundle: true, + }, + dts: true, + entry: { + index: "src/index.ts", + }, + fixedExtension: false, + format: "esm", + outDir: "dist", + platform: "node", + target: "node22", + unbundle: true, +}); diff --git a/packages/stripe/package.json b/packages/stripe/package.json index 470f1209..ab5309df 100644 --- a/packages/stripe/package.json +++ b/packages/stripe/package.json @@ -1,6 +1,6 @@ { "name": "@paykitjs/stripe", - "version": "0.0.3", + "version": "0.0.4-canary.0", "description": "Stripe provider adapter for PayKit", "license": "MIT", "repository": { diff --git a/packages/stripe/src/__tests__/stripe.test.ts b/packages/stripe/src/__tests__/stripe.test.ts index abeed9ea..3592659e 100644 --- a/packages/stripe/src/__tests__/stripe.test.ts +++ b/packages/stripe/src/__tests__/stripe.test.ts @@ -157,7 +157,7 @@ describe("providers/stripe", () => { cancelUrl: "https://example.com/cancel", metadata: {}, providerCustomerId: "cus_123", - providerPriceId: "price_123", + providerProduct: { priceId: "price_123" }, successUrl: "https://example.com/success", }); @@ -176,7 +176,7 @@ describe("providers/stripe", () => { cancelUrl: "https://example.com/cancel", metadata: {}, providerCustomerId: "cus_123", - providerPriceId: "price_123", + providerProduct: { priceId: "price_123" }, successUrl: "https://example.com/success", }); diff --git a/packages/stripe/src/stripe-provider.ts b/packages/stripe/src/stripe-provider.ts index 8450ca42..b7a4318b 100644 --- a/packages/stripe/src/stripe-provider.ts +++ b/packages/stripe/src/stripe-provider.ts @@ -131,7 +131,7 @@ function normalizeStripeSubscription(subscription: StripeSubscriptionWithExtras) currentPeriodEndAt: toDate(periodEnd), currentPeriodStartAt: toDate(periodStart), endedAt: toDate(subscription.ended_at), - providerPriceId: providerPriceId ?? null, + providerProduct: providerPriceId ? { priceId: providerPriceId } : null, providerSubscriptionId: subscription.id, providerSubscriptionScheduleId: (typeof subscription.schedule === "string" @@ -611,7 +611,7 @@ export function createStripeProvider(client: StripeSdk, options: StripeOptions): cancel_url: data.cancelUrl ?? data.successUrl, client_reference_id: data.providerCustomerId, customer: data.providerCustomerId, - line_items: [{ price: data.providerPriceId, quantity: 1 }], + line_items: [{ price: data.providerProduct.priceId, quantity: 1 }], metadata: data.metadata, mode: "subscription", success_url: data.successUrl, @@ -634,7 +634,7 @@ export function createStripeProvider(client: StripeSdk, options: StripeOptions): async createSubscription(data) { const createParams: StripeSdk.SubscriptionCreateParams = { customer: data.providerCustomerId, - items: [{ price: data.providerPriceId }], + items: [{ price: data.providerProduct.priceId }], payment_behavior: "default_incomplete", expand: ["latest_invoice.payment_intent"], }; @@ -677,7 +677,7 @@ export function createStripeProvider(client: StripeSdk, options: StripeOptions): items: [ { id: currentItem.id, - price: data.providerPriceId, + price: data.providerProduct.priceId, }, ], payment_behavior: "pending_if_incomplete", @@ -704,7 +704,7 @@ export function createStripeProvider(client: StripeSdk, options: StripeOptions): }, async scheduleSubscriptionChange(data) { - if (!data.providerPriceId) { + if (!data.providerProduct?.priceId) { throw PayKitError.from("BAD_REQUEST", PAYKIT_ERROR_CODES.PROVIDER_PRICE_REQUIRED); } @@ -752,7 +752,7 @@ export function createStripeProvider(client: StripeSdk, options: StripeOptions): end_date: periodEndSeconds, }, { - items: [{ price: data.providerPriceId, quantity: 1 }], + items: [{ price: data.providerProduct.priceId, quantity: 1 }], start_date: periodEndSeconds, }, ], @@ -838,35 +838,42 @@ export function createStripeProvider(client: StripeSdk, options: StripeOptions): await client.paymentMethods.detach(data.providerMethodId); }, - async syncProduct(data) { - let providerProductId = data.existingProviderProductId; - if (!providerProductId) { - const stripeProduct = await client.products.create({ - metadata: { paykit_product_id: data.id }, - name: data.name, - }); - providerProductId = stripeProduct.id; - } else { - await client.products.update(providerProductId, { name: data.name }); - } - - if (data.existingProviderPriceId) { - return { providerPriceId: data.existingProviderPriceId, providerProductId }; - } - - const priceParams: StripeSdk.PriceCreateParams = { - currency, - product: providerProductId, - unit_amount: data.priceAmount, - }; - if (data.priceInterval) { - priceParams.recurring = { - interval: data.priceInterval as "month" | "year", - }; - } - const stripePrice = await client.prices.create(priceParams); + async syncProducts(data) { + const results = await Promise.all( + data.products.map(async (product) => { + let productId = product.existingProviderProduct?.productId ?? null; + if (!productId) { + const stripeProduct = await client.products.create({ + metadata: { paykit_product_id: product.id }, + name: product.name, + }); + productId = stripeProduct.id; + } else { + await client.products.update(productId, { name: product.name }); + } + + const existingPriceId = product.existingProviderProduct?.priceId ?? null; + if (existingPriceId) { + return { id: product.id, providerProduct: { productId, priceId: existingPriceId } }; + } + + const priceParams: StripeSdk.PriceCreateParams = { + currency, + product: productId, + unit_amount: product.priceAmount, + }; + if (product.priceInterval) { + priceParams.recurring = { + interval: product.priceInterval as "month" | "year", + }; + } + const stripePrice = await client.prices.create(priceParams); + + return { id: product.id, providerProduct: { productId, priceId: stripePrice.id } }; + }), + ); - return { providerPriceId: stripePrice.id, providerProductId }; + return { results }; }, async createInvoice(data) { diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index c054820c..0be75091 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -59,6 +59,9 @@ importers: '@paykitjs/dash': specifier: workspace:^ version: link:../../packages/dash + '@paykitjs/polar': + specifier: workspace:* + version: link:../../packages/polar '@paykitjs/stripe': specifier: workspace:* version: link:../../packages/stripe @@ -201,9 +204,15 @@ importers: e2e: devDependencies: + '@paykitjs/polar': + specifier: workspace:* + version: link:../packages/polar '@paykitjs/stripe': specifier: workspace:* version: link:../packages/stripe + '@t3-oss/env-core': + specifier: ^0.12.0 + version: 0.12.0(typescript@5.9.3)(valibot@1.2.0(typescript@5.9.3))(zod@4.3.6) '@types/pg': specifier: ^8.18.0 version: 8.18.0 @@ -219,12 +228,18 @@ importers: pg: specifier: ^8.20.0 version: 8.20.0 + playwright: + specifier: ^1.52.0 + version: 1.59.1 stripe: specifier: ^19.1.0 version: 19.3.1(@types/node@25.3.0) vitest: specifier: ^4.0.18 version: 4.0.18(@opentelemetry/api@1.9.0)(@types/node@25.3.0)(jiti@2.6.1)(jsdom@28.1.0(@noble/hashes@2.0.1))(lightningcss@1.32.0)(msw@2.12.10(@types/node@25.3.0)(typescript@5.9.3))(tsx@4.21.0)(yaml@2.8.2) + zod: + specifier: ^4.0.0 + version: 4.3.6 landing: dependencies: @@ -269,7 +284,7 @@ importers: version: 16.7.11(@mdx-js/mdx@3.1.1)(@tanstack/react-router@1.166.2(react-dom@19.2.5(react@19.2.5))(react@19.2.5))(@types/estree-jsx@1.0.5)(@types/hast@3.0.4)(@types/mdast@4.0.4)(@types/react@19.2.14)(lucide-react@0.575.0(react@19.2.5))(next@16.2.3(@babel/core@7.29.0)(@opentelemetry/api@1.9.0)(react-dom@19.2.5(react@19.2.5))(react@19.2.5))(react-dom@19.2.5(react@19.2.5))(react@19.2.5)(zod@3.25.76) fumadocs-mdx: specifier: ^14.2.11 - version: 14.2.11(@types/mdast@4.0.4)(@types/mdx@2.0.13)(@types/react@19.2.14)(fumadocs-core@16.7.11(@mdx-js/mdx@3.1.1)(@tanstack/react-router@1.166.2(react-dom@19.2.5(react@19.2.5))(react@19.2.5))(@types/estree-jsx@1.0.5)(@types/hast@3.0.4)(@types/mdast@4.0.4)(@types/react@19.2.14)(lucide-react@0.575.0(react@19.2.5))(next@16.2.3(@babel/core@7.29.0)(@opentelemetry/api@1.9.0)(react-dom@19.2.5(react@19.2.5))(react@19.2.5))(react-dom@19.2.5(react@19.2.5))(react@19.2.5)(zod@3.25.76))(next@16.2.3(@babel/core@7.29.0)(@opentelemetry/api@1.9.0)(react-dom@19.2.5(react@19.2.5))(react@19.2.5))(react@19.2.5)(vite@8.0.3(@types/node@20.19.34)(esbuild@0.27.3)(jiti@2.6.1)(tsx@4.21.0)(yaml@2.8.2)) + version: 14.2.11(@types/mdast@4.0.4)(@types/mdx@2.0.13)(@types/react@19.2.14)(fumadocs-core@16.7.11(@mdx-js/mdx@3.1.1)(@tanstack/react-router@1.166.2(react-dom@19.2.5(react@19.2.5))(react@19.2.5))(@types/estree-jsx@1.0.5)(@types/hast@3.0.4)(@types/mdast@4.0.4)(@types/react@19.2.14)(lucide-react@0.575.0(react@19.2.5))(next@16.2.3(@babel/core@7.29.0)(@opentelemetry/api@1.9.0)(react-dom@19.2.5(react@19.2.5))(react@19.2.5))(react-dom@19.2.5(react@19.2.5))(react@19.2.5)(zod@3.25.76))(next@16.2.3(@babel/core@7.29.0)(@opentelemetry/api@1.9.0)(react-dom@19.2.5(react@19.2.5))(react@19.2.5))(react@19.2.5) fumadocs-ui: specifier: ^16.7.11 version: 16.7.11(@emnapi/core@1.8.1)(@emnapi/runtime@1.8.1)(@types/mdx@2.0.13)(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(fumadocs-core@16.7.11(@mdx-js/mdx@3.1.1)(@tanstack/react-router@1.166.2(react-dom@19.2.5(react@19.2.5))(react@19.2.5))(@types/estree-jsx@1.0.5)(@types/hast@3.0.4)(@types/mdast@4.0.4)(@types/react@19.2.14)(lucide-react@0.575.0(react@19.2.5))(next@16.2.3(@babel/core@7.29.0)(@opentelemetry/api@1.9.0)(react-dom@19.2.5(react@19.2.5))(react@19.2.5))(react-dom@19.2.5(react@19.2.5))(react@19.2.5)(zod@3.25.76))(next@16.2.3(@babel/core@7.29.0)(@opentelemetry/api@1.9.0)(react-dom@19.2.5(react@19.2.5))(react@19.2.5))(react-dom@19.2.5(react@19.2.5))(react@19.2.5)(shiki@4.0.0)(tailwindcss@4.2.1) @@ -475,6 +490,25 @@ importers: specifier: ^4.0.18 version: 4.0.18(@opentelemetry/api@1.9.0)(@types/node@25.3.0)(jiti@2.6.1)(jsdom@28.1.0(@noble/hashes@2.0.1))(lightningcss@1.32.0)(msw@2.12.10(@types/node@25.3.0)(typescript@5.9.2))(tsx@4.21.0)(yaml@2.8.2) + packages/polar: + dependencies: + '@polar-sh/sdk': + specifier: ^0.47.0 + version: 0.47.0 + paykitjs: + specifier: workspace:* + version: link:../paykit + devDependencies: + tsdown: + specifier: ^0.21.1 + version: 0.21.1(oxc-resolver@11.19.1(@emnapi/core@1.8.1)(@emnapi/runtime@1.8.1))(typescript@5.9.3) + typescript: + specifier: ^5.9.2 + version: 5.9.3 + vitest: + specifier: ^4.0.18 + version: 4.0.18(@opentelemetry/api@1.9.0)(@types/node@25.3.0)(jiti@2.6.1)(jsdom@28.1.0(@noble/hashes@2.0.1))(lightningcss@1.32.0)(msw@2.12.10(@types/node@25.3.0)(typescript@5.9.3))(tsx@4.21.0)(yaml@2.8.2) + packages/stripe: dependencies: paykitjs: @@ -497,7 +531,7 @@ importers: packages: '@acemir/cssom@0.9.31': - resolution: {integrity: sha512-ZnR3GSaH+/vJ0YlHau21FjfLYjMpYVIzTD8M8vIEQvIGxeOXyXdzCI140rrCY862p/C/BbzWsjc1dgnM9mkoTA==} + resolution: {integrity: sha512-ZnR3GSaH+/vJ0YlHau21FjfLYjMpYVIzTD8M8vIEQvIGxeOXyXdzCI140rrCY862p/C/BbzWsjc1dgnM9mkoTA==, tarball: https://registry.npmjs.org/@acemir/cssom/-/cssom-0.9.31.tgz} '@alcalzone/ansi-tokenize@0.2.5': resolution: {integrity: sha512-3NX/MpTdroi0aKz134A6RC2Gb2iXVECN4QaAXnvCIxxIm3C3AVB1mkUe8NaaiyvOpDfsrqWhYtj+Q6a62RrTsw==} @@ -508,14 +542,14 @@ packages: engines: {node: '>=10'} '@asamuzakjp/css-color@5.1.9': - resolution: {integrity: sha512-zd9c/Wdso6v1U7v6w3i/hbAr4K7NaSHImdpvmLt+Y9ea5BhilnIGNkfhOJ7FEIuPipAnE9tZeDOll05WDT0kgg==} + resolution: {integrity: sha512-zd9c/Wdso6v1U7v6w3i/hbAr4K7NaSHImdpvmLt+Y9ea5BhilnIGNkfhOJ7FEIuPipAnE9tZeDOll05WDT0kgg==, tarball: https://registry.npmjs.org/@asamuzakjp/css-color/-/css-color-5.1.9.tgz} engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0} '@asamuzakjp/dom-selector@6.8.1': - resolution: {integrity: sha512-MvRz1nCqW0fsy8Qz4dnLIvhOlMzqDVBabZx6lH+YywFDdjXhMY37SmpV1XFX3JzG5GWHn63j6HX6QPr3lZXHvQ==} + resolution: {integrity: sha512-MvRz1nCqW0fsy8Qz4dnLIvhOlMzqDVBabZx6lH+YywFDdjXhMY37SmpV1XFX3JzG5GWHn63j6HX6QPr3lZXHvQ==, tarball: https://registry.npmjs.org/@asamuzakjp/dom-selector/-/dom-selector-6.8.1.tgz} '@asamuzakjp/nwsapi@2.3.9': - resolution: {integrity: sha512-n8GuYSrI9bF7FFZ/SjhwevlHc8xaVlb/7HmHelnc/PZXBD2ZR49NnN9sMMuDdEGPeeRQ5d0hqlSlEpgCX3Wl0Q==} + resolution: {integrity: sha512-n8GuYSrI9bF7FFZ/SjhwevlHc8xaVlb/7HmHelnc/PZXBD2ZR49NnN9sMMuDdEGPeeRQ5d0hqlSlEpgCX3Wl0Q==, tarball: https://registry.npmjs.org/@asamuzakjp/nwsapi/-/nwsapi-2.3.9.tgz} '@babel/code-frame@7.29.0': resolution: {integrity: sha512-9NhCeYjq9+3uxgdtp20LSiJXJvN0FeCtNGpJxuMFZ1Kv3cWUNb6DOhJwUvcVCzKGR66cw4njwM6hrJLqgOwbcw==} @@ -778,71 +812,71 @@ packages: hasBin: true '@biomejs/cli-darwin-arm64@2.4.6': - resolution: {integrity: sha512-NW18GSyxr+8sJIqgoGwVp5Zqm4SALH4b4gftIA0n62PTuBs6G2tHlwNAOj0Vq0KKSs7Sf88VjjmHh0O36EnzrQ==} + resolution: {integrity: sha512-NW18GSyxr+8sJIqgoGwVp5Zqm4SALH4b4gftIA0n62PTuBs6G2tHlwNAOj0Vq0KKSs7Sf88VjjmHh0O36EnzrQ==, tarball: https://registry.npmjs.org/@biomejs/cli-darwin-arm64/-/cli-darwin-arm64-2.4.6.tgz} engines: {node: '>=14.21.3'} cpu: [arm64] os: [darwin] '@biomejs/cli-darwin-x64@2.4.6': - resolution: {integrity: sha512-4uiE/9tuI7cnjtY9b07RgS7gGyYOAfIAGeVJWEfeCnAarOAS7qVmuRyX6d7JTKw28/mt+rUzMasYeZ+0R/U1Mw==} + resolution: {integrity: sha512-4uiE/9tuI7cnjtY9b07RgS7gGyYOAfIAGeVJWEfeCnAarOAS7qVmuRyX6d7JTKw28/mt+rUzMasYeZ+0R/U1Mw==, tarball: https://registry.npmjs.org/@biomejs/cli-darwin-x64/-/cli-darwin-x64-2.4.6.tgz} engines: {node: '>=14.21.3'} cpu: [x64] os: [darwin] '@biomejs/cli-linux-arm64-musl@2.4.6': - resolution: {integrity: sha512-F/JdB7eN22txiTqHM5KhIVt0jVkzZwVYrdTR1O3Y4auBOQcXxHK4dxULf4z43QyZI5tsnQJrRBHZy7wwtL+B3A==} + resolution: {integrity: sha512-F/JdB7eN22txiTqHM5KhIVt0jVkzZwVYrdTR1O3Y4auBOQcXxHK4dxULf4z43QyZI5tsnQJrRBHZy7wwtL+B3A==, tarball: https://registry.npmjs.org/@biomejs/cli-linux-arm64-musl/-/cli-linux-arm64-musl-2.4.6.tgz} engines: {node: '>=14.21.3'} cpu: [arm64] os: [linux] '@biomejs/cli-linux-arm64@2.4.6': - resolution: {integrity: sha512-kMLaI7OF5GN1Q8Doymjro1P8rVEoy7BKQALNz6fiR8IC1WKduoNyteBtJlHT7ASIL0Cx2jR6VUOBIbcB1B8pew==} + resolution: {integrity: sha512-kMLaI7OF5GN1Q8Doymjro1P8rVEoy7BKQALNz6fiR8IC1WKduoNyteBtJlHT7ASIL0Cx2jR6VUOBIbcB1B8pew==, tarball: https://registry.npmjs.org/@biomejs/cli-linux-arm64/-/cli-linux-arm64-2.4.6.tgz} engines: {node: '>=14.21.3'} cpu: [arm64] os: [linux] '@biomejs/cli-linux-x64-musl@2.4.6': - resolution: {integrity: sha512-C9s98IPDu7DYarjlZNuzJKTjVHN03RUnmHV5htvqsx6vEUXCDSJ59DNwjKVD5XYoSS4N+BYhq3RTBAL8X6svEg==} + resolution: {integrity: sha512-C9s98IPDu7DYarjlZNuzJKTjVHN03RUnmHV5htvqsx6vEUXCDSJ59DNwjKVD5XYoSS4N+BYhq3RTBAL8X6svEg==, tarball: https://registry.npmjs.org/@biomejs/cli-linux-x64-musl/-/cli-linux-x64-musl-2.4.6.tgz} engines: {node: '>=14.21.3'} cpu: [x64] os: [linux] '@biomejs/cli-linux-x64@2.4.6': - resolution: {integrity: sha512-oHXmUFEoH8Lql1xfc3QkFLiC1hGR7qedv5eKNlC185or+o4/4HiaU7vYODAH3peRCfsuLr1g6v2fK9dFFOYdyw==} + resolution: {integrity: sha512-oHXmUFEoH8Lql1xfc3QkFLiC1hGR7qedv5eKNlC185or+o4/4HiaU7vYODAH3peRCfsuLr1g6v2fK9dFFOYdyw==, tarball: https://registry.npmjs.org/@biomejs/cli-linux-x64/-/cli-linux-x64-2.4.6.tgz} engines: {node: '>=14.21.3'} cpu: [x64] os: [linux] '@biomejs/cli-win32-arm64@2.4.6': - resolution: {integrity: sha512-xzThn87Pf3YrOGTEODFGONmqXpTwUNxovQb72iaUOdcw8sBSY3+3WD8Hm9IhMYLnPi0n32s3L3NWU6+eSjfqFg==} + resolution: {integrity: sha512-xzThn87Pf3YrOGTEODFGONmqXpTwUNxovQb72iaUOdcw8sBSY3+3WD8Hm9IhMYLnPi0n32s3L3NWU6+eSjfqFg==, tarball: https://registry.npmjs.org/@biomejs/cli-win32-arm64/-/cli-win32-arm64-2.4.6.tgz} engines: {node: '>=14.21.3'} cpu: [arm64] os: [win32] '@biomejs/cli-win32-x64@2.4.6': - resolution: {integrity: sha512-7++XhnsPlr1HDbor5amovPjOH6vsrFOCdp93iKXhFn6bcMUI6soodj3WWKfgEO6JosKU1W5n3uky3WW9RlRjTg==} + resolution: {integrity: sha512-7++XhnsPlr1HDbor5amovPjOH6vsrFOCdp93iKXhFn6bcMUI6soodj3WWKfgEO6JosKU1W5n3uky3WW9RlRjTg==, tarball: https://registry.npmjs.org/@biomejs/cli-win32-x64/-/cli-win32-x64-2.4.6.tgz} engines: {node: '>=14.21.3'} cpu: [x64] os: [win32] '@borewit/text-codec@0.2.2': - resolution: {integrity: sha512-DDaRehssg1aNrH4+2hnj1B7vnUGEjU6OIlyRdkMd0aUdIUvKXrJfXsy8LVtXAy7DRvYVluWbMspsRhz2lcW0mQ==} + resolution: {integrity: sha512-DDaRehssg1aNrH4+2hnj1B7vnUGEjU6OIlyRdkMd0aUdIUvKXrJfXsy8LVtXAy7DRvYVluWbMspsRhz2lcW0mQ==, tarball: https://registry.npmjs.org/@borewit/text-codec/-/text-codec-0.2.2.tgz} '@bramus/specificity@2.4.2': - resolution: {integrity: sha512-ctxtJ/eA+t+6q2++vj5j7FYX3nRu311q1wfYH3xjlLOsczhlhxAg2FWNUXhpGvAw3BWo1xBcvOV6/YLc2r5FJw==} + resolution: {integrity: sha512-ctxtJ/eA+t+6q2++vj5j7FYX3nRu311q1wfYH3xjlLOsczhlhxAg2FWNUXhpGvAw3BWo1xBcvOV6/YLc2r5FJw==, tarball: https://registry.npmjs.org/@bramus/specificity/-/specificity-2.4.2.tgz} hasBin: true '@chevrotain/cst-dts-gen@10.5.0': - resolution: {integrity: sha512-lhmC/FyqQ2o7pGK4Om+hzuDrm9rhFYIJ/AXoQBeongmn870Xeb0L6oGEiuR8nohFNL5sMaQEJWCxr1oIVIVXrw==} + resolution: {integrity: sha512-lhmC/FyqQ2o7pGK4Om+hzuDrm9rhFYIJ/AXoQBeongmn870Xeb0L6oGEiuR8nohFNL5sMaQEJWCxr1oIVIVXrw==, tarball: https://registry.npmjs.org/@chevrotain/cst-dts-gen/-/cst-dts-gen-10.5.0.tgz} '@chevrotain/gast@10.5.0': - resolution: {integrity: sha512-pXdMJ9XeDAbgOWKuD1Fldz4ieCs6+nLNmyVhe2gZVqoO7v8HXuHYs5OV2EzUtbuai37TlOAQHrTDvxMnvMJz3A==} + resolution: {integrity: sha512-pXdMJ9XeDAbgOWKuD1Fldz4ieCs6+nLNmyVhe2gZVqoO7v8HXuHYs5OV2EzUtbuai37TlOAQHrTDvxMnvMJz3A==, tarball: https://registry.npmjs.org/@chevrotain/gast/-/gast-10.5.0.tgz} '@chevrotain/types@10.5.0': - resolution: {integrity: sha512-f1MAia0x/pAVPWH/T73BJVyO2XU5tI4/iE7cnxb7tqdNTNhQI3Uq3XkqcoteTmD4t1aM0LbHCJOhgIDn07kl2A==} + resolution: {integrity: sha512-f1MAia0x/pAVPWH/T73BJVyO2XU5tI4/iE7cnxb7tqdNTNhQI3Uq3XkqcoteTmD4t1aM0LbHCJOhgIDn07kl2A==, tarball: https://registry.npmjs.org/@chevrotain/types/-/types-10.5.0.tgz} '@chevrotain/utils@10.5.0': - resolution: {integrity: sha512-hBzuU5+JjB2cqNZyszkDHZgOSrUUT8V3dhgRl8Q9Gp6dAj/H5+KILGjbhDpc3Iy9qmqlm/akuOI2ut9VUtzJxQ==} + resolution: {integrity: sha512-hBzuU5+JjB2cqNZyszkDHZgOSrUUT8V3dhgRl8Q9Gp6dAj/H5+KILGjbhDpc3Iy9qmqlm/akuOI2ut9VUtzJxQ==, tarball: https://registry.npmjs.org/@chevrotain/utils/-/utils-10.5.0.tgz} '@clack/core@1.1.0': resolution: {integrity: sha512-SVcm4Dqm2ukn64/8Gub2wnlA5nS2iWJyCkdNHcvNHPIeBTGojpdJ+9cZKwLfmqy7irD4N5qLteSilJlE0WLAtA==} @@ -851,31 +885,31 @@ packages: resolution: {integrity: sha512-pkqbPGtohJAvm4Dphs2M8xE29ggupihHdy1x84HNojZuMtFsHiUlRvqD24tM2+XmI+61LlfNceM3Wr7U5QES5g==} '@csstools/color-helpers@6.0.2': - resolution: {integrity: sha512-LMGQLS9EuADloEFkcTBR3BwV/CGHV7zyDxVRtVDTwdI2Ca4it0CCVTT9wCkxSgokjE5Ho41hEPgb8OEUwoXr6Q==} + resolution: {integrity: sha512-LMGQLS9EuADloEFkcTBR3BwV/CGHV7zyDxVRtVDTwdI2Ca4it0CCVTT9wCkxSgokjE5Ho41hEPgb8OEUwoXr6Q==, tarball: https://registry.npmjs.org/@csstools/color-helpers/-/color-helpers-6.0.2.tgz} engines: {node: '>=20.19.0'} '@csstools/css-calc@3.1.1': - resolution: {integrity: sha512-HJ26Z/vmsZQqs/o3a6bgKslXGFAungXGbinULZO3eMsOyNJHeBBZfup5FiZInOghgoM4Hwnmw+OgbJCNg1wwUQ==} + resolution: {integrity: sha512-HJ26Z/vmsZQqs/o3a6bgKslXGFAungXGbinULZO3eMsOyNJHeBBZfup5FiZInOghgoM4Hwnmw+OgbJCNg1wwUQ==, tarball: https://registry.npmjs.org/@csstools/css-calc/-/css-calc-3.1.1.tgz} 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==} + resolution: {integrity: sha512-0GEfbBLmTFf0dJlpsNU7zwxRIH0/BGEMuXLTCvFYxuL1tNhqzTbtnFICyJLTNK4a+RechKP75e7w42ClXSnJQw==, tarball: https://registry.npmjs.org/@csstools/css-color-parser/-/css-color-parser-4.0.2.tgz} 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==} + resolution: {integrity: sha512-+B87qS7fIG3L5h3qwJ/IFbjoVoOe/bpOdh9hAjXbvx0o8ImEmUsGXN0inFOnk2ChCFgqkkGFQ+TpM5rbhkKe4w==, tarball: https://registry.npmjs.org/@csstools/css-parser-algorithms/-/css-parser-algorithms-4.0.0.tgz} 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==} + resolution: {integrity: sha512-5GkLzz4prTIpoyeUiIu3iV6CSG3Plo7xRVOFPKI7FVEJ3mZ0A8SwK0XU3Gl7xAkiQ+mDyam+NNp875/C5y+jSA==, tarball: https://registry.npmjs.org/@csstools/css-syntax-patches-for-csstree/-/css-syntax-patches-for-csstree-1.1.2.tgz} peerDependencies: css-tree: ^3.2.1 peerDependenciesMeta: @@ -883,7 +917,7 @@ packages: optional: true '@csstools/css-tokenizer@4.0.0': - resolution: {integrity: sha512-QxULHAm7cNu72w97JUNCBFODFaXpbDg+dP8b/oWFAZ2MTRppA3U00Y2L1HqaS4J6yBqxwa/Y3nMBaxVKbB/NsA==} + resolution: {integrity: sha512-QxULHAm7cNu72w97JUNCBFODFaXpbDg+dP8b/oWFAZ2MTRppA3U00Y2L1HqaS4J6yBqxwa/Y3nMBaxVKbB/NsA==, tarball: https://registry.npmjs.org/@csstools/css-tokenizer/-/css-tokenizer-4.0.0.tgz} engines: {node: '>=20.19.0'} '@date-fns/tz@1.4.1': @@ -903,27 +937,27 @@ packages: '@noble/ciphers': ^1.0.0 '@electric-sql/pglite-socket@0.0.20': - resolution: {integrity: sha512-J5nLGsicnD9wJHnno9r+DGxfcZWh+YJMCe0q/aCgtG6XOm9Z7fKeite8IZSNXgZeGltSigM9U/vAWZQWdgcSFg==} + resolution: {integrity: sha512-J5nLGsicnD9wJHnno9r+DGxfcZWh+YJMCe0q/aCgtG6XOm9Z7fKeite8IZSNXgZeGltSigM9U/vAWZQWdgcSFg==, tarball: https://registry.npmjs.org/@electric-sql/pglite-socket/-/pglite-socket-0.0.20.tgz} hasBin: true peerDependencies: '@electric-sql/pglite': 0.3.15 '@electric-sql/pglite-tools@0.2.20': - resolution: {integrity: sha512-BK50ZnYa3IG7ztXhtgYf0Q7zijV32Iw1cYS8C+ThdQlwx12V5VZ9KRJ42y82Hyb4PkTxZQklVQA9JHyUlex33A==} + resolution: {integrity: sha512-BK50ZnYa3IG7ztXhtgYf0Q7zijV32Iw1cYS8C+ThdQlwx12V5VZ9KRJ42y82Hyb4PkTxZQklVQA9JHyUlex33A==, tarball: https://registry.npmjs.org/@electric-sql/pglite-tools/-/pglite-tools-0.2.20.tgz} peerDependencies: '@electric-sql/pglite': 0.3.15 '@electric-sql/pglite@0.3.15': - resolution: {integrity: sha512-Cj++n1Mekf9ETfdc16TlDi+cDDQF0W7EcbyRHYOAeZdsAe8M/FJg18itDTSwyHfar2WIezawM9o0EKaRGVKygQ==} + resolution: {integrity: sha512-Cj++n1Mekf9ETfdc16TlDi+cDDQF0W7EcbyRHYOAeZdsAe8M/FJg18itDTSwyHfar2WIezawM9o0EKaRGVKygQ==, tarball: https://registry.npmjs.org/@electric-sql/pglite/-/pglite-0.3.15.tgz} '@emnapi/core@1.8.1': - resolution: {integrity: sha512-AvT9QFpxK0Zd8J0jopedNm+w/2fIzvtPKPjqyw9jwvBaReTTqPBk9Hixaz7KbjimP+QNz605/XnjFcDAL2pqBg==} + resolution: {integrity: sha512-AvT9QFpxK0Zd8J0jopedNm+w/2fIzvtPKPjqyw9jwvBaReTTqPBk9Hixaz7KbjimP+QNz605/XnjFcDAL2pqBg==, tarball: https://registry.npmjs.org/@emnapi/core/-/core-1.8.1.tgz} '@emnapi/runtime@1.8.1': - resolution: {integrity: sha512-mehfKSMWjjNol8659Z8KxEMrdSJDDot5SXMq00dM8BN4o+CLNXQ0xH2V7EchNHV4RmbZLmmPdEaXZc5H2FXmDg==} + resolution: {integrity: sha512-mehfKSMWjjNol8659Z8KxEMrdSJDDot5SXMq00dM8BN4o+CLNXQ0xH2V7EchNHV4RmbZLmmPdEaXZc5H2FXmDg==, tarball: https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.8.1.tgz} '@emnapi/wasi-threads@1.1.0': - resolution: {integrity: sha512-WI0DdZ8xFSbgMjR1sFsKABJ/C5OnRrjT06JXbZKexJGrDuPTzZdDYfFlsgcCXCyf+suG5QU2e/y1Wo2V/OapLQ==} + resolution: {integrity: sha512-WI0DdZ8xFSbgMjR1sFsKABJ/C5OnRrjT06JXbZKexJGrDuPTzZdDYfFlsgcCXCyf+suG5QU2e/y1Wo2V/OapLQ==, tarball: https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.1.0.tgz} '@esbuild-kit/core-utils@3.3.2': resolution: {integrity: sha512-sPRAnw9CdSsRmEtnsl2WXWdyquogVpB3yZ3dgwJfe8zrOzTsV7cJvmwrKVa+0ma5BoiGJ+BoqkMvawbayKUsqQ==} @@ -934,451 +968,451 @@ packages: deprecated: 'Merged into tsx: https://tsx.is' '@esbuild/aix-ppc64@0.25.12': - resolution: {integrity: sha512-Hhmwd6CInZ3dwpuGTF8fJG6yoWmsToE+vYgD4nytZVxcu1ulHpUQRAB1UJ8+N1Am3Mz4+xOByoQoSZf4D+CpkA==} + resolution: {integrity: sha512-Hhmwd6CInZ3dwpuGTF8fJG6yoWmsToE+vYgD4nytZVxcu1ulHpUQRAB1UJ8+N1Am3Mz4+xOByoQoSZf4D+CpkA==, tarball: https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.12.tgz} engines: {node: '>=18'} cpu: [ppc64] os: [aix] '@esbuild/aix-ppc64@0.27.3': - resolution: {integrity: sha512-9fJMTNFTWZMh5qwrBItuziu834eOCUcEqymSH7pY+zoMVEZg3gcPuBNxH1EvfVYe9h0x/Ptw8KBzv7qxb7l8dg==} + resolution: {integrity: sha512-9fJMTNFTWZMh5qwrBItuziu834eOCUcEqymSH7pY+zoMVEZg3gcPuBNxH1EvfVYe9h0x/Ptw8KBzv7qxb7l8dg==, tarball: https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.27.3.tgz} engines: {node: '>=18'} cpu: [ppc64] os: [aix] '@esbuild/android-arm64@0.18.20': - resolution: {integrity: sha512-Nz4rJcchGDtENV0eMKUNa6L12zz2zBDXuhj/Vjh18zGqB44Bi7MBMSXjgunJgjRhCmKOjnPuZp4Mb6OKqtMHLQ==} + resolution: {integrity: sha512-Nz4rJcchGDtENV0eMKUNa6L12zz2zBDXuhj/Vjh18zGqB44Bi7MBMSXjgunJgjRhCmKOjnPuZp4Mb6OKqtMHLQ==, tarball: https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.18.20.tgz} engines: {node: '>=12'} cpu: [arm64] os: [android] '@esbuild/android-arm64@0.25.12': - resolution: {integrity: sha512-6AAmLG7zwD1Z159jCKPvAxZd4y/VTO0VkprYy+3N2FtJ8+BQWFXU+OxARIwA46c5tdD9SsKGZ/1ocqBS/gAKHg==} + resolution: {integrity: sha512-6AAmLG7zwD1Z159jCKPvAxZd4y/VTO0VkprYy+3N2FtJ8+BQWFXU+OxARIwA46c5tdD9SsKGZ/1ocqBS/gAKHg==, tarball: https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.12.tgz} engines: {node: '>=18'} cpu: [arm64] os: [android] '@esbuild/android-arm64@0.27.3': - resolution: {integrity: sha512-YdghPYUmj/FX2SYKJ0OZxf+iaKgMsKHVPF1MAq/P8WirnSpCStzKJFjOjzsW0QQ7oIAiccHdcqjbHmJxRb/dmg==} + resolution: {integrity: sha512-YdghPYUmj/FX2SYKJ0OZxf+iaKgMsKHVPF1MAq/P8WirnSpCStzKJFjOjzsW0QQ7oIAiccHdcqjbHmJxRb/dmg==, tarball: https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.27.3.tgz} engines: {node: '>=18'} cpu: [arm64] os: [android] '@esbuild/android-arm@0.18.20': - resolution: {integrity: sha512-fyi7TDI/ijKKNZTUJAQqiG5T7YjJXgnzkURqmGj13C6dCqckZBLdl4h7bkhHt/t0WP+zO9/zwroDvANaOqO5Sw==} + resolution: {integrity: sha512-fyi7TDI/ijKKNZTUJAQqiG5T7YjJXgnzkURqmGj13C6dCqckZBLdl4h7bkhHt/t0WP+zO9/zwroDvANaOqO5Sw==, tarball: https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.18.20.tgz} engines: {node: '>=12'} cpu: [arm] os: [android] '@esbuild/android-arm@0.25.12': - resolution: {integrity: sha512-VJ+sKvNA/GE7Ccacc9Cha7bpS8nyzVv0jdVgwNDaR4gDMC/2TTRc33Ip8qrNYUcpkOHUT5OZ0bUcNNVZQ9RLlg==} + resolution: {integrity: sha512-VJ+sKvNA/GE7Ccacc9Cha7bpS8nyzVv0jdVgwNDaR4gDMC/2TTRc33Ip8qrNYUcpkOHUT5OZ0bUcNNVZQ9RLlg==, tarball: https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.12.tgz} engines: {node: '>=18'} cpu: [arm] os: [android] '@esbuild/android-arm@0.27.3': - resolution: {integrity: sha512-i5D1hPY7GIQmXlXhs2w8AWHhenb00+GxjxRncS2ZM7YNVGNfaMxgzSGuO8o8SJzRc/oZwU2bcScvVERk03QhzA==} + resolution: {integrity: sha512-i5D1hPY7GIQmXlXhs2w8AWHhenb00+GxjxRncS2ZM7YNVGNfaMxgzSGuO8o8SJzRc/oZwU2bcScvVERk03QhzA==, tarball: https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.27.3.tgz} engines: {node: '>=18'} cpu: [arm] os: [android] '@esbuild/android-x64@0.18.20': - resolution: {integrity: sha512-8GDdlePJA8D6zlZYJV/jnrRAi6rOiNaCC/JclcXpB+KIuvfBN4owLtgzY2bsxnx666XjJx2kDPUmnTtR8qKQUg==} + resolution: {integrity: sha512-8GDdlePJA8D6zlZYJV/jnrRAi6rOiNaCC/JclcXpB+KIuvfBN4owLtgzY2bsxnx666XjJx2kDPUmnTtR8qKQUg==, tarball: https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.18.20.tgz} engines: {node: '>=12'} cpu: [x64] os: [android] '@esbuild/android-x64@0.25.12': - resolution: {integrity: sha512-5jbb+2hhDHx5phYR2By8GTWEzn6I9UqR11Kwf22iKbNpYrsmRB18aX/9ivc5cabcUiAT/wM+YIZ6SG9QO6a8kg==} + resolution: {integrity: sha512-5jbb+2hhDHx5phYR2By8GTWEzn6I9UqR11Kwf22iKbNpYrsmRB18aX/9ivc5cabcUiAT/wM+YIZ6SG9QO6a8kg==, tarball: https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.12.tgz} engines: {node: '>=18'} cpu: [x64] os: [android] '@esbuild/android-x64@0.27.3': - resolution: {integrity: sha512-IN/0BNTkHtk8lkOM8JWAYFg4ORxBkZQf9zXiEOfERX/CzxW3Vg1ewAhU7QSWQpVIzTW+b8Xy+lGzdYXV6UZObQ==} + resolution: {integrity: sha512-IN/0BNTkHtk8lkOM8JWAYFg4ORxBkZQf9zXiEOfERX/CzxW3Vg1ewAhU7QSWQpVIzTW+b8Xy+lGzdYXV6UZObQ==, tarball: https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.27.3.tgz} engines: {node: '>=18'} cpu: [x64] os: [android] '@esbuild/darwin-arm64@0.18.20': - resolution: {integrity: sha512-bxRHW5kHU38zS2lPTPOyuyTm+S+eobPUnTNkdJEfAddYgEcll4xkT8DB9d2008DtTbl7uJag2HuE5NZAZgnNEA==} + resolution: {integrity: sha512-bxRHW5kHU38zS2lPTPOyuyTm+S+eobPUnTNkdJEfAddYgEcll4xkT8DB9d2008DtTbl7uJag2HuE5NZAZgnNEA==, tarball: https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.18.20.tgz} engines: {node: '>=12'} cpu: [arm64] os: [darwin] '@esbuild/darwin-arm64@0.25.12': - resolution: {integrity: sha512-N3zl+lxHCifgIlcMUP5016ESkeQjLj/959RxxNYIthIg+CQHInujFuXeWbWMgnTo4cp5XVHqFPmpyu9J65C1Yg==} + resolution: {integrity: sha512-N3zl+lxHCifgIlcMUP5016ESkeQjLj/959RxxNYIthIg+CQHInujFuXeWbWMgnTo4cp5XVHqFPmpyu9J65C1Yg==, tarball: https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.12.tgz} engines: {node: '>=18'} cpu: [arm64] os: [darwin] '@esbuild/darwin-arm64@0.27.3': - resolution: {integrity: sha512-Re491k7ByTVRy0t3EKWajdLIr0gz2kKKfzafkth4Q8A5n1xTHrkqZgLLjFEHVD+AXdUGgQMq+Godfq45mGpCKg==} + resolution: {integrity: sha512-Re491k7ByTVRy0t3EKWajdLIr0gz2kKKfzafkth4Q8A5n1xTHrkqZgLLjFEHVD+AXdUGgQMq+Godfq45mGpCKg==, tarball: https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.27.3.tgz} engines: {node: '>=18'} cpu: [arm64] os: [darwin] '@esbuild/darwin-x64@0.18.20': - resolution: {integrity: sha512-pc5gxlMDxzm513qPGbCbDukOdsGtKhfxD1zJKXjCCcU7ju50O7MeAZ8c4krSJcOIJGFR+qx21yMMVYwiQvyTyQ==} + resolution: {integrity: sha512-pc5gxlMDxzm513qPGbCbDukOdsGtKhfxD1zJKXjCCcU7ju50O7MeAZ8c4krSJcOIJGFR+qx21yMMVYwiQvyTyQ==, tarball: https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.18.20.tgz} engines: {node: '>=12'} cpu: [x64] os: [darwin] '@esbuild/darwin-x64@0.25.12': - resolution: {integrity: sha512-HQ9ka4Kx21qHXwtlTUVbKJOAnmG1ipXhdWTmNXiPzPfWKpXqASVcWdnf2bnL73wgjNrFXAa3yYvBSd9pzfEIpA==} + resolution: {integrity: sha512-HQ9ka4Kx21qHXwtlTUVbKJOAnmG1ipXhdWTmNXiPzPfWKpXqASVcWdnf2bnL73wgjNrFXAa3yYvBSd9pzfEIpA==, tarball: https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.12.tgz} engines: {node: '>=18'} cpu: [x64] os: [darwin] '@esbuild/darwin-x64@0.27.3': - resolution: {integrity: sha512-vHk/hA7/1AckjGzRqi6wbo+jaShzRowYip6rt6q7VYEDX4LEy1pZfDpdxCBnGtl+A5zq8iXDcyuxwtv3hNtHFg==} + resolution: {integrity: sha512-vHk/hA7/1AckjGzRqi6wbo+jaShzRowYip6rt6q7VYEDX4LEy1pZfDpdxCBnGtl+A5zq8iXDcyuxwtv3hNtHFg==, tarball: https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.27.3.tgz} engines: {node: '>=18'} cpu: [x64] os: [darwin] '@esbuild/freebsd-arm64@0.18.20': - resolution: {integrity: sha512-yqDQHy4QHevpMAaxhhIwYPMv1NECwOvIpGCZkECn8w2WFHXjEwrBn3CeNIYsibZ/iZEUemj++M26W3cNR5h+Tw==} + resolution: {integrity: sha512-yqDQHy4QHevpMAaxhhIwYPMv1NECwOvIpGCZkECn8w2WFHXjEwrBn3CeNIYsibZ/iZEUemj++M26W3cNR5h+Tw==, tarball: https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.18.20.tgz} engines: {node: '>=12'} cpu: [arm64] os: [freebsd] '@esbuild/freebsd-arm64@0.25.12': - resolution: {integrity: sha512-gA0Bx759+7Jve03K1S0vkOu5Lg/85dou3EseOGUes8flVOGxbhDDh/iZaoek11Y8mtyKPGF3vP8XhnkDEAmzeg==} + resolution: {integrity: sha512-gA0Bx759+7Jve03K1S0vkOu5Lg/85dou3EseOGUes8flVOGxbhDDh/iZaoek11Y8mtyKPGF3vP8XhnkDEAmzeg==, tarball: https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.12.tgz} engines: {node: '>=18'} cpu: [arm64] os: [freebsd] '@esbuild/freebsd-arm64@0.27.3': - resolution: {integrity: sha512-ipTYM2fjt3kQAYOvo6vcxJx3nBYAzPjgTCk7QEgZG8AUO3ydUhvelmhrbOheMnGOlaSFUoHXB6un+A7q4ygY9w==} + resolution: {integrity: sha512-ipTYM2fjt3kQAYOvo6vcxJx3nBYAzPjgTCk7QEgZG8AUO3ydUhvelmhrbOheMnGOlaSFUoHXB6un+A7q4ygY9w==, tarball: https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.27.3.tgz} engines: {node: '>=18'} cpu: [arm64] os: [freebsd] '@esbuild/freebsd-x64@0.18.20': - resolution: {integrity: sha512-tgWRPPuQsd3RmBZwarGVHZQvtzfEBOreNuxEMKFcd5DaDn2PbBxfwLcj4+aenoh7ctXcbXmOQIn8HI6mCSw5MQ==} + resolution: {integrity: sha512-tgWRPPuQsd3RmBZwarGVHZQvtzfEBOreNuxEMKFcd5DaDn2PbBxfwLcj4+aenoh7ctXcbXmOQIn8HI6mCSw5MQ==, tarball: https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.18.20.tgz} engines: {node: '>=12'} cpu: [x64] os: [freebsd] '@esbuild/freebsd-x64@0.25.12': - resolution: {integrity: sha512-TGbO26Yw2xsHzxtbVFGEXBFH0FRAP7gtcPE7P5yP7wGy7cXK2oO7RyOhL5NLiqTlBh47XhmIUXuGciXEqYFfBQ==} + resolution: {integrity: sha512-TGbO26Yw2xsHzxtbVFGEXBFH0FRAP7gtcPE7P5yP7wGy7cXK2oO7RyOhL5NLiqTlBh47XhmIUXuGciXEqYFfBQ==, tarball: https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.12.tgz} engines: {node: '>=18'} cpu: [x64] os: [freebsd] '@esbuild/freebsd-x64@0.27.3': - resolution: {integrity: sha512-dDk0X87T7mI6U3K9VjWtHOXqwAMJBNN2r7bejDsc+j03SEjtD9HrOl8gVFByeM0aJksoUuUVU9TBaZa2rgj0oA==} + resolution: {integrity: sha512-dDk0X87T7mI6U3K9VjWtHOXqwAMJBNN2r7bejDsc+j03SEjtD9HrOl8gVFByeM0aJksoUuUVU9TBaZa2rgj0oA==, tarball: https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.27.3.tgz} engines: {node: '>=18'} cpu: [x64] os: [freebsd] '@esbuild/linux-arm64@0.18.20': - resolution: {integrity: sha512-2YbscF+UL7SQAVIpnWvYwM+3LskyDmPhe31pE7/aoTMFKKzIc9lLbyGUpmmb8a8AixOL61sQ/mFh3jEjHYFvdA==} + resolution: {integrity: sha512-2YbscF+UL7SQAVIpnWvYwM+3LskyDmPhe31pE7/aoTMFKKzIc9lLbyGUpmmb8a8AixOL61sQ/mFh3jEjHYFvdA==, tarball: https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.18.20.tgz} engines: {node: '>=12'} cpu: [arm64] os: [linux] '@esbuild/linux-arm64@0.25.12': - resolution: {integrity: sha512-8bwX7a8FghIgrupcxb4aUmYDLp8pX06rGh5HqDT7bB+8Rdells6mHvrFHHW2JAOPZUbnjUpKTLg6ECyzvas2AQ==} + resolution: {integrity: sha512-8bwX7a8FghIgrupcxb4aUmYDLp8pX06rGh5HqDT7bB+8Rdells6mHvrFHHW2JAOPZUbnjUpKTLg6ECyzvas2AQ==, tarball: https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.12.tgz} engines: {node: '>=18'} cpu: [arm64] os: [linux] '@esbuild/linux-arm64@0.27.3': - resolution: {integrity: sha512-sZOuFz/xWnZ4KH3YfFrKCf1WyPZHakVzTiqji3WDc0BCl2kBwiJLCXpzLzUBLgmp4veFZdvN5ChW4Eq/8Fc2Fg==} + resolution: {integrity: sha512-sZOuFz/xWnZ4KH3YfFrKCf1WyPZHakVzTiqji3WDc0BCl2kBwiJLCXpzLzUBLgmp4veFZdvN5ChW4Eq/8Fc2Fg==, tarball: https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.27.3.tgz} engines: {node: '>=18'} cpu: [arm64] os: [linux] '@esbuild/linux-arm@0.18.20': - resolution: {integrity: sha512-/5bHkMWnq1EgKr1V+Ybz3s1hWXok7mDFUMQ4cG10AfW3wL02PSZi5kFpYKrptDsgb2WAJIvRcDm+qIvXf/apvg==} + resolution: {integrity: sha512-/5bHkMWnq1EgKr1V+Ybz3s1hWXok7mDFUMQ4cG10AfW3wL02PSZi5kFpYKrptDsgb2WAJIvRcDm+qIvXf/apvg==, tarball: https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.18.20.tgz} engines: {node: '>=12'} cpu: [arm] os: [linux] '@esbuild/linux-arm@0.25.12': - resolution: {integrity: sha512-lPDGyC1JPDou8kGcywY0YILzWlhhnRjdof3UlcoqYmS9El818LLfJJc3PXXgZHrHCAKs/Z2SeZtDJr5MrkxtOw==} + resolution: {integrity: sha512-lPDGyC1JPDou8kGcywY0YILzWlhhnRjdof3UlcoqYmS9El818LLfJJc3PXXgZHrHCAKs/Z2SeZtDJr5MrkxtOw==, tarball: https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.12.tgz} engines: {node: '>=18'} cpu: [arm] os: [linux] '@esbuild/linux-arm@0.27.3': - resolution: {integrity: sha512-s6nPv2QkSupJwLYyfS+gwdirm0ukyTFNl3KTgZEAiJDd+iHZcbTPPcWCcRYH+WlNbwChgH2QkE9NSlNrMT8Gfw==} + resolution: {integrity: sha512-s6nPv2QkSupJwLYyfS+gwdirm0ukyTFNl3KTgZEAiJDd+iHZcbTPPcWCcRYH+WlNbwChgH2QkE9NSlNrMT8Gfw==, tarball: https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.27.3.tgz} engines: {node: '>=18'} cpu: [arm] os: [linux] '@esbuild/linux-ia32@0.18.20': - resolution: {integrity: sha512-P4etWwq6IsReT0E1KHU40bOnzMHoH73aXp96Fs8TIT6z9Hu8G6+0SHSw9i2isWrD2nbx2qo5yUqACgdfVGx7TA==} + resolution: {integrity: sha512-P4etWwq6IsReT0E1KHU40bOnzMHoH73aXp96Fs8TIT6z9Hu8G6+0SHSw9i2isWrD2nbx2qo5yUqACgdfVGx7TA==, tarball: https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.18.20.tgz} engines: {node: '>=12'} cpu: [ia32] os: [linux] '@esbuild/linux-ia32@0.25.12': - resolution: {integrity: sha512-0y9KrdVnbMM2/vG8KfU0byhUN+EFCny9+8g202gYqSSVMonbsCfLjUO+rCci7pM0WBEtz+oK/PIwHkzxkyharA==} + resolution: {integrity: sha512-0y9KrdVnbMM2/vG8KfU0byhUN+EFCny9+8g202gYqSSVMonbsCfLjUO+rCci7pM0WBEtz+oK/PIwHkzxkyharA==, tarball: https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.12.tgz} engines: {node: '>=18'} cpu: [ia32] os: [linux] '@esbuild/linux-ia32@0.27.3': - resolution: {integrity: sha512-yGlQYjdxtLdh0a3jHjuwOrxQjOZYD/C9PfdbgJJF3TIZWnm/tMd/RcNiLngiu4iwcBAOezdnSLAwQDPqTmtTYg==} + resolution: {integrity: sha512-yGlQYjdxtLdh0a3jHjuwOrxQjOZYD/C9PfdbgJJF3TIZWnm/tMd/RcNiLngiu4iwcBAOezdnSLAwQDPqTmtTYg==, tarball: https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.27.3.tgz} engines: {node: '>=18'} cpu: [ia32] os: [linux] '@esbuild/linux-loong64@0.18.20': - resolution: {integrity: sha512-nXW8nqBTrOpDLPgPY9uV+/1DjxoQ7DoB2N8eocyq8I9XuqJ7BiAMDMf9n1xZM9TgW0J8zrquIb/A7s3BJv7rjg==} + resolution: {integrity: sha512-nXW8nqBTrOpDLPgPY9uV+/1DjxoQ7DoB2N8eocyq8I9XuqJ7BiAMDMf9n1xZM9TgW0J8zrquIb/A7s3BJv7rjg==, tarball: https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.18.20.tgz} engines: {node: '>=12'} cpu: [loong64] os: [linux] '@esbuild/linux-loong64@0.25.12': - resolution: {integrity: sha512-h///Lr5a9rib/v1GGqXVGzjL4TMvVTv+s1DPoxQdz7l/AYv6LDSxdIwzxkrPW438oUXiDtwM10o9PmwS/6Z0Ng==} + resolution: {integrity: sha512-h///Lr5a9rib/v1GGqXVGzjL4TMvVTv+s1DPoxQdz7l/AYv6LDSxdIwzxkrPW438oUXiDtwM10o9PmwS/6Z0Ng==, tarball: https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.12.tgz} engines: {node: '>=18'} cpu: [loong64] os: [linux] '@esbuild/linux-loong64@0.27.3': - resolution: {integrity: sha512-WO60Sn8ly3gtzhyjATDgieJNet/KqsDlX5nRC5Y3oTFcS1l0KWba+SEa9Ja1GfDqSF1z6hif/SkpQJbL63cgOA==} + resolution: {integrity: sha512-WO60Sn8ly3gtzhyjATDgieJNet/KqsDlX5nRC5Y3oTFcS1l0KWba+SEa9Ja1GfDqSF1z6hif/SkpQJbL63cgOA==, tarball: https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.27.3.tgz} engines: {node: '>=18'} cpu: [loong64] os: [linux] '@esbuild/linux-mips64el@0.18.20': - resolution: {integrity: sha512-d5NeaXZcHp8PzYy5VnXV3VSd2D328Zb+9dEq5HE6bw6+N86JVPExrA6O68OPwobntbNJ0pzCpUFZTo3w0GyetQ==} + resolution: {integrity: sha512-d5NeaXZcHp8PzYy5VnXV3VSd2D328Zb+9dEq5HE6bw6+N86JVPExrA6O68OPwobntbNJ0pzCpUFZTo3w0GyetQ==, tarball: https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.18.20.tgz} engines: {node: '>=12'} cpu: [mips64el] os: [linux] '@esbuild/linux-mips64el@0.25.12': - resolution: {integrity: sha512-iyRrM1Pzy9GFMDLsXn1iHUm18nhKnNMWscjmp4+hpafcZjrr2WbT//d20xaGljXDBYHqRcl8HnxbX6uaA/eGVw==} + resolution: {integrity: sha512-iyRrM1Pzy9GFMDLsXn1iHUm18nhKnNMWscjmp4+hpafcZjrr2WbT//d20xaGljXDBYHqRcl8HnxbX6uaA/eGVw==, tarball: https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.12.tgz} engines: {node: '>=18'} cpu: [mips64el] os: [linux] '@esbuild/linux-mips64el@0.27.3': - resolution: {integrity: sha512-APsymYA6sGcZ4pD6k+UxbDjOFSvPWyZhjaiPyl/f79xKxwTnrn5QUnXR5prvetuaSMsb4jgeHewIDCIWljrSxw==} + resolution: {integrity: sha512-APsymYA6sGcZ4pD6k+UxbDjOFSvPWyZhjaiPyl/f79xKxwTnrn5QUnXR5prvetuaSMsb4jgeHewIDCIWljrSxw==, tarball: https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.27.3.tgz} engines: {node: '>=18'} cpu: [mips64el] os: [linux] '@esbuild/linux-ppc64@0.18.20': - resolution: {integrity: sha512-WHPyeScRNcmANnLQkq6AfyXRFr5D6N2sKgkFo2FqguP44Nw2eyDlbTdZwd9GYk98DZG9QItIiTlFLHJHjxP3FA==} + resolution: {integrity: sha512-WHPyeScRNcmANnLQkq6AfyXRFr5D6N2sKgkFo2FqguP44Nw2eyDlbTdZwd9GYk98DZG9QItIiTlFLHJHjxP3FA==, tarball: https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.18.20.tgz} engines: {node: '>=12'} cpu: [ppc64] os: [linux] '@esbuild/linux-ppc64@0.25.12': - resolution: {integrity: sha512-9meM/lRXxMi5PSUqEXRCtVjEZBGwB7P/D4yT8UG/mwIdze2aV4Vo6U5gD3+RsoHXKkHCfSxZKzmDssVlRj1QQA==} + resolution: {integrity: sha512-9meM/lRXxMi5PSUqEXRCtVjEZBGwB7P/D4yT8UG/mwIdze2aV4Vo6U5gD3+RsoHXKkHCfSxZKzmDssVlRj1QQA==, tarball: https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.12.tgz} engines: {node: '>=18'} cpu: [ppc64] os: [linux] '@esbuild/linux-ppc64@0.27.3': - resolution: {integrity: sha512-eizBnTeBefojtDb9nSh4vvVQ3V9Qf9Df01PfawPcRzJH4gFSgrObw+LveUyDoKU3kxi5+9RJTCWlj4FjYXVPEA==} + resolution: {integrity: sha512-eizBnTeBefojtDb9nSh4vvVQ3V9Qf9Df01PfawPcRzJH4gFSgrObw+LveUyDoKU3kxi5+9RJTCWlj4FjYXVPEA==, tarball: https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.27.3.tgz} engines: {node: '>=18'} cpu: [ppc64] os: [linux] '@esbuild/linux-riscv64@0.18.20': - resolution: {integrity: sha512-WSxo6h5ecI5XH34KC7w5veNnKkju3zBRLEQNY7mv5mtBmrP/MjNBCAlsM2u5hDBlS3NGcTQpoBvRzqBcRtpq1A==} + resolution: {integrity: sha512-WSxo6h5ecI5XH34KC7w5veNnKkju3zBRLEQNY7mv5mtBmrP/MjNBCAlsM2u5hDBlS3NGcTQpoBvRzqBcRtpq1A==, tarball: https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.18.20.tgz} engines: {node: '>=12'} cpu: [riscv64] os: [linux] '@esbuild/linux-riscv64@0.25.12': - resolution: {integrity: sha512-Zr7KR4hgKUpWAwb1f3o5ygT04MzqVrGEGXGLnj15YQDJErYu/BGg+wmFlIDOdJp0PmB0lLvxFIOXZgFRrdjR0w==} + resolution: {integrity: sha512-Zr7KR4hgKUpWAwb1f3o5ygT04MzqVrGEGXGLnj15YQDJErYu/BGg+wmFlIDOdJp0PmB0lLvxFIOXZgFRrdjR0w==, tarball: https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.12.tgz} engines: {node: '>=18'} cpu: [riscv64] os: [linux] '@esbuild/linux-riscv64@0.27.3': - resolution: {integrity: sha512-3Emwh0r5wmfm3ssTWRQSyVhbOHvqegUDRd0WhmXKX2mkHJe1SFCMJhagUleMq+Uci34wLSipf8Lagt4LlpRFWQ==} + resolution: {integrity: sha512-3Emwh0r5wmfm3ssTWRQSyVhbOHvqegUDRd0WhmXKX2mkHJe1SFCMJhagUleMq+Uci34wLSipf8Lagt4LlpRFWQ==, tarball: https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.27.3.tgz} engines: {node: '>=18'} cpu: [riscv64] os: [linux] '@esbuild/linux-s390x@0.18.20': - resolution: {integrity: sha512-+8231GMs3mAEth6Ja1iK0a1sQ3ohfcpzpRLH8uuc5/KVDFneH6jtAJLFGafpzpMRO6DzJ6AvXKze9LfFMrIHVQ==} + resolution: {integrity: sha512-+8231GMs3mAEth6Ja1iK0a1sQ3ohfcpzpRLH8uuc5/KVDFneH6jtAJLFGafpzpMRO6DzJ6AvXKze9LfFMrIHVQ==, tarball: https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.18.20.tgz} engines: {node: '>=12'} cpu: [s390x] os: [linux] '@esbuild/linux-s390x@0.25.12': - resolution: {integrity: sha512-MsKncOcgTNvdtiISc/jZs/Zf8d0cl/t3gYWX8J9ubBnVOwlk65UIEEvgBORTiljloIWnBzLs4qhzPkJcitIzIg==} + resolution: {integrity: sha512-MsKncOcgTNvdtiISc/jZs/Zf8d0cl/t3gYWX8J9ubBnVOwlk65UIEEvgBORTiljloIWnBzLs4qhzPkJcitIzIg==, tarball: https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.12.tgz} engines: {node: '>=18'} cpu: [s390x] os: [linux] '@esbuild/linux-s390x@0.27.3': - resolution: {integrity: sha512-pBHUx9LzXWBc7MFIEEL0yD/ZVtNgLytvx60gES28GcWMqil8ElCYR4kvbV2BDqsHOvVDRrOxGySBM9Fcv744hw==} + resolution: {integrity: sha512-pBHUx9LzXWBc7MFIEEL0yD/ZVtNgLytvx60gES28GcWMqil8ElCYR4kvbV2BDqsHOvVDRrOxGySBM9Fcv744hw==, tarball: https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.27.3.tgz} engines: {node: '>=18'} cpu: [s390x] os: [linux] '@esbuild/linux-x64@0.18.20': - resolution: {integrity: sha512-UYqiqemphJcNsFEskc73jQ7B9jgwjWrSayxawS6UVFZGWrAAtkzjxSqnoclCXxWtfwLdzU+vTpcNYhpn43uP1w==} + resolution: {integrity: sha512-UYqiqemphJcNsFEskc73jQ7B9jgwjWrSayxawS6UVFZGWrAAtkzjxSqnoclCXxWtfwLdzU+vTpcNYhpn43uP1w==, tarball: https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.18.20.tgz} engines: {node: '>=12'} cpu: [x64] os: [linux] '@esbuild/linux-x64@0.25.12': - resolution: {integrity: sha512-uqZMTLr/zR/ed4jIGnwSLkaHmPjOjJvnm6TVVitAa08SLS9Z0VM8wIRx7gWbJB5/J54YuIMInDquWyYvQLZkgw==} + resolution: {integrity: sha512-uqZMTLr/zR/ed4jIGnwSLkaHmPjOjJvnm6TVVitAa08SLS9Z0VM8wIRx7gWbJB5/J54YuIMInDquWyYvQLZkgw==, tarball: https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.12.tgz} engines: {node: '>=18'} cpu: [x64] os: [linux] '@esbuild/linux-x64@0.27.3': - resolution: {integrity: sha512-Czi8yzXUWIQYAtL/2y6vogER8pvcsOsk5cpwL4Gk5nJqH5UZiVByIY8Eorm5R13gq+DQKYg0+JyQoytLQas4dA==} + resolution: {integrity: sha512-Czi8yzXUWIQYAtL/2y6vogER8pvcsOsk5cpwL4Gk5nJqH5UZiVByIY8Eorm5R13gq+DQKYg0+JyQoytLQas4dA==, tarball: https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.27.3.tgz} engines: {node: '>=18'} cpu: [x64] os: [linux] '@esbuild/netbsd-arm64@0.25.12': - resolution: {integrity: sha512-xXwcTq4GhRM7J9A8Gv5boanHhRa/Q9KLVmcyXHCTaM4wKfIpWkdXiMog/KsnxzJ0A1+nD+zoecuzqPmCRyBGjg==} + resolution: {integrity: sha512-xXwcTq4GhRM7J9A8Gv5boanHhRa/Q9KLVmcyXHCTaM4wKfIpWkdXiMog/KsnxzJ0A1+nD+zoecuzqPmCRyBGjg==, tarball: https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.12.tgz} engines: {node: '>=18'} cpu: [arm64] os: [netbsd] '@esbuild/netbsd-arm64@0.27.3': - resolution: {integrity: sha512-sDpk0RgmTCR/5HguIZa9n9u+HVKf40fbEUt+iTzSnCaGvY9kFP0YKBWZtJaraonFnqef5SlJ8/TiPAxzyS+UoA==} + resolution: {integrity: sha512-sDpk0RgmTCR/5HguIZa9n9u+HVKf40fbEUt+iTzSnCaGvY9kFP0YKBWZtJaraonFnqef5SlJ8/TiPAxzyS+UoA==, tarball: https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.27.3.tgz} engines: {node: '>=18'} cpu: [arm64] os: [netbsd] '@esbuild/netbsd-x64@0.18.20': - resolution: {integrity: sha512-iO1c++VP6xUBUmltHZoMtCUdPlnPGdBom6IrO4gyKPFFVBKioIImVooR5I83nTew5UOYrk3gIJhbZh8X44y06A==} + resolution: {integrity: sha512-iO1c++VP6xUBUmltHZoMtCUdPlnPGdBom6IrO4gyKPFFVBKioIImVooR5I83nTew5UOYrk3gIJhbZh8X44y06A==, tarball: https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.18.20.tgz} engines: {node: '>=12'} cpu: [x64] os: [netbsd] '@esbuild/netbsd-x64@0.25.12': - resolution: {integrity: sha512-Ld5pTlzPy3YwGec4OuHh1aCVCRvOXdH8DgRjfDy/oumVovmuSzWfnSJg+VtakB9Cm0gxNO9BzWkj6mtO1FMXkQ==} + resolution: {integrity: sha512-Ld5pTlzPy3YwGec4OuHh1aCVCRvOXdH8DgRjfDy/oumVovmuSzWfnSJg+VtakB9Cm0gxNO9BzWkj6mtO1FMXkQ==, tarball: https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.12.tgz} engines: {node: '>=18'} cpu: [x64] os: [netbsd] '@esbuild/netbsd-x64@0.27.3': - resolution: {integrity: sha512-P14lFKJl/DdaE00LItAukUdZO5iqNH7+PjoBm+fLQjtxfcfFE20Xf5CrLsmZdq5LFFZzb5JMZ9grUwvtVYzjiA==} + resolution: {integrity: sha512-P14lFKJl/DdaE00LItAukUdZO5iqNH7+PjoBm+fLQjtxfcfFE20Xf5CrLsmZdq5LFFZzb5JMZ9grUwvtVYzjiA==, tarball: https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.27.3.tgz} engines: {node: '>=18'} cpu: [x64] os: [netbsd] '@esbuild/openbsd-arm64@0.25.12': - resolution: {integrity: sha512-fF96T6KsBo/pkQI950FARU9apGNTSlZGsv1jZBAlcLL1MLjLNIWPBkj5NlSz8aAzYKg+eNqknrUJ24QBybeR5A==} + resolution: {integrity: sha512-fF96T6KsBo/pkQI950FARU9apGNTSlZGsv1jZBAlcLL1MLjLNIWPBkj5NlSz8aAzYKg+eNqknrUJ24QBybeR5A==, tarball: https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.12.tgz} engines: {node: '>=18'} cpu: [arm64] os: [openbsd] '@esbuild/openbsd-arm64@0.27.3': - resolution: {integrity: sha512-AIcMP77AvirGbRl/UZFTq5hjXK+2wC7qFRGoHSDrZ5v5b8DK/GYpXW3CPRL53NkvDqb9D+alBiC/dV0Fb7eJcw==} + resolution: {integrity: sha512-AIcMP77AvirGbRl/UZFTq5hjXK+2wC7qFRGoHSDrZ5v5b8DK/GYpXW3CPRL53NkvDqb9D+alBiC/dV0Fb7eJcw==, tarball: https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.27.3.tgz} engines: {node: '>=18'} cpu: [arm64] os: [openbsd] '@esbuild/openbsd-x64@0.18.20': - resolution: {integrity: sha512-e5e4YSsuQfX4cxcygw/UCPIEP6wbIL+se3sxPdCiMbFLBWu0eiZOJ7WoD+ptCLrmjZBK1Wk7I6D/I3NglUGOxg==} + resolution: {integrity: sha512-e5e4YSsuQfX4cxcygw/UCPIEP6wbIL+se3sxPdCiMbFLBWu0eiZOJ7WoD+ptCLrmjZBK1Wk7I6D/I3NglUGOxg==, tarball: https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.18.20.tgz} engines: {node: '>=12'} cpu: [x64] os: [openbsd] '@esbuild/openbsd-x64@0.25.12': - resolution: {integrity: sha512-MZyXUkZHjQxUvzK7rN8DJ3SRmrVrke8ZyRusHlP+kuwqTcfWLyqMOE3sScPPyeIXN/mDJIfGXvcMqCgYKekoQw==} + resolution: {integrity: sha512-MZyXUkZHjQxUvzK7rN8DJ3SRmrVrke8ZyRusHlP+kuwqTcfWLyqMOE3sScPPyeIXN/mDJIfGXvcMqCgYKekoQw==, tarball: https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.12.tgz} engines: {node: '>=18'} cpu: [x64] os: [openbsd] '@esbuild/openbsd-x64@0.27.3': - resolution: {integrity: sha512-DnW2sRrBzA+YnE70LKqnM3P+z8vehfJWHXECbwBmH/CU51z6FiqTQTHFenPlHmo3a8UgpLyH3PT+87OViOh1AQ==} + resolution: {integrity: sha512-DnW2sRrBzA+YnE70LKqnM3P+z8vehfJWHXECbwBmH/CU51z6FiqTQTHFenPlHmo3a8UgpLyH3PT+87OViOh1AQ==, tarball: https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.27.3.tgz} engines: {node: '>=18'} cpu: [x64] os: [openbsd] '@esbuild/openharmony-arm64@0.25.12': - resolution: {integrity: sha512-rm0YWsqUSRrjncSXGA7Zv78Nbnw4XL6/dzr20cyrQf7ZmRcsovpcRBdhD43Nuk3y7XIoW2OxMVvwuRvk9XdASg==} + resolution: {integrity: sha512-rm0YWsqUSRrjncSXGA7Zv78Nbnw4XL6/dzr20cyrQf7ZmRcsovpcRBdhD43Nuk3y7XIoW2OxMVvwuRvk9XdASg==, tarball: https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.25.12.tgz} engines: {node: '>=18'} cpu: [arm64] os: [openharmony] '@esbuild/openharmony-arm64@0.27.3': - resolution: {integrity: sha512-NinAEgr/etERPTsZJ7aEZQvvg/A6IsZG/LgZy+81wON2huV7SrK3e63dU0XhyZP4RKGyTm7aOgmQk0bGp0fy2g==} + resolution: {integrity: sha512-NinAEgr/etERPTsZJ7aEZQvvg/A6IsZG/LgZy+81wON2huV7SrK3e63dU0XhyZP4RKGyTm7aOgmQk0bGp0fy2g==, tarball: https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.27.3.tgz} engines: {node: '>=18'} cpu: [arm64] os: [openharmony] '@esbuild/sunos-x64@0.18.20': - resolution: {integrity: sha512-kDbFRFp0YpTQVVrqUd5FTYmWo45zGaXe0X8E1G/LKFC0v8x0vWrhOWSLITcCn63lmZIxfOMXtCfti/RxN/0wnQ==} + resolution: {integrity: sha512-kDbFRFp0YpTQVVrqUd5FTYmWo45zGaXe0X8E1G/LKFC0v8x0vWrhOWSLITcCn63lmZIxfOMXtCfti/RxN/0wnQ==, tarball: https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.18.20.tgz} engines: {node: '>=12'} cpu: [x64] os: [sunos] '@esbuild/sunos-x64@0.25.12': - resolution: {integrity: sha512-3wGSCDyuTHQUzt0nV7bocDy72r2lI33QL3gkDNGkod22EsYl04sMf0qLb8luNKTOmgF/eDEDP5BFNwoBKH441w==} + resolution: {integrity: sha512-3wGSCDyuTHQUzt0nV7bocDy72r2lI33QL3gkDNGkod22EsYl04sMf0qLb8luNKTOmgF/eDEDP5BFNwoBKH441w==, tarball: https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.12.tgz} engines: {node: '>=18'} cpu: [x64] os: [sunos] '@esbuild/sunos-x64@0.27.3': - resolution: {integrity: sha512-PanZ+nEz+eWoBJ8/f8HKxTTD172SKwdXebZ0ndd953gt1HRBbhMsaNqjTyYLGLPdoWHy4zLU7bDVJztF5f3BHA==} + resolution: {integrity: sha512-PanZ+nEz+eWoBJ8/f8HKxTTD172SKwdXebZ0ndd953gt1HRBbhMsaNqjTyYLGLPdoWHy4zLU7bDVJztF5f3BHA==, tarball: https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.27.3.tgz} engines: {node: '>=18'} cpu: [x64] os: [sunos] '@esbuild/win32-arm64@0.18.20': - resolution: {integrity: sha512-ddYFR6ItYgoaq4v4JmQQaAI5s7npztfV4Ag6NrhiaW0RrnOXqBkgwZLofVTlq1daVTQNhtI5oieTvkRPfZrePg==} + resolution: {integrity: sha512-ddYFR6ItYgoaq4v4JmQQaAI5s7npztfV4Ag6NrhiaW0RrnOXqBkgwZLofVTlq1daVTQNhtI5oieTvkRPfZrePg==, tarball: https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.18.20.tgz} engines: {node: '>=12'} cpu: [arm64] os: [win32] '@esbuild/win32-arm64@0.25.12': - resolution: {integrity: sha512-rMmLrur64A7+DKlnSuwqUdRKyd3UE7oPJZmnljqEptesKM8wx9J8gx5u0+9Pq0fQQW8vqeKebwNXdfOyP+8Bsg==} + resolution: {integrity: sha512-rMmLrur64A7+DKlnSuwqUdRKyd3UE7oPJZmnljqEptesKM8wx9J8gx5u0+9Pq0fQQW8vqeKebwNXdfOyP+8Bsg==, tarball: https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.12.tgz} engines: {node: '>=18'} cpu: [arm64] os: [win32] '@esbuild/win32-arm64@0.27.3': - resolution: {integrity: sha512-B2t59lWWYrbRDw/tjiWOuzSsFh1Y/E95ofKz7rIVYSQkUYBjfSgf6oeYPNWHToFRr2zx52JKApIcAS/D5TUBnA==} + resolution: {integrity: sha512-B2t59lWWYrbRDw/tjiWOuzSsFh1Y/E95ofKz7rIVYSQkUYBjfSgf6oeYPNWHToFRr2zx52JKApIcAS/D5TUBnA==, tarball: https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.27.3.tgz} engines: {node: '>=18'} cpu: [arm64] os: [win32] '@esbuild/win32-ia32@0.18.20': - resolution: {integrity: sha512-Wv7QBi3ID/rROT08SABTS7eV4hX26sVduqDOTe1MvGMjNd3EjOz4b7zeexIR62GTIEKrfJXKL9LFxTYgkyeu7g==} + resolution: {integrity: sha512-Wv7QBi3ID/rROT08SABTS7eV4hX26sVduqDOTe1MvGMjNd3EjOz4b7zeexIR62GTIEKrfJXKL9LFxTYgkyeu7g==, tarball: https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.18.20.tgz} engines: {node: '>=12'} cpu: [ia32] os: [win32] '@esbuild/win32-ia32@0.25.12': - resolution: {integrity: sha512-HkqnmmBoCbCwxUKKNPBixiWDGCpQGVsrQfJoVGYLPT41XWF8lHuE5N6WhVia2n4o5QK5M4tYr21827fNhi4byQ==} + resolution: {integrity: sha512-HkqnmmBoCbCwxUKKNPBixiWDGCpQGVsrQfJoVGYLPT41XWF8lHuE5N6WhVia2n4o5QK5M4tYr21827fNhi4byQ==, tarball: https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.12.tgz} engines: {node: '>=18'} cpu: [ia32] os: [win32] '@esbuild/win32-ia32@0.27.3': - resolution: {integrity: sha512-QLKSFeXNS8+tHW7tZpMtjlNb7HKau0QDpwm49u0vUp9y1WOF+PEzkU84y9GqYaAVW8aH8f3GcBck26jh54cX4Q==} + resolution: {integrity: sha512-QLKSFeXNS8+tHW7tZpMtjlNb7HKau0QDpwm49u0vUp9y1WOF+PEzkU84y9GqYaAVW8aH8f3GcBck26jh54cX4Q==, tarball: https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.27.3.tgz} engines: {node: '>=18'} cpu: [ia32] os: [win32] '@esbuild/win32-x64@0.18.20': - resolution: {integrity: sha512-kTdfRcSiDfQca/y9QIkng02avJ+NCaQvrMejlsB3RRv5sE9rRoeBPISaZpKxHELzRxZyLvNts1P27W3wV+8geQ==} + resolution: {integrity: sha512-kTdfRcSiDfQca/y9QIkng02avJ+NCaQvrMejlsB3RRv5sE9rRoeBPISaZpKxHELzRxZyLvNts1P27W3wV+8geQ==, tarball: https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.18.20.tgz} engines: {node: '>=12'} cpu: [x64] os: [win32] '@esbuild/win32-x64@0.25.12': - resolution: {integrity: sha512-alJC0uCZpTFrSL0CCDjcgleBXPnCrEAhTBILpeAp7M/OFgoqtAetfBzX0xM00MUsVVPpVjlPuMbREqnZCXaTnA==} + resolution: {integrity: sha512-alJC0uCZpTFrSL0CCDjcgleBXPnCrEAhTBILpeAp7M/OFgoqtAetfBzX0xM00MUsVVPpVjlPuMbREqnZCXaTnA==, tarball: https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.12.tgz} engines: {node: '>=18'} cpu: [x64] os: [win32] '@esbuild/win32-x64@0.27.3': - resolution: {integrity: sha512-4uJGhsxuptu3OcpVAzli+/gWusVGwZZHTlS63hh++ehExkVT8SgiEf7/uC/PclrPPkLhZqGgCTjd0VWLo6xMqA==} + resolution: {integrity: sha512-4uJGhsxuptu3OcpVAzli+/gWusVGwZZHTlS63hh++ehExkVT8SgiEf7/uC/PclrPPkLhZqGgCTjd0VWLo6xMqA==, tarball: https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.27.3.tgz} engines: {node: '>=18'} cpu: [x64] os: [win32] '@exodus/bytes@1.15.0': - resolution: {integrity: sha512-UY0nlA+feH81UGSHv92sLEPLCeZFjXOuHhrIo0HQydScuQc8s0A7kL/UdgwgDq8g8ilksmuoF35YVTNphV2aBQ==} + resolution: {integrity: sha512-UY0nlA+feH81UGSHv92sLEPLCeZFjXOuHhrIo0HQydScuQc8s0A7kL/UdgwgDq8g8ilksmuoF35YVTNphV2aBQ==, tarball: https://registry.npmjs.org/@exodus/bytes/-/bytes-1.15.0.tgz} engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0} peerDependencies: '@noble/hashes': ^1.8.0 || ^2.0.0 @@ -1437,134 +1471,134 @@ packages: engines: {node: '>=18'} '@img/sharp-darwin-arm64@0.34.5': - resolution: {integrity: sha512-imtQ3WMJXbMY4fxb/Ndp6HBTNVtWCUI0WdobyheGf5+ad6xX8VIDO8u2xE4qc/fr08CKG/7dDseFtn6M6g/r3w==} + resolution: {integrity: sha512-imtQ3WMJXbMY4fxb/Ndp6HBTNVtWCUI0WdobyheGf5+ad6xX8VIDO8u2xE4qc/fr08CKG/7dDseFtn6M6g/r3w==, tarball: https://registry.npmjs.org/@img/sharp-darwin-arm64/-/sharp-darwin-arm64-0.34.5.tgz} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} cpu: [arm64] os: [darwin] '@img/sharp-darwin-x64@0.34.5': - resolution: {integrity: sha512-YNEFAF/4KQ/PeW0N+r+aVVsoIY0/qxxikF2SWdp+NRkmMB7y9LBZAVqQ4yhGCm/H3H270OSykqmQMKLBhBJDEw==} + resolution: {integrity: sha512-YNEFAF/4KQ/PeW0N+r+aVVsoIY0/qxxikF2SWdp+NRkmMB7y9LBZAVqQ4yhGCm/H3H270OSykqmQMKLBhBJDEw==, tarball: https://registry.npmjs.org/@img/sharp-darwin-x64/-/sharp-darwin-x64-0.34.5.tgz} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} cpu: [x64] os: [darwin] '@img/sharp-libvips-darwin-arm64@1.2.4': - resolution: {integrity: sha512-zqjjo7RatFfFoP0MkQ51jfuFZBnVE2pRiaydKJ1G/rHZvnsrHAOcQALIi9sA5co5xenQdTugCvtb1cuf78Vf4g==} + resolution: {integrity: sha512-zqjjo7RatFfFoP0MkQ51jfuFZBnVE2pRiaydKJ1G/rHZvnsrHAOcQALIi9sA5co5xenQdTugCvtb1cuf78Vf4g==, tarball: https://registry.npmjs.org/@img/sharp-libvips-darwin-arm64/-/sharp-libvips-darwin-arm64-1.2.4.tgz} cpu: [arm64] os: [darwin] '@img/sharp-libvips-darwin-x64@1.2.4': - resolution: {integrity: sha512-1IOd5xfVhlGwX+zXv2N93k0yMONvUlANylbJw1eTah8K/Jtpi15KC+WSiaX/nBmbm2HxRM1gZ0nSdjSsrZbGKg==} + resolution: {integrity: sha512-1IOd5xfVhlGwX+zXv2N93k0yMONvUlANylbJw1eTah8K/Jtpi15KC+WSiaX/nBmbm2HxRM1gZ0nSdjSsrZbGKg==, tarball: https://registry.npmjs.org/@img/sharp-libvips-darwin-x64/-/sharp-libvips-darwin-x64-1.2.4.tgz} cpu: [x64] os: [darwin] '@img/sharp-libvips-linux-arm64@1.2.4': - resolution: {integrity: sha512-excjX8DfsIcJ10x1Kzr4RcWe1edC9PquDRRPx3YVCvQv+U5p7Yin2s32ftzikXojb1PIFc/9Mt28/y+iRklkrw==} + resolution: {integrity: sha512-excjX8DfsIcJ10x1Kzr4RcWe1edC9PquDRRPx3YVCvQv+U5p7Yin2s32ftzikXojb1PIFc/9Mt28/y+iRklkrw==, tarball: https://registry.npmjs.org/@img/sharp-libvips-linux-arm64/-/sharp-libvips-linux-arm64-1.2.4.tgz} cpu: [arm64] os: [linux] '@img/sharp-libvips-linux-arm@1.2.4': - resolution: {integrity: sha512-bFI7xcKFELdiNCVov8e44Ia4u2byA+l3XtsAj+Q8tfCwO6BQ8iDojYdvoPMqsKDkuoOo+X6HZA0s0q11ANMQ8A==} + resolution: {integrity: sha512-bFI7xcKFELdiNCVov8e44Ia4u2byA+l3XtsAj+Q8tfCwO6BQ8iDojYdvoPMqsKDkuoOo+X6HZA0s0q11ANMQ8A==, tarball: https://registry.npmjs.org/@img/sharp-libvips-linux-arm/-/sharp-libvips-linux-arm-1.2.4.tgz} cpu: [arm] os: [linux] '@img/sharp-libvips-linux-ppc64@1.2.4': - resolution: {integrity: sha512-FMuvGijLDYG6lW+b/UvyilUWu5Ayu+3r2d1S8notiGCIyYU/76eig1UfMmkZ7vwgOrzKzlQbFSuQfgm7GYUPpA==} + resolution: {integrity: sha512-FMuvGijLDYG6lW+b/UvyilUWu5Ayu+3r2d1S8notiGCIyYU/76eig1UfMmkZ7vwgOrzKzlQbFSuQfgm7GYUPpA==, tarball: https://registry.npmjs.org/@img/sharp-libvips-linux-ppc64/-/sharp-libvips-linux-ppc64-1.2.4.tgz} cpu: [ppc64] os: [linux] '@img/sharp-libvips-linux-riscv64@1.2.4': - resolution: {integrity: sha512-oVDbcR4zUC0ce82teubSm+x6ETixtKZBh/qbREIOcI3cULzDyb18Sr/Wcyx7NRQeQzOiHTNbZFF1UwPS2scyGA==} + resolution: {integrity: sha512-oVDbcR4zUC0ce82teubSm+x6ETixtKZBh/qbREIOcI3cULzDyb18Sr/Wcyx7NRQeQzOiHTNbZFF1UwPS2scyGA==, tarball: https://registry.npmjs.org/@img/sharp-libvips-linux-riscv64/-/sharp-libvips-linux-riscv64-1.2.4.tgz} cpu: [riscv64] os: [linux] '@img/sharp-libvips-linux-s390x@1.2.4': - resolution: {integrity: sha512-qmp9VrzgPgMoGZyPvrQHqk02uyjA0/QrTO26Tqk6l4ZV0MPWIW6LTkqOIov+J1yEu7MbFQaDpwdwJKhbJvuRxQ==} + resolution: {integrity: sha512-qmp9VrzgPgMoGZyPvrQHqk02uyjA0/QrTO26Tqk6l4ZV0MPWIW6LTkqOIov+J1yEu7MbFQaDpwdwJKhbJvuRxQ==, tarball: https://registry.npmjs.org/@img/sharp-libvips-linux-s390x/-/sharp-libvips-linux-s390x-1.2.4.tgz} cpu: [s390x] os: [linux] '@img/sharp-libvips-linux-x64@1.2.4': - resolution: {integrity: sha512-tJxiiLsmHc9Ax1bz3oaOYBURTXGIRDODBqhveVHonrHJ9/+k89qbLl0bcJns+e4t4rvaNBxaEZsFtSfAdquPrw==} + resolution: {integrity: sha512-tJxiiLsmHc9Ax1bz3oaOYBURTXGIRDODBqhveVHonrHJ9/+k89qbLl0bcJns+e4t4rvaNBxaEZsFtSfAdquPrw==, tarball: https://registry.npmjs.org/@img/sharp-libvips-linux-x64/-/sharp-libvips-linux-x64-1.2.4.tgz} cpu: [x64] os: [linux] '@img/sharp-libvips-linuxmusl-arm64@1.2.4': - resolution: {integrity: sha512-FVQHuwx1IIuNow9QAbYUzJ+En8KcVm9Lk5+uGUQJHaZmMECZmOlix9HnH7n1TRkXMS0pGxIJokIVB9SuqZGGXw==} + resolution: {integrity: sha512-FVQHuwx1IIuNow9QAbYUzJ+En8KcVm9Lk5+uGUQJHaZmMECZmOlix9HnH7n1TRkXMS0pGxIJokIVB9SuqZGGXw==, tarball: https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-arm64/-/sharp-libvips-linuxmusl-arm64-1.2.4.tgz} cpu: [arm64] os: [linux] '@img/sharp-libvips-linuxmusl-x64@1.2.4': - resolution: {integrity: sha512-+LpyBk7L44ZIXwz/VYfglaX/okxezESc6UxDSoyo2Ks6Jxc4Y7sGjpgU9s4PMgqgjj1gZCylTieNamqA1MF7Dg==} + resolution: {integrity: sha512-+LpyBk7L44ZIXwz/VYfglaX/okxezESc6UxDSoyo2Ks6Jxc4Y7sGjpgU9s4PMgqgjj1gZCylTieNamqA1MF7Dg==, tarball: https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-x64/-/sharp-libvips-linuxmusl-x64-1.2.4.tgz} cpu: [x64] os: [linux] '@img/sharp-linux-arm64@0.34.5': - resolution: {integrity: sha512-bKQzaJRY/bkPOXyKx5EVup7qkaojECG6NLYswgktOZjaXecSAeCWiZwwiFf3/Y+O1HrauiE3FVsGxFg8c24rZg==} + resolution: {integrity: sha512-bKQzaJRY/bkPOXyKx5EVup7qkaojECG6NLYswgktOZjaXecSAeCWiZwwiFf3/Y+O1HrauiE3FVsGxFg8c24rZg==, tarball: https://registry.npmjs.org/@img/sharp-linux-arm64/-/sharp-linux-arm64-0.34.5.tgz} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} cpu: [arm64] os: [linux] '@img/sharp-linux-arm@0.34.5': - resolution: {integrity: sha512-9dLqsvwtg1uuXBGZKsxem9595+ujv0sJ6Vi8wcTANSFpwV/GONat5eCkzQo/1O6zRIkh0m/8+5BjrRr7jDUSZw==} + resolution: {integrity: sha512-9dLqsvwtg1uuXBGZKsxem9595+ujv0sJ6Vi8wcTANSFpwV/GONat5eCkzQo/1O6zRIkh0m/8+5BjrRr7jDUSZw==, tarball: https://registry.npmjs.org/@img/sharp-linux-arm/-/sharp-linux-arm-0.34.5.tgz} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} cpu: [arm] os: [linux] '@img/sharp-linux-ppc64@0.34.5': - resolution: {integrity: sha512-7zznwNaqW6YtsfrGGDA6BRkISKAAE1Jo0QdpNYXNMHu2+0dTrPflTLNkpc8l7MUP5M16ZJcUvysVWWrMefZquA==} + resolution: {integrity: sha512-7zznwNaqW6YtsfrGGDA6BRkISKAAE1Jo0QdpNYXNMHu2+0dTrPflTLNkpc8l7MUP5M16ZJcUvysVWWrMefZquA==, tarball: https://registry.npmjs.org/@img/sharp-linux-ppc64/-/sharp-linux-ppc64-0.34.5.tgz} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} cpu: [ppc64] os: [linux] '@img/sharp-linux-riscv64@0.34.5': - resolution: {integrity: sha512-51gJuLPTKa7piYPaVs8GmByo7/U7/7TZOq+cnXJIHZKavIRHAP77e3N2HEl3dgiqdD/w0yUfiJnII77PuDDFdw==} + resolution: {integrity: sha512-51gJuLPTKa7piYPaVs8GmByo7/U7/7TZOq+cnXJIHZKavIRHAP77e3N2HEl3dgiqdD/w0yUfiJnII77PuDDFdw==, tarball: https://registry.npmjs.org/@img/sharp-linux-riscv64/-/sharp-linux-riscv64-0.34.5.tgz} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} cpu: [riscv64] os: [linux] '@img/sharp-linux-s390x@0.34.5': - resolution: {integrity: sha512-nQtCk0PdKfho3eC5MrbQoigJ2gd1CgddUMkabUj+rBevs8tZ2cULOx46E7oyX+04WGfABgIwmMC0VqieTiR4jg==} + resolution: {integrity: sha512-nQtCk0PdKfho3eC5MrbQoigJ2gd1CgddUMkabUj+rBevs8tZ2cULOx46E7oyX+04WGfABgIwmMC0VqieTiR4jg==, tarball: https://registry.npmjs.org/@img/sharp-linux-s390x/-/sharp-linux-s390x-0.34.5.tgz} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} cpu: [s390x] os: [linux] '@img/sharp-linux-x64@0.34.5': - resolution: {integrity: sha512-MEzd8HPKxVxVenwAa+JRPwEC7QFjoPWuS5NZnBt6B3pu7EG2Ge0id1oLHZpPJdn3OQK+BQDiw9zStiHBTJQQQQ==} + resolution: {integrity: sha512-MEzd8HPKxVxVenwAa+JRPwEC7QFjoPWuS5NZnBt6B3pu7EG2Ge0id1oLHZpPJdn3OQK+BQDiw9zStiHBTJQQQQ==, tarball: https://registry.npmjs.org/@img/sharp-linux-x64/-/sharp-linux-x64-0.34.5.tgz} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} cpu: [x64] os: [linux] '@img/sharp-linuxmusl-arm64@0.34.5': - resolution: {integrity: sha512-fprJR6GtRsMt6Kyfq44IsChVZeGN97gTD331weR1ex1c1rypDEABN6Tm2xa1wE6lYb5DdEnk03NZPqA7Id21yg==} + resolution: {integrity: sha512-fprJR6GtRsMt6Kyfq44IsChVZeGN97gTD331weR1ex1c1rypDEABN6Tm2xa1wE6lYb5DdEnk03NZPqA7Id21yg==, tarball: https://registry.npmjs.org/@img/sharp-linuxmusl-arm64/-/sharp-linuxmusl-arm64-0.34.5.tgz} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} cpu: [arm64] os: [linux] '@img/sharp-linuxmusl-x64@0.34.5': - resolution: {integrity: sha512-Jg8wNT1MUzIvhBFxViqrEhWDGzqymo3sV7z7ZsaWbZNDLXRJZoRGrjulp60YYtV4wfY8VIKcWidjojlLcWrd8Q==} + resolution: {integrity: sha512-Jg8wNT1MUzIvhBFxViqrEhWDGzqymo3sV7z7ZsaWbZNDLXRJZoRGrjulp60YYtV4wfY8VIKcWidjojlLcWrd8Q==, tarball: https://registry.npmjs.org/@img/sharp-linuxmusl-x64/-/sharp-linuxmusl-x64-0.34.5.tgz} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} cpu: [x64] os: [linux] '@img/sharp-wasm32@0.34.5': - resolution: {integrity: sha512-OdWTEiVkY2PHwqkbBI8frFxQQFekHaSSkUIJkwzclWZe64O1X4UlUjqqqLaPbUpMOQk6FBu/HtlGXNblIs0huw==} + resolution: {integrity: sha512-OdWTEiVkY2PHwqkbBI8frFxQQFekHaSSkUIJkwzclWZe64O1X4UlUjqqqLaPbUpMOQk6FBu/HtlGXNblIs0huw==, tarball: https://registry.npmjs.org/@img/sharp-wasm32/-/sharp-wasm32-0.34.5.tgz} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} cpu: [wasm32] '@img/sharp-win32-arm64@0.34.5': - resolution: {integrity: sha512-WQ3AgWCWYSb2yt+IG8mnC6Jdk9Whs7O0gxphblsLvdhSpSTtmu69ZG1Gkb6NuvxsNACwiPV6cNSZNzt0KPsw7g==} + resolution: {integrity: sha512-WQ3AgWCWYSb2yt+IG8mnC6Jdk9Whs7O0gxphblsLvdhSpSTtmu69ZG1Gkb6NuvxsNACwiPV6cNSZNzt0KPsw7g==, tarball: https://registry.npmjs.org/@img/sharp-win32-arm64/-/sharp-win32-arm64-0.34.5.tgz} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} cpu: [arm64] os: [win32] '@img/sharp-win32-ia32@0.34.5': - resolution: {integrity: sha512-FV9m/7NmeCmSHDD5j4+4pNI8Cp3aW+JvLoXcTUo0IqyjSfAZJ8dIUmijx1qaJsIiU+Hosw6xM5KijAWRJCSgNg==} + resolution: {integrity: sha512-FV9m/7NmeCmSHDD5j4+4pNI8Cp3aW+JvLoXcTUo0IqyjSfAZJ8dIUmijx1qaJsIiU+Hosw6xM5KijAWRJCSgNg==, tarball: https://registry.npmjs.org/@img/sharp-win32-ia32/-/sharp-win32-ia32-0.34.5.tgz} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} cpu: [ia32] os: [win32] '@img/sharp-win32-x64@0.34.5': - resolution: {integrity: sha512-+29YMsqY2/9eFEiW93eqWnuLcWcufowXewwSNIT6UwZdUUCrM3oFjMWH/Z6/TMmb4hlFenmfAVbpWeup2jryCw==} + resolution: {integrity: sha512-+29YMsqY2/9eFEiW93eqWnuLcWcufowXewwSNIT6UwZdUUCrM3oFjMWH/Z6/TMmb4hlFenmfAVbpWeup2jryCw==, tarball: https://registry.npmjs.org/@img/sharp-win32-x64/-/sharp-win32-x64-0.34.5.tgz} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} cpu: [x64] os: [win32] @@ -1740,7 +1774,7 @@ packages: optional: true '@mrleebo/prisma-ast@0.13.1': - resolution: {integrity: sha512-XyroGQXcHrZdvmrGJvsA9KNeOOgGMg1Vg9OlheUsBOSKznLMDl+YChxbkboRHvtFYJEMRYmlV3uoo/njCw05iw==} + resolution: {integrity: sha512-XyroGQXcHrZdvmrGJvsA9KNeOOgGMg1Vg9OlheUsBOSKznLMDl+YChxbkboRHvtFYJEMRYmlV3uoo/njCw05iw==, tarball: https://registry.npmjs.org/@mrleebo/prisma-ast/-/prisma-ast-0.13.1.tgz} engines: {node: '>=16'} '@mswjs/interceptors@0.41.3': @@ -1748,10 +1782,10 @@ packages: engines: {node: '>=18'} '@napi-rs/wasm-runtime@1.1.1': - resolution: {integrity: sha512-p64ah1M1ld8xjWv3qbvFwHiFVWrq1yFvV4f7w+mzaqiR4IlSgkqhcRdHwsGgomwzBH51sRY4NEowLxnaBjcW/A==} + resolution: {integrity: sha512-p64ah1M1ld8xjWv3qbvFwHiFVWrq1yFvV4f7w+mzaqiR4IlSgkqhcRdHwsGgomwzBH51sRY4NEowLxnaBjcW/A==, tarball: https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-1.1.1.tgz} '@napi-rs/wasm-runtime@1.1.3': - resolution: {integrity: sha512-xK9sGVbJWYb08+mTJt3/YV24WxvxpXcXtP6B172paPZ+Ts69Re9dAr7lKwJoeIx8OoeuimEiRZ7umkiUVClmmQ==} + resolution: {integrity: sha512-xK9sGVbJWYb08+mTJt3/YV24WxvxpXcXtP6B172paPZ+Ts69Re9dAr7lKwJoeIx8OoeuimEiRZ7umkiUVClmmQ==, tarball: https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-1.1.3.tgz} peerDependencies: '@emnapi/core': ^1.7.1 '@emnapi/runtime': ^1.7.1 @@ -1760,49 +1794,49 @@ packages: resolution: {integrity: sha512-ZWXyj4uNu4GCWQw9cjRxWlbD+33mcDszIo9iQxFnBX3Wmgq9ulaSJcl6VhuWx5pCWqqD+9W6Wfz7N0lM5lYPMA==} '@next/swc-darwin-arm64@16.2.3': - resolution: {integrity: sha512-u37KDKTKQ+OQLvY+z7SNXixwo4Q2/IAJFDzU1fYe66IbCE51aDSAzkNDkWmLN0yjTUh4BKBd+hb69jYn6qqqSg==} + resolution: {integrity: sha512-u37KDKTKQ+OQLvY+z7SNXixwo4Q2/IAJFDzU1fYe66IbCE51aDSAzkNDkWmLN0yjTUh4BKBd+hb69jYn6qqqSg==, tarball: https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-16.2.3.tgz} engines: {node: '>= 10'} cpu: [arm64] os: [darwin] '@next/swc-darwin-x64@16.2.3': - resolution: {integrity: sha512-gHjL/qy6Q6CG3176FWbAKyKh9IfntKZTB3RY/YOJdDFpHGsUDXVH38U4mMNpHVGXmeYW4wj22dMp1lTfmu/bTQ==} + resolution: {integrity: sha512-gHjL/qy6Q6CG3176FWbAKyKh9IfntKZTB3RY/YOJdDFpHGsUDXVH38U4mMNpHVGXmeYW4wj22dMp1lTfmu/bTQ==, tarball: https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-16.2.3.tgz} engines: {node: '>= 10'} cpu: [x64] os: [darwin] '@next/swc-linux-arm64-gnu@16.2.3': - resolution: {integrity: sha512-U6vtblPtU/P14Y/b/n9ZY0GOxbbIhTFuaFR7F4/uMBidCi2nSdaOFhA0Go81L61Zd6527+yvuX44T4ksnf8T+Q==} + resolution: {integrity: sha512-U6vtblPtU/P14Y/b/n9ZY0GOxbbIhTFuaFR7F4/uMBidCi2nSdaOFhA0Go81L61Zd6527+yvuX44T4ksnf8T+Q==, tarball: https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-16.2.3.tgz} engines: {node: '>= 10'} cpu: [arm64] os: [linux] '@next/swc-linux-arm64-musl@16.2.3': - resolution: {integrity: sha512-/YV0LgjHUmfhQpn9bVoGc4x4nan64pkhWR5wyEV8yCOfwwrH630KpvRg86olQHTwHIn1z59uh6JwKvHq1h4QEw==} + resolution: {integrity: sha512-/YV0LgjHUmfhQpn9bVoGc4x4nan64pkhWR5wyEV8yCOfwwrH630KpvRg86olQHTwHIn1z59uh6JwKvHq1h4QEw==, tarball: https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-16.2.3.tgz} engines: {node: '>= 10'} cpu: [arm64] os: [linux] '@next/swc-linux-x64-gnu@16.2.3': - resolution: {integrity: sha512-/HiWEcp+WMZ7VajuiMEFGZ6cg0+aYZPqCJD3YJEfpVWQsKYSjXQG06vJP6F1rdA03COD9Fef4aODs3YxKx+RDQ==} + resolution: {integrity: sha512-/HiWEcp+WMZ7VajuiMEFGZ6cg0+aYZPqCJD3YJEfpVWQsKYSjXQG06vJP6F1rdA03COD9Fef4aODs3YxKx+RDQ==, tarball: https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-16.2.3.tgz} engines: {node: '>= 10'} cpu: [x64] os: [linux] '@next/swc-linux-x64-musl@16.2.3': - resolution: {integrity: sha512-Kt44hGJfZSefebhk/7nIdivoDr3Ugp5+oNz9VvF3GUtfxutucUIHfIO0ZYO8QlOPDQloUVQn4NVC/9JvHRk9hw==} + resolution: {integrity: sha512-Kt44hGJfZSefebhk/7nIdivoDr3Ugp5+oNz9VvF3GUtfxutucUIHfIO0ZYO8QlOPDQloUVQn4NVC/9JvHRk9hw==, tarball: https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-16.2.3.tgz} engines: {node: '>= 10'} cpu: [x64] os: [linux] '@next/swc-win32-arm64-msvc@16.2.3': - resolution: {integrity: sha512-O2NZ9ie3Tq6xj5Z5CSwBT3+aWAMW2PIZ4egUi9MaWLkwaehgtB7YZjPm+UpcNpKOme0IQuqDcor7BsW6QBiQBw==} + resolution: {integrity: sha512-O2NZ9ie3Tq6xj5Z5CSwBT3+aWAMW2PIZ4egUi9MaWLkwaehgtB7YZjPm+UpcNpKOme0IQuqDcor7BsW6QBiQBw==, tarball: https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-16.2.3.tgz} engines: {node: '>= 10'} cpu: [arm64] os: [win32] '@next/swc-win32-x64-msvc@16.2.3': - resolution: {integrity: sha512-Ibm29/GgB/ab5n7XKqlStkm54qqZE8v2FnijUPBgrd67FWrac45o/RsNlaOWjme/B5UqeWt/8KM4aWBwA1D2Kw==} + resolution: {integrity: sha512-Ibm29/GgB/ab5n7XKqlStkm54qqZE8v2FnijUPBgrd67FWrac45o/RsNlaOWjme/B5UqeWt/8KM4aWBwA1D2Kw==, tarball: https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-16.2.3.tgz} engines: {node: '>= 10'} cpu: [x64] os: [win32] @@ -1849,7 +1883,7 @@ packages: resolution: {integrity: sha512-U69T3ItWHvLwGg5eJ0n3I62nWuE6ilHlmz7zM0npLBRvPRd7e6NYmg54vvRtP5mZG7kZqZCFVdsTWo7BPtBujg==} '@opentelemetry/api@1.9.0': - resolution: {integrity: sha512-3giAOQvZiH5F9bMlMiv8+GSPMeqg0dbaeo58/0SlA9sxSqZhnUtxzX9/2FzyhS9sWQf5S0GJE0AKBrFqjpeYcg==} + resolution: {integrity: sha512-3giAOQvZiH5F9bMlMiv8+GSPMeqg0dbaeo58/0SlA9sxSqZhnUtxzX9/2FzyhS9sWQf5S0GJE0AKBrFqjpeYcg==, tarball: https://registry.npmjs.org/@opentelemetry/api/-/api-1.9.0.tgz} engines: {node: '>=8.0.0'} '@opentelemetry/semantic-conventions@1.40.0': @@ -1879,120 +1913,120 @@ packages: resolution: {integrity: sha512-bLE7BtHrURedCn4Mco3ma9L4Y1GR2SMBuIvjWr7rmQ4/W/4Jy70TIAgZ+0nIlk0xHz1vNP8x8DCns45Sb2XRbg==} '@oxc-parser/binding-android-arm-eabi@0.124.0': - resolution: {integrity: sha512-+R9zCafSL8ovjokdPtorUp3sXrh8zQ2AC2L0ivXNvlLR0WS+5WdPkNVrnENq5UvzagM4Xgl0NPsJKz3Hv9+y8g==} + resolution: {integrity: sha512-+R9zCafSL8ovjokdPtorUp3sXrh8zQ2AC2L0ivXNvlLR0WS+5WdPkNVrnENq5UvzagM4Xgl0NPsJKz3Hv9+y8g==, tarball: https://registry.npmjs.org/@oxc-parser/binding-android-arm-eabi/-/binding-android-arm-eabi-0.124.0.tgz} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm] os: [android] '@oxc-parser/binding-android-arm64@0.124.0': - resolution: {integrity: sha512-ULHC/gVZ+nP4pd3kNNQTYaQ/e066BW/KuY5qUsvwkVWwOUQGDg+WpfyVOmQ4xfxoue6cMlkKkJ+ntdzfDXpNlg==} + resolution: {integrity: sha512-ULHC/gVZ+nP4pd3kNNQTYaQ/e066BW/KuY5qUsvwkVWwOUQGDg+WpfyVOmQ4xfxoue6cMlkKkJ+ntdzfDXpNlg==, tarball: https://registry.npmjs.org/@oxc-parser/binding-android-arm64/-/binding-android-arm64-0.124.0.tgz} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [android] '@oxc-parser/binding-darwin-arm64@0.124.0': - resolution: {integrity: sha512-fGJ2hw7bnbUYn6UvTjp0m4WJ9zXz3cohgcwcgeo7gUZehpPNpvcVEVeIVHNmHnAuAw/ysf4YJR8DA1E+xCA4Lw==} + resolution: {integrity: sha512-fGJ2hw7bnbUYn6UvTjp0m4WJ9zXz3cohgcwcgeo7gUZehpPNpvcVEVeIVHNmHnAuAw/ysf4YJR8DA1E+xCA4Lw==, tarball: https://registry.npmjs.org/@oxc-parser/binding-darwin-arm64/-/binding-darwin-arm64-0.124.0.tgz} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [darwin] '@oxc-parser/binding-darwin-x64@0.124.0': - resolution: {integrity: sha512-j0+re9pgps5BH2Tk3fm59Hi3QuLP3C4KhqXi6A+wRHHHJWDFR8mc/KI9mBrfk2JRT+15doGo+zv1eN75/9DuOw==} + resolution: {integrity: sha512-j0+re9pgps5BH2Tk3fm59Hi3QuLP3C4KhqXi6A+wRHHHJWDFR8mc/KI9mBrfk2JRT+15doGo+zv1eN75/9DuOw==, tarball: https://registry.npmjs.org/@oxc-parser/binding-darwin-x64/-/binding-darwin-x64-0.124.0.tgz} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [darwin] '@oxc-parser/binding-freebsd-x64@0.124.0': - resolution: {integrity: sha512-0k5mS0npnrhKy72UfF51lpOZ2ESoPWn6gdFw+RdeRWcokraDW1O2kSx3laQ+yk7cCEavQdJSpWCYS/GvBbUCXQ==} + resolution: {integrity: sha512-0k5mS0npnrhKy72UfF51lpOZ2ESoPWn6gdFw+RdeRWcokraDW1O2kSx3laQ+yk7cCEavQdJSpWCYS/GvBbUCXQ==, tarball: https://registry.npmjs.org/@oxc-parser/binding-freebsd-x64/-/binding-freebsd-x64-0.124.0.tgz} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [freebsd] '@oxc-parser/binding-linux-arm-gnueabihf@0.124.0': - resolution: {integrity: sha512-P/i4eguRWvAUfGdfhQYg1jpwYkyUV6D3gefIH7HhmRl1Ph6P4IqTIEVcyJr1i/3vr1V5OHU4wonH6/ue/Qzvrw==} + resolution: {integrity: sha512-P/i4eguRWvAUfGdfhQYg1jpwYkyUV6D3gefIH7HhmRl1Ph6P4IqTIEVcyJr1i/3vr1V5OHU4wonH6/ue/Qzvrw==, tarball: https://registry.npmjs.org/@oxc-parser/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-0.124.0.tgz} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm] os: [linux] '@oxc-parser/binding-linux-arm-musleabihf@0.124.0': - resolution: {integrity: sha512-/ameqFQH5fFP+66Atr8Ynv/2rYe4utcU7L4MoWS5JtrFLVO78g4qDLavyIlJxa6caSwYOvG/eO3c/DXqY5/6Rw==} + resolution: {integrity: sha512-/ameqFQH5fFP+66Atr8Ynv/2rYe4utcU7L4MoWS5JtrFLVO78g4qDLavyIlJxa6caSwYOvG/eO3c/DXqY5/6Rw==, tarball: https://registry.npmjs.org/@oxc-parser/binding-linux-arm-musleabihf/-/binding-linux-arm-musleabihf-0.124.0.tgz} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm] os: [linux] '@oxc-parser/binding-linux-arm64-gnu@0.124.0': - resolution: {integrity: sha512-gNeyEcXTtfrRCbj2EfxWU85Fs0wIX3p44Y3twnvuMfkWlLrb9M1Z25AYNSKjJM+fdAjeeQCjw0on47zFuBYwQw==} + resolution: {integrity: sha512-gNeyEcXTtfrRCbj2EfxWU85Fs0wIX3p44Y3twnvuMfkWlLrb9M1Z25AYNSKjJM+fdAjeeQCjw0on47zFuBYwQw==, tarball: https://registry.npmjs.org/@oxc-parser/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-0.124.0.tgz} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [linux] '@oxc-parser/binding-linux-arm64-musl@0.124.0': - resolution: {integrity: sha512-uvG7v4Tz9S8/PVqY0SP0DLHxo4hZGe+Pv2tGVnwcsjKCCUPjplbrFVvDzXq+kOaEoUkiCY0Kt1hlZ6FDJ1LKNQ==} + resolution: {integrity: sha512-uvG7v4Tz9S8/PVqY0SP0DLHxo4hZGe+Pv2tGVnwcsjKCCUPjplbrFVvDzXq+kOaEoUkiCY0Kt1hlZ6FDJ1LKNQ==, tarball: https://registry.npmjs.org/@oxc-parser/binding-linux-arm64-musl/-/binding-linux-arm64-musl-0.124.0.tgz} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [linux] '@oxc-parser/binding-linux-ppc64-gnu@0.124.0': - resolution: {integrity: sha512-t7KZaaUhfp2au0MRpoENEFqwLKYDdptEry6V7pTAVdPEcFG4P6ii8yeGU9m6p5vb+b8WEKmdpGMNXBEYy7iJdw==} + resolution: {integrity: sha512-t7KZaaUhfp2au0MRpoENEFqwLKYDdptEry6V7pTAVdPEcFG4P6ii8yeGU9m6p5vb+b8WEKmdpGMNXBEYy7iJdw==, tarball: https://registry.npmjs.org/@oxc-parser/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-0.124.0.tgz} engines: {node: ^20.19.0 || >=22.12.0} cpu: [ppc64] os: [linux] '@oxc-parser/binding-linux-riscv64-gnu@0.124.0': - resolution: {integrity: sha512-eurGGaxHZiIQ+fBSageS8TAkRqZgdOiBeqNrWAqAPup9hXBTmQ0WcBjwsLElf+3jvDL9NhnX0dOgOqPfsjSjdg==} + resolution: {integrity: sha512-eurGGaxHZiIQ+fBSageS8TAkRqZgdOiBeqNrWAqAPup9hXBTmQ0WcBjwsLElf+3jvDL9NhnX0dOgOqPfsjSjdg==, tarball: https://registry.npmjs.org/@oxc-parser/binding-linux-riscv64-gnu/-/binding-linux-riscv64-gnu-0.124.0.tgz} engines: {node: ^20.19.0 || >=22.12.0} cpu: [riscv64] os: [linux] '@oxc-parser/binding-linux-riscv64-musl@0.124.0': - resolution: {integrity: sha512-d1V7/ll1i/LhqE/gZy6Wbz6evlk0egh2XKkwMI3epiojtbtUwQSLIER0Y3yDBBocPuWOjJdvmjtEmPTTLXje/w==} + resolution: {integrity: sha512-d1V7/ll1i/LhqE/gZy6Wbz6evlk0egh2XKkwMI3epiojtbtUwQSLIER0Y3yDBBocPuWOjJdvmjtEmPTTLXje/w==, tarball: https://registry.npmjs.org/@oxc-parser/binding-linux-riscv64-musl/-/binding-linux-riscv64-musl-0.124.0.tgz} engines: {node: ^20.19.0 || >=22.12.0} cpu: [riscv64] os: [linux] '@oxc-parser/binding-linux-s390x-gnu@0.124.0': - resolution: {integrity: sha512-w1+cBvriUteOpox6ATqCFVkpGL47PFdcfCPGmgUZbd78Fw44U0gQkc+kVGvAOTvGrptMYgwomD1c6OTVvkrpGg==} + resolution: {integrity: sha512-w1+cBvriUteOpox6ATqCFVkpGL47PFdcfCPGmgUZbd78Fw44U0gQkc+kVGvAOTvGrptMYgwomD1c6OTVvkrpGg==, tarball: https://registry.npmjs.org/@oxc-parser/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-0.124.0.tgz} engines: {node: ^20.19.0 || >=22.12.0} cpu: [s390x] os: [linux] '@oxc-parser/binding-linux-x64-gnu@0.124.0': - resolution: {integrity: sha512-RRB1evQiXRtMCsQQiAh9U0H3HzguLpE0ytfStuhRgmOj7tqUCOVxkHsvM9geZjAax6NqVRj7VXx32qjjkZPsBw==} + resolution: {integrity: sha512-RRB1evQiXRtMCsQQiAh9U0H3HzguLpE0ytfStuhRgmOj7tqUCOVxkHsvM9geZjAax6NqVRj7VXx32qjjkZPsBw==, tarball: https://registry.npmjs.org/@oxc-parser/binding-linux-x64-gnu/-/binding-linux-x64-gnu-0.124.0.tgz} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [linux] '@oxc-parser/binding-linux-x64-musl@0.124.0': - resolution: {integrity: sha512-asVYN0qmSHlCU8H9Q47SmeJ/Z5EG4IWCC+QGxkfFboI5qh15aLlJnHmnrV61MwQRPXGnVC/sC3qKhrUyqGxUqw==} + resolution: {integrity: sha512-asVYN0qmSHlCU8H9Q47SmeJ/Z5EG4IWCC+QGxkfFboI5qh15aLlJnHmnrV61MwQRPXGnVC/sC3qKhrUyqGxUqw==, tarball: https://registry.npmjs.org/@oxc-parser/binding-linux-x64-musl/-/binding-linux-x64-musl-0.124.0.tgz} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [linux] '@oxc-parser/binding-openharmony-arm64@0.124.0': - resolution: {integrity: sha512-nhwuxm6B8pn9lzAzMUfa571L5hCXYwQo8C8cx5aGOuHWCzruR8gPJnRRXGBci+uGaIIQEZDyU/U6HDgrSp/JlQ==} + resolution: {integrity: sha512-nhwuxm6B8pn9lzAzMUfa571L5hCXYwQo8C8cx5aGOuHWCzruR8gPJnRRXGBci+uGaIIQEZDyU/U6HDgrSp/JlQ==, tarball: https://registry.npmjs.org/@oxc-parser/binding-openharmony-arm64/-/binding-openharmony-arm64-0.124.0.tgz} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [openharmony] '@oxc-parser/binding-wasm32-wasi@0.124.0': - resolution: {integrity: sha512-LWuq4Dl9tff7n+HjJcqoBjDlVCtruc0shgtdtGM+rTUIE9aFxHA/P+wCYR+aWMjN8m9vNaRME/sKXErmhmeKrA==} + resolution: {integrity: sha512-LWuq4Dl9tff7n+HjJcqoBjDlVCtruc0shgtdtGM+rTUIE9aFxHA/P+wCYR+aWMjN8m9vNaRME/sKXErmhmeKrA==, tarball: https://registry.npmjs.org/@oxc-parser/binding-wasm32-wasi/-/binding-wasm32-wasi-0.124.0.tgz} engines: {node: '>=14.0.0'} cpu: [wasm32] '@oxc-parser/binding-win32-arm64-msvc@0.124.0': - resolution: {integrity: sha512-aOh3Lf3AeH0dgzT4yBXcArFZ8VhqNXwZ/xlN0GqBtgVaGoHOOqL2YHlcVIgT+ghsXPVR2PTtYgBiQ1CNK7jp5A==} + resolution: {integrity: sha512-aOh3Lf3AeH0dgzT4yBXcArFZ8VhqNXwZ/xlN0GqBtgVaGoHOOqL2YHlcVIgT+ghsXPVR2PTtYgBiQ1CNK7jp5A==, tarball: https://registry.npmjs.org/@oxc-parser/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-0.124.0.tgz} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [win32] '@oxc-parser/binding-win32-ia32-msvc@0.124.0': - resolution: {integrity: sha512-sib5xC0nz/+SCpaETBuHBz4SXS02KuG5HtyOcHsO/SK5ZvLRGhOZx0elDKawjb6adFkD7dQCqpXUS25wY6ELKQ==} + resolution: {integrity: sha512-sib5xC0nz/+SCpaETBuHBz4SXS02KuG5HtyOcHsO/SK5ZvLRGhOZx0elDKawjb6adFkD7dQCqpXUS25wY6ELKQ==, tarball: https://registry.npmjs.org/@oxc-parser/binding-win32-ia32-msvc/-/binding-win32-ia32-msvc-0.124.0.tgz} engines: {node: ^20.19.0 || >=22.12.0} cpu: [ia32] os: [win32] '@oxc-parser/binding-win32-x64-msvc@0.124.0': - resolution: {integrity: sha512-UgojtjGUgZgAZQYt7SC6VO65OVdxEkRe2q+2vbHJO//18qw3Hrk6UvHGQKldsQKgbVcIBT/YBrt85YberiYIPQ==} + resolution: {integrity: sha512-UgojtjGUgZgAZQYt7SC6VO65OVdxEkRe2q+2vbHJO//18qw3Hrk6UvHGQKldsQKgbVcIBT/YBrt85YberiYIPQ==, tarball: https://registry.npmjs.org/@oxc-parser/binding-win32-x64-msvc/-/binding-win32-x64-msvc-0.124.0.tgz} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [win32] @@ -2007,347 +2041,350 @@ packages: resolution: {integrity: sha512-VBFWMTBvHxS11Z5Lvlr3IWgrwhMTXV+Md+EQF0Xf60+wAdsGFTBx7X7K/hP4pi8N7dcm1RvcHwDxZ16Qx8keUg==} '@oxc-resolver/binding-android-arm-eabi@11.19.1': - resolution: {integrity: sha512-aUs47y+xyXHUKlbhqHUjBABjvycq6YSD7bpxSW7vplUmdzAlJ93yXY6ZR0c1o1x5A/QKbENCvs3+NlY8IpIVzg==} + resolution: {integrity: sha512-aUs47y+xyXHUKlbhqHUjBABjvycq6YSD7bpxSW7vplUmdzAlJ93yXY6ZR0c1o1x5A/QKbENCvs3+NlY8IpIVzg==, tarball: https://registry.npmjs.org/@oxc-resolver/binding-android-arm-eabi/-/binding-android-arm-eabi-11.19.1.tgz} cpu: [arm] os: [android] '@oxc-resolver/binding-android-arm64@11.19.1': - resolution: {integrity: sha512-oolbkRX+m7Pq2LNjr/kKgYeC7bRDMVTWPgxBGMjSpZi/+UskVo4jsMU3MLheZV55jL6c3rNelPl4oD60ggYmqA==} + resolution: {integrity: sha512-oolbkRX+m7Pq2LNjr/kKgYeC7bRDMVTWPgxBGMjSpZi/+UskVo4jsMU3MLheZV55jL6c3rNelPl4oD60ggYmqA==, tarball: https://registry.npmjs.org/@oxc-resolver/binding-android-arm64/-/binding-android-arm64-11.19.1.tgz} cpu: [arm64] os: [android] '@oxc-resolver/binding-darwin-arm64@11.19.1': - resolution: {integrity: sha512-nUC6d2i3R5B12sUW4O646qD5cnMXf2oBGPLIIeaRfU9doJRORAbE2SGv4eW6rMqhD+G7nf2Y8TTJTLiiO3Q/dQ==} + resolution: {integrity: sha512-nUC6d2i3R5B12sUW4O646qD5cnMXf2oBGPLIIeaRfU9doJRORAbE2SGv4eW6rMqhD+G7nf2Y8TTJTLiiO3Q/dQ==, tarball: https://registry.npmjs.org/@oxc-resolver/binding-darwin-arm64/-/binding-darwin-arm64-11.19.1.tgz} cpu: [arm64] os: [darwin] '@oxc-resolver/binding-darwin-x64@11.19.1': - resolution: {integrity: sha512-cV50vE5+uAgNcFa3QY1JOeKDSkM/9ReIcc/9wn4TavhW/itkDGrXhw9jaKnkQnGbjJ198Yh5nbX/Gr2mr4Z5jQ==} + resolution: {integrity: sha512-cV50vE5+uAgNcFa3QY1JOeKDSkM/9ReIcc/9wn4TavhW/itkDGrXhw9jaKnkQnGbjJ198Yh5nbX/Gr2mr4Z5jQ==, tarball: https://registry.npmjs.org/@oxc-resolver/binding-darwin-x64/-/binding-darwin-x64-11.19.1.tgz} cpu: [x64] os: [darwin] '@oxc-resolver/binding-freebsd-x64@11.19.1': - resolution: {integrity: sha512-xZOQiYGFxtk48PBKff+Zwoym7ScPAIVp4c14lfLxizO2LTTTJe5sx9vQNGrBymrf/vatSPNMD4FgsaaRigPkqw==} + resolution: {integrity: sha512-xZOQiYGFxtk48PBKff+Zwoym7ScPAIVp4c14lfLxizO2LTTTJe5sx9vQNGrBymrf/vatSPNMD4FgsaaRigPkqw==, tarball: https://registry.npmjs.org/@oxc-resolver/binding-freebsd-x64/-/binding-freebsd-x64-11.19.1.tgz} cpu: [x64] os: [freebsd] '@oxc-resolver/binding-linux-arm-gnueabihf@11.19.1': - resolution: {integrity: sha512-lXZYWAC6kaGe/ky2su94e9jN9t6M0/6c+GrSlCqL//XO1cxi5lpAhnJYdyrKfm0ZEr/c7RNyAx3P7FSBcBd5+A==} + resolution: {integrity: sha512-lXZYWAC6kaGe/ky2su94e9jN9t6M0/6c+GrSlCqL//XO1cxi5lpAhnJYdyrKfm0ZEr/c7RNyAx3P7FSBcBd5+A==, tarball: https://registry.npmjs.org/@oxc-resolver/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-11.19.1.tgz} cpu: [arm] os: [linux] '@oxc-resolver/binding-linux-arm-musleabihf@11.19.1': - resolution: {integrity: sha512-veG1kKsuK5+t2IsO9q0DErYVSw2azvCVvWHnfTOS73WE0STdLLB7Q1bB9WR+yHPQM76ASkFyRbogWo1GR1+WbQ==} + resolution: {integrity: sha512-veG1kKsuK5+t2IsO9q0DErYVSw2azvCVvWHnfTOS73WE0STdLLB7Q1bB9WR+yHPQM76ASkFyRbogWo1GR1+WbQ==, tarball: https://registry.npmjs.org/@oxc-resolver/binding-linux-arm-musleabihf/-/binding-linux-arm-musleabihf-11.19.1.tgz} cpu: [arm] os: [linux] '@oxc-resolver/binding-linux-arm64-gnu@11.19.1': - resolution: {integrity: sha512-heV2+jmXyYnUrpUXSPugqWDRpnsQcDm2AX4wzTuvgdlZfoNYO0O3W2AVpJYaDn9AG4JdM6Kxom8+foE7/BcSig==} + resolution: {integrity: sha512-heV2+jmXyYnUrpUXSPugqWDRpnsQcDm2AX4wzTuvgdlZfoNYO0O3W2AVpJYaDn9AG4JdM6Kxom8+foE7/BcSig==, tarball: https://registry.npmjs.org/@oxc-resolver/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-11.19.1.tgz} cpu: [arm64] os: [linux] '@oxc-resolver/binding-linux-arm64-musl@11.19.1': - resolution: {integrity: sha512-jvo2Pjs1c9KPxMuMPIeQsgu0mOJF9rEb3y3TdpsrqwxRM+AN6/nDDwv45n5ZrUnQMsdBy5gIabioMKnQfWo9ew==} + resolution: {integrity: sha512-jvo2Pjs1c9KPxMuMPIeQsgu0mOJF9rEb3y3TdpsrqwxRM+AN6/nDDwv45n5ZrUnQMsdBy5gIabioMKnQfWo9ew==, tarball: https://registry.npmjs.org/@oxc-resolver/binding-linux-arm64-musl/-/binding-linux-arm64-musl-11.19.1.tgz} cpu: [arm64] os: [linux] '@oxc-resolver/binding-linux-ppc64-gnu@11.19.1': - resolution: {integrity: sha512-vLmdNxWCdN7Uo5suays6A/+ywBby2PWBBPXctWPg5V0+eVuzsJxgAn6MMB4mPlshskYbppjpN2Zg83ArHze9gQ==} + resolution: {integrity: sha512-vLmdNxWCdN7Uo5suays6A/+ywBby2PWBBPXctWPg5V0+eVuzsJxgAn6MMB4mPlshskYbppjpN2Zg83ArHze9gQ==, tarball: https://registry.npmjs.org/@oxc-resolver/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-11.19.1.tgz} cpu: [ppc64] os: [linux] '@oxc-resolver/binding-linux-riscv64-gnu@11.19.1': - resolution: {integrity: sha512-/b+WgR+VTSBxzgOhDO7TlMXC1ufPIMR6Vj1zN+/x+MnyXGW7prTLzU9eW85Aj7Th7CCEG9ArCbTeqxCzFWdg2w==} + resolution: {integrity: sha512-/b+WgR+VTSBxzgOhDO7TlMXC1ufPIMR6Vj1zN+/x+MnyXGW7prTLzU9eW85Aj7Th7CCEG9ArCbTeqxCzFWdg2w==, tarball: https://registry.npmjs.org/@oxc-resolver/binding-linux-riscv64-gnu/-/binding-linux-riscv64-gnu-11.19.1.tgz} cpu: [riscv64] os: [linux] '@oxc-resolver/binding-linux-riscv64-musl@11.19.1': - resolution: {integrity: sha512-YlRdeWb9j42p29ROh+h4eg/OQ3dTJlpHSa+84pUM9+p6i3djtPz1q55yLJhgW9XfDch7FN1pQ/Vd6YP+xfRIuw==} + resolution: {integrity: sha512-YlRdeWb9j42p29ROh+h4eg/OQ3dTJlpHSa+84pUM9+p6i3djtPz1q55yLJhgW9XfDch7FN1pQ/Vd6YP+xfRIuw==, tarball: https://registry.npmjs.org/@oxc-resolver/binding-linux-riscv64-musl/-/binding-linux-riscv64-musl-11.19.1.tgz} cpu: [riscv64] os: [linux] '@oxc-resolver/binding-linux-s390x-gnu@11.19.1': - resolution: {integrity: sha512-EDpafVOQWF8/MJynsjOGFThcqhRHy417sRyLfQmeiamJ8qVhSKAn2Dn2VVKUGCjVB9C46VGjhNo7nOPUi1x6uA==} + resolution: {integrity: sha512-EDpafVOQWF8/MJynsjOGFThcqhRHy417sRyLfQmeiamJ8qVhSKAn2Dn2VVKUGCjVB9C46VGjhNo7nOPUi1x6uA==, tarball: https://registry.npmjs.org/@oxc-resolver/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-11.19.1.tgz} cpu: [s390x] os: [linux] '@oxc-resolver/binding-linux-x64-gnu@11.19.1': - resolution: {integrity: sha512-NxjZe+rqWhr+RT8/Ik+5ptA3oz7tUw361Wa5RWQXKnfqwSSHdHyrw6IdcTfYuml9dM856AlKWZIUXDmA9kkiBQ==} + resolution: {integrity: sha512-NxjZe+rqWhr+RT8/Ik+5ptA3oz7tUw361Wa5RWQXKnfqwSSHdHyrw6IdcTfYuml9dM856AlKWZIUXDmA9kkiBQ==, tarball: https://registry.npmjs.org/@oxc-resolver/binding-linux-x64-gnu/-/binding-linux-x64-gnu-11.19.1.tgz} cpu: [x64] os: [linux] '@oxc-resolver/binding-linux-x64-musl@11.19.1': - resolution: {integrity: sha512-cM/hQwsO3ReJg5kR+SpI69DMfvNCp+A/eVR4b4YClE5bVZwz8rh2Nh05InhwI5HR/9cArbEkzMjcKgTHS6UaNw==} + resolution: {integrity: sha512-cM/hQwsO3ReJg5kR+SpI69DMfvNCp+A/eVR4b4YClE5bVZwz8rh2Nh05InhwI5HR/9cArbEkzMjcKgTHS6UaNw==, tarball: https://registry.npmjs.org/@oxc-resolver/binding-linux-x64-musl/-/binding-linux-x64-musl-11.19.1.tgz} cpu: [x64] os: [linux] '@oxc-resolver/binding-openharmony-arm64@11.19.1': - resolution: {integrity: sha512-QF080IowFB0+9Rh6RcD19bdgh49BpQHUW5TajG1qvWHvmrQznTZZjYlgE2ltLXyKY+qs4F/v5xuX1XS7Is+3qA==} + resolution: {integrity: sha512-QF080IowFB0+9Rh6RcD19bdgh49BpQHUW5TajG1qvWHvmrQznTZZjYlgE2ltLXyKY+qs4F/v5xuX1XS7Is+3qA==, tarball: https://registry.npmjs.org/@oxc-resolver/binding-openharmony-arm64/-/binding-openharmony-arm64-11.19.1.tgz} cpu: [arm64] os: [openharmony] '@oxc-resolver/binding-wasm32-wasi@11.19.1': - resolution: {integrity: sha512-w8UCKhX826cP/ZLokXDS6+milN8y4X7zidsAttEdWlVoamTNf6lhBJldaWr3ukTDiye7s4HRcuPEPOXNC432Vg==} + resolution: {integrity: sha512-w8UCKhX826cP/ZLokXDS6+milN8y4X7zidsAttEdWlVoamTNf6lhBJldaWr3ukTDiye7s4HRcuPEPOXNC432Vg==, tarball: https://registry.npmjs.org/@oxc-resolver/binding-wasm32-wasi/-/binding-wasm32-wasi-11.19.1.tgz} engines: {node: '>=14.0.0'} cpu: [wasm32] '@oxc-resolver/binding-win32-arm64-msvc@11.19.1': - resolution: {integrity: sha512-nJ4AsUVZrVKwnU/QRdzPCCrO0TrabBqgJ8pJhXITdZGYOV28TIYystV1VFLbQ7DtAcaBHpocT5/ZJnF78YJPtQ==} + resolution: {integrity: sha512-nJ4AsUVZrVKwnU/QRdzPCCrO0TrabBqgJ8pJhXITdZGYOV28TIYystV1VFLbQ7DtAcaBHpocT5/ZJnF78YJPtQ==, tarball: https://registry.npmjs.org/@oxc-resolver/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-11.19.1.tgz} cpu: [arm64] os: [win32] '@oxc-resolver/binding-win32-ia32-msvc@11.19.1': - resolution: {integrity: sha512-EW+ND5q2Tl+a3pH81l1QbfgbF3HmqgwLfDfVithRFheac8OTcnbXt/JxqD2GbDkb7xYEqy1zNaVFRr3oeG8npA==} + resolution: {integrity: sha512-EW+ND5q2Tl+a3pH81l1QbfgbF3HmqgwLfDfVithRFheac8OTcnbXt/JxqD2GbDkb7xYEqy1zNaVFRr3oeG8npA==, tarball: https://registry.npmjs.org/@oxc-resolver/binding-win32-ia32-msvc/-/binding-win32-ia32-msvc-11.19.1.tgz} cpu: [ia32] os: [win32] '@oxc-resolver/binding-win32-x64-msvc@11.19.1': - resolution: {integrity: sha512-6hIU3RQu45B+VNTY4Ru8ppFwjVS/S5qwYyGhBotmjxfEKk41I2DlGtRfGJndZ5+6lneE2pwloqunlOyZuX/XAw==} + resolution: {integrity: sha512-6hIU3RQu45B+VNTY4Ru8ppFwjVS/S5qwYyGhBotmjxfEKk41I2DlGtRfGJndZ5+6lneE2pwloqunlOyZuX/XAw==, tarball: https://registry.npmjs.org/@oxc-resolver/binding-win32-x64-msvc/-/binding-win32-x64-msvc-11.19.1.tgz} cpu: [x64] os: [win32] '@oxfmt/binding-android-arm-eabi@0.36.0': - resolution: {integrity: sha512-Z4yVHJWx/swHHjtr0dXrBZb6LxS+qNz1qdza222mWwPTUK4L790+5i3LTgjx3KYGBzcYpjaiZBw4vOx94dH7MQ==} + resolution: {integrity: sha512-Z4yVHJWx/swHHjtr0dXrBZb6LxS+qNz1qdza222mWwPTUK4L790+5i3LTgjx3KYGBzcYpjaiZBw4vOx94dH7MQ==, tarball: https://registry.npmjs.org/@oxfmt/binding-android-arm-eabi/-/binding-android-arm-eabi-0.36.0.tgz} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm] os: [android] '@oxfmt/binding-android-arm64@0.36.0': - resolution: {integrity: sha512-3ElCJRFNPQl7jexf2CAa9XmAm8eC5JPrIDSjc9jSchkVSFTEqyL0NtZinBB2h1a4i4JgP1oGl/5G5n8YR4FN8Q==} + resolution: {integrity: sha512-3ElCJRFNPQl7jexf2CAa9XmAm8eC5JPrIDSjc9jSchkVSFTEqyL0NtZinBB2h1a4i4JgP1oGl/5G5n8YR4FN8Q==, tarball: https://registry.npmjs.org/@oxfmt/binding-android-arm64/-/binding-android-arm64-0.36.0.tgz} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [android] '@oxfmt/binding-darwin-arm64@0.36.0': - resolution: {integrity: sha512-nak4znWCqIExKhYSY/mz/lWsqWIpdsS7o0+SRzXR1Q0m7GrMcG1UrF1pS7TLGZhhkf7nTfEF7q6oZzJiodRDuw==} + resolution: {integrity: sha512-nak4znWCqIExKhYSY/mz/lWsqWIpdsS7o0+SRzXR1Q0m7GrMcG1UrF1pS7TLGZhhkf7nTfEF7q6oZzJiodRDuw==, tarball: https://registry.npmjs.org/@oxfmt/binding-darwin-arm64/-/binding-darwin-arm64-0.36.0.tgz} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [darwin] '@oxfmt/binding-darwin-x64@0.36.0': - resolution: {integrity: sha512-V4GP96thDnpKx6ADnMDnhIXNdtV+Ql9D4HUU+a37VTeVbs5qQSF/s6hhUP1b3xUqU7iRcwh72jUU2Y12rtGHAw==} + resolution: {integrity: sha512-V4GP96thDnpKx6ADnMDnhIXNdtV+Ql9D4HUU+a37VTeVbs5qQSF/s6hhUP1b3xUqU7iRcwh72jUU2Y12rtGHAw==, tarball: https://registry.npmjs.org/@oxfmt/binding-darwin-x64/-/binding-darwin-x64-0.36.0.tgz} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [darwin] '@oxfmt/binding-freebsd-x64@0.36.0': - resolution: {integrity: sha512-/xapWCADfI5wrhxpEUjhI9fnw7MV5BUZizVa8e24n3VSK6A3Y1TB/ClOP1tfxNspykFKXp4NBWl6NtDJP3osqQ==} + resolution: {integrity: sha512-/xapWCADfI5wrhxpEUjhI9fnw7MV5BUZizVa8e24n3VSK6A3Y1TB/ClOP1tfxNspykFKXp4NBWl6NtDJP3osqQ==, tarball: https://registry.npmjs.org/@oxfmt/binding-freebsd-x64/-/binding-freebsd-x64-0.36.0.tgz} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [freebsd] '@oxfmt/binding-linux-arm-gnueabihf@0.36.0': - resolution: {integrity: sha512-1lOmv61XMFIH5uNm27620kRRzWt/RK6tdn250BRDoG9W7OXGOQ5UyI1HVT+SFkoOoKztBiinWgi68+NA1MjBVQ==} + resolution: {integrity: sha512-1lOmv61XMFIH5uNm27620kRRzWt/RK6tdn250BRDoG9W7OXGOQ5UyI1HVT+SFkoOoKztBiinWgi68+NA1MjBVQ==, tarball: https://registry.npmjs.org/@oxfmt/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-0.36.0.tgz} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm] os: [linux] '@oxfmt/binding-linux-arm-musleabihf@0.36.0': - resolution: {integrity: sha512-vMH23AskdR1ujUS9sPck2Df9rBVoZUnCVY86jisILzIQ/QQ/yKUTi7tgnIvydPx7TyB/48wsQ5QMr5Knq5p/aw==} + resolution: {integrity: sha512-vMH23AskdR1ujUS9sPck2Df9rBVoZUnCVY86jisILzIQ/QQ/yKUTi7tgnIvydPx7TyB/48wsQ5QMr5Knq5p/aw==, tarball: https://registry.npmjs.org/@oxfmt/binding-linux-arm-musleabihf/-/binding-linux-arm-musleabihf-0.36.0.tgz} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm] os: [linux] '@oxfmt/binding-linux-arm64-gnu@0.36.0': - resolution: {integrity: sha512-Hy1V+zOBHpBiENRx77qrUTt5aPDHeCASRc8K5KwwAHkX2AKP0nV89eL17hsZrE9GmnXFjsNmd80lyf7aRTXsbw==} + resolution: {integrity: sha512-Hy1V+zOBHpBiENRx77qrUTt5aPDHeCASRc8K5KwwAHkX2AKP0nV89eL17hsZrE9GmnXFjsNmd80lyf7aRTXsbw==, tarball: https://registry.npmjs.org/@oxfmt/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-0.36.0.tgz} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [linux] '@oxfmt/binding-linux-arm64-musl@0.36.0': - resolution: {integrity: sha512-SPGLJkOIHSIC6ABUQ5V8NqJpvYhMJueJv26NYqfCnwi/Mn6A61amkpJJ9Suy0Nmvs+OWESJpcebrBUbXPGZyQQ==} + resolution: {integrity: sha512-SPGLJkOIHSIC6ABUQ5V8NqJpvYhMJueJv26NYqfCnwi/Mn6A61amkpJJ9Suy0Nmvs+OWESJpcebrBUbXPGZyQQ==, tarball: https://registry.npmjs.org/@oxfmt/binding-linux-arm64-musl/-/binding-linux-arm64-musl-0.36.0.tgz} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [linux] '@oxfmt/binding-linux-ppc64-gnu@0.36.0': - resolution: {integrity: sha512-3EuoyB8x9x8ysYJjbEO/M9fkSk72zQKnXCvpZMDHXlnY36/1qMp55Nm0PrCwjGO/1pen5hdOVkz9WmP3nAp2IQ==} + resolution: {integrity: sha512-3EuoyB8x9x8ysYJjbEO/M9fkSk72zQKnXCvpZMDHXlnY36/1qMp55Nm0PrCwjGO/1pen5hdOVkz9WmP3nAp2IQ==, tarball: https://registry.npmjs.org/@oxfmt/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-0.36.0.tgz} engines: {node: ^20.19.0 || >=22.12.0} cpu: [ppc64] os: [linux] '@oxfmt/binding-linux-riscv64-gnu@0.36.0': - resolution: {integrity: sha512-MpY3itLwpGh8dnywtrZtaZ604T1m715SydCKy0+qTxetv+IHzuA+aO/AGzrlzUNYZZmtWtmDBrChZGibvZxbRQ==} + resolution: {integrity: sha512-MpY3itLwpGh8dnywtrZtaZ604T1m715SydCKy0+qTxetv+IHzuA+aO/AGzrlzUNYZZmtWtmDBrChZGibvZxbRQ==, tarball: https://registry.npmjs.org/@oxfmt/binding-linux-riscv64-gnu/-/binding-linux-riscv64-gnu-0.36.0.tgz} engines: {node: ^20.19.0 || >=22.12.0} cpu: [riscv64] os: [linux] '@oxfmt/binding-linux-riscv64-musl@0.36.0': - resolution: {integrity: sha512-mmDhe4Vtx+XwQPRPn/V25+APnkApYgZ23q+6GVsNYY98pf3aU0aI3Me96pbRs/AfJ1jIiGC+/6q71FEu8dHcHw==} + resolution: {integrity: sha512-mmDhe4Vtx+XwQPRPn/V25+APnkApYgZ23q+6GVsNYY98pf3aU0aI3Me96pbRs/AfJ1jIiGC+/6q71FEu8dHcHw==, tarball: https://registry.npmjs.org/@oxfmt/binding-linux-riscv64-musl/-/binding-linux-riscv64-musl-0.36.0.tgz} engines: {node: ^20.19.0 || >=22.12.0} cpu: [riscv64] os: [linux] '@oxfmt/binding-linux-s390x-gnu@0.36.0': - resolution: {integrity: sha512-AYXhU+DmNWLSnvVwkHM92fuYhogtVHab7UQrPNaDf1sxadugg9gWVmcgJDlIwxJdpk5CVW/TFvwUKwI432zhhA==} + resolution: {integrity: sha512-AYXhU+DmNWLSnvVwkHM92fuYhogtVHab7UQrPNaDf1sxadugg9gWVmcgJDlIwxJdpk5CVW/TFvwUKwI432zhhA==, tarball: https://registry.npmjs.org/@oxfmt/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-0.36.0.tgz} engines: {node: ^20.19.0 || >=22.12.0} cpu: [s390x] os: [linux] '@oxfmt/binding-linux-x64-gnu@0.36.0': - resolution: {integrity: sha512-H16QhhQ3usoakMleiAAQ2mg0NsBDAdyE9agUgfC8IHHh3jZEbr0rIKwjEqwbOHK5M0EmfhJmr+aGO/MgZPsneA==} + resolution: {integrity: sha512-H16QhhQ3usoakMleiAAQ2mg0NsBDAdyE9agUgfC8IHHh3jZEbr0rIKwjEqwbOHK5M0EmfhJmr+aGO/MgZPsneA==, tarball: https://registry.npmjs.org/@oxfmt/binding-linux-x64-gnu/-/binding-linux-x64-gnu-0.36.0.tgz} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [linux] '@oxfmt/binding-linux-x64-musl@0.36.0': - resolution: {integrity: sha512-EFFGkixA39BcmHiCe2ECdrq02D6FCve5ka6ObbvrheXl4V+R0U/E+/uLyVx1X65LW8TA8QQHdnbdDallRekohw==} + resolution: {integrity: sha512-EFFGkixA39BcmHiCe2ECdrq02D6FCve5ka6ObbvrheXl4V+R0U/E+/uLyVx1X65LW8TA8QQHdnbdDallRekohw==, tarball: https://registry.npmjs.org/@oxfmt/binding-linux-x64-musl/-/binding-linux-x64-musl-0.36.0.tgz} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [linux] '@oxfmt/binding-openharmony-arm64@0.36.0': - resolution: {integrity: sha512-zr/t369wZWFOj1qf06Z5gGNjFymfUNDrxKMmr7FKiDRVI1sNsdKRCuRL4XVjtcptKQ+ao3FfxLN1vrynivmCYg==} + resolution: {integrity: sha512-zr/t369wZWFOj1qf06Z5gGNjFymfUNDrxKMmr7FKiDRVI1sNsdKRCuRL4XVjtcptKQ+ao3FfxLN1vrynivmCYg==, tarball: https://registry.npmjs.org/@oxfmt/binding-openharmony-arm64/-/binding-openharmony-arm64-0.36.0.tgz} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [openharmony] '@oxfmt/binding-win32-arm64-msvc@0.36.0': - resolution: {integrity: sha512-FxO7UksTv8h4olzACgrqAXNF6BP329+H322323iDrMB5V/+a1kcAw07fsOsUmqNrb9iJBsCQgH/zqcqp5903ag==} + resolution: {integrity: sha512-FxO7UksTv8h4olzACgrqAXNF6BP329+H322323iDrMB5V/+a1kcAw07fsOsUmqNrb9iJBsCQgH/zqcqp5903ag==, tarball: https://registry.npmjs.org/@oxfmt/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-0.36.0.tgz} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [win32] '@oxfmt/binding-win32-ia32-msvc@0.36.0': - resolution: {integrity: sha512-OjoMQ89H01M0oLMfr/CPNH1zi48ZIwxAKObUl57oh7ssUBNDp/2Vjf7E1TQ8M4oj4VFQ/byxl2SmcPNaI2YNDg==} + resolution: {integrity: sha512-OjoMQ89H01M0oLMfr/CPNH1zi48ZIwxAKObUl57oh7ssUBNDp/2Vjf7E1TQ8M4oj4VFQ/byxl2SmcPNaI2YNDg==, tarball: https://registry.npmjs.org/@oxfmt/binding-win32-ia32-msvc/-/binding-win32-ia32-msvc-0.36.0.tgz} engines: {node: ^20.19.0 || >=22.12.0} cpu: [ia32] os: [win32] '@oxfmt/binding-win32-x64-msvc@0.36.0': - resolution: {integrity: sha512-MoyeQ9S36ZTz/4bDhOKJgOBIDROd4dQ5AkT9iezhEaUBxAPdNX9Oq0jD8OSnCj3G4wam/XNxVWKMA52kmzmPtQ==} + resolution: {integrity: sha512-MoyeQ9S36ZTz/4bDhOKJgOBIDROd4dQ5AkT9iezhEaUBxAPdNX9Oq0jD8OSnCj3G4wam/XNxVWKMA52kmzmPtQ==, tarball: https://registry.npmjs.org/@oxfmt/binding-win32-x64-msvc/-/binding-win32-x64-msvc-0.36.0.tgz} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [win32] '@oxlint/binding-android-arm-eabi@1.51.0': - resolution: {integrity: sha512-jJYIqbx4sX+suIxWstc4P7SzhEwb4ArWA2KVrmEuu9vH2i0qM6QIHz/ehmbGE4/2fZbpuMuBzTl7UkfNoqiSgw==} + resolution: {integrity: sha512-jJYIqbx4sX+suIxWstc4P7SzhEwb4ArWA2KVrmEuu9vH2i0qM6QIHz/ehmbGE4/2fZbpuMuBzTl7UkfNoqiSgw==, tarball: https://registry.npmjs.org/@oxlint/binding-android-arm-eabi/-/binding-android-arm-eabi-1.51.0.tgz} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm] os: [android] '@oxlint/binding-android-arm64@1.51.0': - resolution: {integrity: sha512-GtXyBCcH4ti98YdiMNCrpBNGitx87EjEWxevnyhcBK12k/Vu4EzSB45rzSC4fGFUD6sQgeaxItRCEEWeVwPafw==} + resolution: {integrity: sha512-GtXyBCcH4ti98YdiMNCrpBNGitx87EjEWxevnyhcBK12k/Vu4EzSB45rzSC4fGFUD6sQgeaxItRCEEWeVwPafw==, tarball: https://registry.npmjs.org/@oxlint/binding-android-arm64/-/binding-android-arm64-1.51.0.tgz} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [android] '@oxlint/binding-darwin-arm64@1.51.0': - resolution: {integrity: sha512-3QJbeYaMHn6Bh2XeBXuITSsbnIctyTjvHf5nRjKYrT9pPeErNIpp5VDEeAXC0CZSwSVTsc8WOSDwgrAI24JolQ==} + resolution: {integrity: sha512-3QJbeYaMHn6Bh2XeBXuITSsbnIctyTjvHf5nRjKYrT9pPeErNIpp5VDEeAXC0CZSwSVTsc8WOSDwgrAI24JolQ==, tarball: https://registry.npmjs.org/@oxlint/binding-darwin-arm64/-/binding-darwin-arm64-1.51.0.tgz} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [darwin] '@oxlint/binding-darwin-x64@1.51.0': - resolution: {integrity: sha512-NzErhMaTEN1cY0E8C5APy74lw5VwsNfJfVPBMWPVQLqAbO0k4FFLjvHURvkUL+Y18Wu+8Vs1kbqPh2hjXYA4pg==} + resolution: {integrity: sha512-NzErhMaTEN1cY0E8C5APy74lw5VwsNfJfVPBMWPVQLqAbO0k4FFLjvHURvkUL+Y18Wu+8Vs1kbqPh2hjXYA4pg==, tarball: https://registry.npmjs.org/@oxlint/binding-darwin-x64/-/binding-darwin-x64-1.51.0.tgz} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [darwin] '@oxlint/binding-freebsd-x64@1.51.0': - resolution: {integrity: sha512-msAIh3vPAoKoHlOE/oe6Q5C/n9umypv/k81lED82ibrJotn+3YG2Qp1kiR8o/Dg5iOEU97c6tl0utxcyFenpFw==} + resolution: {integrity: sha512-msAIh3vPAoKoHlOE/oe6Q5C/n9umypv/k81lED82ibrJotn+3YG2Qp1kiR8o/Dg5iOEU97c6tl0utxcyFenpFw==, tarball: https://registry.npmjs.org/@oxlint/binding-freebsd-x64/-/binding-freebsd-x64-1.51.0.tgz} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [freebsd] '@oxlint/binding-linux-arm-gnueabihf@1.51.0': - resolution: {integrity: sha512-CqQPcvqYyMe9ZBot2stjGogEzk1z8gGAngIX7srSzrzexmXixwVxBdFZyxTVM0CjGfDeV+Ru0w25/WNjlMM2Hw==} + resolution: {integrity: sha512-CqQPcvqYyMe9ZBot2stjGogEzk1z8gGAngIX7srSzrzexmXixwVxBdFZyxTVM0CjGfDeV+Ru0w25/WNjlMM2Hw==, tarball: https://registry.npmjs.org/@oxlint/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-1.51.0.tgz} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm] os: [linux] '@oxlint/binding-linux-arm-musleabihf@1.51.0': - resolution: {integrity: sha512-dstrlYQgZMnyOssxSbolGCge/sDbko12N/35RBNuqLpoPbft2aeBidBAb0dvQlyBd9RJ6u8D4o4Eh8Un6iTgyQ==} + resolution: {integrity: sha512-dstrlYQgZMnyOssxSbolGCge/sDbko12N/35RBNuqLpoPbft2aeBidBAb0dvQlyBd9RJ6u8D4o4Eh8Un6iTgyQ==, tarball: https://registry.npmjs.org/@oxlint/binding-linux-arm-musleabihf/-/binding-linux-arm-musleabihf-1.51.0.tgz} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm] os: [linux] '@oxlint/binding-linux-arm64-gnu@1.51.0': - resolution: {integrity: sha512-QEjUpXO7d35rP1/raLGGbAsBLLGZIzV3ZbeSjqWlD3oRnxpRIZ6iL4o51XQHkconn3uKssc+1VKdtHJ81BBhDA==} + resolution: {integrity: sha512-QEjUpXO7d35rP1/raLGGbAsBLLGZIzV3ZbeSjqWlD3oRnxpRIZ6iL4o51XQHkconn3uKssc+1VKdtHJ81BBhDA==, tarball: https://registry.npmjs.org/@oxlint/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.51.0.tgz} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [linux] '@oxlint/binding-linux-arm64-musl@1.51.0': - resolution: {integrity: sha512-YSJua5irtG4DoMAjUapDTPhkQLHhBIY0G9JqlZS6/SZPzqDkPku/1GdWs0D6h/wyx0Iz31lNCfIaWKBQhzP0wQ==} + resolution: {integrity: sha512-YSJua5irtG4DoMAjUapDTPhkQLHhBIY0G9JqlZS6/SZPzqDkPku/1GdWs0D6h/wyx0Iz31lNCfIaWKBQhzP0wQ==, tarball: https://registry.npmjs.org/@oxlint/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.51.0.tgz} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [linux] '@oxlint/binding-linux-ppc64-gnu@1.51.0': - resolution: {integrity: sha512-7L4Wj2IEUNDETKssB9IDYt16T6WlF+X2jgC/hBq3diGHda9vJLpAgb09+D3quFq7TdkFtI7hwz/jmuQmQFPc1Q==} + resolution: {integrity: sha512-7L4Wj2IEUNDETKssB9IDYt16T6WlF+X2jgC/hBq3diGHda9vJLpAgb09+D3quFq7TdkFtI7hwz/jmuQmQFPc1Q==, tarball: https://registry.npmjs.org/@oxlint/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-1.51.0.tgz} engines: {node: ^20.19.0 || >=22.12.0} cpu: [ppc64] os: [linux] '@oxlint/binding-linux-riscv64-gnu@1.51.0': - resolution: {integrity: sha512-cBUHqtOXy76G41lOB401qpFoKx1xq17qYkhWrLSM7eEjiHM9sOtYqpr6ZdqCnN9s6ZpzudX4EkeHOFH2E9q0vA==} + resolution: {integrity: sha512-cBUHqtOXy76G41lOB401qpFoKx1xq17qYkhWrLSM7eEjiHM9sOtYqpr6ZdqCnN9s6ZpzudX4EkeHOFH2E9q0vA==, tarball: https://registry.npmjs.org/@oxlint/binding-linux-riscv64-gnu/-/binding-linux-riscv64-gnu-1.51.0.tgz} engines: {node: ^20.19.0 || >=22.12.0} cpu: [riscv64] os: [linux] '@oxlint/binding-linux-riscv64-musl@1.51.0': - resolution: {integrity: sha512-WKbg8CysgZcHfZX0ixQFBRSBvFZUHa3SBnEjHY2FVYt2nbNJEjzTxA3ZR5wMU0NOCNKIAFUFvAh5/XJKPRJuJg==} + resolution: {integrity: sha512-WKbg8CysgZcHfZX0ixQFBRSBvFZUHa3SBnEjHY2FVYt2nbNJEjzTxA3ZR5wMU0NOCNKIAFUFvAh5/XJKPRJuJg==, tarball: https://registry.npmjs.org/@oxlint/binding-linux-riscv64-musl/-/binding-linux-riscv64-musl-1.51.0.tgz} engines: {node: ^20.19.0 || >=22.12.0} cpu: [riscv64] os: [linux] '@oxlint/binding-linux-s390x-gnu@1.51.0': - resolution: {integrity: sha512-N1QRUvJTxqXNSu35YOufdjsAVmKVx5bkrggOWAhTWBc3J4qjcBwr1IfyLh/6YCg8sYRSR1GraldS9jUgJL/U4A==} + resolution: {integrity: sha512-N1QRUvJTxqXNSu35YOufdjsAVmKVx5bkrggOWAhTWBc3J4qjcBwr1IfyLh/6YCg8sYRSR1GraldS9jUgJL/U4A==, tarball: https://registry.npmjs.org/@oxlint/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-1.51.0.tgz} engines: {node: ^20.19.0 || >=22.12.0} cpu: [s390x] os: [linux] '@oxlint/binding-linux-x64-gnu@1.51.0': - resolution: {integrity: sha512-e0Mz0DizsCoqNIjeOg6OUKe8JKJWZ5zZlwsd05Bmr51Jo3AOL4UJnPvwKumr4BBtBrDZkCmOLhCvDGm95nJM2g==} + resolution: {integrity: sha512-e0Mz0DizsCoqNIjeOg6OUKe8JKJWZ5zZlwsd05Bmr51Jo3AOL4UJnPvwKumr4BBtBrDZkCmOLhCvDGm95nJM2g==, tarball: https://registry.npmjs.org/@oxlint/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.51.0.tgz} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [linux] '@oxlint/binding-linux-x64-musl@1.51.0': - resolution: {integrity: sha512-wD8HGTWhYBKXvRDvoBVB1y+fEYV01samhWQSy1Zkxq2vpezvMnjaFKRuiP6tBNITLGuffbNDEXOwcAhJ3gI5Ug==} + resolution: {integrity: sha512-wD8HGTWhYBKXvRDvoBVB1y+fEYV01samhWQSy1Zkxq2vpezvMnjaFKRuiP6tBNITLGuffbNDEXOwcAhJ3gI5Ug==, tarball: https://registry.npmjs.org/@oxlint/binding-linux-x64-musl/-/binding-linux-x64-musl-1.51.0.tgz} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [linux] '@oxlint/binding-openharmony-arm64@1.51.0': - resolution: {integrity: sha512-5NSwQ2hDEJ0GPXqikjWtwzgAQCsS7P9aLMNenjjKa+gknN3lTCwwwERsT6lKXSirfU3jLjexA2XQvQALh5h27w==} + resolution: {integrity: sha512-5NSwQ2hDEJ0GPXqikjWtwzgAQCsS7P9aLMNenjjKa+gknN3lTCwwwERsT6lKXSirfU3jLjexA2XQvQALh5h27w==, tarball: https://registry.npmjs.org/@oxlint/binding-openharmony-arm64/-/binding-openharmony-arm64-1.51.0.tgz} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [openharmony] '@oxlint/binding-win32-arm64-msvc@1.51.0': - resolution: {integrity: sha512-JEZyah1M0RHMw8d+jjSSJmSmO8sABA1J1RtrHYujGPeCkYg1NeH0TGuClpe2h5QtioRTaF57y/TZfn/2IFV6fA==} + resolution: {integrity: sha512-JEZyah1M0RHMw8d+jjSSJmSmO8sABA1J1RtrHYujGPeCkYg1NeH0TGuClpe2h5QtioRTaF57y/TZfn/2IFV6fA==, tarball: https://registry.npmjs.org/@oxlint/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.51.0.tgz} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [win32] '@oxlint/binding-win32-ia32-msvc@1.51.0': - resolution: {integrity: sha512-q3cEoKH6kwjz/WRyHwSf0nlD2F5Qw536kCXvmlSu+kaShzgrA0ojmh45CA81qL+7udfCaZL2SdKCZlLiGBVFlg==} + resolution: {integrity: sha512-q3cEoKH6kwjz/WRyHwSf0nlD2F5Qw536kCXvmlSu+kaShzgrA0ojmh45CA81qL+7udfCaZL2SdKCZlLiGBVFlg==, tarball: https://registry.npmjs.org/@oxlint/binding-win32-ia32-msvc/-/binding-win32-ia32-msvc-1.51.0.tgz} engines: {node: ^20.19.0 || >=22.12.0} cpu: [ia32] os: [win32] '@oxlint/binding-win32-x64-msvc@1.51.0': - resolution: {integrity: sha512-Q14+fOGb9T28nWF/0EUsYqERiRA7cl1oy4TJrGmLaqhm+aO2cV+JttboHI3CbdeMCAyDI1+NoSlrM7Melhp/cw==} + resolution: {integrity: sha512-Q14+fOGb9T28nWF/0EUsYqERiRA7cl1oy4TJrGmLaqhm+aO2cV+JttboHI3CbdeMCAyDI1+NoSlrM7Melhp/cw==, tarball: https://registry.npmjs.org/@oxlint/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.51.0.tgz} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [win32] '@petamoriken/float16@3.9.3': - resolution: {integrity: sha512-8awtpHXCx/bNpFt4mt2xdkgtgVvKqty8VbjHI/WWWQuEw+KLzFot3f4+LkQY9YmOtq7A5GdOnqoIC8Pdygjk2g==} + resolution: {integrity: sha512-8awtpHXCx/bNpFt4mt2xdkgtgVvKqty8VbjHI/WWWQuEw+KLzFot3f4+LkQY9YmOtq7A5GdOnqoIC8Pdygjk2g==, tarball: https://registry.npmjs.org/@petamoriken/float16/-/float16-3.9.3.tgz} '@pinojs/redact@0.4.0': resolution: {integrity: sha512-k2ENnmBugE/rzQfEcdWHcCY+/FM3VLzH9cYEsbdsoqrvzAKRhUZeRNhAZvB8OitQJ1TBed3yqWtdjzS6wJKBwg==} + '@polar-sh/sdk@0.47.0': + resolution: {integrity: sha512-tZEt8eLWsQVhmyfUQzXhnN84e5Cnu/JsYFnCci1ranWkIGveQc+wTiyzDCG9Tl1xiz1Y/ztPsAJ1fevj6ExdAA==, tarball: https://registry.npmjs.org/@polar-sh/sdk/-/sdk-0.47.0.tgz} + '@posthog/core@1.24.3': resolution: {integrity: sha512-nTyL1R/8V5vfdH37MbjXDYWFnUoxVijb2TnfJSNHz0+RBLtNnq0hNnBDCwWLl5yh1bzeJBYTT8UF+dV7D8y03w==} '@prisma/client-runtime-utils@7.4.2': - resolution: {integrity: sha512-cID+rzOEb38VyMsx5LwJMEY4NGIrWCNpKu/0ImbeooQ2Px7TI+kOt7cm0NelxUzF2V41UVVXAmYjANZQtCu1/Q==} + resolution: {integrity: sha512-cID+rzOEb38VyMsx5LwJMEY4NGIrWCNpKu/0ImbeooQ2Px7TI+kOt7cm0NelxUzF2V41UVVXAmYjANZQtCu1/Q==, tarball: https://registry.npmjs.org/@prisma/client-runtime-utils/-/client-runtime-utils-7.4.2.tgz} '@prisma/client@7.4.2': - resolution: {integrity: sha512-ts2mu+cQHriAhSxngO3StcYubBGTWDtu/4juZhXCUKOwgh26l+s4KD3vT2kMUzFyrYnll9u/3qWrtzRv9CGWzA==} + resolution: {integrity: sha512-ts2mu+cQHriAhSxngO3StcYubBGTWDtu/4juZhXCUKOwgh26l+s4KD3vT2kMUzFyrYnll9u/3qWrtzRv9CGWzA==, tarball: https://registry.npmjs.org/@prisma/client/-/client-7.4.2.tgz} engines: {node: ^20.19 || ^22.12 || >=24.0} peerDependencies: prisma: '*' @@ -2359,37 +2396,37 @@ packages: optional: true '@prisma/config@7.4.2': - resolution: {integrity: sha512-CftBjWxav99lzY1Z4oDgomdb1gh9BJFAOmWF6P2v1xRfXqQb56DfBub+QKcERRdNoAzCb3HXy3Zii8Vb4AsXhg==} + resolution: {integrity: sha512-CftBjWxav99lzY1Z4oDgomdb1gh9BJFAOmWF6P2v1xRfXqQb56DfBub+QKcERRdNoAzCb3HXy3Zii8Vb4AsXhg==, tarball: https://registry.npmjs.org/@prisma/config/-/config-7.4.2.tgz} '@prisma/debug@7.2.0': - resolution: {integrity: sha512-YSGTiSlBAVJPzX4ONZmMotL+ozJwQjRmZweQNIq/ER0tQJKJynNkRB3kyvt37eOfsbMCXk3gnLF6J9OJ4QWftw==} + resolution: {integrity: sha512-YSGTiSlBAVJPzX4ONZmMotL+ozJwQjRmZweQNIq/ER0tQJKJynNkRB3kyvt37eOfsbMCXk3gnLF6J9OJ4QWftw==, tarball: https://registry.npmjs.org/@prisma/debug/-/debug-7.2.0.tgz} '@prisma/debug@7.4.2': - resolution: {integrity: sha512-aP7qzu+g/JnbF6U69LMwHoUkELiserKmWsE2shYuEpNUJ4GrtxBCvZwCyCBHFSH2kLTF2l1goBlBh4wuvRq62w==} + resolution: {integrity: sha512-aP7qzu+g/JnbF6U69LMwHoUkELiserKmWsE2shYuEpNUJ4GrtxBCvZwCyCBHFSH2kLTF2l1goBlBh4wuvRq62w==, tarball: https://registry.npmjs.org/@prisma/debug/-/debug-7.4.2.tgz} '@prisma/dev@0.20.0': - resolution: {integrity: sha512-ovlBYwWor0OzG+yH4J3Ot+AneD818BttLA+Ii7wjbcLHUrnC4tbUPVGyNd3c/+71KETPKZfjhkTSpdS15dmXNQ==} + resolution: {integrity: sha512-ovlBYwWor0OzG+yH4J3Ot+AneD818BttLA+Ii7wjbcLHUrnC4tbUPVGyNd3c/+71KETPKZfjhkTSpdS15dmXNQ==, tarball: https://registry.npmjs.org/@prisma/dev/-/dev-0.20.0.tgz} '@prisma/engines-version@7.5.0-10.94a226be1cf2967af2541cca5529f0f7ba866919': - resolution: {integrity: sha512-5FIKY3KoYQlBuZC2yc16EXfVRQ8HY+fLqgxkYfWCtKhRb3ajCRzP/rPeoSx11+NueJDANdh4hjY36mdmrTcGSg==} + resolution: {integrity: sha512-5FIKY3KoYQlBuZC2yc16EXfVRQ8HY+fLqgxkYfWCtKhRb3ajCRzP/rPeoSx11+NueJDANdh4hjY36mdmrTcGSg==, tarball: https://registry.npmjs.org/@prisma/engines-version/-/engines-version-7.5.0-10.94a226be1cf2967af2541cca5529f0f7ba866919.tgz} '@prisma/engines@7.4.2': - resolution: {integrity: sha512-B+ZZhI4rXlzjVqRw/93AothEKOU5/x4oVyJFGo9RpHPnBwaPwk4Pi0Q4iGXipKxeXPs/dqljgNBjK0m8nocOJA==} + resolution: {integrity: sha512-B+ZZhI4rXlzjVqRw/93AothEKOU5/x4oVyJFGo9RpHPnBwaPwk4Pi0Q4iGXipKxeXPs/dqljgNBjK0m8nocOJA==, tarball: https://registry.npmjs.org/@prisma/engines/-/engines-7.4.2.tgz} '@prisma/fetch-engine@7.4.2': - resolution: {integrity: sha512-f/c/MwYpdJO7taLETU8rahEstLeXfYgQGlz5fycG7Fbmva3iPdzGmjiSWHeSWIgNnlXnelUdCJqyZnFocurZuA==} + resolution: {integrity: sha512-f/c/MwYpdJO7taLETU8rahEstLeXfYgQGlz5fycG7Fbmva3iPdzGmjiSWHeSWIgNnlXnelUdCJqyZnFocurZuA==, tarball: https://registry.npmjs.org/@prisma/fetch-engine/-/fetch-engine-7.4.2.tgz} '@prisma/get-platform@7.2.0': - resolution: {integrity: sha512-k1V0l0Td1732EHpAfi2eySTezyllok9dXb6UQanajkJQzPUGi3vO2z7jdkz67SypFTdmbnyGYxvEvYZdZsMAVA==} + resolution: {integrity: sha512-k1V0l0Td1732EHpAfi2eySTezyllok9dXb6UQanajkJQzPUGi3vO2z7jdkz67SypFTdmbnyGYxvEvYZdZsMAVA==, tarball: https://registry.npmjs.org/@prisma/get-platform/-/get-platform-7.2.0.tgz} '@prisma/get-platform@7.4.2': - resolution: {integrity: sha512-UTnChXRwiauzl/8wT4hhe7Xmixja9WE28oCnGpBtRejaHhvekx5kudr3R4Y9mLSA0kqGnAMeyTiKwDVMjaEVsw==} + resolution: {integrity: sha512-UTnChXRwiauzl/8wT4hhe7Xmixja9WE28oCnGpBtRejaHhvekx5kudr3R4Y9mLSA0kqGnAMeyTiKwDVMjaEVsw==, tarball: https://registry.npmjs.org/@prisma/get-platform/-/get-platform-7.4.2.tgz} '@prisma/query-plan-executor@7.2.0': - resolution: {integrity: sha512-EOZmNzcV8uJ0mae3DhTsiHgoNCuu1J9mULQpGCh62zN3PxPTd+qI9tJvk5jOst8WHKQNwJWR3b39t0XvfBB0WQ==} + resolution: {integrity: sha512-EOZmNzcV8uJ0mae3DhTsiHgoNCuu1J9mULQpGCh62zN3PxPTd+qI9tJvk5jOst8WHKQNwJWR3b39t0XvfBB0WQ==, tarball: https://registry.npmjs.org/@prisma/query-plan-executor/-/query-plan-executor-7.2.0.tgz} '@prisma/studio-core@0.13.1': - resolution: {integrity: sha512-agdqaPEePRHcQ7CexEfkX1RvSH9uWDb6pXrZnhCRykhDFAV0/0P3d07WtfiY8hZWb7oRU4v+NkT4cGFHkQJIPg==} + resolution: {integrity: sha512-agdqaPEePRHcQ7CexEfkX1RvSH9uWDb6pXrZnhCRykhDFAV0/0P3d07WtfiY8hZWb7oRU4v+NkT4cGFHkQJIPg==, tarball: https://registry.npmjs.org/@prisma/studio-core/-/studio-core-0.13.1.tgz} peerDependencies: '@types/react': ^18.0.0 || ^19.0.0 react: ^18.0.0 || ^19.0.0 @@ -3109,179 +3146,179 @@ packages: optional: true '@rolldown/binding-android-arm64@1.0.0-rc.12': - resolution: {integrity: sha512-pv1y2Fv0JybcykuiiD3qBOBdz6RteYojRFY1d+b95WVuzx211CRh+ytI/+9iVyWQ6koTh5dawe4S/yRfOFjgaA==} + resolution: {integrity: sha512-pv1y2Fv0JybcykuiiD3qBOBdz6RteYojRFY1d+b95WVuzx211CRh+ytI/+9iVyWQ6koTh5dawe4S/yRfOFjgaA==, tarball: https://registry.npmjs.org/@rolldown/binding-android-arm64/-/binding-android-arm64-1.0.0-rc.12.tgz} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [android] '@rolldown/binding-android-arm64@1.0.0-rc.8': - resolution: {integrity: sha512-5bcmMQDWEfWUq3m79Mcf/kbO6e5Jr6YjKSsA1RnpXR6k73hQ9z1B17+4h93jXpzHvS18p7bQHM1HN/fSd+9zog==} + resolution: {integrity: sha512-5bcmMQDWEfWUq3m79Mcf/kbO6e5Jr6YjKSsA1RnpXR6k73hQ9z1B17+4h93jXpzHvS18p7bQHM1HN/fSd+9zog==, tarball: https://registry.npmjs.org/@rolldown/binding-android-arm64/-/binding-android-arm64-1.0.0-rc.8.tgz} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [android] '@rolldown/binding-darwin-arm64@1.0.0-rc.12': - resolution: {integrity: sha512-cFYr6zTG/3PXXF3pUO+umXxt1wkRK/0AYT8lDwuqvRC+LuKYWSAQAQZjCWDQpAH172ZV6ieYrNnFzVVcnSflAg==} + resolution: {integrity: sha512-cFYr6zTG/3PXXF3pUO+umXxt1wkRK/0AYT8lDwuqvRC+LuKYWSAQAQZjCWDQpAH172ZV6ieYrNnFzVVcnSflAg==, tarball: https://registry.npmjs.org/@rolldown/binding-darwin-arm64/-/binding-darwin-arm64-1.0.0-rc.12.tgz} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [darwin] '@rolldown/binding-darwin-arm64@1.0.0-rc.8': - resolution: {integrity: sha512-dcHPd5N4g9w2iiPRJmAvO0fsIWzF2JPr9oSuTjxLL56qu+oML5aMbBMNwWbk58Mt3pc7vYs9CCScwLxdXPdRsg==} + resolution: {integrity: sha512-dcHPd5N4g9w2iiPRJmAvO0fsIWzF2JPr9oSuTjxLL56qu+oML5aMbBMNwWbk58Mt3pc7vYs9CCScwLxdXPdRsg==, tarball: https://registry.npmjs.org/@rolldown/binding-darwin-arm64/-/binding-darwin-arm64-1.0.0-rc.8.tgz} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [darwin] '@rolldown/binding-darwin-x64@1.0.0-rc.12': - resolution: {integrity: sha512-ZCsYknnHzeXYps0lGBz8JrF37GpE9bFVefrlmDrAQhOEi4IOIlcoU1+FwHEtyXGx2VkYAvhu7dyBf75EJQffBw==} + resolution: {integrity: sha512-ZCsYknnHzeXYps0lGBz8JrF37GpE9bFVefrlmDrAQhOEi4IOIlcoU1+FwHEtyXGx2VkYAvhu7dyBf75EJQffBw==, tarball: https://registry.npmjs.org/@rolldown/binding-darwin-x64/-/binding-darwin-x64-1.0.0-rc.12.tgz} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [darwin] '@rolldown/binding-darwin-x64@1.0.0-rc.8': - resolution: {integrity: sha512-mw0VzDvoj8AuR761QwpdCFN0sc/jspuc7eRYJetpLWd+XyansUrH3C7IgNw6swBOgQT9zBHNKsVCjzpfGJlhUA==} + resolution: {integrity: sha512-mw0VzDvoj8AuR761QwpdCFN0sc/jspuc7eRYJetpLWd+XyansUrH3C7IgNw6swBOgQT9zBHNKsVCjzpfGJlhUA==, tarball: https://registry.npmjs.org/@rolldown/binding-darwin-x64/-/binding-darwin-x64-1.0.0-rc.8.tgz} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [darwin] '@rolldown/binding-freebsd-x64@1.0.0-rc.12': - resolution: {integrity: sha512-dMLeprcVsyJsKolRXyoTH3NL6qtsT0Y2xeuEA8WQJquWFXkEC4bcu1rLZZSnZRMtAqwtrF/Ib9Ddtpa/Gkge9Q==} + resolution: {integrity: sha512-dMLeprcVsyJsKolRXyoTH3NL6qtsT0Y2xeuEA8WQJquWFXkEC4bcu1rLZZSnZRMtAqwtrF/Ib9Ddtpa/Gkge9Q==, tarball: https://registry.npmjs.org/@rolldown/binding-freebsd-x64/-/binding-freebsd-x64-1.0.0-rc.12.tgz} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [freebsd] '@rolldown/binding-freebsd-x64@1.0.0-rc.8': - resolution: {integrity: sha512-xNrRa6mQ9NmMIJBdJtPMPG8Mso0OhM526pDzc/EKnRrIrrkHD1E0Z6tONZRmUeJElfsQ6h44lQQCcDilSNIvSQ==} + resolution: {integrity: sha512-xNrRa6mQ9NmMIJBdJtPMPG8Mso0OhM526pDzc/EKnRrIrrkHD1E0Z6tONZRmUeJElfsQ6h44lQQCcDilSNIvSQ==, tarball: https://registry.npmjs.org/@rolldown/binding-freebsd-x64/-/binding-freebsd-x64-1.0.0-rc.8.tgz} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [freebsd] '@rolldown/binding-linux-arm-gnueabihf@1.0.0-rc.12': - resolution: {integrity: sha512-YqWjAgGC/9M1lz3GR1r1rP79nMgo3mQiiA+Hfo+pvKFK1fAJ1bCi0ZQVh8noOqNacuY1qIcfyVfP6HoyBRZ85Q==} + resolution: {integrity: sha512-YqWjAgGC/9M1lz3GR1r1rP79nMgo3mQiiA+Hfo+pvKFK1fAJ1bCi0ZQVh8noOqNacuY1qIcfyVfP6HoyBRZ85Q==, tarball: https://registry.npmjs.org/@rolldown/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-1.0.0-rc.12.tgz} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm] os: [linux] '@rolldown/binding-linux-arm-gnueabihf@1.0.0-rc.8': - resolution: {integrity: sha512-WgCKoO6O/rRUwimWfEJDeztwJJmuuX0N2bYLLRxmXDTtCwjToTOqk7Pashl/QpQn3H/jHjx0b5yCMbcTVYVpNg==} + resolution: {integrity: sha512-WgCKoO6O/rRUwimWfEJDeztwJJmuuX0N2bYLLRxmXDTtCwjToTOqk7Pashl/QpQn3H/jHjx0b5yCMbcTVYVpNg==, tarball: https://registry.npmjs.org/@rolldown/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-1.0.0-rc.8.tgz} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm] os: [linux] '@rolldown/binding-linux-arm64-gnu@1.0.0-rc.12': - resolution: {integrity: sha512-/I5AS4cIroLpslsmzXfwbe5OmWvSsrFuEw3mwvbQ1kDxJ822hFHIx+vsN/TAzNVyepI/j/GSzrtCIwQPeKCLIg==} + resolution: {integrity: sha512-/I5AS4cIroLpslsmzXfwbe5OmWvSsrFuEw3mwvbQ1kDxJ822hFHIx+vsN/TAzNVyepI/j/GSzrtCIwQPeKCLIg==, tarball: https://registry.npmjs.org/@rolldown/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.0.0-rc.12.tgz} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [linux] '@rolldown/binding-linux-arm64-gnu@1.0.0-rc.8': - resolution: {integrity: sha512-tOHgTOQa8G4Z3ULj4G3NYOGGJEsqPHR91dT72u63OtVsZ7B6wFJKOx+ZKv+pvwzxWz92/I2ycaqi2/Ll4l+rlg==} + resolution: {integrity: sha512-tOHgTOQa8G4Z3ULj4G3NYOGGJEsqPHR91dT72u63OtVsZ7B6wFJKOx+ZKv+pvwzxWz92/I2ycaqi2/Ll4l+rlg==, tarball: https://registry.npmjs.org/@rolldown/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.0.0-rc.8.tgz} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [linux] '@rolldown/binding-linux-arm64-musl@1.0.0-rc.12': - resolution: {integrity: sha512-V6/wZztnBqlx5hJQqNWwFdxIKN0m38p8Jas+VoSfgH54HSj9tKTt1dZvG6JRHcjh6D7TvrJPWFGaY9UBVOaWPw==} + resolution: {integrity: sha512-V6/wZztnBqlx5hJQqNWwFdxIKN0m38p8Jas+VoSfgH54HSj9tKTt1dZvG6JRHcjh6D7TvrJPWFGaY9UBVOaWPw==, tarball: https://registry.npmjs.org/@rolldown/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.0.0-rc.12.tgz} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [linux] '@rolldown/binding-linux-arm64-musl@1.0.0-rc.8': - resolution: {integrity: sha512-oRbxcgDujCi2Yp1GTxoUFsIFlZsuPHU4OV4AzNc3/6aUmR4lfm9FK0uwQu82PJsuUwnF2jFdop3Ep5c1uK7Uxg==} + resolution: {integrity: sha512-oRbxcgDujCi2Yp1GTxoUFsIFlZsuPHU4OV4AzNc3/6aUmR4lfm9FK0uwQu82PJsuUwnF2jFdop3Ep5c1uK7Uxg==, tarball: https://registry.npmjs.org/@rolldown/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.0.0-rc.8.tgz} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [linux] '@rolldown/binding-linux-ppc64-gnu@1.0.0-rc.12': - resolution: {integrity: sha512-AP3E9BpcUYliZCxa3w5Kwj9OtEVDYK6sVoUzy4vTOJsjPOgdaJZKFmN4oOlX0Wp0RPV2ETfmIra9x1xuayFB7g==} + resolution: {integrity: sha512-AP3E9BpcUYliZCxa3w5Kwj9OtEVDYK6sVoUzy4vTOJsjPOgdaJZKFmN4oOlX0Wp0RPV2ETfmIra9x1xuayFB7g==, tarball: https://registry.npmjs.org/@rolldown/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-1.0.0-rc.12.tgz} engines: {node: ^20.19.0 || >=22.12.0} cpu: [ppc64] os: [linux] '@rolldown/binding-linux-ppc64-gnu@1.0.0-rc.8': - resolution: {integrity: sha512-oaLRyUHw8kQE5M89RqrDJZ10GdmGJcMeCo8tvaE4ukOofqgjV84AbqBSH6tTPjeT2BHv+xlKj678GBuIb47lKA==} + resolution: {integrity: sha512-oaLRyUHw8kQE5M89RqrDJZ10GdmGJcMeCo8tvaE4ukOofqgjV84AbqBSH6tTPjeT2BHv+xlKj678GBuIb47lKA==, tarball: https://registry.npmjs.org/@rolldown/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-1.0.0-rc.8.tgz} engines: {node: ^20.19.0 || >=22.12.0} cpu: [ppc64] os: [linux] '@rolldown/binding-linux-s390x-gnu@1.0.0-rc.12': - resolution: {integrity: sha512-nWwpvUSPkoFmZo0kQazZYOrT7J5DGOJ/+QHHzjvNlooDZED8oH82Yg67HvehPPLAg5fUff7TfWFHQS8IV1n3og==} + resolution: {integrity: sha512-nWwpvUSPkoFmZo0kQazZYOrT7J5DGOJ/+QHHzjvNlooDZED8oH82Yg67HvehPPLAg5fUff7TfWFHQS8IV1n3og==, tarball: https://registry.npmjs.org/@rolldown/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-1.0.0-rc.12.tgz} engines: {node: ^20.19.0 || >=22.12.0} cpu: [s390x] os: [linux] '@rolldown/binding-linux-s390x-gnu@1.0.0-rc.8': - resolution: {integrity: sha512-1hjSKFrod5MwBBdLOOA0zpUuSfSDkYIY+QqcMcIU1WOtswZtZdUkcFcZza9b2HcAb0bnpmmyo0LZcaxLb2ov1g==} + resolution: {integrity: sha512-1hjSKFrod5MwBBdLOOA0zpUuSfSDkYIY+QqcMcIU1WOtswZtZdUkcFcZza9b2HcAb0bnpmmyo0LZcaxLb2ov1g==, tarball: https://registry.npmjs.org/@rolldown/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-1.0.0-rc.8.tgz} engines: {node: ^20.19.0 || >=22.12.0} cpu: [s390x] os: [linux] '@rolldown/binding-linux-x64-gnu@1.0.0-rc.12': - resolution: {integrity: sha512-RNrafz5bcwRy+O9e6P8Z/OCAJW/A+qtBczIqVYwTs14pf4iV1/+eKEjdOUta93q2TsT/FI0XYDP3TCky38LMAg==} + resolution: {integrity: sha512-RNrafz5bcwRy+O9e6P8Z/OCAJW/A+qtBczIqVYwTs14pf4iV1/+eKEjdOUta93q2TsT/FI0XYDP3TCky38LMAg==, tarball: https://registry.npmjs.org/@rolldown/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.0.0-rc.12.tgz} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [linux] '@rolldown/binding-linux-x64-gnu@1.0.0-rc.8': - resolution: {integrity: sha512-a1+F0aV4Wy9tT3o+cHl3XhOy6aFV+B8Ll+/JFj98oGkb6lGk3BNgrxd+80RwYRVd23oLGvj3LwluKYzlv1PEuw==} + resolution: {integrity: sha512-a1+F0aV4Wy9tT3o+cHl3XhOy6aFV+B8Ll+/JFj98oGkb6lGk3BNgrxd+80RwYRVd23oLGvj3LwluKYzlv1PEuw==, tarball: https://registry.npmjs.org/@rolldown/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.0.0-rc.8.tgz} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [linux] '@rolldown/binding-linux-x64-musl@1.0.0-rc.12': - resolution: {integrity: sha512-Jpw/0iwoKWx3LJ2rc1yjFrj+T7iHZn2JDg1Yny1ma0luviFS4mhAIcd1LFNxK3EYu3DHWCps0ydXQ5i/rrJ2ig==} + resolution: {integrity: sha512-Jpw/0iwoKWx3LJ2rc1yjFrj+T7iHZn2JDg1Yny1ma0luviFS4mhAIcd1LFNxK3EYu3DHWCps0ydXQ5i/rrJ2ig==, tarball: https://registry.npmjs.org/@rolldown/binding-linux-x64-musl/-/binding-linux-x64-musl-1.0.0-rc.12.tgz} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [linux] '@rolldown/binding-linux-x64-musl@1.0.0-rc.8': - resolution: {integrity: sha512-bGyXCFU11seFrf7z8PcHSwGEiFVkZ9vs+auLacVOQrVsI8PFHJzzJROF3P6b0ODDmXr0m6Tj5FlDhcXVk0Jp8w==} + resolution: {integrity: sha512-bGyXCFU11seFrf7z8PcHSwGEiFVkZ9vs+auLacVOQrVsI8PFHJzzJROF3P6b0ODDmXr0m6Tj5FlDhcXVk0Jp8w==, tarball: https://registry.npmjs.org/@rolldown/binding-linux-x64-musl/-/binding-linux-x64-musl-1.0.0-rc.8.tgz} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [linux] '@rolldown/binding-openharmony-arm64@1.0.0-rc.12': - resolution: {integrity: sha512-vRugONE4yMfVn0+7lUKdKvN4D5YusEiPilaoO2sgUWpCvrncvWgPMzK00ZFFJuiPgLwgFNP5eSiUlv2tfc+lpA==} + resolution: {integrity: sha512-vRugONE4yMfVn0+7lUKdKvN4D5YusEiPilaoO2sgUWpCvrncvWgPMzK00ZFFJuiPgLwgFNP5eSiUlv2tfc+lpA==, tarball: https://registry.npmjs.org/@rolldown/binding-openharmony-arm64/-/binding-openharmony-arm64-1.0.0-rc.12.tgz} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [openharmony] '@rolldown/binding-openharmony-arm64@1.0.0-rc.8': - resolution: {integrity: sha512-n8d+L2bKgf9G3+AM0bhHFWdlz9vYKNim39ujRTieukdRek0RAo2TfG2uEnV9spa4r4oHUfL9IjcY3M9SlqN1gw==} + resolution: {integrity: sha512-n8d+L2bKgf9G3+AM0bhHFWdlz9vYKNim39ujRTieukdRek0RAo2TfG2uEnV9spa4r4oHUfL9IjcY3M9SlqN1gw==, tarball: https://registry.npmjs.org/@rolldown/binding-openharmony-arm64/-/binding-openharmony-arm64-1.0.0-rc.8.tgz} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [openharmony] '@rolldown/binding-wasm32-wasi@1.0.0-rc.12': - resolution: {integrity: sha512-ykGiLr/6kkiHc0XnBfmFJuCjr5ZYKKofkx+chJWDjitX+KsJuAmrzWhwyOMSHzPhzOHOy7u9HlFoa5MoAOJ/Zg==} + resolution: {integrity: sha512-ykGiLr/6kkiHc0XnBfmFJuCjr5ZYKKofkx+chJWDjitX+KsJuAmrzWhwyOMSHzPhzOHOy7u9HlFoa5MoAOJ/Zg==, tarball: https://registry.npmjs.org/@rolldown/binding-wasm32-wasi/-/binding-wasm32-wasi-1.0.0-rc.12.tgz} engines: {node: '>=14.0.0'} cpu: [wasm32] '@rolldown/binding-wasm32-wasi@1.0.0-rc.8': - resolution: {integrity: sha512-4R4iJDIk7BrJdteAbEAICXPoA7vZoY/M0OBfcRlQxzQvUYMcEp2GbC/C8UOgQJhu2TjGTpX1H8vVO1xHWcRqQA==} + resolution: {integrity: sha512-4R4iJDIk7BrJdteAbEAICXPoA7vZoY/M0OBfcRlQxzQvUYMcEp2GbC/C8UOgQJhu2TjGTpX1H8vVO1xHWcRqQA==, tarball: https://registry.npmjs.org/@rolldown/binding-wasm32-wasi/-/binding-wasm32-wasi-1.0.0-rc.8.tgz} engines: {node: '>=14.0.0'} cpu: [wasm32] '@rolldown/binding-win32-arm64-msvc@1.0.0-rc.12': - resolution: {integrity: sha512-5eOND4duWkwx1AzCxadcOrNeighiLwMInEADT0YM7xeEOOFcovWZCq8dadXgcRHSf3Ulh1kFo/qvzoFiCLOL1Q==} + resolution: {integrity: sha512-5eOND4duWkwx1AzCxadcOrNeighiLwMInEADT0YM7xeEOOFcovWZCq8dadXgcRHSf3Ulh1kFo/qvzoFiCLOL1Q==, tarball: https://registry.npmjs.org/@rolldown/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.0.0-rc.12.tgz} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [win32] '@rolldown/binding-win32-arm64-msvc@1.0.0-rc.8': - resolution: {integrity: sha512-3lwnklba9qQOpFnQ7EW+A1m4bZTWXZE4jtehsZ0YOl2ivW1FQqp5gY7X2DLuKITggesyuLwcmqS11fA7NtrmrA==} + resolution: {integrity: sha512-3lwnklba9qQOpFnQ7EW+A1m4bZTWXZE4jtehsZ0YOl2ivW1FQqp5gY7X2DLuKITggesyuLwcmqS11fA7NtrmrA==, tarball: https://registry.npmjs.org/@rolldown/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.0.0-rc.8.tgz} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [win32] '@rolldown/binding-win32-x64-msvc@1.0.0-rc.12': - resolution: {integrity: sha512-PyqoipaswDLAZtot351MLhrlrh6lcZPo2LSYE+VDxbVk24LVKAGOuE4hb8xZQmrPAuEtTZW8E6D2zc5EUZX4Lw==} + resolution: {integrity: sha512-PyqoipaswDLAZtot351MLhrlrh6lcZPo2LSYE+VDxbVk24LVKAGOuE4hb8xZQmrPAuEtTZW8E6D2zc5EUZX4Lw==, tarball: https://registry.npmjs.org/@rolldown/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.0.0-rc.12.tgz} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [win32] '@rolldown/binding-win32-x64-msvc@1.0.0-rc.8': - resolution: {integrity: sha512-VGjCx9Ha1P/r3tXGDZyG0Fcq7Q0Afnk64aaKzr1m40vbn1FL8R3W0V1ELDvPgzLXaaqK/9PnsqSaLWXfn6JtGQ==} + resolution: {integrity: sha512-VGjCx9Ha1P/r3tXGDZyG0Fcq7Q0Afnk64aaKzr1m40vbn1FL8R3W0V1ELDvPgzLXaaqK/9PnsqSaLWXfn6JtGQ==, tarball: https://registry.npmjs.org/@rolldown/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.0.0-rc.8.tgz} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [win32] @@ -3296,127 +3333,127 @@ packages: resolution: {integrity: sha512-wzJwL82/arVfeSP3BLr1oTy40XddjtEdrdgtJ4lLRBu06mP3q/8HGM6K0JRlQuTA3XB0pNJx2so/nmpY4xyOew==} '@rollup/rollup-android-arm-eabi@4.59.0': - resolution: {integrity: sha512-upnNBkA6ZH2VKGcBj9Fyl9IGNPULcjXRlg0LLeaioQWueH30p6IXtJEbKAgvyv+mJaMxSm1l6xwDXYjpEMiLMg==} + resolution: {integrity: sha512-upnNBkA6ZH2VKGcBj9Fyl9IGNPULcjXRlg0LLeaioQWueH30p6IXtJEbKAgvyv+mJaMxSm1l6xwDXYjpEMiLMg==, tarball: https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.59.0.tgz} cpu: [arm] os: [android] '@rollup/rollup-android-arm64@4.59.0': - resolution: {integrity: sha512-hZ+Zxj3SySm4A/DylsDKZAeVg0mvi++0PYVceVyX7hemkw7OreKdCvW2oQ3T1FMZvCaQXqOTHb8qmBShoqk69Q==} + resolution: {integrity: sha512-hZ+Zxj3SySm4A/DylsDKZAeVg0mvi++0PYVceVyX7hemkw7OreKdCvW2oQ3T1FMZvCaQXqOTHb8qmBShoqk69Q==, tarball: https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.59.0.tgz} cpu: [arm64] os: [android] '@rollup/rollup-darwin-arm64@4.59.0': - resolution: {integrity: sha512-W2Psnbh1J8ZJw0xKAd8zdNgF9HRLkdWwwdWqubSVk0pUuQkoHnv7rx4GiF9rT4t5DIZGAsConRE3AxCdJ4m8rg==} + resolution: {integrity: sha512-W2Psnbh1J8ZJw0xKAd8zdNgF9HRLkdWwwdWqubSVk0pUuQkoHnv7rx4GiF9rT4t5DIZGAsConRE3AxCdJ4m8rg==, tarball: https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.59.0.tgz} cpu: [arm64] os: [darwin] '@rollup/rollup-darwin-x64@4.59.0': - resolution: {integrity: sha512-ZW2KkwlS4lwTv7ZVsYDiARfFCnSGhzYPdiOU4IM2fDbL+QGlyAbjgSFuqNRbSthybLbIJ915UtZBtmuLrQAT/w==} + resolution: {integrity: sha512-ZW2KkwlS4lwTv7ZVsYDiARfFCnSGhzYPdiOU4IM2fDbL+QGlyAbjgSFuqNRbSthybLbIJ915UtZBtmuLrQAT/w==, tarball: https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.59.0.tgz} cpu: [x64] os: [darwin] '@rollup/rollup-freebsd-arm64@4.59.0': - resolution: {integrity: sha512-EsKaJ5ytAu9jI3lonzn3BgG8iRBjV4LxZexygcQbpiU0wU0ATxhNVEpXKfUa0pS05gTcSDMKpn3Sx+QB9RlTTA==} + resolution: {integrity: sha512-EsKaJ5ytAu9jI3lonzn3BgG8iRBjV4LxZexygcQbpiU0wU0ATxhNVEpXKfUa0pS05gTcSDMKpn3Sx+QB9RlTTA==, tarball: https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.59.0.tgz} cpu: [arm64] os: [freebsd] '@rollup/rollup-freebsd-x64@4.59.0': - resolution: {integrity: sha512-d3DuZi2KzTMjImrxoHIAODUZYoUUMsuUiY4SRRcJy6NJoZ6iIqWnJu9IScV9jXysyGMVuW+KNzZvBLOcpdl3Vg==} + resolution: {integrity: sha512-d3DuZi2KzTMjImrxoHIAODUZYoUUMsuUiY4SRRcJy6NJoZ6iIqWnJu9IScV9jXysyGMVuW+KNzZvBLOcpdl3Vg==, tarball: https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.59.0.tgz} cpu: [x64] os: [freebsd] '@rollup/rollup-linux-arm-gnueabihf@4.59.0': - resolution: {integrity: sha512-t4ONHboXi/3E0rT6OZl1pKbl2Vgxf9vJfWgmUoCEVQVxhW6Cw/c8I6hbbu7DAvgp82RKiH7TpLwxnJeKv2pbsw==} + resolution: {integrity: sha512-t4ONHboXi/3E0rT6OZl1pKbl2Vgxf9vJfWgmUoCEVQVxhW6Cw/c8I6hbbu7DAvgp82RKiH7TpLwxnJeKv2pbsw==, tarball: https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.59.0.tgz} cpu: [arm] os: [linux] '@rollup/rollup-linux-arm-musleabihf@4.59.0': - resolution: {integrity: sha512-CikFT7aYPA2ufMD086cVORBYGHffBo4K8MQ4uPS/ZnY54GKj36i196u8U+aDVT2LX4eSMbyHtyOh7D7Zvk2VvA==} + resolution: {integrity: sha512-CikFT7aYPA2ufMD086cVORBYGHffBo4K8MQ4uPS/ZnY54GKj36i196u8U+aDVT2LX4eSMbyHtyOh7D7Zvk2VvA==, tarball: https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.59.0.tgz} cpu: [arm] os: [linux] '@rollup/rollup-linux-arm64-gnu@4.59.0': - resolution: {integrity: sha512-jYgUGk5aLd1nUb1CtQ8E+t5JhLc9x5WdBKew9ZgAXg7DBk0ZHErLHdXM24rfX+bKrFe+Xp5YuJo54I5HFjGDAA==} + resolution: {integrity: sha512-jYgUGk5aLd1nUb1CtQ8E+t5JhLc9x5WdBKew9ZgAXg7DBk0ZHErLHdXM24rfX+bKrFe+Xp5YuJo54I5HFjGDAA==, tarball: https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.59.0.tgz} cpu: [arm64] os: [linux] '@rollup/rollup-linux-arm64-musl@4.59.0': - resolution: {integrity: sha512-peZRVEdnFWZ5Bh2KeumKG9ty7aCXzzEsHShOZEFiCQlDEepP1dpUl/SrUNXNg13UmZl+gzVDPsiCwnV1uI0RUA==} + resolution: {integrity: sha512-peZRVEdnFWZ5Bh2KeumKG9ty7aCXzzEsHShOZEFiCQlDEepP1dpUl/SrUNXNg13UmZl+gzVDPsiCwnV1uI0RUA==, tarball: https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.59.0.tgz} cpu: [arm64] os: [linux] '@rollup/rollup-linux-loong64-gnu@4.59.0': - resolution: {integrity: sha512-gbUSW/97f7+r4gHy3Jlup8zDG190AuodsWnNiXErp9mT90iCy9NKKU0Xwx5k8VlRAIV2uU9CsMnEFg/xXaOfXg==} + resolution: {integrity: sha512-gbUSW/97f7+r4gHy3Jlup8zDG190AuodsWnNiXErp9mT90iCy9NKKU0Xwx5k8VlRAIV2uU9CsMnEFg/xXaOfXg==, tarball: https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.59.0.tgz} cpu: [loong64] os: [linux] '@rollup/rollup-linux-loong64-musl@4.59.0': - resolution: {integrity: sha512-yTRONe79E+o0FWFijasoTjtzG9EBedFXJMl888NBEDCDV9I2wGbFFfJQQe63OijbFCUZqxpHz1GzpbtSFikJ4Q==} + resolution: {integrity: sha512-yTRONe79E+o0FWFijasoTjtzG9EBedFXJMl888NBEDCDV9I2wGbFFfJQQe63OijbFCUZqxpHz1GzpbtSFikJ4Q==, tarball: https://registry.npmjs.org/@rollup/rollup-linux-loong64-musl/-/rollup-linux-loong64-musl-4.59.0.tgz} cpu: [loong64] os: [linux] '@rollup/rollup-linux-ppc64-gnu@4.59.0': - resolution: {integrity: sha512-sw1o3tfyk12k3OEpRddF68a1unZ5VCN7zoTNtSn2KndUE+ea3m3ROOKRCZxEpmT9nsGnogpFP9x6mnLTCaoLkA==} + resolution: {integrity: sha512-sw1o3tfyk12k3OEpRddF68a1unZ5VCN7zoTNtSn2KndUE+ea3m3ROOKRCZxEpmT9nsGnogpFP9x6mnLTCaoLkA==, tarball: https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.59.0.tgz} cpu: [ppc64] os: [linux] '@rollup/rollup-linux-ppc64-musl@4.59.0': - resolution: {integrity: sha512-+2kLtQ4xT3AiIxkzFVFXfsmlZiG5FXYW7ZyIIvGA7Bdeuh9Z0aN4hVyXS/G1E9bTP/vqszNIN/pUKCk/BTHsKA==} + resolution: {integrity: sha512-+2kLtQ4xT3AiIxkzFVFXfsmlZiG5FXYW7ZyIIvGA7Bdeuh9Z0aN4hVyXS/G1E9bTP/vqszNIN/pUKCk/BTHsKA==, tarball: https://registry.npmjs.org/@rollup/rollup-linux-ppc64-musl/-/rollup-linux-ppc64-musl-4.59.0.tgz} cpu: [ppc64] os: [linux] '@rollup/rollup-linux-riscv64-gnu@4.59.0': - resolution: {integrity: sha512-NDYMpsXYJJaj+I7UdwIuHHNxXZ/b/N2hR15NyH3m2qAtb/hHPA4g4SuuvrdxetTdndfj9b1WOmy73kcPRoERUg==} + resolution: {integrity: sha512-NDYMpsXYJJaj+I7UdwIuHHNxXZ/b/N2hR15NyH3m2qAtb/hHPA4g4SuuvrdxetTdndfj9b1WOmy73kcPRoERUg==, tarball: https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.59.0.tgz} cpu: [riscv64] os: [linux] '@rollup/rollup-linux-riscv64-musl@4.59.0': - resolution: {integrity: sha512-nLckB8WOqHIf1bhymk+oHxvM9D3tyPndZH8i8+35p/1YiVoVswPid2yLzgX7ZJP0KQvnkhM4H6QZ5m0LzbyIAg==} + resolution: {integrity: sha512-nLckB8WOqHIf1bhymk+oHxvM9D3tyPndZH8i8+35p/1YiVoVswPid2yLzgX7ZJP0KQvnkhM4H6QZ5m0LzbyIAg==, tarball: https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.59.0.tgz} cpu: [riscv64] os: [linux] '@rollup/rollup-linux-s390x-gnu@4.59.0': - resolution: {integrity: sha512-oF87Ie3uAIvORFBpwnCvUzdeYUqi2wY6jRFWJAy1qus/udHFYIkplYRW+wo+GRUP4sKzYdmE1Y3+rY5Gc4ZO+w==} + resolution: {integrity: sha512-oF87Ie3uAIvORFBpwnCvUzdeYUqi2wY6jRFWJAy1qus/udHFYIkplYRW+wo+GRUP4sKzYdmE1Y3+rY5Gc4ZO+w==, tarball: https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.59.0.tgz} cpu: [s390x] os: [linux] '@rollup/rollup-linux-x64-gnu@4.59.0': - resolution: {integrity: sha512-3AHmtQq/ppNuUspKAlvA8HtLybkDflkMuLK4DPo77DfthRb71V84/c4MlWJXixZz4uruIH4uaa07IqoAkG64fg==} + resolution: {integrity: sha512-3AHmtQq/ppNuUspKAlvA8HtLybkDflkMuLK4DPo77DfthRb71V84/c4MlWJXixZz4uruIH4uaa07IqoAkG64fg==, tarball: https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.59.0.tgz} cpu: [x64] os: [linux] '@rollup/rollup-linux-x64-musl@4.59.0': - resolution: {integrity: sha512-2UdiwS/9cTAx7qIUZB/fWtToJwvt0Vbo0zmnYt7ED35KPg13Q0ym1g442THLC7VyI6JfYTP4PiSOWyoMdV2/xg==} + resolution: {integrity: sha512-2UdiwS/9cTAx7qIUZB/fWtToJwvt0Vbo0zmnYt7ED35KPg13Q0ym1g442THLC7VyI6JfYTP4PiSOWyoMdV2/xg==, tarball: https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.59.0.tgz} cpu: [x64] os: [linux] '@rollup/rollup-openbsd-x64@4.59.0': - resolution: {integrity: sha512-M3bLRAVk6GOwFlPTIxVBSYKUaqfLrn8l0psKinkCFxl4lQvOSz8ZrKDz2gxcBwHFpci0B6rttydI4IpS4IS/jQ==} + resolution: {integrity: sha512-M3bLRAVk6GOwFlPTIxVBSYKUaqfLrn8l0psKinkCFxl4lQvOSz8ZrKDz2gxcBwHFpci0B6rttydI4IpS4IS/jQ==, tarball: https://registry.npmjs.org/@rollup/rollup-openbsd-x64/-/rollup-openbsd-x64-4.59.0.tgz} cpu: [x64] os: [openbsd] '@rollup/rollup-openharmony-arm64@4.59.0': - resolution: {integrity: sha512-tt9KBJqaqp5i5HUZzoafHZX8b5Q2Fe7UjYERADll83O4fGqJ49O1FsL6LpdzVFQcpwvnyd0i+K/VSwu/o/nWlA==} + resolution: {integrity: sha512-tt9KBJqaqp5i5HUZzoafHZX8b5Q2Fe7UjYERADll83O4fGqJ49O1FsL6LpdzVFQcpwvnyd0i+K/VSwu/o/nWlA==, tarball: https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.59.0.tgz} cpu: [arm64] os: [openharmony] '@rollup/rollup-win32-arm64-msvc@4.59.0': - resolution: {integrity: sha512-V5B6mG7OrGTwnxaNUzZTDTjDS7F75PO1ae6MJYdiMu60sq0CqN5CVeVsbhPxalupvTX8gXVSU9gq+Rx1/hvu6A==} + resolution: {integrity: sha512-V5B6mG7OrGTwnxaNUzZTDTjDS7F75PO1ae6MJYdiMu60sq0CqN5CVeVsbhPxalupvTX8gXVSU9gq+Rx1/hvu6A==, tarball: https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.59.0.tgz} cpu: [arm64] os: [win32] '@rollup/rollup-win32-ia32-msvc@4.59.0': - resolution: {integrity: sha512-UKFMHPuM9R0iBegwzKF4y0C4J9u8C6MEJgFuXTBerMk7EJ92GFVFYBfOZaSGLu6COf7FxpQNqhNS4c4icUPqxA==} + resolution: {integrity: sha512-UKFMHPuM9R0iBegwzKF4y0C4J9u8C6MEJgFuXTBerMk7EJ92GFVFYBfOZaSGLu6COf7FxpQNqhNS4c4icUPqxA==, tarball: https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.59.0.tgz} cpu: [ia32] os: [win32] '@rollup/rollup-win32-x64-gnu@4.59.0': - resolution: {integrity: sha512-laBkYlSS1n2L8fSo1thDNGrCTQMmxjYY5G0WFWjFFYZkKPjsMBsgJfGf4TLxXrF6RyhI60L8TMOjBMvXiTcxeA==} + resolution: {integrity: sha512-laBkYlSS1n2L8fSo1thDNGrCTQMmxjYY5G0WFWjFFYZkKPjsMBsgJfGf4TLxXrF6RyhI60L8TMOjBMvXiTcxeA==, tarball: https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.59.0.tgz} cpu: [x64] os: [win32] '@rollup/rollup-win32-x64-msvc@4.59.0': - resolution: {integrity: sha512-2HRCml6OztYXyJXAvdDXPKcawukWY2GpR5/nxKp4iBgiO3wcoEGkAaqctIbZcNB6KlUQBIqt8VYkNSj2397EfA==} + resolution: {integrity: sha512-2HRCml6OztYXyJXAvdDXPKcawukWY2GpR5/nxKp4iBgiO3wcoEGkAaqctIbZcNB6KlUQBIqt8VYkNSj2397EfA==, tarball: https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.59.0.tgz} cpu: [x64] os: [win32] @@ -3491,7 +3528,7 @@ packages: resolution: {integrity: sha512-83yeghZ2xxin3Nj8z1NMd/NCuca+gsYXswywDy5bHvwlWL8tpTQmzGeUuHd9FC3E/SBEMvzJRwWEOz5gGes9Qg==} '@sinclair/typebox@0.34.48': - resolution: {integrity: sha512-kKJTNuK3AQOrgjjotVxMrCn1sUJwM76wMszfq1kdU4uYVJjvEWuFQ6HgvLt4Xz3fSmZlTOxJ/Ie13KnIcWQXFA==} + resolution: {integrity: sha512-kKJTNuK3AQOrgjjotVxMrCn1sUJwM76wMszfq1kdU4uYVJjvEWuFQ6HgvLt4Xz3fSmZlTOxJ/Ie13KnIcWQXFA==, tarball: https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.34.48.tgz} '@sindresorhus/merge-streams@4.0.0': resolution: {integrity: sha512-tlqY9xq5ukxTUZBmoOp+m61cqwQD5pHJtFY3Mn8CA8ps6yghLH/Hw8UPdqg4OLmFW3IFlcXnQNmo/dh8HzXYIQ==} @@ -3510,7 +3547,7 @@ packages: resolution: {integrity: sha512-JQ5TuMi45Owi4/BIMAJBoSQoOJu12oOk/gADqlcUL9JEdHB8vyjUSsxqeNXnmXHjYKMi2WcYtezGEEhqUI/E2g==} '@t3-oss/env-core@0.12.0': - resolution: {integrity: sha512-lOPj8d9nJJTt81mMuN9GMk8x5veOt7q9m11OSnCBJhwp1QrL/qR+M8Y467ULBSm9SunosryWNbmQQbgoiMgcdw==} + resolution: {integrity: sha512-lOPj8d9nJJTt81mMuN9GMk8x5veOt7q9m11OSnCBJhwp1QrL/qR+M8Y467ULBSm9SunosryWNbmQQbgoiMgcdw==, tarball: https://registry.npmjs.org/@t3-oss/env-core/-/env-core-0.12.0.tgz} peerDependencies: typescript: '>=5.0.0' valibot: ^1.0.0-beta.7 || ^1.0.0 @@ -3548,115 +3585,115 @@ packages: resolution: {integrity: sha512-pXS+wJ2gZpVXqFaUEjojq7jzMpTGf8rU6ipJz5ovJV6PUGmlJ+jvIwGrzdHdQ80Sg+wmQxUFuoW1UAAwHNEdFA==} '@tailwindcss/oxide-android-arm64@4.2.1': - resolution: {integrity: sha512-eZ7G1Zm5EC8OOKaesIKuw77jw++QJ2lL9N+dDpdQiAB/c/B2wDh0QPFHbkBVrXnwNugvrbJFk1gK2SsVjwWReg==} + resolution: {integrity: sha512-eZ7G1Zm5EC8OOKaesIKuw77jw++QJ2lL9N+dDpdQiAB/c/B2wDh0QPFHbkBVrXnwNugvrbJFk1gK2SsVjwWReg==, tarball: https://registry.npmjs.org/@tailwindcss/oxide-android-arm64/-/oxide-android-arm64-4.2.1.tgz} engines: {node: '>= 20'} cpu: [arm64] os: [android] '@tailwindcss/oxide-android-arm64@4.2.2': - resolution: {integrity: sha512-dXGR1n+P3B6748jZO/SvHZq7qBOqqzQ+yFrXpoOWWALWndF9MoSKAT3Q0fYgAzYzGhxNYOoysRvYlpixRBBoDg==} + resolution: {integrity: sha512-dXGR1n+P3B6748jZO/SvHZq7qBOqqzQ+yFrXpoOWWALWndF9MoSKAT3Q0fYgAzYzGhxNYOoysRvYlpixRBBoDg==, tarball: https://registry.npmjs.org/@tailwindcss/oxide-android-arm64/-/oxide-android-arm64-4.2.2.tgz} engines: {node: '>= 20'} cpu: [arm64] os: [android] '@tailwindcss/oxide-darwin-arm64@4.2.1': - resolution: {integrity: sha512-q/LHkOstoJ7pI1J0q6djesLzRvQSIfEto148ppAd+BVQK0JYjQIFSK3JgYZJa+Yzi0DDa52ZsQx2rqytBnf8Hw==} + resolution: {integrity: sha512-q/LHkOstoJ7pI1J0q6djesLzRvQSIfEto148ppAd+BVQK0JYjQIFSK3JgYZJa+Yzi0DDa52ZsQx2rqytBnf8Hw==, tarball: https://registry.npmjs.org/@tailwindcss/oxide-darwin-arm64/-/oxide-darwin-arm64-4.2.1.tgz} engines: {node: '>= 20'} cpu: [arm64] os: [darwin] '@tailwindcss/oxide-darwin-arm64@4.2.2': - resolution: {integrity: sha512-iq9Qjr6knfMpZHj55/37ouZeykwbDqF21gPFtfnhCCKGDcPI/21FKC9XdMO/XyBM7qKORx6UIhGgg6jLl7BZlg==} + resolution: {integrity: sha512-iq9Qjr6knfMpZHj55/37ouZeykwbDqF21gPFtfnhCCKGDcPI/21FKC9XdMO/XyBM7qKORx6UIhGgg6jLl7BZlg==, tarball: https://registry.npmjs.org/@tailwindcss/oxide-darwin-arm64/-/oxide-darwin-arm64-4.2.2.tgz} engines: {node: '>= 20'} cpu: [arm64] os: [darwin] '@tailwindcss/oxide-darwin-x64@4.2.1': - resolution: {integrity: sha512-/f/ozlaXGY6QLbpvd/kFTro2l18f7dHKpB+ieXz+Cijl4Mt9AI2rTrpq7V+t04nK+j9XBQHnSMdeQRhbGyt6fw==} + resolution: {integrity: sha512-/f/ozlaXGY6QLbpvd/kFTro2l18f7dHKpB+ieXz+Cijl4Mt9AI2rTrpq7V+t04nK+j9XBQHnSMdeQRhbGyt6fw==, tarball: https://registry.npmjs.org/@tailwindcss/oxide-darwin-x64/-/oxide-darwin-x64-4.2.1.tgz} engines: {node: '>= 20'} cpu: [x64] os: [darwin] '@tailwindcss/oxide-darwin-x64@4.2.2': - resolution: {integrity: sha512-BlR+2c3nzc8f2G639LpL89YY4bdcIdUmiOOkv2GQv4/4M0vJlpXEa0JXNHhCHU7VWOKWT/CjqHdTP8aUuDJkuw==} + resolution: {integrity: sha512-BlR+2c3nzc8f2G639LpL89YY4bdcIdUmiOOkv2GQv4/4M0vJlpXEa0JXNHhCHU7VWOKWT/CjqHdTP8aUuDJkuw==, tarball: https://registry.npmjs.org/@tailwindcss/oxide-darwin-x64/-/oxide-darwin-x64-4.2.2.tgz} engines: {node: '>= 20'} cpu: [x64] os: [darwin] '@tailwindcss/oxide-freebsd-x64@4.2.1': - resolution: {integrity: sha512-5e/AkgYJT/cpbkys/OU2Ei2jdETCLlifwm7ogMC7/hksI2fC3iiq6OcXwjibcIjPung0kRtR3TxEITkqgn0TcA==} + resolution: {integrity: sha512-5e/AkgYJT/cpbkys/OU2Ei2jdETCLlifwm7ogMC7/hksI2fC3iiq6OcXwjibcIjPung0kRtR3TxEITkqgn0TcA==, tarball: https://registry.npmjs.org/@tailwindcss/oxide-freebsd-x64/-/oxide-freebsd-x64-4.2.1.tgz} engines: {node: '>= 20'} cpu: [x64] os: [freebsd] '@tailwindcss/oxide-freebsd-x64@4.2.2': - resolution: {integrity: sha512-YUqUgrGMSu2CDO82hzlQ5qSb5xmx3RUrke/QgnoEx7KvmRJHQuZHZmZTLSuuHwFf0DJPybFMXMYf+WJdxHy/nQ==} + resolution: {integrity: sha512-YUqUgrGMSu2CDO82hzlQ5qSb5xmx3RUrke/QgnoEx7KvmRJHQuZHZmZTLSuuHwFf0DJPybFMXMYf+WJdxHy/nQ==, tarball: https://registry.npmjs.org/@tailwindcss/oxide-freebsd-x64/-/oxide-freebsd-x64-4.2.2.tgz} engines: {node: '>= 20'} cpu: [x64] os: [freebsd] '@tailwindcss/oxide-linux-arm-gnueabihf@4.2.1': - resolution: {integrity: sha512-Uny1EcVTTmerCKt/1ZuKTkb0x8ZaiuYucg2/kImO5A5Y/kBz41/+j0gxUZl+hTF3xkWpDmHX+TaWhOtba2Fyuw==} + resolution: {integrity: sha512-Uny1EcVTTmerCKt/1ZuKTkb0x8ZaiuYucg2/kImO5A5Y/kBz41/+j0gxUZl+hTF3xkWpDmHX+TaWhOtba2Fyuw==, tarball: https://registry.npmjs.org/@tailwindcss/oxide-linux-arm-gnueabihf/-/oxide-linux-arm-gnueabihf-4.2.1.tgz} engines: {node: '>= 20'} cpu: [arm] os: [linux] '@tailwindcss/oxide-linux-arm-gnueabihf@4.2.2': - resolution: {integrity: sha512-FPdhvsW6g06T9BWT0qTwiVZYE2WIFo2dY5aCSpjG/S/u1tby+wXoslXS0kl3/KXnULlLr1E3NPRRw0g7t2kgaQ==} + resolution: {integrity: sha512-FPdhvsW6g06T9BWT0qTwiVZYE2WIFo2dY5aCSpjG/S/u1tby+wXoslXS0kl3/KXnULlLr1E3NPRRw0g7t2kgaQ==, tarball: https://registry.npmjs.org/@tailwindcss/oxide-linux-arm-gnueabihf/-/oxide-linux-arm-gnueabihf-4.2.2.tgz} engines: {node: '>= 20'} cpu: [arm] os: [linux] '@tailwindcss/oxide-linux-arm64-gnu@4.2.1': - resolution: {integrity: sha512-CTrwomI+c7n6aSSQlsPL0roRiNMDQ/YzMD9EjcR+H4f0I1SQ8QqIuPnsVp7QgMkC1Qi8rtkekLkOFjo7OlEFRQ==} + resolution: {integrity: sha512-CTrwomI+c7n6aSSQlsPL0roRiNMDQ/YzMD9EjcR+H4f0I1SQ8QqIuPnsVp7QgMkC1Qi8rtkekLkOFjo7OlEFRQ==, tarball: https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-gnu/-/oxide-linux-arm64-gnu-4.2.1.tgz} engines: {node: '>= 20'} cpu: [arm64] os: [linux] '@tailwindcss/oxide-linux-arm64-gnu@4.2.2': - resolution: {integrity: sha512-4og1V+ftEPXGttOO7eCmW7VICmzzJWgMx+QXAJRAhjrSjumCwWqMfkDrNu1LXEQzNAwz28NCUpucgQPrR4S2yw==} + resolution: {integrity: sha512-4og1V+ftEPXGttOO7eCmW7VICmzzJWgMx+QXAJRAhjrSjumCwWqMfkDrNu1LXEQzNAwz28NCUpucgQPrR4S2yw==, tarball: https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-gnu/-/oxide-linux-arm64-gnu-4.2.2.tgz} engines: {node: '>= 20'} cpu: [arm64] os: [linux] '@tailwindcss/oxide-linux-arm64-musl@4.2.1': - resolution: {integrity: sha512-WZA0CHRL/SP1TRbA5mp9htsppSEkWuQ4KsSUumYQnyl8ZdT39ntwqmz4IUHGN6p4XdSlYfJwM4rRzZLShHsGAQ==} + resolution: {integrity: sha512-WZA0CHRL/SP1TRbA5mp9htsppSEkWuQ4KsSUumYQnyl8ZdT39ntwqmz4IUHGN6p4XdSlYfJwM4rRzZLShHsGAQ==, tarball: https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-musl/-/oxide-linux-arm64-musl-4.2.1.tgz} engines: {node: '>= 20'} cpu: [arm64] os: [linux] '@tailwindcss/oxide-linux-arm64-musl@4.2.2': - resolution: {integrity: sha512-oCfG/mS+/+XRlwNjnsNLVwnMWYH7tn/kYPsNPh+JSOMlnt93mYNCKHYzylRhI51X+TbR+ufNhhKKzm6QkqX8ag==} + resolution: {integrity: sha512-oCfG/mS+/+XRlwNjnsNLVwnMWYH7tn/kYPsNPh+JSOMlnt93mYNCKHYzylRhI51X+TbR+ufNhhKKzm6QkqX8ag==, tarball: https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-musl/-/oxide-linux-arm64-musl-4.2.2.tgz} engines: {node: '>= 20'} cpu: [arm64] os: [linux] '@tailwindcss/oxide-linux-x64-gnu@4.2.1': - resolution: {integrity: sha512-qMFzxI2YlBOLW5PhblzuSWlWfwLHaneBE0xHzLrBgNtqN6mWfs+qYbhryGSXQjFYB1Dzf5w+LN5qbUTPhW7Y5g==} + resolution: {integrity: sha512-qMFzxI2YlBOLW5PhblzuSWlWfwLHaneBE0xHzLrBgNtqN6mWfs+qYbhryGSXQjFYB1Dzf5w+LN5qbUTPhW7Y5g==, tarball: https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-gnu/-/oxide-linux-x64-gnu-4.2.1.tgz} engines: {node: '>= 20'} cpu: [x64] os: [linux] '@tailwindcss/oxide-linux-x64-gnu@4.2.2': - resolution: {integrity: sha512-rTAGAkDgqbXHNp/xW0iugLVmX62wOp2PoE39BTCGKjv3Iocf6AFbRP/wZT/kuCxC9QBh9Pu8XPkv/zCZB2mcMg==} + resolution: {integrity: sha512-rTAGAkDgqbXHNp/xW0iugLVmX62wOp2PoE39BTCGKjv3Iocf6AFbRP/wZT/kuCxC9QBh9Pu8XPkv/zCZB2mcMg==, tarball: https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-gnu/-/oxide-linux-x64-gnu-4.2.2.tgz} engines: {node: '>= 20'} cpu: [x64] os: [linux] '@tailwindcss/oxide-linux-x64-musl@4.2.1': - resolution: {integrity: sha512-5r1X2FKnCMUPlXTWRYpHdPYUY6a1Ar/t7P24OuiEdEOmms5lyqjDRvVY1yy9Rmioh+AunQ0rWiOTPE8F9A3v5g==} + resolution: {integrity: sha512-5r1X2FKnCMUPlXTWRYpHdPYUY6a1Ar/t7P24OuiEdEOmms5lyqjDRvVY1yy9Rmioh+AunQ0rWiOTPE8F9A3v5g==, tarball: https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-musl/-/oxide-linux-x64-musl-4.2.1.tgz} engines: {node: '>= 20'} cpu: [x64] os: [linux] '@tailwindcss/oxide-linux-x64-musl@4.2.2': - resolution: {integrity: sha512-XW3t3qwbIwiSyRCggeO2zxe3KWaEbM0/kW9e8+0XpBgyKU4ATYzcVSMKteZJ1iukJ3HgHBjbg9P5YPRCVUxlnQ==} + resolution: {integrity: sha512-XW3t3qwbIwiSyRCggeO2zxe3KWaEbM0/kW9e8+0XpBgyKU4ATYzcVSMKteZJ1iukJ3HgHBjbg9P5YPRCVUxlnQ==, tarball: https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-musl/-/oxide-linux-x64-musl-4.2.2.tgz} engines: {node: '>= 20'} cpu: [x64] os: [linux] '@tailwindcss/oxide-wasm32-wasi@4.2.1': - resolution: {integrity: sha512-MGFB5cVPvshR85MTJkEvqDUnuNoysrsRxd6vnk1Lf2tbiqNlXpHYZqkqOQalydienEWOHHFyyuTSYRsLfxFJ2Q==} + resolution: {integrity: sha512-MGFB5cVPvshR85MTJkEvqDUnuNoysrsRxd6vnk1Lf2tbiqNlXpHYZqkqOQalydienEWOHHFyyuTSYRsLfxFJ2Q==, tarball: https://registry.npmjs.org/@tailwindcss/oxide-wasm32-wasi/-/oxide-wasm32-wasi-4.2.1.tgz} engines: {node: '>=14.0.0'} cpu: [wasm32] bundledDependencies: @@ -3668,7 +3705,7 @@ packages: - tslib '@tailwindcss/oxide-wasm32-wasi@4.2.2': - resolution: {integrity: sha512-eKSztKsmEsn1O5lJ4ZAfyn41NfG7vzCg496YiGtMDV86jz1q/irhms5O0VrY6ZwTUkFy/EKG3RfWgxSI3VbZ8Q==} + resolution: {integrity: sha512-eKSztKsmEsn1O5lJ4ZAfyn41NfG7vzCg496YiGtMDV86jz1q/irhms5O0VrY6ZwTUkFy/EKG3RfWgxSI3VbZ8Q==, tarball: https://registry.npmjs.org/@tailwindcss/oxide-wasm32-wasi/-/oxide-wasm32-wasi-4.2.2.tgz} engines: {node: '>=14.0.0'} cpu: [wasm32] bundledDependencies: @@ -3680,25 +3717,25 @@ packages: - tslib '@tailwindcss/oxide-win32-arm64-msvc@4.2.1': - resolution: {integrity: sha512-YlUEHRHBGnCMh4Nj4GnqQyBtsshUPdiNroZj8VPkvTZSoHsilRCwXcVKnG9kyi0ZFAS/3u+qKHBdDc81SADTRA==} + resolution: {integrity: sha512-YlUEHRHBGnCMh4Nj4GnqQyBtsshUPdiNroZj8VPkvTZSoHsilRCwXcVKnG9kyi0ZFAS/3u+qKHBdDc81SADTRA==, tarball: https://registry.npmjs.org/@tailwindcss/oxide-win32-arm64-msvc/-/oxide-win32-arm64-msvc-4.2.1.tgz} engines: {node: '>= 20'} cpu: [arm64] os: [win32] '@tailwindcss/oxide-win32-arm64-msvc@4.2.2': - resolution: {integrity: sha512-qPmaQM4iKu5mxpsrWZMOZRgZv1tOZpUm+zdhhQP0VhJfyGGO3aUKdbh3gDZc/dPLQwW4eSqWGrrcWNBZWUWaXQ==} + resolution: {integrity: sha512-qPmaQM4iKu5mxpsrWZMOZRgZv1tOZpUm+zdhhQP0VhJfyGGO3aUKdbh3gDZc/dPLQwW4eSqWGrrcWNBZWUWaXQ==, tarball: https://registry.npmjs.org/@tailwindcss/oxide-win32-arm64-msvc/-/oxide-win32-arm64-msvc-4.2.2.tgz} engines: {node: '>= 20'} cpu: [arm64] os: [win32] '@tailwindcss/oxide-win32-x64-msvc@4.2.1': - resolution: {integrity: sha512-rbO34G5sMWWyrN/idLeVxAZgAKWrn5LiR3/I90Q9MkA67s6T1oB0xtTe+0heoBvHSpbU9Mk7i6uwJnpo4u21XQ==} + resolution: {integrity: sha512-rbO34G5sMWWyrN/idLeVxAZgAKWrn5LiR3/I90Q9MkA67s6T1oB0xtTe+0heoBvHSpbU9Mk7i6uwJnpo4u21XQ==, tarball: https://registry.npmjs.org/@tailwindcss/oxide-win32-x64-msvc/-/oxide-win32-x64-msvc-4.2.1.tgz} engines: {node: '>= 20'} cpu: [x64] os: [win32] '@tailwindcss/oxide-win32-x64-msvc@4.2.2': - resolution: {integrity: sha512-1T/37VvI7WyH66b+vqHj/cLwnCxt7Qt3WFu5Q8hk65aOvlwAhs7rAp1VkulBJw/N4tMirXjVnylTR72uI0HGcA==} + resolution: {integrity: sha512-1T/37VvI7WyH66b+vqHj/cLwnCxt7Qt3WFu5Q8hk65aOvlwAhs7rAp1VkulBJw/N4tMirXjVnylTR72uI0HGcA==, tarball: https://registry.npmjs.org/@tailwindcss/oxide-win32-x64-msvc/-/oxide-win32-x64-msvc-4.2.2.tgz} engines: {node: '>= 20'} cpu: [x64] os: [win32] @@ -3720,7 +3757,7 @@ packages: vite: ^5.2.0 || ^6 || ^7 || ^8 '@tanstack/history@1.161.4': - resolution: {integrity: sha512-Kp/WSt411ZWYvgXy6uiv5RmhHrz9cAml05AQPrtdAp7eUqvIDbMGPnML25OKbzR3RJ1q4wgENxDTvlGPa9+Mww==} + resolution: {integrity: sha512-Kp/WSt411ZWYvgXy6uiv5RmhHrz9cAml05AQPrtdAp7eUqvIDbMGPnML25OKbzR3RJ1q4wgENxDTvlGPa9+Mww==, tarball: https://registry.npmjs.org/@tanstack/history/-/history-1.161.4.tgz} engines: {node: '>=20.19'} '@tanstack/query-core@5.90.20': @@ -3732,31 +3769,31 @@ packages: react: ^18 || ^19 '@tanstack/react-router@1.166.2': - resolution: {integrity: sha512-pKhUtrvVLlhjWhsHkJSuIzh1J4LcP+8ErbIqRLORX9Js8dUFMKoT0+8oFpi+P8QRpuhm/7rzjYiWfcyTsqQZtA==} + resolution: {integrity: sha512-pKhUtrvVLlhjWhsHkJSuIzh1J4LcP+8ErbIqRLORX9Js8dUFMKoT0+8oFpi+P8QRpuhm/7rzjYiWfcyTsqQZtA==, tarball: https://registry.npmjs.org/@tanstack/react-router/-/react-router-1.166.2.tgz} engines: {node: '>=20.19'} peerDependencies: react: '>=18.0.0 || >=19.0.0' react-dom: '>=18.0.0 || >=19.0.0' '@tanstack/react-store@0.9.3': - resolution: {integrity: sha512-y2iHd/N9OkoQbFJLUX1T9vbc2O9tjH0pQRgTcx1/Nz4IlwLvkgpuglXUx+mXt0g5ZDFrEeDnONPqkbfxXJKwRg==} + resolution: {integrity: sha512-y2iHd/N9OkoQbFJLUX1T9vbc2O9tjH0pQRgTcx1/Nz4IlwLvkgpuglXUx+mXt0g5ZDFrEeDnONPqkbfxXJKwRg==, tarball: https://registry.npmjs.org/@tanstack/react-store/-/react-store-0.9.3.tgz} peerDependencies: react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 '@tanstack/router-core@1.166.2': - resolution: {integrity: sha512-zn3NhENOAX9ToQiX077UV2OH3aJKOvV2ZMNZZxZ3gDG3i3WqL8NfWfEgetEAfMN37/Mnt90PpotYgf7IyuoKqQ==} + resolution: {integrity: sha512-zn3NhENOAX9ToQiX077UV2OH3aJKOvV2ZMNZZxZ3gDG3i3WqL8NfWfEgetEAfMN37/Mnt90PpotYgf7IyuoKqQ==, tarball: https://registry.npmjs.org/@tanstack/router-core/-/router-core-1.166.2.tgz} engines: {node: '>=20.19'} '@tanstack/store@0.9.3': - resolution: {integrity: sha512-8reSzl/qGWGGVKhBoxXPMWzATSbZLZFWhwBAFO9NAyp0TxzfBP0mIrGb8CP8KrQTmvzXlR/vFPPUrHTLBGyFyw==} + resolution: {integrity: sha512-8reSzl/qGWGGVKhBoxXPMWzATSbZLZFWhwBAFO9NAyp0TxzfBP0mIrGb8CP8KrQTmvzXlR/vFPPUrHTLBGyFyw==, tarball: https://registry.npmjs.org/@tanstack/store/-/store-0.9.3.tgz} '@tokenizer/inflate@0.4.1': - resolution: {integrity: sha512-2mAv+8pkG6GIZiF1kNg1jAjh27IDxEPKwdGul3snfztFerfPGI1LjDezZp3i7BElXompqEtPmoPx6c2wgtWsOA==} + resolution: {integrity: sha512-2mAv+8pkG6GIZiF1kNg1jAjh27IDxEPKwdGul3snfztFerfPGI1LjDezZp3i7BElXompqEtPmoPx6c2wgtWsOA==, tarball: https://registry.npmjs.org/@tokenizer/inflate/-/inflate-0.4.1.tgz} engines: {node: '>=18'} '@tokenizer/token@0.3.0': - resolution: {integrity: sha512-OvjF+z51L3ov0OyAU0duzsYuvO01PH7x4t6DJx+guahgTnBHkhJdG7soQeTSFLWN3efnHyibZ4Z8l2EuWwJN3A==} + resolution: {integrity: sha512-OvjF+z51L3ov0OyAU0duzsYuvO01PH7x4t6DJx+guahgTnBHkhJdG7soQeTSFLWN3efnHyibZ4Z8l2EuWwJN3A==, tarball: https://registry.npmjs.org/@tokenizer/token/-/token-0.3.0.tgz} '@trpc/client@11.12.0': resolution: {integrity: sha512-zTwFKQdE99pvNm7kXFdHo5xIQpGqpQJHtqVkT9o+i8h/0fbDOUBEEbFVICiMsNA+GiXskoaDRX2l+z6ir+Ug3w==} @@ -3782,7 +3819,7 @@ packages: resolution: {integrity: sha512-Wf29UqxWDpc+i61k3oIOzcUfQt79PIT9y/MWfAGlrkjg6lBC1hwDECLXPVJAhWjiGbfBCxZd65F/LIZF3+jeJQ==} '@tybys/wasm-util@0.10.1': - resolution: {integrity: sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg==} + resolution: {integrity: sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg==, tarball: https://registry.npmjs.org/@tybys/wasm-util/-/wasm-util-0.10.1.tgz} '@types/chai@5.2.3': resolution: {integrity: sha512-Mw558oeA9fFbv65/y4mHtXDs9bPnFMZAL/jxdPFUpOHHIXX91mcgEHbS5Lahr+pwZFR8A7GQleRWeI6cGFC2UA==} @@ -4077,7 +4114,7 @@ packages: optional: true aws-ssl-profiles@1.1.2: - resolution: {integrity: sha512-NZKeq9AfyQvEeNlN0zSYAaWrmBffJh3IELMZfRpJVWgrpEbtEpnjvzqBPf+mxoI287JohRDoa+/nsfqqiZmF6g==} + resolution: {integrity: sha512-NZKeq9AfyQvEeNlN0zSYAaWrmBffJh3IELMZfRpJVWgrpEbtEpnjvzqBPf+mxoI287JohRDoa+/nsfqqiZmF6g==, tarball: https://registry.npmjs.org/aws-ssl-profiles/-/aws-ssl-profiles-1.1.2.tgz} engines: {node: '>= 6.0.0'} axios@1.14.0: @@ -4174,7 +4211,7 @@ packages: optional: true bidi-js@1.0.3: - resolution: {integrity: sha512-RKshQI1R3YQ+n9YJz2QQ147P66ELpa1FQEg20Dk8oW9t2KgLbpDLLp9aGZ7y8WHSshDknG0bknqGw5/tyCs5tw==} + resolution: {integrity: sha512-RKshQI1R3YQ+n9YJz2QQ147P66ELpa1FQEg20Dk8oW9t2KgLbpDLLp9aGZ7y8WHSshDknG0bknqGw5/tyCs5tw==, tarball: https://registry.npmjs.org/bidi-js/-/bidi-js-1.0.3.tgz} binary-extensions@2.3.0: resolution: {integrity: sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==} @@ -4225,7 +4262,7 @@ packages: optional: true c12@3.1.0: - resolution: {integrity: sha512-uWoS8OU1MEIsOv8p/5a82c3H31LsWVR5qiyXVfBNOzfffjUWtPnhAb4BYI2uG2HfGmZmFjCtui5XNWaps+iFuw==} + resolution: {integrity: sha512-uWoS8OU1MEIsOv8p/5a82c3H31LsWVR5qiyXVfBNOzfffjUWtPnhAb4BYI2uG2HfGmZmFjCtui5XNWaps+iFuw==, tarball: https://registry.npmjs.org/c12/-/c12-3.1.0.tgz} peerDependencies: magicast: ^0.3.5 peerDependenciesMeta: @@ -4308,14 +4345,14 @@ packages: resolution: {integrity: sha512-PsezH1rqdV9VvyNhxxOW32/d75r01NY7TQCmOqomRo15ZSOKbpTFVsfjghxo6JloQUCGnH4k1LGu0R4yCLlWQQ==} chevrotain@10.5.0: - resolution: {integrity: sha512-Pkv5rBY3+CsHOYfV5g/Vs5JY9WTHHDEKOlohI2XeygaZhUeqhAlldZ8Hz9cRmxu709bvS08YzxHdTPHhffc13A==} + resolution: {integrity: sha512-Pkv5rBY3+CsHOYfV5g/Vs5JY9WTHHDEKOlohI2XeygaZhUeqhAlldZ8Hz9cRmxu709bvS08YzxHdTPHhffc13A==, tarball: https://registry.npmjs.org/chevrotain/-/chevrotain-10.5.0.tgz} chokidar@3.6.0: resolution: {integrity: sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==} engines: {node: '>= 8.10.0'} chokidar@4.0.3: - resolution: {integrity: sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==} + resolution: {integrity: sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==, tarball: https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz} engines: {node: '>= 14.16.0'} chokidar@5.0.0: @@ -4330,7 +4367,7 @@ packages: resolution: {integrity: sha512-tskPPKEs8D2KPafUypv2gxwJP8h/OaJmC82QQGGDQcHvXX43xF2VDACcJVmZ0EuSxkpO9Kc4MlrA3q0+FG58AQ==} citty@0.2.2: - resolution: {integrity: sha512-+6vJA3L98yv+IdfKGZHBNiGW5KHn22e/JwID0Strsz8h4S/csAu/OuICwxrg44k5MRiZHWIo8XXuJgQTriRP4w==} + resolution: {integrity: sha512-+6vJA3L98yv+IdfKGZHBNiGW5KHn22e/JwID0Strsz8h4S/csAu/OuICwxrg44k5MRiZHWIo8XXuJgQTriRP4w==, tarball: https://registry.npmjs.org/citty/-/citty-0.2.2.tgz} class-variance-authority@0.7.1: resolution: {integrity: sha512-Ka+9Trutv7G8M6WT6SeiRWz792K5qEqIGEGzXKhAE6xOWAY6pPH8U+9IY3oCMv6kqTmLsv7Xh/2w2RigkePMsg==} @@ -4460,7 +4497,7 @@ packages: engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} cookie-es@2.0.1: - resolution: {integrity: sha512-aVf4A4hI2w70LnF7GG+7xDQUkliwiXWXFvTjkip4+b64ygDQ2sJPRSKFDHbxn8o0xu9QzPkMuuiWIXyFSE2slA==} + resolution: {integrity: sha512-aVf4A4hI2w70LnF7GG+7xDQUkliwiXWXFvTjkip4+b64ygDQ2sJPRSKFDHbxn8o0xu9QzPkMuuiWIXyFSE2slA==, tarball: https://registry.npmjs.org/cookie-es/-/cookie-es-2.0.1.tgz} cookie-signature@1.2.2: resolution: {integrity: sha512-D76uU73ulSXrD1UXF4KE2TMxVVwhsnCgfAyTg9k8P6KGZjlXKrOLe4dJQKI3Bxi5wjesZoFXJWElNWBjPZMbhg==} @@ -4500,7 +4537,7 @@ packages: engines: {node: '>=12'} css-tree@3.2.1: - resolution: {integrity: sha512-X7sjQzceUhu1u7Y/ylrRZFU2FS6LRiFVp6rKLPg23y3x3c3DOKAwuXGDp+PAGjh6CSnCjYeAul8pcT8bAl+lSA==} + resolution: {integrity: sha512-X7sjQzceUhu1u7Y/ylrRZFU2FS6LRiFVp6rKLPg23y3x3c3DOKAwuXGDp+PAGjh6CSnCjYeAul8pcT8bAl+lSA==, tarball: https://registry.npmjs.org/css-tree/-/css-tree-3.2.1.tgz} engines: {node: ^10 || ^12.20.0 || ^14.13.0 || >=15.0.0} cssesc@3.0.0: @@ -4509,7 +4546,7 @@ packages: hasBin: true cssstyle@6.2.0: - resolution: {integrity: sha512-Fm5NvhYathRnXNVndkUsCCuR63DCLVVwGOOwQw782coXFi5HhkXdu289l59HlXZBawsyNccXfWRYvLzcDCdDig==} + resolution: {integrity: sha512-Fm5NvhYathRnXNVndkUsCCuR63DCLVVwGOOwQw782coXFi5HhkXdu289l59HlXZBawsyNccXfWRYvLzcDCdDig==, tarball: https://registry.npmjs.org/cssstyle/-/cssstyle-6.2.0.tgz} engines: {node: '>=20'} csstype@3.2.3: @@ -4564,7 +4601,7 @@ packages: engines: {node: '>= 12'} data-urls@7.0.0: - resolution: {integrity: sha512-23XHcCF+coGYevirZceTVD7NdJOqVn+49IHyxgszm+JIiHLoB2TkmPtsYkNWT1pvRSGkc35L6NHs0yHkN2SumA==} + resolution: {integrity: sha512-23XHcCF+coGYevirZceTVD7NdJOqVn+49IHyxgszm+JIiHLoB2TkmPtsYkNWT1pvRSGkc35L6NHs0yHkN2SumA==, tarball: https://registry.npmjs.org/data-urls/-/data-urls-7.0.0.tgz} engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0} date-fns-jalali@4.1.0-0: @@ -4593,7 +4630,7 @@ packages: resolution: {integrity: sha512-qIMFpTMZmny+MMIitAB6D7iVPEorVw6YQRWkvarTkT4tBeSLLiHzcwj6q0MmYSFCiVpiqPJTJEYIrpcPzVEIvg==} decimal.js@10.6.0: - resolution: {integrity: sha512-YpgQiITW3JXGntzdUmyUR1V812Hn8T1YVXhCu+wO3OpS4eU9l4YdD3qjyiKdV6mvV29zapkMeD390UVEf2lkUg==} + resolution: {integrity: sha512-YpgQiITW3JXGntzdUmyUR1V812Hn8T1YVXhCu+wO3OpS4eU9l4YdD3qjyiKdV6mvV29zapkMeD390UVEf2lkUg==, tarball: https://registry.npmjs.org/decimal.js/-/decimal.js-10.6.0.tgz} decode-named-character-reference@1.3.0: resolution: {integrity: sha512-GtpQYB283KrPp6nRw50q3U9/VfOutZOe103qlN7BPP6Ad27xYnOIWv4lPzo8HCAL+mMZofJ9KEy30fq6MfaK6Q==} @@ -4611,7 +4648,7 @@ packages: optional: true deepmerge-ts@7.1.5: - resolution: {integrity: sha512-HOJkrhaYsweh+W+e74Yn7YStZOilkoPb6fycpwNLKzSPtruFs48nYis0zy5yJz1+ktUhHxoRDJ27RQAWLIJVJw==} + resolution: {integrity: sha512-HOJkrhaYsweh+W+e74Yn7YStZOilkoPb6fycpwNLKzSPtruFs48nYis0zy5yJz1+ktUhHxoRDJ27RQAWLIJVJw==, tarball: https://registry.npmjs.org/deepmerge-ts/-/deepmerge-ts-7.1.5.tgz} engines: {node: '>=16.0.0'} deepmerge@4.3.1: @@ -4645,7 +4682,7 @@ packages: engines: {node: '>=0.4.0'} denque@2.1.0: - resolution: {integrity: sha512-HVQE3AAb/pxF8fQAoiqpvg9i3evqug3hoiwakOyZAwJm+6vZehbkYXZ0l4JxS+I3QxM97v5aaRNhj8v5oBhekw==} + resolution: {integrity: sha512-HVQE3AAb/pxF8fQAoiqpvg9i3evqug3hoiwakOyZAwJm+6vZehbkYXZ0l4JxS+I3QxM97v5aaRNhj8v5oBhekw==, tarball: https://registry.npmjs.org/denque/-/denque-2.1.0.tgz} engines: {node: '>=0.10'} depd@2.0.0: @@ -4802,7 +4839,7 @@ packages: resolution: {integrity: sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==} effect@3.18.4: - resolution: {integrity: sha512-b1LXQJLe9D11wfnOKAk3PKxuqYshQ0Heez+y5pnkd3jLj1yx9QhM72zZ9uUrOQyNvrs2GZZd/3maL0ZV18YuDA==} + resolution: {integrity: sha512-b1LXQJLe9D11wfnOKAk3PKxuqYshQ0Heez+y5pnkd3jLj1yx9QhM72zZ9uUrOQyNvrs2GZZd/3maL0ZV18YuDA==, tarball: https://registry.npmjs.org/effect/-/effect-3.18.4.tgz} electron-to-chromium@1.5.302: resolution: {integrity: sha512-sM6HAN2LyK82IyPBpznDRqlTQAtuSaO+ShzFiWTvoMJLHyZ+Y39r8VMfHzwbU8MVBzQ4Wdn85+wlZl2TLGIlwg==} @@ -4987,7 +5024,7 @@ packages: engines: {node: '>=18.0.0'} exact-mirror@0.2.7: - resolution: {integrity: sha512-+MeEmDcLA4o/vjK2zujgk+1VTxPR4hdp23qLqkWfStbECtAq9gmsvQa3LW6z/0GXZyHJobrCnmy1cdeE7BjsYg==} + resolution: {integrity: sha512-+MeEmDcLA4o/vjK2zujgk+1VTxPR4hdp23qLqkWfStbECtAq9gmsvQa3LW6z/0GXZyHJobrCnmy1cdeE7BjsYg==, tarball: https://registry.npmjs.org/exact-mirror/-/exact-mirror-0.2.7.tgz} peerDependencies: '@sinclair/typebox': ^0.34.15 peerDependenciesMeta: @@ -5023,7 +5060,7 @@ packages: resolution: {integrity: sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==} fast-check@3.23.2: - resolution: {integrity: sha512-h5+1OzzfCC3Ef7VbtKdcv7zsstUQwUDlYpUTvjeUsJAssPgLn7QzbboPtL5ro04Mq0rPOsMzl7q5hIbRs2wD1A==} + resolution: {integrity: sha512-h5+1OzzfCC3Ef7VbtKdcv7zsstUQwUDlYpUTvjeUsJAssPgLn7QzbboPtL5ro04Mq0rPOsMzl7q5hIbRs2wD1A==, tarball: https://registry.npmjs.org/fast-check/-/fast-check-3.23.2.tgz} engines: {node: '>=8.0.0'} fast-copy@4.0.2: @@ -5069,7 +5106,7 @@ packages: engines: {node: '>=18'} file-type@21.3.0: - resolution: {integrity: sha512-8kPJMIGz1Yt/aPEwOsrR97ZyZaD1Iqm8PClb1nYFclUCkBi0Ma5IsYNQzvSFS9ib51lWyIw5mIT9rWzI/xjpzA==} + resolution: {integrity: sha512-8kPJMIGz1Yt/aPEwOsrR97ZyZaD1Iqm8PClb1nYFclUCkBi0Ma5IsYNQzvSFS9ib51lWyIw5mIT9rWzI/xjpzA==, tarball: https://registry.npmjs.org/file-type/-/file-type-21.3.0.tgz} engines: {node: '>=20'} fill-range@7.1.1: @@ -5094,7 +5131,7 @@ packages: optional: true foreground-child@3.3.1: - resolution: {integrity: sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==} + resolution: {integrity: sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==, tarball: https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.1.tgz} engines: {node: '>=14'} form-data@4.0.5: @@ -5149,8 +5186,13 @@ packages: resolution: {integrity: sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==} engines: {node: '>= 8'} + fsevents@2.3.2: + resolution: {integrity: sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==, tarball: https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz} + engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} + os: [darwin] + fsevents@2.3.3: - resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} + resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==, tarball: https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz} engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} os: [darwin] @@ -5282,12 +5324,12 @@ packages: next: '>=13.2.0' gel@2.2.0: - resolution: {integrity: sha512-q0ma7z2swmoamHQusey8ayo8+ilVdzDt4WTxSPzq/yRqvucWRfymRVMvNgmSC0XK7eNjjEZEcplxpgaNojKdmQ==} + resolution: {integrity: sha512-q0ma7z2swmoamHQusey8ayo8+ilVdzDt4WTxSPzq/yRqvucWRfymRVMvNgmSC0XK7eNjjEZEcplxpgaNojKdmQ==, tarball: https://registry.npmjs.org/gel/-/gel-2.2.0.tgz} engines: {node: '>= 18.0.0'} hasBin: true generate-function@2.3.1: - resolution: {integrity: sha512-eeB5GfMNeevm/GRYq20ShmsaGcmI81kIX2K9XQx5miC8KdHaC6Jm0qQ8ZNeGOi7wYB8OsdxKs+Y2oVuTFuVwKQ==} + resolution: {integrity: sha512-eeB5GfMNeevm/GRYq20ShmsaGcmI81kIX2K9XQx5miC8KdHaC6Jm0qQ8ZNeGOi7wYB8OsdxKs+Y2oVuTFuVwKQ==, tarball: https://registry.npmjs.org/generate-function/-/generate-function-2.3.1.tgz} gensync@1.0.0-beta.2: resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==} @@ -5314,7 +5356,7 @@ packages: engines: {node: '>=14.16'} get-port-please@3.2.0: - resolution: {integrity: sha512-I9QVvBw5U/hw3RmWpYKRumUeaDgxTPd401x364rLmWBJcOQ753eov1eTgzDqRG9bqFIfDc7gfzcQEWrUri3o1A==} + resolution: {integrity: sha512-I9QVvBw5U/hw3RmWpYKRumUeaDgxTPd401x364rLmWBJcOQ753eov1eTgzDqRG9bqFIfDc7gfzcQEWrUri3o1A==, tarball: https://registry.npmjs.org/get-port-please/-/get-port-please-3.2.0.tgz} get-proto@1.0.1: resolution: {integrity: sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==} @@ -5336,7 +5378,7 @@ packages: hasBin: true giget@2.0.0: - resolution: {integrity: sha512-L5bGsVkxJbJgdnwyuheIunkGatUF/zssUoxxjACCseZYAVbaqdh9Tsmmlkl8vYan09H7sbvKt4pS8GqKLBrEzA==} + resolution: {integrity: sha512-L5bGsVkxJbJgdnwyuheIunkGatUF/zssUoxxjACCseZYAVbaqdh9Tsmmlkl8vYan09H7sbvKt4pS8GqKLBrEzA==, tarball: https://registry.npmjs.org/giget/-/giget-2.0.0.tgz} hasBin: true giget@3.2.0: @@ -5358,10 +5400,10 @@ packages: resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} grammex@3.1.12: - resolution: {integrity: sha512-6ufJOsSA7LcQehIJNCO7HIBykfM7DXQual0Ny780/DEcJIpBlHRvcqEBWGPYd7hrXL2GJ3oJI1MIhaXjWmLQOQ==} + resolution: {integrity: sha512-6ufJOsSA7LcQehIJNCO7HIBykfM7DXQual0Ny780/DEcJIpBlHRvcqEBWGPYd7hrXL2GJ3oJI1MIhaXjWmLQOQ==, tarball: https://registry.npmjs.org/grammex/-/grammex-3.1.12.tgz} graphmatch@1.1.1: - resolution: {integrity: sha512-5ykVn/EXM1hF0XCaWh05VbYvEiOL2lY1kBxZtaYsyvjp7cmWOU1XsAdfQBwClraEofXDT197lFbXOEVMHpvQOg==} + resolution: {integrity: sha512-5ykVn/EXM1hF0XCaWh05VbYvEiOL2lY1kBxZtaYsyvjp7cmWOU1XsAdfQBwClraEofXDT197lFbXOEVMHpvQOg==, tarball: https://registry.npmjs.org/graphmatch/-/graphmatch-1.1.1.tgz} graphql@16.13.0: resolution: {integrity: sha512-uSisMYERbaB9bkA9M4/4dnqyktaEkf1kMHNKq/7DHyxVeWqHQ2mBmVqm5u6/FVHwF3iCNalKcg82Zfl+tffWoA==} @@ -5420,7 +5462,7 @@ packages: resolution: {integrity: sha512-7xgomUX6ADmcYzFik0HzAxh/73YlKR9bmFzf51CZwR+b6YtzU2m0u49hQCqV6SvlqIqsaxovfwdvbnsw3b/zpg==} hono@4.11.4: - resolution: {integrity: sha512-U7tt8JsyrxSRKspfhtLET79pU8K+tInj5QZXs1jSugO1Vq5dFj3kmZsRldo29mTBfcjDRVRXrEZ6LS63Cog9ZA==} + resolution: {integrity: sha512-U7tt8JsyrxSRKspfhtLET79pU8K+tInj5QZXs1jSugO1Vq5dFj3kmZsRldo29mTBfcjDRVRXrEZ6LS63Cog9ZA==, tarball: https://registry.npmjs.org/hono/-/hono-4.11.4.tgz} engines: {node: '>=16.9.0'} hono@4.12.3: @@ -5431,7 +5473,7 @@ packages: resolution: {integrity: sha512-uKGyY8BuzN/a5gvzvA+3FVWo0+wUjgtfSdnmjtrOVwQCZPHpHDH2WRO3VZSOeluYrHoDCiXFffZXs8Dj1ULWtw==} html-encoding-sniffer@6.0.0: - resolution: {integrity: sha512-CV9TW3Y3f8/wT0BRFc1/KAVQ3TUHiXmaAb6VW9vtiMFf7SLoMd1PdAc4W3KFOFETBJUb90KatHqlsZMWV+R9Gg==} + resolution: {integrity: sha512-CV9TW3Y3f8/wT0BRFc1/KAVQ3TUHiXmaAb6VW9vtiMFf7SLoMd1PdAc4W3KFOFETBJUb90KatHqlsZMWV+R9Gg==, tarball: https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-6.0.0.tgz} engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0} html-void-elements@3.0.0: @@ -5442,11 +5484,11 @@ packages: engines: {node: '>= 0.8'} http-proxy-agent@7.0.2: - resolution: {integrity: sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==} + resolution: {integrity: sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==, tarball: https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz} engines: {node: '>= 14'} http-status-codes@2.3.0: - resolution: {integrity: sha512-RJ8XvFvpPM/Dmc5SV+dC4y5PCeOhT3x1Hq0NU3rjGeg5a/CqlhZ7uudknPwZFz4aeAXDcbAyaeP7GAo9lvngtA==} + resolution: {integrity: sha512-RJ8XvFvpPM/Dmc5SV+dC4y5PCeOhT3x1Hq0NU3rjGeg5a/CqlhZ7uudknPwZFz4aeAXDcbAyaeP7GAo9lvngtA==, tarball: https://registry.npmjs.org/http-status-codes/-/http-status-codes-2.3.0.tgz} https-proxy-agent@7.0.6: resolution: {integrity: sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==} @@ -5465,7 +5507,7 @@ packages: engines: {node: '>=0.10.0'} ieee754@1.2.1: - resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==} + resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==, tarball: https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz} ignore@5.3.2: resolution: {integrity: sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==} @@ -5700,13 +5742,13 @@ packages: engines: {node: '>=12'} is-potential-custom-element-name@1.0.1: - resolution: {integrity: sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==} + resolution: {integrity: sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==, tarball: https://registry.npmjs.org/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz} is-promise@4.0.0: resolution: {integrity: sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ==} is-property@1.0.2: - resolution: {integrity: sha512-Ks/IoX00TtClbGQr4TWXemAnktAQvYB7HzcCxDGqEZU6oCmb2INHuOoKxbtR+HFkmYWBKv/dOZtGRiAjDhj92g==} + resolution: {integrity: sha512-Ks/IoX00TtClbGQr4TWXemAnktAQvYB7HzcCxDGqEZU6oCmb2INHuOoKxbtR+HFkmYWBKv/dOZtGRiAjDhj92g==, tarball: https://registry.npmjs.org/is-property/-/is-property-1.0.2.tgz} is-regexp@3.1.0: resolution: {integrity: sha512-rbku49cWloU5bSMI+zaRaXdQHXnthP6DZ/vLnfdSKyL4zUzuWnomtOEiZZOd+ioQ+avFo/qau3KPTc7Fjy1uPA==} @@ -5745,7 +5787,7 @@ packages: engines: {node: '>=18'} isbot@5.1.37: - resolution: {integrity: sha512-5bcicX81xf6NlTEV8rWdg7Pk01LFizDetuYGHx6d/f6y3lR2/oo8IfxjzJqn1UdDEyCcwT9e7NRloj8DwCYujQ==} + resolution: {integrity: sha512-5bcicX81xf6NlTEV8rWdg7Pk01LFizDetuYGHx6d/f6y3lR2/oo8IfxjzJqn1UdDEyCcwT9e7NRloj8DwCYujQ==, tarball: https://registry.npmjs.org/isbot/-/isbot-5.1.37.tgz} engines: {node: '>=18'} isexe@2.0.0: @@ -5778,7 +5820,7 @@ packages: hasBin: true jsdom@28.1.0: - resolution: {integrity: sha512-0+MoQNYyr2rBHqO1xilltfDjV9G7ymYGlAUazgcDLQaUf8JDHbuGwsxN6U9qWaElZ4w1B2r7yEGIL3GdeW3Rug==} + resolution: {integrity: sha512-0+MoQNYyr2rBHqO1xilltfDjV9G7ymYGlAUazgcDLQaUf8JDHbuGwsxN6U9qWaElZ4w1B2r7yEGIL3GdeW3Rug==, tarball: https://registry.npmjs.org/jsdom/-/jsdom-28.1.0.tgz} engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0} peerDependencies: canvas: ^3.0.0 @@ -5828,133 +5870,133 @@ packages: engines: {node: '>=20.0.0'} lightningcss-android-arm64@1.31.1: - resolution: {integrity: sha512-HXJF3x8w9nQ4jbXRiNppBCqeZPIAfUo8zE/kOEGbW5NZvGc/K7nMxbhIr+YlFlHW5mpbg/YFPdbnCh1wAXCKFg==} + resolution: {integrity: sha512-HXJF3x8w9nQ4jbXRiNppBCqeZPIAfUo8zE/kOEGbW5NZvGc/K7nMxbhIr+YlFlHW5mpbg/YFPdbnCh1wAXCKFg==, tarball: https://registry.npmjs.org/lightningcss-android-arm64/-/lightningcss-android-arm64-1.31.1.tgz} engines: {node: '>= 12.0.0'} cpu: [arm64] os: [android] lightningcss-android-arm64@1.32.0: - resolution: {integrity: sha512-YK7/ClTt4kAK0vo6w3X+Pnm0D2cf2vPHbhOXdoNti1Ga0al1P4TBZhwjATvjNwLEBCnKvjJc2jQgHXH0NEwlAg==} + resolution: {integrity: sha512-YK7/ClTt4kAK0vo6w3X+Pnm0D2cf2vPHbhOXdoNti1Ga0al1P4TBZhwjATvjNwLEBCnKvjJc2jQgHXH0NEwlAg==, tarball: https://registry.npmjs.org/lightningcss-android-arm64/-/lightningcss-android-arm64-1.32.0.tgz} engines: {node: '>= 12.0.0'} cpu: [arm64] os: [android] lightningcss-darwin-arm64@1.31.1: - resolution: {integrity: sha512-02uTEqf3vIfNMq3h/z2cJfcOXnQ0GRwQrkmPafhueLb2h7mqEidiCzkE4gBMEH65abHRiQvhdcQ+aP0D0g67sg==} + resolution: {integrity: sha512-02uTEqf3vIfNMq3h/z2cJfcOXnQ0GRwQrkmPafhueLb2h7mqEidiCzkE4gBMEH65abHRiQvhdcQ+aP0D0g67sg==, tarball: https://registry.npmjs.org/lightningcss-darwin-arm64/-/lightningcss-darwin-arm64-1.31.1.tgz} engines: {node: '>= 12.0.0'} cpu: [arm64] os: [darwin] lightningcss-darwin-arm64@1.32.0: - resolution: {integrity: sha512-RzeG9Ju5bag2Bv1/lwlVJvBE3q6TtXskdZLLCyfg5pt+HLz9BqlICO7LZM7VHNTTn/5PRhHFBSjk5lc4cmscPQ==} + resolution: {integrity: sha512-RzeG9Ju5bag2Bv1/lwlVJvBE3q6TtXskdZLLCyfg5pt+HLz9BqlICO7LZM7VHNTTn/5PRhHFBSjk5lc4cmscPQ==, tarball: https://registry.npmjs.org/lightningcss-darwin-arm64/-/lightningcss-darwin-arm64-1.32.0.tgz} engines: {node: '>= 12.0.0'} cpu: [arm64] os: [darwin] lightningcss-darwin-x64@1.31.1: - resolution: {integrity: sha512-1ObhyoCY+tGxtsz1lSx5NXCj3nirk0Y0kB/g8B8DT+sSx4G9djitg9ejFnjb3gJNWo7qXH4DIy2SUHvpoFwfTA==} + resolution: {integrity: sha512-1ObhyoCY+tGxtsz1lSx5NXCj3nirk0Y0kB/g8B8DT+sSx4G9djitg9ejFnjb3gJNWo7qXH4DIy2SUHvpoFwfTA==, tarball: https://registry.npmjs.org/lightningcss-darwin-x64/-/lightningcss-darwin-x64-1.31.1.tgz} engines: {node: '>= 12.0.0'} cpu: [x64] os: [darwin] lightningcss-darwin-x64@1.32.0: - resolution: {integrity: sha512-U+QsBp2m/s2wqpUYT/6wnlagdZbtZdndSmut/NJqlCcMLTWp5muCrID+K5UJ6jqD2BFshejCYXniPDbNh73V8w==} + resolution: {integrity: sha512-U+QsBp2m/s2wqpUYT/6wnlagdZbtZdndSmut/NJqlCcMLTWp5muCrID+K5UJ6jqD2BFshejCYXniPDbNh73V8w==, tarball: https://registry.npmjs.org/lightningcss-darwin-x64/-/lightningcss-darwin-x64-1.32.0.tgz} engines: {node: '>= 12.0.0'} cpu: [x64] os: [darwin] lightningcss-freebsd-x64@1.31.1: - resolution: {integrity: sha512-1RINmQKAItO6ISxYgPwszQE1BrsVU5aB45ho6O42mu96UiZBxEXsuQ7cJW4zs4CEodPUioj/QrXW1r9pLUM74A==} + resolution: {integrity: sha512-1RINmQKAItO6ISxYgPwszQE1BrsVU5aB45ho6O42mu96UiZBxEXsuQ7cJW4zs4CEodPUioj/QrXW1r9pLUM74A==, tarball: https://registry.npmjs.org/lightningcss-freebsd-x64/-/lightningcss-freebsd-x64-1.31.1.tgz} engines: {node: '>= 12.0.0'} cpu: [x64] os: [freebsd] lightningcss-freebsd-x64@1.32.0: - resolution: {integrity: sha512-JCTigedEksZk3tHTTthnMdVfGf61Fky8Ji2E4YjUTEQX14xiy/lTzXnu1vwiZe3bYe0q+SpsSH/CTeDXK6WHig==} + resolution: {integrity: sha512-JCTigedEksZk3tHTTthnMdVfGf61Fky8Ji2E4YjUTEQX14xiy/lTzXnu1vwiZe3bYe0q+SpsSH/CTeDXK6WHig==, tarball: https://registry.npmjs.org/lightningcss-freebsd-x64/-/lightningcss-freebsd-x64-1.32.0.tgz} engines: {node: '>= 12.0.0'} cpu: [x64] os: [freebsd] lightningcss-linux-arm-gnueabihf@1.31.1: - resolution: {integrity: sha512-OOCm2//MZJ87CdDK62rZIu+aw9gBv4azMJuA8/KB74wmfS3lnC4yoPHm0uXZ/dvNNHmnZnB8XLAZzObeG0nS1g==} + resolution: {integrity: sha512-OOCm2//MZJ87CdDK62rZIu+aw9gBv4azMJuA8/KB74wmfS3lnC4yoPHm0uXZ/dvNNHmnZnB8XLAZzObeG0nS1g==, tarball: https://registry.npmjs.org/lightningcss-linux-arm-gnueabihf/-/lightningcss-linux-arm-gnueabihf-1.31.1.tgz} engines: {node: '>= 12.0.0'} cpu: [arm] os: [linux] lightningcss-linux-arm-gnueabihf@1.32.0: - resolution: {integrity: sha512-x6rnnpRa2GL0zQOkt6rts3YDPzduLpWvwAF6EMhXFVZXD4tPrBkEFqzGowzCsIWsPjqSK+tyNEODUBXeeVHSkw==} + resolution: {integrity: sha512-x6rnnpRa2GL0zQOkt6rts3YDPzduLpWvwAF6EMhXFVZXD4tPrBkEFqzGowzCsIWsPjqSK+tyNEODUBXeeVHSkw==, tarball: https://registry.npmjs.org/lightningcss-linux-arm-gnueabihf/-/lightningcss-linux-arm-gnueabihf-1.32.0.tgz} engines: {node: '>= 12.0.0'} cpu: [arm] os: [linux] lightningcss-linux-arm64-gnu@1.31.1: - resolution: {integrity: sha512-WKyLWztD71rTnou4xAD5kQT+982wvca7E6QoLpoawZ1gP9JM0GJj4Tp5jMUh9B3AitHbRZ2/H3W5xQmdEOUlLg==} + resolution: {integrity: sha512-WKyLWztD71rTnou4xAD5kQT+982wvca7E6QoLpoawZ1gP9JM0GJj4Tp5jMUh9B3AitHbRZ2/H3W5xQmdEOUlLg==, tarball: https://registry.npmjs.org/lightningcss-linux-arm64-gnu/-/lightningcss-linux-arm64-gnu-1.31.1.tgz} engines: {node: '>= 12.0.0'} cpu: [arm64] os: [linux] lightningcss-linux-arm64-gnu@1.32.0: - resolution: {integrity: sha512-0nnMyoyOLRJXfbMOilaSRcLH3Jw5z9HDNGfT/gwCPgaDjnx0i8w7vBzFLFR1f6CMLKF8gVbebmkUN3fa/kQJpQ==} + resolution: {integrity: sha512-0nnMyoyOLRJXfbMOilaSRcLH3Jw5z9HDNGfT/gwCPgaDjnx0i8w7vBzFLFR1f6CMLKF8gVbebmkUN3fa/kQJpQ==, tarball: https://registry.npmjs.org/lightningcss-linux-arm64-gnu/-/lightningcss-linux-arm64-gnu-1.32.0.tgz} engines: {node: '>= 12.0.0'} cpu: [arm64] os: [linux] lightningcss-linux-arm64-musl@1.31.1: - resolution: {integrity: sha512-mVZ7Pg2zIbe3XlNbZJdjs86YViQFoJSpc41CbVmKBPiGmC4YrfeOyz65ms2qpAobVd7WQsbW4PdsSJEMymyIMg==} + resolution: {integrity: sha512-mVZ7Pg2zIbe3XlNbZJdjs86YViQFoJSpc41CbVmKBPiGmC4YrfeOyz65ms2qpAobVd7WQsbW4PdsSJEMymyIMg==, tarball: https://registry.npmjs.org/lightningcss-linux-arm64-musl/-/lightningcss-linux-arm64-musl-1.31.1.tgz} engines: {node: '>= 12.0.0'} cpu: [arm64] os: [linux] lightningcss-linux-arm64-musl@1.32.0: - resolution: {integrity: sha512-UpQkoenr4UJEzgVIYpI80lDFvRmPVg6oqboNHfoH4CQIfNA+HOrZ7Mo7KZP02dC6LjghPQJeBsvXhJod/wnIBg==} + resolution: {integrity: sha512-UpQkoenr4UJEzgVIYpI80lDFvRmPVg6oqboNHfoH4CQIfNA+HOrZ7Mo7KZP02dC6LjghPQJeBsvXhJod/wnIBg==, tarball: https://registry.npmjs.org/lightningcss-linux-arm64-musl/-/lightningcss-linux-arm64-musl-1.32.0.tgz} engines: {node: '>= 12.0.0'} cpu: [arm64] os: [linux] lightningcss-linux-x64-gnu@1.31.1: - resolution: {integrity: sha512-xGlFWRMl+0KvUhgySdIaReQdB4FNudfUTARn7q0hh/V67PVGCs3ADFjw+6++kG1RNd0zdGRlEKa+T13/tQjPMA==} + resolution: {integrity: sha512-xGlFWRMl+0KvUhgySdIaReQdB4FNudfUTARn7q0hh/V67PVGCs3ADFjw+6++kG1RNd0zdGRlEKa+T13/tQjPMA==, tarball: https://registry.npmjs.org/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.31.1.tgz} engines: {node: '>= 12.0.0'} cpu: [x64] os: [linux] lightningcss-linux-x64-gnu@1.32.0: - resolution: {integrity: sha512-V7Qr52IhZmdKPVr+Vtw8o+WLsQJYCTd8loIfpDaMRWGUZfBOYEJeyJIkqGIDMZPwPx24pUMfwSxxI8phr/MbOA==} + resolution: {integrity: sha512-V7Qr52IhZmdKPVr+Vtw8o+WLsQJYCTd8loIfpDaMRWGUZfBOYEJeyJIkqGIDMZPwPx24pUMfwSxxI8phr/MbOA==, tarball: https://registry.npmjs.org/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.32.0.tgz} engines: {node: '>= 12.0.0'} cpu: [x64] os: [linux] lightningcss-linux-x64-musl@1.31.1: - resolution: {integrity: sha512-eowF8PrKHw9LpoZii5tdZwnBcYDxRw2rRCyvAXLi34iyeYfqCQNA9rmUM0ce62NlPhCvof1+9ivRaTY6pSKDaA==} + resolution: {integrity: sha512-eowF8PrKHw9LpoZii5tdZwnBcYDxRw2rRCyvAXLi34iyeYfqCQNA9rmUM0ce62NlPhCvof1+9ivRaTY6pSKDaA==, tarball: https://registry.npmjs.org/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.31.1.tgz} engines: {node: '>= 12.0.0'} cpu: [x64] os: [linux] lightningcss-linux-x64-musl@1.32.0: - resolution: {integrity: sha512-bYcLp+Vb0awsiXg/80uCRezCYHNg1/l3mt0gzHnWV9XP1W5sKa5/TCdGWaR/zBM2PeF/HbsQv/j2URNOiVuxWg==} + resolution: {integrity: sha512-bYcLp+Vb0awsiXg/80uCRezCYHNg1/l3mt0gzHnWV9XP1W5sKa5/TCdGWaR/zBM2PeF/HbsQv/j2URNOiVuxWg==, tarball: https://registry.npmjs.org/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.32.0.tgz} engines: {node: '>= 12.0.0'} cpu: [x64] os: [linux] lightningcss-win32-arm64-msvc@1.31.1: - resolution: {integrity: sha512-aJReEbSEQzx1uBlQizAOBSjcmr9dCdL3XuC/6HLXAxmtErsj2ICo5yYggg1qOODQMtnjNQv2UHb9NpOuFtYe4w==} + resolution: {integrity: sha512-aJReEbSEQzx1uBlQizAOBSjcmr9dCdL3XuC/6HLXAxmtErsj2ICo5yYggg1qOODQMtnjNQv2UHb9NpOuFtYe4w==, tarball: https://registry.npmjs.org/lightningcss-win32-arm64-msvc/-/lightningcss-win32-arm64-msvc-1.31.1.tgz} engines: {node: '>= 12.0.0'} cpu: [arm64] os: [win32] lightningcss-win32-arm64-msvc@1.32.0: - resolution: {integrity: sha512-8SbC8BR40pS6baCM8sbtYDSwEVQd4JlFTOlaD3gWGHfThTcABnNDBda6eTZeqbofalIJhFx0qKzgHJmcPTnGdw==} + resolution: {integrity: sha512-8SbC8BR40pS6baCM8sbtYDSwEVQd4JlFTOlaD3gWGHfThTcABnNDBda6eTZeqbofalIJhFx0qKzgHJmcPTnGdw==, tarball: https://registry.npmjs.org/lightningcss-win32-arm64-msvc/-/lightningcss-win32-arm64-msvc-1.32.0.tgz} engines: {node: '>= 12.0.0'} cpu: [arm64] os: [win32] lightningcss-win32-x64-msvc@1.31.1: - resolution: {integrity: sha512-I9aiFrbd7oYHwlnQDqr1Roz+fTz61oDDJX7n9tYF9FJymH1cIN1DtKw3iYt6b8WZgEjoNwVSncwF4wx/ZedMhw==} + resolution: {integrity: sha512-I9aiFrbd7oYHwlnQDqr1Roz+fTz61oDDJX7n9tYF9FJymH1cIN1DtKw3iYt6b8WZgEjoNwVSncwF4wx/ZedMhw==, tarball: https://registry.npmjs.org/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.31.1.tgz} engines: {node: '>= 12.0.0'} cpu: [x64] os: [win32] lightningcss-win32-x64-msvc@1.32.0: - resolution: {integrity: sha512-Amq9B/SoZYdDi1kFrojnoqPLxYhQ4Wo5XiL8EVJrVsB8ARoC1PWW6VGtT0WKCemjy8aC+louJnjS7U18x3b06Q==} + resolution: {integrity: sha512-Amq9B/SoZYdDi1kFrojnoqPLxYhQ4Wo5XiL8EVJrVsB8ARoC1PWW6VGtT0WKCemjy8aC+louJnjS7U18x3b06Q==, tarball: https://registry.npmjs.org/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.32.0.tgz} engines: {node: '>= 12.0.0'} cpu: [x64] os: [win32] @@ -5968,7 +6010,7 @@ packages: engines: {node: '>= 12.0.0'} lilconfig@2.1.0: - resolution: {integrity: sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ==} + resolution: {integrity: sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ==, tarball: https://registry.npmjs.org/lilconfig/-/lilconfig-2.1.0.tgz} engines: {node: '>=10'} lines-and-columns@1.2.4: @@ -5984,7 +6026,7 @@ packages: engines: {node: '>=20.0.0'} lodash@4.17.21: - resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==} + resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==, tarball: https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz} log-symbols@6.0.0: resolution: {integrity: sha512-i24m8rpwhmPIS4zscNzK6MSEhk0DUWa/8iYQWxhffV8jkI4Phvs3F+quL5xvS0gdQR0FyTCMMH33Y78dDTzzIw==} @@ -5995,7 +6037,7 @@ packages: engines: {node: '>=18'} long@5.3.2: - resolution: {integrity: sha512-mNAgZ1GmyNhD7AuqnTG3/VQ26o760+ZYBPKjPvugO8+nLbYfX6TVpJPseBvopbdY+qpZ/lKUnmEc1LeZYS3QAA==} + resolution: {integrity: sha512-mNAgZ1GmyNhD7AuqnTG3/VQ26o760+ZYBPKjPvugO8+nLbYfX6TVpJPseBvopbdY+qpZ/lKUnmEc1LeZYS3QAA==, tarball: https://registry.npmjs.org/long/-/long-5.3.2.tgz} longest-streak@3.1.0: resolution: {integrity: sha512-9Ri+o0JYgehTaVBBDoMqIl8GXtbWg711O3srftcHhZ0dqnETqLaoIK0x17fUw9rFSlK/0NlsKe0Ahhyl5pXE2g==} @@ -6005,14 +6047,14 @@ packages: hasBin: true lru-cache@11.3.3: - resolution: {integrity: sha512-JvNw9Y81y33E+BEYPr0U7omo+U9AySnsMsEiXgwT6yqd31VQWTLNQqmT4ou5eqPFUrTfIDFta2wKhB1hyohtAQ==} + resolution: {integrity: sha512-JvNw9Y81y33E+BEYPr0U7omo+U9AySnsMsEiXgwT6yqd31VQWTLNQqmT4ou5eqPFUrTfIDFta2wKhB1hyohtAQ==, tarball: https://registry.npmjs.org/lru-cache/-/lru-cache-11.3.3.tgz} engines: {node: 20 || >=22} lru-cache@5.1.1: resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==} lru.min@1.1.4: - resolution: {integrity: sha512-DqC6n3QQ77zdFpCMASA1a3Jlb64Hv2N2DciFGkO/4L9+q/IpIAuRlKOvCXabtRW6cQf8usbmM6BE/TOPysCdIA==} + resolution: {integrity: sha512-DqC6n3QQ77zdFpCMASA1a3Jlb64Hv2N2DciFGkO/4L9+q/IpIAuRlKOvCXabtRW6cQf8usbmM6BE/TOPysCdIA==, tarball: https://registry.npmjs.org/lru.min/-/lru.min-1.1.4.tgz} engines: {bun: '>=1.0.0', deno: '>=1.30.0', node: '>=8.0.0'} lucide-react@0.575.0: @@ -6092,7 +6134,7 @@ packages: resolution: {integrity: sha512-0H44vDimn51F0YwvxSJSm0eCDOJTRlmN0R1yBh4HLj9wiV1Dn0QoXGbvFAWj2hSItVTlCmBF1hqKlIyUBVFLPg==} mdn-data@2.27.1: - resolution: {integrity: sha512-9Yubnt3e8A0OKwxYSXyhLymGW4sCufcLG6VdiDdUGVkPhpqLxlvP5vl1983gQjJl3tqbrM731mjaZaP68AgosQ==} + resolution: {integrity: sha512-9Yubnt3e8A0OKwxYSXyhLymGW4sCufcLG6VdiDdUGVkPhpqLxlvP5vl1983gQjJl3tqbrM731mjaZaP68AgosQ==, tarball: https://registry.npmjs.org/mdn-data/-/mdn-data-2.27.1.tgz} media-typer@1.1.0: resolution: {integrity: sha512-aisnrDP4GNe06UcKFnV5bfMNPBUw4jsLGaWwWfnH3v02GnBuXX2MCVn5RbrWo0j3pczUilYblq7fQ7Nw2t5XKw==} @@ -6320,11 +6362,11 @@ packages: engines: {node: ^18.17.0 || >=20.5.0} mysql2@3.15.3: - resolution: {integrity: sha512-FBrGau0IXmuqg4haEZRBfHNWB5mUARw6hNwPDXXGg0XzVJ50mr/9hb267lvpVMnhZ1FON3qNd4Xfcez1rbFwSg==} + resolution: {integrity: sha512-FBrGau0IXmuqg4haEZRBfHNWB5mUARw6hNwPDXXGg0XzVJ50mr/9hb267lvpVMnhZ1FON3qNd4Xfcez1rbFwSg==, tarball: https://registry.npmjs.org/mysql2/-/mysql2-3.15.3.tgz} engines: {node: '>= 8.0'} named-placeholders@1.1.6: - resolution: {integrity: sha512-Tz09sEL2EEuv5fFowm419c1+a/jSMiBjI9gHxVLrVdbUkkNUUfjsVYs9pVZu5oCon/kmRh9TfLEObFtkVxmY0w==} + resolution: {integrity: sha512-Tz09sEL2EEuv5fFowm419c1+a/jSMiBjI9gHxVLrVdbUkkNUUfjsVYs9pVZu5oCon/kmRh9TfLEObFtkVxmY0w==, tarball: https://registry.npmjs.org/named-placeholders/-/named-placeholders-1.1.6.tgz} engines: {node: '>=8.0.0'} nano-spawn@2.0.0: @@ -6408,7 +6450,7 @@ packages: hasBin: true nypm@0.6.5: - resolution: {integrity: sha512-K6AJy1GMVyfyMXRVB88700BJqNUkByijGJM8kEHpLdcAt+vSQAVfkWWHYzuRXHSY6xA2sNc5RjTj0p9rE2izVQ==} + resolution: {integrity: sha512-K6AJy1GMVyfyMXRVB88700BJqNUkByijGJM8kEHpLdcAt+vSQAVfkWWHYzuRXHSY6xA2sNc5RjTj0p9rE2izVQ==, tarball: https://registry.npmjs.org/nypm/-/nypm-0.6.5.tgz} engines: {node: '>=18'} hasBin: true @@ -6477,7 +6519,7 @@ packages: engines: {node: '>=20'} openapi-types@12.1.3: - resolution: {integrity: sha512-N4YtSYJqghVu4iek2ZUvcN/0aqH1kRDuNqzcycDxhOUpg7GdvLa2F3DgS6yBNhInhv2r/6I0Flkn7CqL8+nIcw==} + resolution: {integrity: sha512-N4YtSYJqghVu4iek2ZUvcN/0aqH1kRDuNqzcycDxhOUpg7GdvLa2F3DgS6yBNhInhv2r/6I0Flkn7CqL8+nIcw==, tarball: https://registry.npmjs.org/openapi-types/-/openapi-types-12.1.3.tgz} ora@8.2.0: resolution: {integrity: sha512-weP+BZ8MVNnlCm8c0Qdc1WSWq4Qn7I+9CJGm7Qali6g44e/PUzbjNqJX5NJ9ljlNMosfJvg1fKEGILklK9cwnw==} @@ -6530,7 +6572,7 @@ packages: resolution: {integrity: sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw==} parse5@8.0.0: - resolution: {integrity: sha512-9m4m5GSgXjL4AjumKzq1Fgfp3Z8rsvjRNbnkVwfu2ImRqE5D0LnY2QfDen18FSY9C573YU5XxSapdHZTZ2WolA==} + resolution: {integrity: sha512-9m4m5GSgXjL4AjumKzq1Fgfp3Z8rsvjRNbnkVwfu2ImRqE5D0LnY2QfDen18FSY9C573YU5XxSapdHZTZ2WolA==, tarball: https://registry.npmjs.org/parse5/-/parse5-8.0.0.tgz} parseurl@1.3.3: resolution: {integrity: sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==} @@ -6570,7 +6612,7 @@ packages: resolution: {integrity: sha512-LjgdTytVFXeUgtHZr9WYViYSM/g8MkcTPYDlPa3cDqMirHjKiSZPYd6DoL7pK8AJQr+uWkQvCjHNdiMqsrJs+g==} pg-cloudflare@1.3.0: - resolution: {integrity: sha512-6lswVVSztmHiRtD6I8hw4qP/nDm1EJbKMRhf3HCYaqud7frGysPv7FYJ5noZQdhQtN2xJnimfMtvQq21pdbzyQ==} + resolution: {integrity: sha512-6lswVVSztmHiRtD6I8hw4qP/nDm1EJbKMRhf3HCYaqud7frGysPv7FYJ5noZQdhQtN2xJnimfMtvQq21pdbzyQ==, tarball: https://registry.npmjs.org/pg-cloudflare/-/pg-cloudflare-1.3.0.tgz} pg-connection-string@2.12.0: resolution: {integrity: sha512-U7qg+bpswf3Cs5xLzRqbXbQl85ng0mfSV/J0nnA31MCLgvEaAo7CIhmeyrmJpOr7o+zm0rXK+hNnT5l9RHkCkQ==} @@ -6647,6 +6689,16 @@ packages: pkg-types@2.3.0: resolution: {integrity: sha512-SIqCzDRg0s9npO5XQ3tNZioRY1uK06lA41ynBC1YmFTmnY6FjUjVt6s4LoADmwoig1qqD0oK8h1p/8mlMx8Oig==} + playwright-core@1.59.1: + resolution: {integrity: sha512-HBV/RJg81z5BiiZ9yPzIiClYV/QMsDCKUyogwH9p3MCP6IYjUFu/MActgYAvK0oWyV9NlwM3GLBjADyWgydVyg==, tarball: https://registry.npmjs.org/playwright-core/-/playwright-core-1.59.1.tgz} + engines: {node: '>=18'} + hasBin: true + + playwright@1.59.1: + resolution: {integrity: sha512-C8oWjPR3F81yljW9o5OxcWzfh6avkVwDD2VYdwIGqTkl+OGFISgypqzfu7dOe4QNLL2aqcWBmI3PMtLIK233lw==, tarball: https://registry.npmjs.org/playwright/-/playwright-1.59.1.tgz} + engines: {node: '>=18'} + hasBin: true + postal-mime@2.7.3: resolution: {integrity: sha512-MjhXadAJaWgYzevi46+3kLak8y6gbg0ku14O1gO/LNOuay8dO+1PtcSGvAdgDR0DoIsSaiIA8y/Ddw6MnrO0Tw==} @@ -6683,11 +6735,11 @@ packages: engines: {node: '>=0.10.0'} postgres@3.4.7: - resolution: {integrity: sha512-Jtc2612XINuBjIl/QTWsV5UvE8UHuNblcO3vVADSrKsrc6RqGX6lOW1cEo3CM2v0XG4Nat8nI+YM7/f26VxXLw==} + resolution: {integrity: sha512-Jtc2612XINuBjIl/QTWsV5UvE8UHuNblcO3vVADSrKsrc6RqGX6lOW1cEo3CM2v0XG4Nat8nI+YM7/f26VxXLw==, tarball: https://registry.npmjs.org/postgres/-/postgres-3.4.7.tgz} engines: {node: '>=12'} postgres@3.4.8: - resolution: {integrity: sha512-d+JFcLM17njZaOLkv6SCev7uoLaBtfK86vMUXhW1Z4glPWh4jozno9APvW/XKFJ3CCxVoC7OL38BqRydtu5nGg==} + resolution: {integrity: sha512-d+JFcLM17njZaOLkv6SCev7uoLaBtfK86vMUXhW1Z4glPWh4jozno9APvW/XKFJ3CCxVoC7OL38BqRydtu5nGg==, tarball: https://registry.npmjs.org/postgres/-/postgres-3.4.8.tgz} engines: {node: '>=12'} posthog-node@5.28.8: @@ -6717,7 +6769,7 @@ packages: engines: {node: '>=18'} prisma@7.4.2: - resolution: {integrity: sha512-2bP8Ruww3Q95Z2eH4Yqh4KAENRsj/SxbdknIVBfd6DmjPwmpsC4OVFMLOeHt6tM3Amh8ebjvstrUz3V/hOe1dA==} + resolution: {integrity: sha512-2bP8Ruww3Q95Z2eH4Yqh4KAENRsj/SxbdknIVBfd6DmjPwmpsC4OVFMLOeHt6tM3Amh8ebjvstrUz3V/hOe1dA==, tarball: https://registry.npmjs.org/prisma/-/prisma-7.4.2.tgz} engines: {node: ^20.19 || ^22.12 || >=24.0} hasBin: true peerDependencies: @@ -6740,7 +6792,7 @@ packages: resolution: {integrity: sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==} proper-lockfile@4.1.2: - resolution: {integrity: sha512-TjNPblN4BwAWMXU8s9AEz4JmQxnD1NNL7bNOY/AKUzyamc379FWASUhc/K1pL2noVb+XmZKLL68cjzLsiOAMaA==} + resolution: {integrity: sha512-TjNPblN4BwAWMXU8s9AEz4JmQxnD1NNL7bNOY/AKUzyamc379FWASUhc/K1pL2noVb+XmZKLL68cjzLsiOAMaA==, tarball: https://registry.npmjs.org/proper-lockfile/-/proper-lockfile-4.1.2.tgz} property-information@7.1.0: resolution: {integrity: sha512-TwEZ+X+yCJmYfL7TPUOcvBZ4QfoT5YenQiJuX//0th53DE6w0xxLEtfK3iyryQFddXuvkIk51EEgrJQ0WJkOmQ==} @@ -6757,11 +6809,11 @@ packages: resolution: {integrity: sha512-VS7sjc6KR7e1ukRFhQSY5LM2uBWAUPiOPa/A3mkKmiMwSmRFUITt0xuj+/lesgnCv+dPIEYlkzrcyXgquIHMcA==} punycode@2.3.1: - resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} + resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==, tarball: https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz} engines: {node: '>=6'} pure-rand@6.1.0: - resolution: {integrity: sha512-bVWawvoZoBYpp6yIoQtQXHZjmz35RSVHnUOTefl8Vcjr8snTPY1wnpSPMWekcFwbxI6gtmT7rSYPFvz71ldiOA==} + resolution: {integrity: sha512-bVWawvoZoBYpp6yIoQtQXHZjmz35RSVHnUOTefl8Vcjr8snTPY1wnpSPMWekcFwbxI6gtmT7rSYPFvz71ldiOA==, tarball: https://registry.npmjs.org/pure-rand/-/pure-rand-6.1.0.tgz} qs@6.15.0: resolution: {integrity: sha512-mAZTtNCeetKMH+pSjrb76NAM8V9a05I9aBZOHztWy/UqcJdQYNsf59vrRKWnojAT9Y+GbIvoTBC++CPHqpDBhQ==} @@ -6832,7 +6884,7 @@ packages: resolution: {integrity: sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==} react-is@18.3.1: - resolution: {integrity: sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==} + resolution: {integrity: sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==, tarball: https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz} react-medium-image-zoom@5.4.3: resolution: {integrity: sha512-cDIwdn35fRUPsGnnj/cG6Pacll+z+Mfv6EWU2wDO5ngbZjg5uLRb2ZhEnh92ufbXCJDFvXHekb8G3+oKqUcv5g==} @@ -6907,7 +6959,7 @@ packages: engines: {node: '>=8.10.0'} readdirp@4.1.2: - resolution: {integrity: sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==} + resolution: {integrity: sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==, tarball: https://registry.npmjs.org/readdirp/-/readdirp-4.1.2.tgz} engines: {node: '>= 14.18.0'} readdirp@5.0.0: @@ -6962,7 +7014,7 @@ packages: resolution: {integrity: sha512-6VwtthbV4o/7+OaAF9I5L5V3llLEsoPyq9P1JVXkedTP33c7MfCG0/5NOPcSJn0TzXcG9YUrR0gQSWioew3LDg==} regexp-to-ast@0.5.0: - resolution: {integrity: sha512-tlbJqcMHnPKI9zSrystikWKwHkBqu2a/Sgw01h3zFjvYrMxEDYHzzoMZnUrbIfpTFEsoRnnviOXNCzFiSc54Qw==} + resolution: {integrity: sha512-tlbJqcMHnPKI9zSrystikWKwHkBqu2a/Sgw01h3zFjvYrMxEDYHzzoMZnUrbIfpTFEsoRnnviOXNCzFiSc54Qw==, tarball: https://registry.npmjs.org/regexp-to-ast/-/regexp-to-ast-0.5.0.tgz} rehype-raw@7.0.0: resolution: {integrity: sha512-/aE8hCfKlQeA8LmyeyQvQF3eBiLRGNlfBJEvWH7ivp9sBqs7TNqBL5X3v157rM4IFETqDnIOO+z5M/biZbo9Ww==} @@ -6989,7 +7041,7 @@ packages: resolution: {integrity: sha512-Eht5w30ruCXgFmxVUSlNWQ9iiimq07URKeFS3hNc8cUWy1llX4KDWfyEDZRycMc+znsN9Ux5/tJ/BFdgdOwA3A==} remeda@2.33.4: - resolution: {integrity: sha512-ygHswjlc/opg2VrtiYvUOPLjxjtdKvjGz1/plDhkG66hjNjFr1xmfrs2ClNFo/E6TyUFiwYNh53bKV26oBoMGQ==} + resolution: {integrity: sha512-ygHswjlc/opg2VrtiYvUOPLjxjtdKvjGz1/plDhkG66hjNjFr1xmfrs2ClNFo/E6TyUFiwYNh53bKV26oBoMGQ==, tarball: https://registry.npmjs.org/remeda/-/remeda-2.33.4.tgz} require-directory@2.1.1: resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==} @@ -7027,7 +7079,7 @@ packages: engines: {node: '>=18'} retry@0.12.0: - resolution: {integrity: sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==} + resolution: {integrity: sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==, tarball: https://registry.npmjs.org/retry/-/retry-0.12.0.tgz} engines: {node: '>= 4'} rettime@0.10.1: @@ -7110,7 +7162,7 @@ packages: resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} saxes@6.0.0: - resolution: {integrity: sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA==} + resolution: {integrity: sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA==, tarball: https://registry.npmjs.org/saxes/-/saxes-6.0.0.tgz} engines: {node: '>=v12.22.7'} scheduler@0.27.0: @@ -7142,16 +7194,16 @@ packages: engines: {node: '>= 18'} seq-queue@0.0.5: - resolution: {integrity: sha512-hr3Wtp/GZIc/6DAGPDcV4/9WoZhjrkXsi5B/07QgX8tsdc6ilr7BFM6PM6rbdAX1kFSDYeZGLipIZZKyQP0O5Q==} + resolution: {integrity: sha512-hr3Wtp/GZIc/6DAGPDcV4/9WoZhjrkXsi5B/07QgX8tsdc6ilr7BFM6PM6rbdAX1kFSDYeZGLipIZZKyQP0O5Q==, tarball: https://registry.npmjs.org/seq-queue/-/seq-queue-0.0.5.tgz} seroval-plugins@1.5.2: - resolution: {integrity: sha512-qpY0Cl+fKYFn4GOf3cMiq6l72CpuVaawb6ILjubOQ+diJ54LfOWaSSPsaswN8DRPIPW4Yq+tE1k5aKd7ILyaFg==} + resolution: {integrity: sha512-qpY0Cl+fKYFn4GOf3cMiq6l72CpuVaawb6ILjubOQ+diJ54LfOWaSSPsaswN8DRPIPW4Yq+tE1k5aKd7ILyaFg==, tarball: https://registry.npmjs.org/seroval-plugins/-/seroval-plugins-1.5.2.tgz} engines: {node: '>=10'} peerDependencies: seroval: ^1.0 seroval@1.5.2: - resolution: {integrity: sha512-xcRN39BdsnO9Tf+VzsE7b3JyTJASItIV1FVFewJKCFcW4s4haIKS3e6vj8PGB9qBwC7tnuOywQMdv5N4qkzi7Q==} + resolution: {integrity: sha512-xcRN39BdsnO9Tf+VzsE7b3JyTJASItIV1FVFewJKCFcW4s4haIKS3e6vj8PGB9qBwC7tnuOywQMdv5N4qkzi7Q==, tarball: https://registry.npmjs.org/seroval/-/seroval-1.5.2.tgz} engines: {node: '>=10'} serve-static@2.2.1: @@ -7172,7 +7224,7 @@ packages: hasBin: true sharp@0.34.5: - resolution: {integrity: sha512-Ou9I5Ft9WNcCbXrU9cMgPBcCK8LiwLqcbywW3t4oDV37n1pzpuNLsYiAV8eODnjbtQlSDwZ2cUEeQz4E54Hltg==} + resolution: {integrity: sha512-Ou9I5Ft9WNcCbXrU9cMgPBcCK8LiwLqcbywW3t4oDV37n1pzpuNLsYiAV8eODnjbtQlSDwZ2cUEeQz4E54Hltg==, tarball: https://registry.npmjs.org/sharp/-/sharp-0.34.5.tgz} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} shebang-command@2.0.0: @@ -7184,7 +7236,7 @@ packages: engines: {node: '>=8'} shell-quote@1.8.3: - resolution: {integrity: sha512-ObmnIF4hXNg1BqhnHmgbDETF8dLPCggZWBjkQfhZpbszZnYur5DUljTcCHii5LC3J5E0yeO/1LIMyH+UvHQgyw==} + resolution: {integrity: sha512-ObmnIF4hXNg1BqhnHmgbDETF8dLPCggZWBjkQfhZpbszZnYur5DUljTcCHii5LC3J5E0yeO/1LIMyH+UvHQgyw==, tarball: https://registry.npmjs.org/shell-quote/-/shell-quote-1.8.3.tgz} engines: {node: '>= 0.4'} shiki@4.0.0: @@ -7272,7 +7324,7 @@ packages: engines: {node: '>= 10.x'} sqlstring@2.3.3: - resolution: {integrity: sha512-qC9iz2FlN7DQl3+wjwn3802RTyjCx7sDvfQEXchwa6CWOx07/WVfh91gBmQ9fahw8snwGEWU3xGzOt4tFyHLxg==} + resolution: {integrity: sha512-qC9iz2FlN7DQl3+wjwn3802RTyjCx7sDvfQEXchwa6CWOx07/WVfh91gBmQ9fahw8snwGEWU3xGzOt4tFyHLxg==, tarball: https://registry.npmjs.org/sqlstring/-/sqlstring-2.3.3.tgz} engines: {node: '>= 0.6'} stack-utils@2.0.6: @@ -7357,7 +7409,7 @@ packages: optional: true strtok3@10.3.5: - resolution: {integrity: sha512-ki4hZQfh5rX0QDLLkOCj+h+CVNkqmp/CMf8v8kZpkNVK6jGQooMytqzLZYUVYIZcFZ6yDB70EfD8POcFXiF5oA==} + resolution: {integrity: sha512-ki4hZQfh5rX0QDLLkOCj+h+CVNkqmp/CMf8v8kZpkNVK6jGQooMytqzLZYUVYIZcFZ6yDB70EfD8POcFXiF5oA==, tarball: https://registry.npmjs.org/strtok3/-/strtok3-10.3.5.tgz} engines: {node: '>=18'} stubborn-fs@2.0.0: @@ -7405,7 +7457,7 @@ packages: resolution: {integrity: sha512-/HTvXwjLJe1l/MsLXAO1ddCYxElJk4eNR4DzOjDOEmGrPN/3BtBE8perGwMAaJ2sT5T172VkBYzmHcjUfM1JRQ==} symbol-tree@3.2.4: - resolution: {integrity: sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==} + resolution: {integrity: sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==, tarball: https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz} system-architecture@0.1.0: resolution: {integrity: sha512-ulAk51I9UVUyJgxlv9M6lFot2WP3e7t8Kz9+IS6D4rVba1tR9kON+Ey69f+1R4Q8cd45Lod6a4IcJIxnzGc/zA==} @@ -7448,7 +7500,7 @@ packages: resolution: {integrity: sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg==} tiny-warning@1.0.3: - resolution: {integrity: sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA==} + resolution: {integrity: sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA==, tarball: https://registry.npmjs.org/tiny-warning/-/tiny-warning-1.0.3.tgz} tinybench@2.9.0: resolution: {integrity: sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==} @@ -7480,14 +7532,14 @@ packages: resolution: {integrity: sha512-0g9vrtDQLrNIiCj22HSe9d4mLVG3g5ph5DZ8zCKBr4OtrspmNB6ss7hVyzArAeE88ceZocIEGkyW1Ime7fxPtQ==} tldts-core@7.0.28: - resolution: {integrity: sha512-7W5Efjhsc3chVdFhqtaU0KtK32J37Zcr9RKtID54nG+tIpcY79CQK/veYPODxtD/LJ4Lue66jvrQzIX2Z2/pUQ==} + resolution: {integrity: sha512-7W5Efjhsc3chVdFhqtaU0KtK32J37Zcr9RKtID54nG+tIpcY79CQK/veYPODxtD/LJ4Lue66jvrQzIX2Z2/pUQ==, tarball: https://registry.npmjs.org/tldts-core/-/tldts-core-7.0.28.tgz} tldts@7.0.23: resolution: {integrity: sha512-ASdhgQIBSay0R/eXggAkQ53G4nTJqTXqC2kbaBbdDwM7SkjyZyO0OaaN1/FH7U/yCeqOHDwFO5j8+Os/IS1dXw==} hasBin: true tldts@7.0.28: - resolution: {integrity: sha512-+Zg3vWhRUv8B1maGSTFdev9mjoo8Etn2Ayfs4cnjlD3CsGkxXX4QyW3j2WJ0wdjYcYmy7Lx2RDsZMhgCWafKIw==} + resolution: {integrity: sha512-+Zg3vWhRUv8B1maGSTFdev9mjoo8Etn2Ayfs4cnjlD3CsGkxXX4QyW3j2WJ0wdjYcYmy7Lx2RDsZMhgCWafKIw==, tarball: https://registry.npmjs.org/tldts/-/tldts-7.0.28.tgz} hasBin: true to-regex-range@5.0.1: @@ -7503,7 +7555,7 @@ packages: engines: {node: '>=0.6'} token-types@6.1.2: - resolution: {integrity: sha512-dRXchy+C0IgK8WPC6xvCHFRIWYUbqqdEIKPaKo/AcTUNzwLTK6AH7RjdLWsEZcAN/TBdtfUw3PYEgPr5VPr6ww==} + resolution: {integrity: sha512-dRXchy+C0IgK8WPC6xvCHFRIWYUbqqdEIKPaKo/AcTUNzwLTK6AH7RjdLWsEZcAN/TBdtfUw3PYEgPr5VPr6ww==, tarball: https://registry.npmjs.org/token-types/-/token-types-6.1.2.tgz} engines: {node: '>=14.16'} tough-cookie@6.0.0: @@ -7511,11 +7563,11 @@ packages: engines: {node: '>=16'} tough-cookie@6.0.1: - resolution: {integrity: sha512-LktZQb3IeoUWB9lqR5EWTHgW/VTITCXg4D21M+lvybRVdylLrRMnqaIONLVb5mav8vM19m44HIcGq4qASeu2Qw==} + resolution: {integrity: sha512-LktZQb3IeoUWB9lqR5EWTHgW/VTITCXg4D21M+lvybRVdylLrRMnqaIONLVb5mav8vM19m44HIcGq4qASeu2Qw==, tarball: https://registry.npmjs.org/tough-cookie/-/tough-cookie-6.0.1.tgz} engines: {node: '>=16'} tr46@6.0.0: - resolution: {integrity: sha512-bLVMLPtstlZ4iMQHpFHTR7GAGj2jxi8Dg0s2h2MafAE4uSWF98FC/3MomU51iQAMf8/qDUbKWf5GxuvvVcXEhw==} + resolution: {integrity: sha512-bLVMLPtstlZ4iMQHpFHTR7GAGj2jxi8Dg0s2h2MafAE4uSWF98FC/3MomU51iQAMf8/qDUbKWf5GxuvvVcXEhw==, tarball: https://registry.npmjs.org/tr46/-/tr46-6.0.0.tgz} engines: {node: '>=20'} tree-kill@1.2.2: @@ -7572,32 +7624,32 @@ packages: hasBin: true turbo-darwin-64@2.8.10: - resolution: {integrity: sha512-A03fXh+B7S8mL3PbdhTd+0UsaGrhfyPkODvzBDpKRY7bbeac4MDFpJ7I+Slf2oSkCEeSvHKR7Z4U71uKRUfX7g==} + resolution: {integrity: sha512-A03fXh+B7S8mL3PbdhTd+0UsaGrhfyPkODvzBDpKRY7bbeac4MDFpJ7I+Slf2oSkCEeSvHKR7Z4U71uKRUfX7g==, tarball: https://registry.npmjs.org/turbo-darwin-64/-/turbo-darwin-64-2.8.10.tgz} cpu: [x64] os: [darwin] turbo-darwin-arm64@2.8.10: - resolution: {integrity: sha512-sidzowgWL3s5xCHLeqwC9M3s9M0i16W1nuQF3Mc7fPHpZ+YPohvcbVFBB2uoRRHYZg6yBnwD4gyUHKTeXfwtXA==} + resolution: {integrity: sha512-sidzowgWL3s5xCHLeqwC9M3s9M0i16W1nuQF3Mc7fPHpZ+YPohvcbVFBB2uoRRHYZg6yBnwD4gyUHKTeXfwtXA==, tarball: https://registry.npmjs.org/turbo-darwin-arm64/-/turbo-darwin-arm64-2.8.10.tgz} cpu: [arm64] os: [darwin] turbo-linux-64@2.8.10: - resolution: {integrity: sha512-YK9vcpL3TVtqonB021XwgaQhY9hJJbKKUhLv16osxV0HkcQASQWUqR56yMge7puh6nxU67rQlTq1b7ksR1T3KA==} + resolution: {integrity: sha512-YK9vcpL3TVtqonB021XwgaQhY9hJJbKKUhLv16osxV0HkcQASQWUqR56yMge7puh6nxU67rQlTq1b7ksR1T3KA==, tarball: https://registry.npmjs.org/turbo-linux-64/-/turbo-linux-64-2.8.10.tgz} cpu: [x64] os: [linux] turbo-linux-arm64@2.8.10: - resolution: {integrity: sha512-3+j2tL0sG95iBJTm+6J8/45JsETQABPqtFyYjVjBbi6eVGdtNTiBmHNKrbvXRlQ3ZbUG75bKLaSSDHSEEN+btQ==} + resolution: {integrity: sha512-3+j2tL0sG95iBJTm+6J8/45JsETQABPqtFyYjVjBbi6eVGdtNTiBmHNKrbvXRlQ3ZbUG75bKLaSSDHSEEN+btQ==, tarball: https://registry.npmjs.org/turbo-linux-arm64/-/turbo-linux-arm64-2.8.10.tgz} cpu: [arm64] os: [linux] turbo-windows-64@2.8.10: - resolution: {integrity: sha512-hdeF5qmVY/NFgiucf8FW0CWJWtyT2QPm5mIsX0W1DXAVzqKVXGq+Zf+dg4EUngAFKjDzoBeN6ec2Fhajwfztkw==} + resolution: {integrity: sha512-hdeF5qmVY/NFgiucf8FW0CWJWtyT2QPm5mIsX0W1DXAVzqKVXGq+Zf+dg4EUngAFKjDzoBeN6ec2Fhajwfztkw==, tarball: https://registry.npmjs.org/turbo-windows-64/-/turbo-windows-64-2.8.10.tgz} cpu: [x64] os: [win32] turbo-windows-arm64@2.8.10: - resolution: {integrity: sha512-QGdr/Q8LWmj+ITMkSvfiz2glf0d7JG0oXVzGL3jxkGqiBI1zXFj20oqVY0qWi+112LO9SVrYdpHS0E/oGFrMbQ==} + resolution: {integrity: sha512-QGdr/Q8LWmj+ITMkSvfiz2glf0d7JG0oXVzGL3jxkGqiBI1zXFj20oqVY0qWi+112LO9SVrYdpHS0E/oGFrMbQ==, tarball: https://registry.npmjs.org/turbo-windows-arm64/-/turbo-windows-arm64-2.8.10.tgz} cpu: [arm64] os: [win32] @@ -7655,7 +7707,7 @@ packages: resolution: {integrity: sha512-AsuCzffGHJybSaRrmr5eHr81mwJU3kjw6M+uprWvCXiNeN9SOGwQ3Jn8jb8m3Z6izVgknn1R0FTCEAP2QrLY/w==} undici@7.24.7: - resolution: {integrity: sha512-H/nlJ/h0ggGC+uRL3ovD+G0i4bqhvsDOpbDv7At5eFLlj2b41L8QliGbnl2H7SnDiYhENphh1tQFJZf+MyfLsQ==} + resolution: {integrity: sha512-H/nlJ/h0ggGC+uRL3ovD+G0i4bqhvsDOpbDv7At5eFLlj2b41L8QliGbnl2H7SnDiYhENphh1tQFJZf+MyfLsQ==, tarball: https://registry.npmjs.org/undici/-/undici-7.24.7.tgz} engines: {node: '>=20.18.1'} unicorn-magic@0.3.0: @@ -7750,7 +7802,7 @@ packages: hasBin: true valibot@1.2.0: - resolution: {integrity: sha512-mm1rxUsmOxzrwnX5arGS+U4T25RdvpPjPN4yR0u9pUBov9+zGVtO84tif1eY4r6zWxVxu3KzIyknJy3rxfRZZg==} + resolution: {integrity: sha512-mm1rxUsmOxzrwnX5arGS+U4T25RdvpPjPN4yR0u9pUBov9+zGVtO84tif1eY4r6zWxVxu3KzIyknJy3rxfRZZg==, tarball: https://registry.npmjs.org/valibot/-/valibot-1.2.0.tgz} peerDependencies: typescript: '>=5' peerDependenciesMeta: @@ -7901,7 +7953,7 @@ packages: optional: true w3c-xmlserializer@5.0.0: - resolution: {integrity: sha512-o8qghlI8NZHU1lLPrpi2+Uq7abh4GGPpYANlalzWxyWteJOCsr/P+oPBA49TOLu5FTZO4d3F9MnWJfiMo4BkmA==} + resolution: {integrity: sha512-o8qghlI8NZHU1lLPrpi2+Uq7abh4GGPpYANlalzWxyWteJOCsr/P+oPBA49TOLu5FTZO4d3F9MnWJfiMo4BkmA==, tarball: https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-5.0.0.tgz} engines: {node: '>=18'} web-namespaces@2.0.1: @@ -7912,15 +7964,15 @@ packages: engines: {node: '>= 8'} webidl-conversions@8.0.1: - resolution: {integrity: sha512-BMhLD/Sw+GbJC21C/UgyaZX41nPt8bUTg+jWyDeg7e7YN4xOM05YPSIXceACnXVtqyEw/LMClUQMtMZ+PGGpqQ==} + resolution: {integrity: sha512-BMhLD/Sw+GbJC21C/UgyaZX41nPt8bUTg+jWyDeg7e7YN4xOM05YPSIXceACnXVtqyEw/LMClUQMtMZ+PGGpqQ==, tarball: https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-8.0.1.tgz} engines: {node: '>=20'} whatwg-mimetype@5.0.0: - resolution: {integrity: sha512-sXcNcHOC51uPGF0P/D4NVtrkjSU2fNsm9iog4ZvZJsL3rjoDAzXZhkm2MWt1y+PUdggKAYVoMAIYcs78wJ51Cw==} + resolution: {integrity: sha512-sXcNcHOC51uPGF0P/D4NVtrkjSU2fNsm9iog4ZvZJsL3rjoDAzXZhkm2MWt1y+PUdggKAYVoMAIYcs78wJ51Cw==, tarball: https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-5.0.0.tgz} engines: {node: '>=20'} whatwg-url@16.0.1: - resolution: {integrity: sha512-1to4zXBxmXHV3IiSSEInrreIlu02vUOvrhxJJH5vcxYTBDAx51cqZiKdyTxlecdKNSjj8EcxGBxNf6Vg+945gw==} + resolution: {integrity: sha512-1to4zXBxmXHV3IiSSEInrreIlu02vUOvrhxJJH5vcxYTBDAx51cqZiKdyTxlecdKNSjj8EcxGBxNf6Vg+945gw==, tarball: https://registry.npmjs.org/whatwg-url/-/whatwg-url-16.0.1.tgz} engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0} when-exit@2.1.5: @@ -7986,11 +8038,11 @@ packages: engines: {node: '>=20'} xml-name-validator@5.0.0: - resolution: {integrity: sha512-EvGK8EJ3DhaHfbRlETOWAS5pO9MZITeauHKJyb8wyajUfQUenkIg2MvLDTZ4T/TgIcm3HU0TFBgWWboAZ30UHg==} + resolution: {integrity: sha512-EvGK8EJ3DhaHfbRlETOWAS5pO9MZITeauHKJyb8wyajUfQUenkIg2MvLDTZ4T/TgIcm3HU0TFBgWWboAZ30UHg==, tarball: https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-5.0.0.tgz} engines: {node: '>=18'} xmlchars@2.2.0: - resolution: {integrity: sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==} + resolution: {integrity: sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==, tarball: https://registry.npmjs.org/xmlchars/-/xmlchars-2.2.0.tgz} xtend@4.0.2: resolution: {integrity: sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==} @@ -8039,7 +8091,7 @@ packages: resolution: {integrity: sha512-0LPOt3AxKqMdFBZA3HBAt/t/8vIKq7VaQYbuA8WxCgung+p9TVyKRYdpvCb80HcdTN2NkbIKbhNwKUfm3tQywQ==} zeptomatch@2.1.0: - resolution: {integrity: sha512-KiGErG2J0G82LSpniV0CtIzjlJ10E04j02VOudJsPyPwNZgGnRKQy7I1R7GMyg/QswnE4l7ohSGrQbQbjXPPDA==} + resolution: {integrity: sha512-KiGErG2J0G82LSpniV0CtIzjlJ10E04j02VOudJsPyPwNZgGnRKQy7I1R7GMyg/QswnE4l7ohSGrQbQbjXPPDA==, tarball: https://registry.npmjs.org/zeptomatch/-/zeptomatch-2.1.0.tgz} zod-to-json-schema@3.25.1: resolution: {integrity: sha512-pM/SU9d3YAggzi6MtR4h7ruuQlqKtad8e9S0fmxcMi+ueAK5Korys/aWcV9LIIHTVbj01NdzxcnXSN+O74ZIVA==} @@ -9533,6 +9585,11 @@ snapshots: '@pinojs/redact@0.4.0': {} + '@polar-sh/sdk@0.47.0': + dependencies: + standardwebhooks: 1.0.0 + zod: 4.3.6 + '@posthog/core@1.24.3': dependencies: cross-spawn: 7.0.6 @@ -12354,6 +12411,9 @@ snapshots: dependencies: minipass: 3.3.6 + fsevents@2.3.2: + optional: true + fsevents@2.3.3: optional: true @@ -12410,7 +12470,7 @@ snapshots: transitivePeerDependencies: - supports-color - fumadocs-mdx@14.2.11(@types/mdast@4.0.4)(@types/mdx@2.0.13)(@types/react@19.2.14)(fumadocs-core@16.7.11(@mdx-js/mdx@3.1.1)(@tanstack/react-router@1.166.2(react-dom@19.2.5(react@19.2.5))(react@19.2.5))(@types/estree-jsx@1.0.5)(@types/hast@3.0.4)(@types/mdast@4.0.4)(@types/react@19.2.14)(lucide-react@0.575.0(react@19.2.5))(next@16.2.3(@babel/core@7.29.0)(@opentelemetry/api@1.9.0)(react-dom@19.2.5(react@19.2.5))(react@19.2.5))(react-dom@19.2.5(react@19.2.5))(react@19.2.5)(zod@3.25.76))(next@16.2.3(@babel/core@7.29.0)(@opentelemetry/api@1.9.0)(react-dom@19.2.5(react@19.2.5))(react@19.2.5))(react@19.2.5)(vite@8.0.3(@types/node@20.19.34)(esbuild@0.27.3)(jiti@2.6.1)(tsx@4.21.0)(yaml@2.8.2)): + fumadocs-mdx@14.2.11(@types/mdast@4.0.4)(@types/mdx@2.0.13)(@types/react@19.2.14)(fumadocs-core@16.7.11(@mdx-js/mdx@3.1.1)(@tanstack/react-router@1.166.2(react-dom@19.2.5(react@19.2.5))(react@19.2.5))(@types/estree-jsx@1.0.5)(@types/hast@3.0.4)(@types/mdast@4.0.4)(@types/react@19.2.14)(lucide-react@0.575.0(react@19.2.5))(next@16.2.3(@babel/core@7.29.0)(@opentelemetry/api@1.9.0)(react-dom@19.2.5(react@19.2.5))(react@19.2.5))(react-dom@19.2.5(react@19.2.5))(react@19.2.5)(zod@3.25.76))(next@16.2.3(@babel/core@7.29.0)(@opentelemetry/api@1.9.0)(react-dom@19.2.5(react@19.2.5))(react@19.2.5))(react@19.2.5): dependencies: '@mdx-js/mdx': 3.1.1 '@standard-schema/spec': 1.1.0 @@ -12436,7 +12496,6 @@ snapshots: '@types/react': 19.2.14 next: 16.2.3(@babel/core@7.29.0)(@opentelemetry/api@1.9.0)(react-dom@19.2.5(react@19.2.5))(react@19.2.5) react: 19.2.5 - vite: 8.0.3(@types/node@20.19.34)(esbuild@0.27.3)(jiti@2.6.1)(tsx@4.21.0)(yaml@2.8.2) transitivePeerDependencies: - supports-color @@ -14314,6 +14373,14 @@ snapshots: exsolve: 1.0.8 pathe: 2.0.3 + playwright-core@1.59.1: {} + + playwright@1.59.1: + dependencies: + playwright-core: 1.59.1 + optionalDependencies: + fsevents: 2.3.2 + postal-mime@2.7.3: {} postcss-selector-parser@7.1.1: @@ -14829,6 +14896,23 @@ snapshots: transitivePeerDependencies: - oxc-resolver + rolldown-plugin-dts@0.22.4(oxc-resolver@11.19.1(@emnapi/core@1.8.1)(@emnapi/runtime@1.8.1))(rolldown@1.0.0-rc.8)(typescript@5.9.3): + dependencies: + '@babel/generator': 8.0.0-rc.2 + '@babel/helper-validator-identifier': 8.0.0-rc.2 + '@babel/parser': 8.0.0-rc.2 + '@babel/types': 8.0.0-rc.2 + ast-kit: 3.0.0-beta.1 + birpc: 4.0.0 + dts-resolver: 2.1.3(oxc-resolver@11.19.1(@emnapi/core@1.8.1)(@emnapi/runtime@1.8.1)) + get-tsconfig: 4.13.6 + obug: 2.1.1 + rolldown: 1.0.0-rc.8 + optionalDependencies: + typescript: 5.9.3 + transitivePeerDependencies: + - oxc-resolver + rolldown@1.0.0-rc.12: dependencies: '@oxc-project/types': 0.122.0 @@ -15529,6 +15613,33 @@ snapshots: - synckit - vue-tsc + tsdown@0.21.1(oxc-resolver@11.19.1(@emnapi/core@1.8.1)(@emnapi/runtime@1.8.1))(typescript@5.9.3): + dependencies: + ansis: 4.2.0 + cac: 7.0.0 + defu: 6.1.4 + empathic: 2.0.0 + hookable: 6.0.1 + import-without-cache: 0.2.5 + obug: 2.1.1 + picomatch: 4.0.3 + rolldown: 1.0.0-rc.8 + rolldown-plugin-dts: 0.22.4(oxc-resolver@11.19.1(@emnapi/core@1.8.1)(@emnapi/runtime@1.8.1))(rolldown@1.0.0-rc.8)(typescript@5.9.3) + semver: 7.7.4 + tinyexec: 1.0.2 + tinyglobby: 0.2.16 + tree-kill: 1.2.2 + unconfig-core: 7.5.0 + unrun: 0.2.31 + optionalDependencies: + typescript: 5.9.3 + transitivePeerDependencies: + - '@ts-macro/tsc' + - '@typescript/native-preview' + - oxc-resolver + - synckit + - vue-tsc + tslib@2.8.1: {} tsx@4.21.0: @@ -15782,22 +15893,6 @@ snapshots: tsx: 4.21.0 yaml: 2.8.2 - vite@8.0.3(@types/node@20.19.34)(esbuild@0.27.3)(jiti@2.6.1)(tsx@4.21.0)(yaml@2.8.2): - dependencies: - lightningcss: 1.32.0 - picomatch: 4.0.4 - postcss: 8.5.8 - rolldown: 1.0.0-rc.12 - tinyglobby: 0.2.16 - optionalDependencies: - '@types/node': 20.19.34 - esbuild: 0.27.3 - fsevents: 2.3.3 - jiti: 2.6.1 - tsx: 4.21.0 - yaml: 2.8.2 - optional: true - vite@8.0.3(@types/node@25.3.0)(esbuild@0.27.3)(jiti@2.6.1)(tsx@4.21.0)(yaml@2.8.2): dependencies: lightningcss: 1.32.0