Skip to content

The Noob (Saibot?) Guide to mojo.js utilities.

KrisMatrix edited this page Nov 3, 2022 · 1 revision

Helpers

mojo.js Helpers are little functions (technically methods) that are available across your app. As the docs explain, it is a useful tool when you need to reuse some code throughout your whole application. It is available via context (ctx).

As a best practice, helper functions are usually created in your application script (src/index.ts). Since the application script connects to the controller files, the controller files thus have access to the helper functions. Therefore, any code, that may be reused in one or more controller files can be made into a helper function.

A good use case is to include a database or cache-store connection.

pg_host: postgres
pg_user: admin
pg_dbname: users_db
pg_password: password
pg_port: 5432
app.addHelper('postgres', ctx => {
  //connect to postgres database.
  let pg = new Pg('postgres://' + ctx.app.config.pg_user + ":" + ctx.app.cofig.pg_password + "@"
        + ctx.app.config.pg_host + ":" + ctx.app.config.pg_port + "/" + ctx.app.config.pg_dbname);

  return pg;
});

You can now connect to the postgres database in your controller files.

// in controller script

async validate_user(ctx: MojoContext): Promise<void> {
  // check whether the user's sign in credentials are valid.
  const pg = ctx.postgres();
  const pg_db = await pg.db();
  const params = await ctx.params();  // email and password
  const results = await pg.query`SELECT email, password FROM userdata WHERE userdata.email = ${params.get('email')}`;

  if (Object.keys(results).length == 0) {
    // email does not exist in our records, so return with error
    await ctx.render({json: {response: 'Error: No such email!'}});
  }
  else if (Object.keys(results).length == 1) {
    // .. add some code to verify password ..//
    await ctx.render({json: {response: 'Success'}});
  }
}

Here is an example of a helper for redis.

//config.yml
redis_host: localhost:6379
app.addHelper('redis', ctx => {
  // connect to redis cache-store
  let redis = createClient({
    url: 'redis://' + ctx.app.config.redis_host'
  });

  return redis;
});

User-Agent for APIs

When you want to make requests to an external API, you may not have the option of a pre-built module and need to build requests that connect the external API and get responses from them. We will illustrate how to do this with an example using Stripe's Payment Gateway API.

You are free to use stripe's own npm module, available here, but if you want to build your own requests you can do so using mojo.js user-agent. Here we will show you an example of creating a customer with Stripe's npm module and a similar request with mojo.js user-agent.

// Stripe npm module usage for creating a customer

import Stripe from 'stripe';

const stripe = new Stripe('sk_test_...', {
  apiVersion: '2022-08-01',
});

const createCustomer = async () => {
  const params: Stripe.CustomerCreateParams = {
    description: 'test customer',
  };

  const customer: Stripe.Customer = await stripe.customers.create(params);

  console.log(customer.id);
};
createCustomer();

To build your own request with Stripe's API, you want to look up Stripe's API reference for the curl command that will create a customer. You can find that reference here.

curl https://api.stripe.com/v1/customers \
  -u sk_test_... \
  -d description="test customer"
import {UserAgent} from '@mojojs/core';

const ua: UserAgent = new UserAgent();

const res = await ua.request({
  method: 'POST',
  url: new URL('https://api.stripe.com/v1/customers'),
  form: {
    'description': 'test customer',
  },
  auth: 'sk_test_...',
});

Why would you want to roll your own request mechanism instead of using a vendor-built module?

mojo.js user-agent comes pre-installed with the core mojo.js app. And as such, your implementation will likely minimize the size of your project. You also have greater control over what features you want and how you want to use them. Security concerns of external modules are also minimized. This however assumes that you know what you are doing.

Having said that, our purpose here is merely to show you how you could do it, in the event you want to use an external API for which you do not have a pre-built module.