From d90826e8510c98a8bfa4194505f7ac4c00b77f9a Mon Sep 17 00:00:00 2001 From: MartinBraquet Date: Fri, 24 Oct 2025 01:30:03 +0200 Subject: [PATCH] Create bookmarked searches in the backend --- backend/api/src/app.ts | 2 ++ backend/api/src/create-bookmarked-search.ts | 23 +++++++++++++++++++++ common/src/api/schema.ts | 12 +++++++++++ web/lib/supabase/searches.ts | 14 +++++-------- 4 files changed, 42 insertions(+), 9 deletions(-) create mode 100644 backend/api/src/create-bookmarked-search.ts diff --git a/backend/api/src/app.ts b/backend/api/src/app.ts index 030c0afb..0e72fabc 100644 --- a/backend/api/src/app.ts +++ b/backend/api/src/app.ts @@ -60,6 +60,7 @@ import {createVote} from "api/create-vote"; import {vote} from "api/vote"; import {contact} from "api/contact"; import {saveSubscription} from "api/save-subscription"; +import {createBookmarkedSearch} from './create-bookmarked-search' // const corsOptions: CorsOptions = { // origin: ['*'], // Only allow requests from this domain @@ -185,6 +186,7 @@ const handlers: { [k in APIPath]: APIHandler } = { 'get-messages-count': getMessagesCount, 'set-last-online-time': setLastOnlineTime, 'save-subscription': saveSubscription, + 'create-bookmarked-search': createBookmarkedSearch, } Object.entries(handlers).forEach(([path, handler]) => { diff --git a/backend/api/src/create-bookmarked-search.ts b/backend/api/src/create-bookmarked-search.ts new file mode 100644 index 00000000..2dc0bd75 --- /dev/null +++ b/backend/api/src/create-bookmarked-search.ts @@ -0,0 +1,23 @@ +import {APIHandler} from './helpers/endpoint' +import {createSupabaseDirectClient} from 'shared/supabase/init' + +export const createBookmarkedSearch: APIHandler<'create-bookmarked-search'> = async ( + props, + auth +) => { + const creator_id = auth.uid + const {search_filters, location = null, search_name = null} = props + + const pg = createSupabaseDirectClient() + + const inserted = await pg.one( + ` + INSERT INTO bookmarked_searches (creator_id, search_filters, location, search_name) + VALUES ($1, $2, $3, $4) + RETURNING * + `, + [creator_id, search_filters, location, search_name] + ) + + return inserted +} diff --git a/common/src/api/schema.ts b/common/src/api/schema.ts index 2e496bc8..f94c8e10 100644 --- a/common/src/api/schema.ts +++ b/common/src/api/schema.ts @@ -583,6 +583,18 @@ export const API = (_apiTypeCheck = { subscription: z.record(z.any()) }), }, + 'create-bookmarked-search': { + method: 'POST', + authed: true, + rateLimited: true, + returns: {} as Row<'bookmarked_searches'>, + props: z + .object({ + search_filters: z.any().optional(), + location: z.any().optional(), + search_name: z.string().nullable().optional(), + }), + }, } as const) export type APIPath = keyof typeof API diff --git a/web/lib/supabase/searches.ts b/web/lib/supabase/searches.ts index d6157d5d..ee2543c7 100644 --- a/web/lib/supabase/searches.ts +++ b/web/lib/supabase/searches.ts @@ -4,6 +4,7 @@ import {filterKeys} from "web/components/questions-form"; import {track} from "web/lib/service/analytics"; import {removeNullOrUndefinedProps} from "common/util/object"; import {FilterFields} from "common/filters"; +import {api} from "web/lib/api"; export const getUserBookmarkedSearches = async (userId: string) => { @@ -19,7 +20,7 @@ export const getUserBookmarkedSearches = async (userId: string) => { export type BookmarkedSearchSubmitType = Omit< Row<'bookmarked_searches'>, - 'created_time' | 'id' | 'last_notified_at' + 'created_time' | 'id' | 'last_notified_at' | 'creator_id' > export const submitBookmarkedSearch = async ( @@ -33,17 +34,12 @@ export const submitBookmarkedSearch = async ( const row = { search_filters: removeNullOrUndefinedProps(filters), location: locationFilterProps?.location ? locationFilterProps : null, - creator_id: userId, } - const input = { - ...filterKeys(row, (key, _) => !['id', 'created_time', 'last_notified_at'].includes(key)), + const props = { + ...filterKeys(row, (key, _) => !['id', 'created_time', 'last_notified_at', 'creator_id'].includes(key)), } as BookmarkedSearchSubmitType - await run( - db.from('bookmarked_searches').upsert(input) - ).then(() => { - track('bookmarked_searches submit', {...filters}) - }) + await api('create-bookmarked-search', props) } export const deleteBookmarkedSearch = async (