diff --git a/apps/web/app/api/metatags/route.ts b/apps/web/app/api/links/metatags/route.ts
similarity index 58%
rename from apps/web/app/api/metatags/route.ts
rename to apps/web/app/api/links/metatags/route.ts
index 683349fd638..056632c611c 100644
--- a/apps/web/app/api/metatags/route.ts
+++ b/apps/web/app/api/links/metatags/route.ts
@@ -6,37 +6,41 @@ import { getMetaTags } from "./utils";
export const runtime = "edge";
-const CORS_HEADERS = {
- "Access-Control-Allow-Origin": "*",
- "Access-Control-Allow-Methods": "GET, OPTIONS",
-};
-
export async function GET(req: NextRequest) {
try {
+ const origin = req.headers.get("origin");
+ // Validate the origin header and set CORS headers accordingly
+ const corsHeaders = {
+ "Access-Control-Allow-Methods": "GET",
+ "Access-Control-Allow-Headers": "Content-Type",
+ };
+
+ if (origin && origin.endsWith(".dub.co")) {
+ corsHeaders["Access-Control-Allow-Origin"] = origin;
+ }
+
+ // Validate URL parameter
const { url } = getUrlQuerySchema.parse({
url: req.nextUrl.searchParams.get("url"),
});
+ // Rate limit by IP
await ratelimitOrThrow(req, "metatags");
+ // Get metatags
const metatags = await getMetaTags(url);
+
+ // Return response
return NextResponse.json(
{
...metatags,
poweredBy: "Dub.co - Link management for modern marketing teams",
},
{
- headers: CORS_HEADERS,
+ headers: corsHeaders,
},
);
} catch (error) {
- return handleAndReturnErrorResponse(error, CORS_HEADERS);
+ return handleAndReturnErrorResponse(error);
}
}
-
-export function OPTIONS() {
- return new Response(null, {
- status: 204,
- headers: CORS_HEADERS,
- });
-}
diff --git a/apps/web/app/api/metatags/utils.ts b/apps/web/app/api/links/metatags/utils.ts
similarity index 58%
rename from apps/web/app/api/metatags/utils.ts
rename to apps/web/app/api/links/metatags/utils.ts
index 5be950ebb2c..04d1d173423 100644
--- a/apps/web/app/api/metatags/utils.ts
+++ b/apps/web/app/api/links/metatags/utils.ts
@@ -5,13 +5,36 @@ import he from "he";
import { parse } from "node-html-parser";
export const getHtml = async (url: string) => {
- return await fetchWithTimeout(url, {
- headers: {
- "User-Agent": "Dub.co Metatags API (https://api.dub.co/metatags)",
- },
- })
- .then((r) => r.text())
- .catch(() => null);
+ try {
+ const response = await fetchWithTimeout(url);
+
+ if (!response.ok) {
+ // If we get a 406 or other error, check if it's a Cloudflare-protected site
+ const isCloudflare = response.headers.get("server") === "cloudflare";
+ if (isCloudflare) {
+ console.warn(`Cloudflare-protected site detected: ${url}`);
+ return null;
+ }
+ console.error(`HTTP error! status: ${response.status} for URL: ${url}`);
+ return null;
+ }
+
+ const text = await response.text();
+
+ // Check if the response contains Cloudflare's challenge page
+ if (
+ text.includes("challenge-platform") ||
+ text.includes("cf-browser-verification")
+ ) {
+ console.warn(`Cloudflare challenge page detected for: ${url}`);
+ return null;
+ }
+
+ return text;
+ } catch (error) {
+ console.error(`Error fetching ${url}:`, error);
+ return null;
+ }
};
export const getHeadChildNodes = (html) => {
@@ -47,15 +70,42 @@ export const getRelativeUrl = (url: string, imageUrl: string) => {
return new URL(imageUrl, baseURL).toString();
};
-export const getMetaTags = async (url: string) => {
- const html = await getHtml(url);
- if (!html) {
+const generateFallbackMetadata = (url: string) => {
+ try {
+ const parsedUrl = new URL(url);
+ const hostname = parsedUrl.hostname;
+ const path = parsedUrl.pathname;
+
+ // Clean up the path for title
+ const pathParts = path.split("/").filter(Boolean);
+ const lastPathPart = pathParts[pathParts.length - 1] || "";
+ const formattedPath = lastPathPart
+ .split("-")
+ .map((word) => word.charAt(0).toUpperCase() + word.slice(1))
+ .join(" ");
+
+ return {
+ title: formattedPath || hostname.replace(/^www\./, ""),
+ description: `Visit ${hostname}${path}`,
+ image: null,
+ };
+ } catch (e) {
return {
title: url,
- description: "No description",
+ description: "No description available",
image: null,
};
}
+};
+
+export const getMetaTags = async (url: string) => {
+ const html = await getHtml(url);
+ if (!html) {
+ // If we couldn't fetch the HTML (e.g., due to Cloudflare protection),
+ // generate fallback metadata from the URL
+ return generateFallbackMetadata(url);
+ }
+
const { metaTags, title: titleTag, linkTags } = getHeadChildNodes(html);
let object = {};
diff --git a/apps/web/app/api/track/lead/route.ts b/apps/web/app/api/track/lead/route.ts
index 4215b9f1762..b64c057da0e 100644
--- a/apps/web/app/api/track/lead/route.ts
+++ b/apps/web/app/api/track/lead/route.ts
@@ -44,8 +44,8 @@ export const POST = withWorkspace(
} = trackLeadRequestSchema
.extend({
// add backwards compatibility
- externalId: z.string().optional(),
- customerId: z.string().optional(),
+ externalId: z.string().nullish(),
+ customerId: z.string().nullish(),
})
.parse(body);
diff --git a/apps/web/app/api/track/sale/route.ts b/apps/web/app/api/track/sale/route.ts
index 0adb04f4e57..e96e7ccff68 100644
--- a/apps/web/app/api/track/sale/route.ts
+++ b/apps/web/app/api/track/sale/route.ts
@@ -42,8 +42,8 @@ export const POST = withWorkspace(
} = trackSaleRequestSchema
.extend({
// add backwards compatibility
- externalId: z.string().optional(),
- customerId: z.string().optional(),
+ externalId: z.string().nullish(),
+ customerId: z.string().nullish(),
})
.parse(body);
diff --git a/apps/web/app/app.dub.co/(auth)/oauth/authorize/page.tsx b/apps/web/app/app.dub.co/(auth)/oauth/authorize/page.tsx
index 2bb27e8ef40..976337af7be 100644
--- a/apps/web/app/app.dub.co/(auth)/oauth/authorize/page.tsx
+++ b/apps/web/app/app.dub.co/(auth)/oauth/authorize/page.tsx
@@ -5,7 +5,7 @@ import { authorizeRequestSchema } from "@/lib/zod/schemas/oauth";
import EmptyState from "@/ui/shared/empty-state";
import { BlurImage, Logo } from "@dub/ui";
import { CircleWarning, CubeSettings } from "@dub/ui/icons";
-import { HOME_DOMAIN, constructMetadata } from "@dub/utils";
+import { constructMetadata } from "@dub/utils";
import { ArrowLeftRight } from "lucide-react";
import { redirect } from "next/navigation";
import { Suspense } from "react";
@@ -62,7 +62,7 @@ export default async function Authorize({
)}
-
+
diff --git a/apps/web/app/app.dub.co/(onboarding)/onboarding/(steps)/link/form.tsx b/apps/web/app/app.dub.co/(onboarding)/onboarding/(steps)/link/form.tsx
index ecc1821b78a..70b05c1f01d 100644
--- a/apps/web/app/app.dub.co/(onboarding)/onboarding/(steps)/link/form.tsx
+++ b/apps/web/app/app.dub.co/(onboarding)/onboarding/(steps)/link/form.tsx
@@ -73,7 +73,7 @@ export function Form() {
// If url is valid, continue to generate metatags, else return null
new URL(debouncedUrl);
setLoadingPreviewImage(true);
- const res = await fetch(`/api/metatags?url=${debouncedUrl}`);
+ const res = await fetch(`/api/links/metatags?url=${debouncedUrl}`);
if (res.ok) {
const results = await res.json();
setPreviewImage(results.image);
diff --git a/apps/web/app/cloaked/[url]/page.tsx b/apps/web/app/cloaked/[url]/page.tsx
index f110a6ffb19..e2f3cf30fc2 100644
--- a/apps/web/app/cloaked/[url]/page.tsx
+++ b/apps/web/app/cloaked/[url]/page.tsx
@@ -3,7 +3,7 @@ import {
constructMetadata,
getApexDomain,
} from "@dub/utils";
-import { getMetaTags } from "app/api/metatags/utils";
+import { getMetaTags } from "app/api/links/metatags/utils";
export const runtime = "edge";
export const fetchCache = "force-no-store";
diff --git a/apps/web/lib/middleware/api.ts b/apps/web/lib/middleware/api.ts
index 0988aaddfd9..c129bf9089e 100644
--- a/apps/web/lib/middleware/api.ts
+++ b/apps/web/lib/middleware/api.ts
@@ -1,18 +1,14 @@
import { parse } from "@/lib/middleware/utils";
-import { HOME_DOMAIN } from "@dub/utils";
import { NextRequest, NextResponse } from "next/server";
export default function ApiMiddleware(req: NextRequest) {
- const { path, fullPath } = parse(req);
+ const { fullPath } = parse(req);
- // special case for /metatags
- if (path === "/metatags") {
- const url = req.nextUrl.searchParams.get("url");
- if (!url) {
- return NextResponse.redirect(`${HOME_DOMAIN}/tools/metatags`, {
- status: 301,
- });
- }
+ // redirect to dub.co for /metatags
+ if (fullPath.startsWith("/metatags")) {
+ return NextResponse.redirect("https://dub.co", {
+ status: 301,
+ });
}
// Note: we don't have to account for paths starting with `/api`
// since they're automatically excluded via our middleware matcher
diff --git a/apps/web/lib/middleware/utils/bots-list.ts b/apps/web/lib/middleware/utils/bots-list.ts
index 9a2d23140d3..d1c5d498de1 100644
--- a/apps/web/lib/middleware/utils/bots-list.ts
+++ b/apps/web/lib/middleware/utils/bots-list.ts
@@ -1,7 +1,6 @@
export const UA_BOTS = [
"bot", // most bots
"crawler", // most crawlers
- "metatags", // Dub.co Metatags API (https://api.dub.co/metatags)
"chatgpt", // ChatGPT
"bluesky", // Bluesky crawler
"facebookexternalhit", // Facebook crawler
@@ -18,6 +17,7 @@ export const UA_BOTS = [
"MetaInspector", // metatags.io
"Go-http-client", // Go-http-client/1.1 is a bot: https://user-agents.net/string/go-http-client-1-1
"iframely", // https://iframely.com/docs/about (used by Notion, Linear)
+ "H1cbA69", // internal links/metatags API
// new
"ia_archiver",
diff --git a/apps/web/lib/openapi/index.ts b/apps/web/lib/openapi/index.ts
index d01bfb56337..ac1015e2d09 100644
--- a/apps/web/lib/openapi/index.ts
+++ b/apps/web/lib/openapi/index.ts
@@ -13,7 +13,6 @@ import { embedTokensPaths } from "./embed-tokens";
import { eventsPath } from "./events";
import { foldersPaths } from "./folders";
import { linksPaths } from "./links";
-import { metatagsPath } from "./metatags";
import { partnersPaths } from "./partners";
import { qrCodePaths } from "./qr";
import { tagsPaths } from "./tags";
@@ -56,7 +55,6 @@ export const document = createDocument({
...workspacesPaths,
...embedTokensPaths,
...qrCodePaths,
- ...metatagsPath,
},
components: {
schemas: {
diff --git a/apps/web/lib/openapi/metatags/index.ts b/apps/web/lib/openapi/metatags/index.ts
deleted file mode 100644
index b50d5920341..00000000000
--- a/apps/web/lib/openapi/metatags/index.ts
+++ /dev/null
@@ -1,38 +0,0 @@
-import z from "@/lib/zod";
-import { getUrlQuerySchema } from "@/lib/zod/schemas/links";
-import { metaTagsSchema } from "@/lib/zod/schemas/metatags";
-import { ZodOpenApiOperationObject, ZodOpenApiPathsObject } from "zod-openapi";
-
-const getMetatags: ZodOpenApiOperationObject = {
- operationId: "getMetatags",
- "x-speakeasy-name-override": "get",
- summary: "Retrieve the metatags for a URL",
- description: "Retrieve the metatags for a URL.",
- requestParams: {
- query: getUrlQuerySchema.merge(
- z.object({
- url: z.string().openapi({
- example: "https://dub.co",
- description: "The URL to retrieve metatags for.",
- }),
- }),
- ),
- },
- responses: {
- "200": {
- description: "The retrieved metatags",
- content: {
- "application/json": {
- schema: metaTagsSchema,
- },
- },
- },
- },
- tags: ["Metatags"],
-};
-
-export const metatagsPath: ZodOpenApiPathsObject = {
- "/metatags": {
- get: getMetatags,
- },
-};
diff --git a/apps/web/lib/types.ts b/apps/web/lib/types.ts
index 2998c899971..d2953ea8ec9 100644
--- a/apps/web/lib/types.ts
+++ b/apps/web/lib/types.ts
@@ -1,5 +1,4 @@
import z from "@/lib/zod";
-import { metaTagsSchema } from "@/lib/zod/schemas/metatags";
import {
PartnerEarningsSchema,
PartnerProfileCustomerSchema,
@@ -278,8 +277,6 @@ export const tagColors = [
export type DashboardProps = z.infer;
-export type MetaTag = z.infer;
-
export type TokenProps = z.infer;
export type OAuthAppProps = z.infer;
diff --git a/apps/web/lib/upstash/record-metatags.ts b/apps/web/lib/upstash/record-metatags.ts
index 3a2d311f52f..ef546c03a67 100644
--- a/apps/web/lib/upstash/record-metatags.ts
+++ b/apps/web/lib/upstash/record-metatags.ts
@@ -2,7 +2,7 @@ import { getDomainWithoutWWW } from "@dub/utils";
import { redis } from "./redis";
/**
- * Recording metatags that were generated via `/api/metatags`
+ * Recording metatags that were generated via "/api/links/metatags"
* If there's an error, it will be logged to a separate redis list for debugging
**/
export async function recordMetatags(url: string, error: boolean) {
diff --git a/apps/web/lib/zod/schemas/links.ts b/apps/web/lib/zod/schemas/links.ts
index e8adadf9270..bb749573a3f 100644
--- a/apps/web/lib/zod/schemas/links.ts
+++ b/apps/web/lib/zod/schemas/links.ts
@@ -538,19 +538,19 @@ export const LinkSchema = z
.string()
.nullable()
.describe(
- "The title of the short link generated via `api.dub.co/metatags`. Will be used for Custom Social Media Cards if `proxy` is true.",
+ "The title of the short link. Will be used for Custom Social Media Cards if `proxy` is true.",
),
description: z
.string()
.nullable()
.describe(
- "The description of the short link generated via `api.dub.co/metatags`. Will be used for Custom Social Media Cards if `proxy` is true.",
+ "The description of the short link. Will be used for Custom Social Media Cards if `proxy` is true.",
),
image: z
.string()
.nullable()
.describe(
- "The image of the short link generated via `api.dub.co/metatags`. Will be used for Custom Social Media Cards if `proxy` is true.",
+ "The image of the short link. Will be used for Custom Social Media Cards if `proxy` is true.",
),
video: z
.string()
diff --git a/apps/web/lib/zod/schemas/metatags.ts b/apps/web/lib/zod/schemas/metatags.ts
deleted file mode 100644
index cb7280f27cf..00000000000
--- a/apps/web/lib/zod/schemas/metatags.ts
+++ /dev/null
@@ -1,23 +0,0 @@
-import z from "@/lib/zod";
-
-export const metaTagsSchema = z.object({
- title: z
- .string()
- .nullable()
- .describe("The meta title tag for the URL.")
- .openapi({
- example: "Dub.co - Link Management for Modern Marketing Teams",
- }),
- description: z
- .string()
- .nullable()
- .describe("The meta description tag for the URL.")
- .openapi({
- example: "Dub.co is the open-source link management infrastructure ...",
- }),
- image: z
- .string()
- .nullable()
- .describe("The OpenGraph image for the URL.")
- .openapi({ example: "https://assets.dub.co/thumbnail.jpg" }),
-});
diff --git a/apps/web/lib/zod/schemas/sales.ts b/apps/web/lib/zod/schemas/sales.ts
index f8033d3df6b..c7dea11efa9 100644
--- a/apps/web/lib/zod/schemas/sales.ts
+++ b/apps/web/lib/zod/schemas/sales.ts
@@ -26,7 +26,7 @@ export const trackSaleRequestSchema = z.object({
.optional()
.default("Purchase")
.describe("The name of the sale event.")
- .openapi({ examples: ["Purchase", "Upgrade", "Payment"] }),
+ .openapi({ example: "Invoice paid" }),
invoiceId: z
.string()
.nullish()
diff --git a/apps/web/next.config.js b/apps/web/next.config.js
index f98cf13ca0b..49bed7f523e 100644
--- a/apps/web/next.config.js
+++ b/apps/web/next.config.js
@@ -165,30 +165,6 @@ module.exports = withAxiom({
}
),
),
- {
- source: "/metatags",
- has: [
- {
- type: "host",
- value: "dub.sh",
- },
- ],
- destination: "https://dub.co/tools/metatags",
- permanent: true,
- statusCode: 301,
- },
- {
- source: "/metatags",
- has: [
- {
- type: "host",
- value: "dub.co",
- },
- ],
- destination: "/tools/metatags",
- permanent: true,
- statusCode: 301,
- },
{
source: "/",
has: [
diff --git a/apps/web/package.json b/apps/web/package.json
index 270a9e40a1c..853457d892b 100644
--- a/apps/web/package.json
+++ b/apps/web/package.json
@@ -124,7 +124,7 @@
"vaul": "^1.1.2",
"zod": "^3.22.4",
"zod-error": "^1.5.0",
- "zod-openapi": "^2.19.0"
+ "zod-openapi": "^4.2.4"
},
"devDependencies": {
"@types/he": "^1.2.3",
diff --git a/apps/web/tests/metatags/retrieve-metatags.test.ts b/apps/web/tests/links/retrieve-metatags.test.ts
similarity index 80%
rename from apps/web/tests/metatags/retrieve-metatags.test.ts
rename to apps/web/tests/links/retrieve-metatags.test.ts
index e2236073990..bdf744ab6c3 100644
--- a/apps/web/tests/metatags/retrieve-metatags.test.ts
+++ b/apps/web/tests/links/retrieve-metatags.test.ts
@@ -1,13 +1,12 @@
-import { MetaTag } from "@/lib/types";
import { expect, test } from "vitest";
import { IntegrationHarness } from "../utils/integration";
-test("GET /metatags", async (ctx) => {
+test("GET /links/metatags", async (ctx) => {
const h = new IntegrationHarness(ctx);
const { http } = await h.init();
- const { status, data: metatags } = await http.get({
- path: `/metatags`,
+ const { status, data: metatags } = await http.get({
+ path: "/links/metatags",
query: {
url: "https://dub.co",
},
diff --git a/apps/web/ui/links/link-builder/use-metatags.ts b/apps/web/ui/links/link-builder/use-metatags.ts
index 7cd2942aa2e..374e67831fd 100644
--- a/apps/web/ui/links/link-builder/use-metatags.ts
+++ b/apps/web/ui/links/link-builder/use-metatags.ts
@@ -42,7 +42,7 @@ export function useMetatags({ enabled = true }: { enabled?: boolean } = {}) {
// if url is valid, continue to generate metatags, else throw error and return null
new URL(debouncedUrl);
setGeneratingMetatags(true);
- fetch(`/api/metatags?url=${debouncedUrl}`).then(async (res) => {
+ fetch(`/api/links/metatags?url=${debouncedUrl}`).then(async (res) => {
if (res.status === 200) {
const results = await res.json();
const truncatedTitle = truncate(results.title, 120);
diff --git a/packages/ui/package.json b/packages/ui/package.json
index 7ae6d61199d..f6f7c7020d9 100644
--- a/packages/ui/package.json
+++ b/packages/ui/package.json
@@ -1,7 +1,7 @@
{
"name": "@dub/ui",
"description": "UI components for Dub.co",
- "version": "0.2.35",
+ "version": "0.2.36",
"sideEffects": false,
"main": "./dist/index.js",
"module": "./dist/index.mjs",
diff --git a/packages/ui/src/link-preview.tsx b/packages/ui/src/link-preview.tsx
index 82f3a49f6f1..3dc301a5a0e 100644
--- a/packages/ui/src/link-preview.tsx
+++ b/packages/ui/src/link-preview.tsx
@@ -2,7 +2,7 @@
import { fetcher, getDomainWithoutWWW, getUrlFromString } from "@dub/utils";
import { Link2 } from "lucide-react";
-import { useRouter, useSearchParams } from "next/navigation";
+import { useSearchParams } from "next/navigation";
import { useEffect, useMemo, useRef } from "react";
import useSWR from "swr";
import { useDebounce } from "use-debounce";
@@ -10,7 +10,6 @@ import { useMediaQuery } from "./hooks";
import { LoadingCircle, Photo } from "./icons";
export function LinkPreview({ defaultUrl }: { defaultUrl?: string }) {
- const router = useRouter();
const searchParams = useSearchParams();
const url =
defaultUrl || searchParams?.get("url") || "https://github.com/dubinc/dub";
@@ -24,7 +23,8 @@ export function LinkPreview({ defaultUrl }: { defaultUrl?: string }) {
description: string | null;
image: string | null;
}>(
- debouncedUrl && `/api/metatags?url=${encodeURIComponent(debouncedUrl)}`,
+ debouncedUrl &&
+ `/api/links/metatags?url=${encodeURIComponent(debouncedUrl)}`,
fetcher,
{
revalidateOnFocus: false,
@@ -56,13 +56,6 @@ export function LinkPreview({ defaultUrl }: { defaultUrl?: string }) {
className="block w-full rounded-md border-neutral-200 pl-10 text-sm text-neutral-900 placeholder-neutral-400 shadow-lg focus:border-neutral-500 focus:outline-none focus:ring-neutral-500"
placeholder="Enter your URL"
defaultValue={url}
- onChange={(e) =>
- router.replace(
- `/tools/metatags${
- e.target.value.length > 0 ? `?url=${e.target.value}` : ""
- }`,
- )
- }
aria-invalid="true"
/>
diff --git a/packages/utils/src/constants/layout.ts b/packages/utils/src/constants/layout.ts
index c874cda1b95..e1fca2a6ccc 100644
--- a/packages/utils/src/constants/layout.ts
+++ b/packages/utils/src/constants/layout.ts
@@ -8,6 +8,5 @@ export const ALL_TOOLS = [
{ name: "Google Link Shortener", slug: "google-link-shortener" },
{ name: "Amazon Link Shortener", slug: "amazon-link-shortener" },
{ name: "Figma Link Shortener", slug: "figma-link-shortener" },
- { name: "Metatags API", slug: "metatags" },
{ name: "Link Inspector", slug: "inspector" },
];
diff --git a/packages/utils/src/constants/main.ts b/packages/utils/src/constants/main.ts
index d2f6e607e7b..ce6e1928ec9 100644
--- a/packages/utils/src/constants/main.ts
+++ b/packages/utils/src/constants/main.ts
@@ -3,8 +3,6 @@ export const APP_NAME = process.env.NEXT_PUBLIC_APP_NAME || "Dub.co";
export const SHORT_DOMAIN =
process.env.NEXT_PUBLIC_APP_SHORT_DOMAIN || "dub.sh";
-export const HOME_DOMAIN = `https://${process.env.NEXT_PUBLIC_APP_DOMAIN}`;
-
export const APP_HOSTNAMES = new Set([
`app.${process.env.NEXT_PUBLIC_APP_DOMAIN}`,
`preview.${process.env.NEXT_PUBLIC_APP_DOMAIN}`,
diff --git a/packages/utils/src/functions/construct-metadata.ts b/packages/utils/src/functions/construct-metadata.ts
index 32756a6de2c..fecf6172043 100644
--- a/packages/utils/src/functions/construct-metadata.ts
+++ b/packages/utils/src/functions/construct-metadata.ts
@@ -1,5 +1,4 @@
import { Metadata } from "next";
-import { HOME_DOMAIN } from "../constants";
export function constructMetadata({
title,
@@ -73,7 +72,7 @@ export function constructMetadata({
creator: "@dubdotco",
},
icons,
- metadataBase: new URL(HOME_DOMAIN),
+ metadataBase: new URL("https://dub.co"),
...((url || canonicalUrl) && {
alternates: {
canonical: url || canonicalUrl,
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 8b7fc77cbda..a4ae930b647 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -361,8 +361,8 @@ importers:
specifier: ^1.5.0
version: 1.5.0
zod-openapi:
- specifier: ^2.19.0
- version: 2.19.0(zod@3.22.4)
+ specifier: ^4.2.4
+ version: 4.2.4(zod@3.22.4)
devDependencies:
'@types/he':
specifier: ^1.2.3
@@ -11921,9 +11921,9 @@ packages:
zod-error@1.5.0:
resolution: {integrity: sha512-zzopKZ/skI9iXpqCEPj+iLCKl9b88E43ehcU+sbRoHuwGd9F1IDVGQ70TyO6kmfiRL1g4IXkjsXK+g1gLYl4WQ==}
- zod-openapi@2.19.0:
- resolution: {integrity: sha512-OUAAyBDPPwZ9u61i4k/LieXUzP2re8kFjqdNh2AvHjsyi/aRNz9leDAtMGcSoSzUT5xUeQoACJufBI6FzzZyxA==}
- engines: {node: '>=16.11'}
+ zod-openapi@4.2.4:
+ resolution: {integrity: sha512-tsrQpbpqFCXqVXUzi3TPwFhuMtLN3oNZobOtYnK6/5VkXsNdnIgyNr4r8no4wmYluaxzN3F7iS+8xCW8BmMQ8g==}
+ engines: {node: '>=18'}
peerDependencies:
zod: ^3.21.4
@@ -25761,7 +25761,7 @@ snapshots:
dependencies:
zod: 3.22.4
- zod-openapi@2.19.0(zod@3.22.4):
+ zod-openapi@4.2.4(zod@3.22.4):
dependencies:
zod: 3.22.4