Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Conversation

@steven-tey
Copy link
Collaborator

@steven-tey steven-tey commented Oct 26, 2025

Summary by CodeRabbit

  • New Features

    • Enhanced partner search with improved filtering capabilities
  • Changes

    • Partner search interface updated to focus on name and email queries only
    • Campaign text body field removed

@vercel
Copy link
Contributor

vercel bot commented Oct 26, 2025

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Preview Updated (UTC)
dub Ready Ready Preview Oct 26, 2025 4:46am

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Oct 26, 2025

Walkthrough

This PR refactors partner search functionality to prioritize email-based filtering and implement full-text search sanitization. It introduces a new sanitizeFullTextSearch utility, updates search logic across API routes and client libraries, adds database indexes on partner email and name fields, and removes an unused body field from the Campaign model.

Changes

Cohort / File(s) Summary
Partner Search Logic
apps/web/app/(ee)/api/partners/count/route.ts, apps/web/lib/api/partners/get-partners.ts
Refactored search to implement email-first filtering logic. If email provided, filter by email directly; if search contains "@", match email; otherwise apply sanitizeFullTextSearch to both email and name fields. Replaces previous OR-based search across multiple fields.
Search UI Update
apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/program/partners/partners-table.tsx
Updated SearchBoxPersisted placeholder text to remove ID from search scope, narrowing search to name and email only.
Database Schema Updates
packages/prisma/schema/partner.prisma
Added three new indexes to Partner model: @@index([email]), @@index([name]), and @@fulltext([email, name]) for optimized search performance.
Full-Text Search Utility
packages/prisma/index.ts
Introduced new exported utility function sanitizeFullTextSearch(search: string) that removes unsupported characters (punctuation, whitespace) for full-text search compatibility.
Campaign Schema Cleanup
packages/prisma/schema/campaign.prisma
Removed unused optional body field (String\? @db.Text) from Campaign model.

Sequence Diagram

sequenceDiagram
    actor User
    participant UI as SearchBoxPersisted
    participant API as /api/partners/count
    participant Lib as get-partners.ts
    participant DB as Prisma<br/>Partner Query
    
    User->>UI: Enter search term
    UI->>API: GET /api/partners/count?search=term
    API->>Lib: getPartners({search, email})
    
    alt Email parameter provided
        Lib->>DB: WHERE email = {email}
    else Search contains "@"
        Lib->>DB: WHERE email CONTAINS {search}
    else Search is text
        Lib->>Lib: sanitized = sanitizeFullTextSearch(search)
        Lib->>DB: WHERE MATCH email, name AGAINST {sanitized}
    end
    
    DB-->>Lib: Partner results
    Lib-->>API: Filtered partners
    API-->>UI: Count result
    UI-->>User: Display results
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

  • Partner search refactoring: Verify the email-first logic is correctly applied across both the API route and library function, including edge cases where search may contain "@" or when email parameter is explicitly provided.
  • sanitizeFullTextSearch utility: Confirm character removal logic is appropriate for full-text search compatibility and doesn't inadvertently strip necessary search content.
  • Database indexes: Validate that new indexes on email, name, and the composite fulltext index align with query patterns and don't create redundancy or performance issues.
  • Schema field removal: Confirm that the removal of Campaign.body field has no downstream dependencies in queries, types, or API responses that weren't updated.

Possibly related PRs

Suggested reviewers

  • TWilson023

Poem

🐰 Hops with glee, searching email-first so bright,
Full-text sanitized for results just right,
Indexes bloom where partners play,
Campaign body swept away—
Faster searches hop through the night! ✨

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title Check ✅ Passed The title "Add fulltext search to GET /partners" directly and clearly describes the primary objective of this pull request. The changes systematically implement full-text search across multiple files: adding the sanitizeFullTextSearch utility function, updating the search logic in the GET /partners endpoint and related partner retrieval logic, and adding the necessary database indexes (email, name, and fulltext indexes on the Partner model). While the changeset includes an unrelated modification to the Campaign model (removing the body field), the title appropriately focuses on the main feature, which is consistent with the principle that titles don't need to cover every detail of the changeset.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch fulltext-partner-search

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between d713466 and 235fb13.

📒 Files selected for processing (6)
  • apps/web/app/(ee)/api/partners/count/route.ts (2 hunks)
  • apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/program/partners/partners-table.tsx (1 hunks)
  • apps/web/lib/api/partners/get-partners.ts (2 hunks)
  • packages/prisma/index.ts (1 hunks)
  • packages/prisma/schema/campaign.prisma (0 hunks)
  • packages/prisma/schema/partner.prisma (1 hunks)
💤 Files with no reviewable changes (1)
  • packages/prisma/schema/campaign.prisma
🧰 Additional context used
🧬 Code graph analysis (2)
apps/web/app/(ee)/api/partners/count/route.ts (2)
apps/web/lib/zod/schemas/partners.ts (1)
  • partnersCountQuerySchema (184-193)
packages/prisma/index.ts (1)
  • sanitizeFullTextSearch (19-23)
apps/web/lib/api/partners/get-partners.ts (1)
packages/prisma/index.ts (1)
  • sanitizeFullTextSearch (19-23)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: build
🔇 Additional comments (2)
apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/program/partners/partners-table.tsx (1)

414-416: LGTM — placeholder aligns with new name/email search scope.
Please ensure any docs/tooltips referencing ID search are updated as well.

packages/prisma/schema/partner.prisma (1)

81-83: Drop redundant email index; clarify intent for name index.

  • email already has @unique (line 30) → an extra @@index([email]) is redundant and adds write/read overhead. Unique constraints already optimize exact lookups.
  • @@index(name) appears to be new (no prior declaration found), not duplicate. The comment "Already exists" is misleading. Verify whether this index is intentional for query performance on the name field.
  • The composite @@fulltext([email, name]) is appropriate for full-text search.

Suggested change:

-  @@index([email])  // For exact email lookups
-  @@index(name)     // Already exists
+  @@index(name)
   @@fulltext([email, name])  // For full-text search

Or remove the name index entirely if it's not needed for query patterns. Please clarify the intent.

Comment on lines +17 to 27
...(email
? { email }
: search
? search.includes("@")
? { email: search }
: {
email: { search: sanitizeFullTextSearch(search) },
name: { search: sanitizeFullTextSearch(search) },
}
: {}),
...(partnerIds && {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

Search logic uses AND across email/name; should be OR. Also needs empty‑query guard.

Current block applies both email.search and name.search simultaneously (AND), causing near-zero matches and potential FTS errors when sanitized is empty.

Fix:

-    const commonWhere: Prisma.PartnerWhereInput = {
-      ...(email
-        ? { email }
-        : search
-          ? search.includes("@")
-            ? { email: search }
-            : {
-                email: { search: sanitizeFullTextSearch(search) },
-                name: { search: sanitizeFullTextSearch(search) },
-              }
-          : {}),
+    const sanitized =
+      search && !search.includes("@") ? sanitizeFullTextSearch(search) : undefined;
+
+    const searchWhere: Prisma.PartnerWhereInput =
+      email
+        ? { email }
+        : search
+        ? search.includes("@")
+          ? { email: search }
+          : sanitized
+          ? {
+              OR: [
+                { email: { search: sanitized } },
+                { name:  { search: sanitized } },
+              ],
+            }
+          : {}
+        : {};
+
+    const commonWhere: Prisma.PartnerWhereInput = {
+      ...searchWhere,
       ...(partnerIds && {
         id: { in: partnerIds },
       }),
     };

Consider making the email match case‑insensitive or partial if desired UX (e.g., contains with mode: 'insensitive'). Please confirm DB/provider supports the chosen FTS semantics.


I'll verify the review comment by examining the actual codebase.


🏁 Script executed:

#!/bin/bash
# 1. Check if the file exists and show lines around 17-27
fd "route.ts" --path "*partners/count*" --exec cat {} \;

Length of output: 215


🏁 Script executed:

#!/bin/bash
# 2. Find the sanitizeFullTextSearch function definition to understand its behavior
rg -n "sanitizeFullTextSearch" -A 5 -B 2 --type=ts --type=js

Length of output: 3320


🏁 Script executed:

#!/bin/bash
# 3. Get full context of the route.ts file to understand the complete logic
fd "route.ts" --path "*partners/count*" --exec wc -l {} \;

Length of output: 215


🏁 Script executed:

#!/bin/bash
# 4. Check Prisma schema to understand PartnerWhereInput structure
fd "schema.prisma" --exec cat {} \;

Length of output: 2710


🏁 Script executed:

#!/bin/bash
# Get full content of the partners count route file
cat "apps/web/app/(ee)/api/partners/count/route.ts"

Length of output: 3722


🏁 Script executed:

#!/bin/bash
# Find full where-clause context with more lines before/after
rg -n "commonWhere" -B 10 -A 5 "apps/web/app/(ee)/api/partners/count/route.ts"

Length of output: 2161


🏁 Script executed:

#!/bin/bash
# Check how the where clause is actually used in the query
rg -n "where.*commonWhere" -A 3 -B 3 --type=ts "apps/web/app/(ee)/api/partners/count"

Length of output: 0


AND logic in email/name search is overly restrictive; empty-string handling needed.

The review correctly identifies two issues:

  1. AND vs OR: Lines 23–24 simultaneously apply email.search AND name.search, making results far too restrictive (both must match). Typical UX expects OR (match either field).

  2. Empty string risk: sanitizeFullTextSearch() can return "" (e.g., if search is @ or contains only special chars). Passing empty string to Prisma full-text search on MySQL may cause errors or unexpected behavior.

The suggested fix is valid: extract and guard the sanitized value, then wrap both conditions in an OR block. This also affects the identical pattern in apps/web/lib/api/partners/get-partners.ts lines 58–59.

🤖 Prompt for AI Agents
In apps/web/app/(ee)/api/partners/count/route.ts lines 17-27 (and similarly in
apps/web/lib/api/partners/get-partners.ts around lines 58-59), the current logic
combines email.search and name.search with AND and passes the raw sanitized
string directly; fix by first computing a sanitizedSearch =
sanitizeFullTextSearch(search) and only add the full-text search block when
sanitizedSearch !== ""; when search includes "@" keep the existing equality
email match, otherwise replace the existing { email: { search: ... }, name: {
search: ... } } AND structure with an OR block that includes either { email: {
search: sanitizedSearch } } OR { name: { search: sanitizedSearch } }; ensure the
code falls back to no full-text filter if sanitizedSearch is empty to avoid
Prisma/MySQL errors.

Comment on lines +52 to +61
...(email
? { email }
: search
? search.includes("@")
? { email: search }
: {
email: { search: sanitizeFullTextSearch(search) },
name: { search: sanitizeFullTextSearch(search) },
}
: {}),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

Use OR across email/name and guard empty sanitized search.

Current where merges email.search and name.search as AND and doesn’t guard empty sanitized input.

Apply:

-              ...(email
-                ? { email }
-                : search
-                  ? search.includes("@")
-                    ? { email: search }
-                    : {
-                        email: { search: sanitizeFullTextSearch(search) },
-                        name: { search: sanitizeFullTextSearch(search) },
-                      }
-                  : {}),
+              ...(email
+                ? { email }
+                : search
+                ? search.includes("@")
+                  ? { email: search }
+                  : sanitizedSearch
+                  ? {
+                      OR: [
+                        { email: { search: sanitizedSearch } },
+                        { name:  { search: sanitizedSearch } },
+                      ],
+                    }
+                  : {}
+                : {}),

Add above the query (after destructuring):

const sanitizedSearch =
  search && !search.includes("@") ? sanitizeFullTextSearch(search) : undefined;

Please verify that results now include matches where either name or email satisfies the query and that whitespace‑only queries don’t throw.



---

🏁 Script executed:

```shell
#!/bin/bash
# Find and inspect the get-partners.ts file
fd 'get-partners\.ts' --type f

Length of output: 41


🏁 Script executed:

#!/bin/bash
# Inspect the file context around lines 40-70
cat apps/web/lib/api/partners/get-partners.ts | head -80 | tail -50

Length of output: 1080


🏁 Script executed:

#!/bin/bash
# Search for sanitizeFullTextSearch definition
rg -n 'sanitizeFullTextSearch' --type ts --type js -B2 -A5

Length of output: 3320


🏁 Script executed:

#!/bin/bash
# Look for count route mentioned in review
rg -n 'count.*where' apps/web/lib/api/partners/ -B3 -A3 --type ts

Length of output: 0


🏁 Script executed:

#!/bin/bash
# Get full context of the query to understand its structure
cat apps/web/lib/api/partners/get-partners.ts | head -100

Length of output: 2148



---

🏁 Script executed:

```shell
#!/bin/bash
# Inspect count route to compare with get-partners.ts
cat apps/web/app/(ee)/api/partners/count/route.ts

Length of output: 136


🏁 Script executed:

#!/bin/bash
# Search for other uses of Prisma OR pattern to confirm syntax
rg -n 'OR:\s*\[' apps/ -A3 --type ts --type js | head -40

Length of output: 2239


🏁 Script executed:

#!/bin/bash
# Verify sanitizeFullTextSearch edge cases
python3 << 'EOF'
import re

def sanitizeFullTextSearch(search):
    return re.sub(r'[*+\- ()~@%<>!=?:\s]', '', search).strip()

# Test cases
test_cases = [
    "john doe",
    "   ",
    "***---",
    "@@@",
    "[email protected]",
    "normal",
]

for test in test_cases:
    result = sanitizeFullTextSearch(test)
    print(f"'{test}' → '{result}' (empty: {not result})")
EOF

Length of output: 200



---

🏁 Script executed:

```shell
#!/bin/bash
# Find and read count route with proper escaping
find apps/web/app -path "*partners/count/route.ts" -type f -exec cat {} \;

Length of output: 7640


🏁 Script executed:

#!/bin/bash
# Confirm both files have the same search pattern issue
rg -n 'email.*search.*sanitizeFullTextSearch' apps/web/lib/api/partners/get-partners.ts apps/web/app -B1 -A1 --type ts

Length of output: 606


Use OR across email/name and guard empty sanitized search.

Current where merges email.search and name.search as AND, and doesn't guard empty sanitized input. The sanitizeFullTextSearch function can return an empty string when input is whitespace-only or contains only special characters, causing Prisma full-text search to fail or return unexpected results.

Also note: apps/web/app/(ee)/api/partners/count/route.ts lines 23-24 has the identical issue and needs the same fix for consistency.

Apply to apps/web/lib/api/partners/get-partners.ts:

-              ...(email
-                ? { email }
-                : search
-                  ? search.includes("@")
-                    ? { email: search }
-                    : {
-                        email: { search: sanitizeFullTextSearch(search) },
-                        name: { search: sanitizeFullTextSearch(search) },
-                      }
-                  : {}),
+              ...(email
+                ? { email }
+                : search
+                ? search.includes("@")
+                  ? { email: search }
+                  : sanitizedSearch
+                  ? {
+                      OR: [
+                        { email: { search: sanitizedSearch } },
+                        { name:  { search: sanitizedSearch } },
+                      ],
+                    }
+                  : {}
+                : {}),

Add above the query (after destructuring):

const sanitizedSearch =
  search && !search.includes("@") ? sanitizeFullTextSearch(search) : undefined;

Apply the same changes to apps/web/app/(ee)/api/partners/count/route.ts lines 20-26.

🤖 Prompt for AI Agents
In apps/web/lib/api/partners/get-partners.ts around lines 52 to 61, the current
merge builds email.search and name.search as an AND and doesn’t guard against
sanitizeFullTextSearch returning an empty string; create a sanitizedSearch
variable right after destructuring as: const sanitizedSearch = search &&
!search.includes("@") ? sanitizeFullTextSearch(search) : undefined; then change
the where clause to use an OR between email and name when using sanitizedSearch
(only include the full-text search conditions if sanitizedSearch is truthy) and
keep the direct email branch for exact email matches; apply the identical fix in
apps/web/app/(ee)/api/partners/count/route.ts around lines 20 to 26.

Comment on lines +19 to +23
export const sanitizeFullTextSearch = (search: string) => {
// remove unsupported characters for full text search
// '*', '+', '-', ' ', '(', ')', '~', '@','%', '<', '>', '=', '|', '!', '?', ':'
return search.replace(/[*+\- ()~@%<>!=?:\s]/g, "").trim();
};
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

Sanitizer can produce empty queries and over‑sanitize (drops spaces).

  • Returning "" risks FTS errors downstream.
  • Removing whitespace downgrades multi‑token search.

Refine and keep tokens:

-export const sanitizeFullTextSearch = (search: string) => {
-  // remove unsupported characters for full text search
-  // '*', '+', '-', ' ', '(', ')', '~', '@','%', '<', '>', '=', '|', '!', '?', ':'
-  return search.replace(/[*+\- ()~@%<>!=?:\s]/g, "").trim();
-};
+export const sanitizeFullTextSearch = (search: string) => {
+  // Keep letters/numbers/spaces; strip punctuation; collapse whitespace.
+  const sanitized = search
+    .normalize("NFKC")
+    .replace(/[^\p{L}\p{N}\s]+/gu, " ")
+    .replace(/\s+/g, " ")
+    .trim();
+  return sanitized;
+};

Please verify behavior for inputs like "john doe", "john-doe", "***", and whitespace-only.


I'll verify this review comment by examining the codebase and understanding the Prisma FTS constraints.





🏁 Script executed:

#!/bin/bash
# Find the file and inspect current implementation
fd -t f "index.ts" packages/prisma 2>/dev/null | head -5

Length of output: 24


🏁 Script executed:

#!/bin/bash
# Check content of the file
cat packages/prisma/index.ts

Length of output: 617


🏁 Script executed:

#!/bin/bash
# Search for uses of sanitizeFullTextSearch
rg -n "sanitizeFullTextSearch" --type=ts --type=js -C2

Length of output: 2331


🏁 Script executed:

#!/bin/bash
# Test the regex patterns and function behavior
node << 'EOF'
// Current implementation
const current = (search) => {
  return search.replace(/[*+\- ()~@%<>!=?:\s]/g, "").trim();
};

// Proposed implementation
const proposed = (search) => {
  const sanitized = search
    .normalize("NFKC")
    .replace(/[^\p{L}\p{N}\s]+/gu, " ")
    .replace(/\s+/g, " ")
    .trim();
  return sanitized;
};

const testCases = ["john doe", "john-doe", "***", "   ", "", "hello  world", "@@@test"];

console.log("TEST RESULTS:");
console.log("=".repeat(60));
testCases.forEach(input => {
  const curr = current(input);
  const prop = proposed(input);
  console.log(`Input: "${input}"`);
  console.log(`  Current: "${curr}" (empty: ${curr === ""})`);
  console.log(`  Proposed: "${prop}" (empty: ${prop === ""})`);
  console.log();
});
EOF

Length of output: 658


🌐 Web query:

Prisma full text search empty string MATCH AGAINST behavior PostgreSQL

💡 Result:

Short answer

  • Prisma's Postgres full-text search delegates to PostgreSQL. An empty/blank search string produces a tsquery with no lexemes (effectively an empty/non‑indexable query), so the match (@@) yields no matches — i.e., you get no rows unless you handle the empty input in your app/ORM layer. [1][2][3]

Why

  • Prisma's FTS API uses the database's native text‑search machinery (so behavior comes from PostgreSQL). [1]
  • PostgreSQL text‑search helpers such as plainto_tsquery/websearch_to_tsquery convert input text into a tsquery; if no lexemes survive (empty string or only stopwords), the resulting query is non‑indexable / empty and will not match documents. This is documented in PostgreSQL and reported in user Q&As. [2][3]

What to do

  • Check for empty/blank search strings in your application and:
    • skip the full‑text filter (return all rows or apply other filters), or
    • treat empty as a special case (e.g., fallback to ILIKE or a different query), or
    • build a tsquery yourself (e.g., avoid calling plainto_tsquery with '') if you want different behavior.
  • If you need web‑style parsing, consider websearch_to_tsquery but still guard empty input. [2][4]

References

  • Prisma docs: Full‑text search (Postgres uses DB native queries). [1]
  • PostgreSQL text‑search functions/operators (plainto_tsquery/websearch_to_tsquery, behavior with no surviving lexemes). [2]
  • Reports / Q&A showing plainto_tsquery/tsquery empty/no matches for empty/stopword inputs. [3]
  • PostgreSQL websearch_to_tsquery documentation (alternative, but still requires non‑empty input). [4]

Sources
[1] Prisma — Full‑Text Search (PostgreSQL).
[2] PostgreSQL docs — Text Search Functions and Operators / Controlling Text Search.
[3] Example discussions: StackOverflow (plainto_tsquery/no lexemes) and related threads.
[4] PostgreSQL docs — websearch_to_tsquery / plainto_tsquery.


🏁 Script executed:

#!/bin/bash
# Check if usage sites guard against empty strings after sanitization
cat apps/web/lib/api/partners/get-partners.ts | sed -n '50,70p'

Length of output: 556


🏁 Script executed:

#!/bin/bash
# Check the second usage site
cat apps/web/app/(ee)/api/partners/count/route.ts | sed -n '15,35p'

Length of output: 154


🏁 Script executed:

#!/bin/bash
# Fix path escaping for second usage site
cat "apps/web/app/(ee)/api/partners/count/route.ts" | sed -n '15,35p'

Length of output: 576


🏁 Script executed:

#!/bin/bash
# Get broader context around first usage to see full conditional logic
cat apps/web/lib/api/partners/get-partners.ts | sed -n '40,75p'

Length of output: 839


Proposed fix is incomplete—addresses space removal but not empty-string risk.

The review correctly identifies two problems: space removal (hurts multi-token search) and empty strings (break FTS). The proposed diff fixes space preservation but leaves the empty-string issue unresolved.

Test results:

  • Current: "***""" (empty, breaks FTS)
  • Proposed: "***""" (still empty, still breaks FTS)

Both call sites (get-partners.ts, count/route.ts) pass the sanitized value directly to Prisma without checking for empty strings. Per PostgreSQL behavior, an empty tsquery yields no results.

Refine the proposed fix to guard against empty results:

export const sanitizeFullTextSearch = (search: string) => {
  // Keep letters/numbers/spaces; strip punctuation; collapse whitespace.
  const sanitized = search
    .normalize("NFKC")
    .replace(/[^\p{L}\p{N}\s]+/gu, " ")
    .replace(/\s+/g, " ")
    .trim();
  return sanitized || null;  // Return null if empty to signal invalid query
};

Then update call sites to skip FTS when the result is null/empty:

: search
  ? search.includes("@")
    ? { email: search }
-   : {
+   : sanitizeFullTextSearch(search) ? {
        email: { search: sanitizeFullTextSearch(search) },
        name: { search: sanitizeFullTextSearch(search) },
      }
+   : {}

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
In packages/prisma/index.ts around lines 19 to 23, the sanitizer currently
strips unsupported characters but can return an empty string (e.g., "***"),
which breaks PostgreSQL full-text search; change sanitizeFullTextSearch to
preserve spaces where appropriate and return null (or undefined) instead of an
empty string when the sanitized result contains no alphanumeric tokens (i.e.,
after trimming and collapsing multiple spaces, if the string is empty or only
non-word characters, return null). Then update call sites (get-partners.ts and
count/route.ts) to check the sanitizer's result and skip adding the Prisma
full-text-search condition when the value is null/empty (use the non-FTS
fallback or omit the where clause), ensuring no empty tsquery is passed to
Prisma.

@steven-tey steven-tey merged commit 736d33d into main Oct 26, 2025
8 checks passed
@steven-tey steven-tey deleted the fulltext-partner-search branch October 26, 2025 04:50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants