Home > Software design >  Javascript - Dependency between arguments of partial applications
Javascript - Dependency between arguments of partial applications

Time:05-10

Introduction

I have created the given partial application in my module:

// GENERIC
const sendEmail = (subject, template) =>
  async (to, ...props) => {
    const mailsRef = firestore.collection("mails");
    const html = template(...props);
    const mail = {
      to,
      message: {
        subject,
        html,
      },
    };

    await mailsRef.add(mail);

    functions.logger.log("Email queued for delivery!");
  };

// SPECIFIC
const sendUpdatePasswordEmail = sendEmail(
  "Your password has been updated.",
  updatePasswordHTMLTemplate
);

const sendSignUpWelcomeEmail = sendEmail(
  "Welcome to Binance!",
  signUpWelcomeHTMLTemplate
);

const sendBitcoinAddressUpdatedEmail = sendEmail(
  "Your bitcoin address has been updated.",
  bitcoinWalletAddressHTMLTemplate
);

As you can see, my sendUpdatePasswordEmail pass a subject and HTML template generator to the sendEmail function.

This is how my updatePasswordHTMLTemplate looks like:

const updatePasswordHTMLTemplate = (language) => `
  <!DOCTYPE html>
  <html lang="${language}">
  ...
  <body>
    <h1>${t("auth.password.update.title", language)}</h1>
  </body>
  </html>
`;

As you can see, I am internationalizing the emails I send to the final users, using some kind of i18n.

Problem

The problem I am experiencing is that I need a way to pass, as argument, the user's language to my sendUpdatePasswordEmail function. And, also, I need to translate the subject of the email:

const sendUpdatePasswordEmail = sendEmail(
  "Your password has been updated.", <--- t("auth.password.update.subject", language)
  updatePasswordHTMLTemplate
);

Is there any design pattern I should use here? I mean, as you can see, I used the partial application in order to "generalize" my code, making it more readable, but the big problem comes with the subject translation...

This is the way I use the methods I described:

const { email, language } = context.auth.token;

await sendUpdatePasswordEmail(email); // I need to pass the language!

Any ideas? Thank you.


I have thought to do something like:

const sendUpdatePasswordEmail = (language) => sendEmail(
  t("subject.scope", language), 
  updatePasswordTemplate,
  language
);

But then, I would have to use the method as follows:

sendUpdatePasswordEmail(language)(emailAddress);

and I don't like it (not a clean way).

CodePudding user response:

I would suggest to simply make the subject parameter a function accepting a language as well, just like your template parameter already is:

const makeSendEmail = (subjectTemplate, bodyTemplate) => async (to, ...props) => {
    const mailsRef = firestore.collection("mails");
    const subject = subjectTemplate(...props);
    const html = bodyTemplate(...props);
    const mail = {…};
    …
};

Then use

const sendUpdatePasswordEmail = makeSendEmail(
  (language) => t("subject.scope", language), 
  updatePasswordTemplate
);

and call

sendUpdatePasswordEmail(emailAddress, language);

as before

  • Related