Files
Compass/backend/api/src/update-options.ts
Martin Braquet ba9b3cfb06 Add pretty formatting (#29)
* Test

* Add pretty formatting

* Fix Tests

* Fix Tests

* Fix Tests

* Fix

* Add pretty formatting fix

* Fix

* Test

* Fix tests

* Clean typeckech

* Add prettier check

* Fix api tsconfig

* Fix api tsconfig

* Fix tsconfig

* Fix

* Fix

* Prettier
2026-02-20 17:32:27 +01:00

85 lines
2.7 KiB
TypeScript

import {APIError, APIHandler} from 'api/helpers/endpoint'
import {OPTION_TABLES} from 'common/profiles/constants'
import {tryCatch} from 'common/util/try-catch'
import {createSupabaseDirectClient} from 'shared/supabase/init'
import {log} from 'shared/utils'
export const updateOptions: APIHandler<'update-options'> = async ({table, values}, auth) => {
if (!OPTION_TABLES.includes(table)) throw new APIError(400, 'Invalid table')
if (!values || !Array.isArray(values)) {
throw new APIError(400, 'No ids provided')
}
const idsWithNumbers = values.map((id) => {
const numberId = Number(id)
return isNaN(numberId) ? {isNumber: false, v: id} : {isNumber: true, v: numberId}
})
const names: string[] = idsWithNumbers
.filter((item) => !item.isNumber)
.map((item) => item.v) as string[]
const ids: number[] = idsWithNumbers
.filter((item) => item.isNumber)
.map((item) => item.v) as number[]
log('Updating profile options', {table, ids, names})
const pg = createSupabaseDirectClient()
const profileIdResult = await pg.oneOrNone<{id: number}>(
'SELECT id FROM profiles WHERE user_id = $1',
[auth.uid],
)
if (!profileIdResult) throw new APIError(404, 'Profile not found')
const profileId = profileIdResult.id
const result = await tryCatch(
pg.tx(async (t) => {
const currentOptionsResult = await t.manyOrNone<{id: string}>(
`SELECT option_id as id
FROM profile_${table}
WHERE profile_id = $1`,
[profileId],
)
const currentOptions = currentOptionsResult.map((row) => row.id)
if (currentOptions.sort().join(',') === ids.sort().join(',') && !names?.length) {
log(`Skipping /update-${table} because they are already the same`)
return undefined
}
// Add new options
for (const name of names || []) {
const row = await t.one<{id: number}>(
`INSERT INTO ${table} (name, creator_id)
VALUES ($1, $2)
ON CONFLICT (name) DO UPDATE
SET name = ${table}.name
RETURNING id`,
[name, auth.uid],
)
ids.push(row.id)
}
// Delete old options for this profile
await t.none(`DELETE FROM profile_${table} WHERE profile_id = $1`, [profileId])
// Insert new option_ids
if (ids.length > 0) {
const values = ids.map((id, i) => `($1, $${i + 2})`).join(', ')
await t.none(`INSERT INTO profile_${table} (profile_id, option_id) VALUES ${values}`, [
profileId,
...ids,
])
}
return ids
}),
)
if (result.error) {
log('Error updating profile options', result.error)
throw new APIError(500, 'Error updating profile options')
}
return {updatedIds: result.data}
}