Last active
October 23, 2020 13:35
-
-
Save the-frey/c766fc8996a164417e013e6516aaa643 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 'use strict'; | |
| import * as R from 'ramda'; | |
| import * as responses from '../../common/responses'; | |
| import * as db from '../../common/db'; | |
| import * as uDb from '../../common/users/db'; | |
| import * as uXfms from '../../common/users/transformations'; | |
| // welcome to the party, pal | |
| import { pipe } from 'fp-ts/lib/pipeable'; | |
| import * as T from 'fp-ts/lib/Task'; | |
| import * as E from 'fp-ts/lib/Either'; | |
| import * as TE from 'fp-ts/lib/TaskEither'; | |
| import { Do } from 'fp-ts-contrib/lib/Do'; | |
| const getIdFromPath = (event): E.Either<responses.Response, string> => { | |
| try { | |
| const userId = event.pathParameters.id; | |
| return E.right(userId); | |
| } catch (err) { | |
| return E.left(responses.respond400('your_project/error', 'Could not parse ID')); | |
| } | |
| }; | |
| const getUser = (client, userId: string): TE.TaskEither<responses.Response, any> => { | |
| return TE.tryCatch( | |
| // the anon fn creates a thunk, making the type Lazy<Promise<any>> | |
| // this pattern lifts us from regular promise ctx to TE ctx | |
| () => uDb.getUser(client, userId), | |
| () => responses.respond404('your_project/error', 'User does not exist') | |
| ); | |
| }; | |
| const getUserFromRes = (userRes): E.Either<responses.Response, User> => { | |
| const user = userRes.rows[0]; | |
| if (R.isNil(user)) { | |
| return E.left(responses.respond404('your_project/error', 'User does not exist')); | |
| } else { | |
| return E.right(user); | |
| } | |
| }; | |
| const userToPubliclyVisibleUser = (dbUser): E.Either<responses.Response, CCSharableUser> => { | |
| try { | |
| return E.right(uXfms.dbUserToSharableUser(dbUser)); | |
| } catch (err) { | |
| return E.left(responses.respond500('your_project/error', 'Error while serialising User')); | |
| } | |
| }; | |
| // this is an API endpoint | |
| // it has to return something comprehensible to the AWS SDK | |
| // to guard against runtime errors we use the outer try/catch/finally | |
| export const usersPublicGet = async (event): Promise<responses.Response> => { | |
| const client = await db.getDbConn(); | |
| try { | |
| const pipeline = Do(TE.taskEither) | |
| .bind('userId', TE.fromEither(getIdFromPath(event))) | |
| .bindL('getUserRes', ({userId}) => getUser(client, userId)) | |
| .bindL('user', ({getUserRes}) => TE.fromEither(getUserFromRes(getUserRes))) | |
| .bindL('userWithoutPII', ({user}) => TE.fromEither(userToPubliclyVisibleUser(user))) | |
| .return(({userWithoutPII}) => responses.respond200('your_project/user', userWithoutPII)); | |
| const run = pipe( | |
| pipeline, | |
| TE.fold( | |
| errRes => T.of(errRes), | |
| userRes => T.of(userRes) | |
| )); | |
| // TE API used to be TE.run() | |
| // but now you have to invoke with () | |
| const response = await run(); | |
| return response; | |
| } catch (err) { | |
| console.log(err); | |
| return responses.respond500('your_project/error', 'Something went wrong'); | |
| } finally { | |
| await db.closeDbConn(client); | |
| } | |
| }; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment