78-Nodejs Course 2023: Resources: Custom Output handlers
Tags: node, typescript, mongodb, fastify
Published: 2022-12-02 18:45:40

---
title: 78-Nodejs Course 2023: Resources: Custom Output handlers
published: true
description: 
series: Nodejs Course 2023
tags: nodejs, typescript, mongodb, fastify
cover_image: https://dev-to-uploads.s3.amazonaws.com/uploads/articles/obtk5gpvxlk0lw3gg6ax.png
# Use a ratio of 100:42 for best results.
---

We already defined out output cast types in our previous chapter, now let's see how we can define custom output handlers.

## Purpose

Sometimes we want to customize the final output of certain value, for example using `uploadsUrl` to generate a full url for the uploaded file as we store only in the database the relative path of uploads directory thus we need to return full url for the uploaded file.

## Custom output handler

This is where we can define our custom output handlers, let's take an example to make everything clear, let's update our user resource class.

```ts
// src/app/users/resources/user-resource.ts
import Resource from 'core/resources/resource';
import { uploadsUrl } from 'core/utils/urls';

export default class UserResource extends Resource {
  /**
   * Output shape
   */
  protected output: any = {
    id: 'number',
    name: 'string',
    email: 'string',
    age: 'number',
    avatar: uploadsUrl,
  };
}
```

Of course this will not work as we didn't transform the call of `uploadsUrl` to be a function call, so let's do that in our base resource class

```ts
// src/core/resources/resource.ts
import { get } from "@mongez/reinforcements";

// this will be used to skip the output property if it is missing from the given resource
const missingKey = Symbol("missing");

export default class Resource {
  /**
   * Constructor
   */
  public constructor(protected resource: any = {}) {
    //
  }

  /**
   * Output shape
   */
  protected output: any = {};

  /**
   * {@inheritDoc}
   */
  public toJSON() {
    // final output
    const data: Record<string, any> = {};

    // loop through the output property
    for (const key in this.output) {
      // get the value type
      const valueType = this.output[key];
      // get the value, and also make sure to skip the output property if it is missing from the given resource
      let value = get(this.resource, key, missingKey);

      // skip the output property if it is missing from the given resource
      if (value === missingKey) {
        continue;
      }

      if (typeof valueType === "string") {
        // cast the value
        value = this.cast(value, valueType);
      } else if (typeof valueType === "function") {
        // call the custom output handler
        value = valueType(value);
      }

      // just for now sett the output value to the data
      data[key] = value;
    }

    return data;
  }
  
  /**
   * Builtin casts
   */
  protected cast(value: any, type: string) {
    switch (type) {
      case "number":
        return Number(value);
      case "float":
      case "double":
        return parseFloat(value);
      case "int":
      case "integer":
        return parseInt(value);
      case "string":
        return String(value);
      case "boolean":
        return Boolean(value);
      default:
        return value;
    }
  }
}
```

We added another if statement to check the value type, if it is a function then we call it and pass the value to it, and then we return the result.

Now when we check the response, we'll see something like this.

`"image": "http://127.0.0.1:3000/uploads/users/my-image.jpg"`

As we only have in the resource object, `users/my-image.jpg` and we want to return the full url.

## 🎨 Conclusion

In this chapter, we added another feature which is using custom output handler to mutate the final output value as we want, this will give us much flexibility to customize the final output.

In our next chapter, we'll see how to use nested resources, a resource inside another resource!, stay tuned.

## ☕♨️ Buy me a Coffee ♨️☕

If you enjoy my articles and see it useful to you, you may [buy me a coffee](https://www.paypal.com/paypalme/hassanzohdy), it will help me to keep going and keep creating more content.

## 🚀 Project Repository

You can find the latest updates of this project on [Github](https://github.com/hassanzohdy/nodejs-2023)

## 😍 Join our community

Join our community on [Discord](https://discord.gg/pb2vmdfhGf) to get help and support (Node Js 2023 Channel).

## 🎞️ Video Course (Arabic Voice)

If you want to learn this course in video format, you can find it on [Youtube](https://www.youtube.com/playlist?list=PLGO8ntvxgiZMJc7RN2lIq9WmMOlWZGzmz), the course is in Arabic language.

## 📚 Bonus Content 📚

You may have a look at these articles, it will definitely boost your knowledge and productivity.

General Topics

* [Event Driven Architecture: A Practical Guide in Javascript](https://dev.to/hassanzohdy/event-driven-architecture-the-best-paradigm-that-i-love-to-work-with-in-javascript-and-node-js-1gnk)
* [Best Practices For Case Styles: Camel, Pascal, Snake, and Kebab Case In Node And Javascript](https://dev.to/hassanzohdy/best-practices-for-case-styles-camel-pascal-snake-and-kebab-case-in-node-and-javascript-55oi)
* [After 6 years of practicing MongoDB, Here are my thoughts on MongoDB vs MySQL
](https://dev.to/hassanzohdy/after-6-years-of-practicing-mongodb-here-are-my-thoughts-on-mongodb-vs-mysql-574b)

Packages & Libraries

* [Collections: Your ultimate Javascript Arrays Manager](https://dev.to/hassanzohdy/collections-your-ultimate-javascript-array-handler-3o15)
* [Supportive Is: an elegant utility to check types of values in JavaScript](https://dev.to/hassanzohdy/supportive-is-an-elegant-utility-to-check-types-of-values-in-javascript-1b3e)
* [Localization: An agnostic i18n package to manage localization in your project](https://dev.to/hassanzohdy/mongez-localization-the-simplest-way-to-translate-your-website-regardless-your-favorite-framework-4gi3)

 React Js Packages

* [useFetcher: easiest way to fetch data in React Js](https://dev.to/hassanzohdy/usefetcher-the-easiest-way-to-fetch-data-in-react-45o9)

Courses (Articles)

* [OOP In JS And TS From The Very Beginning](https://dev.to/hassanzohdy/jsts-oop-course-1-introduction-2ld)
* [ES6++: The Ultimate Guide to ES6 and Beyond](https://dev.to/hassanzohdy/es6-1-introduction-h3e)
* [React Js: Let"s Create File Manager With React Js and Node Js](https://dev.to/hassanzohdy/lets-create-a-file-manager-from-scratch-with-react-and-typescript-chapter-i-a-good-way-to-expand-your-experience-5g4k)