diff --git a/backend/src/activitypub/actors/index.ts b/backend/src/activitypub/actors/index.ts index 0b622f1..3bd94e2 100644 --- a/backend/src/activitypub/actors/index.ts +++ b/backend/src/activitypub/actors/index.ts @@ -224,14 +224,24 @@ export async function updateActorProperty(db: Database, actorId: URL, key: strin } export async function setActorAlias(db: Database, actorId: URL, alias: URL) { - const { success, error } = await db - .prepare( - `UPDATE actors SET properties=${db.qb.jsonSet('properties', 'alsoKnownAs', db.qb.jsonArray('?1'))} WHERE id=?2` - ) - .bind(alias.toString(), actorId.toString()) - .run() - if (!success) { - throw new Error('SQL error: ' + error) + if (db.client === 'neon') { + const { success, error } = await db + .prepare(`UPDATE actors SET properties=${db.qb.jsonSet('properties', 'alsoKnownAs,0', '?1')} WHERE id=?2`) + .bind('"' + alias.toString() + '"', actorId.toString()) + .run() + if (!success) { + throw new Error('SQL error: ' + error) + } + } else { + const { success, error } = await db + .prepare( + `UPDATE actors SET properties=${db.qb.jsonSet('properties', 'alsoKnownAs', 'json_array(?1)')} WHERE id=?2` + ) + .bind(alias.toString(), actorId.toString()) + .run() + if (!success) { + throw new Error('SQL error: ' + error) + } } } @@ -246,7 +256,16 @@ export async function getActorById(db: Database, id: URL): Promise } export function personFromRow(row: any): Person { - const properties = JSON.parse(row.properties) as PersonProperties + let properties + if (typeof row.properties === 'object') { + // neon uses JSONB for properties which is returned as a deserialized + // object. + properties = row.properties as PersonProperties + } else { + // D1 uses a string for JSON properties + properties = JSON.parse(row.properties) as PersonProperties + } + const icon = properties.icon ?? { type: 'Image', mediaType: 'image/jpeg', diff --git a/backend/src/database/d1.ts b/backend/src/database/d1.ts index e5a4ca9..f13b433 100644 --- a/backend/src/database/d1.ts +++ b/backend/src/database/d1.ts @@ -26,10 +26,6 @@ const qb: QueryBuilder = { return '' }, - jsonArray(r: string): string { - return `json_array(${r})` - }, - jsonSet(obj: string, field: string, value: string): string { return `json_set(${obj}, '$.${field}', ${value})` }, diff --git a/backend/src/database/index.ts b/backend/src/database/index.ts index bb6f685..9e17829 100644 --- a/backend/src/database/index.ts +++ b/backend/src/database/index.ts @@ -33,7 +33,6 @@ export interface QueryBuilder { epoch(): string insertOrIgnore(q: string): string psqlOnly(raw: string): string - jsonArray(r: string): string jsonSet(obj: string, field: string, value: string): string } diff --git a/backend/src/database/neon.ts b/backend/src/database/neon.ts index 062cc59..0dde858 100644 --- a/backend/src/database/neon.ts +++ b/backend/src/database/neon.ts @@ -12,7 +12,7 @@ function sqliteToPsql(query: string): string { const qb: QueryBuilder = { jsonExtract(obj: string, prop: string): string { - return `json_extract_path(${obj}::json, '${prop}')::text` + return `jsonb_extract_path(${obj}, '${prop}')::text` }, jsonExtractIsNull(obj: string, prop: string): string { @@ -35,12 +35,8 @@ const qb: QueryBuilder = { return q }, - jsonArray(r: string): string { - return `json_array_elements_text(${r})` - }, - jsonSet(obj: string, field: string, value: string): string { - return `jsonb_set(${obj}, '${field}', ${value})` + return `jsonb_set(${obj}, '{${field}}', ${value})` }, }