diff --git a/.changeset/late-colts-shout.md b/.changeset/late-colts-shout.md deleted file mode 100644 index a8d9104b4e..0000000000 --- a/.changeset/late-colts-shout.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"api": minor ---- - -add /v1/keys.whoami route diff --git a/.github/workflows/pr-alerts-campsite.yml b/.github/workflows/pr-alerts-campsite.yml new file mode 100644 index 0000000000..9587de0368 --- /dev/null +++ b/.github/workflows/pr-alerts-campsite.yml @@ -0,0 +1,53 @@ +name: Campsite PR Alerts + +on: + pull_request: + types: [opened, closed, merged, ready_for_review, reopened] + +jobs: + post_to_campsite: + runs-on: ubuntu-latest + + steps: + - name: Checkout repository + uses: actions/checkout@v2 + + - name: Set up Node.js + uses: actions/setup-node@v2 + with: + node-version: '20' + + - name: Post to Campsite + id: post_to_campsite + run: | + if [[ "${{ github.event.pull_request.draft }}" == "true" ]]; then + STATUS_EMOJI="⚪" + elif [[ "${{ github.event.action }}" == "opened" || "${{ github.event.action }}" == "reopened" || "${{ github.event.action }}" == "ready_for_review" ]]; then + STATUS_EMOJI="🟢" + elif [[ "${{ github.event.action }}" == "closed" && "${{ github.event.pull_request.merged }}" == "true" ]]; then + STATUS_EMOJI="🟣" + elif [[ "${{ github.event.action }}" == "closed" ]]; then + STATUS_EMOJI="🔴" + fi + + ACTION=${{ github.event.action }} + if [[ "${ACTION}" == "ready_for_review" ]]; then + ACTION="ready for review" + elif [[ "${ACTION}" == "reopened" ]]; then + ACTION="reopened" + elif [[ "${ACTION}" == "closed" && "${{ github.event.pull_request.merged }}" == "true" ]]; then + ACTION="merged" + fi + + ESCAPED_TITLE=$(echo "${{ github.event.pull_request.title }}" | jq -Rr @json) + + CONTENT="${STATUS_EMOJI} Pull request ${ACTION} by ${{ github.event.pull_request.user.login }}: [#${{ github.event.pull_request.number }} ${ESCAPED_TITLE}](${{ github.event.pull_request.html_url }})" + + echo "content=${CONTENT}" >> $GITHUB_OUTPUT + - name: Create Campsite message + uses: campsite/campsite-github-action@v1 + with: + api_key: ${{ secrets.CAMPSITE_API_KEY }} + action_type: create_message + thread_id: ${{ secrets.CAMPSITE_PR_ALERTS_THREAD_ID }} + content: ${{ steps.post_to_campsite.outputs.content }} diff --git a/apps/api/CHANGELOG.md b/apps/api/CHANGELOG.md index 3c58505cf5..fbae939478 100644 --- a/apps/api/CHANGELOG.md +++ b/apps/api/CHANGELOG.md @@ -1,5 +1,11 @@ # api +## 0.1.0 + +### Minor Changes + +- 09d36ad: add /v1/keys.whoami route + ## 0.0.14 ### Patch Changes diff --git a/apps/api/package.json b/apps/api/package.json index 7f3da98972..6945d90ee3 100644 --- a/apps/api/package.json +++ b/apps/api/package.json @@ -1,6 +1,6 @@ { "name": "api", - "version": "0.0.14", + "version": "0.1.0", "private": true, "scripts": { "build": "tsc", diff --git a/apps/api/src/pkg/env.ts b/apps/api/src/pkg/env.ts index 6ce33d7a81..335c865164 100644 --- a/apps/api/src/pkg/env.ts +++ b/apps/api/src/pkg/env.ts @@ -1,6 +1,10 @@ import { z } from "zod"; import type { MessageBody } from "./key_migration/message"; +export const cloudflareRatelimiter = z.custom<{ + limit: (opts: { key: string }) => Promise<{ success: boolean }>; +}>((r) => typeof r.limit === "function"); + export const zEnv = z.object({ VERSION: z.string().default("unknown"), DATABASE_HOST: z.string(), @@ -42,6 +46,11 @@ export const zEnv = z.object({ return 0; } }), + RL_10_60s: cloudflareRatelimiter, + RL_30_60s: cloudflareRatelimiter, + RL_200_60s: cloudflareRatelimiter, + RL_500_10s: cloudflareRatelimiter, + RL_200_10s: cloudflareRatelimiter, }); export type Env = z.infer; diff --git a/apps/api/src/pkg/key_migration/handler.ts b/apps/api/src/pkg/key_migration/handler.ts index d3875a8837..1696a18463 100644 --- a/apps/api/src/pkg/key_migration/handler.ts +++ b/apps/api/src/pkg/key_migration/handler.ts @@ -96,6 +96,7 @@ export async function migrateKey( expires: message.expires ? new Date(message.expires) : null, refillInterval: message.refill?.interval, refillAmount: message.refill?.amount, + refillDay: message.refill?.refillDay, enabled: message.enabled, remaining: message.remaining, ratelimitAsync: message.ratelimit?.async, diff --git a/apps/api/src/pkg/key_migration/message.ts b/apps/api/src/pkg/key_migration/message.ts index 33cd34c509..91a9e39ccc 100644 --- a/apps/api/src/pkg/key_migration/message.ts +++ b/apps/api/src/pkg/key_migration/message.ts @@ -14,7 +14,7 @@ export type MessageBody = { permissions?: string[]; expires?: number; remaining?: number; - refill?: { interval: "daily" | "monthly"; amount: number }; + refill?: { interval: "daily" | "monthly"; amount: number; refillDay?: number }; ratelimit?: { async: boolean; limit: number; duration: number }; enabled: boolean; environment?: string; diff --git a/apps/api/src/pkg/keys/service.ts b/apps/api/src/pkg/keys/service.ts index bf28869692..8b2dab21fd 100644 --- a/apps/api/src/pkg/keys/service.ts +++ b/apps/api/src/pkg/keys/service.ts @@ -57,7 +57,11 @@ type InvalidResponse = { | "DISABLED" | "INSUFFICIENT_PERMISSIONS"; key: Key; - identity: { id: string; externalId: string; meta: Record | null } | null; + identity: { + id: string; + externalId: string; + meta: Record | null; + } | null; api: Api; ratelimit?: { remaining: number; @@ -73,7 +77,11 @@ type ValidResponse = { code?: never; valid: true; key: Key; - identity: { id: string; externalId: string; meta: Record | null } | null; + identity: { + id: string; + externalId: string; + meta: Record | null; + } | null; api: Api; ratelimit?: { remaining: number; @@ -451,6 +459,7 @@ export class KeyService { if (data.api.ipWhitelist) { const ip = c.req.header("True-Client-IP") ?? c.req.header("CF-Connecting-IP"); + if (!ip) { return Ok({ key: data.key, @@ -461,7 +470,8 @@ export class KeyService { permissions: data.permissions, }); } - const ipWhitelist = JSON.parse(data.api.ipWhitelist) as string[]; + + const ipWhitelist = data.api.ipWhitelist.split(",").map((s) => s.trim()); if (!ipWhitelist.includes(ip)) { return Ok({ key: data.key, diff --git a/apps/api/src/pkg/ratelimit/client.ts b/apps/api/src/pkg/ratelimit/client.ts index fc231d9d04..40730a93c3 100644 --- a/apps/api/src/pkg/ratelimit/client.ts +++ b/apps/api/src/pkg/ratelimit/client.ts @@ -1,8 +1,8 @@ import { Err, Ok, type Result } from "@unkey/error"; import type { Logger } from "@unkey/worker-logging"; -import type { Metrics } from "../metrics"; - +import { cloudflareRatelimiter } from "../env"; import type { Context } from "../hono/app"; +import type { Metrics } from "../metrics"; import { retry } from "../util/retry"; import { Agent } from "./agent"; import { @@ -11,7 +11,6 @@ import { type RatelimitRequest, type RatelimitResponse, } from "./interface"; - export class AgentRatelimiter implements RateLimiter { private readonly logger: Logger; private readonly metrics: Metrics; @@ -67,7 +66,34 @@ export class AgentRatelimiter implements RateLimiter { req: RatelimitRequest, ): Promise> { const start = performance.now(); + try { + if (req.async) { + // Construct a binding key that could match a configured ratelimiter + const lookup = `RL_${req.limit}_${Math.round(req.interval / 1000)}s` as keyof typeof c.env; + const binding = c.env[lookup]; + + if (binding) { + const res = await cloudflareRatelimiter.parse(binding).limit({ key: req.identifier }); + this.metrics.emit({ + metric: "metric.ratelimit", + workspaceId: req.workspaceId, + namespaceId: req.namespaceId, + latency: performance.now() - start, + identifier: req.identifier, + mode: "async", + error: false, + success: res.success, + source: "cloudflare", + }); + return Ok({ pass: res.success, reset: -1, current: -1, remaining: -1, triggered: null }); + } + } + } catch (err) { + this.logger.error("cfrl failed, falling back to agent", { + error: (err as Error).message, + }); + } const res = await this._limit(c, req); this.metrics.emit({ metric: "metric.ratelimit", diff --git a/apps/api/src/routes/legacy_keys_verifyKey.test.ts b/apps/api/src/routes/legacy_keys_verifyKey.test.ts index eba5cfa153..6d549e55ee 100644 --- a/apps/api/src/routes/legacy_keys_verifyKey.test.ts +++ b/apps/api/src/routes/legacy_keys_verifyKey.test.ts @@ -129,7 +129,7 @@ describe("with ip whitelist", () => { name: "test", authType: "key", keyAuthId: keyAuthId, - ipWhitelist: JSON.stringify(["100.100.100.100"]), + ipWhitelist: ["100.100.100.100"].join(","), createdAt: new Date(), deletedAt: null, }); @@ -177,7 +177,7 @@ describe("with ip whitelist", () => { name: "test", authType: "key", keyAuthId: keyAuthid, - ipWhitelist: JSON.stringify(["100.100.100.100"]), + ipWhitelist: ["100.100.100.100"].join(","), createdAt: new Date(), deletedAt: null, }); diff --git a/apps/api/src/routes/schema.ts b/apps/api/src/routes/schema.ts index 1652e8e92f..a9d4d4b14b 100644 --- a/apps/api/src/routes/schema.ts +++ b/apps/api/src/routes/schema.ts @@ -59,13 +59,19 @@ export const keySchema = z refill: z .object({ interval: z.enum(["daily", "monthly"]).openapi({ - description: "Determines the rate at which verifications will be refilled.", + description: + "Determines the rate at which verifications will be refilled. When 'daily' is set for 'interval' 'refillDay' will be set to null.", example: "daily", }), amount: z.number().int().openapi({ description: "Resets `remaining` to this value every interval.", example: 100, }), + refillDay: z.number().min(1).max(31).default(1).nullable().openapi({ + description: + "The day verifications will refill each month, when interval is set to 'monthly'. Value is not zero-indexed making 1 the first day of the month. If left blank it will default to the first day of the month. When 'daily' is set for 'interval' 'refillDay' will be set to null.", + example: 15, + }), lastRefillAt: z.number().int().optional().openapi({ description: "The unix timestamp in miliseconds when the key was last refilled.", example: 100, @@ -76,10 +82,12 @@ export const keySchema = z description: "Unkey allows you to refill remaining verifications on a key on a regular interval.", example: { - interval: "daily", + interval: "monthly", amount: 10, + refillDay: 10, }, }), + ratelimit: z .object({ async: z.boolean().openapi({ diff --git a/apps/api/src/routes/v1_apis_getApi.happy.test.ts b/apps/api/src/routes/v1_apis_getApi.happy.test.ts index 23600af73a..60cdbc991d 100644 --- a/apps/api/src/routes/v1_apis_getApi.happy.test.ts +++ b/apps/api/src/routes/v1_apis_getApi.happy.test.ts @@ -31,7 +31,7 @@ test("with ip whitelist", async (t) => { id: newId("api"), name: "with ip whitelist", workspaceId: h.resources.userWorkspace.id, - ipWhitelist: JSON.stringify(["127.0.0.1"]), + ipWhitelist: ["127.0.0.1"].join(","), createdAt: new Date(), deletedAt: null, }; diff --git a/apps/api/src/routes/v1_apis_listKeys.ts b/apps/api/src/routes/v1_apis_listKeys.ts index c7c7b51f56..ab38e76085 100644 --- a/apps/api/src/routes/v1_apis_listKeys.ts +++ b/apps/api/src/routes/v1_apis_listKeys.ts @@ -317,6 +317,7 @@ export const registerV1ApisListKeys = (app: App) => ? { interval: k.refillInterval, amount: k.refillAmount, + refillDay: k.refillInterval === "monthly" && k.refillDay ? k.refillDay : null, lastRefillAt: k.lastRefillAt?.getTime(), } : undefined, diff --git a/apps/api/src/routes/v1_keys_createKey.error.test.ts b/apps/api/src/routes/v1_keys_createKey.error.test.ts index ced18efc5d..f9a197f956 100644 --- a/apps/api/src/routes/v1_keys_createKey.error.test.ts +++ b/apps/api/src/routes/v1_keys_createKey.error.test.ts @@ -11,7 +11,6 @@ import type { V1KeysCreateKeyRequest, V1KeysCreateKeyResponse } from "./v1_keys_ test("when the api does not exist", async (t) => { const h = await IntegrationHarness.init(t); const apiId = newId("api"); - const root = await h.createRootKey([`api.${apiId}.create_key`]); /* The code snippet is making a POST request to the "/v1/keys.createKey" endpoint with the specified headers. It is using the `h.post` method from the `Harness` instance to send the request. The generic types `` specify the request payload and response types respectively. */ @@ -119,3 +118,35 @@ test("when key recovery is not enabled", async (t) => { }, }); }); + +test("reject invalid refill config when daily interval has non-null refillDay", async (t) => { + const h = await IntegrationHarness.init(t); + + const root = await h.createRootKey([`api.${h.resources.userApi.id}.create_key`]); + + const res = await h.post({ + url: "/v1/keys.createKey", + headers: { + "Content-Type": "application/json", + Authorization: `Bearer ${root.key}`, + }, + body: { + byteLength: 16, + apiId: h.resources.userApi.id, + remaining: 10, + refill: { + amount: 100, + refillDay: 4, + interval: "daily", + }, + }, + }); + expect(res.status).toEqual(400); + expect(res.body).toMatchObject({ + error: { + code: "BAD_REQUEST", + docs: "https://unkey.dev/docs/api-reference/errors/code/BAD_REQUEST", + message: "when interval is set to 'daily', 'refillDay' must be null.", + }, + }); +}); diff --git a/apps/api/src/routes/v1_keys_createKey.happy.test.ts b/apps/api/src/routes/v1_keys_createKey.happy.test.ts index 8b02cec8e5..d8a8be632d 100644 --- a/apps/api/src/routes/v1_keys_createKey.happy.test.ts +++ b/apps/api/src/routes/v1_keys_createKey.happy.test.ts @@ -467,4 +467,35 @@ describe("with externalId", () => { expect(key!.identity!.id).toEqual(identity.id); }); }); + describe("Should default first day of month if none provided", () => { + test("should provide default value", async (t) => { + const h = await IntegrationHarness.init(t); + const root = await h.createRootKey([`api.${h.resources.userApi.id}.create_key`]); + + const res = await h.post({ + url: "/v1/keys.createKey", + headers: { + "Content-Type": "application/json", + Authorization: `Bearer ${root.key}`, + }, + body: { + apiId: h.resources.userApi.id, + remaining: 10, + refill: { + interval: "monthly", + amount: 20, + refillDay: undefined, + }, + }, + }); + + expect(res.status, `expected 200, received: ${JSON.stringify(res, null, 2)}`).toBe(200); + + const key = await h.db.primary.query.keys.findFirst({ + where: (table, { eq }) => eq(table.id, res.body.keyId), + }); + expect(key).toBeDefined(); + expect(key!.refillDay).toEqual(1); + }); + }); }); diff --git a/apps/api/src/routes/v1_keys_createKey.ts b/apps/api/src/routes/v1_keys_createKey.ts index 4841dfb36c..3870d7d68c 100644 --- a/apps/api/src/routes/v1_keys_createKey.ts +++ b/apps/api/src/routes/v1_keys_createKey.ts @@ -118,16 +118,27 @@ When validating a key, we will return this back to you, so you can clearly ident description: "The number of verifications to refill for each occurrence is determined individually for each key.", }), + refillDay: z + .number() + .min(1) + .max(31) + .optional() + .openapi({ + description: `The day of the month, when we will refill the remaining verifications. To refill on the 15th of each month, set 'refillDay': 15. + If the day does not exist, for example you specified the 30th and it's february, we will refill them on the last day of the month instead.`, + }), }) .optional() .openapi({ description: "Unkey enables you to refill verifications for each key at regular intervals.", example: { - interval: "daily", + interval: "monthly", amount: 100, + refillDay: 15, }, }), + ratelimit: z .object({ async: z @@ -309,6 +320,12 @@ export const registerV1KeysCreateKey = (app: App) => message: "remaining must be set if you are using refill.", }); } + if (req.refill?.refillDay && req.refill.interval === "daily") { + throw new UnkeyApiError({ + code: "BAD_REQUEST", + message: "when interval is set to 'daily', 'refillDay' must be null.", + }); + } /** * Set up an api for production */ @@ -325,6 +342,7 @@ export const registerV1KeysCreateKey = (app: App) => ? upsertIdentity(db.primary, authorizedWorkspaceId, externalId) : Promise.resolve(null), ]); + const newKey = await retry(5, async (attempt) => { if (attempt > 1) { logger.warn("retrying key creation", { @@ -357,6 +375,7 @@ export const registerV1KeysCreateKey = (app: App) => ratelimitDuration: req.ratelimit?.duration ?? req.ratelimit?.refillInterval, remaining: req.remaining, refillInterval: req.refill?.interval, + refillDay: req.refill?.interval === "daily" ? null : req?.refill?.refillDay ?? 1, refillAmount: req.refill?.amount, lastRefillAt: req.refill?.interval ? new Date() : null, deletedAt: null, diff --git a/apps/api/src/routes/v1_keys_getKey.ts b/apps/api/src/routes/v1_keys_getKey.ts index a1fd3efb23..524b5b215c 100644 --- a/apps/api/src/routes/v1_keys_getKey.ts +++ b/apps/api/src/routes/v1_keys_getKey.ts @@ -155,6 +155,7 @@ export const registerV1KeysGetKey = (app: App) => ? { interval: key.refillInterval, amount: key.refillAmount, + refillDay: key.refillInterval === "monthly" ? key.refillDay : null, lastRefillAt: key.lastRefillAt?.getTime(), } : undefined, diff --git a/apps/api/src/routes/v1_keys_updateKey.error.test.ts b/apps/api/src/routes/v1_keys_updateKey.error.test.ts index b9954a3642..396b0564cd 100644 --- a/apps/api/src/routes/v1_keys_updateKey.error.test.ts +++ b/apps/api/src/routes/v1_keys_updateKey.error.test.ts @@ -3,6 +3,10 @@ import { expect, test } from "vitest"; import { newId } from "@unkey/id"; import { IntegrationHarness } from "src/pkg/testutil/integration-harness"; +import type { ErrorResponse } from "@/pkg/errors"; +import { schema } from "@unkey/db"; +import { sha256 } from "@unkey/hash"; +import { KeyV1 } from "@unkey/keys"; import type { V1KeysUpdateKeyRequest, V1KeysUpdateKeyResponse } from "./v1_keys_updateKey"; test("when the key does not exist", async (t) => { @@ -31,3 +35,46 @@ test("when the key does not exist", async (t) => { }, }); }); +test("reject invalid refill config", async (t) => { + const h = await IntegrationHarness.init(t); + const keyId = newId("test"); + const root = await h.createRootKey([`api.${h.resources.userApi.id}.update_key`]); + /* The code snippet is making a POST request to the "/v1/keys.createKey" endpoint with the specified headers. It is using the `h.post` method from the `Harness` instance to send the request. The generic types `` specify the request payload and response types respectively. */ + const key = { + id: keyId, + keyAuthId: h.resources.userKeyAuth.id, + workspaceId: h.resources.userWorkspace.id, + start: "test", + name: "test", + remaining: 10, + hash: await sha256(new KeyV1({ byteLength: 16 }).toString()), + + createdAt: new Date(), + }; + await h.db.primary.insert(schema.keys).values(key); + + const res = await h.post({ + url: "/v1/keys.updateKey", + headers: { + "Content-Type": "application/json", + Authorization: `Bearer ${root.key}`, + }, + body: { + keyId, + remaining: 10, + refill: { + amount: 100, + refillDay: 4, + interval: "daily", + }, + }, + }); + expect(res.status).toEqual(400); + expect(res.body).toMatchObject({ + error: { + code: "BAD_REQUEST", + docs: "https://unkey.dev/docs/api-reference/errors/code/BAD_REQUEST", + message: "Cannot set 'refillDay' if 'interval' is 'daily'", + }, + }); +}); diff --git a/apps/api/src/routes/v1_keys_updateKey.happy.test.ts b/apps/api/src/routes/v1_keys_updateKey.happy.test.ts index 30c1d555e1..f51d034a19 100644 --- a/apps/api/src/routes/v1_keys_updateKey.happy.test.ts +++ b/apps/api/src/routes/v1_keys_updateKey.happy.test.ts @@ -1013,3 +1013,48 @@ test("update ratelimit should not disable it", async (t) => { expect(verify.body.ratelimit!.limit).toBe(5); expect(verify.body.ratelimit!.remaining).toBe(4); }); +describe("When refillDay is omitted.", () => { + test("should provide default value", async (t) => { + const h = await IntegrationHarness.init(t); + + const key = { + id: newId("test"), + keyAuthId: h.resources.userKeyAuth.id, + workspaceId: h.resources.userWorkspace.id, + start: "test", + name: "test", + remaining: 10, + hash: await sha256(new KeyV1({ byteLength: 16 }).toString()), + + createdAt: new Date(), + }; + await h.db.primary.insert(schema.keys).values(key); + const root = await h.createRootKey([`api.${h.resources.userApi.id}.update_key`]); + const res = await h.post({ + url: "/v1/keys.updateKey", + headers: { + "Content-Type": "application/json", + Authorization: `Bearer ${root.key}`, + }, + body: { + keyId: key.id, + refill: { + interval: "monthly", + amount: 130, + }, + enabled: true, + }, + }); + + expect(res.status, `expected 200, received: ${JSON.stringify(res, null, 2)}`).toBe(200); + + const found = await h.db.primary.query.keys.findFirst({ + where: (table, { eq }) => eq(table.id, key.id), + }); + expect(found).toBeDefined(); + expect(found?.remaining).toEqual(10); + expect(found?.refillAmount).toEqual(130); + expect(found?.refillInterval).toEqual("monthly"); + expect(found?.refillDay).toEqual(1); + }); +}); diff --git a/apps/api/src/routes/v1_keys_updateKey.ts b/apps/api/src/routes/v1_keys_updateKey.ts index a2c90fb72d..c28c0d3e0e 100644 --- a/apps/api/src/routes/v1_keys_updateKey.ts +++ b/apps/api/src/routes/v1_keys_updateKey.ts @@ -151,6 +151,10 @@ This field will become required in a future version.`, description: "The amount of verifications to refill for each occurrence is determined individually for each key.", }), + refillDay: z.number().min(1).max(31).optional().openapi({ + description: + "The day verifications will refill each month, when interval is set to 'monthly'", + }), }) .nullable() .optional() @@ -276,9 +280,7 @@ export const registerV1KeysUpdate = (app: App) => app.openapi(route, async (c) => { const req = c.req.valid("json"); const { cache, db, usageLimiter, analytics, rbac } = c.get("services"); - const auth = await rootKeyAuth(c); - const key = await db.primary.query.keys.findFirst({ where: (table, { eq }) => eq(table.id, req.keyId), with: { @@ -329,13 +331,12 @@ export const registerV1KeysUpdate = (app: App) => message: "Cannot set refill on a key with unlimited requests", }); } - if (req.refill && key.remaining === null) { + if (req.refill?.interval === "daily" && req.refill.refillDay) { throw new UnkeyApiError({ code: "BAD_REQUEST", - message: "Cannot set refill on a key with unlimited requests", + message: "Cannot set 'refillDay' if 'interval' is 'daily'", }); } - const authorizedWorkspaceId = auth.authorizedWorkspaceId; const rootKeyId = auth.key.id; @@ -377,6 +378,7 @@ export const registerV1KeysUpdate = (app: App) => : req.ratelimit?.duration ?? req.ratelimit?.refillInterval ?? null, refillInterval: req.refill === null ? null : req.refill?.interval, refillAmount: req.refill === null ? null : req.refill?.amount, + refillDay: req.refill?.interval === "daily" ? null : req?.refill?.refillDay ?? 1, lastRefillAt: req.refill == null || req.refill?.amount == null ? null : new Date(), enabled: req.enabled, }) diff --git a/apps/api/src/routes/v1_keys_verifyKey.test.ts b/apps/api/src/routes/v1_keys_verifyKey.test.ts index d97e9d1952..a5534e16ca 100644 --- a/apps/api/src/routes/v1_keys_verifyKey.test.ts +++ b/apps/api/src/routes/v1_keys_verifyKey.test.ts @@ -349,6 +349,7 @@ describe("when ratelimited", () => { expect(res.body.identity!.externalId).toEqual(externalId); }); }); + describe("with ratelimit override", () => { test("deducts the correct number of tokens", { timeout: 20000 }, async (t) => { const h = await IntegrationHarness.init(t); @@ -517,7 +518,7 @@ describe("with ip whitelist", () => { name: "test", authType: "key", keyAuthId: keyAuthId, - ipWhitelist: JSON.stringify(["100.100.100.100"]), + ipWhitelist: ["100.100.100.100"].join(","), createdAt: new Date(), }); @@ -565,7 +566,7 @@ describe("with ip whitelist", () => { name: "test", authType: "key", keyAuthId: keyAuthid, - ipWhitelist: JSON.stringify(["100.100.100.100"]), + ipWhitelist: ["100.100.100.100"].join(","), createdAt: new Date(), }); diff --git a/apps/api/src/routes/v1_migrations_createKey.error.test.ts b/apps/api/src/routes/v1_migrations_createKey.error.test.ts index 45523eaec5..14562b30e1 100644 --- a/apps/api/src/routes/v1_migrations_createKey.error.test.ts +++ b/apps/api/src/routes/v1_migrations_createKey.error.test.ts @@ -112,3 +112,39 @@ test("reject invalid ratelimit config", async (t) => { expect(res.status).toEqual(400); expect(res.body.error.code).toEqual("BAD_REQUEST"); }); +test("reject invalid refill config when daily interval has non-null refillDay", async (t) => { + const h = await IntegrationHarness.init(t); + const { key } = await h.createRootKey(["*"]); + + const res = await h.post({ + url: "/v1/migrations.createKeys", + headers: { + "Content-Type": "application/json", + Authorization: `Bearer ${key}`, + }, + body: [ + { + start: "x", + hash: { + value: "x", + variant: "sha256_base64", + }, + apiId: h.resources.userApi.id, + remaining: 10, + refill: { + amount: 100, + refillDay: 4, + interval: "daily", + }, + }, + ], + }); + expect(res.status).toEqual(400); + expect(res.body).toMatchObject({ + error: { + code: "BAD_REQUEST", + docs: "https://unkey.dev/docs/api-reference/errors/code/BAD_REQUEST", + message: "when interval is set to 'daily', 'refillDay' must be null.", + }, + }); +}); diff --git a/apps/api/src/routes/v1_migrations_createKey.happy.test.ts b/apps/api/src/routes/v1_migrations_createKey.happy.test.ts index 6fe8f27b48..6e633b90a3 100644 --- a/apps/api/src/routes/v1_migrations_createKey.happy.test.ts +++ b/apps/api/src/routes/v1_migrations_createKey.happy.test.ts @@ -496,3 +496,48 @@ test("migrate and verify a key", async (t) => { expect(verifyRes.status).toBe(200); expect(verifyRes.body.valid).toEqual(true); }); + +describe("Should default to first day of month if none provided", () => { + test("should provide default value", async (t) => { + const h = await IntegrationHarness.init(t); + const root = await h.createRootKey([`api.${h.resources.userApi.id}.create_key`]); + + const hash = await sha256(randomUUID()); + const res = await h.post({ + url: "/v1/migrations.createKeys", + headers: { + "Content-Type": "application/json", + Authorization: `Bearer ${root.key}`, + }, + body: [ + { + start: "start_", + hash: { + value: hash, + variant: "sha256_base64", + }, + apiId: h.resources.userApi.id, + enabled: true, + remaining: 10, + refill: { + interval: "monthly", + amount: 100, + refillDay: undefined, + }, + }, + ], + }); + + expect(res.status, `expected 200, received: ${JSON.stringify(res, null, 2)}`).toBe(200); + + const found = await h.db.primary.query.keys.findFirst({ + where: (table, { eq }) => eq(table.id, res.body.keyIds[0]), + }); + expect(found).toBeDefined(); + expect(found?.remaining).toEqual(10); + expect(found?.refillAmount).toEqual(100); + expect(found?.refillInterval).toEqual("monthly"); + expect(found?.refillDay).toEqual(1); + expect(found?.hash).toEqual(hash); + }); +}); diff --git a/apps/api/src/routes/v1_migrations_createKey.ts b/apps/api/src/routes/v1_migrations_createKey.ts index 50914bc9d0..311c54fb1c 100644 --- a/apps/api/src/routes/v1_migrations_createKey.ts +++ b/apps/api/src/routes/v1_migrations_createKey.ts @@ -131,6 +131,10 @@ When validating a key, we will return this back to you, so you can clearly ident description: "The number of verifications to refill for each occurrence is determined individually for each key.", }), + refillDay: z.number().min(1).max(31).optional().openapi({ + description: + "The day verifications will refill each month, when interval is set to 'monthly'", + }), }) .optional() .openapi({ @@ -388,6 +392,12 @@ export const registerV1MigrationsCreateKeys = (app: App) => message: "provide either `hash` or `plaintext`", }); } + if (key.refill?.refillDay && key.refill.interval === "daily") { + throw new UnkeyApiError({ + code: "BAD_REQUEST", + message: "when interval is set to 'daily', 'refillDay' must be null.", + }); + } /** * Set up an api for production */ @@ -412,14 +422,15 @@ export const registerV1MigrationsCreateKeys = (app: App) => ratelimitDuration: key.ratelimit?.refillInterval ?? key.ratelimit?.refillInterval ?? null, remaining: key.remaining ?? null, refillInterval: key.refill?.interval ?? null, + refillDay: key.refill?.interval === "daily" ? null : key?.refill?.refillDay ?? 1, refillAmount: key.refill?.amount ?? null, - lastRefillAt: key.refill?.interval ? new Date() : null, deletedAt: null, enabled: key.enabled ?? true, environment: key.environment ?? null, createdAtM: Date.now(), updatedAtM: null, deletedAtM: null, + lastRefillAt: null, }); for (const role of key.roles ?? []) { diff --git a/apps/api/src/routes/v1_migrations_enqueueKeys.ts b/apps/api/src/routes/v1_migrations_enqueueKeys.ts index efecfe80cc..a21d6931ea 100644 --- a/apps/api/src/routes/v1_migrations_enqueueKeys.ts +++ b/apps/api/src/routes/v1_migrations_enqueueKeys.ts @@ -131,6 +131,10 @@ When validating a key, we will return this back to you, so you can clearly ident description: "The number of verifications to refill for each occurrence is determined individually for each key.", }), + refillDay: z.number().min(1).max(31).optional().openapi({ + description: + "The day verifications will refill each month, when interval is set to 'monthly'", + }), }) .optional() .openapi({ diff --git a/apps/api/wrangler.toml b/apps/api/wrangler.toml index 7aaea468c5..17c309cb67 100644 --- a/apps/api/wrangler.toml +++ b/apps/api/wrangler.toml @@ -35,6 +35,44 @@ bindings = [ { name = "DO_USAGELIMIT", class_name = "DurableObjectUsagelimiter" }, ] +[[unsafe.bindings]] +# The nameing scheme is important, because we're dynamically constructing +# these in the api code +# +# RL_{LIMIT}_{DURATION}s +# +# The namespace_id schema is somewhat made up though. +# I prefixed everything with 9900 -> 9900{limit}{duration} +name = "RL_10_60s" +type = "ratelimit" +namespace_id = "99001060" +simple = { limit = 10, period = 60} + +[[unsafe.bindings]] +name = "RL_30_60s" +type = "ratelimit" +namespace_id = "99003060" +simple = { limit = 30, period = 60} + +[[unsafe.bindings]] +name = "RL_200_60s" +type = "ratelimit" +namespace_id = "990020060" +simple = { limit = 200, period = 60} + +[[unsafe.bindings]] +name = "RL_500_10s" +type = "ratelimit" +namespace_id = "990050010" +simple = { limit = 500, period = 10} + +[[unsafe.bindings]] +name = "RL_200_10s" +type = "ratelimit" +namespace_id = "990020010" +simple = { limit = 200, period = 10} + + [queues] consumers = [ { queue = "key-migrations-development", max_batch_size = 10, max_retries = 10, dead_letter_queue = "key-migrations-development-dlq" }, @@ -62,6 +100,45 @@ consumers = [ { queue = "key-migrations-preview-dlq", max_batch_size = 10, max_retries = 10 }, ] +[[env.preview.unsafe.bindings]] +# The nameing scheme is important, because we're dynamically constructing +# these in the api code +# +# RL_{LIMIT}_{DURATION}s +# +# The namespace_id schema is somewhat made up though. +# I prefixed everything with 9900 -> 9900{limit}{duration} +name = "RL_10_60s" +type = "ratelimit" +namespace_id = "99001060" +simple = { limit = 10, period = 60} + +[[env.preview.unsafe.bindings]] +name = "RL_30_60s" +type = "ratelimit" +namespace_id = "99003060" +simple = { limit = 30, period = 60} + +[[env.preview.unsafe.bindings]] +name = "RL_200_60s" +type = "ratelimit" +namespace_id = "990020060" +simple = { limit = 200, period = 60} + +[[env.preview.unsafe.bindings]] +name = "RL_500_10s" +type = "ratelimit" +namespace_id = "990050010" +simple = { limit = 500, period = 10} + +[[env.preview.unsafe.bindings]] +name = "RL_200_10s" +type = "ratelimit" +namespace_id = "990020010" +simple = { limit = 200, period = 10} + + + # canary is a special environment that is used to test new code by a small percentage of users before it is rolled out to the rest of the world. # all settings must be the same as production, except for the route pattern [env.canary] @@ -81,6 +158,45 @@ consumers = [ { queue = "key-migrations-canary", max_batch_size = 10, max_retries = 10, dead_letter_queue = "key-migrations-canary-dlq" }, { queue = "key-migrations-canary-dlq", max_batch_size = 10, max_retries = 10 }, ] + +[[env.canary.unsafe.bindings]] +# The nameing scheme is important, because we're dynamically constructing +# these in the api code +# +# RL_{LIMIT}_{DURATION}s +# +# The namespace_id schema is somewhat made up though. +# I prefixed everything with 9900 -> 9900{limit}{duration} +name = "RL_10_60s" +type = "ratelimit" +namespace_id = "99001060" +simple = { limit = 10, period = 60} + +[[env.canary.unsafe.bindings]] +name = "RL_30_60s" +type = "ratelimit" +namespace_id = "99003060" +simple = { limit = 30, period = 60} + +[[env.canary.unsafe.bindings]] +name = "RL_200_60s" +type = "ratelimit" +namespace_id = "990020060" +simple = { limit = 200, period = 60} + +[[env.canary.unsafe.bindings]] +name = "RL_500_10s" +type = "ratelimit" +namespace_id = "990050010" +simple = { limit = 500, period = 10} + +[[env.canary.unsafe.bindings]] +name = "RL_200_10s" +type = "ratelimit" +namespace_id = "990020010" +simple = { limit = 200, period = 10} + + [env.production] vars = { ENVIRONMENT = "production", SYNC_RATELIMIT_ON_NO_DATA = "1" } route = { pattern = "api.unkey.dev", custom_domain = true } @@ -104,3 +220,42 @@ consumers = [ [env.production.observability] enabled = true + +[[env.production.unsafe.bindings]] +# The nameing scheme is important, because we're dynamically constructing +# these in the api code +# +# RL_{LIMIT}_{DURATION}s +# +# The namespace_id schema is somewhat made up though. +# I prefixed everything with 9900 -> 9900{limit}{duration} +name = "RL_10_60s" +type = "ratelimit" +namespace_id = "99001060" +simple = { limit = 10, period = 60} + +[[env.production.unsafe.bindings]] +name = "RL_30_60s" +type = "ratelimit" +namespace_id = "99003060" +simple = { limit = 30, period = 60} + +[[env.production.unsafe.bindings]] +name = "RL_200_60s" +type = "ratelimit" +namespace_id = "990020060" +simple = { limit = 200, period = 60} + +[[env.production.unsafe.bindings]] +name = "RL_500_10s" +type = "ratelimit" +namespace_id = "990050010" +simple = { limit = 500, period = 10} + +[[env.production.unsafe.bindings]] +name = "RL_200_10s" +type = "ratelimit" +namespace_id = "990020010" +simple = { limit = 200, period = 10} + + diff --git a/apps/dashboard/app/(app)/apis/[apiId]/keys/[keyAuthId]/[keyId]/settings/update-key-remaining.tsx b/apps/dashboard/app/(app)/apis/[apiId]/keys/[keyAuthId]/[keyId]/settings/update-key-remaining.tsx index 0a9d978f65..beee505036 100644 --- a/apps/dashboard/app/(app)/apis/[apiId]/keys/[keyAuthId]/[keyId]/settings/update-key-remaining.tsx +++ b/apps/dashboard/app/(app)/apis/[apiId]/keys/[keyAuthId]/[keyId]/settings/update-key-remaining.tsx @@ -51,6 +51,19 @@ const formSchema = z.object({ }) .positive() .optional(), + refillDay: z.coerce + .number({ + errorMap: (issue, { defaultError }) => ({ + message: + issue.code === "invalid_type" + ? "Refill day must be an integer between 1 and 31" + : defaultError, + }), + }) + .int() + .min(1) + .max(31) + .optional(), }) .optional(), }); @@ -61,6 +74,7 @@ type Props = { remaining: number | null; refillInterval: "daily" | "monthly" | null; refillAmount: number | null; + refillDay: number | null; }; }; @@ -78,6 +92,8 @@ export const UpdateKeyRemaining: React.FC = ({ apiKey }) => { refill: { interval: apiKey.refillInterval === null ? "none" : apiKey.refillInterval, amount: apiKey.refillAmount ? apiKey.refillAmount : undefined, + refillDay: + apiKey.refillInterval === "monthly" && apiKey.refillDay ? apiKey.refillDay : undefined, }, }, }); @@ -213,6 +229,27 @@ export const UpdateKeyRemaining: React.FC = ({ apiKey }) => { )} /> + ( + + Day of the month to refill uses + + + + Enter the day to refill monthly. + + + )} + /> diff --git a/apps/dashboard/app/(app)/apis/[apiId]/keys/[keyAuthId]/new/client.tsx b/apps/dashboard/app/(app)/apis/[apiId]/keys/[keyAuthId]/new/client.tsx index b63ffd734e..f940d81724 100644 --- a/apps/dashboard/app/(app)/apis/[apiId]/keys/[keyAuthId]/new/client.tsx +++ b/apps/dashboard/app/(app)/apis/[apiId]/keys/[keyAuthId]/new/client.tsx @@ -25,6 +25,7 @@ import { SelectTrigger, SelectValue, } from "@/components/ui/select"; + import { Separator } from "@/components/ui/separator"; import { Switch } from "@/components/ui/switch"; import { Textarea } from "@/components/ui/textarea"; @@ -90,11 +91,10 @@ const formSchema = z.object({ }), }) .int() - .positive({ message: "Please enter a positive number" }) - .optional(), + .positive({ message: "Please enter a positive number" }), refill: z .object({ - interval: z.enum(["none", "daily", "monthly"]).default("none"), + interval: z.enum(["daily", "monthly"]).default("monthly"), amount: z.coerce .number({ errorMap: (issue, { defaultError }) => ({ @@ -106,7 +106,19 @@ const formSchema = z.object({ }) .int() .min(1) - .positive() + .positive(), + refillDay: z.coerce + .number({ + errorMap: (issue, { defaultError }) => ({ + message: + issue.code === "invalid_type" + ? "Refill day must be an integer between 1 and 31" + : defaultError, + }), + }) + .int() + .min(1) + .max(31) .optional(), }) .optional(), @@ -151,7 +163,6 @@ type Props = { export const CreateKey: React.FC = ({ apiId, keyAuthId, defaultBytes, defaultPrefix }) => { const router = useRouter(); - const form = useForm>({ resolver: async (data, context, options) => { return zodResolver(formSchema)(data, context, options); @@ -196,6 +207,13 @@ export const CreateKey: React.FC = ({ apiId, keyAuthId, defaultBytes, def if (!values.ratelimitEnabled) { delete values.ratelimit; } + const refill = values.limit?.refill; + if (refill?.interval === "daily") { + refill?.refillDay === undefined; + } + if (refill?.interval === "monthly" && !refill.refillDay) { + refill.refillDay = 1; + } await key.mutateAsync({ keyAuthId, @@ -204,6 +222,7 @@ export const CreateKey: React.FC = ({ apiId, keyAuthId, defaultBytes, def expires: values.expires?.getTime() ?? undefined, ownerId: values.ownerId ?? undefined, remaining: values.limit?.remaining ?? undefined, + refill: refill, enabled: true, }); @@ -434,9 +453,7 @@ export const CreateKey: React.FC = ({ apiId, keyAuthId, defaultBytes, def )} /> - -
@@ -527,12 +544,10 @@ export const CreateKey: React.FC = ({ apiId, keyAuthId, defaultBytes, def ) : null} -
Limited Use - = ({ apiId, keyAuthId, defaultBytes, def Refill Rate - + + Interval key will be refilled. + )} /> ( @@ -637,6 +649,39 @@ export const CreateKey: React.FC = ({ apiId, keyAuthId, defaultBytes, def )} /> + + ( + + {/* Refill day or daily */} + +
+ +
+
+ + Enter the day to refill monthly. + + +
+ )} + /> How many requests may be performed in a given interval @@ -657,6 +702,7 @@ export const CreateKey: React.FC = ({ apiId, keyAuthId, defaultBytes, def ( @@ -816,9 +862,9 @@ export const CreateKey: React.FC = ({ apiId, keyAuthId, defaultBytes, def
diff --git a/apps/dashboard/app/(app)/apis/[apiId]/settings/page.tsx b/apps/dashboard/app/(app)/apis/[apiId]/settings/page.tsx index fc16fc94b8..0fb16523f2 100644 --- a/apps/dashboard/app/(app)/apis/[apiId]/settings/page.tsx +++ b/apps/dashboard/app/(app)/apis/[apiId]/settings/page.tsx @@ -34,6 +34,7 @@ export default async function SettingsPage(props: Props) { if (!workspace || workspace.tenantId !== tenantId) { return redirect("/new"); } + const api = workspace.apis.find((api) => api.id === props.params.apiId); if (!api) { return notFound(); diff --git a/apps/dashboard/app/(app)/apis/[apiId]/settings/update-ip-whitelist.tsx b/apps/dashboard/app/(app)/apis/[apiId]/settings/update-ip-whitelist.tsx index 06fe1b3f71..df8224e196 100644 --- a/apps/dashboard/app/(app)/apis/[apiId]/settings/update-ip-whitelist.tsx +++ b/apps/dashboard/app/(app)/apis/[apiId]/settings/update-ip-whitelist.tsx @@ -30,7 +30,7 @@ const formSchema = z.object({ type Props = { workspace: { - plan: Workspace["plan"]; + features: Workspace["features"]; }; api: { id: string; @@ -42,7 +42,7 @@ type Props = { export const UpdateIpWhitelist: React.FC = ({ api, workspace }) => { const router = useRouter(); - const isEnabled = workspace.plan === "enterprise"; + const isEnabled = workspace.features.ipWhitelist; const form = useForm>({ resolver: zodResolver(formSchema), @@ -79,7 +79,7 @@ export const UpdateIpWhitelist: React.FC = ({ api, workspace }) => { - {workspace.plan === "enterprise" ? ( + {isEnabled ? (
diff --git a/apps/dashboard/app/(app)/settings/general/update-workspace-name.tsx b/apps/dashboard/app/(app)/settings/general/update-workspace-name.tsx index b60ab1e45d..70a0be2673 100644 --- a/apps/dashboard/app/(app)/settings/general/update-workspace-name.tsx +++ b/apps/dashboard/app/(app)/settings/general/update-workspace-name.tsx @@ -13,9 +13,14 @@ import { useForm } from "react-hook-form"; import { z } from "zod"; export const dynamic = "force-dynamic"; + +const validCharactersRegex = /^[a-zA-Z0-9-_]+$/; + const formSchema = z.object({ workspaceId: z.string(), - name: z.string(), + name: z.string().min(3).regex(validCharactersRegex, { + message: "Workspace can only contain letters, numbers, dashes, and underscores", + }), }); type Props = { @@ -53,7 +58,7 @@ export const UpdateWorkspaceName: React.FC = ({ workspace }) => { async function onSubmit(values: z.infer) { await updateName.mutateAsync(values); } - + const isDisabled = form.formState.isLoading || !form.formState.isValid || updateName.isLoading; return (
@@ -84,7 +89,7 @@ export const UpdateWorkspaceName: React.FC = ({ workspace }) => { diff --git a/apps/dashboard/app/(app)/settings/root-keys/[keyId]/permissions/permissions.ts b/apps/dashboard/app/(app)/settings/root-keys/[keyId]/permissions/permissions.ts index 7f0e049bda..c0964b033a 100644 --- a/apps/dashboard/app/(app)/settings/root-keys/[keyId]/permissions/permissions.ts +++ b/apps/dashboard/app/(app)/settings/root-keys/[keyId]/permissions/permissions.ts @@ -1,12 +1,10 @@ import type { UnkeyPermission } from "@unkey/rbac"; - export type UnkeyPermissions = { [action: string]: { description: string; permission: UnkeyPermission; }; }; - export const workspacePermissions = { API: { create_api: { @@ -135,7 +133,6 @@ export const workspacePermissions = { }, }, } satisfies Record; - export function apiPermissions(apiId: string): { [category: string]: UnkeyPermissions } { return { API: { diff --git a/apps/dashboard/lib/trpc/ratelimitProcedure.ts b/apps/dashboard/lib/trpc/ratelimitProcedure.ts index a6fc5839a0..fb018fb4a8 100644 --- a/apps/dashboard/lib/trpc/ratelimitProcedure.ts +++ b/apps/dashboard/lib/trpc/ratelimitProcedure.ts @@ -9,7 +9,7 @@ export const ratelimit = env().UNKEY_ROOT_KEY create: new Ratelimit({ rootKey: env().UNKEY_ROOT_KEY ?? "", namespace: "trpc_create", - limit: 5, + limit: 25, duration: "3s", }), @@ -22,7 +22,7 @@ export const ratelimit = env().UNKEY_ROOT_KEY delete: new Ratelimit({ rootKey: env().UNKEY_ROOT_KEY ?? "", namespace: "trpc_delete", - limit: 5, + limit: 25, duration: "5s", }), } diff --git a/apps/dashboard/lib/trpc/routers/api/create.ts b/apps/dashboard/lib/trpc/routers/api/create.ts index e9ced2eba4..bc5ad78add 100644 --- a/apps/dashboard/lib/trpc/routers/api/create.ts +++ b/apps/dashboard/lib/trpc/routers/api/create.ts @@ -3,10 +3,11 @@ import { z } from "zod"; import { insertAuditLogs } from "@/lib/audit"; import { db, schema } from "@/lib/db"; -import { rateLimitedProcedure, ratelimit } from "@/lib/trpc/ratelimitProcedure"; import { newId } from "@unkey/id"; +import { auth, t } from "../../trpc"; -export const createApi = rateLimitedProcedure(ratelimit.create) +export const createApi = t.procedure + .use(auth) .input( z.object({ name: z diff --git a/apps/dashboard/lib/trpc/routers/api/delete.ts b/apps/dashboard/lib/trpc/routers/api/delete.ts index fc445f23b4..90aa9e329c 100644 --- a/apps/dashboard/lib/trpc/routers/api/delete.ts +++ b/apps/dashboard/lib/trpc/routers/api/delete.ts @@ -3,9 +3,9 @@ import { z } from "zod"; import { insertAuditLogs } from "@/lib/audit"; import { db, eq, schema } from "@/lib/db"; -import { rateLimitedProcedure, ratelimit } from "@/lib/trpc/ratelimitProcedure"; - -export const deleteApi = rateLimitedProcedure(ratelimit.delete) +import { auth, t } from "../../trpc"; +export const deleteApi = t.procedure + .use(auth) .input( z.object({ apiId: z.string(), diff --git a/apps/dashboard/lib/trpc/routers/api/setDefaultBytes.ts b/apps/dashboard/lib/trpc/routers/api/setDefaultBytes.ts index 4e45f064b2..4e6b491ee4 100644 --- a/apps/dashboard/lib/trpc/routers/api/setDefaultBytes.ts +++ b/apps/dashboard/lib/trpc/routers/api/setDefaultBytes.ts @@ -3,9 +3,10 @@ import { z } from "zod"; import { insertAuditLogs } from "@/lib/audit"; import { db, eq, schema } from "@/lib/db"; -import { rateLimitedProcedure, ratelimit } from "@/lib/trpc/ratelimitProcedure"; +import { auth, t } from "../../trpc"; -export const setDefaultApiBytes = rateLimitedProcedure(ratelimit.update) +export const setDefaultApiBytes = t.procedure + .use(auth) .input( z.object({ defaultBytes: z diff --git a/apps/dashboard/lib/trpc/routers/api/setDefaultPrefix.ts b/apps/dashboard/lib/trpc/routers/api/setDefaultPrefix.ts index 1d3ec5681c..b28406dc8e 100644 --- a/apps/dashboard/lib/trpc/routers/api/setDefaultPrefix.ts +++ b/apps/dashboard/lib/trpc/routers/api/setDefaultPrefix.ts @@ -3,9 +3,10 @@ import { z } from "zod"; import { insertAuditLogs } from "@/lib/audit"; import { db, eq, schema } from "@/lib/db"; -import { rateLimitedProcedure, ratelimit } from "@/lib/trpc/ratelimitProcedure"; +import { auth, t } from "../../trpc"; -export const setDefaultApiPrefix = rateLimitedProcedure(ratelimit.update) +export const setDefaultApiPrefix = t.procedure + .use(auth) .input( z.object({ defaultPrefix: z.string().max(8, "Prefix can be a maximum of 8 characters"), diff --git a/apps/dashboard/lib/trpc/routers/api/updateDeleteProtection.ts b/apps/dashboard/lib/trpc/routers/api/updateDeleteProtection.ts index c6cdf3fca9..aabb412529 100644 --- a/apps/dashboard/lib/trpc/routers/api/updateDeleteProtection.ts +++ b/apps/dashboard/lib/trpc/routers/api/updateDeleteProtection.ts @@ -3,9 +3,11 @@ import { z } from "zod"; import { insertAuditLogs } from "@/lib/audit"; import { db, eq, schema } from "@/lib/db"; -import { rateLimitedProcedure, ratelimit } from "@/lib/trpc/ratelimitProcedure"; -export const updateAPIDeleteProtection = rateLimitedProcedure(ratelimit.update) +import { auth, t } from "../../trpc"; + +export const updateAPIDeleteProtection = t.procedure + .use(auth) .input( z.object({ apiId: z.string(), diff --git a/apps/dashboard/lib/trpc/routers/api/updateIpWhitelist.ts b/apps/dashboard/lib/trpc/routers/api/updateIpWhitelist.ts index 67954331c0..f86ec639ca 100644 --- a/apps/dashboard/lib/trpc/routers/api/updateIpWhitelist.ts +++ b/apps/dashboard/lib/trpc/routers/api/updateIpWhitelist.ts @@ -3,9 +3,11 @@ import { z } from "zod"; import { insertAuditLogs } from "@/lib/audit"; import { db, eq, schema } from "@/lib/db"; -import { rateLimitedProcedure, ratelimit } from "@/lib/trpc/ratelimitProcedure"; -export const updateApiIpWhitelist = rateLimitedProcedure(ratelimit.update) +import { auth, t } from "../../trpc"; + +export const updateApiIpWhitelist = t.procedure + .use(auth) .input( z.object({ ipWhitelist: z @@ -43,7 +45,12 @@ export const updateApiIpWhitelist = rateLimitedProcedure(ratelimit.update) "We are unable to update the API whitelist. Please try again or contact support@unkey.dev", }); }); - if (!api || api.workspace.tenantId !== ctx.tenant.id) { + + if ( + !api || + api.workspace.tenantId !== ctx.tenant.id || + input.workspaceId !== api.workspace.id + ) { throw new TRPCError({ code: "NOT_FOUND", message: @@ -51,6 +58,14 @@ export const updateApiIpWhitelist = rateLimitedProcedure(ratelimit.update) }); } + if (!api.workspace.features.ipWhitelist) { + throw new TRPCError({ + code: "FORBIDDEN", + message: + "IP Whitelisting is only available for enterprise plans. Please contact support@unkey.dev.", + }); + } + const newIpWhitelist = input.ipWhitelist === null ? null : input.ipWhitelist.join(","); await db @@ -68,6 +83,7 @@ export const updateApiIpWhitelist = rateLimitedProcedure(ratelimit.update) "We are unable to update the API whitelist. Please try again or contact support@unkey.dev", }); }); + await insertAuditLogs(tx, { workspaceId: api.workspace.id, actor: { diff --git a/apps/dashboard/lib/trpc/routers/api/updateName.ts b/apps/dashboard/lib/trpc/routers/api/updateName.ts index b11a28a47e..ee3cf687d1 100644 --- a/apps/dashboard/lib/trpc/routers/api/updateName.ts +++ b/apps/dashboard/lib/trpc/routers/api/updateName.ts @@ -3,9 +3,11 @@ import { z } from "zod"; import { insertAuditLogs } from "@/lib/audit"; import { db, eq, schema } from "@/lib/db"; -import { rateLimitedProcedure, ratelimit } from "@/lib/trpc/ratelimitProcedure"; -export const updateApiName = rateLimitedProcedure(ratelimit.update) +import { auth, t } from "../../trpc"; + +export const updateApiName = t.procedure + .use(auth) .input( z.object({ name: z.string().min(3, "API names must contain at least 3 characters"), diff --git a/apps/dashboard/lib/trpc/routers/key/create.ts b/apps/dashboard/lib/trpc/routers/key/create.ts index 46f2b0e6fc..93fb4c659f 100644 --- a/apps/dashboard/lib/trpc/routers/key/create.ts +++ b/apps/dashboard/lib/trpc/routers/key/create.ts @@ -1,12 +1,13 @@ import { insertAuditLogs } from "@/lib/audit"; import { db, schema } from "@/lib/db"; -import { rateLimitedProcedure, ratelimit } from "@/lib/trpc/ratelimitProcedure"; import { TRPCError } from "@trpc/server"; import { newId } from "@unkey/id"; import { newKey } from "@unkey/keys"; import { z } from "zod"; +import { auth, t } from "../../trpc"; -export const createKey = rateLimitedProcedure(ratelimit.create) +export const createKey = t.procedure + .use(auth) .input( z.object({ prefix: z.string().optional(), @@ -19,6 +20,7 @@ export const createKey = rateLimitedProcedure(ratelimit.create) .object({ interval: z.enum(["daily", "monthly"]), amount: z.coerce.number().int().min(1), + refillDay: z.number().int().min(1).max(31).optional(), }) .optional(), expires: z.number().int().nullish(), // unix timestamp in milliseconds @@ -101,6 +103,7 @@ export const createKey = rateLimitedProcedure(ratelimit.create) ratelimitDuration: input.ratelimit?.duration, remaining: input.remaining, refillInterval: input.refill?.interval ?? null, + refillDay: input.refill?.refillDay ?? null, refillAmount: input.refill?.amount ?? null, lastRefillAt: input.refill?.interval ? new Date() : null, deletedAt: null, diff --git a/apps/dashboard/lib/trpc/routers/key/createRootKey.ts b/apps/dashboard/lib/trpc/routers/key/createRootKey.ts index c78fafd35c..702aa8f08d 100644 --- a/apps/dashboard/lib/trpc/routers/key/createRootKey.ts +++ b/apps/dashboard/lib/trpc/routers/key/createRootKey.ts @@ -1,17 +1,18 @@ import { db, eq, schema } from "@/lib/db"; import { env } from "@/lib/env"; import type { UnkeyAuditLog } from "@/lib/tinybird"; -import { rateLimitedProcedure, ratelimit } from "@/lib/trpc/ratelimitProcedure"; import { TRPCError } from "@trpc/server"; import { newId } from "@unkey/id"; import { newKey } from "@unkey/keys"; import { unkeyPermissionValidation } from "@unkey/rbac"; import { z } from "zod"; +import { auth, t } from "../../trpc"; import { insertAuditLogs } from "@/lib/audit"; import { upsertPermissions } from "../rbac"; -export const createRootKey = rateLimitedProcedure(ratelimit.create) +export const createRootKey = t.procedure + .use(auth) .input( z.object({ name: z.string().optional(), @@ -92,6 +93,7 @@ export const createRootKey = rateLimitedProcedure(ratelimit.create) remaining: null, refillInterval: null, refillAmount: null, + refillDay: null, lastRefillAt: null, deletedAt: null, enabled: true, diff --git a/apps/dashboard/lib/trpc/routers/key/delete.ts b/apps/dashboard/lib/trpc/routers/key/delete.ts index 8624762c77..94f36bcb63 100644 --- a/apps/dashboard/lib/trpc/routers/key/delete.ts +++ b/apps/dashboard/lib/trpc/routers/key/delete.ts @@ -1,10 +1,11 @@ import { insertAuditLogs } from "@/lib/audit"; import { and, db, eq, inArray, schema } from "@/lib/db"; -import { rateLimitedProcedure, ratelimit } from "@/lib/trpc/ratelimitProcedure"; import { TRPCError } from "@trpc/server"; import { z } from "zod"; +import { auth, t } from "../../trpc"; -export const deleteKeys = rateLimitedProcedure(ratelimit.delete) +export const deleteKeys = t.procedure + .use(auth) .input( z.object({ keyIds: z.array(z.string()), diff --git a/apps/dashboard/lib/trpc/routers/key/deleteRootKey.ts b/apps/dashboard/lib/trpc/routers/key/deleteRootKey.ts index 980a46d80f..46703a92cd 100644 --- a/apps/dashboard/lib/trpc/routers/key/deleteRootKey.ts +++ b/apps/dashboard/lib/trpc/routers/key/deleteRootKey.ts @@ -1,11 +1,11 @@ import { insertAuditLogs } from "@/lib/audit"; import { db, inArray, schema } from "@/lib/db"; import { env } from "@/lib/env"; -import { rateLimitedProcedure, ratelimit } from "@/lib/trpc/ratelimitProcedure"; import { TRPCError } from "@trpc/server"; import { z } from "zod"; - -export const deleteRootKeys = rateLimitedProcedure(ratelimit.delete) +import { auth, t } from "../../trpc"; +export const deleteRootKeys = t.procedure + .use(auth) .input( z.object({ keyIds: z.array(z.string()), diff --git a/apps/dashboard/lib/trpc/routers/key/updateEnabled.ts b/apps/dashboard/lib/trpc/routers/key/updateEnabled.ts index bc5e4d5322..be05e3ed8a 100644 --- a/apps/dashboard/lib/trpc/routers/key/updateEnabled.ts +++ b/apps/dashboard/lib/trpc/routers/key/updateEnabled.ts @@ -1,10 +1,10 @@ import { insertAuditLogs } from "@/lib/audit"; import { db, eq, schema } from "@/lib/db"; -import { rateLimitedProcedure, ratelimit } from "@/lib/trpc/ratelimitProcedure"; import { TRPCError } from "@trpc/server"; import { z } from "zod"; - -export const updateKeyEnabled = rateLimitedProcedure(ratelimit.update) +import { auth, t } from "../../trpc"; +export const updateKeyEnabled = t.procedure + .use(auth) .input( z.object({ keyId: z.string(), diff --git a/apps/dashboard/lib/trpc/routers/key/updateExpiration.ts b/apps/dashboard/lib/trpc/routers/key/updateExpiration.ts index c40cd8d380..fff50f21b6 100644 --- a/apps/dashboard/lib/trpc/routers/key/updateExpiration.ts +++ b/apps/dashboard/lib/trpc/routers/key/updateExpiration.ts @@ -1,10 +1,10 @@ import { insertAuditLogs } from "@/lib/audit"; import { db, eq, schema } from "@/lib/db"; -import { rateLimitedProcedure, ratelimit } from "@/lib/trpc/ratelimitProcedure"; import { TRPCError } from "@trpc/server"; import { z } from "zod"; - -export const updateKeyExpiration = rateLimitedProcedure(ratelimit.update) +import { auth, t } from "../../trpc"; +export const updateKeyExpiration = t.procedure + .use(auth) .input( z.object({ keyId: z.string(), diff --git a/apps/dashboard/lib/trpc/routers/key/updateMetadata.ts b/apps/dashboard/lib/trpc/routers/key/updateMetadata.ts index 28fe176d3e..6694b56b9c 100644 --- a/apps/dashboard/lib/trpc/routers/key/updateMetadata.ts +++ b/apps/dashboard/lib/trpc/routers/key/updateMetadata.ts @@ -1,10 +1,10 @@ import { insertAuditLogs } from "@/lib/audit"; import { db, eq, schema } from "@/lib/db"; -import { rateLimitedProcedure, ratelimit } from "@/lib/trpc/ratelimitProcedure"; import { TRPCError } from "@trpc/server"; import { z } from "zod"; - -export const updateKeyMetadata = rateLimitedProcedure(ratelimit.update) +import { auth, t } from "../../trpc"; +export const updateKeyMetadata = t.procedure + .use(auth) .input( z.object({ keyId: z.string(), diff --git a/apps/dashboard/lib/trpc/routers/key/updateName.ts b/apps/dashboard/lib/trpc/routers/key/updateName.ts index a072e5cdc5..539b7384f6 100644 --- a/apps/dashboard/lib/trpc/routers/key/updateName.ts +++ b/apps/dashboard/lib/trpc/routers/key/updateName.ts @@ -1,11 +1,9 @@ import { insertAuditLogs } from "@/lib/audit"; import { db, eq, schema } from "@/lib/db"; -import { rateLimitedProcedure, ratelimit } from "@/lib/trpc/ratelimitProcedure"; import { TRPCError } from "@trpc/server"; import { z } from "zod"; -import { auth } from "../../trpc"; - -export const updateKeyName = rateLimitedProcedure(ratelimit.update) +import { auth, t } from "../../trpc"; +export const updateKeyName = t.procedure .use(auth) .input( z.object({ diff --git a/apps/dashboard/lib/trpc/routers/key/updateOwnerId.ts b/apps/dashboard/lib/trpc/routers/key/updateOwnerId.ts index 4b32a0a1d5..60f7e8ac3c 100644 --- a/apps/dashboard/lib/trpc/routers/key/updateOwnerId.ts +++ b/apps/dashboard/lib/trpc/routers/key/updateOwnerId.ts @@ -1,10 +1,10 @@ import { insertAuditLogs } from "@/lib/audit"; import { db, eq, schema } from "@/lib/db"; -import { rateLimitedProcedure, ratelimit } from "@/lib/trpc/ratelimitProcedure"; import { TRPCError } from "@trpc/server"; import { z } from "zod"; - -export const updateKeyOwnerId = rateLimitedProcedure(ratelimit.update) +import { auth, t } from "../../trpc"; +export const updateKeyOwnerId = t.procedure + .use(auth) .input( z.object({ keyId: z.string(), diff --git a/apps/dashboard/lib/trpc/routers/key/updateRatelimit.ts b/apps/dashboard/lib/trpc/routers/key/updateRatelimit.ts index 7d64654ea6..8316b8d503 100644 --- a/apps/dashboard/lib/trpc/routers/key/updateRatelimit.ts +++ b/apps/dashboard/lib/trpc/routers/key/updateRatelimit.ts @@ -1,10 +1,10 @@ import { insertAuditLogs } from "@/lib/audit"; import { db, eq, schema } from "@/lib/db"; -import { rateLimitedProcedure, ratelimit } from "@/lib/trpc/ratelimitProcedure"; import { TRPCError } from "@trpc/server"; import { z } from "zod"; - -export const updateKeyRatelimit = rateLimitedProcedure(ratelimit.update) +import { auth, t } from "../../trpc"; +export const updateKeyRatelimit = t.procedure + .use(auth) .input( z.object({ keyId: z.string(), diff --git a/apps/dashboard/lib/trpc/routers/key/updateRemaining.ts b/apps/dashboard/lib/trpc/routers/key/updateRemaining.ts index 4e04452366..835ece954c 100644 --- a/apps/dashboard/lib/trpc/routers/key/updateRemaining.ts +++ b/apps/dashboard/lib/trpc/routers/key/updateRemaining.ts @@ -1,10 +1,10 @@ import { insertAuditLogs } from "@/lib/audit"; import { db, eq, schema } from "@/lib/db"; -import { rateLimitedProcedure, ratelimit } from "@/lib/trpc/ratelimitProcedure"; import { TRPCError } from "@trpc/server"; import { z } from "zod"; - -export const updateKeyRemaining = rateLimitedProcedure(ratelimit.update) +import { auth, t } from "../../trpc"; +export const updateKeyRemaining = t.procedure + .use(auth) .input( z.object({ keyId: z.string(), @@ -14,6 +14,7 @@ export const updateKeyRemaining = rateLimitedProcedure(ratelimit.update) .object({ interval: z.enum(["daily", "monthly", "none"]), amount: z.number().int().min(1).optional(), + refillDay: z.number().int().min(1).max(31).optional(), }) .optional(), }), @@ -36,7 +37,7 @@ export const updateKeyRemaining = rateLimitedProcedure(ratelimit.update) workspace: true, }, }); - + const isMonthlyInterval = input.refill?.interval === "monthly"; if (!key || key.workspace.tenantId !== ctx.tenant.id) { throw new TRPCError({ message: @@ -52,6 +53,7 @@ export const updateKeyRemaining = rateLimitedProcedure(ratelimit.update) input.refill?.interval === "none" || input.refill?.interval === undefined ? null : input.refill?.interval, + refillDay: isMonthlyInterval ? input.refill?.refillDay : null, refillAmount: input.refill?.amount ?? null, lastRefillAt: input.refill?.interval ? new Date() : null, }) diff --git a/apps/dashboard/lib/trpc/routers/key/updateRootKeyName.ts b/apps/dashboard/lib/trpc/routers/key/updateRootKeyName.ts index c78586f7c5..c67ab39789 100644 --- a/apps/dashboard/lib/trpc/routers/key/updateRootKeyName.ts +++ b/apps/dashboard/lib/trpc/routers/key/updateRootKeyName.ts @@ -3,7 +3,6 @@ import { db, eq, schema } from "@/lib/db"; import { TRPCError } from "@trpc/server"; import { z } from "zod"; import { auth, t } from "../../trpc"; - export const updateRootKeyName = t.procedure .use(auth) .input( diff --git a/apps/dashboard/lib/trpc/routers/llmGateway/create.ts b/apps/dashboard/lib/trpc/routers/llmGateway/create.ts index a50a08562c..f31500999b 100644 --- a/apps/dashboard/lib/trpc/routers/llmGateway/create.ts +++ b/apps/dashboard/lib/trpc/routers/llmGateway/create.ts @@ -1,12 +1,12 @@ import { insertAuditLogs } from "@/lib/audit"; import { db, schema } from "@/lib/db"; -import { rateLimitedProcedure, ratelimit } from "@/lib/trpc/ratelimitProcedure"; import { DatabaseError } from "@planetscale/database"; import { TRPCError } from "@trpc/server"; import { newId } from "@unkey/id"; import { z } from "zod"; - -export const createLlmGateway = rateLimitedProcedure(ratelimit.create) +import { auth, t } from "../../trpc"; +export const createLlmGateway = t.procedure + .use(auth) .input( z.object({ subdomain: z.string().min(1).max(50), diff --git a/apps/dashboard/lib/trpc/routers/llmGateway/delete.ts b/apps/dashboard/lib/trpc/routers/llmGateway/delete.ts index a031dbb4ff..cfe2220cd9 100644 --- a/apps/dashboard/lib/trpc/routers/llmGateway/delete.ts +++ b/apps/dashboard/lib/trpc/routers/llmGateway/delete.ts @@ -3,9 +3,9 @@ import { z } from "zod"; import { insertAuditLogs } from "@/lib/audit"; import { db, eq, schema } from "@/lib/db"; -import { rateLimitedProcedure, ratelimit } from "@/lib/trpc/ratelimitProcedure"; - -export const deleteLlmGateway = rateLimitedProcedure(ratelimit.delete) +import { auth, t } from "../../trpc"; +export const deleteLlmGateway = t.procedure + .use(auth) .input(z.object({ gatewayId: z.string() })) .mutation(async ({ ctx, input }) => { const llmGateway = await db.query.llmGateways diff --git a/apps/dashboard/lib/trpc/routers/ratelimit/createNamespace.ts b/apps/dashboard/lib/trpc/routers/ratelimit/createNamespace.ts index b8f03e5369..181adbb14e 100644 --- a/apps/dashboard/lib/trpc/routers/ratelimit/createNamespace.ts +++ b/apps/dashboard/lib/trpc/routers/ratelimit/createNamespace.ts @@ -3,11 +3,11 @@ import { z } from "zod"; import { insertAuditLogs } from "@/lib/audit"; import { db, schema } from "@/lib/db"; -import { rateLimitedProcedure, ratelimit } from "@/lib/trpc/ratelimitProcedure"; import { DatabaseError } from "@planetscale/database"; import { newId } from "@unkey/id"; - -export const createNamespace = rateLimitedProcedure(ratelimit.create) +import { auth, t } from "../../trpc"; +export const createNamespace = t.procedure + .use(auth) .input( z.object({ name: z.string().min(1).max(50), diff --git a/apps/dashboard/lib/trpc/routers/ratelimit/createOverride.ts b/apps/dashboard/lib/trpc/routers/ratelimit/createOverride.ts index 35332ad322..e78415fd55 100644 --- a/apps/dashboard/lib/trpc/routers/ratelimit/createOverride.ts +++ b/apps/dashboard/lib/trpc/routers/ratelimit/createOverride.ts @@ -3,10 +3,10 @@ import { z } from "zod"; import { insertAuditLogs } from "@/lib/audit"; import { and, db, eq, isNull, schema, sql } from "@/lib/db"; -import { rateLimitedProcedure, ratelimit } from "@/lib/trpc/ratelimitProcedure"; import { newId } from "@unkey/id"; - -export const createOverride = rateLimitedProcedure(ratelimit.create) +import { auth, t } from "../../trpc"; +export const createOverride = t.procedure + .use(auth) .input( z.object({ namespaceId: z.string(), diff --git a/apps/dashboard/lib/trpc/routers/ratelimit/deleteNamespace.ts b/apps/dashboard/lib/trpc/routers/ratelimit/deleteNamespace.ts index 352dd4bd77..eea6566bd0 100644 --- a/apps/dashboard/lib/trpc/routers/ratelimit/deleteNamespace.ts +++ b/apps/dashboard/lib/trpc/routers/ratelimit/deleteNamespace.ts @@ -3,9 +3,9 @@ import { z } from "zod"; import { insertAuditLogs } from "@/lib/audit"; import { db, eq, schema } from "@/lib/db"; -import { rateLimitedProcedure, ratelimit } from "@/lib/trpc/ratelimitProcedure"; - -export const deleteNamespace = rateLimitedProcedure(ratelimit.delete) +import { auth, t } from "../../trpc"; +export const deleteNamespace = t.procedure + .use(auth) .input( z.object({ namespaceId: z.string(), diff --git a/apps/dashboard/lib/trpc/routers/ratelimit/deleteOverride.ts b/apps/dashboard/lib/trpc/routers/ratelimit/deleteOverride.ts index 1cbd3bb713..c190f830cd 100644 --- a/apps/dashboard/lib/trpc/routers/ratelimit/deleteOverride.ts +++ b/apps/dashboard/lib/trpc/routers/ratelimit/deleteOverride.ts @@ -3,9 +3,9 @@ import { z } from "zod"; import { insertAuditLogs } from "@/lib/audit"; import { db, eq, schema } from "@/lib/db"; -import { rateLimitedProcedure, ratelimit } from "@/lib/trpc/ratelimitProcedure"; - -export const deleteOverride = rateLimitedProcedure(ratelimit.create) +import { auth, t } from "../../trpc"; +export const deleteOverride = t.procedure + .use(auth) .input( z.object({ id: z.string(), diff --git a/apps/dashboard/lib/trpc/routers/ratelimit/updateNamespaceName.ts b/apps/dashboard/lib/trpc/routers/ratelimit/updateNamespaceName.ts index 91ea8e5242..2251988124 100644 --- a/apps/dashboard/lib/trpc/routers/ratelimit/updateNamespaceName.ts +++ b/apps/dashboard/lib/trpc/routers/ratelimit/updateNamespaceName.ts @@ -3,9 +3,9 @@ import { z } from "zod"; import { insertAuditLogs } from "@/lib/audit"; import { db, eq, schema } from "@/lib/db"; -import { rateLimitedProcedure, ratelimit } from "@/lib/trpc/ratelimitProcedure"; - -export const updateNamespaceName = rateLimitedProcedure(ratelimit.update) +import { auth, t } from "../../trpc"; +export const updateNamespaceName = t.procedure + .use(auth) .input( z.object({ name: z.string().min(3, "namespace names must contain at least 3 characters"), diff --git a/apps/dashboard/lib/trpc/routers/ratelimit/updateOverride.ts b/apps/dashboard/lib/trpc/routers/ratelimit/updateOverride.ts index 6971ffdc3b..f570ca407d 100644 --- a/apps/dashboard/lib/trpc/routers/ratelimit/updateOverride.ts +++ b/apps/dashboard/lib/trpc/routers/ratelimit/updateOverride.ts @@ -3,9 +3,9 @@ import { z } from "zod"; import { insertAuditLogs } from "@/lib/audit"; import { db, eq, schema } from "@/lib/db"; -import { rateLimitedProcedure, ratelimit } from "@/lib/trpc/ratelimitProcedure"; - -export const updateOverride = rateLimitedProcedure(ratelimit.update) +import { auth, t } from "../../trpc"; +export const updateOverride = t.procedure + .use(auth) .input( z.object({ id: z.string(), diff --git a/apps/dashboard/lib/trpc/routers/rbac/addPermissionToRootKey.ts b/apps/dashboard/lib/trpc/routers/rbac/addPermissionToRootKey.ts index 64749a0c94..765a59c0fa 100644 --- a/apps/dashboard/lib/trpc/routers/rbac/addPermissionToRootKey.ts +++ b/apps/dashboard/lib/trpc/routers/rbac/addPermissionToRootKey.ts @@ -1,12 +1,12 @@ import { insertAuditLogs } from "@/lib/audit"; import { db, schema } from "@/lib/db"; -import { rateLimitedProcedure, ratelimit } from "@/lib/trpc/ratelimitProcedure"; import { TRPCError } from "@trpc/server"; import { unkeyPermissionValidation } from "@unkey/rbac"; import { z } from "zod"; +import { auth, t } from "../../trpc"; import { upsertPermissions } from "../rbac"; - -export const addPermissionToRootKey = rateLimitedProcedure(ratelimit.create) +export const addPermissionToRootKey = t.procedure + .use(auth) .input( z.object({ rootKeyId: z.string(), diff --git a/apps/dashboard/lib/trpc/routers/rbac/connectPermissionToRole.ts b/apps/dashboard/lib/trpc/routers/rbac/connectPermissionToRole.ts index 10897edaa4..0f863ff81f 100644 --- a/apps/dashboard/lib/trpc/routers/rbac/connectPermissionToRole.ts +++ b/apps/dashboard/lib/trpc/routers/rbac/connectPermissionToRole.ts @@ -1,10 +1,10 @@ import { insertAuditLogs } from "@/lib/audit"; import { db, schema } from "@/lib/db"; -import { rateLimitedProcedure, ratelimit } from "@/lib/trpc/ratelimitProcedure"; import { TRPCError } from "@trpc/server"; import { z } from "zod"; - -export const connectPermissionToRole = rateLimitedProcedure(ratelimit.update) +import { auth, t } from "../../trpc"; +export const connectPermissionToRole = t.procedure + .use(auth) .input( z.object({ roleId: z.string(), diff --git a/apps/dashboard/lib/trpc/routers/rbac/connectRoleToKey.ts b/apps/dashboard/lib/trpc/routers/rbac/connectRoleToKey.ts index 96ae10d5c9..92a58b9663 100644 --- a/apps/dashboard/lib/trpc/routers/rbac/connectRoleToKey.ts +++ b/apps/dashboard/lib/trpc/routers/rbac/connectRoleToKey.ts @@ -1,10 +1,10 @@ import { insertAuditLogs } from "@/lib/audit"; import { db, schema } from "@/lib/db"; -import { rateLimitedProcedure, ratelimit } from "@/lib/trpc/ratelimitProcedure"; import { TRPCError } from "@trpc/server"; import { z } from "zod"; - -export const connectRoleToKey = rateLimitedProcedure(ratelimit.update) +import { auth, t } from "../../trpc"; +export const connectRoleToKey = t.procedure + .use(auth) .input( z.object({ roleId: z.string(), diff --git a/apps/dashboard/lib/trpc/routers/rbac/createPermission.ts b/apps/dashboard/lib/trpc/routers/rbac/createPermission.ts index 86095b75f2..cfcf486fd4 100644 --- a/apps/dashboard/lib/trpc/routers/rbac/createPermission.ts +++ b/apps/dashboard/lib/trpc/routers/rbac/createPermission.ts @@ -1,10 +1,9 @@ import { insertAuditLogs } from "@/lib/audit"; import { db, schema } from "@/lib/db"; -import { rateLimitedProcedure, ratelimit } from "@/lib/trpc/ratelimitProcedure"; import { TRPCError } from "@trpc/server"; import { newId } from "@unkey/id"; import { z } from "zod"; - +import { auth, t } from "../../trpc"; const nameSchema = z .string() .min(3) @@ -13,7 +12,8 @@ const nameSchema = z "Must be at least 3 characters long and only contain alphanumeric, colons, periods, dashes and underscores", }); -export const createPermission = rateLimitedProcedure(ratelimit.create) +export const createPermission = t.procedure + .use(auth) .input( z.object({ name: nameSchema, diff --git a/apps/dashboard/lib/trpc/routers/rbac/createRole.ts b/apps/dashboard/lib/trpc/routers/rbac/createRole.ts index 1ece2a4562..cba903ee82 100644 --- a/apps/dashboard/lib/trpc/routers/rbac/createRole.ts +++ b/apps/dashboard/lib/trpc/routers/rbac/createRole.ts @@ -1,10 +1,9 @@ import { insertAuditLogs } from "@/lib/audit"; import { db, schema } from "@/lib/db"; -import { rateLimitedProcedure, ratelimit } from "@/lib/trpc/ratelimitProcedure"; import { TRPCError } from "@trpc/server"; import { newId } from "@unkey/id"; import { z } from "zod"; - +import { auth, t } from "../../trpc"; const nameSchema = z .string() .min(3) @@ -13,7 +12,8 @@ const nameSchema = z "Must be at least 3 characters long and only contain alphanumeric, colons, periods, dashes and underscores", }); -export const createRole = rateLimitedProcedure(ratelimit.create) +export const createRole = t.procedure + .use(auth) .input( z.object({ name: nameSchema, diff --git a/apps/dashboard/lib/trpc/routers/rbac/deletePermission.ts b/apps/dashboard/lib/trpc/routers/rbac/deletePermission.ts index 0558bac556..c978716fa0 100644 --- a/apps/dashboard/lib/trpc/routers/rbac/deletePermission.ts +++ b/apps/dashboard/lib/trpc/routers/rbac/deletePermission.ts @@ -1,10 +1,10 @@ import { insertAuditLogs } from "@/lib/audit"; import { and, db, eq, schema } from "@/lib/db"; -import { rateLimitedProcedure, ratelimit } from "@/lib/trpc/ratelimitProcedure"; import { TRPCError } from "@trpc/server"; import { z } from "zod"; - -export const deletePermission = rateLimitedProcedure(ratelimit.delete) +import { auth, t } from "../../trpc"; +export const deletePermission = t.procedure + .use(auth) .input( z.object({ permissionId: z.string(), diff --git a/apps/dashboard/lib/trpc/routers/rbac/deleteRole.ts b/apps/dashboard/lib/trpc/routers/rbac/deleteRole.ts index a0eb9d27c4..b59496b7a1 100644 --- a/apps/dashboard/lib/trpc/routers/rbac/deleteRole.ts +++ b/apps/dashboard/lib/trpc/routers/rbac/deleteRole.ts @@ -1,10 +1,10 @@ import { insertAuditLogs } from "@/lib/audit"; import { and, db, eq, schema } from "@/lib/db"; -import { rateLimitedProcedure, ratelimit } from "@/lib/trpc/ratelimitProcedure"; import { TRPCError } from "@trpc/server"; import { z } from "zod"; - -export const deleteRole = rateLimitedProcedure(ratelimit.delete) +import { auth, t } from "../../trpc"; +export const deleteRole = t.procedure + .use(auth) .input( z.object({ roleId: z.string(), diff --git a/apps/dashboard/lib/trpc/routers/rbac/disconnectPermissionFromRole.ts b/apps/dashboard/lib/trpc/routers/rbac/disconnectPermissionFromRole.ts index 97fd27f57b..a6023c03e9 100644 --- a/apps/dashboard/lib/trpc/routers/rbac/disconnectPermissionFromRole.ts +++ b/apps/dashboard/lib/trpc/routers/rbac/disconnectPermissionFromRole.ts @@ -1,10 +1,10 @@ import { insertAuditLogs } from "@/lib/audit"; import { and, db, eq, schema } from "@/lib/db"; -import { rateLimitedProcedure, ratelimit } from "@/lib/trpc/ratelimitProcedure"; import { TRPCError } from "@trpc/server"; import { z } from "zod"; - -export const disconnectPermissionFromRole = rateLimitedProcedure(ratelimit.update) +import { auth, t } from "../../trpc"; +export const disconnectPermissionFromRole = t.procedure + .use(auth) .input( z.object({ roleId: z.string(), diff --git a/apps/dashboard/lib/trpc/routers/rbac/disconnectRoleFromKey.ts b/apps/dashboard/lib/trpc/routers/rbac/disconnectRoleFromKey.ts index bfa719b850..3610cac54f 100644 --- a/apps/dashboard/lib/trpc/routers/rbac/disconnectRoleFromKey.ts +++ b/apps/dashboard/lib/trpc/routers/rbac/disconnectRoleFromKey.ts @@ -1,10 +1,10 @@ import { insertAuditLogs } from "@/lib/audit"; import { and, db, eq, schema } from "@/lib/db"; -import { rateLimitedProcedure, ratelimit } from "@/lib/trpc/ratelimitProcedure"; import { TRPCError } from "@trpc/server"; import { z } from "zod"; - -export const disconnectRoleFromKey = rateLimitedProcedure(ratelimit.update) +import { auth, t } from "../../trpc"; +export const disconnectRoleFromKey = t.procedure + .use(auth) .input( z.object({ roleId: z.string(), diff --git a/apps/dashboard/lib/trpc/routers/rbac/removePermissionFromRootKey.ts b/apps/dashboard/lib/trpc/routers/rbac/removePermissionFromRootKey.ts index 51ac33d6ce..32aff38da2 100644 --- a/apps/dashboard/lib/trpc/routers/rbac/removePermissionFromRootKey.ts +++ b/apps/dashboard/lib/trpc/routers/rbac/removePermissionFromRootKey.ts @@ -1,10 +1,10 @@ import { insertAuditLogs } from "@/lib/audit"; import { and, db, eq, schema } from "@/lib/db"; -import { rateLimitedProcedure, ratelimit } from "@/lib/trpc/ratelimitProcedure"; import { TRPCError } from "@trpc/server"; import { z } from "zod"; - -export const removePermissionFromRootKey = rateLimitedProcedure(ratelimit.update) +import { auth, t } from "../../trpc"; +export const removePermissionFromRootKey = t.procedure + .use(auth) .input( z.object({ rootKeyId: z.string(), diff --git a/apps/dashboard/lib/trpc/routers/rbac/updatePermission.ts b/apps/dashboard/lib/trpc/routers/rbac/updatePermission.ts index 833bdfc643..9e77e15f0e 100644 --- a/apps/dashboard/lib/trpc/routers/rbac/updatePermission.ts +++ b/apps/dashboard/lib/trpc/routers/rbac/updatePermission.ts @@ -1,9 +1,8 @@ import { insertAuditLogs } from "@/lib/audit"; import { db, eq, schema } from "@/lib/db"; -import { rateLimitedProcedure, ratelimit } from "@/lib/trpc/ratelimitProcedure"; import { TRPCError } from "@trpc/server"; import { z } from "zod"; - +import { auth, t } from "../../trpc"; const nameSchema = z .string() .min(3) @@ -12,7 +11,8 @@ const nameSchema = z "Must be at least 3 characters long and only contain alphanumeric, colons, periods, dashes and underscores", }); -export const updatePermission = rateLimitedProcedure(ratelimit.update) +export const updatePermission = t.procedure + .use(auth) .input( z.object({ id: z.string(), diff --git a/apps/dashboard/lib/trpc/routers/rbac/updateRole.ts b/apps/dashboard/lib/trpc/routers/rbac/updateRole.ts index 1f1af9b63b..0843d7f406 100644 --- a/apps/dashboard/lib/trpc/routers/rbac/updateRole.ts +++ b/apps/dashboard/lib/trpc/routers/rbac/updateRole.ts @@ -1,9 +1,8 @@ import { insertAuditLogs } from "@/lib/audit"; import { db, eq, schema } from "@/lib/db"; -import { rateLimitedProcedure, ratelimit } from "@/lib/trpc/ratelimitProcedure"; import { TRPCError } from "@trpc/server"; import { z } from "zod"; - +import { auth, t } from "../../trpc"; const nameSchema = z .string() .min(3) @@ -12,7 +11,8 @@ const nameSchema = z "Must be at least 3 characters long and only contain alphanumeric, colons, periods, dashes and underscores", }); -export const updateRole = rateLimitedProcedure(ratelimit.update) +export const updateRole = t.procedure + .use(auth) .input( z.object({ id: z.string(), diff --git a/apps/dashboard/lib/trpc/routers/workspace/changeName.ts b/apps/dashboard/lib/trpc/routers/workspace/changeName.ts index 78cbc4bdb9..67e1ad6206 100644 --- a/apps/dashboard/lib/trpc/routers/workspace/changeName.ts +++ b/apps/dashboard/lib/trpc/routers/workspace/changeName.ts @@ -1,11 +1,11 @@ import { insertAuditLogs } from "@/lib/audit"; import { db, eq, schema } from "@/lib/db"; -import { rateLimitedProcedure, ratelimit } from "@/lib/trpc/ratelimitProcedure"; import { clerkClient } from "@clerk/nextjs"; import { TRPCError } from "@trpc/server"; import { z } from "zod"; - -export const changeWorkspaceName = rateLimitedProcedure(ratelimit.update) +import { auth, t } from "../../trpc"; +export const changeWorkspaceName = t.procedure + .use(auth) .input( z.object({ name: z.string().min(3, "workspace names must contain at least 3 characters"), diff --git a/apps/dashboard/lib/trpc/routers/workspace/changePlan.ts b/apps/dashboard/lib/trpc/routers/workspace/changePlan.ts index 253c7f4f18..bf8af62d2f 100644 --- a/apps/dashboard/lib/trpc/routers/workspace/changePlan.ts +++ b/apps/dashboard/lib/trpc/routers/workspace/changePlan.ts @@ -1,13 +1,13 @@ import { insertAuditLogs } from "@/lib/audit"; import { db, eq, schema } from "@/lib/db"; import { stripeEnv } from "@/lib/env"; -import { rateLimitedProcedure, ratelimit } from "@/lib/trpc/ratelimitProcedure"; import { TRPCError } from "@trpc/server"; import { defaultProSubscriptions } from "@unkey/billing"; import Stripe from "stripe"; import { z } from "zod"; - -export const changeWorkspacePlan = rateLimitedProcedure(ratelimit.update) +import { auth, t } from "../../trpc"; +export const changeWorkspacePlan = t.procedure + .use(auth) .input( z.object({ workspaceId: z.string(), diff --git a/apps/dashboard/lib/trpc/routers/workspace/create.ts b/apps/dashboard/lib/trpc/routers/workspace/create.ts index b8a3f6e1c5..cd158b026b 100644 --- a/apps/dashboard/lib/trpc/routers/workspace/create.ts +++ b/apps/dashboard/lib/trpc/routers/workspace/create.ts @@ -1,13 +1,13 @@ import { insertAuditLogs } from "@/lib/audit"; import { type Workspace, db, schema } from "@/lib/db"; -import { rateLimitedProcedure, ratelimit } from "@/lib/trpc/ratelimitProcedure"; import { clerkClient } from "@clerk/nextjs"; import { TRPCError } from "@trpc/server"; import { defaultProSubscriptions } from "@unkey/billing"; import { newId } from "@unkey/id"; import { z } from "zod"; - -export const createWorkspace = rateLimitedProcedure(ratelimit.create) +import { auth, t } from "../../trpc"; +export const createWorkspace = t.procedure + .use(auth) .input( z.object({ name: z.string().min(1).max(50), diff --git a/apps/dashboard/lib/trpc/routers/workspace/optIntoBeta.ts b/apps/dashboard/lib/trpc/routers/workspace/optIntoBeta.ts index be49661d08..3f3e52b173 100644 --- a/apps/dashboard/lib/trpc/routers/workspace/optIntoBeta.ts +++ b/apps/dashboard/lib/trpc/routers/workspace/optIntoBeta.ts @@ -1,10 +1,10 @@ import { insertAuditLogs } from "@/lib/audit"; import { db, eq, schema } from "@/lib/db"; -import { rateLimitedProcedure, ratelimit } from "@/lib/trpc/ratelimitProcedure"; import { TRPCError } from "@trpc/server"; import { z } from "zod"; - -export const optWorkspaceIntoBeta = rateLimitedProcedure(ratelimit.update) +import { auth, t } from "../../trpc"; +export const optWorkspaceIntoBeta = t.procedure + .use(auth) .input( z.object({ feature: z.enum(["rbac", "ratelimit", "identities"]), diff --git a/apps/dashboard/lib/zod-helper.ts b/apps/dashboard/lib/zod-helper.ts index 0d08868d4a..7970b612ec 100644 --- a/apps/dashboard/lib/zod-helper.ts +++ b/apps/dashboard/lib/zod-helper.ts @@ -44,6 +44,19 @@ export const formSchema = z.object({ .int() .min(1) .positive(), + refillDay: z.coerce + .number({ + errorMap: (issue, { defaultError }) => ({ + message: + issue.code === "invalid_type" + ? "Refill day must be an integer between 1 and 31" + : defaultError, + }), + }) + .int() + .min(1) + .max(31) + .optional(), }) .optional(), }) diff --git a/apps/docs/introduction.mdx b/apps/docs/introduction.mdx index 7455de82cf..5280f1f1d3 100644 --- a/apps/docs/introduction.mdx +++ b/apps/docs/introduction.mdx @@ -4,7 +4,7 @@ description: API management redefined mode: "wide" --- -Unkey provides an easy to use API management platform, including API key management, standalone ratelimting and LLM caching. +Unkey provides an easy to use API management platform, including API key management, standalone ratelimiting and LLM caching. ## New to Unkey? diff --git a/apps/docs/libraries/ts/sdk/keys/create.mdx b/apps/docs/libraries/ts/sdk/keys/create.mdx index b5c9671df4..5c212b180d 100644 --- a/apps/docs/libraries/ts/sdk/keys/create.mdx +++ b/apps/docs/libraries/ts/sdk/keys/create.mdx @@ -108,6 +108,13 @@ Unkey allows automatic refill on 'remaining' on a 'daily' or 'monthly' interval. The amount to refill 'remaining'. +Read more [here](/apis/features/refill) + + + value from `1` to `31`. + + The day each month to refill 'remaining'. If no value is given, The 1st will be used as a default. + Read more [here](/apis/features/refill) @@ -152,8 +159,9 @@ const created = await unkey.keys.create({ }, remaining: 1000, refill: { - interval: "daily", - amount: 100 + interval: "monthly", + amount: 100, + refillDay: 15, }, enabled: true }) diff --git a/apps/docs/libraries/ts/sdk/keys/get.mdx b/apps/docs/libraries/ts/sdk/keys/get.mdx index c36c113d58..17c3724248 100644 --- a/apps/docs/libraries/ts/sdk/keys/get.mdx +++ b/apps/docs/libraries/ts/sdk/keys/get.mdx @@ -59,13 +59,23 @@ The number of requests that can be made with this key before it becomes invalid. Unkey allows you to refill remaining verifications on a key on a regular interval. - + Determines the rate at which verifications will be refilled. + +Available options: +- `daily`: Refills occur every day +- `monthly`: Refills occur once a month (see `refillDay` for specific day) Resets `remaining` to this value every interval. + + value from `1` to `31`. + + The day each month to refill 'remaining'. If no value is given, The 1st will be used as a default. +Read more [here](/apis/features/refill) + The unix timestamp in miliseconds when the key was last refilled. diff --git a/apps/docs/libraries/ts/sdk/keys/update.mdx b/apps/docs/libraries/ts/sdk/keys/update.mdx index 832db7cbc3..447cd7b48e 100644 --- a/apps/docs/libraries/ts/sdk/keys/update.mdx +++ b/apps/docs/libraries/ts/sdk/keys/update.mdx @@ -79,6 +79,13 @@ Unkey allows automatic refill on 'remaining' on a 'daily' or 'monthly' interval. The amount to refill 'remaining'. +Read more [here](/apis/features/refill) + + + value from `1` to `31`. + + The day each month to refill 'remaining'. If no value is given, The 1st will be used as a default. + Read more [here](/apis/features/refill) @@ -110,8 +117,9 @@ await unkey.keys.update({ ownerId: "new owner", remaining: 300, refil: { - interval: "daily", - amount: 100 + interval: "monthly", + amount: 100, + refillDay: 15, }, enabled: true }); diff --git a/apps/semantic-cache/package.json b/apps/semantic-cache/package.json index 8d9418351c..5c9b027d3e 100644 --- a/apps/semantic-cache/package.json +++ b/apps/semantic-cache/package.json @@ -27,7 +27,7 @@ }, "dependencies": { "@chronark/zod-bird": "^0.3.9", - "@planetscale/database": "^1.18.0", + "@planetscale/database": "^1.16.0", "@unkey/cache": "workspace:^", "@unkey/db": "workspace:^", "@unkey/error": "workspace:^", diff --git a/apps/workflows/jobs/index.ts b/apps/workflows/jobs/index.ts index 249e51f0fa..4b574e1e08 100644 --- a/apps/workflows/jobs/index.ts +++ b/apps/workflows/jobs/index.ts @@ -1,4 +1,3 @@ // export all your job files here export * from "./refill-daily"; -export * from "./refill-monthly"; diff --git a/apps/workflows/jobs/refill-daily.ts b/apps/workflows/jobs/refill-daily.ts index eca82f7578..4800b88115 100644 --- a/apps/workflows/jobs/refill-daily.ts +++ b/apps/workflows/jobs/refill-daily.ts @@ -1,4 +1,4 @@ -import { connectDatabase, eq, lte, schema } from "@/lib/db"; +import { connectDatabase, eq, schema } from "@/lib/db"; import { client } from "@/trigger"; import { cronTrigger } from "@trigger.dev/sdk"; import { newId } from "@unkey/id"; @@ -11,33 +11,36 @@ client.defineJob({ cron: "0 0 * * *", // Daily at midnight UTC }), - run: async (_payload, io, _ctx) => { + run: async (payload, io, _ctx) => { + const date = payload.ts; + // Set up last day of month so if refillDay is after last day of month, Key will be refilled today. + const lastDayOfMonth = new Date(date.getFullYear(), date.getMonth() + 1, 0).getDate(); + const today = date.getUTCDate(); const db = connectDatabase(); - const t = new Date(); - t.setUTCHours(t.getUTCHours() - 24); const BUCKET_NAME = "unkey_mutations"; type Key = `${string}::${string}`; type BucketId = string; const bucketCache = new Map(); - const keys = await io.runTask("list keys", () => - db.query.keys.findMany({ - where: (table, { isNotNull, isNull, eq, and, gt, or }) => - and( - isNull(table.deletedAt), - isNotNull(table.refillInterval), - isNotNull(table.refillAmount), - eq(table.refillInterval, "daily"), - gt(table.refillAmount, table.remaining), - or( - isNull(table.lastRefillAt), - lte(table.lastRefillAt, t), // Check if more than 24 hours have passed - ), - ), - }), - ); - io.logger.info(`found ${keys.length} keys with daily refill set`); + // If refillDay is after last day of month, refillDay will be today. + const keys = await db.query.keys.findMany({ + where: (table, { isNotNull, isNull, and, gt, or, eq }) => { + const baseConditions = and( + isNull(table.deletedAt), + isNotNull(table.refillAmount), + gt(table.refillAmount, table.remaining), + or(isNull(table.refillDay), eq(table.refillDay, today)), + ); + + if (today === lastDayOfMonth) { + return and(baseConditions, gt(table.refillDay, today)); + } + return baseConditions; + }, + }); + + io.logger.info(`found ${keys.length} keys with refill set for today`); for (const key of keys) { const cacheKey: Key = `${key.workspaceId}::${BUCKET_NAME}`; let bucketId = ""; @@ -109,7 +112,7 @@ client.defineJob({ }); } return { - keyIds: keys.map((k) => k.id), + refillKeyIds: keys.map((k) => k.id), }; }, }); diff --git a/apps/workflows/jobs/refill-monthly.ts b/apps/workflows/jobs/refill-monthly.ts deleted file mode 100644 index 47c9cd1369..0000000000 --- a/apps/workflows/jobs/refill-monthly.ts +++ /dev/null @@ -1,113 +0,0 @@ -import { connectDatabase, eq, gt, lte, schema } from "@/lib/db"; -import { client } from "@/trigger"; -import { cronTrigger } from "@trigger.dev/sdk"; -import { newId } from "@unkey/id"; -client.defineJob({ - id: "refill.monthly", - name: "Monthly refill", - version: "0.0.1", - trigger: cronTrigger({ - cron: "0 0 0 1 1/1 ? *", // First of each month at 00:00 UTC - }), - - run: async (_payload, io, _ctx) => { - const db = connectDatabase(); - const t = new Date(); - t.setUTCMonth(t.getUTCMonth() - 1); - const BUCKET_NAME = "unkey_mutations"; - - type Key = `${string}::${string}`; - type BucketId = string; - const bucketCache = new Map(); - const keys = await io.runTask("list keys", () => - db.query.keys.findMany({ - where: (table, { isNotNull, isNull, eq, and, or }) => - and( - isNull(table.deletedAt), - isNotNull(table.refillInterval), - isNotNull(table.refillAmount), - eq(table.refillInterval, "monthly"), - gt(table.refillAmount, table.remaining), - or( - isNull(table.lastRefillAt), - lte(table.lastRefillAt, t), // Check if more than 1 Month has passed - ), - ), - }), - ); - io.logger.info(`found ${keys.length} keys with monthly refill set`); - for (const key of keys) { - const cacheKey: Key = `${key.workspaceId}::${BUCKET_NAME}`; - let bucketId = ""; - const cachedBucketId = bucketCache.get(cacheKey); - if (cachedBucketId) { - bucketId = cachedBucketId; - } else { - const bucket = await db.query.auditLogBucket.findFirst({ - where: (table, { eq, and }) => - and(eq(table.workspaceId, key.workspaceId), eq(table.name, BUCKET_NAME)), - columns: { - id: true, - }, - }); - - if (bucket) { - bucketId = bucket.id; - } else { - bucketId = newId("auditLogBucket"); - await db.insert(schema.auditLogBucket).values({ - id: bucketId, - workspaceId: key.workspaceId, - name: BUCKET_NAME, - }); - } - } - - bucketCache.set(cacheKey, bucketId); - await io.runTask(`refill for ${key.id}`, async () => { - await db.transaction(async (tx) => { - await tx - .update(schema.keys) - .set({ - remaining: key.refillAmount, - lastRefillAt: new Date(), - }) - .where(eq(schema.keys.id, key.id)); - - const auditLogId = newId("auditLog"); - await tx.insert(schema.auditLog).values({ - id: auditLogId, - workspaceId: key.workspaceId, - bucketId: bucketId, - time: Date.now(), - event: "key.update", - actorId: "trigger", - actorType: "system", - display: `Refilled ${key.id} to ${key.refillAmount}`, - }); - await tx.insert(schema.auditLogTarget).values([ - { - type: "workspace", - id: key.workspaceId, - workspaceId: key.workspaceId, - bucketId: bucketId, - auditLogId, - displayName: `workspace ${key.workspaceId}`, - }, - { - type: "key", - id: key.id, - workspaceId: key.workspaceId, - bucketId: bucketId, - auditLogId, - displayName: `key ${key.id}`, - }, - ]); - }); - }); - } - return { - keyIds: keys.map((k) => k.id), - }; - }, -}); diff --git a/apps/www/app/glossary/[slug]/faq.tsx b/apps/www/app/glossary/[slug]/faq.tsx new file mode 100644 index 0000000000..3a73e6b0ba --- /dev/null +++ b/apps/www/app/glossary/[slug]/faq.tsx @@ -0,0 +1,38 @@ +import { + Accordion, + AccordionContent, + AccordionItem, + AccordionTrigger, +} from "@/components/ui/accordion"; + +export function FAQ(props: { + epigraph?: string; + title: string; + description: string; + items: Array<{ question: string; answer: string }>; +}) { + return ( + <> +
+

+ {props.title} +

+

+ {props.description} +

+
+
+ + {props.items.map((item) => ( + + + {item.question} + + {item.answer} + + ))} + +
+ + ); +} diff --git a/apps/www/app/glossary/[slug]/page.tsx b/apps/www/app/glossary/[slug]/page.tsx new file mode 100644 index 0000000000..0afcf55c21 --- /dev/null +++ b/apps/www/app/glossary/[slug]/page.tsx @@ -0,0 +1,283 @@ +import { CTA } from "@/components/cta"; +import { Frame } from "@/components/frame"; + +import TermsStepperMobile from "@/components/glossary/terms-stepper-mobile"; +import { MDX } from "@/components/mdx-content"; +import { TopLeftShiningLight, TopRightShiningLight } from "@/components/svg/background-shiny"; +import { Card, CardContent, CardHeader } from "@/components/ui/card"; +import { MeteorLinesAngular } from "@/components/ui/meteorLines"; +import { cn } from "@/lib/utils"; +import { allGlossaries } from "content-collections"; +import { Zap } from "lucide-react"; +import type { Metadata } from "next"; +import Link from "next/link"; +import { notFound } from "next/navigation"; +import { FAQ } from "./faq"; +import Takeaways from "./takeaways"; +import TermsRolodexDesktop from "@/components/glossary/terms-rolodex-desktop"; +import { FilterableCommand } from "@/components/glossary/search"; + +export const generateStaticParams = async () => + allGlossaries.map((term) => ({ + slug: term.slug, + })); + +export function generateMetadata({ + params, +}: { + params: { slug: string }; +}): Metadata { + const term = allGlossaries.find((term) => term.slug === params.slug); + if (!term) { + notFound(); + } + return { + title: `${term.title} | Unkey Glossary`, + description: term.description, + openGraph: { + title: `${term.title} | Unkey Glossary`, + description: term.description, + url: `https://unkey.com/glossary/${term.slug}`, + siteName: "unkey.com", + type: "article", + }, + twitter: { + card: "summary_large_image", + title: `${term.title} | Unkey Glossary`, + description: term.description, + site: "@unkeydev", + creator: "@unkeydev", + }, + icons: { + shortcut: "/images/landing/unkey.png", + }, + }; +} + +const GlossaryTermWrapper = async ({ params }: { params: { slug: string } }) => { + const term = allGlossaries.find((term) => term.slug === params.slug); + if (!term) { + notFound(); + } + + const relatedTerms: { + slug: string; + term: string; + tldr: string; + }[] = []; + return ( + <> +
+
+ +
+
+ + + + + + + + +
+
+ +
+
+
+ {/* Left Sidebar */} +
+
+

+ Find a term +

+ +
+

Terms

+ ({ slug: term.slug, title: term.title }))} + /> + ({ slug: term.slug, title: term.title }))} + /> +
+
+
+ {/* Main Content */} +
+
+
+ + + Glossary + + + / + + {term.term} + +
+

+ {term.h1} +

+

+ {term.intro} +

+
+
+ +
+
+ +
+
+ +
+
+ {/* Right Sidebar */} +
+
+ {term.tableOfContents?.length !== 0 && ( +
+

Contents

+
    + {term.tableOfContents.map((heading) => ( +
  • + 2, + "ml-4": heading?.level && heading.level === 3, + "ml-8": heading?.level && heading.level === 4, + })} + > + {heading?.text} + +
  • + ))} +
+
+ )} + {/* Related Blogs */} +
+

Related Terms

+
+ {relatedTerms.length > 0 ? ( + relatedTerms.map((relatedTerm) => ( + + + + +
+

+ TL;DR +

+

{relatedTerm.tldr}

+
+ +
+ +

+ {relatedTerm.term} +

+
+
+ + )) + ) : ( +

No related terms found.

+ )} +
+
+
+
+
+ +
+
+ + ); +}; + +export default GlossaryTermWrapper; diff --git a/apps/www/app/glossary/[slug]/takeaways.tsx b/apps/www/app/glossary/[slug]/takeaways.tsx new file mode 100644 index 0000000000..6decc40bb5 --- /dev/null +++ b/apps/www/app/glossary/[slug]/takeaways.tsx @@ -0,0 +1,170 @@ +import type { Glossary } from "@/.content-collections/generated"; +import { Badge } from "@/components/ui/badge"; +import { Card, CardContent, CardFooter, CardHeader, CardTitle } from "@/components/ui/card"; +import { + AlertTriangle, + BookOpen, + Clock, + Code, + Coffee, + ExternalLink, + FileText, + RefreshCcw, + Zap, +} from "lucide-react"; +import { z } from "zod"; + +const itemSchema = z.object({ + key: z.string(), + value: z.string(), +}); + +export const takeawaysSchema = z.object({ + tldr: z.string(), + definitionAndStructure: z.array(itemSchema), + historicalContext: z.array(itemSchema), + usageInAPIs: z.object({ + tags: z.array(z.string()), + description: z.string(), + }), + bestPractices: z.array(z.string()), + recommendedReading: z.array( + z.object({ + title: z.string(), + url: z.string(), + }), + ), + didYouKnow: z.string(), +}); + +export default function Takeaways(props: Pick) { + return ( + +
+ + {props.term}: Key Takeaways + + +
+

+ TL;DR +

+

{props.takeaways.tldr}

+
+
+
} + title="Definition & Structure" + content={ +
+ {props.takeaways.definitionAndStructure.map((item) => ( +
+ {item.key} + + {item.value} + +
+ ))} +
+ } + /> +
} + title="Historical Context" + items={props.takeaways.historicalContext} + /> +
} + title="Usage in APIs" + content={ + <> +
+ {props.takeaways.usageInAPIs.tags.map((tag) => ( + + {tag} + + ))} +
+

{props.takeaways.usageInAPIs.description}

+ + } + /> +
} + title="Best Practices" + items={props.takeaways.bestPractices} + /> +
+
} + title="Recommended Reading" + content={ + + } + /> + + +
+
+ + Did You Know? +
+ {props.takeaways.didYouKnow} + +
+
+ + ); +} + +type SectionProps = { + icon: React.ReactNode; + title: string; +} & ( + | { items: Array>; content?: never } + | { items?: never; content: React.ReactNode } +); + +function Section(props: SectionProps) { + const { icon, title } = props; + return ( +
+

+ {icon} + {title} +

+ {props.content ? ( + props.content + ) : ( +
+ {props.items?.map((item) => + typeof item === "string" ? ( +
  • + {item} +
  • + ) : ( +
    + {item.key} + {item.value} +
    + ), + )} +
    + )} +
    + ); +} diff --git a/apps/www/app/glossary/client.tsx b/apps/www/app/glossary/client.tsx new file mode 100644 index 0000000000..1e6f16dd06 --- /dev/null +++ b/apps/www/app/glossary/client.tsx @@ -0,0 +1,219 @@ +"use client"; +import { CTA } from "@/components/cta"; +import { ChangelogLight } from "@/components/svg/changelog"; + +import { PrimaryButton } from "@/components/button"; +import { Container } from "@/components/container"; +import { FilterableCommand } from "@/components/glossary/search"; +import { MeteorLinesAngular } from "@/components/ui/meteorLines"; +import { LogIn } from "lucide-react"; +import Link from "next/link"; +import { allGlossaries, type Glossary } from "@/.content-collections/generated"; +import { Zap } from "lucide-react"; + +export function GlossaryClient() { + const alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ".split(""); + + const groupedTerms = allGlossaries.reduce( + (acc, term) => { + const firstLetter = term.title[0].toUpperCase(); + if (!acc[firstLetter]) { + acc[firstLetter] = []; + } + acc[firstLetter].push(term); + return acc; + }, + {} as Record>, + ); + + return ( +
    +
    +
    + +
    +
    + + + + + + + + +
    +
    + +
    +

    + + API Glossary: A comprehensive guide to API terminology by Unkey + +

    +
    +

    + With clear definitions and helpful examples, Unkey's API Glossary is your go-to + resource for understanding the key concepts and terminology in API development. +

    +
    +
    +
    +

    Ready to protect your API?

    + + + +
    +
    +
    +
    + {/* Left Sidebar */} +
    +

    + Find a term +

    + +
    +
    +
    + {alphabet.map((letter) => + groupedTerms[letter]?.length > 0 ? ( + + {letter} + + ) : ( + + {letter} + + ), + )} +
    + {Object.entries(groupedTerms).map( + ([letter, letterTerms]) => + letterTerms.length > 0 && ( +
    +

    {letter}

    +
    + {letterTerms.map(({ slug, categories, takeaways, term }) => ( + +
    +
    +
    +

    + TL;DR +

    +

    {takeaways.tldr}

    +
    +
    +
    +
    +
    +
    + {categories.length > 0 + ? categories.map((categorySlug) => ( +
    + {categorySlug // unslugged + .replace(/-/g, " ") + .replace(/\b\w/g, (char) => char.toUpperCase())} +
    + )) + : null} +
    +
    +
    +
    +

    + {term} +

    +
    +
    +
    + + ))} +
    +
    + ), + )} +
    +
    +
    + +
    + ); +} + +// +// +// +// +//
    +//

    +// TL;DR +//

    +//

    {takeaways.tldr}

    +//
    +// +//
    +// +//

    {term}

    +//
    +//
    +// diff --git a/apps/www/app/glossary/data-client.tsx b/apps/www/app/glossary/data-client.tsx new file mode 100644 index 0000000000..209dde91ae --- /dev/null +++ b/apps/www/app/glossary/data-client.tsx @@ -0,0 +1,6 @@ +import { FileJson } from "lucide-react"; +import { categories } from "./data"; +// note this is a separate client-file to include the icons, so that we can load the typescript .ts file into our content-collection config +export const categoriesWithIcons = [ + ...categories.map((c) => ({ ...c, icon: })), +] as const; diff --git a/apps/www/app/glossary/data.ts b/apps/www/app/glossary/data.ts new file mode 100644 index 0000000000..855021f43a --- /dev/null +++ b/apps/www/app/glossary/data.ts @@ -0,0 +1,21 @@ +import { z } from "zod"; + +// note that this doesn't include the react icons, so that we can load the typescript .ts file into our content-collection config +export const categories = [ + { + slug: "api-specification", + title: "API Specification", + description: + "API & Web standards for defining data formats and interactions (e.g. OpenAPI, REST, HTTP Requests, etc.)", + }, +] as const; + +// Extract slug values to create a union type +type CategorySlug = (typeof categories)[number]["slug"]; + +// Create a Zod enum from the CategorySlug type +export const categoryEnum = z.enum( + categories.map((c) => c.slug) as [CategorySlug, ...Array], +); + +export type CategoryEnum = z.infer; diff --git a/apps/www/app/glossary/page.tsx b/apps/www/app/glossary/page.tsx new file mode 100644 index 0000000000..a200131bc1 --- /dev/null +++ b/apps/www/app/glossary/page.tsx @@ -0,0 +1,34 @@ +import { GlossaryClient } from "./client"; + +export const metadata = { + title: "Glossary | Unkey", + description: "Jumpstart your API development with our pre-built solutions.", + openGraph: { + title: "Glossary | Unkey", + description: "Jumpstart your API development with our pre-built solutions.", + url: "https://unkey.com/glossary", + siteName: "unkey.com", + images: [ + { + url: "https://unkey.com/images/landing/og.png", + width: 1200, + height: 675, + }, + ], + }, + twitter: { + title: "Glossary | Unkey", + card: "summary_large_image", + }, + icons: { + shortcut: "/images/landing/unkey.png", + }, +}; + +export default function GlossaryPage() { + return ( +
    + +
    + ); +} diff --git a/apps/www/app/templates/[slug]/page.tsx b/apps/www/app/templates/[slug]/page.tsx index d7d0c31f03..3eecba286b 100644 --- a/apps/www/app/templates/[slug]/page.tsx +++ b/apps/www/app/templates/[slug]/page.tsx @@ -20,7 +20,7 @@ type Props = { }; }; -export const revalidate = 300; // 5min +export const revalidate = 3600; // 1 hour export async function generateStaticParams() { return Object.keys(templates).map((slug) => ({ diff --git a/apps/www/app/templates/data.ts b/apps/www/app/templates/data.ts index 8cc5e20d6d..865c7da386 100644 --- a/apps/www/app/templates/data.ts +++ b/apps/www/app/templates/data.ts @@ -16,6 +16,10 @@ export const frameworks = [ "Oak", "FastAPI", "NestJS", + "Koa", + "Hono", + "AdonisJS", + "fastify", ] as const; export type Framework = StrArrayToUnion; // id -> label @@ -55,6 +59,80 @@ export type Template = { }; export const templates: Record = { + "go-nethttp": { + title: "Go standard lib", + description: "Unkey with net/http", + authors: ["diwasrimal"], + repository: "https://github.com/diwasrimal/unkey-go-stdlib-auth", + image: "/images/templates/go-nethttp.png", + readmeUrl: + "https://raw.githubusercontent.com/diwasrimal/unkey-go-stdlib-auth/refs/heads/main/README.md", + language: "Golang", + framework: undefined, + }, + "hono-cloudflare": { + title: "Hono Ratelimit Starter for Cloudflare Workers", + description: "Simple hono and cloudflare workers api with rate limiting by unkey", + authors: ["Devansh-Baghel"], + repository: "https://github.com/Devansh-Baghel/hono-unkey-ratelimit-starter", + + image: "/images/templates/hono-cloudflare.png", + readmeUrl: + "https://raw.githubusercontent.com/Devansh-Baghel/hono-unkey-ratelimit-starter/refs/heads/main/README.md", + + language: "Typescript", + framework: "Hono", + }, + fastify: { + title: "Protecting your fastify API", + description: "API keys and ratelimiting for fastify", + authors: ["Vardhaman619"], + repository: "https://github.com/Vardhaman619/fastify-unkey", + + image: "/images/templates/fastify.png", + readmeUrl: + "https://raw.githubusercontent.com/Vardhaman619/fastify-unkey/refs/heads/main/README.md", + + language: "Typescript", + framework: "fastify", + }, + "sadonis-ratelimit": { + title: "Ratelimiting in AdonisJS apps", + description: "Dynamic IP based ratelimiting.", + authors: ["Ionfinisher"], + repository: "https://github.com/Ionfinisher/unkey-adonisjs-ratelimit", + + image: "/images/templates/adonis-ratelimit.png", + readmeUrl: + "https://raw.githubusercontent.com/Ionfinisher/unkey-adonisjs-ratelimit/refs/heads/main/README.md", + + language: "Typescript", + framework: "AdonisJS", + }, + sealshare: { + title: "End-to-end encrypted secret sharing", + description: "Share secrets securely, directly in your browser.", + authors: ["unrenamed"], + repository: "https://github.com/unrenamed/sealshare", + + image: "/images/templates/sealshare.png", + readmeUrl: "https://raw.githubusercontent.com/unrenamed/sealshare/refs/heads/main/README.md", + + language: "Typescript", + framework: "Next.js", + }, + koa: { + title: "Koa.js middleware with Unkey RBAC", + description: "Implement API key verification in your Koa apps", + authors: ["harshsbhat"], + repository: "https://github.com/harshsbhat/unkey-koa", + + image: "/images/templates/koa.png", + readmeUrl: "https://raw.githubusercontent.com/harshsbhat/unkey-koa/refs/heads/main/README.md", + + language: "Typescript", + framework: "Koa", + }, "nextjs-supabase-payasyougo": { title: "Next.js Pay-as-you-Go starter kit", description: "Building Pay-As-You-Go apps with Next.js, Unkey and Supabase", @@ -63,7 +141,8 @@ export const templates: Record = { image: "/images/templates/nextjs-supabase-payasyougo.png", readmeUrl: - "https://raw.githubusercontent.com/unrenamed/unkey-nextjs-pay-as-you-go/heads/main/README.md", + "https://raw.githubusercontent.com/unrenamed/unkey-nextjs-pay-as-you-go/refs/heads/main/README.md", + language: "Typescript", framework: "Next.js", }, diff --git a/apps/www/components/glossary/search.tsx b/apps/www/components/glossary/search.tsx new file mode 100644 index 0000000000..8d31b8b9cb --- /dev/null +++ b/apps/www/components/glossary/search.tsx @@ -0,0 +1,60 @@ +"use client"; + +import * as React from "react"; +import { Command as CommandPrimitive } from "cmdk"; +import { + Command, + CommandEmpty, + CommandGroup, + CommandInput, + CommandList, +} from "@/components/ui/command"; +import { cn } from "@/lib/utils"; +import { useRouter } from "next/navigation"; +import type { Glossary } from "@/.content-collections/generated"; + +export function FilterableCommand(props: { + placeholder: string; + className?: string; + terms: Array; +}) { + const [open, setOpen] = React.useState(false); + const router = useRouter(); + const commandRef = React.useRef(null); + + return ( + div]:border-b-0", props.className)} ref={commandRef}> + setOpen(true)} + // The `onBlur` event checks if the new focus target (relatedTarget) is within the Command component: + // - If it's not (i.e., clicking outside), it closes the list. + // - If it is (i.e., selecting an item), it keeps the list open, allowing the `onSelect` to handle the navigation. + onBlur={(event: React.FocusEvent) => { + const relatedTarget = event.relatedTarget as Node | null; + if (!commandRef.current?.contains(relatedTarget)) { + setOpen(false); + } + }} + /> + + {open && ( + + No terms found. + + {props.terms.map((item) => ( + router.push(`/glossary/${item.slug}`)} + > + {item.title} + + ))} + + + )} + + ); +} diff --git a/apps/www/components/glossary/terms-rolodex-desktop.tsx b/apps/www/components/glossary/terms-rolodex-desktop.tsx new file mode 100644 index 0000000000..17af33a986 --- /dev/null +++ b/apps/www/components/glossary/terms-rolodex-desktop.tsx @@ -0,0 +1,105 @@ +"use client"; + +import { useState } from "react"; +import Link from "next/link"; +import { Button } from "@/components/ui/button"; +import { ChevronUpIcon, ChevronDownIcon } from "lucide-react"; +import { cn } from "@/lib/utils"; +import { useParams } from "next/navigation"; +import type { Glossary } from "@/.content-collections/generated"; + +export default function TermsRolodexDesktop({ + className, + terms, +}: { className?: string; terms: Array> }) { + const params = useParams(); + const currentSlug = params.slug; + if (typeof currentSlug !== "string") { + throw new Error("slug is not a string"); + } + + const [currentIndex, setCurrentIndex] = useState(() => { + const initialIndex = terms.findIndex((term) => term.slug === currentSlug); + return initialIndex >= 0 ? initialIndex : 0; + }); + + const getVisibleTerms = () => { + const totalVisible = Math.min(7, terms.length); + const halfVisible = Math.floor(totalVisible / 2); + + const start = currentIndex - halfVisible; + const end = currentIndex + halfVisible + 1; + + const wrappedTerms = [...terms, ...terms, ...terms]; + const centerOffset = terms.length; + + return wrappedTerms.slice(centerOffset + start, centerOffset + end); + }; + + const handleScroll = (direction: "up" | "down") => { + setCurrentIndex((prevIndex) => { + let newIndex = direction === "up" ? prevIndex - 1 : prevIndex + 1; + if (newIndex < 0) { + newIndex = terms.length - 1; + } + if (newIndex >= terms.length) { + newIndex = 0; + } + return newIndex; + }); + }; + + const visibleTerms = getVisibleTerms(); + + return ( +
    +
    + +
    + {visibleTerms.map((term, index) => ( + 2 && (index === 0 || index === visibleTerms.length - 1), + }, + )} + > + {term.title} + + ))} +
    + +
    +
    + ); +} diff --git a/apps/www/components/glossary/terms-stepper-mobile.tsx b/apps/www/components/glossary/terms-stepper-mobile.tsx new file mode 100644 index 0000000000..1a1b50b479 --- /dev/null +++ b/apps/www/components/glossary/terms-stepper-mobile.tsx @@ -0,0 +1,49 @@ +"use client"; + +import type { Glossary } from "@/.content-collections/generated"; +import { cn } from "@/lib/utils"; +import { ChevronLeftIcon, ChevronRightIcon } from "lucide-react"; +import Link from "next/link"; +import { useParams } from "next/navigation"; + +export default function TermsStepperMobile({ + className, + terms, +}: { className?: string; terms: Array> }) { + const params = useParams(); + const slug = params.slug as string; + const sortedTerms = terms.sort((a, b) => a.title.localeCompare(b.title)); + const slugIndex = sortedTerms.findIndex((term) => term.slug === slug); + const startIndex = slugIndex !== -1 ? slugIndex : 0; + const currentTerm = sortedTerms[startIndex]; + const previousTerm = sortedTerms[(startIndex - 1 + sortedTerms.length) % sortedTerms.length]; + const nextTerm = sortedTerms[(startIndex + 1) % sortedTerms.length]; + + return ( +
    +
    +
    + + + {previousTerm.title} + + +
    +

    {currentTerm.title}

    +
    + + + {nextTerm.title} + + +
    +
    +
    + ); +} diff --git a/apps/www/components/svg/glossary-page.tsx b/apps/www/components/svg/glossary-page.tsx new file mode 100644 index 0000000000..e2266f7dd9 --- /dev/null +++ b/apps/www/components/svg/glossary-page.tsx @@ -0,0 +1,18 @@ +export const KeyIcon = ({ className }: { className?: string }) => ( + + + +); diff --git a/apps/www/components/ui/badge.tsx b/apps/www/components/ui/badge.tsx new file mode 100644 index 0000000000..effc532bc4 --- /dev/null +++ b/apps/www/components/ui/badge.tsx @@ -0,0 +1,33 @@ +import { type VariantProps, cva } from "class-variance-authority"; +import type * as React from "react"; + +import { cn } from "@/lib/utils"; + +const badgeVariants = cva( + "inline-flex items-center rounded-full border px-2.5 py-0.5 text-xs font-semibold transition-colors focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2", + { + variants: { + variant: { + default: "border-transparent bg-primary text-primary-foreground hover:bg-primary/80", + secondary: + "border-transparent bg-secondary text-secondary-foreground hover:bg-secondary/80", + destructive: + "border-transparent bg-destructive text-destructive-foreground hover:bg-destructive/80", + outline: "text-foreground", + }, + }, + defaultVariants: { + variant: "default", + }, + }, +); + +export interface BadgeProps + extends React.HTMLAttributes, + VariantProps {} + +function Badge({ className, variant, ...props }: BadgeProps) { + return
    ; +} + +export { Badge, badgeVariants }; diff --git a/apps/www/components/ui/button.tsx b/apps/www/components/ui/button.tsx new file mode 100644 index 0000000000..f20e872485 --- /dev/null +++ b/apps/www/components/ui/button.tsx @@ -0,0 +1,49 @@ +import { Slot } from "@radix-ui/react-slot"; +import { type VariantProps, cva } from "class-variance-authority"; +import * as React from "react"; + +import { cn } from "@/lib/utils"; + +const buttonVariants = cva( + "inline-flex items-center justify-center whitespace-nowrap rounded-md text-sm font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50", + { + variants: { + variant: { + default: "bg-primary text-primary-foreground hover:bg-primary/90", + destructive: "bg-destructive text-destructive-foreground hover:bg-destructive/90", + outline: "border border-input bg-background hover:bg-accent hover:text-accent-foreground", + secondary: "bg-secondary text-secondary-foreground hover:bg-secondary/80", + ghost: "hover:bg-accent hover:text-accent-foreground", + link: "text-primary underline-offset-4 hover:underline", + }, + size: { + default: "h-10 px-4 py-2", + sm: "h-9 rounded-md px-3", + lg: "h-11 rounded-md px-8", + icon: "h-10 w-10", + }, + }, + defaultVariants: { + variant: "default", + size: "default", + }, + }, +); + +export interface ButtonProps + extends React.ButtonHTMLAttributes, + VariantProps { + asChild?: boolean; +} + +const Button = React.forwardRef( + ({ className, variant, size, asChild = false, ...props }, ref) => { + const Comp = asChild ? Slot : "button"; + return ( + + ); + }, +); +Button.displayName = "Button"; + +export { Button, buttonVariants }; diff --git a/apps/www/components/ui/card.tsx b/apps/www/components/ui/card.tsx new file mode 100644 index 0000000000..117feb709d --- /dev/null +++ b/apps/www/components/ui/card.tsx @@ -0,0 +1,56 @@ +import * as React from "react"; + +import { cn } from "@/lib/utils"; + +const Card = React.forwardRef>( + ({ className, ...props }, ref) => ( +
    + ), +); +Card.displayName = "Card"; + +const CardHeader = React.forwardRef>( + ({ className, ...props }, ref) => ( +
    + ), +); +CardHeader.displayName = "CardHeader"; + +const CardTitle = React.forwardRef>( + ({ className, ...props }, ref) => ( +

    + ), +); +CardTitle.displayName = "CardTitle"; + +const CardDescription = React.forwardRef< + HTMLParagraphElement, + React.HTMLAttributes +>(({ className, ...props }, ref) => ( +

    +)); +CardDescription.displayName = "CardDescription"; + +const CardContent = React.forwardRef>( + ({ className, ...props }, ref) => ( +

    + ), +); +CardContent.displayName = "CardContent"; + +const CardFooter = React.forwardRef>( + ({ className, ...props }, ref) => ( +
    + ), +); +CardFooter.displayName = "CardFooter"; + +export { Card, CardHeader, CardFooter, CardTitle, CardDescription, CardContent }; diff --git a/apps/www/components/ui/input.tsx b/apps/www/components/ui/input.tsx new file mode 100644 index 0000000000..84da2c01c0 --- /dev/null +++ b/apps/www/components/ui/input.tsx @@ -0,0 +1,24 @@ +import * as React from "react"; + +import { cn } from "@/lib/utils"; + +export interface InputProps extends React.InputHTMLAttributes {} + +const Input = React.forwardRef( + ({ className, type, ...props }, ref) => { + return ( + + ); + }, +); +Input.displayName = "Input"; + +export { Input }; diff --git a/apps/www/components/ui/label.tsx b/apps/www/components/ui/label.tsx new file mode 100644 index 0000000000..ef8f3bd7c4 --- /dev/null +++ b/apps/www/components/ui/label.tsx @@ -0,0 +1,21 @@ +"use client"; + +import * as LabelPrimitive from "@radix-ui/react-label"; +import { type VariantProps, cva } from "class-variance-authority"; +import * as React from "react"; + +import { cn } from "@/lib/utils"; + +const labelVariants = cva( + "text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70", +); + +const Label = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef & VariantProps +>(({ className, ...props }, ref) => ( + +)); +Label.displayName = LabelPrimitive.Root.displayName; + +export { Label }; diff --git a/apps/www/content-collections.ts b/apps/www/content-collections.ts index b92e3b0eee..5d075fb1de 100644 --- a/apps/www/content-collections.ts +++ b/apps/www/content-collections.ts @@ -2,6 +2,7 @@ import { defineCollection, defineConfig } from "@content-collections/core"; import { compileMDX } from "@content-collections/mdx"; import { remarkGfm, remarkHeading, remarkStructure } from "fumadocs-core/mdx-plugins"; import GithubSlugger from "github-slugger"; +import { categoryEnum } from "./app/glossary/data"; const posts = defineCollection({ name: "posts", @@ -104,6 +105,78 @@ const job = defineCollection({ }, }); +const glossary = defineCollection({ + name: "glossary", + directory: "content/glossary", + include: "*.mdx", + schema: (z) => ({ + title: z.string(), + description: z.string(), + intro: z.string(), + h1: z.string(), + term: z.string(), + categories: z.array(categoryEnum), + takeaways: z.object({ + tldr: z.string(), + definitionAndStructure: z.array( + z.object({ + key: z.string(), + value: z.string(), + }), + ), + historicalContext: z.array( + z.object({ + key: z.string(), + value: z.string(), + }), + ), + usageInAPIs: z.object({ + tags: z.array(z.string()), + description: z.string(), + }), + bestPractices: z.array(z.string()), + recommendedReading: z.array( + z.object({ + title: z.string(), + url: z.string(), + }), + ), + didYouKnow: z.string(), + }), + }), + transform: async (document, context) => { + const mdx = await compileMDX(context, document, { + remarkPlugins: [remarkGfm, remarkHeading, remarkStructure], + }); + const slugger = new GithubSlugger(); + // This regex is different from the one in the blog post. It matches the first header without requiring a newline as well (the h1 is provided in the frontmatter) + + const regXHeader = /(?:^|\n)(?#+)\s+(?.+)/g; + const tableOfContents = Array.from(document.content.matchAll(regXHeader)) + .map(({ groups }) => { + const flag = groups?.flag; + const content = groups?.content; + // Only include headers that are not the main title (h1) + if (flag && flag.length > 1) { + return { + level: flag.length, + text: content, + slug: content ? slugger.slug(content) : undefined, + }; + } + return null; + }) + .filter(Boolean); // Remove null entries + return { + ...document, + mdx, + slug: document._meta.path, + url: `/glossary/${document._meta.path}`, + tableOfContents, + }; + }, +}); + export default defineConfig({ - collections: [posts, changelog, policy, job], + collections: [posts, changelog, policy, job, glossary], }); diff --git a/apps/www/content/glossary/mime-types.mdx b/apps/www/content/glossary/mime-types.mdx new file mode 100644 index 0000000000..a42590ec45 --- /dev/null +++ b/apps/www/content/glossary/mime-types.mdx @@ -0,0 +1,98 @@ +--- +title: "MIME Types Explained" +description: "Learn about MIME types in API development. Understand their role in defining file formats like images and PDFs. Explore our glossary for more insights." +term: "MIME Types" +h1: "What are MIME Types? Format IDs Explained" +intro: "MIME types are essential identifiers in digital communication, specifying the nature and format of data. They play a crucial role in web development and API interactions, ensuring that information is correctly interpreted and displayed across various platforms and applications." +categories: ["api-specification"] +takeaways: + tldr: "Crucial identifiers in digital communication, especially APIs. They specify data format, ensuring correct interpretation and interoperability." + definitionAndStructure: + - key: "Format" + value: "type/subtype" + - key: "Example" + value: "image/jpeg" + - key: "Optional" + value: "charset=UTF-8" + historicalContext: + - key: "Introduced" + value: "1996" + - key: "Origin" + value: "Email (MIME)" + - key: "Evolution" + value: "HTTP & Web" + usageInAPIs: + tags: + - "Content-Type Header" + - "HTTP Requests" + - "File Uploads" + description: "In API responses, MIME types are included in HTTP headers (e.g., 'Content-Type: application/json') to inform clients about the data format." + bestPractices: + - "Always set the correct MIME type in API responses" + - "Be aware of security implications (e.g., XSS risks with incorrect MIME types)" + - "Use standardized MIME types when possible" + recommendedReading: + - title: "RFC 6838: Media Type Specifications and Registration Procedures" + url: "https://tools.ietf.org/html/rfc6838" + - title: "MDN Web Docs: MIME types (IANA media types)" + url: "https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/MIME_types" + - title: "RESTful Web Services by Leonard Richardson & Sam Ruby" + url: "https://www.oreilly.com/library/view/restful-web-services/9780596529260/" + didYouKnow: '"application/octet-stream" is the catch-all for unknown binary files.' +--- + +## Understanding MIME Types in Web and API Development + +MIME types are widely used in web development and APIs to specify the format of the content being transferred. In the context of APIs, particularly RESTful APIs, MIME types are included in HTTP headers to inform the client about the format of the returned data, whether it is JSON, XML, or another format. For example, when a server returns JSON data, it uses the MIME type `application/json`. This helps client applications understand how to parse and handle the data effectively. + +In web development, specifying the correct MIME type is vital for ensuring that browsers know how to display or handle the served file. For instance, when a server sends a CSS file, it uses the MIME type `text/css`, indicating to the browser that it should interpret it as a stylesheet. + +### Examples of MIME Types in HTTP Headers + +Here are some common MIME type examples used in HTTP headers: + +```http +Content-Type: application/json +``` +This header in an API response indicates that the data is in JSON format. + +```http +Content-Type: text/html +``` +This header in a web response tells the browser to interpret the response as HTML. + +### MIME Type List + +A comprehensive MIME type list includes various formats, such as: + +- **Image MIME Types**: + - `image/jpeg` for JPEG images + - `image/png` for PNG images + - `image/gif` for GIF images + +- **Video MIME Types**: + - `video/mp4` for MP4 videos + - `video/x-msvideo` for AVI videos + - `video/webm` for WebM videos + +- **Document MIME Types**: + - `application/pdf` for PDF documents + - `application/msword` for Microsoft Word documents + +### Detailed Structure of MIME Types + +A MIME type consists of two main parts: a type and a subtype, separated by a slash (`/`). The type represents the general category of the data, while the subtype specifies the specific kind of data. For example, in `image/jpeg`, `image` is the type, and `jpeg` is the subtype, indicating that the file is an image in JPEG format. Similarly, `application/json` indicates that the data is in the application-specific format of JSON. + +The structure can also include additional parameters, such as `charset`, which defines the character set used in text data. For example: + +```http +Content-Type: text/html; charset=UTF-8 +``` +This indicates that the HTML content should be interpreted using the UTF-8 character set. + +### Importance of MIME Types in API Development + +Understanding the detailed structure and usage of MIME types is crucial for API developers. Properly specifying MIME types enhances compatibility and efficiency across different systems and platforms. It ensures that data is correctly processed in web applications and when interacting with APIs, ultimately improving the user experience. + +For further exploration, developers can refer to the official IANA Media Types registry (https://www.iana.org/assignments/media-types/) or the resources listed in the recommended reading section above. +By mastering MIME types, API developers can ensure that their applications handle data correctly, leading to more robust and user-friendly web services. diff --git a/apps/www/public/images/templates/adonis-ratelimit.png b/apps/www/public/images/templates/adonis-ratelimit.png new file mode 100644 index 0000000000..0d21f2da6e Binary files /dev/null and b/apps/www/public/images/templates/adonis-ratelimit.png differ diff --git a/apps/www/public/images/templates/fastify.png b/apps/www/public/images/templates/fastify.png new file mode 100644 index 0000000000..e7bd4ca805 Binary files /dev/null and b/apps/www/public/images/templates/fastify.png differ diff --git a/apps/www/public/images/templates/go-nethttp.png b/apps/www/public/images/templates/go-nethttp.png new file mode 100644 index 0000000000..52fd3b8b05 Binary files /dev/null and b/apps/www/public/images/templates/go-nethttp.png differ diff --git a/apps/www/public/images/templates/hono-cloudflare.png b/apps/www/public/images/templates/hono-cloudflare.png new file mode 100644 index 0000000000..309b5f884e Binary files /dev/null and b/apps/www/public/images/templates/hono-cloudflare.png differ diff --git a/apps/www/public/images/templates/koa.png b/apps/www/public/images/templates/koa.png new file mode 100644 index 0000000000..ad2b775aff Binary files /dev/null and b/apps/www/public/images/templates/koa.png differ diff --git a/apps/www/public/images/templates/sealshare.png b/apps/www/public/images/templates/sealshare.png new file mode 100644 index 0000000000..7bac21662c Binary files /dev/null and b/apps/www/public/images/templates/sealshare.png differ diff --git a/internal/db/src/schema/key_migrations.ts b/internal/db/src/schema/key_migrations.ts index 3d12548dc5..0c3470435b 100644 --- a/internal/db/src/schema/key_migrations.ts +++ b/internal/db/src/schema/key_migrations.ts @@ -30,7 +30,7 @@ export const keyMigrationErrors = mysqlTable("key_migration_errors", { permissions?: string[]; expires?: number; remaining?: number; - refill?: { interval: "daily" | "monthly"; amount: number }; + refill?: { interval: "daily" | "monthly"; amount: number; refillDay?: number | undefined }; ratelimit?: { async: boolean; limit: number; duration: number }; enabled: boolean; environment?: string; diff --git a/internal/db/src/schema/keys.ts b/internal/db/src/schema/keys.ts index 5eeb701f65..afba30984f 100644 --- a/internal/db/src/schema/keys.ts +++ b/internal/db/src/schema/keys.ts @@ -8,6 +8,7 @@ import { mysqlEnum, mysqlTable, text, + tinyint, uniqueIndex, varchar, } from "drizzle-orm/mysql-core"; @@ -63,6 +64,7 @@ export const keys = mysqlTable( * You can refill uses to keys at a desired interval */ refillInterval: mysqlEnum("refill_interval", ["daily", "monthly"]), + refillDay: tinyint("refill_day"), refillAmount: int("refill_amount"), lastRefillAt: datetime("last_refill_at", { fsp: 3 }), /** diff --git a/internal/metrics/src/index.ts b/internal/metrics/src/index.ts index fc6c6a70d7..1d14ce0710 100644 --- a/internal/metrics/src/index.ts +++ b/internal/metrics/src/index.ts @@ -79,10 +79,10 @@ export const metricSchema = z.discriminatedUnion("metric", [ namespaceId: z.string().optional(), identifier: z.string(), latency: z.number(), - mode: z.enum(["sync", "async"]), + mode: z.enum(["sync", "async", "cloudflare"]), success: z.boolean().optional(), error: z.boolean().optional(), - source: z.enum(["agent", "durable_object"]), + source: z.enum(["agent", "durable_object", "cloudflare"]), }), z.object({ metric: z.literal("metric.usagelimit"), diff --git a/packages/rbac/src/permissions.ts b/packages/rbac/src/permissions.ts index 0f7e9b7f08..e387617183 100644 --- a/packages/rbac/src/permissions.ts +++ b/packages/rbac/src/permissions.ts @@ -7,10 +7,8 @@ * - `gateway_id.xxx` * */ - import { z } from "zod"; import type { Flatten } from "./types"; - export function buildIdSchema(prefix: string) { return z.string().refine((s) => { if (s === "*") { @@ -26,7 +24,6 @@ const apiId = buildIdSchema("api"); const ratelimitNamespaceId = buildIdSchema("rl"); const rbacId = buildIdSchema("rbac"); const identityEnvId = z.string(); - export const apiActions = z.enum([ "read_api", "create_api", @@ -39,15 +36,16 @@ export const apiActions = z.enum([ "decrypt_key", "read_key", ]); - export const ratelimitActions = z.enum([ "limit", "create_namespace", "read_namespace", "update_namespace", "delete_namespace", + "set_override", + "read_override", + "delete_override", ]); - export const rbacActions = z.enum([ "create_permission", "update_permission", @@ -64,14 +62,12 @@ export const rbacActions = z.enum([ "add_permission_to_role", "remove_permission_from_role", ]); - export const identityActions = z.enum([ "create_identity", "read_identity", "update_identity", "delete_identity", ]); - export type Resources = { [resourceId in `api.${z.infer}`]: z.infer; } & { @@ -83,9 +79,7 @@ export type Resources = { } & { [resourceId in `identity.${z.infer}`]: z.infer; }; - export type UnkeyPermission = Flatten | "*"; - /** * Validation for roles used for our root keys */ @@ -117,7 +111,6 @@ export const unkeyPermissionValidation = z.custom().refine((s) case "identity": { return identityEnvId.safeParse(id).success && identityActions.safeParse(action).success; } - default: { return false; } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 55231cbbca..702bd4fa85 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -145,7 +145,7 @@ importers: version: 5.5.3 vitest: specifier: ^1.6.0 - version: 1.6.0(@vitest/ui@1.6.0) + version: 1.6.0(@types/node@20.14.9)(@vitest/ui@1.6.0) wrangler: specifier: ^3.80.5 version: 3.80.5(@cloudflare/workers-types@4.20240603.0) @@ -199,7 +199,7 @@ importers: version: link:../../internal/schema ai: specifier: ^3.4.7 - version: 3.4.7(openai@4.52.1)(react@18.3.1)(svelte@4.2.19)(vue@3.5.11)(zod@3.23.8) + version: 3.4.7(openai@4.52.1)(react@18.3.1)(svelte@5.0.5)(vue@3.5.12)(zod@3.23.8) drizzle-orm: specifier: ^0.33.0 version: 0.33.0(@opentelemetry/api@1.4.1)(@planetscale/database@1.18.0)(@types/react@18.3.11)(react@18.3.1) @@ -458,7 +458,7 @@ importers: version: 2.1.3 next: specifier: 14.2.10 - version: 14.2.10(@babel/core@7.25.8)(@opentelemetry/api@1.4.1)(react-dom@18.3.1)(react@18.3.1) + version: 14.2.10(@babel/core@7.25.9)(@opentelemetry/api@1.4.1)(react-dom@18.3.1)(react@18.3.1) next-mdx-remote: specifier: ^4.4.1 version: 4.4.1(react-dom@18.3.1)(react@18.3.1) @@ -595,7 +595,7 @@ importers: version: 13.4.10(@types/react@18.3.11)(next@14.2.10)(react-dom@18.3.1)(react@18.3.1) fumadocs-mdx: specifier: 10.0.2 - version: 10.0.2(fumadocs-core@13.4.10)(next@14.2.10) + version: 10.0.2(acorn@8.13.0)(fumadocs-core@13.4.10)(next@14.2.10) fumadocs-ui: specifier: 13.4.10 version: 13.4.10(@types/react-dom@18.3.0)(@types/react@18.3.11)(next@14.2.10)(react-dom@18.3.1)(react@18.3.1)(tailwindcss@3.4.10) @@ -604,7 +604,7 @@ importers: version: 0.378.0(react@18.3.1) next: specifier: ^14.2.8 - version: 14.2.10(@babel/core@7.25.8)(@opentelemetry/api@1.4.1)(react-dom@18.3.1)(react@18.3.1) + version: 14.2.10(@babel/core@7.25.9)(@opentelemetry/api@1.4.1)(react-dom@18.3.1)(react@18.3.1) react: specifier: ^18.3.1 version: 18.3.1 @@ -675,7 +675,7 @@ importers: version: link:../../packages/api next: specifier: 14.2.10 - version: 14.2.10(@babel/core@7.25.8)(@opentelemetry/api@1.4.1)(react-dom@18.3.1)(react@18.3.1) + version: 14.2.10(@babel/core@7.25.9)(@opentelemetry/api@1.4.1)(react-dom@18.3.1)(react@18.3.1) react: specifier: ^18 version: 18.3.1 @@ -757,7 +757,7 @@ importers: version: 2.1.3 next: specifier: 14.2.10 - version: 14.2.10(@babel/core@7.25.8)(@opentelemetry/api@1.4.1)(react-dom@18.3.1)(react@18.3.1) + version: 14.2.10(@babel/core@7.25.9)(@opentelemetry/api@1.4.1)(react-dom@18.3.1)(react@18.3.1) next-themes: specifier: ^0.3.0 version: 0.3.0(react-dom@18.3.1)(react@18.3.1) @@ -832,7 +832,7 @@ importers: specifier: ^0.3.9 version: 0.3.9 '@planetscale/database': - specifier: ^1.18.0 + specifier: ^1.16.0 version: 1.18.0 '@unkey/cache': specifier: workspace:^ @@ -860,7 +860,7 @@ importers: version: link:../../internal/worker-logging ai: specifier: ^3.0.23 - version: 3.4.7(openai@4.52.1)(react@18.3.1)(svelte@4.2.19)(vue@3.5.12)(zod@3.23.8) + version: 3.4.7(openai@4.52.1)(react@18.3.1)(svelte@5.0.5)(vue@3.5.12)(zod@3.23.8) drizzle-orm: specifier: generated version: 0.32.0-aaf764c(@cloudflare/workers-types@4.20240603.0)(@planetscale/database@1.18.0)(react@18.3.1) @@ -939,7 +939,7 @@ importers: version: 0.32.0-aaf764c(@planetscale/database@1.18.0)(@types/react@18.3.11)(react@18.3.1) next: specifier: 14.2.10 - version: 14.2.10(@babel/core@7.25.8)(@opentelemetry/api@1.4.1)(react-dom@18.3.1)(react@18.3.1) + version: 14.2.10(@babel/core@7.25.9)(@opentelemetry/api@1.4.1)(react-dom@18.3.1)(react@18.3.1) react: specifier: ^18 version: 18.3.1 @@ -1063,7 +1063,7 @@ importers: version: 5.0.7 next: specifier: 14.2.10 - version: 14.2.10(@babel/core@7.25.8)(@opentelemetry/api@1.4.1)(react-dom@18.3.1)(react@18.3.1) + version: 14.2.10(@babel/core@7.25.9)(@opentelemetry/api@1.4.1)(react-dom@18.3.1)(react@18.3.1) next-mdx-remote: specifier: ^4.4.1 version: 4.4.1(react-dom@18.3.1)(react@18.3.1) @@ -1118,7 +1118,7 @@ importers: version: 0.7.2(typescript@5.5.3) '@content-collections/mdx': specifier: ^0.1.3 - version: 0.1.3(@content-collections/core@0.7.2)(react-dom@18.3.1)(react@18.3.1) + version: 0.1.3(@content-collections/core@0.7.2)(acorn@8.13.0)(react-dom@18.3.1)(react@18.3.1) '@content-collections/next': specifier: ^0.2.0 version: 0.2.0(@content-collections/core@0.7.2)(next@14.2.10) @@ -1172,7 +1172,7 @@ importers: version: link:../../packages/error ai: specifier: ^3.0.23 - version: 3.4.7(openai@4.52.1)(react@18.3.1)(svelte@4.2.19)(vue@3.5.11)(zod@3.23.8) + version: 3.4.7(openai@4.52.1)(react@18.3.1)(svelte@5.0.5)(vue@3.5.12)(zod@3.23.8) zod: specifier: ^3.23.5 version: 3.23.8 @@ -1194,7 +1194,7 @@ importers: devDependencies: checkly: specifier: latest - version: 4.9.0(@types/node@20.14.9)(typescript@5.5.3) + version: 4.9.1(@types/node@20.14.9)(typescript@5.5.3) ts-node: specifier: 10.9.1 version: 10.9.1(@types/node@20.14.9)(typescript@5.5.3) @@ -1415,7 +1415,7 @@ importers: version: 18.3.1 react-email: specifier: 2.1.1 - version: 2.1.1(@babel/core@7.25.8)(eslint@9.12.0)(ts-node@10.9.2) + version: 2.1.1(@babel/core@7.25.9)(eslint@9.13.0)(ts-node@10.9.2) resend: specifier: ^4.0.0 version: 4.0.0(react-dom@18.3.1)(react@18.3.1) @@ -1525,7 +1525,7 @@ importers: version: 1.31.3 next: specifier: ^14.2.10 - version: 14.2.10(@babel/core@7.25.8)(@opentelemetry/api@1.4.1)(react-dom@18.3.1)(react@18.3.1) + version: 14.2.10(@babel/core@7.25.9)(@opentelemetry/api@1.4.1)(react-dom@18.3.1)(react@18.3.1) tsup: specifier: ^8.0.2 version: 8.0.2(ts-node@10.9.2)(typescript@5.5.3) @@ -1591,7 +1591,7 @@ importers: version: 20.14.9 next: specifier: ^14.2.10 - version: 14.2.10(@babel/core@7.25.8)(@opentelemetry/api@1.4.1)(react-dom@18.3.1)(react@18.3.1) + version: 14.2.10(@babel/core@7.25.9)(@opentelemetry/api@1.4.1)(react-dom@18.3.1)(react@18.3.1) tsup: specifier: ^8.0.2 version: 8.0.2(ts-node@10.9.2)(typescript@5.5.3) @@ -1767,7 +1767,7 @@ packages: delay: 6.0.0 hash-object: 5.0.1 is-relative-url: 4.0.0 - jsonrepair: 3.8.1 + jsonrepair: 3.9.0 ky: 1.7.2 normalize-url: 8.0.1 p-map: 7.0.2 @@ -1860,7 +1860,7 @@ packages: - zod dev: false - /@ai-sdk/svelte@0.0.51(svelte@4.2.19)(zod@3.23.8): + /@ai-sdk/svelte@0.0.51(svelte@5.0.5)(zod@3.23.8): resolution: {integrity: sha512-aIZJaIds+KpCt19yUDCRDWebzF/17GCY7gN9KkcA2QM6IKRO5UmMcqEYja0ZmwFQPm1kBZkF2njhr8VXis2mAw==} engines: {node: '>=18'} peerDependencies: @@ -1871,8 +1871,8 @@ packages: dependencies: '@ai-sdk/provider-utils': 1.0.20(zod@3.23.8) '@ai-sdk/ui-utils': 0.0.46(zod@3.23.8) - sswr: 2.1.0(svelte@4.2.19) - svelte: 4.2.19 + sswr: 2.1.0(svelte@5.0.5) + svelte: 5.0.5 transitivePeerDependencies: - zod dev: false @@ -1894,23 +1894,6 @@ packages: zod-to-json-schema: 3.23.2(zod@3.23.8) dev: false - /@ai-sdk/vue@0.0.53(vue@3.5.11)(zod@3.23.8): - resolution: {integrity: sha512-FNScuIvM8N4Pj4Xto11blgI97c5cjjTelyk0M0MkyU+sLSbpQNDE78CRq5cW1oeVkJzzdv63+xh8jaFNe+2vnQ==} - engines: {node: '>=18'} - peerDependencies: - vue: ^3.3.4 - peerDependenciesMeta: - vue: - optional: true - dependencies: - '@ai-sdk/provider-utils': 1.0.20(zod@3.23.8) - '@ai-sdk/ui-utils': 0.0.46(zod@3.23.8) - swrv: 1.0.4(vue@3.5.11) - vue: 3.5.11(typescript@5.5.3) - transitivePeerDependencies: - - zod - dev: false - /@ai-sdk/vue@0.0.53(vue@3.5.12)(zod@3.23.8): resolution: {integrity: sha512-FNScuIvM8N4Pj4Xto11blgI97c5cjjTelyk0M0MkyU+sLSbpQNDE78CRq5cW1oeVkJzzdv63+xh8jaFNe+2vnQ==} engines: {node: '>=18'} @@ -1985,7 +1968,7 @@ packages: resolution: {integrity: sha512-DVhcFSQ8YQnMNW34Mk8BSsfc61iC1sAnmcfYoXTAshYHuU50p/6b7x3QYaGctDNKWGvi1ub7mPcSY0bK+aN0qg==} dependencies: '@antv/util': 2.0.17 - tslib: 2.7.0 + tslib: 2.8.0 dev: false /@antv/attr@0.3.5: @@ -1994,14 +1977,14 @@ packages: '@antv/color-util': 2.0.6 '@antv/scale': 0.3.18 '@antv/util': 2.0.17 - tslib: 2.7.0 + tslib: 2.8.0 dev: false /@antv/color-util@2.0.6: resolution: {integrity: sha512-KnPEaAH+XNJMjax9U35W67nzPI+QQ2x27pYlzmSIWrbj4/k8PGrARXfzDTjwoozHJY8qG62Z+Ww6Alhu2FctXQ==} dependencies: '@antv/util': 2.0.17 - tslib: 2.7.0 + tslib: 2.8.0 dev: false /@antv/component@0.8.35: @@ -2015,7 +1998,7 @@ packages: '@antv/scale': 0.3.18 '@antv/util': 2.0.17 fecha: 4.2.3 - tslib: 2.7.0 + tslib: 2.8.0 dev: false /@antv/coord@0.3.1: @@ -2023,13 +2006,13 @@ packages: dependencies: '@antv/matrix-util': 3.1.0-beta.3 '@antv/util': 2.0.17 - tslib: 2.7.0 + tslib: 2.8.0 dev: false /@antv/dom-util@2.0.4: resolution: {integrity: sha512-2shXUl504fKwt82T3GkuT4Uoc6p9qjCKnJ8gXGLSW4T1W37dqf9AV28aCfoVPHp2BUXpSsB+PAJX2rG/jLHsLQ==} dependencies: - tslib: 2.7.0 + tslib: 2.8.0 dev: false /@antv/event-emitter@0.1.3: @@ -2049,7 +2032,7 @@ packages: d3-interpolate: 3.0.1 d3-timer: 1.0.10 detect-browser: 5.3.0 - tslib: 2.7.0 + tslib: 2.8.0 dev: false /@antv/g-canvas@0.5.17: @@ -2061,7 +2044,7 @@ packages: '@antv/path-util': 2.0.15 '@antv/util': 2.0.17 gl-matrix: 3.4.3 - tslib: 2.7.0 + tslib: 2.8.0 dev: false /@antv/g-math@0.1.9: @@ -2078,7 +2061,7 @@ packages: '@antv/g-math': 0.1.9 '@antv/util': 2.0.17 detect-browser: 5.3.0 - tslib: 2.7.0 + tslib: 2.8.0 dev: false /@antv/g-webgpu-core@0.5.6: @@ -2169,7 +2152,7 @@ packages: '@antv/path-util': 2.0.15 '@antv/scale': 0.3.18 '@antv/util': 2.0.17 - tslib: 2.7.0 + tslib: 2.8.0 dev: false /@antv/g2plot@2.4.32: @@ -2188,7 +2171,7 @@ packages: fmin: 0.0.2 pdfast: 0.2.0 size-sensor: 1.0.2 - tslib: 2.7.0 + tslib: 2.8.0 dev: false /@antv/g6-core@0.8.24: @@ -2202,8 +2185,8 @@ packages: '@antv/matrix-util': 3.1.0-beta.3 '@antv/path-util': 2.0.15 '@antv/util': 2.0.17 - ml-matrix: 6.11.1 - tslib: 2.7.0 + ml-matrix: 6.12.0 + tslib: 2.8.0 dev: false /@antv/g6-element@0.8.24(@antv/g6@4.8.24): @@ -2215,7 +2198,7 @@ packages: '@antv/g6': 4.8.24 '@antv/g6-core': 0.8.24 '@antv/util': 2.0.17 - tslib: 2.7.0 + tslib: 2.8.0 dev: false /@antv/g6-pc@0.8.24(@antv/g6@4.8.24): @@ -2241,8 +2224,8 @@ packages: d3-force: 2.1.1 dagre: 0.8.5 insert-css: 2.0.0 - ml-matrix: 6.11.1 - tslib: 2.7.0 + ml-matrix: 6.12.0 + tslib: 2.8.0 transitivePeerDependencies: - '@antv/g6' dev: false @@ -2286,7 +2269,7 @@ packages: '@antv/g-webgpu': 0.5.5 '@dagrejs/graphlib': 2.1.4 d3-force: 2.1.1 - ml-matrix: 6.11.1 + ml-matrix: 6.12.0 dev: false /@antv/layout@0.3.25(dagre@0.8.5): @@ -2308,7 +2291,7 @@ packages: dependencies: '@antv/util': 2.0.17 gl-matrix: 3.4.3 - tslib: 2.7.0 + tslib: 2.8.0 dev: false /@antv/matrix-util@3.1.0-beta.3: @@ -2316,7 +2299,7 @@ packages: dependencies: '@antv/util': 2.0.17 gl-matrix: 3.4.3 - tslib: 2.7.0 + tslib: 2.8.0 dev: false /@antv/path-util@2.0.15: @@ -2324,7 +2307,7 @@ packages: dependencies: '@antv/matrix-util': 3.0.4 '@antv/util': 2.0.17 - tslib: 2.7.0 + tslib: 2.8.0 dev: false /@antv/path-util@3.0.1: @@ -2332,7 +2315,7 @@ packages: dependencies: gl-matrix: 3.4.3 lodash-es: 4.17.21 - tslib: 2.7.0 + tslib: 2.8.0 dev: false /@antv/scale@0.3.18: @@ -2340,14 +2323,14 @@ packages: dependencies: '@antv/util': 2.0.17 fecha: 4.2.3 - tslib: 2.7.0 + tslib: 2.8.0 dev: false /@antv/util@2.0.17: resolution: {integrity: sha512-o6I9hi5CIUvLGDhth0RxNSFDRwXeywmt6ExR4+RmVAzIi48ps6HUy+svxOCayvrPBN37uE6TAc2KDofRo0nK9Q==} dependencies: csstype: 3.1.3 - tslib: 2.7.0 + tslib: 2.8.0 dev: false /@antv/util@3.3.10: @@ -2355,7 +2338,7 @@ packages: dependencies: fast-deep-equal: 3.1.3 gl-matrix: 3.4.3 - tslib: 2.7.0 + tslib: 2.8.0 dev: false /@apidevtools/json-schema-ref-parser@9.0.6: @@ -2407,31 +2390,31 @@ packages: uuid: 8.3.2 dev: false - /@babel/code-frame@7.25.7: - resolution: {integrity: sha512-0xZJFNE5XMpENsgfHYTw8FbX4kv53mFLn2i3XPoq69LyhYSCBJtitaHx9QnsVTrsogI4Z3+HtEfZ2/GFPOtf5g==} + /@babel/code-frame@7.25.9: + resolution: {integrity: sha512-z88xeGxnzehn2sqZ8UdGQEvYErF1odv2CftxInpSYJt6uHuPe9YjahKZITGs3l5LeI9d2ROG+obuDAoSlqbNfQ==} engines: {node: '>=6.9.0'} dependencies: - '@babel/highlight': 7.25.7 - picocolors: 1.1.0 + '@babel/highlight': 7.25.9 + picocolors: 1.1.1 - /@babel/compat-data@7.25.8: - resolution: {integrity: sha512-ZsysZyXY4Tlx+Q53XdnOFmqwfB9QDTHYxaZYajWRoBLuLEAwI2UIbtxOjWh/cFaa9IKUlcB+DDuoskLuKu56JA==} + /@babel/compat-data@7.25.9: + resolution: {integrity: sha512-yD+hEuJ/+wAJ4Ox2/rpNv5HIuPG82x3ZlQvYVn8iYCprdxzE7P1udpGF1jyjQVBU4dgznN+k2h103vxZ7NdPyw==} engines: {node: '>=6.9.0'} - /@babel/core@7.25.8: - resolution: {integrity: sha512-Oixnb+DzmRT30qu9d3tJSQkxuygWm32DFykT4bRoORPa9hZ/L4KhVB/XiRm6KG+roIEM7DBQlmg27kw2HZkdZg==} + /@babel/core@7.25.9: + resolution: {integrity: sha512-WYvQviPw+Qyib0v92AwNIrdLISTp7RfDkM7bPqBvpbnhY4wq8HvHBZREVdYDXk98C8BkOIVnHAY3yvj7AVISxQ==} engines: {node: '>=6.9.0'} dependencies: '@ampproject/remapping': 2.3.0 - '@babel/code-frame': 7.25.7 - '@babel/generator': 7.25.7 - '@babel/helper-compilation-targets': 7.25.7 - '@babel/helper-module-transforms': 7.25.7(@babel/core@7.25.8) - '@babel/helpers': 7.25.7 - '@babel/parser': 7.25.8 - '@babel/template': 7.25.7 - '@babel/traverse': 7.25.7 - '@babel/types': 7.25.8 + '@babel/code-frame': 7.25.9 + '@babel/generator': 7.25.9 + '@babel/helper-compilation-targets': 7.25.9 + '@babel/helper-module-transforms': 7.25.9(@babel/core@7.25.9) + '@babel/helpers': 7.25.9 + '@babel/parser': 7.25.9 + '@babel/template': 7.25.9 + '@babel/traverse': 7.25.9 + '@babel/types': 7.25.9 convert-source-map: 2.0.0 debug: 4.3.7(supports-color@8.1.1) gensync: 1.0.0-beta.2 @@ -2440,135 +2423,134 @@ packages: transitivePeerDependencies: - supports-color - /@babel/generator@7.25.7: - resolution: {integrity: sha512-5Dqpl5fyV9pIAD62yK9P7fcA768uVPUyrQmqpqstHWgMma4feF1x/oFysBCVZLY5wJ2GkMUCdsNDnGZrPoR6rA==} + /@babel/generator@7.25.9: + resolution: {integrity: sha512-omlUGkr5EaoIJrhLf9CJ0TvjBRpd9+AXRG//0GEQ9THSo8wPiTlbpy1/Ow8ZTrbXpjd9FHXfbFQx32I04ht0FA==} engines: {node: '>=6.9.0'} dependencies: - '@babel/types': 7.25.8 + '@babel/types': 7.25.9 '@jridgewell/gen-mapping': 0.3.5 '@jridgewell/trace-mapping': 0.3.25 jsesc: 3.0.2 - /@babel/helper-compilation-targets@7.25.7: - resolution: {integrity: sha512-DniTEax0sv6isaw6qSQSfV4gVRNtw2rte8HHM45t9ZR0xILaufBRNkpMifCRiAPyvL4ACD6v0gfCwCmtOQaV4A==} + /@babel/helper-compilation-targets@7.25.9: + resolution: {integrity: sha512-j9Db8Suy6yV/VHa4qzrj9yZfZxhLWQdVnRlXxmKLYlhWUVB1sB2G5sxuWYXk/whHD9iW76PmNzxZ4UCnTQTVEQ==} engines: {node: '>=6.9.0'} dependencies: - '@babel/compat-data': 7.25.8 - '@babel/helper-validator-option': 7.25.7 - browserslist: 4.24.0 + '@babel/compat-data': 7.25.9 + '@babel/helper-validator-option': 7.25.9 + browserslist: 4.24.2 lru-cache: 5.1.1 semver: 6.3.1 - /@babel/helper-module-imports@7.25.7: - resolution: {integrity: sha512-o0xCgpNmRohmnoWKQ0Ij8IdddjyBFE4T2kagL/x6M3+4zUgc+4qTOUBoNe4XxDskt1HPKO007ZPiMgLDq2s7Kw==} + /@babel/helper-module-imports@7.25.9: + resolution: {integrity: sha512-tnUA4RsrmflIM6W6RFTLFSXITtl0wKjgpnLgXyowocVPrbYrLUXSBXDgTs8BlbmIzIdlBySRQjINYs2BAkiLtw==} engines: {node: '>=6.9.0'} dependencies: - '@babel/traverse': 7.25.7 - '@babel/types': 7.25.8 + '@babel/traverse': 7.25.9 + '@babel/types': 7.25.9 transitivePeerDependencies: - supports-color - /@babel/helper-module-transforms@7.25.7(@babel/core@7.25.8): - resolution: {integrity: sha512-k/6f8dKG3yDz/qCwSM+RKovjMix563SLxQFo0UhRNo239SP6n9u5/eLtKD6EAjwta2JHJ49CsD8pms2HdNiMMQ==} + /@babel/helper-module-transforms@7.25.9(@babel/core@7.25.9): + resolution: {integrity: sha512-TvLZY/F3+GvdRYFZFyxMvnsKi+4oJdgZzU3BoGN9Uc2d9C6zfNwJcKKhjqLAhK8i46mv93jsO74fDh3ih6rpHA==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0 dependencies: - '@babel/core': 7.25.8 - '@babel/helper-module-imports': 7.25.7 - '@babel/helper-simple-access': 7.25.7 - '@babel/helper-validator-identifier': 7.25.7 - '@babel/traverse': 7.25.7 + '@babel/core': 7.25.9 + '@babel/helper-module-imports': 7.25.9 + '@babel/helper-simple-access': 7.25.9 + '@babel/helper-validator-identifier': 7.25.9 + '@babel/traverse': 7.25.9 transitivePeerDependencies: - supports-color - /@babel/helper-simple-access@7.25.7: - resolution: {integrity: sha512-FPGAkJmyoChQeM+ruBGIDyrT2tKfZJO8NcxdC+CWNJi7N8/rZpSxK7yvBJ5O/nF1gfu5KzN7VKG3YVSLFfRSxQ==} + /@babel/helper-simple-access@7.25.9: + resolution: {integrity: sha512-c6WHXuiaRsJTyHYLJV75t9IqsmTbItYfdj99PnzYGQZkYKvan5/2jKJ7gu31J3/BJ/A18grImSPModuyG/Eo0Q==} engines: {node: '>=6.9.0'} dependencies: - '@babel/traverse': 7.25.7 - '@babel/types': 7.25.8 + '@babel/traverse': 7.25.9 + '@babel/types': 7.25.9 transitivePeerDependencies: - supports-color - /@babel/helper-string-parser@7.25.7: - resolution: {integrity: sha512-CbkjYdsJNHFk8uqpEkpCvRs3YRp9tY6FmFY7wLMSYuGYkrdUi7r2lc4/wqsvlHoMznX3WJ9IP8giGPq68T/Y6g==} + /@babel/helper-string-parser@7.25.9: + resolution: {integrity: sha512-4A/SCr/2KLd5jrtOMFzaKjVtAei3+2r/NChoBNoZ3EyP/+GlhoaEGoWOZUmFmoITP7zOJyHIMm+DYRd8o3PvHA==} engines: {node: '>=6.9.0'} - /@babel/helper-validator-identifier@7.25.7: - resolution: {integrity: sha512-AM6TzwYqGChO45oiuPqwL2t20/HdMC1rTPAesnBCgPCSF1x3oN9MVUwQV2iyz4xqWrctwK5RNC8LV22kaQCNYg==} + /@babel/helper-validator-identifier@7.25.9: + resolution: {integrity: sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ==} engines: {node: '>=6.9.0'} - /@babel/helper-validator-option@7.25.7: - resolution: {integrity: sha512-ytbPLsm+GjArDYXJ8Ydr1c/KJuutjF2besPNbIZnZ6MKUxi/uTA22t2ymmA4WFjZFpjiAMO0xuuJPqK2nvDVfQ==} + /@babel/helper-validator-option@7.25.9: + resolution: {integrity: sha512-e/zv1co8pp55dNdEcCynfj9X7nyUKUXoUEwfXqaZt0omVOmDe9oOTdKStH4GmAw6zxMFs50ZayuMfHDKlO7Tfw==} engines: {node: '>=6.9.0'} - /@babel/helpers@7.25.7: - resolution: {integrity: sha512-Sv6pASx7Esm38KQpF/U/OXLwPPrdGHNKoeblRxgZRLXnAtnkEe4ptJPDtAZM7fBLadbc1Q07kQpSiGQ0Jg6tRA==} + /@babel/helpers@7.25.9: + resolution: {integrity: sha512-oKWp3+usOJSzDZOucZUAMayhPz/xVjzymyDzUN8dk0Wd3RWMlGLXi07UCQ/CgQVb8LvXx3XBajJH4XGgkt7H7g==} engines: {node: '>=6.9.0'} dependencies: - '@babel/template': 7.25.7 - '@babel/types': 7.25.8 + '@babel/template': 7.25.9 + '@babel/types': 7.25.9 - /@babel/highlight@7.25.7: - resolution: {integrity: sha512-iYyACpW3iW8Fw+ZybQK+drQre+ns/tKpXbNESfrhNnPLIklLbXr7MYJ6gPEd0iETGLOK+SxMjVvKb/ffmk+FEw==} + /@babel/highlight@7.25.9: + resolution: {integrity: sha512-llL88JShoCsth8fF8R4SJnIn+WLvR6ccFxu1H3FlMhDontdcmZWf2HgIZ7AIqV3Xcck1idlohrN4EUBQz6klbw==} engines: {node: '>=6.9.0'} dependencies: - '@babel/helper-validator-identifier': 7.25.7 + '@babel/helper-validator-identifier': 7.25.9 chalk: 2.4.2 js-tokens: 4.0.0 - picocolors: 1.1.0 + picocolors: 1.1.1 /@babel/parser@7.24.1: resolution: {integrity: sha512-Zo9c7N3xdOIQrNip7Lc9wvRPzlRtovHVE4lkz8WEDr7uYh/GMQhSiIgFxGIArRHYdJE5kxtZjAf8rT0xhdLCzg==} engines: {node: '>=6.0.0'} hasBin: true dependencies: - '@babel/types': 7.25.8 + '@babel/types': 7.25.9 dev: false - /@babel/parser@7.25.8: - resolution: {integrity: sha512-HcttkxzdPucv3nNFmfOOMfFf64KgdJVqm1KaCm25dPGMLElo9nsLvXeJECQg8UzPuBGLyTSA0ZzqCtDSzKTEoQ==} + /@babel/parser@7.25.9: + resolution: {integrity: sha512-aI3jjAAO1fh7vY/pBGsn1i9LDbRP43+asrRlkPuTXW5yHXtd1NgTEMudbBoDDxrf1daEEfPJqR+JBMakzrR4Dg==} engines: {node: '>=6.0.0'} hasBin: true dependencies: - '@babel/types': 7.25.8 + '@babel/types': 7.25.9 - /@babel/runtime@7.25.7: - resolution: {integrity: sha512-FjoyLe754PMiYsFaN5C94ttGiOmBNYTf6pLr4xXHAT5uctHb092PBszndLDR5XA/jghQvn4n7JMHl7dmTgbm9w==} + /@babel/runtime@7.25.9: + resolution: {integrity: sha512-4zpTHZ9Cm6L9L+uIqghQX8ZXg8HKFcjYO3qHoO8zTmRm6HQUJ8SSJ+KRvbMBZn0EGVlT4DRYeQ/6hjlyXBh+Kg==} engines: {node: '>=6.9.0'} dependencies: regenerator-runtime: 0.14.1 - /@babel/template@7.25.7: - resolution: {integrity: sha512-wRwtAgI3bAS+JGU2upWNL9lSlDcRCqD05BZ1n3X2ONLH1WilFP6O1otQjeMK/1g0pvYcXC7b/qVUB1keofjtZA==} + /@babel/template@7.25.9: + resolution: {integrity: sha512-9DGttpmPvIxBb/2uwpVo3dqJ+O6RooAFOS+lB+xDqoE2PVCE8nfoHMdZLpfCQRLwvohzXISPZcgxt80xLfsuwg==} engines: {node: '>=6.9.0'} dependencies: - '@babel/code-frame': 7.25.7 - '@babel/parser': 7.25.8 - '@babel/types': 7.25.8 + '@babel/code-frame': 7.25.9 + '@babel/parser': 7.25.9 + '@babel/types': 7.25.9 - /@babel/traverse@7.25.7: - resolution: {integrity: sha512-jatJPT1Zjqvh/1FyJs6qAHL+Dzb7sTb+xr7Q+gM1b+1oBsMsQQ4FkVKb6dFlJvLlVssqkRzV05Jzervt9yhnzg==} + /@babel/traverse@7.25.9: + resolution: {integrity: sha512-ZCuvfwOwlz/bawvAuvcj8rrithP2/N55Tzz342AkTvq4qaWbGfmCk/tKhNaV2cthijKrPAA8SRJV5WWe7IBMJw==} engines: {node: '>=6.9.0'} dependencies: - '@babel/code-frame': 7.25.7 - '@babel/generator': 7.25.7 - '@babel/parser': 7.25.8 - '@babel/template': 7.25.7 - '@babel/types': 7.25.8 + '@babel/code-frame': 7.25.9 + '@babel/generator': 7.25.9 + '@babel/parser': 7.25.9 + '@babel/template': 7.25.9 + '@babel/types': 7.25.9 debug: 4.3.7(supports-color@8.1.1) globals: 11.12.0 transitivePeerDependencies: - supports-color - /@babel/types@7.25.8: - resolution: {integrity: sha512-JWtuCu8VQsMladxVz/P4HzHUGCAwpuqacmowgXFs5XjxIgKuNjnLokQzuVjlTvIzODaDmpjT3oxcC48vyk9EWg==} + /@babel/types@7.25.9: + resolution: {integrity: sha512-OwS2CM5KocvQ/k7dFJa8i5bNGJP0hXWfVCfDkqRFP1IreH1JDC7wG6eCYCi0+McbfT8OR/kNqsI0UU0xP9H6PQ==} engines: {node: '>=6.9.0'} dependencies: - '@babel/helper-string-parser': 7.25.7 - '@babel/helper-validator-identifier': 7.25.7 - to-fast-properties: 2.0.0 + '@babel/helper-string-parser': 7.25.9 + '@babel/helper-validator-identifier': 7.25.9 /@bany/curl-to-json@1.2.8: resolution: {integrity: sha512-hPt9KUM2sGZ5Ojx3O9utjzUgjRZI3CZPAlLf+cRY9EUzVs7tWt1OpA0bhEUTX2PEEkOeyZ6sC0tAQMOHh9ld+Q==} @@ -2715,7 +2697,7 @@ packages: resolution: {integrity: sha512-iJ91xlvRnnrJnELTp4eJJEOPjgpF3NOh4qeQehM6Ugiz9gJPRZ2t+TsXun6E3AMN4hScZKjqVXl0TX+C7AB3ZQ==} hasBin: true dependencies: - '@babel/runtime': 7.25.7 + '@babel/runtime': 7.25.9 '@changesets/apply-release-plan': 7.0.5 '@changesets/assemble-release-plan': 6.0.4 '@changesets/changelog-git': 0.2.0 @@ -2772,7 +2754,7 @@ packages: dependencies: '@changesets/types': 6.0.0 '@manypkg/get-packages': 1.1.3 - picocolors: 1.1.0 + picocolors: 1.1.1 semver: 7.6.3 dev: true @@ -2804,7 +2786,7 @@ packages: /@changesets/logger@0.1.1: resolution: {integrity: sha512-OQtR36ZlnuTxKqoW4Sv6x5YIhOmClRd5pWsjZsddYxpWs517R0HkyiefQPIytCVh4ZcC5x9XaG8KTdd5iRQUfg==} dependencies: - picocolors: 1.1.0 + picocolors: 1.1.1 dev: true /@changesets/parse@0.4.0: @@ -2832,7 +2814,7 @@ packages: '@changesets/types': 6.0.0 fs-extra: 7.0.1 p-filter: 2.1.0 - picocolors: 1.1.0 + picocolors: 1.1.1 dev: true /@changesets/should-skip-package@0.1.1: @@ -2868,7 +2850,7 @@ packages: /@clack/core@0.3.4: resolution: {integrity: sha512-H4hxZDXgHtWTwV3RAVenqcC4VbJZNegbBjlPvzOzCouXtS2y3sDvlO3IsbrPNWuLWPPlYVYPghQdSF64683Ldw==} dependencies: - picocolors: 1.1.0 + picocolors: 1.1.1 sisteransi: 1.0.5 dev: true @@ -2876,7 +2858,7 @@ packages: resolution: {integrity: sha512-0MhX9/B4iL6Re04jPrttDm+BsP8y6mS7byuv0BvXgdXhbV5PdlsHt55dvNsuBCPZ7xq1oTAOOuotR9NFbQyMSA==} dependencies: '@clack/core': 0.3.4 - picocolors: 1.1.0 + picocolors: 1.1.1 sisteransi: 1.0.5 dev: true bundledDependencies: @@ -2941,7 +2923,7 @@ packages: '@clerk/clerk-sdk-node': 4.13.12(react@18.3.1) '@clerk/shared': 1.4.0(react@18.3.1) '@clerk/types': 3.63.0 - next: 14.2.10(@babel/core@7.25.8)(@opentelemetry/api@1.4.1)(react-dom@18.3.1)(react@18.3.1) + next: 14.2.10(@babel/core@7.25.9)(@opentelemetry/api@1.4.1)(react-dom@18.3.1)(react@18.3.1) path-to-regexp: 6.2.1 react: 18.3.1 react-dom: 18.3.1(react@18.3.1) @@ -3015,7 +2997,7 @@ packages: esbuild: 0.17.19 miniflare: 3.20240524.2 semver: 7.6.3 - vitest: 1.5.3(@types/node@20.14.9) + vitest: 1.5.3(@types/node@20.14.9)(@vitest/ui@1.6.0) wrangler: 3.59.0(@cloudflare/workers-types@4.20240603.0) zod: 3.23.8 transitivePeerDependencies: @@ -3040,7 +3022,7 @@ packages: esbuild: 0.17.19 miniflare: 3.20240524.2 semver: 7.6.3 - vitest: 1.6.0(@vitest/ui@1.6.0) + vitest: 1.6.0(@types/node@20.14.9)(@vitest/ui@1.6.0) wrangler: 3.59.0(@cloudflare/workers-types@4.20240603.0) zod: 3.23.8 transitivePeerDependencies: @@ -3177,7 +3159,7 @@ packages: '@commitlint/types': 19.5.0 chalk: 5.3.0 cosmiconfig: 9.0.0(typescript@5.5.3) - cosmiconfig-typescript-loader: 5.0.0(@types/node@20.14.9)(cosmiconfig@9.0.0)(typescript@5.5.3) + cosmiconfig-typescript-loader: 5.1.0(@types/node@20.14.9)(cosmiconfig@9.0.0)(typescript@5.5.3) lodash.isplainobject: 4.0.6 lodash.merge: 4.6.2 lodash.uniq: 4.5.0 @@ -3224,7 +3206,7 @@ packages: serialize-javascript: 6.0.2 tinyglobby: 0.2.9 typescript: 5.5.3 - yaml: 2.5.1 + yaml: 2.6.0 zod: 3.23.8 dev: true @@ -3236,7 +3218,7 @@ packages: '@content-collections/core': 0.7.2(typescript@5.5.3) dev: true - /@content-collections/mdx@0.1.3(@content-collections/core@0.7.2)(react-dom@18.3.1)(react@18.3.1): + /@content-collections/mdx@0.1.3(@content-collections/core@0.7.2)(acorn@8.13.0)(react-dom@18.3.1)(react@18.3.1): resolution: {integrity: sha512-YnZVCppJsA3FgPMtctyL3RqcrLFbGWoi3D8xfDSdx9Yuu9HdIQjgAhrLo+XNQLngTeHaRUBNJfwhYEfAxV84PA==} peerDependencies: '@content-collections/core': 0.x @@ -3245,11 +3227,12 @@ packages: dependencies: '@content-collections/core': 0.7.2(typescript@5.5.3) esbuild: 0.19.12 - mdx-bundler: 10.0.3(esbuild@0.19.12) + mdx-bundler: 10.0.3(acorn@8.13.0)(esbuild@0.19.12) react: 18.3.1 react-dom: 18.3.1(react@18.3.1) unified: 11.0.5 transitivePeerDependencies: + - acorn - supports-color dev: true @@ -3261,7 +3244,7 @@ packages: dependencies: '@content-collections/core': 0.7.2(typescript@5.5.3) '@content-collections/integrations': 0.1.1(@content-collections/core@0.7.2) - next: 14.2.10(@babel/core@7.25.8)(@opentelemetry/api@1.4.1)(react-dom@18.3.1)(react@18.3.1) + next: 14.2.10(@babel/core@7.25.9)(@opentelemetry/api@1.4.1)(react-dom@18.3.1)(react@18.3.1) dev: true /@cspotcode/source-map-support@0.8.1: @@ -3285,11 +3268,11 @@ packages: resolution: {integrity: sha512-AHy0vjc+n/4w/8Mif+w86qpppHuF3AyXbcWW+R/W7GNA3F5/p2nuhlkCJaTXSLZheB4l1rtHzOfr9A7NwoR/Zg==} dev: true - /@emnapi/runtime@1.3.0: - resolution: {integrity: sha512-XMBySMuNZs3DM96xcJmLW4EfGnf+uGmFNjzpehMjuX5PLB5j87ar2Zc4e3PVeZ3I5g3tYtAqskB28manlF69Zw==} + /@emnapi/runtime@1.3.1: + resolution: {integrity: sha512-kEBmG8KyqtxJZv+ygbEim+KCGtIq1fC22Ms3S4ziXmYKm8uyoLX0MHONVKwp+9opg390VaKRNt4a7A9NwmpNhw==} requiresBuild: true dependencies: - tslib: 2.7.0 + tslib: 2.8.0 optional: true /@emotion/is-prop-valid@0.8.8: @@ -4786,13 +4769,13 @@ packages: requiresBuild: true optional: true - /@eslint-community/eslint-utils@4.4.0(eslint@9.12.0): + /@eslint-community/eslint-utils@4.4.0(eslint@9.13.0): resolution: {integrity: sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} peerDependencies: eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 dependencies: - eslint: 9.12.0 + eslint: 9.13.0 eslint-visitor-keys: 3.4.3 dev: false @@ -4812,8 +4795,8 @@ packages: - supports-color dev: false - /@eslint/core@0.6.0: - resolution: {integrity: sha512-8I2Q8ykA4J0x0o7cg67FPVnehcqWTBehu/lmY+bolPFHGjh49YzGBMXTvpqVgEbBdvNCSxj6iFgiIyHzf03lzg==} + /@eslint/core@0.7.0: + resolution: {integrity: sha512-xp5Jirz5DyPYlPiKat8jaq0EmYvDXKKpzTbxXMpT9eqlRJkRKIz9AGMdlvYjih+im+QlhWrpvVjl8IPC/lHlUw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} dev: false @@ -4834,8 +4817,8 @@ packages: - supports-color dev: false - /@eslint/js@9.12.0: - resolution: {integrity: sha512-eohesHH8WFRUprDNyEREgqP6beG6htMeUYeCpkEgBCieCMme5r9zFWjzAJp//9S+Kub4rqE+jXe9Cp1a7IYIIA==} + /@eslint/js@9.13.0: + resolution: {integrity: sha512-IFLyoY4d72Z5y/6o/BazFBezupzI/taV8sGumxTAVw3lXG9A6md1Dc34T9s1FoD/an9pJH8RHbAxsaEbBed9lA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} dev: false @@ -4844,8 +4827,8 @@ packages: engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} dev: false - /@eslint/plugin-kit@0.2.0: - resolution: {integrity: sha512-vH9PiIMMwvhCx31Af3HiGzsVNULDbyVkHXwlemn/B0TFj/00ho3y55efXrUZTfQipxoHC5u4xq6zblww1zm1Ig==} + /@eslint/plugin-kit@0.2.1: + resolution: {integrity: sha512-HFZ4Mp26nbWk9d/BpvP0YNL6W4UoZF0VFcTw/aPPA8RpOxeFQgK+ClABGgAUXs9Y/RGX/l1vOmrqz1MQt9MNuw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} dependencies: levn: 0.4.1 @@ -4888,10 +4871,10 @@ packages: /@floating-ui/utils@0.2.8: resolution: {integrity: sha512-kym7SodPp8/wloecOpcmSnWJsK7M0E5Wg8UcFA+uO4B9s5d0ywXOEro/8HM9x0rW+TljRzul/14UYz3TleT3ig==} - /@formatjs/intl-localematcher@0.5.4: - resolution: {integrity: sha512-zTwEpWOzZ2CiKcB93BLngUX59hQkuZjT2+SAQEscSm52peDW/getsawMcWF1rGRpMCX6D7nSJA3CzJ8gn13N/g==} + /@formatjs/intl-localematcher@0.5.5: + resolution: {integrity: sha512-t5tOGMgZ/i5+ALl2/offNqAQq/lfUnKLEw0mXQI4N4bqpedhrSE+fyKLpwnd22sK0dif6AV+ufQcTsKShB9J1g==} dependencies: - tslib: 2.7.0 + tslib: 2.8.0 dev: false /@google-cloud/precise-date@4.0.0: @@ -5130,7 +5113,7 @@ packages: cpu: [wasm32] requiresBuild: true dependencies: - '@emnapi/runtime': 1.3.0 + '@emnapi/runtime': 1.3.1 optional: true /@img/sharp-win32-ia32@0.33.4: @@ -5164,7 +5147,7 @@ packages: '@inquirer/figures': 1.0.7 '@inquirer/type': 2.0.0 '@types/mute-stream': 0.0.4 - '@types/node': 22.7.5 + '@types/node': 22.7.9 '@types/wrap-ansi': 3.0.0 ansi-escapes: 4.3.2 cli-width: 4.1.0 @@ -5381,7 +5364,7 @@ packages: /@manypkg/find-root@1.1.0: resolution: {integrity: sha512-mki5uBvhHzO8kYYix/WRy2WX8S3B5wdVSc9D6KcU5lQNglP2yt58/VfLuAK49glRXChosY8ap2oJ1qgma3GUVA==} dependencies: - '@babel/runtime': 7.25.7 + '@babel/runtime': 7.25.9 '@types/node': 12.20.55 find-up: 4.1.0 fs-extra: 8.1.0 @@ -5390,7 +5373,7 @@ packages: /@manypkg/get-packages@1.1.3: resolution: {integrity: sha512-fo+QhuU3qE/2TQMQmbVMqaQ6EWbMhi4ABWP+O4AM1NqPBuy0OrApV5LO6BrrgnhtAHS2NH6RrVk9OL181tTi8A==} dependencies: - '@babel/runtime': 7.25.7 + '@babel/runtime': 7.25.9 '@changesets/types': 4.1.0 '@manypkg/find-root': 1.1.0 fs-extra: 8.1.0 @@ -5398,17 +5381,19 @@ packages: read-yaml-file: 1.1.0 dev: true - /@mdx-js/esbuild@3.0.1(esbuild@0.19.12): - resolution: {integrity: sha512-+KZbCKcRjFtRD6qzD+c70Vq/VPVt5LHFsOshNcsdcONkaLTCSjmM7/uj71i3BcP+170f+P4DwVEMtqR/k0t5aw==} + /@mdx-js/esbuild@3.1.0(acorn@8.13.0)(esbuild@0.19.12): + resolution: {integrity: sha512-Jk42xUb1SEJxh6n2GBAtJjQISFIZccjz8XVEsHVhrlvZJAJziIxR9KyaFF6nTeTB/jCAFQGDgO7+oMRH/ApRsg==} peerDependencies: esbuild: '>=0.14.0' dependencies: - '@mdx-js/mdx': 3.0.1 + '@mdx-js/mdx': 3.1.0(acorn@8.13.0) '@types/unist': 3.0.3 esbuild: 0.19.12 + source-map: 0.7.4 vfile: 6.0.3 vfile-message: 4.0.2 transitivePeerDependencies: + - acorn - supports-color dev: true @@ -5435,8 +5420,8 @@ packages: transitivePeerDependencies: - supports-color - /@mdx-js/mdx@3.0.1: - resolution: {integrity: sha512-eIQ4QTrOWyL3LWEe/bu6Taqzq2HQvHcyTMaOrI95P2/LmJE7AsfPfgJGuFLPVqBUE1BC1rik3VIhU+s9u72arA==} + /@mdx-js/mdx@3.1.0(acorn@8.13.0): + resolution: {integrity: sha512-/QxEhPAvGwbQmy1Px8F899L5Uc2KZ6JtXwlCgJmjSTBedwOZkByYcBG4GceIGPXRDsmfxhHazuS+hlOShRLeDw==} dependencies: '@types/estree': 1.0.6 '@types/estree-jsx': 1.0.5 @@ -5444,15 +5429,16 @@ packages: '@types/mdx': 2.0.13 collapse-white-space: 2.1.0 devlop: 1.1.0 - estree-util-build-jsx: 3.0.1 estree-util-is-identifier-name: 3.0.0 - estree-util-to-js: 2.0.0 + estree-util-scope: 1.0.0 estree-walker: 3.0.3 - hast-util-to-estree: 3.1.0 - hast-util-to-jsx-runtime: 2.3.0 + hast-util-to-jsx-runtime: 2.3.2 markdown-extensions: 2.0.0 - periscopic: 3.1.0 - remark-mdx: 3.0.1 + recma-build-jsx: 1.0.0 + recma-jsx: 1.0.0(acorn@8.13.0) + recma-stringify: 1.0.0 + rehype-recma: 1.0.0 + remark-mdx: 3.1.0 remark-parse: 11.0.0 remark-rehype: 11.1.1 source-map: 0.7.4 @@ -5462,6 +5448,7 @@ packages: unist-util-visit: 5.0.0 vfile: 6.0.3 transitivePeerDependencies: + - acorn - supports-color /@mdx-js/react@2.3.0(react@18.3.1): @@ -5490,9 +5477,9 @@ packages: resolution: {integrity: sha512-UR1VR/GorYt5bRKBtNeS2ZWj6PZk8RVpwV7WDjWmdbLqLAYv4JlRnkPAImZbJR5R50jsHpopmcqqm4mcbyZwiw==} hasBin: true dependencies: - '@babel/core': 7.25.8 - '@babel/helper-module-imports': 7.25.7 - '@babel/types': 7.25.8 + '@babel/core': 7.25.9 + '@babel/helper-module-imports': 7.25.9 + '@babel/types': 7.25.9 '@radix-ui/react-dialog': 1.1.2(@types/react-dom@18.3.0)(@types/react@18.3.11)(react-dom@18.3.1)(react@18.3.1) '@radix-ui/react-tooltip': 1.1.3(react-dom@18.3.1)(react@18.3.1) '@rollup/pluginutils': 5.1.2 @@ -5556,8 +5543,8 @@ packages: '@mintlify/models': 0.0.104 '@mintlify/validation': 0.1.166 '@sindresorhus/slugify': 2.2.1 - acorn: 8.12.1 - acorn-jsx: 5.3.2(acorn@8.12.1) + acorn: 8.13.0 + acorn-jsx: 5.3.2(acorn@8.13.0) esast-util-from-js: 2.0.1 estree-util-to-js: 2.0.0 estree-walker: 3.0.3 @@ -5985,7 +5972,7 @@ packages: chalk: 4.1.2 strip-ansi: 6.0.1 supports-color: 8.1.1 - tslib: 2.7.0 + tslib: 2.8.0 dev: true /@oclif/core@1.26.2: @@ -6017,7 +6004,7 @@ packages: strip-ansi: 6.0.1 supports-color: 8.1.1 supports-hyperlinks: 2.3.0 - tslib: 2.7.0 + tslib: 2.8.0 widest-line: 3.1.0 wrap-ansi: 7.0.0 dev: true @@ -6051,7 +6038,7 @@ packages: supports-color: 8.1.1 supports-hyperlinks: 2.3.0 ts-node: 10.9.2(@types/node@20.14.9)(typescript@5.5.3) - tslib: 2.7.0 + tslib: 2.8.0 widest-line: 3.1.0 wordwrap: 1.0.0 wrap-ansi: 7.0.0 @@ -6062,8 +6049,8 @@ packages: - typescript dev: true - /@oclif/core@4.0.27: - resolution: {integrity: sha512-9j92jHr6k2tjQ6/mIwNi46Gqw+qbPFQ02mxT5T8/nxO2fgsPL3qL0kb9SR1il5AVfqpgLIG3uLUcw87rgaioUg==} + /@oclif/core@4.0.30: + resolution: {integrity: sha512-Ak3OUdOcoovIRWZOT6oC5JhZgyJD90uWX/7HjSofn+C4LEmHxxfiyu04a73dwnezfzqDu9jEXfd2mQOOC54KZw==} engines: {node: '>=18.0.0'} dependencies: ansi-escapes: 4.3.2 @@ -6116,7 +6103,7 @@ packages: resolution: {integrity: sha512-p30fo3JPtbOqTJOX9A/8qKV/14XWt8xFgG/goVfIkuKBAO+cdY78ag8pYatlpzsYzJhO27X1MFn0WkkPWo36Ww==} engines: {node: '>=18.0.0'} dependencies: - '@oclif/core': 4.0.27 + '@oclif/core': 4.0.30 ansis: 3.3.2 debug: 4.3.7(supports-color@8.1.1) npm: 10.9.0 @@ -6939,14 +6926,14 @@ packages: dependencies: asn1js: 3.0.5 pvtsutils: 1.3.5 - tslib: 2.7.0 + tslib: 2.8.0 dev: false /@peculiar/json-schema@1.1.12: resolution: {integrity: sha512-coUfuoMeIB7B8/NMekxaDzLhaYmp0HZNPEjYRm9goRou8UZIC3z21s0sL9AWoCw4EG876QyO3kYrc61WNF9B/w==} engines: {node: '>=8.0.0'} dependencies: - tslib: 2.7.0 + tslib: 2.4.1 dev: false /@peculiar/webcrypto@1.4.1: @@ -6956,7 +6943,7 @@ packages: '@peculiar/asn1-schema': 2.3.13 '@peculiar/json-schema': 1.1.12 pvtsutils: 1.3.5 - tslib: 2.7.0 + tslib: 2.4.1 webcrypto-core: 1.8.1 dev: false @@ -6976,20 +6963,20 @@ packages: /@probe.gl/env@3.6.0: resolution: {integrity: sha512-4tTZYUg/8BICC3Yyb9rOeoKeijKbZHRXBEKObrfPmX4sQmYB15ZOUpoVBhAyJkOYVAM8EkPci6Uw5dLCwx2BEQ==} dependencies: - '@babel/runtime': 7.25.7 + '@babel/runtime': 7.25.9 dev: false /@probe.gl/log@3.6.0: resolution: {integrity: sha512-hjpyenpEvOdowgZ1qMeCJxfRD4JkKdlXz0RC14m42Un62NtOT+GpWyKA4LssT0+xyLULCByRAtG2fzZorpIAcA==} dependencies: - '@babel/runtime': 7.25.7 + '@babel/runtime': 7.25.9 '@probe.gl/env': 3.6.0 dev: false /@probe.gl/stats@3.6.0: resolution: {integrity: sha512-JdALQXB44OP4kUBN/UrQgzbJe4qokbVF4Y8lkIA8iVCFnjVowWIgkD/z/0QO65yELT54tTrtepw1jScjKB+rhQ==} dependencies: - '@babel/runtime': 7.25.7 + '@babel/runtime': 7.25.9 dev: false /@protobufjs/aspromise@1.1.2: @@ -7065,7 +7052,7 @@ packages: /@radix-ui/number@1.0.1: resolution: {integrity: sha512-T5gIdVO2mmPW3NNhjNgEP3cqMXjXL9UbO0BzWcXfvdBs+BohbQxvd/K5hSVKmn9/lbTdsQVKbUcP5WLCwvUbBg==} dependencies: - '@babel/runtime': 7.25.7 + '@babel/runtime': 7.25.9 dev: false /@radix-ui/number@1.1.0: @@ -7075,13 +7062,13 @@ packages: /@radix-ui/primitive@1.0.0: resolution: {integrity: sha512-3e7rn8FDMin4CgeL7Z/49smCA3rFYY3Ha2rUQ7HRWFadS5iCRw08ZgVT1LaNTCNqgvrUiyczLflrVrF0SRQtNA==} dependencies: - '@babel/runtime': 7.25.7 + '@babel/runtime': 7.25.9 dev: true /@radix-ui/primitive@1.0.1: resolution: {integrity: sha512-yQ8oGX2GVsEYMWGxcovu1uGWPCxV5BFfeeYxqPmuAzUyLT9qmaMXSAhXpb0WrspIeqYzdJpkh2vHModJPgRIaw==} dependencies: - '@babel/runtime': 7.25.7 + '@babel/runtime': 7.25.9 dev: false /@radix-ui/primitive@1.1.0: @@ -7156,7 +7143,7 @@ packages: '@types/react-dom': optional: true dependencies: - '@babel/runtime': 7.25.7 + '@babel/runtime': 7.25.9 '@radix-ui/primitive': 1.0.1 '@radix-ui/react-compose-refs': 1.0.1(@types/react@18.3.11)(react@18.3.1) '@radix-ui/react-context': 1.0.1(@types/react@18.3.11)(react@18.3.1) @@ -7182,7 +7169,7 @@ packages: '@types/react-dom': optional: true dependencies: - '@babel/runtime': 7.25.7 + '@babel/runtime': 7.25.9 '@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.3.0)(@types/react@18.3.11)(react-dom@18.3.1)(react@18.3.1) '@types/react': 18.3.11 '@types/react-dom': 18.3.0 @@ -7222,7 +7209,7 @@ packages: '@types/react-dom': optional: true dependencies: - '@babel/runtime': 7.25.7 + '@babel/runtime': 7.25.9 '@radix-ui/react-context': 1.0.1(@types/react@18.3.11)(react@18.3.1) '@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.3.0)(@types/react@18.3.11)(react-dom@18.3.1)(react@18.3.1) '@radix-ui/react-use-callback-ref': 1.0.1(@types/react@18.3.11)(react@18.3.1) @@ -7246,7 +7233,7 @@ packages: '@types/react-dom': optional: true dependencies: - '@babel/runtime': 7.25.7 + '@babel/runtime': 7.25.9 '@radix-ui/primitive': 1.0.1 '@radix-ui/react-compose-refs': 1.0.1(@types/react@18.3.11)(react@18.3.1) '@radix-ui/react-context': 1.0.1(@types/react@18.3.11)(react@18.3.1) @@ -7274,7 +7261,7 @@ packages: '@types/react-dom': optional: true dependencies: - '@babel/runtime': 7.25.7 + '@babel/runtime': 7.25.9 '@radix-ui/primitive': 1.0.1 '@radix-ui/react-compose-refs': 1.0.1(@types/react@18.3.11)(react@18.3.1) '@radix-ui/react-context': 1.0.1(@types/react@18.3.11)(react@18.3.1) @@ -7356,7 +7343,7 @@ packages: '@types/react-dom': optional: true dependencies: - '@babel/runtime': 7.25.7 + '@babel/runtime': 7.25.9 '@radix-ui/react-compose-refs': 1.0.1(@types/react@18.3.11)(react@18.3.1) '@radix-ui/react-context': 1.0.1(@types/react@18.3.11)(react@18.3.1) '@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.3.0)(@types/react@18.3.11)(react-dom@18.3.1)(react@18.3.1) @@ -7395,7 +7382,7 @@ packages: peerDependencies: react: ^16.8 || ^17.0 || ^18.0 dependencies: - '@babel/runtime': 7.25.7 + '@babel/runtime': 7.25.9 react: 18.3.1 dev: true @@ -7408,7 +7395,7 @@ packages: '@types/react': optional: true dependencies: - '@babel/runtime': 7.25.7 + '@babel/runtime': 7.25.9 '@types/react': 18.3.11 react: 18.3.1 dev: false @@ -7430,7 +7417,7 @@ packages: peerDependencies: react: ^16.8 || ^17.0 || ^18.0 dependencies: - '@babel/runtime': 7.25.7 + '@babel/runtime': 7.25.9 react: 18.3.1 dev: true @@ -7443,7 +7430,7 @@ packages: '@types/react': optional: true dependencies: - '@babel/runtime': 7.25.7 + '@babel/runtime': 7.25.9 '@types/react': 18.3.11 react: 18.3.1 dev: false @@ -7478,7 +7465,7 @@ packages: react: ^16.8 || ^17.0 || ^18.0 react-dom: ^16.8 || ^17.0 || ^18.0 dependencies: - '@babel/runtime': 7.25.7 + '@babel/runtime': 7.25.9 '@radix-ui/primitive': 1.0.0 '@radix-ui/react-compose-refs': 1.0.0(react@18.3.1) '@radix-ui/react-context': 1.0.0(react@18.3.1) @@ -7512,7 +7499,7 @@ packages: '@types/react-dom': optional: true dependencies: - '@babel/runtime': 7.25.7 + '@babel/runtime': 7.25.9 '@radix-ui/primitive': 1.0.1 '@radix-ui/react-compose-refs': 1.0.1(@types/react@18.3.11)(react@18.3.1) '@radix-ui/react-context': 1.0.1(@types/react@18.3.11)(react@18.3.1) @@ -7574,7 +7561,7 @@ packages: '@types/react': optional: true dependencies: - '@babel/runtime': 7.25.7 + '@babel/runtime': 7.25.9 '@types/react': 18.3.11 react: 18.3.1 dev: false @@ -7598,7 +7585,7 @@ packages: react: ^16.8 || ^17.0 || ^18.0 react-dom: ^16.8 || ^17.0 || ^18.0 dependencies: - '@babel/runtime': 7.25.7 + '@babel/runtime': 7.25.9 '@radix-ui/primitive': 1.0.0 '@radix-ui/react-compose-refs': 1.0.0(react@18.3.1) '@radix-ui/react-primitive': 1.0.0(react-dom@18.3.1)(react@18.3.1) @@ -7621,7 +7608,7 @@ packages: '@types/react-dom': optional: true dependencies: - '@babel/runtime': 7.25.7 + '@babel/runtime': 7.25.9 '@radix-ui/primitive': 1.0.1 '@radix-ui/react-compose-refs': 1.0.1(@types/react@18.3.11)(react@18.3.1) '@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.3.0)(@types/react@18.3.11)(react-dom@18.3.1)(react@18.3.1) @@ -7646,7 +7633,7 @@ packages: '@types/react-dom': optional: true dependencies: - '@babel/runtime': 7.25.7 + '@babel/runtime': 7.25.9 '@radix-ui/primitive': 1.0.1 '@radix-ui/react-compose-refs': 1.0.1(@types/react@18.3.11)(react@18.3.1) '@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.3.0)(@types/react@18.3.11)(react-dom@18.3.1)(react@18.3.1) @@ -7736,7 +7723,7 @@ packages: peerDependencies: react: ^16.8 || ^17.0 || ^18.0 dependencies: - '@babel/runtime': 7.25.7 + '@babel/runtime': 7.25.9 react: 18.3.1 dev: true @@ -7749,7 +7736,7 @@ packages: '@types/react': optional: true dependencies: - '@babel/runtime': 7.25.7 + '@babel/runtime': 7.25.9 '@types/react': 18.3.11 react: 18.3.1 dev: false @@ -7785,7 +7772,7 @@ packages: react: ^16.8 || ^17.0 || ^18.0 react-dom: ^16.8 || ^17.0 || ^18.0 dependencies: - '@babel/runtime': 7.25.7 + '@babel/runtime': 7.25.9 '@radix-ui/react-compose-refs': 1.0.0(react@18.3.1) '@radix-ui/react-primitive': 1.0.0(react-dom@18.3.1)(react@18.3.1) '@radix-ui/react-use-callback-ref': 1.0.0(react@18.3.1) @@ -7806,7 +7793,7 @@ packages: '@types/react-dom': optional: true dependencies: - '@babel/runtime': 7.25.7 + '@babel/runtime': 7.25.9 '@radix-ui/react-compose-refs': 1.0.1(@types/react@18.3.11)(react@18.3.1) '@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.3.0)(@types/react@18.3.11)(react-dom@18.3.1)(react@18.3.1) '@radix-ui/react-use-callback-ref': 1.0.1(@types/react@18.3.11)(react@18.3.1) @@ -7850,7 +7837,7 @@ packages: peerDependencies: react: ^16.8 || ^17.0 || ^18.0 dependencies: - '@babel/runtime': 7.25.7 + '@babel/runtime': 7.25.9 '@radix-ui/react-use-layout-effect': 1.0.0(react@18.3.1) react: 18.3.1 dev: true @@ -7864,7 +7851,7 @@ packages: '@types/react': optional: true dependencies: - '@babel/runtime': 7.25.7 + '@babel/runtime': 7.25.9 '@radix-ui/react-use-layout-effect': 1.0.1(@types/react@18.3.11)(react@18.3.1) '@types/react': 18.3.11 react: 18.3.1 @@ -7896,7 +7883,7 @@ packages: '@types/react-dom': optional: true dependencies: - '@babel/runtime': 7.25.7 + '@babel/runtime': 7.25.9 '@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.3.0)(@types/react@18.3.11)(react-dom@18.3.1)(react@18.3.1) '@types/react': 18.3.11 '@types/react-dom': 18.3.0 @@ -7954,7 +7941,7 @@ packages: '@types/react-dom': optional: true dependencies: - '@babel/runtime': 7.25.7 + '@babel/runtime': 7.25.9 '@radix-ui/primitive': 1.0.1 '@radix-ui/react-compose-refs': 1.0.1(@types/react@18.3.11)(react@18.3.1) '@radix-ui/react-context': 1.0.1(@types/react@18.3.11)(react@18.3.1) @@ -8023,7 +8010,7 @@ packages: '@types/react-dom': optional: true dependencies: - '@babel/runtime': 7.25.7 + '@babel/runtime': 7.25.9 '@floating-ui/react-dom': 2.1.2(react-dom@18.3.1)(react@18.3.1) '@radix-ui/react-arrow': 1.0.3(@types/react-dom@18.3.0)(@types/react@18.3.11)(react-dom@18.3.1)(react@18.3.1) '@radix-ui/react-compose-refs': 1.0.1(@types/react@18.3.11)(react@18.3.1) @@ -8053,7 +8040,7 @@ packages: '@types/react-dom': optional: true dependencies: - '@babel/runtime': 7.25.7 + '@babel/runtime': 7.25.9 '@floating-ui/react-dom': 2.1.2(react-dom@18.3.1)(react@18.3.1) '@radix-ui/react-arrow': 1.0.3(@types/react-dom@18.3.0)(@types/react@18.3.11)(react-dom@18.3.1)(react@18.3.1) '@radix-ui/react-compose-refs': 1.0.1(@types/react@18.3.11)(react@18.3.1) @@ -8104,7 +8091,7 @@ packages: react: ^16.8 || ^17.0 || ^18.0 react-dom: ^16.8 || ^17.0 || ^18.0 dependencies: - '@babel/runtime': 7.25.7 + '@babel/runtime': 7.25.9 '@radix-ui/react-primitive': 1.0.0(react-dom@18.3.1)(react@18.3.1) react: 18.3.1 react-dom: 18.3.1(react@18.3.1) @@ -8123,7 +8110,7 @@ packages: '@types/react-dom': optional: true dependencies: - '@babel/runtime': 7.25.7 + '@babel/runtime': 7.25.9 '@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.3.0)(@types/react@18.3.11)(react-dom@18.3.1)(react@18.3.1) '@types/react': 18.3.11 '@types/react-dom': 18.3.0 @@ -8144,7 +8131,7 @@ packages: '@types/react-dom': optional: true dependencies: - '@babel/runtime': 7.25.7 + '@babel/runtime': 7.25.9 '@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.3.0)(@types/react@18.3.11)(react-dom@18.3.1)(react@18.3.1) '@types/react': 18.3.11 '@types/react-dom': 18.3.0 @@ -8199,7 +8186,7 @@ packages: react: ^16.8 || ^17.0 || ^18.0 react-dom: ^16.8 || ^17.0 || ^18.0 dependencies: - '@babel/runtime': 7.25.7 + '@babel/runtime': 7.25.9 '@radix-ui/react-compose-refs': 1.0.0(react@18.3.1) '@radix-ui/react-use-layout-effect': 1.0.0(react@18.3.1) react: 18.3.1 @@ -8219,7 +8206,7 @@ packages: '@types/react-dom': optional: true dependencies: - '@babel/runtime': 7.25.7 + '@babel/runtime': 7.25.9 '@radix-ui/react-compose-refs': 1.0.1(@types/react@18.3.11)(react@18.3.1) '@radix-ui/react-use-layout-effect': 1.0.1(@types/react@18.3.11)(react@18.3.1) '@types/react': 18.3.11 @@ -8275,7 +8262,7 @@ packages: react: ^16.8 || ^17.0 || ^18.0 react-dom: ^16.8 || ^17.0 || ^18.0 dependencies: - '@babel/runtime': 7.25.7 + '@babel/runtime': 7.25.9 '@radix-ui/react-slot': 1.0.0(react@18.3.1) react: 18.3.1 react-dom: 18.3.1(react@18.3.1) @@ -8294,7 +8281,7 @@ packages: '@types/react-dom': optional: true dependencies: - '@babel/runtime': 7.25.7 + '@babel/runtime': 7.25.9 '@radix-ui/react-slot': 1.0.2(@types/react@18.3.11)(react@18.3.1) '@types/react': 18.3.11 '@types/react-dom': 18.3.0 @@ -8334,7 +8321,7 @@ packages: '@types/react-dom': optional: true dependencies: - '@babel/runtime': 7.25.7 + '@babel/runtime': 7.25.9 '@radix-ui/react-context': 1.0.1(@types/react@18.3.11)(react@18.3.1) '@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.3.0)(@types/react@18.3.11)(react-dom@18.3.1)(react@18.3.1) '@types/react': 18.3.11 @@ -8356,7 +8343,7 @@ packages: '@types/react-dom': optional: true dependencies: - '@babel/runtime': 7.25.7 + '@babel/runtime': 7.25.9 '@radix-ui/primitive': 1.0.1 '@radix-ui/react-collection': 1.0.3(@types/react-dom@18.3.0)(@types/react@18.3.11)(react-dom@18.3.1)(react@18.3.1) '@radix-ui/react-compose-refs': 1.0.1(@types/react@18.3.11)(react@18.3.1) @@ -8413,7 +8400,7 @@ packages: '@types/react-dom': optional: true dependencies: - '@babel/runtime': 7.25.7 + '@babel/runtime': 7.25.9 '@radix-ui/number': 1.0.1 '@radix-ui/primitive': 1.0.1 '@radix-ui/react-compose-refs': 1.0.1(@types/react@18.3.11)(react@18.3.1) @@ -8470,7 +8457,7 @@ packages: '@types/react-dom': optional: true dependencies: - '@babel/runtime': 7.25.7 + '@babel/runtime': 7.25.9 '@radix-ui/number': 1.0.1 '@radix-ui/primitive': 1.0.1 '@radix-ui/react-collection': 1.0.3(@types/react-dom@18.3.0)(@types/react@18.3.11)(react-dom@18.3.1)(react@18.3.1) @@ -8511,7 +8498,7 @@ packages: '@types/react-dom': optional: true dependencies: - '@babel/runtime': 7.25.7 + '@babel/runtime': 7.25.9 '@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.3.0)(@types/react@18.3.11)(react-dom@18.3.1)(react@18.3.1) '@types/react': 18.3.11 '@types/react-dom': 18.3.0 @@ -8532,7 +8519,7 @@ packages: '@types/react-dom': optional: true dependencies: - '@babel/runtime': 7.25.7 + '@babel/runtime': 7.25.9 '@radix-ui/number': 1.0.1 '@radix-ui/primitive': 1.0.1 '@radix-ui/react-collection': 1.0.3(@types/react-dom@18.3.0)(@types/react@18.3.11)(react-dom@18.3.1)(react@18.3.1) @@ -8555,7 +8542,7 @@ packages: peerDependencies: react: ^16.8 || ^17.0 || ^18.0 dependencies: - '@babel/runtime': 7.25.7 + '@babel/runtime': 7.25.9 '@radix-ui/react-compose-refs': 1.0.0(react@18.3.1) react: 18.3.1 dev: true @@ -8569,7 +8556,7 @@ packages: '@types/react': optional: true dependencies: - '@babel/runtime': 7.25.7 + '@babel/runtime': 7.25.9 '@radix-ui/react-compose-refs': 1.0.1(@types/react@18.3.11)(react@18.3.1) '@types/react': 18.3.11 react: 18.3.1 @@ -8601,7 +8588,7 @@ packages: '@types/react-dom': optional: true dependencies: - '@babel/runtime': 7.25.7 + '@babel/runtime': 7.25.9 '@radix-ui/primitive': 1.0.1 '@radix-ui/react-compose-refs': 1.0.1(@types/react@18.3.11)(react@18.3.1) '@radix-ui/react-context': 1.0.1(@types/react@18.3.11)(react@18.3.1) @@ -8713,7 +8700,7 @@ packages: '@types/react-dom': optional: true dependencies: - '@babel/runtime': 7.25.7 + '@babel/runtime': 7.25.9 '@radix-ui/primitive': 1.0.1 '@radix-ui/react-context': 1.0.1(@types/react@18.3.11)(react@18.3.1) '@radix-ui/react-direction': 1.0.1(@types/react@18.3.11)(react@18.3.1) @@ -8740,7 +8727,7 @@ packages: '@types/react-dom': optional: true dependencies: - '@babel/runtime': 7.25.7 + '@babel/runtime': 7.25.9 '@radix-ui/primitive': 1.0.1 '@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.3.0)(@types/react@18.3.11)(react-dom@18.3.1)(react@18.3.1) '@radix-ui/react-use-controllable-state': 1.0.1(@types/react@18.3.11)(react@18.3.1) @@ -8763,7 +8750,7 @@ packages: '@types/react-dom': optional: true dependencies: - '@babel/runtime': 7.25.7 + '@babel/runtime': 7.25.9 '@radix-ui/primitive': 1.0.1 '@radix-ui/react-compose-refs': 1.0.1(@types/react@18.3.11)(react@18.3.1) '@radix-ui/react-context': 1.0.1(@types/react@18.3.11)(react@18.3.1) @@ -8795,7 +8782,7 @@ packages: '@types/react-dom': optional: true dependencies: - '@babel/runtime': 7.25.7 + '@babel/runtime': 7.25.9 '@radix-ui/primitive': 1.0.1 '@radix-ui/react-compose-refs': 1.0.1(@types/react@18.3.11)(react@18.3.1) '@radix-ui/react-context': 1.0.1(@types/react@18.3.11)(react@18.3.1) @@ -8848,7 +8835,7 @@ packages: peerDependencies: react: ^16.8 || ^17.0 || ^18.0 dependencies: - '@babel/runtime': 7.25.7 + '@babel/runtime': 7.25.9 react: 18.3.1 dev: true @@ -8861,7 +8848,7 @@ packages: '@types/react': optional: true dependencies: - '@babel/runtime': 7.25.7 + '@babel/runtime': 7.25.9 '@types/react': 18.3.11 react: 18.3.1 dev: false @@ -8883,7 +8870,7 @@ packages: peerDependencies: react: ^16.8 || ^17.0 || ^18.0 dependencies: - '@babel/runtime': 7.25.7 + '@babel/runtime': 7.25.9 '@radix-ui/react-use-callback-ref': 1.0.0(react@18.3.1) react: 18.3.1 dev: true @@ -8897,7 +8884,7 @@ packages: '@types/react': optional: true dependencies: - '@babel/runtime': 7.25.7 + '@babel/runtime': 7.25.9 '@radix-ui/react-use-callback-ref': 1.0.1(@types/react@18.3.11)(react@18.3.1) '@types/react': 18.3.11 react: 18.3.1 @@ -8921,7 +8908,7 @@ packages: peerDependencies: react: ^16.8 || ^17.0 || ^18.0 dependencies: - '@babel/runtime': 7.25.7 + '@babel/runtime': 7.25.9 '@radix-ui/react-use-callback-ref': 1.0.0(react@18.3.1) react: 18.3.1 dev: true @@ -8935,7 +8922,7 @@ packages: '@types/react': optional: true dependencies: - '@babel/runtime': 7.25.7 + '@babel/runtime': 7.25.9 '@radix-ui/react-use-callback-ref': 1.0.1(@types/react@18.3.11)(react@18.3.1) '@types/react': 18.3.11 react: 18.3.1 @@ -8959,7 +8946,7 @@ packages: peerDependencies: react: ^16.8 || ^17.0 || ^18.0 dependencies: - '@babel/runtime': 7.25.7 + '@babel/runtime': 7.25.9 react: 18.3.1 dev: true @@ -8972,7 +8959,7 @@ packages: '@types/react': optional: true dependencies: - '@babel/runtime': 7.25.7 + '@babel/runtime': 7.25.9 '@types/react': 18.3.11 react: 18.3.1 dev: false @@ -8998,7 +8985,7 @@ packages: '@types/react': optional: true dependencies: - '@babel/runtime': 7.25.7 + '@babel/runtime': 7.25.9 '@types/react': 18.3.11 react: 18.3.1 dev: false @@ -9012,7 +8999,7 @@ packages: '@types/react': optional: true dependencies: - '@babel/runtime': 7.25.7 + '@babel/runtime': 7.25.9 '@radix-ui/rect': 1.0.1 '@types/react': 18.3.11 react: 18.3.1 @@ -9040,7 +9027,7 @@ packages: '@types/react': optional: true dependencies: - '@babel/runtime': 7.25.7 + '@babel/runtime': 7.25.9 '@radix-ui/react-use-layout-effect': 1.0.1(@types/react@18.3.11)(react@18.3.1) '@types/react': 18.3.11 react: 18.3.1 @@ -9072,7 +9059,7 @@ packages: '@types/react-dom': optional: true dependencies: - '@babel/runtime': 7.25.7 + '@babel/runtime': 7.25.9 '@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.3.0)(@types/react@18.3.11)(react-dom@18.3.1)(react@18.3.1) '@types/react': 18.3.11 '@types/react-dom': 18.3.0 @@ -9102,7 +9089,7 @@ packages: /@radix-ui/rect@1.0.1: resolution: {integrity: sha512-fyrgCaedtvMg9NK3en0pnOYJdtfwxUcNolezkNPUsoX57X8oQk+NkqcvzHXD2uKNij6GXmWU9NDru2IWjrO4BQ==} dependencies: - '@babel/runtime': 7.25.7 + '@babel/runtime': 7.25.9 dev: false /@radix-ui/rect@1.1.0: @@ -9916,14 +9903,14 @@ packages: /@swc/helpers@0.5.2: resolution: {integrity: sha512-E4KcWTpoLHqwPHLxidpOqQbcrZVgi0rsmmZXUle1jXmJfuIf/UWpczUJ7MZZ5tlxytgJXyp0w4PGkkeLiuIdZw==} dependencies: - tslib: 2.7.0 + tslib: 2.8.0 dev: false /@swc/helpers@0.5.5: resolution: {integrity: sha512-KGYxvIOXcceOAbEk4bi/dVLEK9z8sZ0uBB3Il5b1rhfClSpcX0yfRO0KmTkqR2cnQDymwLB+25ZyMzICg/cm/A==} dependencies: '@swc/counter': 0.1.3 - tslib: 2.7.0 + tslib: 2.8.0 /@swc/types@0.1.12: resolution: {integrity: sha512-wBJA+SdtkbFhHjTMYH+dEH1y4VpfGdAc2Kw/LK09i9bXd/K6j6PkDcFCEzb6iVfZMkPRrl/q0e3toqTAJdkIVA==} @@ -10076,7 +10063,7 @@ packages: dependencies: '@trigger.dev/sdk': 2.3.18 debug: 4.3.7(supports-color@8.1.1) - next: 14.2.10(@babel/core@7.25.8)(@opentelemetry/api@1.4.1)(react-dom@18.3.1)(react@18.3.1) + next: 14.2.10(@babel/core@7.25.9)(@opentelemetry/api@1.4.1)(react-dom@18.3.1)(react@18.3.1) transitivePeerDependencies: - supports-color dev: false @@ -10090,7 +10077,7 @@ packages: dependencies: '@trigger.dev/sdk': 3.0.9 debug: 4.3.7(supports-color@8.1.1) - next: 14.2.10(@babel/core@7.25.8)(@opentelemetry/api@1.4.1)(react-dom@18.3.1)(react@18.3.1) + next: 14.2.10(@babel/core@7.25.9)(@opentelemetry/api@1.4.1)(react-dom@18.3.1)(react@18.3.1) transitivePeerDependencies: - supports-color dev: false @@ -10584,8 +10571,8 @@ packages: resolution: {integrity: sha512-lZuNAY9xeJt7Bx4t4dx0rYCDqGPW8RXhQZK1td7d4H6E9zYbLoOtjBvfwdTKpsyxQI/2jv+armjX/RW+ZNpXOQ==} dev: false - /@types/lodash@4.17.10: - resolution: {integrity: sha512-YpS0zzoduEhuOWjAotS6A5AVCva7X4lVlYLF0FYHAY9sdraBfnatttHItlWeZdGhuEkf+OzMNg2ZYAx8t+52uQ==} + /@types/lodash@4.17.12: + resolution: {integrity: sha512-sviUmCE8AYdaF/KIHLDJBQgeYzPBI0vf/17NaYehBJfYD1j6/L95Slh07NlyK2iNyBNaEkb3En2jRt+a8y3xZQ==} dev: false /@types/mdast@3.0.15: @@ -10641,7 +10628,7 @@ packages: /@types/node-forge@1.3.11: resolution: {integrity: sha512-FQx220y22OKNTqaByeBGqHWYz4cl94tpcxeFdvBo3wjG6XPBuZ0BNgNZRV5J5TFmmcsJ4IzsLkmGRiQbnYsBEQ==} dependencies: - '@types/node': 22.7.6 + '@types/node': 20.14.9 dev: true /@types/node@12.20.55: @@ -10652,8 +10639,8 @@ packages: resolution: {integrity: sha512-vmYJF0REqDyyU0gviezF/KHq/fYaUbFhkcNbQCuPGFQj6VTbXuHZoxs/Y7mutWe73C8AC6l9fFu8mSYiBAqkGA==} dev: false - /@types/node@18.19.55: - resolution: {integrity: sha512-zzw5Vw52205Zr/nmErSEkN5FLqXPuKX/k5d1D7RKHATGqU7y6YfX9QxZraUzUrFGqH6XzOzG196BC35ltJC4Cw==} + /@types/node@18.19.59: + resolution: {integrity: sha512-vizm2EqwV/7Zay+A6J3tGl9Lhr7CjZe2HmWS988sefiEmsyP9CeXEleho6i4hJk/8UtZAo0bWN4QPZZr83RxvQ==} dependencies: undici-types: 5.26.5 dev: false @@ -10669,14 +10656,8 @@ packages: undici-types: 6.19.8 dev: true - /@types/node@22.7.5: - resolution: {integrity: sha512-jML7s2NAzMWc//QSJ1a3prpk78cOPchGvXJsC3C6R6PSMoooztvRVQEz89gmBTBY1SPMaqo5teB4uNHPdetShQ==} - dependencies: - undici-types: 6.19.8 - dev: true - - /@types/node@22.7.6: - resolution: {integrity: sha512-/d7Rnj0/ExXDMcioS78/kf1lMzYk4BZV8MZGTBKzTGZ6/406ukkbYlIsZmMPhcR5KlkunDHQLrtAVmSq7r+mSw==} + /@types/node@22.7.9: + resolution: {integrity: sha512-jrTfRC7FM6nChvU7X2KqcrgquofrWLFDeYC1hKfwNWomVvrn7JIksqf344WN2X/y8xrgqBd2dJATZV4GbatBfg==} dependencies: undici-types: 6.19.8 dev: true @@ -10689,8 +10670,8 @@ packages: resolution: {integrity: sha512-SuT16Q1K51EAVPz1K29DJ/sXjhSQ0zjvsypYJ6tlwVsRV9jwW5Adq2ch8Dq8kDBCkYnELS7N7VNCSB5nC56t/g==} dev: true - /@types/prismjs@1.26.4: - resolution: {integrity: sha512-rlAnzkW2sZOjbqZ743IHUhFcvzaGbqijwOu8QZnZCjfQzBqFE3s4lOTJEsxikImav9uzz/42I+O7YUs1mWgMlg==} + /@types/prismjs@1.26.5: + resolution: {integrity: sha512-AUZTa7hQ2KY5L7AmtSiqxlhWxb4ina0yd8hNbl4TWuqnv/pFP0nDMb3YrfSBf4hJVGLh2YEIBfKaBW/9UEl6IQ==} /@types/prop-types@15.7.13: resolution: {integrity: sha512-hCZTSvwbzWGvhqxp/RqVqwU999pBf2vp7hzIjiYOsl8wqOmUxkQ6ddw1cV3l8811+kdUFus/q4d1Y3E3SyEifA==} @@ -10958,7 +10939,7 @@ packages: peerDependencies: react: ^16.0.0-0 || ^17.0.0-0 || ^18.0.0-0 dependencies: - '@types/lodash': 4.17.10 + '@types/lodash': 4.17.12 '@types/react': 18.3.11 lodash: 4.17.21 prop-types: 15.8.1 @@ -10978,7 +10959,7 @@ packages: dependencies: '@types/d3-path': 1.0.11 '@types/d3-shape': 1.3.12 - '@types/lodash': 4.17.10 + '@types/lodash': 4.17.12 '@types/react': 18.3.11 '@visx/curve': 3.3.0 '@visx/group': 3.3.0(react@18.3.1) @@ -10996,7 +10977,7 @@ packages: peerDependencies: react: ^16.3.0-0 || ^17.0.0-0 || ^18.0.0-0 dependencies: - '@types/lodash': 4.17.10 + '@types/lodash': 4.17.12 '@types/react': 18.3.11 classnames: 2.5.1 lodash: 4.17.21 @@ -11114,9 +11095,9 @@ packages: fflate: 0.8.2 flatted: 3.3.1 pathe: 1.1.2 - picocolors: 1.1.0 + picocolors: 1.1.1 sirv: 2.0.4 - vitest: 1.6.0(@vitest/ui@1.6.0) + vitest: 1.6.0(@types/node@20.14.9)(@vitest/ui@1.6.0) dev: true /@vitest/utils@1.5.3: @@ -11137,33 +11118,16 @@ packages: pretty-format: 29.7.0 dev: true - /@vue/compiler-core@3.5.11: - resolution: {integrity: sha512-PwAdxs7/9Hc3ieBO12tXzmTD+Ln4qhT/56S+8DvrrZ4kLDn4Z/AMUr8tXJD0axiJBS0RKIoNaR0yMuQB9v9Udg==} - dependencies: - '@babel/parser': 7.25.8 - '@vue/shared': 3.5.11 - entities: 4.5.0 - estree-walker: 2.0.2 - source-map-js: 1.2.1 - dev: false - /@vue/compiler-core@3.5.12: resolution: {integrity: sha512-ISyBTRMmMYagUxhcpyEH0hpXRd/KqDU4ymofPgl2XAkY9ZhQ+h0ovEZJIiPop13UmR/54oA2cgMDjgroRelaEw==} dependencies: - '@babel/parser': 7.25.8 + '@babel/parser': 7.25.9 '@vue/shared': 3.5.12 entities: 4.5.0 estree-walker: 2.0.2 source-map-js: 1.2.1 dev: false - /@vue/compiler-dom@3.5.11: - resolution: {integrity: sha512-pyGf8zdbDDRkBrEzf8p7BQlMKNNF5Fk/Cf/fQ6PiUz9at4OaUfyXW0dGJTo2Vl1f5U9jSLCNf0EZJEogLXoeew==} - dependencies: - '@vue/compiler-core': 3.5.11 - '@vue/shared': 3.5.11 - dev: false - /@vue/compiler-dom@3.5.12: resolution: {integrity: sha512-9G6PbJ03uwxLHKQ3P42cMTi85lDRvGLB2rSGOiQqtXELat6uI4n8cNz9yjfVHRPIu+MsK6TE418Giruvgptckg==} dependencies: @@ -11171,24 +11135,10 @@ packages: '@vue/shared': 3.5.12 dev: false - /@vue/compiler-sfc@3.5.11: - resolution: {integrity: sha512-gsbBtT4N9ANXXepprle+X9YLg2htQk1sqH/qGJ/EApl+dgpUBdTv3yP7YlR535uHZY3n6XaR0/bKo0BgwwDniw==} - dependencies: - '@babel/parser': 7.25.8 - '@vue/compiler-core': 3.5.11 - '@vue/compiler-dom': 3.5.11 - '@vue/compiler-ssr': 3.5.11 - '@vue/shared': 3.5.11 - estree-walker: 2.0.2 - magic-string: 0.30.12 - postcss: 8.4.47 - source-map-js: 1.2.1 - dev: false - /@vue/compiler-sfc@3.5.12: resolution: {integrity: sha512-2k973OGo2JuAa5+ZlekuQJtitI5CgLMOwgl94BzMCsKZCX/xiqzJYzapl4opFogKHqwJk34vfsaKpfEhd1k5nw==} dependencies: - '@babel/parser': 7.25.8 + '@babel/parser': 7.25.9 '@vue/compiler-core': 3.5.12 '@vue/compiler-dom': 3.5.12 '@vue/compiler-ssr': 3.5.12 @@ -11199,13 +11149,6 @@ packages: source-map-js: 1.2.1 dev: false - /@vue/compiler-ssr@3.5.11: - resolution: {integrity: sha512-P4+GPjOuC2aFTk1Z4WANvEhyOykcvEd5bIj2KVNGKGfM745LaXGr++5njpdBTzVz5pZifdlR1kpYSJJpIlSePA==} - dependencies: - '@vue/compiler-dom': 3.5.11 - '@vue/shared': 3.5.11 - dev: false - /@vue/compiler-ssr@3.5.12: resolution: {integrity: sha512-eLwc7v6bfGBSM7wZOGPmRavSWzNFF6+PdRhE+VFJhNCgHiF8AM7ccoqcv5kBXA2eWUfigD7byekvf/JsOfKvPA==} dependencies: @@ -11213,25 +11156,12 @@ packages: '@vue/shared': 3.5.12 dev: false - /@vue/reactivity@3.5.11: - resolution: {integrity: sha512-Nqo5VZEn8MJWlCce8XoyVqHZbd5P2NH+yuAaFzuNSR96I+y1cnuUiq7xfSG+kyvLSiWmaHTKP1r3OZY4mMD50w==} - dependencies: - '@vue/shared': 3.5.11 - dev: false - /@vue/reactivity@3.5.12: resolution: {integrity: sha512-UzaN3Da7xnJXdz4Okb/BGbAaomRHc3RdoWqTzlvd9+WBR5m3J39J1fGcHes7U3za0ruYn/iYy/a1euhMEHvTAg==} dependencies: '@vue/shared': 3.5.12 dev: false - /@vue/runtime-core@3.5.11: - resolution: {integrity: sha512-7PsxFGqwfDhfhh0OcDWBG1DaIQIVOLgkwA5q6MtkPiDFjp5gohVnJEahSktwSFLq7R5PtxDKy6WKURVN1UDbzA==} - dependencies: - '@vue/reactivity': 3.5.11 - '@vue/shared': 3.5.11 - dev: false - /@vue/runtime-core@3.5.12: resolution: {integrity: sha512-hrMUYV6tpocr3TL3Ad8DqxOdpDe4zuQY4HPY3X/VRh+L2myQO8MFXPAMarIOSGNu0bFAjh1yBkMPXZBqCk62Uw==} dependencies: @@ -11239,15 +11169,6 @@ packages: '@vue/shared': 3.5.12 dev: false - /@vue/runtime-dom@3.5.11: - resolution: {integrity: sha512-GNghjecT6IrGf0UhuYmpgaOlN7kxzQBhxWEn08c/SQDxv1yy4IXI1bn81JgEpQ4IXjRxWtPyI8x0/7TF5rPfYQ==} - dependencies: - '@vue/reactivity': 3.5.11 - '@vue/runtime-core': 3.5.11 - '@vue/shared': 3.5.11 - csstype: 3.1.3 - dev: false - /@vue/runtime-dom@3.5.12: resolution: {integrity: sha512-q8VFxR9A2MRfBr6/55Q3umyoN7ya836FzRXajPB6/Vvuv0zOPL+qltd9rIMzG/DbRLAIlREmnLsplEF/kotXKA==} dependencies: @@ -11257,16 +11178,6 @@ packages: csstype: 3.1.3 dev: false - /@vue/server-renderer@3.5.11(vue@3.5.11): - resolution: {integrity: sha512-cVOwYBxR7Wb1B1FoxYvtjJD8X/9E5nlH4VSkJy2uMA1MzYNdzAAB//l8nrmN9py/4aP+3NjWukf9PZ3TeWULaA==} - peerDependencies: - vue: 3.5.11 - dependencies: - '@vue/compiler-ssr': 3.5.11 - '@vue/shared': 3.5.11 - vue: 3.5.11(typescript@5.5.3) - dev: false - /@vue/server-renderer@3.5.12(vue@3.5.12): resolution: {integrity: sha512-I3QoeDDeEPZm8yR28JtY+rk880Oqmj43hreIBVTicisFTx/Dl7JpG72g/X7YF8hnQD3IFhkky5i2bPonwrTVPg==} peerDependencies: @@ -11277,10 +11188,6 @@ packages: vue: 3.5.12(typescript@5.5.3) dev: false - /@vue/shared@3.5.11: - resolution: {integrity: sha512-W8GgysJVnFo81FthhzurdRAWP/byq3q2qIw70e0JWblzVhjgOMiC2GyovXrZTFQJnFVryYaKGP3Tc9vYzYm6PQ==} - dev: false - /@vue/shared@3.5.12: resolution: {integrity: sha512-L2RPSAwUFbgZH20etwrXyVyCBu9OxRSi8T/38QsvnkJyvq2LufW2lDCOzm7t/U9C1mkhJGWYfCuFBCmIuNivrg==} dev: false @@ -11430,20 +11337,28 @@ packages: mime-types: 2.1.35 negotiator: 0.6.3 - /acorn-import-attributes@1.9.5(acorn@8.12.1): + /acorn-import-attributes@1.9.5(acorn@8.13.0): resolution: {integrity: sha512-n02Vykv5uA3eHGM/Z2dQrcD56kL8TyDb2p1+0P83PClMnC/nc+anbQRhIOWnSq4Ke/KvDPrY3C9hDtC/A3eHnQ==} peerDependencies: acorn: ^8 dependencies: - acorn: 8.12.1 + acorn: 8.13.0 dev: false - /acorn-jsx@5.3.2(acorn@8.12.1): + /acorn-jsx@5.3.2(acorn@8.13.0): resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==} peerDependencies: acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 dependencies: - acorn: 8.12.1 + acorn: 8.13.0 + + /acorn-typescript@1.4.13(acorn@8.13.0): + resolution: {integrity: sha512-xsc9Xv0xlVfwp2o7sQ+GCQ1PgbkdcpWdTzrwXxO3xDMTAywVS3oXVOcOHuRjAPkS4P9b+yc/qNF15460v+jp4Q==} + peerDependencies: + acorn: '>=8.9.0' + dependencies: + acorn: 8.13.0 + dev: false /acorn-walk@8.2.0: resolution: {integrity: sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==} @@ -11454,12 +11369,7 @@ packages: resolution: {integrity: sha512-ueEepnujpqee2o5aIYnvHU6C0A42MNdsIDeqy5BydrkuC5R1ZuUFnm27EeFJGoEHJQgn3uleRvmTXaJgfXbt4g==} engines: {node: '>=0.4.0'} dependencies: - acorn: 8.12.1 - - /acorn@8.12.1: - resolution: {integrity: sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg==} - engines: {node: '>=0.4.0'} - hasBin: true + acorn: 8.13.0 /acorn@8.13.0: resolution: {integrity: sha512-8zSiw54Oxrdym50NlZ9sUusyO1Z1ZchgRLWRaK6c86XJFClyCgFKetdowBg5bKxyp/u+CDBJG4Mpp0m3HLZl9w==} @@ -11509,51 +11419,7 @@ packages: indent-string: 5.0.0 dev: true - /ai@3.4.7(openai@4.52.1)(react@18.3.1)(svelte@4.2.19)(vue@3.5.11)(zod@3.23.8): - resolution: {integrity: sha512-SutkVjFE86+xNql7fJERJkSEwpILEuiQvCoogJef6ZX/PGHvu3yepwHwVwedgABXe9SudOIKN48EQESrXX/xCw==} - engines: {node: '>=18'} - peerDependencies: - openai: ^4.42.0 - react: ^18 || ^19 - sswr: ^2.1.0 - svelte: ^3.0.0 || ^4.0.0 - zod: ^3.0.0 - peerDependenciesMeta: - openai: - optional: true - react: - optional: true - sswr: - optional: true - svelte: - optional: true - zod: - optional: true - dependencies: - '@ai-sdk/provider': 0.0.24 - '@ai-sdk/provider-utils': 1.0.20(zod@3.23.8) - '@ai-sdk/react': 0.0.62(react@18.3.1)(zod@3.23.8) - '@ai-sdk/solid': 0.0.49(zod@3.23.8) - '@ai-sdk/svelte': 0.0.51(svelte@4.2.19)(zod@3.23.8) - '@ai-sdk/ui-utils': 0.0.46(zod@3.23.8) - '@ai-sdk/vue': 0.0.53(vue@3.5.11)(zod@3.23.8) - '@opentelemetry/api': 1.4.1 - eventsource-parser: 1.1.2 - json-schema: 0.4.0 - jsondiffpatch: 0.6.0 - nanoid: 3.3.6 - openai: 4.52.1 - react: 18.3.1 - secure-json-parse: 2.7.0 - svelte: 4.2.19 - zod: 3.23.8 - zod-to-json-schema: 3.23.2(zod@3.23.8) - transitivePeerDependencies: - - solid-js - - vue - dev: false - - /ai@3.4.7(openai@4.52.1)(react@18.3.1)(svelte@4.2.19)(vue@3.5.12)(zod@3.23.8): + /ai@3.4.7(openai@4.52.1)(react@18.3.1)(svelte@5.0.5)(vue@3.5.12)(zod@3.23.8): resolution: {integrity: sha512-SutkVjFE86+xNql7fJERJkSEwpILEuiQvCoogJef6ZX/PGHvu3yepwHwVwedgABXe9SudOIKN48EQESrXX/xCw==} engines: {node: '>=18'} peerDependencies: @@ -11578,7 +11444,7 @@ packages: '@ai-sdk/provider-utils': 1.0.20(zod@3.23.8) '@ai-sdk/react': 0.0.62(react@18.3.1)(zod@3.23.8) '@ai-sdk/solid': 0.0.49(zod@3.23.8) - '@ai-sdk/svelte': 0.0.51(svelte@4.2.19)(zod@3.23.8) + '@ai-sdk/svelte': 0.0.51(svelte@5.0.5)(zod@3.23.8) '@ai-sdk/ui-utils': 0.0.46(zod@3.23.8) '@ai-sdk/vue': 0.0.53(vue@3.5.12)(zod@3.23.8) '@opentelemetry/api': 1.4.1 @@ -11589,7 +11455,7 @@ packages: openai: 4.52.1 react: 18.3.1 secure-json-parse: 2.7.0 - svelte: 4.2.19 + svelte: 5.0.5 zod: 3.23.8 zod-to-json-schema: 3.23.2(zod@3.23.8) transitivePeerDependencies: @@ -11640,7 +11506,7 @@ packages: resolution: {integrity: sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==} dependencies: fast-deep-equal: 3.1.3 - fast-uri: 3.0.2 + fast-uri: 3.0.3 json-schema-traverse: 1.0.0 require-from-string: 2.0.2 dev: true @@ -11765,7 +11631,7 @@ packages: resolution: {integrity: sha512-y+CcFFwelSXpLZk/7fMB2mUbGtX9lKycf1MWJ7CaTIERyitVlyQx6C+sxcROU2BAJ24OiZyK+8wj2i8AlBoS3A==} engines: {node: '>=10'} dependencies: - tslib: 2.7.0 + tslib: 2.8.0 /aria-query@5.3.2: resolution: {integrity: sha512-COROpnaoap1E2F000S62r6A60uHZnmlvomhfyT2DlTcrY1OrBKn2UhH7qn5wTC9zMvD0AY7csdPSNwKP+7WiQw==} @@ -11843,7 +11709,7 @@ packages: dependencies: pvtsutils: 1.3.5 pvutils: 1.1.3 - tslib: 2.7.0 + tslib: 2.8.0 dev: false /assert@2.1.0: @@ -11864,7 +11730,7 @@ packages: resolution: {integrity: sha512-6t10qk83GOG8p0vKmaCr8eiilZwO171AvbROMtvvNiwrTly62t+7XkA8RdIIVbpMhCASAsxgAzdRSwh6nw/5Dg==} engines: {node: '>=4'} dependencies: - tslib: 2.7.0 + tslib: 2.8.0 dev: true /astring@1.9.0: @@ -11905,11 +11771,11 @@ packages: peerDependencies: postcss: ^8.1.0 dependencies: - browserslist: 4.24.0 - caniuse-lite: 1.0.30001668 + browserslist: 4.24.2 + caniuse-lite: 1.0.30001669 fraction.js: 4.3.7 normalize-range: 0.1.2 - picocolors: 1.1.0 + picocolors: 1.1.1 postcss: 8.4.35 postcss-value-parser: 4.2.0 dev: false @@ -11921,11 +11787,11 @@ packages: peerDependencies: postcss: ^8.1.0 dependencies: - browserslist: 4.24.0 - caniuse-lite: 1.0.30001668 + browserslist: 4.24.2 + caniuse-lite: 1.0.30001669 fraction.js: 4.3.7 normalize-range: 0.1.2 - picocolors: 1.1.0 + picocolors: 1.1.1 postcss: 8.4.38 postcss-value-parser: 4.2.0 @@ -11936,11 +11802,11 @@ packages: peerDependencies: postcss: ^8.1.0 dependencies: - browserslist: 4.24.0 - caniuse-lite: 1.0.30001668 + browserslist: 4.24.2 + caniuse-lite: 1.0.30001669 fraction.js: 4.3.7 normalize-range: 0.1.2 - picocolors: 1.1.0 + picocolors: 1.1.1 postcss: 8.4.45 postcss-value-parser: 4.2.0 dev: true @@ -11983,7 +11849,7 @@ packages: resolution: {integrity: sha512-fdRxJkQ9MUSEi4jH2DcV3FAPFktk0wefilxrwNyUuWpoWawQGN7G7cB+fOYTtFfI6XNkFgwqJ/D3G18BoJJ/jg==} engines: {node: '>= 10.0.0'} dependencies: - '@babel/types': 7.25.8 + '@babel/types': 7.25.9 dev: false /babylon@6.18.0: @@ -12101,15 +11967,15 @@ packages: wcwidth: 1.0.1 dev: true - /browserslist@4.24.0: - resolution: {integrity: sha512-Rmb62sR1Zpjql25eSanFGEhAxcFwfA1K0GuQcLoaJBAcENegrQut3hYdhXFF1obQfiDyqIW/cLM5HSJ/9k884A==} + /browserslist@4.24.2: + resolution: {integrity: sha512-ZIc+Q62revdMcqC6aChtW4jz3My3klmCO1fEmINZY/8J3EpBg5/A/D0AKmBveUh6pgoeycoMkVMko84tuYS+Gg==} engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} hasBin: true dependencies: - caniuse-lite: 1.0.30001668 - electron-to-chromium: 1.5.36 + caniuse-lite: 1.0.30001669 + electron-to-chromium: 1.5.43 node-releases: 2.0.18 - update-browserslist-db: 1.1.1(browserslist@4.24.0) + update-browserslist-db: 1.1.1(browserslist@4.24.2) /buffer-crc32@0.2.13: resolution: {integrity: sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==} @@ -12238,14 +12104,14 @@ packages: resolution: {integrity: sha512-dU+Tx2fsypxTgtLoE36npi3UqcjSSMNYfkqgmoEhtZrraP5VWq0K7FkWVTYa8eMPtnU/G2txVsfdCJTn9uzpuQ==} dev: false - /caniuse-lite@1.0.30001668: - resolution: {integrity: sha512-nWLrdxqCdblixUO+27JtGJJE/txpJlyUy5YN1u53wLZkP0emYCo5zgS6QYft7VUYR42LGgi/S5hdLZTrnyIddw==} + /caniuse-lite@1.0.30001669: + resolution: {integrity: sha512-DlWzFDJqstqtIVx1zeSpIMLjunf5SmwOw0N2Ck/QSQdS8PLS4+9HrLaYei4w8BIAL7IB/UEDu889d8vhCTPA0w==} /capnp-ts@0.7.0: resolution: {integrity: sha512-XKxXAC3HVPv7r674zP0VC3RTXz+/JKhfyw94ljvF80yynK6VkTnqE3jMuN8b3dUVmmc43TjyxjW4KTsmB3c86g==} dependencies: - debug: 4.3.7 - tslib: 2.7.0 + debug: 4.3.7(supports-color@8.1.1) + tslib: 2.8.0 transitivePeerDependencies: - supports-color dev: true @@ -12346,8 +12212,8 @@ packages: get-func-name: 2.0.2 dev: true - /checkly@4.9.0(@types/node@20.14.9)(typescript@5.5.3): - resolution: {integrity: sha512-LqohEntErF7dJaJPsEpjvr/O9wUfzBRac6DOXgFDMEw+dNi19oBAcspdOqVGjPjMoCZ9/s5b5tSJI1pusY4mJQ==} + /checkly@4.9.1(@types/node@20.14.9)(typescript@5.5.3): + resolution: {integrity: sha512-BLVLb9EB8iOQVNZIRUjoEYVPdzOSiBwPlbNOYXOWDoMZHo6dUxWB4ckqJhqWfrvmVPEnSw6JMQ0v/XAXaGYmqw==} engines: {node: '>=16.0.0'} hasBin: true dependencies: @@ -12653,16 +12519,6 @@ packages: - '@types/react-dom' dev: false - /code-red@1.0.4: - resolution: {integrity: sha512-7qJWqItLA8/VPVlKJlFXU+NBlo/qyfs39aJcuMT/2ere32ZqvF5OSxgdM5xOfJJ7O429gg2HM47y8v9P+9wrNw==} - dependencies: - '@jridgewell/sourcemap-codec': 1.5.0 - '@types/estree': 1.0.6 - acorn: 8.13.0 - estree-walker: 3.0.3 - periscopic: 3.1.0 - dev: false - /collapse-white-space@2.1.0: resolution: {integrity: sha512-loKTxY1zCOuG4j9f6EPnuyyYkf58RnhhWTvRoZEokgB+WbdXehfjFviyOVYkqzEWz1Q5kRiZdBYS5SwxbQYwzw==} @@ -12893,8 +12749,8 @@ packages: object-assign: 4.1.1 vary: 1.1.2 - /cosmiconfig-typescript-loader@5.0.0(@types/node@20.14.9)(cosmiconfig@9.0.0)(typescript@5.5.3): - resolution: {integrity: sha512-+8cK7jRAReYkMwMiG+bxhcNKiHJDM6bR9FD/nGBXOWdMLuYawjF5cGrtLilJ+LGd3ZjCXnJjR5DkfWPoIVlqJA==} + /cosmiconfig-typescript-loader@5.1.0(@types/node@20.14.9)(cosmiconfig@9.0.0)(typescript@5.5.3): + resolution: {integrity: sha512-7PtBB+6FdsOvZyJtlF3hEPpACq7RQX6BVGsgC7/lfVXnKMvNCu/XY3ykreqG5w/rBNdu2z8LCIKoF3kpHHdHlA==} engines: {node: '>=v16'} peerDependencies: '@types/node': '*' @@ -13010,14 +12866,6 @@ packages: postcss-value-parser: 4.2.0 dev: false - /css-tree@2.3.1: - resolution: {integrity: sha512-6Fv1DV/TYw//QF5IzQdqsNDjx/wc8TrMBZsqjL9eW01tWb7R7k/mq+/VXfJCl7SoD5emsJop9cOByJZfs8hYIw==} - engines: {node: ^10 || ^12.20.0 || ^14.13.0 || >=15.0.0} - dependencies: - mdn-data: 2.0.30 - source-map-js: 1.2.1 - dev: false - /css-what@2.1.3: resolution: {integrity: sha512-a+EPoD+uZiNfh+5fxw2nO9QwFa6nJe2Or35fGY6Ipw1R3R4AGz1d1TEZrCegvw2YTmZ0jXirGYlzxxpYSHwpEg==} dev: true @@ -13338,18 +13186,6 @@ packages: ms: 2.1.2 dev: true - /debug@4.3.7: - resolution: {integrity: sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==} - engines: {node: '>=6.0'} - peerDependencies: - supports-color: '*' - peerDependenciesMeta: - supports-color: - optional: true - dependencies: - ms: 2.1.3 - dev: true - /debug@4.3.7(supports-color@8.1.1): resolution: {integrity: sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==} engines: {node: '>=6.0'} @@ -13672,7 +13508,7 @@ packages: resolution: {integrity: sha512-Kv5nKlh6yRrdrGvxeJ2e5y2eRUpkUosIW4A2AS38zwSz27zu7ufDwQPi5Jhs3XAlGNetl3bmnGhQsMtkKJnj3w==} dependencies: no-case: 3.0.4 - tslib: 2.7.0 + tslib: 2.4.1 dev: false /dot-prop@6.0.1: @@ -14170,8 +14006,8 @@ packages: jake: 10.9.2 dev: true - /electron-to-chromium@1.5.36: - resolution: {integrity: sha512-HYTX8tKge/VNp6FGO+f/uVDmUkq+cEfcxYhKf15Akc4M5yxt5YmorwlAitKWjWhWQnKcDRBAQKXkhqqXMqcrjw==} + /electron-to-chromium@1.5.43: + resolution: {integrity: sha512-NxnmFBHDl5Sachd2P46O7UJiMaMHMLSofoIWVJq3mj8NJgG0umiSeljAVP9lGzjI0UDLJJ5jjoGjcrB8RSbjLQ==} /emoji-regex@10.4.0: resolution: {integrity: sha512-EC+0oUMY1Rqm4O6LLrgjtYDvcVYTy7chDnM4Q7030tP4Kwj3u/pR6gP9ygnp2CJMK5Gq+9Q2oqmrFJAz01DXjw==} @@ -14400,16 +14236,14 @@ packages: devlop: 1.1.0 estree-util-visit: 2.0.0 unist-util-position-from-estree: 2.0.0 - dev: true /esast-util-from-js@2.0.1: resolution: {integrity: sha512-8Ja+rNJ0Lt56Pcf3TAmpBZjmx8ZcK5Ts4cAzIOjsjevg9oSXJnl6SUQ2EevU8tv3h6ZLWmoKL5H4fgWvdvfETw==} dependencies: '@types/estree-jsx': 1.0.5 - acorn: 8.12.1 + acorn: 8.13.0 esast-util-from-estree: 2.0.0 vfile-message: 4.0.2 - dev: true /esbuild-register@3.6.0(esbuild@0.19.12): resolution: {integrity: sha512-H2/S7Pm8a9CL1uhp9OvjwrBh5Pvx0H8qVOxNu8Wed9Y7qv56MPtq+GGM8RJpq6glYJn9Wspr8uw7l55uyinNeg==} @@ -14655,31 +14489,31 @@ packages: resolution: {integrity: sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==} engines: {node: '>=12'} - /eslint-config-prettier@9.0.0(eslint@9.12.0): + /eslint-config-prettier@9.0.0(eslint@9.13.0): resolution: {integrity: sha512-IcJsTkJae2S35pRsRAwoCE+925rJJStOdkKnLVgtE+tEpqU0EVVM7OqrwxqgptKdX29NUwC82I5pXsGFIgSevw==} hasBin: true peerDependencies: eslint: '>=7.0.0' dependencies: - eslint: 9.12.0 + eslint: 9.13.0 dev: false - /eslint-config-turbo@1.10.12(eslint@9.12.0): + /eslint-config-turbo@1.10.12(eslint@9.13.0): resolution: {integrity: sha512-z3jfh+D7UGYlzMWGh+Kqz++hf8LOE96q3o5R8X4HTjmxaBWlLAWG+0Ounr38h+JLR2TJno0hU9zfzoPNkR9BdA==} peerDependencies: eslint: '>6.6.0' dependencies: - eslint: 9.12.0 - eslint-plugin-turbo: 1.10.12(eslint@9.12.0) + eslint: 9.13.0 + eslint-plugin-turbo: 1.10.12(eslint@9.13.0) dev: false - /eslint-plugin-turbo@1.10.12(eslint@9.12.0): + /eslint-plugin-turbo@1.10.12(eslint@9.13.0): resolution: {integrity: sha512-uNbdj+ohZaYo4tFJ6dStRXu2FZigwulR1b3URPXe0Q8YaE7thuekKNP+54CHtZPH9Zey9dmDx5btAQl9mfzGOw==} peerDependencies: eslint: '>6.6.0' dependencies: dotenv: 16.0.3 - eslint: 9.12.0 + eslint: 9.13.0 dev: false /eslint-scope@5.1.1: @@ -14707,8 +14541,8 @@ packages: engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} dev: false - /eslint@9.12.0: - resolution: {integrity: sha512-UVIOlTEWxwIopRL1wgSQYdnVDcEvs2wyaO6DGo5mXqe3r16IoCNWkR29iHhyaP4cICWjbgbmFUGAhh0GJRuGZw==} + /eslint@9.13.0: + resolution: {integrity: sha512-EYZK6SX6zjFHST/HRytOdA/zE72Cq/bfw45LSyuwrdvcclb/gqV8RRQxywOBEWO2+WDpva6UZa4CcDeJKzUCFA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} hasBin: true peerDependencies: @@ -14717,13 +14551,13 @@ packages: jiti: optional: true dependencies: - '@eslint-community/eslint-utils': 4.4.0(eslint@9.12.0) + '@eslint-community/eslint-utils': 4.4.0(eslint@9.13.0) '@eslint-community/regexpp': 4.11.1 '@eslint/config-array': 0.18.0 - '@eslint/core': 0.6.0 + '@eslint/core': 0.7.0 '@eslint/eslintrc': 3.1.0 - '@eslint/js': 9.12.0 - '@eslint/plugin-kit': 0.2.0 + '@eslint/js': 9.13.0 + '@eslint/plugin-kit': 0.2.1 '@humanfs/node': 0.16.5 '@humanwhocodes/module-importer': 1.0.1 '@humanwhocodes/retry': 0.3.1 @@ -14756,12 +14590,16 @@ packages: - supports-color dev: false + /esm-env@1.0.0: + resolution: {integrity: sha512-Cf6VksWPsTuW01vU9Mk/3vRue91Zevka5SjyNf3nEpokFRuqt/KjUQoGAwq9qMmhpLTHmXzSIrFRw8zxWzmFBA==} + dev: false + /espree@10.2.0: resolution: {integrity: sha512-upbkBJbckcCNBDBDXEbuhjbP68n+scUd3k/U2EkyM9nw+I/jPiL4cLF/Al06CF96wRltFda16sxDFrxsI1v0/g==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} dependencies: - acorn: 8.12.1 - acorn-jsx: 5.3.2(acorn@8.12.1) + acorn: 8.13.0 + acorn-jsx: 5.3.2(acorn@8.13.0) eslint-visitor-keys: 4.1.0 dev: false @@ -14777,6 +14615,13 @@ packages: estraverse: 5.3.0 dev: false + /esrap@1.2.2: + resolution: {integrity: sha512-F2pSJklxx1BlQIQgooczXCPHmcWpn6EsP5oo73LQfonG9fIlIENQ8vMmfGXeojP9MrkzUNAfyU5vdFlR9shHAw==} + dependencies: + '@jridgewell/sourcemap-codec': 1.5.0 + '@types/estree': 1.0.6 + dev: false + /esrecurse@4.3.0: resolution: {integrity: sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==} engines: {node: '>=4.0'} @@ -14825,6 +14670,12 @@ packages: /estree-util-is-identifier-name@3.0.0: resolution: {integrity: sha512-hFtqIDZTIUZ9BXLb8y4pYGyk6+wekIivNVTcmvk8NoOh+VeRn5y6cEHzbURrWbfp1fIqdVipilzj+lfaadNZmg==} + /estree-util-scope@1.0.0: + resolution: {integrity: sha512-2CAASclonf+JFWBNJPndcOpA8EMJwa0Q8LUFJEKqXLW6+qBvbFZuF5gItbQOs/umBUkjviCSDCbBwU2cXbmrhQ==} + dependencies: + '@types/estree': 1.0.6 + devlop: 1.1.0 + /estree-util-to-js@1.2.0: resolution: {integrity: sha512-IzU74r1PK5IMMGZXUVZbmiu4A1uhiPgW5hm1GjcOfr4ZzHaMPpLNJjR7HjXiIOzi25nZDrgFTobHTkV5Q6ITjA==} dependencies: @@ -15042,7 +14893,7 @@ packages: engines: {node: '>= 10.17.0'} hasBin: true dependencies: - debug: 4.3.7(supports-color@8.1.1) + debug: 4.3.4 get-stream: 5.2.0 yauzl: 2.10.0 optionalDependencies: @@ -15086,8 +14937,8 @@ packages: resolution: {integrity: sha512-n11RGP/lrWEFI/bWdygLxhI+pVeo1ZYIVwvvPkW7azl/rOy+F3HYRZ2K5zeE9mmkhQppyv9sQFx0JM9UabnpPQ==} dev: false - /fast-uri@3.0.2: - resolution: {integrity: sha512-GR6f0hD7XXyNJa25Tb9BuIdN0tdr+0BMi6/CJPH3wJO1JjNG3n/VsSw38AwRdKZABm8lGbPfakLRkYzx2V9row==} + /fast-uri@3.0.3: + resolution: {integrity: sha512-aLrHthzCjH5He4Z2H9YZ+v6Ujb9ocRuW6ZzkJQOrTxleEijANq4v1TsaPaVG1PZcuurEzrLcWRyYBYXD5cEiaw==} dev: true /fastest-levenshtein@1.0.16: @@ -15127,8 +14978,8 @@ packages: pend: 1.2.0 dev: true - /fdir@6.4.0(picomatch@4.0.2): - resolution: {integrity: sha512-3oB133prH1o4j/L5lLW7uOCF1PlD+/It2L0eL/iAqWMB91RBbqTewABqxhj0ibBd90EEmWZq7ntIWzVaWcXTGQ==} + /fdir@6.4.2(picomatch@4.0.2): + resolution: {integrity: sha512-KnhMXsKSPZlAhp7+IjUkRZKPb4fUyccpDrdFXbi4QL1qkmFh9kVY09Yox+n4MaOb3lHZ1Tv829C3oaaXoMYPDQ==} peerDependencies: picomatch: ^3 || ^4 peerDependenciesMeta: @@ -15392,7 +15243,7 @@ packages: dependencies: react: 18.3.1 react-dom: 18.3.1(react@18.3.1) - tslib: 2.7.0 + tslib: 2.8.0 optionalDependencies: '@emotion/is-prop-valid': 0.8.8 dev: false @@ -15413,7 +15264,7 @@ packages: dependencies: react: 18.3.1 react-dom: 18.3.1(react@18.3.1) - tslib: 2.7.0 + tslib: 2.8.0 dev: false /free-email-domains@1.2.13: @@ -15506,21 +15357,21 @@ packages: react: '>= 18' react-dom: '>= 18' dependencies: - '@formatjs/intl-localematcher': 0.5.4 + '@formatjs/intl-localematcher': 0.5.5 '@shikijs/rehype': 1.22.0 '@shikijs/transformers': 1.22.0 flexsearch: 0.7.21 github-slugger: 2.0.0 image-size: 1.1.1 - negotiator: 0.6.3 - next: 14.2.10(@babel/core@7.25.8)(@opentelemetry/api@1.4.1)(react-dom@18.3.1)(react@18.3.1) + negotiator: 0.6.4 + next: 14.2.10(@babel/core@7.25.9)(@opentelemetry/api@1.4.1)(react-dom@18.3.1)(react@18.3.1) npm-to-yarn: 3.0.0 react: 18.3.1 react-dom: 18.3.1(react@18.3.1) react-remove-scroll: 2.6.0(@types/react@18.3.11)(react@18.3.1) remark: 15.0.1 remark-gfm: 4.0.0 - remark-mdx: 3.0.1 + remark-mdx: 3.1.0 scroll-into-view-if-needed: 3.1.0 shiki: 1.22.0 swr: 2.2.5(react@18.3.1) @@ -15530,14 +15381,14 @@ packages: - supports-color dev: false - /fumadocs-mdx@10.0.2(fumadocs-core@13.4.10)(next@14.2.10): + /fumadocs-mdx@10.0.2(acorn@8.13.0)(fumadocs-core@13.4.10)(next@14.2.10): resolution: {integrity: sha512-kpM4QfLXF3CjqBCLsYySZNvXvKpDrqDCK7wobhoAbTTmzql2cGXBk+bkAogwjgW3sidGw9d/HIGOcB61R07QLA==} hasBin: true peerDependencies: fumadocs-core: ^13.2.1 next: '>= 14.1.0' dependencies: - '@mdx-js/mdx': 3.0.1 + '@mdx-js/mdx': 3.1.0(acorn@8.13.0) chokidar: 3.6.0 cross-spawn: 7.0.3 esbuild: 0.23.1 @@ -15546,9 +15397,10 @@ packages: fumadocs-core: 13.4.10(@types/react@18.3.11)(next@14.2.10)(react-dom@18.3.1)(react@18.3.1) gray-matter: 4.0.3 micromatch: 4.0.8 - next: 14.2.10(@babel/core@7.25.8)(@opentelemetry/api@1.4.1)(react-dom@18.3.1)(react@18.3.1) + next: 14.2.10(@babel/core@7.25.9)(@opentelemetry/api@1.4.1)(react-dom@18.3.1)(react@18.3.1) zod: 3.23.8 transitivePeerDependencies: + - acorn - supports-color dev: false @@ -15571,13 +15423,13 @@ packages: cmdk: 1.0.0(@types/react-dom@18.3.0)(@types/react@18.3.11)(react-dom@18.3.1)(react@18.3.1) fumadocs-core: 13.4.10(@types/react@18.3.11)(next@14.2.10)(react-dom@18.3.1)(react@18.3.1) lucide-react: 0.438.0(react@18.3.1) - next: 14.2.10(@babel/core@7.25.8)(@opentelemetry/api@1.4.1)(react-dom@18.3.1)(react@18.3.1) + next: 14.2.10(@babel/core@7.25.9)(@opentelemetry/api@1.4.1)(react-dom@18.3.1)(react@18.3.1) next-themes: 0.3.0(react-dom@18.3.1)(react@18.3.1) react: 18.3.1 react-dom: 18.3.1(react@18.3.1) react-medium-image-zoom: 5.2.10(react-dom@18.3.1)(react@18.3.1) swr: 2.2.5(react@18.3.1) - tailwind-merge: 2.5.3 + tailwind-merge: 2.5.4 transitivePeerDependencies: - '@types/react' - '@types/react-dom' @@ -15609,7 +15461,7 @@ packages: peerDependencies: next: '>=13.2.0 <15.0.0-0' dependencies: - next: 14.2.10(@babel/core@7.25.8)(@opentelemetry/api@1.4.1)(react-dom@18.3.1)(react@18.3.1) + next: 14.2.10(@babel/core@7.25.9)(@opentelemetry/api@1.4.1)(react-dom@18.3.1)(react@18.3.1) dev: false /generate-function@2.3.1: @@ -15625,8 +15477,8 @@ packages: resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==} engines: {node: 6.* || 8.* || >= 10.*} - /get-east-asian-width@1.2.0: - resolution: {integrity: sha512-2nk+7SIVb14QrgXFHcm84tD4bKQz0RxPuMT8Ag5KPOq7J5fEmAg0UbXdTOSHqNuHSU28k55qnceesxXRZGzKWA==} + /get-east-asian-width@1.3.0: + resolution: {integrity: sha512-vpeMIQKxczTD/0s2CdEWHcb0eeJe6TFjxb+J5xgX7hScxqrGuyjmv4c1D4A/gelKfyox0gJJwIHF+fLjeaM8kQ==} engines: {node: '>=18'} dev: true @@ -16026,7 +15878,7 @@ packages: dependencies: '@types/hast': 2.3.10 hast-util-from-parse5: 7.1.2 - parse5: 7.1.2 + parse5: 7.2.0 vfile: 5.3.7 vfile-message: 3.1.4 dev: true @@ -16037,7 +15889,7 @@ packages: '@types/hast': 3.0.4 devlop: 1.1.0 hast-util-from-parse5: 8.0.1 - parse5: 7.1.2 + parse5: 7.2.0 vfile: 6.0.3 vfile-message: 4.0.2 @@ -16124,7 +15976,7 @@ packages: hast-util-to-parse5: 8.0.0 html-void-elements: 3.0.0 mdast-util-to-hast: 13.2.0 - parse5: 7.1.2 + parse5: 7.2.0 unist-util-position: 5.0.0 unist-util-visit: 5.0.0 vfile: 6.0.3 @@ -16207,8 +16059,8 @@ packages: zwitch: 2.0.4 dev: false - /hast-util-to-jsx-runtime@2.3.0: - resolution: {integrity: sha512-H/y0+IWPdsLLS738P8tDnrQ8Z+dj12zQQ6WC11TIM21C8WFVoIxcqWXf2H3hiTVZjF1AWqoimGwrTWecWrnmRQ==} + /hast-util-to-jsx-runtime@2.3.2: + resolution: {integrity: sha512-1ngXYb+V9UT5h+PxNRa1O1FYguZK/XL+gkeqvp7EdHlB9oHUG0eYRo/vY5inBdcqo3RkPMC58/H94HvkbfGdyg==} dependencies: '@types/estree': 1.0.6 '@types/hast': 3.0.4 @@ -16348,6 +16200,10 @@ packages: resolution: {integrity: sha512-tzcUFauisWKNHaRkN4Wjl/ZA07gENAjFl3J/c480dprkGTg5EQstgaNFqBfUqCq54kZRIEcreTsAgF/m2quD7A==} dev: false + /highlightjs-vue@1.0.0: + resolution: {integrity: sha512-PDEfEF102G23vHmPhLyPboFCD+BkMGu+GuJe2d9/eH4FsCwvgBpnc9n0pGE+ffKdph38s6foEZiEjdgHdzp+IA==} + dev: false + /homedir-polyfill@1.0.3: resolution: {integrity: sha512-eSmmWE5bZTK2Nou4g0AI3zZ9rswp7GRKoKXS1BLUkvPviOqs4YTN1djQIqrXy9k5gEtdLPy86JjRwsNM9tnDcA==} engines: {node: '>=0.10.0'} @@ -16535,8 +16391,8 @@ packages: /import-in-the-middle@1.11.2: resolution: {integrity: sha512-gK6Rr6EykBcc6cVWRSBR5TWf8nn6hZMYSRYqCcHa0l0d1fPK7JSYo6+Mlmck76jIX9aL/IZ71c06U2VpFwl1zA==} dependencies: - acorn: 8.12.1 - acorn-import-attributes: 1.9.5(acorn@8.12.1) + acorn: 8.13.0 + acorn-import-attributes: 1.9.5(acorn@8.13.0) cjs-module-lexer: 1.4.1 module-details-from-path: 1.0.3 dev: false @@ -16809,7 +16665,7 @@ packages: resolution: {integrity: sha512-OVa3u9kkBbw7b8Xw5F9P+D/T9X+Z4+JruYVNapTjPYZYUznQ5YfWeFkOj606XYYW8yugTfC8Pj0hYqvi4ryAhA==} engines: {node: '>=18'} dependencies: - get-east-asian-width: 1.2.0 + get-east-asian-width: 1.3.0 dev: true /is-generator-function@1.0.10: @@ -17256,8 +17112,8 @@ packages: graceful-fs: 4.2.11 dev: true - /jsonrepair@3.8.1: - resolution: {integrity: sha512-5wnjaO53EJOhfLFY92nvBz2B9gqF9ql/D4HKUb1WOSBaqtVcAifFfmurblnhCJn/ySqKFA8U3n7nhGMAu/hEjQ==} + /jsonrepair@3.9.0: + resolution: {integrity: sha512-gC8z8NP6gEh/9DwDFl8G8nr6KSxdUQBhjTyCq+aZy1mT8DxZf9/V1947MztjLDCdnsn8VjoXj0b2R4HGJdEo7A==} hasBin: true dev: false @@ -17638,7 +17494,7 @@ packages: /lower-case@2.0.2: resolution: {integrity: sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg==} dependencies: - tslib: 2.7.0 + tslib: 2.4.1 dev: false /lowercase-keys@3.0.0: @@ -17746,8 +17602,8 @@ packages: resolution: {integrity: sha512-o5vL7aDWatOTX8LzaS1WMoaoxIiLRQJuIKKe2wAw6IeULDHaqbiqiggmx+pKvZDb1Sj+pE46Sn1T7lCqfFtg1Q==} engines: {node: '>=16'} - /markdown-table@3.0.3: - resolution: {integrity: sha512-Z1NL3Tb1M9wH4XESsCDEksWoKTdlUafKc4pt0GRwjUyXaCFZ+dc3g2erqB6zm3szA2IUSi7VnPI+o/9jnxh9hw==} + /markdown-table@3.0.4: + resolution: {integrity: sha512-wiYz4+JrLyb/DqW2hkFJxP7Vd7JuTDm77fvbM8VfEQdmSMqcImWeeRbHwZjBjIFki/VaMK2BhFi7oUUZeM5bqw==} /marked@7.0.4: resolution: {integrity: sha512-t8eP0dXRJMtMvBojtkcsA7n48BkauktUKzfkPSCq85ZMTJ0v76Rke4DYz01omYpPTUh4p/f7HePgRo3ebG8+QQ==} @@ -17906,7 +17762,7 @@ packages: resolution: {integrity: sha512-jjcpmNnQvrmN5Vx7y7lEc2iIOEytYv7rTvu+MeyAsSHTASGCCRA79Igg2uKssgOs1i1po8s3plW0sTu1wkkLGg==} dependencies: '@types/mdast': 3.0.15 - markdown-table: 3.0.3 + markdown-table: 3.0.4 mdast-util-from-markdown: 1.3.1 mdast-util-to-markdown: 1.5.0 transitivePeerDependencies: @@ -17917,7 +17773,7 @@ packages: dependencies: '@types/mdast': 4.0.4 devlop: 1.1.0 - markdown-table: 3.0.3 + markdown-table: 3.0.4 mdast-util-from-markdown: 2.0.1 mdast-util-to-markdown: 2.1.0 transitivePeerDependencies: @@ -18156,20 +18012,16 @@ packages: deprecated: '`mdast` was renamed to `remark`' dev: true - /mdn-data@2.0.30: - resolution: {integrity: sha512-GaqWWShW4kv/G9IEucWScBx9G1/vsFZZJUO+tD26M8J8z3Kw5RDQjaoZe03YAClgeS/SWPOcb4nkFBTEi5DUEA==} - dev: false - - /mdx-bundler@10.0.3(esbuild@0.19.12): + /mdx-bundler@10.0.3(acorn@8.13.0)(esbuild@0.19.12): resolution: {integrity: sha512-vRtVZ5t+nUP0QtoRVgjDFO10YDjRgKe/19ie0IR8FqE8SugNn5RP4sCWBPzKoEwoGbqfQOrgHy+PHCVyfaCDQQ==} engines: {node: '>=18', npm: '>=6'} peerDependencies: esbuild: 0.* dependencies: - '@babel/runtime': 7.25.7 + '@babel/runtime': 7.25.9 '@esbuild-plugins/node-resolve': 0.2.2(esbuild@0.19.12) '@fal-works/esbuild-plugin-global-externals': 2.1.2 - '@mdx-js/esbuild': 3.0.1(esbuild@0.19.12) + '@mdx-js/esbuild': 3.1.0(acorn@8.13.0)(esbuild@0.19.12) esbuild: 0.19.12 gray-matter: 4.0.3 remark-frontmatter: 5.0.0 @@ -18177,6 +18029,7 @@ packages: uuid: 9.0.1 vfile: 6.0.3 transitivePeerDependencies: + - acorn - supports-color dev: true @@ -18521,8 +18374,8 @@ packages: /micromark-extension-mdxjs@1.0.1: resolution: {integrity: sha512-7YA7hF6i5eKOfFUzZ+0z6avRG52GpWR8DL+kN47y3f2KhxbBZMhmxe7auOeaTBrW2DenbbZTf1ea9tA2hDpC2Q==} dependencies: - acorn: 8.12.1 - acorn-jsx: 5.3.2(acorn@8.12.1) + acorn: 8.13.0 + acorn-jsx: 5.3.2(acorn@8.13.0) micromark-extension-mdx-expression: 1.0.8 micromark-extension-mdx-jsx: 1.0.5 micromark-extension-mdx-md: 1.0.1 @@ -18533,8 +18386,8 @@ packages: /micromark-extension-mdxjs@3.0.0: resolution: {integrity: sha512-A873fJfhnJ2siZyUrJ31l34Uqwy4xIFmvPY1oj+Ean5PHcPBYzEsvqvWGaWcfEIr11O5Dlw3p2y0tZWpKHDejQ==} dependencies: - acorn: 8.12.1 - acorn-jsx: 5.3.2(acorn@8.12.1) + acorn: 8.13.0 + acorn-jsx: 5.3.2(acorn@8.13.0) micromark-extension-mdx-expression: 3.0.0 micromark-extension-mdx-jsx: 3.0.1 micromark-extension-mdx-md: 2.0.0 @@ -18946,7 +18799,7 @@ packages: hasBin: true dependencies: '@cspotcode/source-map-support': 0.8.1 - acorn: 8.12.1 + acorn: 8.13.0 acorn-walk: 8.3.4 capnp-ts: 0.7.0 exit-hook: 2.2.1 @@ -19053,7 +18906,6 @@ packages: /minipass@6.0.2: resolution: {integrity: sha512-MzWSV5nYVT7mVyWCwn2o7JH13w2TBRmmSqSRCKzTw+lmft9X4z+3wjvs06Tzijo5z4W/kahUCDpRXTF+ZrmF/w==} engines: {node: '>=16 || 14 >=14.17'} - dev: true /minipass@7.1.2: resolution: {integrity: sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==} @@ -19128,8 +18980,8 @@ packages: ml-array-min: 1.2.3 dev: false - /ml-matrix@6.11.1: - resolution: {integrity: sha512-Fvp1xF1O07tt6Ux9NcnEQTei5UlqbRpvvaFZGs7l3Ij+nOaEDcmbSVtxwNa8V4IfdyFI1NLNUteroMJ1S6vcEg==} + /ml-matrix@6.12.0: + resolution: {integrity: sha512-AGfR+pWaC0GmzjUnB6BfwhndPEUGz0i7QUYdqNuw1zhTov/vSRJ9pP2hs6BoGpaSbtXgrKjZz2zjD1M0xuur6A==} dependencies: is-any-array: 2.0.1 ml-array-rescale: 1.3.7 @@ -19144,7 +18996,7 @@ packages: /mlly@1.7.2: resolution: {integrity: sha512-tN3dvVHYVz4DhSXinXIk7u9syPYaJvio118uomkovAtWBT+RdbP6Lfh/5Lvo519YMmwBafwlh20IPTXIStscpA==} dependencies: - acorn: 8.12.1 + acorn: 8.13.0 pathe: 1.1.2 pkg-types: 1.2.1 ufo: 1.5.4 @@ -19324,6 +19176,11 @@ packages: resolution: {integrity: sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==} engines: {node: '>= 0.6'} + /negotiator@0.6.4: + resolution: {integrity: sha512-myRT3DiWPHqho5PrJaIRyaMv2kgYf0mUVgBNOYMuCH5Ki1yEiQaf/ZJuQ62nvpc44wL5WDbTX7yGJi1Neevw8w==} + engines: {node: '>= 0.6'} + dev: false + /neo-async@2.6.2: resolution: {integrity: sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==} dev: false @@ -19354,7 +19211,7 @@ packages: react-dom: 18.3.1(react@18.3.1) dev: false - /next@14.1.0(@babel/core@7.25.8)(react-dom@18.3.1)(react@18.3.1): + /next@14.1.0(@babel/core@7.25.9)(react-dom@18.3.1)(react@18.3.1): resolution: {integrity: sha512-wlzrsbfeSU48YQBjZhDzOwhWhGsy+uQycR8bHAOt1LY1bn3zZEcDyHQOEoN3aWzQ8LHCAJ1nqrWCc9XF2+O45Q==} engines: {node: '>=18.17.0'} hasBin: true @@ -19372,12 +19229,12 @@ packages: '@next/env': 14.1.0 '@swc/helpers': 0.5.2 busboy: 1.6.0 - caniuse-lite: 1.0.30001668 + caniuse-lite: 1.0.30001669 graceful-fs: 4.2.11 postcss: 8.4.31 react: 18.3.1 react-dom: 18.3.1(react@18.3.1) - styled-jsx: 5.1.1(@babel/core@7.25.8)(react@18.3.1) + styled-jsx: 5.1.1(@babel/core@7.25.9)(react@18.3.1) optionalDependencies: '@next/swc-darwin-arm64': 14.1.0 '@next/swc-darwin-x64': 14.1.0 @@ -19393,7 +19250,7 @@ packages: - babel-plugin-macros dev: false - /next@14.2.10(@babel/core@7.25.8)(@opentelemetry/api@1.4.1)(react-dom@18.3.1)(react@18.3.1): + /next@14.2.10(@babel/core@7.25.9)(@opentelemetry/api@1.4.1)(react-dom@18.3.1)(react@18.3.1): resolution: {integrity: sha512-sDDExXnh33cY3RkS9JuFEKaS4HmlWmDKP1VJioucCG6z5KuA008DPsDZOzi8UfqEk3Ii+2NCQSJrfbEWtZZfww==} engines: {node: '>=18.17.0'} hasBin: true @@ -19415,12 +19272,12 @@ packages: '@opentelemetry/api': 1.4.1 '@swc/helpers': 0.5.5 busboy: 1.6.0 - caniuse-lite: 1.0.30001668 + caniuse-lite: 1.0.30001669 graceful-fs: 4.2.11 postcss: 8.4.31 react: 18.3.1 react-dom: 18.3.1(react@18.3.1) - styled-jsx: 5.1.1(@babel/core@7.25.8)(react@18.3.1) + styled-jsx: 5.1.1(@babel/core@7.25.9)(react@18.3.1) optionalDependencies: '@next/swc-darwin-arm64': 14.2.10 '@next/swc-darwin-x64': 14.2.10 @@ -19445,7 +19302,7 @@ packages: resolution: {integrity: sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==} dependencies: lower-case: 2.0.2 - tslib: 2.7.0 + tslib: 2.4.1 dev: false /node-addon-api@7.1.1: @@ -19673,7 +19530,7 @@ packages: next: '>=13.4 <14.0.2 || ^14.0.3' dependencies: mitt: 3.0.1 - next: 14.2.10(@babel/core@7.25.8)(@opentelemetry/api@1.4.1)(react-dom@18.3.1)(react@18.3.1) + next: 14.2.10(@babel/core@7.25.9)(@opentelemetry/api@1.4.1)(react-dom@18.3.1)(react@18.3.1) dev: false /object-assign@4.1.1: @@ -19794,7 +19651,7 @@ packages: resolution: {integrity: sha512-kv2hevAWZZ3I/vd2t8znGO2rd8wkowncsfcYpo8i+wU9ML+JEcdqiViANXXjWWGjIhajFNixE6gOY1fEgqILAg==} hasBin: true dependencies: - '@types/node': 18.19.55 + '@types/node': 18.19.59 '@types/node-fetch': 2.6.11 abort-controller: 3.0.0 agentkeepalive: 4.5.0 @@ -19825,7 +19682,7 @@ packages: /openapi3-ts@4.4.0: resolution: {integrity: sha512-9asTNB9IkKEzWMcHmVZE7Ts3kC9G7AFHfs8i7caD8HbI76gEjdkId4z/AkP83xdZsH7PLAnnbl47qZkXuxpArw==} dependencies: - yaml: 2.5.1 + yaml: 2.6.0 dev: false /opener@1.5.2: @@ -20074,7 +19931,7 @@ packages: resolution: {integrity: sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==} engines: {node: '>=8'} dependencies: - '@babel/code-frame': 7.25.7 + '@babel/code-frame': 7.25.9 error-ex: 1.3.2 json-parse-even-better-errors: 2.3.1 lines-and-columns: 1.2.4 @@ -20105,8 +19962,8 @@ packages: resolution: {integrity: sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==} dev: true - /parse5@7.1.2: - resolution: {integrity: sha512-Czj1WaSVpaoj0wbhMzLmWD69anp2WH7FXMB9n1Sy8/ZFF9jolSQVMu1Ij5WIyGmcBmhk7EOndpO4mIpihVqAXw==} + /parse5@7.2.0: + resolution: {integrity: sha512-ZkDsAOcxsUMZ4Lz5fVciOehNcJ+Gb8gTzcA4yl3wnc273BAybYWrQ+Ks/OjCjSEpjvQkDSeZbybK9qj2VHHdGA==} dependencies: entities: 4.5.0 @@ -20158,7 +20015,7 @@ packages: engines: {node: '>=16 || 14 >=14.18'} dependencies: lru-cache: 10.4.3 - minipass: 7.1.2 + minipass: 6.0.2 /path-to-regexp@0.1.10: resolution: {integrity: sha512-7lf7qcQidTku0Gu3YDPc8DJ1q7OOucfa/BSsIwjuh56VU7katFvuM8hULfkwB3Fns/rsVF7PwPKVw1sl5KQS9w==} @@ -20208,12 +20065,8 @@ packages: resolution: {integrity: sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==} dev: true - /picocolors@1.1.0: - resolution: {integrity: sha512-TQ92mBOW0l3LeMeyLV6mzy/kWr8lkd/hp3mTg7wYK7zJhuBStmGMBG0BdeDZS/dZx1IukaX6Bk11zcln25o1Aw==} - /picocolors@1.1.1: resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==} - dev: true /picomatch@2.3.1: resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} @@ -20331,7 +20184,7 @@ packages: lilconfig: 3.1.2 postcss: 8.4.47 ts-node: 10.9.2(@types/node@20.14.9)(typescript@5.5.3) - yaml: 2.5.1 + yaml: 2.6.0 /postcss-nested@6.2.0(postcss@8.4.47): resolution: {integrity: sha512-HQbt28KulC5AJzG+cZtj9kvKB93CFCdLvog1WFLf1D+xmMvPGlBstkpTEZfK5+AN9hfJocyBFCNiqyS48bpgzQ==} @@ -20364,7 +20217,7 @@ packages: engines: {node: ^10 || ^12 || >=14} dependencies: nanoid: 3.3.7 - picocolors: 1.1.0 + picocolors: 1.1.1 source-map-js: 1.2.1 /postcss@8.4.35: @@ -20372,7 +20225,7 @@ packages: engines: {node: ^10 || ^12 || >=14} dependencies: nanoid: 3.3.7 - picocolors: 1.1.0 + picocolors: 1.1.1 source-map-js: 1.0.2 dev: false @@ -20381,7 +20234,7 @@ packages: engines: {node: ^10 || ^12 || >=14} dependencies: nanoid: 3.3.7 - picocolors: 1.1.0 + picocolors: 1.1.1 source-map-js: 1.2.1 /postcss@8.4.45: @@ -20389,7 +20242,7 @@ packages: engines: {node: ^10 || ^12 || >=14} dependencies: nanoid: 3.3.7 - picocolors: 1.1.0 + picocolors: 1.1.1 source-map-js: 1.2.1 dev: true @@ -20398,14 +20251,14 @@ packages: engines: {node: ^10 || ^12 || >=14} dependencies: nanoid: 3.3.7 - picocolors: 1.1.0 + picocolors: 1.1.1 source-map-js: 1.2.1 /posthog-js@1.130.1: resolution: {integrity: sha512-BC283kxeJnVIeAxn7ZPHf5sCTA6oXs4uvo9fdGAsbKwwfmF9g09rnJOOaoF95J/auf8HT4YB6Vt2KytqtJD44w==} dependencies: fflate: 0.4.8 - preact: 10.24.2 + preact: 10.24.3 dev: false /posthog-node@3.6.3: @@ -20428,8 +20281,8 @@ packages: - debug dev: false - /preact@10.24.2: - resolution: {integrity: sha512-1cSoF0aCC8uaARATfrlz4VCBqE8LwZwRfLgkxJOQwAlQt6ayTmi0D9OF7nXid1POI5SZidFuG9CnlXbDfLqY/Q==} + /preact@10.24.3: + resolution: {integrity: sha512-Z2dPnBnMUfyQfSQ+GBdsGa16hz35YmLmtTLhM169uW944hYL6xzTYkJjC07j+Wosz733pMWx0fgON3JNw1jJQA==} dev: false /preferred-pm@3.1.4: @@ -20485,7 +20338,7 @@ packages: peerDependencies: react: '>=16.0.0' dependencies: - '@types/prismjs': 1.26.4 + '@types/prismjs': 1.26.5 clsx: 1.2.1 react: 18.3.1 dev: false @@ -20495,7 +20348,7 @@ packages: peerDependencies: react: '>=16.0.0' dependencies: - '@types/prismjs': 1.26.4 + '@types/prismjs': 1.26.5 clsx: 2.1.1 react: 18.3.1 dev: false @@ -20513,7 +20366,7 @@ packages: /probe.gl@3.6.0: resolution: {integrity: sha512-19JydJWI7+DtR4feV+pu4Mn1I5TAc0xojuxVgZdXIyfmTLfUaFnk4OloWK1bKbPtkgGKLr2lnbnCXmpZEcEp9g==} dependencies: - '@babel/runtime': 7.25.7 + '@babel/runtime': 7.25.9 '@probe.gl/env': 3.6.0 '@probe.gl/log': 3.6.0 '@probe.gl/stats': 3.6.0 @@ -20669,7 +20522,7 @@ packages: /pvtsutils@1.3.5: resolution: {integrity: sha512-ARvb14YB9Nm2Xi6nBq1ZX6dAM0FsJnuk+31aUp4TrcZEdKUlSqOqsxJHUPJDNE3qiIp+iUPEIeR6Je/tgV7zsA==} dependencies: - tslib: 2.7.0 + tslib: 2.8.0 dev: false /pvutils@1.1.3: @@ -20736,11 +20589,11 @@ packages: peerDependencies: react: '>=16' dependencies: - '@babel/runtime': 7.25.7 + '@babel/runtime': 7.25.9 react: 18.3.1 - react-syntax-highlighter: 15.5.0(react@18.3.1) + react-syntax-highlighter: 15.6.1(react@18.3.1) styled-components: 6.1.13(react-dom@18.3.1)(react@18.3.1) - tslib: 2.7.0 + tslib: 2.8.0 transitivePeerDependencies: - react-dom dev: false @@ -20796,7 +20649,7 @@ packages: react-dom: 18.3.1(react@18.3.1) dev: true - /react-email@2.1.1(@babel/core@7.25.8)(eslint@9.12.0)(ts-node@10.9.2): + /react-email@2.1.1(@babel/core@7.25.9)(eslint@9.13.0)(ts-node@10.9.2): resolution: {integrity: sha512-09oMVl/jN0/Re0bT0sEqYjyyFSCN/Tg0YmzjC9wfYpnMx02Apk40XXitySDfUBMR9EgTdr6T4lYknACqiLK3mg==} engines: {node: '>=18.0.0'} hasBin: true @@ -20822,13 +20675,13 @@ packages: commander: 11.1.0 debounce: 2.0.0 esbuild: 0.19.11 - eslint-config-prettier: 9.0.0(eslint@9.12.0) - eslint-config-turbo: 1.10.12(eslint@9.12.0) + eslint-config-prettier: 9.0.0(eslint@9.13.0) + eslint-config-turbo: 1.10.12(eslint@9.13.0) framer-motion: 10.17.4(react-dom@18.3.1)(react@18.3.1) glob: 10.3.4 log-symbols: 4.1.0 mime-types: 2.1.35 - next: 14.1.0(@babel/core@7.25.8)(react-dom@18.3.1)(react@18.3.1) + next: 14.1.0(@babel/core@7.25.9)(react-dom@18.3.1)(react@18.3.1) normalize-path: 3.0.0 ora: 5.4.1 postcss: 8.4.35 @@ -20941,7 +20794,7 @@ packages: '@types/react': 18.3.11 react: 18.3.1 react-style-singleton: 2.2.1(@types/react@18.3.11)(react@18.3.1) - tslib: 2.7.0 + tslib: 2.8.0 /react-remove-scroll@2.5.4(react@18.3.1): resolution: {integrity: sha512-xGVKJJr0SJGQVirVFAUZ2k1QLyO6m+2fy0l8Qawbp5Jgrv3DeLalrfMNBFSlmz5kriGGzsVBtGVnf4pTKIhhWA==} @@ -20956,7 +20809,7 @@ packages: react: 18.3.1 react-remove-scroll-bar: 2.3.6(@types/react@18.3.11)(react@18.3.1) react-style-singleton: 2.2.1(@types/react@18.3.11)(react@18.3.1) - tslib: 2.7.0 + tslib: 2.8.0 use-callback-ref: 1.3.2(@types/react@18.3.11)(react@18.3.1) use-sidecar: 1.1.2(@types/react@18.3.11)(react@18.3.1) dev: true @@ -20975,7 +20828,7 @@ packages: react: 18.3.1 react-remove-scroll-bar: 2.3.6(@types/react@18.3.11)(react@18.3.1) react-style-singleton: 2.2.1(@types/react@18.3.11)(react@18.3.1) - tslib: 2.7.0 + tslib: 2.8.0 use-callback-ref: 1.3.2(@types/react@18.3.11)(react@18.3.1) use-sidecar: 1.1.2(@types/react@18.3.11)(react@18.3.1) dev: false @@ -20994,7 +20847,7 @@ packages: react: 18.3.1 react-remove-scroll-bar: 2.3.6(@types/react@18.3.11)(react@18.3.1) react-style-singleton: 2.2.1(@types/react@18.3.11)(react@18.3.1) - tslib: 2.7.0 + tslib: 2.8.0 use-callback-ref: 1.3.2(@types/react@18.3.11)(react@18.3.1) use-sidecar: 1.1.2(@types/react@18.3.11)(react@18.3.1) dev: false @@ -21013,7 +20866,7 @@ packages: react: 18.3.1 react-remove-scroll-bar: 2.3.6(@types/react@18.3.11)(react@18.3.1) react-style-singleton: 2.2.1(@types/react@18.3.11)(react@18.3.1) - tslib: 2.7.0 + tslib: 2.8.0 use-callback-ref: 1.3.2(@types/react@18.3.11)(react@18.3.1) use-sidecar: 1.1.2(@types/react@18.3.11)(react@18.3.1) @@ -21031,15 +20884,29 @@ packages: get-nonce: 1.0.1 invariant: 2.2.4 react: 18.3.1 - tslib: 2.7.0 + tslib: 2.8.0 /react-syntax-highlighter@15.5.0(react@18.3.1): resolution: {integrity: sha512-+zq2myprEnQmH5yw6Gqc8lD55QHnpKaU8TOcFeC/Lg/MQSs8UknEA0JC4nTZGFAXC2J2Hyj/ijJ7NlabyPi2gg==} peerDependencies: react: '>= 0.14.0' dependencies: - '@babel/runtime': 7.25.7 + '@babel/runtime': 7.25.9 + highlight.js: 10.7.3 + lowlight: 1.20.0 + prismjs: 1.29.0 + react: 18.3.1 + refractor: 3.6.0 + dev: false + + /react-syntax-highlighter@15.6.1(react@18.3.1): + resolution: {integrity: sha512-OqJ2/vL7lEeV5zTJyG7kmARppUjiB9h9udl4qHQjjgEos66z00Ia0OckwYfRxCSFrW8RJIBnsBwQsHZbVPspqg==} + peerDependencies: + react: '>= 0.14.0' + dependencies: + '@babel/runtime': 7.25.9 highlight.js: 10.7.3 + highlightjs-vue: 1.0.0 lowlight: 1.20.0 prismjs: 1.29.0 react: 18.3.1 @@ -21170,7 +21037,7 @@ packages: ast-types: 0.16.1 esprima: 4.0.1 source-map: 0.6.1 - tslib: 2.7.0 + tslib: 2.8.0 dev: true /rechoir@0.6.2: @@ -21180,6 +21047,40 @@ packages: resolve: 1.22.8 dev: false + /recma-build-jsx@1.0.0: + resolution: {integrity: sha512-8GtdyqaBcDfva+GUKDr3nev3VpKAhup1+RvkMvUxURHpW7QyIvk9F5wz7Vzo06CEMSilw6uArgRqhpiUcWp8ew==} + dependencies: + '@types/estree': 1.0.6 + estree-util-build-jsx: 3.0.1 + vfile: 6.0.3 + + /recma-jsx@1.0.0(acorn@8.13.0): + resolution: {integrity: sha512-5vwkv65qWwYxg+Atz95acp8DMu1JDSqdGkA2Of1j6rCreyFUE/gp15fC8MnGEuG1W68UKjM6x6+YTWIh7hZM/Q==} + dependencies: + acorn-jsx: 5.3.2(acorn@8.13.0) + estree-util-to-js: 2.0.0 + recma-parse: 1.0.0 + recma-stringify: 1.0.0 + unified: 11.0.5 + transitivePeerDependencies: + - acorn + + /recma-parse@1.0.0: + resolution: {integrity: sha512-OYLsIGBB5Y5wjnSnQW6t3Xg7q3fQ7FWbw/vcXtORTnyaSFscOtABg+7Pnz6YZ6c27fG1/aN8CjfwoUEUIdwqWQ==} + dependencies: + '@types/estree': 1.0.6 + esast-util-from-js: 2.0.1 + unified: 11.0.5 + vfile: 6.0.3 + + /recma-stringify@1.0.0: + resolution: {integrity: sha512-cjwII1MdIIVloKvC9ErQ+OgAtwHBmcZ0Bg4ciz78FtbT8In39aAYbaA7zvxQ61xVMSPE8WxhLwLbhif4Js2C+g==} + dependencies: + '@types/estree': 1.0.6 + estree-util-to-js: 2.0.0 + unified: 11.0.5 + vfile: 6.0.3 + /redent@3.0.0: resolution: {integrity: sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==} engines: {node: '>=8'} @@ -21224,7 +21125,7 @@ packages: resolution: {integrity: sha512-/fk5sI0iTgFYlmVGYVew90AoYnNMP6pooClx/XKqyeeCQXrL0Kvgn8V0VEht5ccdljbzzF1i3Q213gcntkRExg==} dependencies: '@types/hast': 2.3.10 - '@types/prismjs': 1.26.4 + '@types/prismjs': 1.26.5 hastscript: 7.2.0 parse-entities: 4.0.1 dev: true @@ -21311,6 +21212,15 @@ packages: vfile: 6.0.3 dev: false + /rehype-recma@1.0.0: + resolution: {integrity: sha512-lqA4rGUf1JmacCNWWZx0Wv1dHqMwxzsDWYMTowuplHF3xH0N/MmrZ/G3BDZnzAkRmxDadujCjaKM2hqYdCBOGw==} + dependencies: + '@types/estree': 1.0.6 + '@types/hast': 3.0.4 + hast-util-to-estree: 3.1.0 + transitivePeerDependencies: + - supports-color + /rehype-slug@6.0.0: resolution: {integrity: sha512-lWyvf/jwu+oS5+hL5eClVd3hNdmwM1kAC0BUvEGD19pajQMIzcNUd/k9GsfQ+FfECvX+JE+e9/btsKH0EjJT6A==} dependencies: @@ -21385,7 +21295,7 @@ packages: estree-util-value-to-estree: 3.1.2 toml: 3.0.0 unified: 11.0.5 - yaml: 2.5.1 + yaml: 2.6.0 dev: true /remark-mdx@2.3.0: @@ -21396,8 +21306,8 @@ packages: transitivePeerDependencies: - supports-color - /remark-mdx@3.0.1: - resolution: {integrity: sha512-3Pz3yPQ5Rht2pM5R+0J2MrGoBSrzf+tJG94N+t/ilfdh8YLyyKYtidAYwTveB20BoHAcwIopOUqhcmh2F7hGYA==} + /remark-mdx@3.1.0: + resolution: {integrity: sha512-Ngl/H3YXyBV9RcRNdlYsZujAmhsxwzxpDzpDEhFBVAGthS4GDgnctpDjgFl/ULx5UEDzqtW1cyBSNKqYYrqLBA==} dependencies: mdast-util-mdx: 3.0.0 micromark-extension-mdxjs: 3.0.0 @@ -21757,7 +21667,7 @@ packages: /rxjs@7.8.1: resolution: {integrity: sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==} dependencies: - tslib: 2.7.0 + tslib: 2.8.0 dev: true /sade@1.8.1: @@ -22136,7 +22046,7 @@ packages: resolution: {integrity: sha512-LAOh4z89bGQvl9pFfNF8V146i7o7/CqFPbqzYgP+yYzDIDeS9HaNFtXABamRW+AQzEVODcvE79ljJ+8a9YSdMg==} dependencies: dot-case: 3.0.4 - tslib: 2.7.0 + tslib: 2.4.1 dev: false /snakecase-keys@3.2.1: @@ -22366,12 +22276,12 @@ packages: resolution: {integrity: sha512-qC9iz2FlN7DQl3+wjwn3802RTyjCx7sDvfQEXchwa6CWOx07/WVfh91gBmQ9fahw8snwGEWU3xGzOt4tFyHLxg==} engines: {node: '>= 0.6'} - /sswr@2.1.0(svelte@4.2.19): + /sswr@2.1.0(svelte@5.0.5): resolution: {integrity: sha512-Cqc355SYlTAaUt8iDPaC/4DPPXK925PePLMxyBKuWd5kKc5mwsG3nT9+Mq2tyguL5s7b4Jg+IRMpTRsNTAfpSQ==} peerDependencies: svelte: ^4.0.0 || ^5.0.0-next.0 dependencies: - svelte: 4.2.19 + svelte: 5.0.5 swrev: 4.0.0 dev: false @@ -22458,7 +22368,7 @@ packages: engines: {node: '>=18'} dependencies: emoji-regex: 10.4.0 - get-east-asian-width: 1.2.0 + get-east-asian-width: 1.3.0 strip-ansi: 7.1.0 dev: true @@ -22612,7 +22522,7 @@ packages: tslib: 2.6.2 dev: false - /styled-jsx@5.1.1(@babel/core@7.25.8)(react@18.3.1): + /styled-jsx@5.1.1(@babel/core@7.25.9)(react@18.3.1): resolution: {integrity: sha512-pW7uC1l4mBZ8ugbiZrcIsiIvVx1UmTfw7UkC3Um2tmfUq9Bhk8IiyEIPl6F8agHgjzku6j0xQEZbfA5uSgSaCw==} engines: {node: '>= 12.0.0'} peerDependencies: @@ -22625,7 +22535,7 @@ packages: babel-plugin-macros: optional: true dependencies: - '@babel/core': 7.25.8 + '@babel/core': 7.25.9 client-only: 0.0.1 react: 18.3.1 @@ -22696,24 +22606,23 @@ packages: resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} engines: {node: '>= 0.4'} - /svelte@4.2.19: - resolution: {integrity: sha512-IY1rnGr6izd10B0A8LqsBfmlT5OILVuZ7XsI0vdGPEvuonFV7NYEUK4dAkm9Zg2q0Um92kYjTpS1CAP3Nh/KWw==} - engines: {node: '>=16'} + /svelte@5.0.5: + resolution: {integrity: sha512-f4WBlP5g8W6pEoDfx741lewMlemy+LIGpEqjGPWqnHVP92wqlQXl87U5O5Bi2tkSUrO95OxOoqwU8qlqiHmFKA==} + engines: {node: '>=18'} dependencies: '@ampproject/remapping': 2.3.0 '@jridgewell/sourcemap-codec': 1.5.0 - '@jridgewell/trace-mapping': 0.3.25 '@types/estree': 1.0.6 acorn: 8.13.0 + acorn-typescript: 1.4.13(acorn@8.13.0) aria-query: 5.3.2 axobject-query: 4.1.0 - code-red: 1.0.4 - css-tree: 2.3.1 - estree-walker: 3.0.3 + esm-env: 1.0.0 + esrap: 1.2.2 is-reference: 3.0.2 locate-character: 3.0.0 magic-string: 0.30.12 - periscopic: 3.1.0 + zimmerframe: 1.1.2 dev: false /svix-fetch@3.0.0: @@ -22760,14 +22669,6 @@ packages: resolution: {integrity: sha512-LqVcOHSB4cPGgitD1riJ1Hh4vdmITOp+BkmfmXRh4hSF/t7EnS4iD+SOTmq7w5pPm/SiPeto4ADbKS6dHUDWFA==} dev: false - /swrv@1.0.4(vue@3.5.11): - resolution: {integrity: sha512-zjEkcP8Ywmj+xOJW3lIT65ciY/4AL4e/Or7Gj0MzU3zBJNMdJiT8geVZhINavnlHRMMCcJLHhraLTAiDOTmQ9g==} - peerDependencies: - vue: '>=3.2.26 < 4' - dependencies: - vue: 3.5.11(typescript@5.5.3) - dev: false - /swrv@1.0.4(vue@3.5.12): resolution: {integrity: sha512-zjEkcP8Ywmj+xOJW3lIT65ciY/4AL4e/Or7Gj0MzU3zBJNMdJiT8geVZhINavnlHRMMCcJLHhraLTAiDOTmQ9g==} peerDependencies: @@ -22779,17 +22680,17 @@ packages: /tailwind-merge@2.2.0: resolution: {integrity: sha512-SqqhhaL0T06SW59+JVNfAqKdqLs0497esifRrZ7jOaefP3o64fdFNDMrAQWZFMxTLJPiHVjRLUywT8uFz1xNWQ==} dependencies: - '@babel/runtime': 7.25.7 + '@babel/runtime': 7.25.9 dev: false /tailwind-merge@2.3.0: resolution: {integrity: sha512-vkYrLpIP+lgR0tQCG6AP7zZXCTLc1Lnv/CCRT3BqJ9CZ3ui2++GPaGb1x/ILsINIMSYqqvrpqjUFsMNLlW99EA==} dependencies: - '@babel/runtime': 7.25.7 + '@babel/runtime': 7.25.9 dev: false - /tailwind-merge@2.5.3: - resolution: {integrity: sha512-d9ZolCAIzom1nf/5p4LdD5zvjmgSxY0BGgdSvmXIoMYAiPdAW/dSpP7joCDYFY7r/HkEa2qmPtkgsu0xjQeQtw==} + /tailwind-merge@2.5.4: + resolution: {integrity: sha512-0q8cfZHMu9nuYP/b5Shb7Y7Sh1B7Nnl5GqNr1U+n2p6+mybvRtayrQ+0042Z5byvTA8ihjlP8Odo8/VnHbZu4Q==} dev: false /tailwind-scrollbar@3.1.0(tailwindcss@3.4.10): @@ -22827,7 +22728,7 @@ packages: micromatch: 4.0.8 normalize-path: 3.0.0 object-hash: 3.0.0 - picocolors: 1.1.0 + picocolors: 1.1.1 postcss: 8.4.47 postcss-import: 15.1.0(postcss@8.4.47) postcss-js: 4.0.1(postcss@8.4.47) @@ -22858,7 +22759,7 @@ packages: micromatch: 4.0.8 normalize-path: 3.0.0 object-hash: 3.0.0 - picocolors: 1.1.0 + picocolors: 1.1.1 postcss: 8.4.47 postcss-import: 15.1.0(postcss@8.4.47) postcss-js: 4.0.1(postcss@8.4.47) @@ -22964,17 +22865,17 @@ packages: jest-worker: 27.5.1 schema-utils: 3.3.0 serialize-javascript: 6.0.2 - terser: 5.34.1 + terser: 5.36.0 webpack: 5.95.0(@swc/core@1.3.101)(esbuild@0.19.11) dev: false - /terser@5.34.1: - resolution: {integrity: sha512-FsJZ7iZLd/BXkz+4xrRTGJ26o/6VTjQytUk8b8OxkwcD2I+79VPJlz7qss1+zE7h8GNIScFqXcDyJ/KqBYZFVA==} + /terser@5.36.0: + resolution: {integrity: sha512-IYV9eNMuFAV4THUspIRXkLakHnV6XO7FEdtKjf/mDyrnqUg9LnlOn6/RwRvM9SZjR4GUq8Nk8zj67FzVARr74w==} engines: {node: '>=10'} hasBin: true dependencies: '@jridgewell/source-map': 0.3.6 - acorn: 8.12.1 + acorn: 8.13.0 commander: 2.20.3 source-map-support: 0.5.21 dev: false @@ -23014,7 +22915,7 @@ packages: resolution: {integrity: sha512-8or1+BGEdk1Zkkw2ii16qSS7uVrQJPre5A9o/XkWPATkk23FZh/15BKFxPnlTy6vkljZxLqYCzzBMj30ZrSvjw==} engines: {node: '>=12.0.0'} dependencies: - fdir: 6.4.0(picomatch@4.0.2) + fdir: 6.4.2(picomatch@4.0.2) picomatch: 4.0.2 dev: true @@ -23035,10 +22936,6 @@ packages: os-tmpdir: 1.0.2 dev: true - /to-fast-properties@2.0.0: - resolution: {integrity: sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==} - engines: {node: '>=4'} - /to-no-case@1.0.2: resolution: {integrity: sha512-Z3g735FxuZY8rodxV4gH7LxClE4H0hTIyHNIHdk+vpQxjLm0cwnKXq/OFVZ76SOQmto7txVcwSCwkU5kqp+FKg==} @@ -23167,7 +23064,7 @@ packages: '@tsconfig/node14': 1.0.3 '@tsconfig/node16': 1.0.4 '@types/node': 20.14.9 - acorn: 8.12.1 + acorn: 8.13.0 acorn-walk: 8.3.4 arg: 4.1.3 create-require: 1.1.1 @@ -23198,7 +23095,7 @@ packages: '@tsconfig/node14': 1.0.3 '@tsconfig/node16': 1.0.4 '@types/node': 20.14.9 - acorn: 8.12.1 + acorn: 8.13.0 acorn-walk: 8.3.4 arg: 4.1.3 create-require: 1.1.1 @@ -23229,8 +23126,8 @@ packages: resolution: {integrity: sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==} dev: false - /tslib@2.7.0: - resolution: {integrity: sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==} + /tslib@2.8.0: + resolution: {integrity: sha512-jWVzBLplnCmoaTr13V9dYbiQ99wvZRd0vNWaDRg+aVYRcjDF3nDksxFDE/+fkXnKhpnUUkmx5pK/v8mCtLVqZA==} /tsup@8.0.2(ts-node@10.9.2)(typescript@5.5.3): resolution: {integrity: sha512-NY8xtQXdH7hDUAZwcQdY/Vzlw9johQsaqf7iwZ6g1DOUlFYQ5/AtVAjTvihhEyeRlGo4dLRVHtrRaL35M1daqQ==} @@ -23764,19 +23661,19 @@ packages: webpack-sources: optional: true dependencies: - acorn: 8.12.1 + acorn: 8.13.0 webpack-virtual-modules: 0.6.2 dev: true - /update-browserslist-db@1.1.1(browserslist@4.24.0): + /update-browserslist-db@1.1.1(browserslist@4.24.2): resolution: {integrity: sha512-R8UzCaa9Az+38REPiJ1tXlImTJXlVfgHZsglwBD/k6nj76ctsH1E3q4doGrukiLQd3sGQYu56r5+lo5r94l29A==} hasBin: true peerDependencies: browserslist: '>= 4.21.0' dependencies: - browserslist: 4.24.0 + browserslist: 4.24.2 escalade: 3.2.0 - picocolors: 1.1.0 + picocolors: 1.1.1 /uri-js@4.4.1: resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} @@ -23803,7 +23700,7 @@ packages: dependencies: '@types/react': 18.3.11 react: 18.3.1 - tslib: 2.7.0 + tslib: 2.8.0 /use-sidecar@1.1.2(@types/react@18.3.11)(react@18.3.1): resolution: {integrity: sha512-epTbsLuzZ7lPClpz2TyryBfztm7m+28DlEv2ZCQ3MDr5ssiwyOwGH/e5F9CkfWjJ1t4clvI58yF822/GUkjjhw==} @@ -23818,7 +23715,7 @@ packages: '@types/react': 18.3.11 detect-node-es: 1.1.0 react: 18.3.1 - tslib: 2.7.0 + tslib: 2.8.0 /use-sync-external-store@1.2.2(react@18.3.1): resolution: {integrity: sha512-PElTlVMwpblvbNqQ82d2n6RjStvdSoNe9FG28kNfz3WiXilJm4DdNkEzRhCZuIDwY8U08WVihhGR5iRqAwfDiw==} @@ -23964,32 +23861,10 @@ packages: hasBin: true dependencies: cac: 6.7.14 - debug: 4.3.7 + debug: 4.3.7(supports-color@8.1.1) pathe: 1.1.2 picocolors: 1.1.1 - vite: 5.4.9(@types/node@20.14.9) - transitivePeerDependencies: - - '@types/node' - - less - - lightningcss - - sass - - sass-embedded - - stylus - - sugarss - - supports-color - - terser - dev: true - - /vite-node@1.6.0: - resolution: {integrity: sha512-de6HJgzC+TFzOu0NTC4RAIsyf/DY/ibWDYQUcuEA84EMHhcefTUGkjFHKKEJhQN4A+6I0u++kr3l36ZF2d7XRw==} - engines: {node: ^18.0.0 || >=20.0.0} - hasBin: true - dependencies: - cac: 6.7.14 - debug: 4.3.7 - pathe: 1.1.2 - picocolors: 1.1.0 - vite: 5.4.8 + vite: 5.4.10(@types/node@20.14.9) transitivePeerDependencies: - '@types/node' - less @@ -24010,8 +23885,8 @@ packages: cac: 6.7.14 debug: 4.3.7(supports-color@8.1.1) pathe: 1.1.2 - picocolors: 1.1.0 - vite: 5.4.8(@types/node@20.14.9) + picocolors: 1.1.1 + vite: 5.4.10(@types/node@20.14.9) transitivePeerDependencies: - '@types/node' - less @@ -24024,85 +23899,8 @@ packages: - terser dev: true - /vite@5.4.8: - resolution: {integrity: sha512-FqrItQ4DT1NC4zCUqMB4c4AZORMKIa0m8/URVCZ77OZ/QSNeJ54bU1vrFADbDsuwfIPcgknRkmqakQcgnL4GiQ==} - engines: {node: ^18.0.0 || >=20.0.0} - hasBin: true - peerDependencies: - '@types/node': ^18.0.0 || >=20.0.0 - less: '*' - lightningcss: ^1.21.0 - sass: '*' - sass-embedded: '*' - stylus: '*' - sugarss: '*' - terser: ^5.4.0 - peerDependenciesMeta: - '@types/node': - optional: true - less: - optional: true - lightningcss: - optional: true - sass: - optional: true - sass-embedded: - optional: true - stylus: - optional: true - sugarss: - optional: true - terser: - optional: true - dependencies: - esbuild: 0.21.5 - postcss: 8.4.47 - rollup: 4.24.0 - optionalDependencies: - fsevents: 2.3.3 - dev: true - - /vite@5.4.8(@types/node@20.14.9): - resolution: {integrity: sha512-FqrItQ4DT1NC4zCUqMB4c4AZORMKIa0m8/URVCZ77OZ/QSNeJ54bU1vrFADbDsuwfIPcgknRkmqakQcgnL4GiQ==} - engines: {node: ^18.0.0 || >=20.0.0} - hasBin: true - peerDependencies: - '@types/node': ^18.0.0 || >=20.0.0 - less: '*' - lightningcss: ^1.21.0 - sass: '*' - sass-embedded: '*' - stylus: '*' - sugarss: '*' - terser: ^5.4.0 - peerDependenciesMeta: - '@types/node': - optional: true - less: - optional: true - lightningcss: - optional: true - sass: - optional: true - sass-embedded: - optional: true - stylus: - optional: true - sugarss: - optional: true - terser: - optional: true - dependencies: - '@types/node': 20.14.9 - esbuild: 0.21.5 - postcss: 8.4.47 - rollup: 4.24.0 - optionalDependencies: - fsevents: 2.3.3 - dev: true - - /vite@5.4.9(@types/node@20.14.9): - resolution: {integrity: sha512-20OVpJHh0PAM0oSOELa5GaZNWeDjcAvQjGXy2Uyr+Tp+/D2/Hdz6NLgpJLsarPTA2QJ6v8mX2P1ZfbsSKvdMkg==} + /vite@5.4.10(@types/node@20.14.9): + resolution: {integrity: sha512-1hvaPshuPUtxeQ0hsVH3Mud0ZanOLwVTneA1EgbAM5LhaZEqyPWGRQ7BtaMvUrTDeEaC8pxtj6a6jku3x4z6SQ==} engines: {node: ^18.0.0 || >=20.0.0} hasBin: true peerDependencies: @@ -24140,7 +23938,7 @@ packages: fsevents: 2.3.3 dev: true - /vitest@1.5.3(@types/node@20.14.9): + /vitest@1.5.3(@types/node@20.14.9)(@vitest/ui@1.6.0): resolution: {integrity: sha512-2oM7nLXylw3mQlW6GXnRriw+7YvZFk/YNV8AxIC3Z3MfFbuziLGWP9GPxxu/7nRlXhqyxBikpamr+lEEj1sUEw==} engines: {node: ^18.0.0 || >=20.0.0} hasBin: true @@ -24170,10 +23968,11 @@ packages: '@vitest/runner': 1.5.3 '@vitest/snapshot': 1.5.3 '@vitest/spy': 1.5.3 + '@vitest/ui': 1.6.0(vitest@1.6.0) '@vitest/utils': 1.5.3 acorn-walk: 8.3.4 chai: 4.5.0 - debug: 4.3.7 + debug: 4.3.7(supports-color@8.1.1) execa: 8.0.1 local-pkg: 0.5.0 magic-string: 0.30.12 @@ -24183,7 +23982,7 @@ packages: strip-literal: 2.1.0 tinybench: 2.9.0 tinypool: 0.8.4 - vite: 5.4.9(@types/node@20.14.9) + vite: 5.4.10(@types/node@20.14.9) vite-node: 1.5.3(@types/node@20.14.9) why-is-node-running: 2.3.0 transitivePeerDependencies: @@ -24236,12 +24035,12 @@ packages: local-pkg: 0.5.0 magic-string: 0.30.12 pathe: 1.1.2 - picocolors: 1.1.0 + picocolors: 1.1.1 std-env: 3.7.0 strip-literal: 2.1.0 tinybench: 2.9.0 tinypool: 0.8.4 - vite: 5.4.8(@types/node@20.14.9) + vite: 5.4.10(@types/node@20.14.9) vite-node: 1.6.0(@types/node@20.14.9) why-is-node-running: 2.3.0 transitivePeerDependencies: @@ -24255,63 +24054,6 @@ packages: - terser dev: true - /vitest@1.6.0(@vitest/ui@1.6.0): - resolution: {integrity: sha512-H5r/dN06swuFnzNFhq/dnz37bPXnq8xB2xB5JOVk8K09rUtoeNN+LHWkoQ0A/i3hvbUKKcCei9KpbxqHMLhLLA==} - engines: {node: ^18.0.0 || >=20.0.0} - hasBin: true - peerDependencies: - '@edge-runtime/vm': '*' - '@types/node': ^18.0.0 || >=20.0.0 - '@vitest/browser': 1.6.0 - '@vitest/ui': 1.6.0 - happy-dom: '*' - jsdom: '*' - peerDependenciesMeta: - '@edge-runtime/vm': - optional: true - '@types/node': - optional: true - '@vitest/browser': - optional: true - '@vitest/ui': - optional: true - happy-dom: - optional: true - jsdom: - optional: true - dependencies: - '@vitest/expect': 1.6.0 - '@vitest/runner': 1.6.0 - '@vitest/snapshot': 1.6.0 - '@vitest/spy': 1.6.0 - '@vitest/ui': 1.6.0(vitest@1.6.0) - '@vitest/utils': 1.6.0 - acorn-walk: 8.3.4 - chai: 4.5.0 - debug: 4.3.7 - execa: 8.0.1 - local-pkg: 0.5.0 - magic-string: 0.30.12 - pathe: 1.1.2 - picocolors: 1.1.0 - std-env: 3.7.0 - strip-literal: 2.1.0 - tinybench: 2.9.0 - tinypool: 0.8.4 - vite: 5.4.8 - vite-node: 1.6.0 - why-is-node-running: 2.3.0 - transitivePeerDependencies: - - less - - lightningcss - - sass - - sass-embedded - - stylus - - sugarss - - supports-color - - terser - dev: true - /vlq@0.2.3: resolution: {integrity: sha512-DRibZL6DsNhIgYQ+wNdWDL2SL3bKPlVrRiBqV5yuMm++op8W4kGFtaQfCs4KEJn0wBZcHVHJ3eoywX8983k1ow==} dev: true @@ -24324,22 +24066,6 @@ packages: resolution: {integrity: sha512-AFbieoL7a5LMqcnOF04ji+rpXadgOXnZsxQr//r83kLPr7biP7am3g9zbaZIaBGwBRWeSvoMD4mgPdX3e4NWBg==} dev: false - /vue@3.5.11(typescript@5.5.3): - resolution: {integrity: sha512-/8Wurrd9J3lb72FTQS7gRMNQD4nztTtKPmuDuPuhqXmmpD6+skVjAeahNpVzsuky6Sy9gy7wn8UadqPtt9SQIg==} - peerDependencies: - typescript: '*' - peerDependenciesMeta: - typescript: - optional: true - dependencies: - '@vue/compiler-dom': 3.5.11 - '@vue/compiler-sfc': 3.5.11 - '@vue/runtime-dom': 3.5.11 - '@vue/server-renderer': 3.5.11(vue@3.5.11) - '@vue/shared': 3.5.11 - typescript: 5.5.3 - dev: false - /vue@3.5.12(typescript@5.5.3): resolution: {integrity: sha512-CLVZtXtn2ItBIi/zHZ0Sg1Xkb7+PU32bJJ8Bmy7ts3jxXTcbfsEfBivFYYWz1Hur+lalqGAh65Coin0r+HRUfg==} peerDependencies: @@ -24388,7 +24114,7 @@ packages: '@peculiar/json-schema': 1.1.12 asn1js: 3.0.5 pvtsutils: 1.3.5 - tslib: 2.7.0 + tslib: 2.8.0 dev: false /webidl-conversions@3.0.1: @@ -24404,7 +24130,7 @@ packages: hasBin: true dependencies: '@discoveryjs/json-ext': 0.5.7 - acorn: 8.12.1 + acorn: 8.13.0 acorn-walk: 8.3.4 commander: 7.2.0 debounce: 1.2.1 @@ -24413,7 +24139,7 @@ packages: html-escaper: 2.0.2 is-plain-object: 5.0.0 opener: 1.5.2 - picocolors: 1.1.0 + picocolors: 1.1.1 sirv: 2.0.4 ws: 7.5.10 transitivePeerDependencies: @@ -24444,9 +24170,9 @@ packages: '@webassemblyjs/ast': 1.12.1 '@webassemblyjs/wasm-edit': 1.12.1 '@webassemblyjs/wasm-parser': 1.12.1 - acorn: 8.12.1 - acorn-import-attributes: 1.9.5(acorn@8.12.1) - browserslist: 4.24.0 + acorn: 8.13.0 + acorn-import-attributes: 1.9.5(acorn@8.13.0) + browserslist: 4.24.2 chrome-trace-event: 1.0.4 enhanced-resolve: 5.17.1 es-module-lexer: 1.5.4 @@ -24825,8 +24551,8 @@ packages: engines: {node: '>= 14'} dev: true - /yaml@2.5.1: - resolution: {integrity: sha512-bLQOjaX/ADgQ20isPJRvF0iRUHIxVhYvr53Of7wGcWlO2jvtUlH5m87DsmulFVxRpNLOnI4tB6p/oh8D7kpn9Q==} + /yaml@2.6.0: + resolution: {integrity: sha512-a6ae//JvKDEra2kdi1qzCyrJW/WZCgFi8ydDV+eXExl95t+5R+ijnqHJbz9tmMh8FUjx3iv2fCQ4dclAQlO2UQ==} engines: {node: '>= 14'} hasBin: true @@ -24942,6 +24668,10 @@ packages: stacktracey: 2.1.8 dev: true + /zimmerframe@1.1.2: + resolution: {integrity: sha512-rAbqEGa8ovJy4pyBxZM70hg4pE6gDgaQ0Sl9M3enG3I0d6H4XSAM3GeNGLKnsBpuijUow064sf7ww1nutC5/3w==} + dev: false + /zod-error@1.5.0: resolution: {integrity: sha512-zzopKZ/skI9iXpqCEPj+iLCKl9b88E43ehcU+sbRoHuwGd9F1IDVGQ70TyO6kmfiRL1g4IXkjsXK+g1gLYl4WQ==} dependencies: