You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
I actually wanted to propose a slightly different change, and decouple the controller with the database.
Right now tests are very slow because they spool a whole DB, and any new changes will be very sequilize bound. Maybe it's because I don't really like sequalize, but I would like to have the domain logic (e.g.: hashing the password, or failing if there are no file) to live outside the class Post extends Model and leave the current Post class as a mere DTO to the database
Current implementation
Lets explore how one route would change. /posts/create is a big ofender:
// server/src/routes/posts.tsposts.post("/create",jwt,celebrate({// ---- All good. This is a route responsability 🆗 body: {title: Joi.string().required(),files: Joi.any().required(),visibility: Joi.string().custom(postVisibilitySchema,"valid visibility").required(),userId: Joi.string().required(),password: Joi.string().optional(),// expiresAt, allow to be nullexpiresAt: Joi.date().optional().allow(null,""),parentId: Joi.string().optional().allow(null,"")}}),async(req,res,next)=>{try{// check if all files have titlesconstfiles=req.body.filesasFile[]constfileTitles=files.map((file)=>file.title)constmissingTitles=fileTitles.filter((title)=>title==="")if(missingTitles.length>0){// ---- This is an invariant on all post->files. There should never be a post without titles 🙅 thrownewError("All files must have a title")}if(files.length===0){// ---- This again is an invariant on all post->files. 🙅 thrownewError("You must submit at least one file")}lethashedPassword: string=""if(req.body.visibility==="protected"){// ---- This again is transformation of the Post creation; not the router🙅 hashedPassword=crypto.createHash("sha256").update(req.body.password).digest("hex")}constnewPost=newPost({title: req.body.title,visibility: req.body.visibility,password: hashedPassword,expiresAt: req.body.expiresAt})awaitnewPost.save()// ---- Now we are crosing a lot of boundries, directly accesing the DB🙅 awaitnewPost.$add("users",req.body.userId)constnewFiles=awaitPromise.all(files.map(async(file)=>{consthtml=getHtmlFromFile(file)constnewFile=newFile({title: file.title||"",content: file.content,sha: crypto.createHash("sha256").update(file.content).digest("hex").toString(),html: html||"",userId: req.body.userId,postId: newPost.id})awaitnewFile.save()returnnewFile}))awaitPromise.all(newFiles.map(async(file)=>{awaitnewPost.$add("files",file.id)// ---- We have to manage timings on how sequalize like things to be stored🙅 awaitnewPost.save()}))if(req.body.parentId){// const parentPost = await Post.findOne({// where: { id: req.body.parentId }// })// if (parentPost) {// await parentPost.$add("children", newPost.id)// await parentPost.save()// }constparentPost=awaitPost.findByPk(req.body.parentId)if(parentPost){newPost.$set("parent",req.body.parentId)awaitnewPost.save()}else{thrownewError("Parent post not found")}}res.json(newPost)}catch(e){res.status(400).json(e)}})
Thanks for the thorough issue, this is a great idea. I just overlooked it while hacking together the initial version /:
Do you want to start an initial conversion starting in #76? Or maybe we should do it before more work is done there?
P.S. If you want to stay connected in IRC I can give you an account on my thelounge.chat instance. Send me an email at [email protected] if that's something you'd like.
I actually wanted to propose a slightly different change, and decouple the controller with the database.
Right now tests are very slow because they spool a whole DB, and any new changes will be very
sequilize
bound. Maybe it's because I don't really likesequalize
, but I would like to have the domain logic (e.g.: hashing the password, or failing if there are no file) to live outside theclass Post extends Model
and leave the currentPost
class as a mere DTO to the databaseCurrent implementation
Lets explore how one route would change.
/posts/create
is a big ofender:Proposed implementation
We can then discuss how to implement the dependency injection mechanism of the
postService
.The text was updated successfully, but these errors were encountered: