From 136cce99b650503f5bc1cfa372f6c11455020539 Mon Sep 17 00:00:00 2001 From: Waleed Latif Date: Wed, 4 Nov 2026 19:34:46 -0800 Subject: [PATCH] fix(links): keep long searches within the list limit A Links search over 200 characters failed client validation and showed the raw error. Cap it in the input and in the URL parser, the way People does, so a deep link stays valid too. --- apps/sim/app/o/[organizationId]/links/search-params.ts | 9 ++++++--- apps/sim/app/o/[organizationId]/links/sim-links.tsx | 3 ++- apps/sim/app/sim/[[...path]]/page.tsx | 8 ++------ 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/apps/sim/app/o/[organizationId]/links/search-params.ts b/apps/sim/app/o/[organizationId]/links/search-params.ts index 381e818a28a..1fb8368f3e0 100644 --- a/apps/sim/app/o/[organizationId]/links/search-params.ts +++ b/apps/sim/app/o/[organizationId]/links/search-params.ts @@ -1,14 +1,17 @@ -import { createSerializer, parseAsString } from 'nuqs/server' -import { SIM_LINK_SORTS } from '@/lib/sim-links/validation' +import { truncateAtCodePoint } from '@sim/utils/string' +import { createParser, createSerializer, parseAsString } from 'nuqs/server' +import { SIM_LINK_SEARCH_MAX_LENGTH, SIM_LINK_SORTS } from '@/lib/sim-links/validation' import { createSortParams } from '@/lib/url-state' +const boundedSearch = (value: string) => truncateAtCodePoint(value, SIM_LINK_SEARCH_MAX_LENGTH, '') + /** * `create` opens the new-link editor, prefilled with its value as the name. `search` filters by * name, destination, or description. */ export const simLinksParsers = { create: parseAsString, - search: parseAsString.withDefault(''), + search: createParser({ parse: boundedSearch, serialize: boundedSearch }).withDefault(''), } as const export const serializeSimLinkView = createSerializer(simLinksParsers) diff --git a/apps/sim/app/o/[organizationId]/links/sim-links.tsx b/apps/sim/app/o/[organizationId]/links/sim-links.tsx index ee0f8efa4c2..d966744ebb8 100644 --- a/apps/sim/app/o/[organizationId]/links/sim-links.tsx +++ b/apps/sim/app/o/[organizationId]/links/sim-links.tsx @@ -8,7 +8,7 @@ import { useQueryStates } from 'nuqs' import type { SimLink } from '@/lib/api/contracts/sim-links' import { useDeploymentShape } from '@/lib/core/config/deployment-shape' import { simLinkPath, simLinkUrl } from '@/lib/navigation/paths' -import { toSimLinkName } from '@/lib/sim-links/validation' +import { SIM_LINK_SEARCH_MAX_LENGTH, toSimLinkName } from '@/lib/sim-links/validation' import { SEARCH_DEBOUNCE_MS } from '@/lib/url-state' import { INSTALL_EXTENSION_ACTION, @@ -132,6 +132,7 @@ export function SimLinks({ organizationId }: SimLinksProps) { const searchConfig: SearchConfig = { value: search, + maxLength: SIM_LINK_SEARCH_MAX_LENGTH, onChange: setSearch, onClearAll: () => setSearch(''), placeholder: SIM_LINKS_SEARCH_PLACEHOLDER, diff --git a/apps/sim/app/sim/[[...path]]/page.tsx b/apps/sim/app/sim/[[...path]]/page.tsx index 4dcd852ff41..698a4ffee5d 100644 --- a/apps/sim/app/sim/[[...path]]/page.tsx +++ b/apps/sim/app/sim/[[...path]]/page.tsx @@ -9,11 +9,7 @@ import { type SimLinkResolution, suggestSimLinks, } from '@/lib/sim-links/application/use-cases' -import { - parseTypedSimLink, - SIM_LINK_SEARCH_MAX_LENGTH, - simLinkNameSchema, -} from '@/lib/sim-links/validation' +import { parseTypedSimLink, simLinkNameSchema } from '@/lib/sim-links/validation' import { buildAuthCrossLink } from '@/app/(auth)/auth-redirect' import { LogoShell } from '@/app/(landing)/components/logo-shell' import { serializeSimLinkView } from '@/app/o/[organizationId]/links/search-params' @@ -108,7 +104,7 @@ export default async function SimLinkPage({ params, searchParams }: SimLinkPageP const validName = simLinkNameSchema.safeParse(name).success // A name can't hold a space, so `sim card prices` is someone looking for a link, not naming one. if (result.kind === 'not_found' && /\s/.test(name)) { - redirect(serializeSimLinkView(library, { search: name.slice(0, SIM_LINK_SEARCH_MAX_LENGTH) })) + redirect(serializeSimLinkView(library, { search: name })) } const creatable = result.kind === 'not_found' && validName const similar = creatable