| 25 | } |
| 26 | |
| 27 | public async upsert(user: Partial<User>, client: DatabaseClient = this.dbClient): Promise<number> { |
| 28 | logger('upsert: %o', user) |
| 29 | |
| 30 | const date = new Date() |
| 31 | |
| 32 | const row = applySpec<DBUser>({ |
| 33 | pubkey: pipe(prop('pubkey'), toBuffer), |
| 34 | is_admitted: pipe(prop('isAdmitted'), defaultTo(false)), |
| 35 | is_vanished: pipe(prop('isVanished'), defaultTo(false)), |
| 36 | tos_accepted_at: prop('tosAcceptedAt'), |
| 37 | updated_at: always(date), |
| 38 | created_at: always(date), |
| 39 | })(user) |
| 40 | |
| 41 | const query = client<DBUser>('users') |
| 42 | .insert(row) |
| 43 | .onConflict('pubkey') |
| 44 | .merge(omit(['pubkey', 'balance', 'created_at'])(row)) |
| 45 | |
| 46 | return { |
| 47 | then: <T1, T2>( |
| 48 | onfulfilled: (value: number) => T1 | PromiseLike<T1>, |
| 49 | onrejected: (reason: any) => T2 | PromiseLike<T2>, |
| 50 | ) => query.then(prop('rowCount') as () => number).then(onfulfilled, onrejected), |
| 51 | catch: <T>(onrejected: (reason: any) => T | PromiseLike<T>) => query.catch(onrejected), |
| 52 | toString: (): string => query.toString(), |
| 53 | } as Promise<number> |
| 54 | } |
| 55 | |
| 56 | /** |
| 57 | * Returns vanish state from users.is_vanished, or lazily hydrates a user row from events once |