83-Nodejs Course 2023: Resources: Allowed And Disabled Outputs
Tags: node, typescript, mongodb, fastify
Published: 2022-12-03 13:14:42

---
title: 83-Nodejs Course 2023: Resources: Allowed And Disabled Outputs
published: true
description: 
series: Nodejs Course 2023
tags: nodejs, typescript, mongodb, fastify
cover_image: https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1qkweda3dlmrptv6bund.png
# Use a ratio of 100:42 for best results.
---

Sometimes, we can use the resource in multiple apis, for example we may use the resource for admin api and for the front office (Website or mobile app) api, therefore some keys can be displayed in the admin but not in the front office.

For example, the `published` key probably won't be needed in the front office, but it will be needed in the admin thus we need to disable it if it was sent to the resource so it doesn't get displayed in the front office.

## Allowed And Disabled Outputs

To achieve this, we need to define two static properties, `disabledKeys` and `allowedKeys`, these properties will be used to filter the data before sending it to the response.

## Defining Disabled Keys

Now let's update our base resource class and add a new static method `disable` this method receives multiple keys that are going to be used to filter the data before sending it to the response.

```ts
// src/core/resources/resource.ts
// ...
export default class Resource {
  // ...
  /**
   * Disabled keys from being returned in the final output
   */
  protected static disabledKeys: string[] = [];

  /**
   * Disable the given keys
   */
  public static disable(...keys: string[]) {
    this.disabledKeys.push(...keys);

    return this;
  }
  // ...
}
```

We defined here out `disable` method that allows us to add multiple keys to the `disabledKeys` array.

## Defining Allowed Keys

Now let's do the same with the other case, we'll define a new static method `allow` this method receives multiple keys that are going to be used to filter the data before sending it to the response.

```ts
// src/core/resources/resource.ts
// ...

export default class Resource {
  // ...
  /**
   * Allowed keys to be returned in the final output
   */
  protected static allowedKeys: string[] = [];

  /**
   * Allow the given keys
   */
  public static allow(...keys: string[]) {
    this.allowedKeys.push(...keys);

    return this;
  }
  // ...
}
```

Of course as usual, these methods have no effect until we use them in our `toJSON` method, so let's update it.

## Updating toJSON

To do so, we need to define also two internal methods one to check for the given key that will be in the output object if it is disabled, if so then skip the transformation step and go to the next key.

And also we need to check if the given key is not in `the allowed list`, if so then skip the transformation step and go to the next key.

But note that the allowed list must have at least one key, otherwise, it will be ignored and all keys will be allowed.

```ts
// src/core/resources/resource.ts
// ...
export default class Resource {
  // ...
  
  /**
   * Check if the given key is disabled
   */
  protected isDisabledKey(key: string) {
    return (this.constructor as typeof Resource).disabledKeys.includes(key);
  }

  /**
   * Check if the given key is allowed
   */
  protected isAllowedKey(key: string) {
    const allowedKeys = (this.constructor as typeof Resource).allowedKeys;
    return allowedKeys.length === 0 || allowedKeys.includes(key);
  }

  // ...
}
```

You may get confused with the syntax `this.constructor`, why? because we are trying to access a static member from non static member, and also we need to access it from the child resource class not the base class, otherwise we could just used `Resource.disabledKeys` and `Resource.allowedKeys`.

In the first method `isDisabledKey` we check if the given key is in the `disabledKeys` array, if so then we return `true` otherwise `false`.

In the second method `isAllowedKey` we check if the `allowedKeys` array is empty, if so then we return `true` otherwise we check if the given key is in the `allowedKeys` array, if so then we return `true` otherwise `false`.

Now let's use these methods in our `toJSON` method.

```ts
// src/core/resources/resource.ts
// ...

export default class Resource {
  // ...
  
  /**
   * Final data output
   */
  protected data: Record<string, any> = {};

  /**
   * Transform resource to object, that's going to be used as the final output
   */
  public toJSON() {
    for (const key in this.output) {
      // first check if key is disabled
      if (this.isDisabledKey(key)) continue;

      if (!this.isAllowedKey(key)) continue;

      // get value type
      const valueType = this.output[key];

      // now get the value from the given resource data
      const value = get(
        this.resource,
        key,
        get(this.defaults, key, missingKey),
      );

      if (value === missingKey) {
        continue;
      }

      if (Is.empty(value)) continue;

      if (Array.isArray(value)) {
        this.data[key] = value.map(item =>
          this.transformValue(item, valueType),
        );
      } else {
        this.data[key] = this.transformValue(value, valueType);
      }
    }

    return this.data;
  }
  // ...
}
```

We made two checks here before even getting the value type, the first one is to check if the given key is disabled, if so then we skip the transformation step and go to the next key.

The second one is to check if the given key is allowed, if so then we skip the transformation step and go to the next key.

> Please note that i added a new property called `data`, this is going to be used later to add more features like customizing the final output and adding more complex outputs.

## Using Disabled And Allowed Keys

Now let's open our `users-list.ts` file and we can add the following code

```ts
// src/app/users/controllers/users-list.ts

import User from "../models/user";
import UserResource from "../resources/user-resource";

export default async function usersList() {
  const users = await User.list();

  UserResource.disable("isPhoneVerified", "isActive");

  return {
    users: UserResource.collect(users),
  };
}
```

This will disable the `isPhoneVerified` and `isActive` keys from being returned in the final output.

## 🎨 Conclusion

In this article, we learned how to disable and allow keys from being returned in the final output.

## ☕♨️ 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)