-
Notifications
You must be signed in to change notification settings - Fork 0
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
1. BIG server clean & API response schema standardization #266
Conversation
FROM inserted | ||
) | ||
) AS "photoIds" | ||
`, [userId, photoCount + 1, uuid, userId]); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Return the new photoIds!
return apiUtils.status(409).json({ | ||
status: codes.DELETE_PHOTO__CANNOT_DELETE_LAST_PHOTO, | ||
}); | ||
return apiUtils.status(codes.DELETE_PHOTO__NOT_FOUND).noData(); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This removes the server check that it is a user's last photo.
SET splash_photo_id = $1 | ||
WHERE user_id = $2 | ||
`, [photos[0].id, userId]); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Delete "splash photo id"
${updatedPhotos.join(',')} | ||
) AS updated_photos (id, index) | ||
WHERE photos.id = updated_photos.id | ||
`); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No need to reorder the photos if there are no photos! This just wraps the old query in an if statement
|
||
return apiUtils.status(codes.DELETE_PHOTO__SUCCESS).data( | ||
_.map(photos, photo => photo.id), | ||
); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Return the new photo order
status: codes.GET_PHOTO__NOT_FOUND, | ||
}); | ||
// $FlowFixMe I'm really not sure what's going on here...it's only HERE | ||
return apiUtils.status(codes.GET_PHOTO__NOT_FOUND).noData(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is weird...I'm not worried about it and I'm pretty sure it's flow getting confused. Will look into it more
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Spent a little time debugging this. I think the root of this is the implicit types returned by functions; feels like it should work, perhaps related to:
facebook/flow#5294
I tested out a solution there by explicitly typing the return type (which is safe, as flow does make sure it's a valid return type).
const foo: { body: { status: string }, statusCode: number } = apiUtils
.status(codes.GET_PHOTO__NOT_FOUND)
.noData();
return foo;
Worth looking into later the deeper cause of this, but how about for now at least keeping this with a TODO comment so that the export here is well typed
// If the photo was succesfully retrieved, redirect to it! | ||
// NOTE: This is "abnormal" by the standards of the API | ||
if (photoRes.body.status === codes.GET_PHOTO__SUCCESS.status) { | ||
return res.redirect(photoRes.body.data.url); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This handles the redirect. Internally, we still have a GET_PHOTO__SUCCCES response
return apiUtils.status(200).json({ | ||
status: codes.REORDER_PHOTOS__SUCCESS, | ||
photos: newOrder, | ||
}); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Delete stuff about splash photo
@@ -4,6 +4,7 @@ import type { $Request } from 'express'; | |||
|
|||
const db = require('../../db'); | |||
const apiUtils = require('../utils'); | |||
const { profileSelectQuery } = require('../users/utils'); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This allows for a standard profile select query. This is nice and standardized and I use it in a few places.
candidates: result.rows, | ||
}); | ||
|
||
`, [userId, excludedUsers]); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I realized you can reuse paramaters...duh. Also it is better practice to USE paramaters
to_char(profile.birthday, 'YYYY-MM-DD') AS birthday, | ||
profile.bio | ||
profile.user_id AS "userId", | ||
${profileSelectQuery('profile.user_id', { tableAlias: 'profile', buildJSON: true })} AS profile |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This returns it in the format we discussed with profile, fields, and photoIds
last_swipe_timestamp = now() | ||
`, [userId, candidateUserId, liked, liked]); | ||
`, [userId, candidateUserId, liked]); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
you can reuse params
@@ -1,173 +1,221 @@ | |||
// @flow |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This whole file is changed and just has nicer abstraction over the 'code'. Much cleaner now
@@ -3,7 +3,7 @@ | |||
import type { $Request } from 'express'; | |||
|
|||
const apiUtils = require('../utils'); | |||
const utils = require('./utils'); | |||
const { validateProfile, profileSelectQuery } = require('./utils'); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Better to do imports like this
SET display_name = EXCLUDED.display_name | ||
RETURNING | ||
${profileSelectQuery('$5')}, | ||
(xmax::text::int > 0) as existed |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is cool. 'existed' checks to see if it hit a conflict or not. If existed is true, then there was a conflict.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
some comments during my 15 break in class haha
return apiUtils.status(400).json({ | ||
status: codes.SEND_VERIFICATION_EMAIL__UTLN_NOT_FOUND, | ||
}); | ||
return apiUtils.status(codes.SEND_VERIFICATION_EMAIL__UTLN_NOT_FOUND).noData(); | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: lots of reuse of .classyear and such, in general on these I think it would be a good idea to use destructure {classyear} = memberinfo in these
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I totally agree...I think that's a separate PR. I started doing that for some util functions too and I'd like to do a full sweep
@@ -42,26 +42,20 @@ const verify = async (utln: string, code: number) => { | |||
|
|||
// No email has been sent for this utln | |||
if (result.rowCount === 0) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is more of a syntac standardization idea, but I was thinking we could do
result.rowCount === 0 && return apiUtils...
for these kinda things? It would really clean up lots of code that's lots of conditional chaining
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is that cleaner in general? I guess I don't see that as more readable
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
More incremental comments
@@ -92,29 +77,21 @@ const deletePhoto = async (photoId: number, userId: number, userHasProfile: bool | |||
|
|||
// 4. Commit the transaction! | |||
await client.query('COMMIT'); | |||
|
|||
return apiUtils.status(codes.DELETE_PHOTO__SUCCESS).data( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can this happen in the finally
? It's dangerous to put anything after the s3Delete, because theoretically any additional code could trigger the rollback, but s3 would have been changed.
Actually, for this reason I think step 3 and 4 should also be switched.
}; | ||
|
||
const handler = [ | ||
apiUtils.asyncHandler(async (req: $Request) => { | ||
return deletePhoto(Number.parseInt(req.params.photoId, 10), req.user.id, req.user.hasProfile); | ||
return deletePhoto(Number.parseInt(req.params.photoId, 10), req.user.id); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think that the Number.parseInt
should be abstracted to a photoUtils function if we pass the same constant base 10 to it every time.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Params.photoId comes in as a string. I am about to refactor this endpoint to be MUCH simpler using a new way of ordering photos using a trigger. This will remove the need for the photoId to come in as a number and instead allow it to come in as a string. Therefore, I'd prefer not to add a utility here as it will soon be removed
status: codes.GET_PHOTO__NOT_FOUND, | ||
}); | ||
// $FlowFixMe I'm really not sure what's going on here...it's only HERE | ||
return apiUtils.status(codes.GET_PHOTO__NOT_FOUND).noData(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Spent a little time debugging this. I think the root of this is the implicit types returned by functions; feels like it should work, perhaps related to:
facebook/flow#5294
I tested out a solution there by explicitly typing the return type (which is safe, as flow does make sure it's a valid return type).
const foo: { body: { status: string }, statusCode: number } = apiUtils
.status(codes.GET_PHOTO__NOT_FOUND)
.noData();
return foo;
Worth looking into later the deeper cause of this, but how about for now at least keeping this with a TODO comment so that the export here is well typed
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
see comments
return apiUtils.status(400).json({ | ||
status: codes.REORDER_PHOTOS__MISMATCHED_IDS, | ||
}); | ||
return apiUtils.status(codes.REORDER_PHOTOS__MISMATCHED_IDS).noData(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can we return or log the mismatches?
edit: made a task
@@ -75,8 +75,74 @@ function getFieldTemplates(definedFields: Array<[string, any]>) { | |||
}; | |||
} | |||
|
|||
const DefaultProfileOptions = { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Comments please
@@ -11,7 +11,8 @@ const asyncHandler = (fn : Middleware) => { | |||
return (req: $Request, res: $Response, next: NextFunction) => { | |||
Promise.resolve(fn(req, res, next)) | |||
.then((response) => { | |||
res.status(response.status).json(response.body); | |||
// This is where the magic happens |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
please elaborate
Ok so I did this in a really dumb order and never committed and it was bad. I'm really sorry. I will not do that again. Here's what changed: