Introduction
Let's start a new chapter, the resources
chapter, in this chapter we will learn how to create a resource
file that will be used to return the response to the client, and we will learn how to use it in our project.
What is a resource
A resource is meant to be used to fulfil a response shape based on the given let's say a model and return a specific response shape.
What does this mean?
Let's take an example to make everything clear, let's say we have a user
model that has the following data:
const userData = {
id: 1,
_id: ObjectId("60f6b9b9b9b9b9b9b9b9b9b9"),
name: "Hasan",
email: 'hassanzohdy@gmail.com',
password: '$2sd#$qwdfer2wqesder2wqsdewqesdfegrhty6t54re',
createdAt: Date("2021-07-18T12:00:00.000Z"),
updatedAt: Date("2022-12-02T12:00:00.000Z"),
image: 'images/users/sadfe2e3wdsfweq/logo.png',
published: true,
}
That's what our model includes, now let's say we want to return the user's response like this:
{
"user": {
"id": 1,
"name": "Hasan",
"email": "hassanzohdy@gmail.com",
"published": true,
"image": "https://example.com/uploads/images/users/sadfe2e3wdsfweq/logo.png",
"createdAt": {
"format": "2021-07-18T12:00:00.000Z",
"timestamp": 1626585600,
"humanTime": "2 months ago"
},
"updatedAt": {
"format": "2022-12-02T12:00:00.000Z",
"timestamp": 1638438400,
"humanTime": "2 months ago"
}
}
}
You will see a difference here between our data model and our desired response, for example we store the image's path relatively to the uploads directory, but we need to return it to the client as an absolute url, also the createdAt
and updatedAt
fields are Date
objects, but we need to return them as an object that contains the format
, timestamp
and humanTime
fields, this will help the clients' developer to easily use these data.
Also we hid some data from the client, for example the password
field, we don't want to return it to the client, so we need to hide it.
And we didn't return _id
field as well as we don't really need it now.
This will be managed with what we can call a Resource
, so basically a Resource
is a file that will be used to return a specific response shape based on the given model.
Resource workflow
Now let's see, what are we going to do with these resources?
Firstly let's establish an essential thing here, resources are supposed to receive two types of data, a Model
object or a plain
object.
Now a resource class will receive its own data resource in the constructor.
Then we want to shape our output based on the resource output standard definitions.
Finally, we'll create a method to convert the resource to a plain object using the toJSON
method.
Resource standard definitions
We already defined tha the resource class will receive its resource data in the constructor, it can be either a Model or a plain object.
Now the resource has to define the response output
shape, thus we need to have an output
property in our resource class, this property will be an object that contains the response shape.
That output object will have multiple shapes, but let's start with a basic one
key: type
where the key
is the name of the output and also the key that will be used to get the value from the given resource and the type
will define what is going to return for this key.
Output types: A Model cast like
Remember the casts
property in our model? it will be pretty much the same in concept but different in implementation.
We'll have a builtin types, like string
number
boolean
date
and so on, and also we set a function that will receive the value and return the final output for that key, we're going to see that right now.
Implementing the resource
Enough talking, let's start implementing the resource.
Go to our beloved core
directory and create resources
directory, then create Resource.ts
file.
// src/core/resources/Resource.ts
export default class Resource {
/**
* Constructor
*/
public constructor(protected resource: any = {}) {
//
}
}
Simple class, nothing fancy here just a constructor that will receive the resource data and store it in a protected property.
// src/core/resources/Resource.ts
export default class Resource {
/**
* Constructor
*/
public constructor(protected resource: any = {}) {
//
}
/**
* Convert the class object to a plain object, this is needed when returning the resource class in response
*/
public toJSON() {
return this.resource;
}
}
Now let's try this, open get-user
controller, and let's try it.
// src/app/users/controllers/get-user.ts
import Resource from "core/resources/resource";
export default function getUser() {
return {
user: new Resource({
name: "Hasan",
email: "hassanzohdy@gmail.com",
}),
};
}
Now run the code on postman or in the browser in http://localhost:3000/users/1
and you'll see the following response:
{
"user": {
"name": "Hasan",
"email": "hassanzohdy@gmail.com"
}
}
This is done just by passing our object as a resource data then we implemented toJSON
which is used to stringify the class object, so we can return it in the response.
🎨 Conclusion
In this article, we learned how to create a resource class that will be used to return a specific response shape based on the given model/data.
In our next article, we're going to create our output
property and start implementing our builtin types and also how to use custom functions.
☕♨️ Buy me a Coffee ♨️☕
If you enjoy my articles and see it useful to you, you may buy me a coffee, 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
😍 Join our community
Join our community on Discord 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, 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
- Best Practices For Case Styles: Camel, Pascal, Snake, and Kebab Case In Node And Javascript
- After 6 years of practicing MongoDB, Here are my thoughts on MongoDB vs MySQL
Packages & Libraries
- Collections: Your ultimate Javascript Arrays Manager
- Supportive Is: an elegant utility to check types of values in JavaScript
- Localization: An agnostic i18n package to manage localization in your project
React Js Packages
Courses (Articles)
Top comments (0)