class-1: NODE
-
CommonJS and Modules && Paint with colors the terminal without dependencies
- How to import and export commonjs files and modules
- How to paint with color, background color, and text changes on terminal
-
OS info
- OS Info from
node:os
- It can be access to: platform, release, architecture, cpu, free memory, total memory and more
- OS Info from
-
FS stat: isFile, isDirectory, isSize
- Can now if a something is a file, is directory, the size with
node:fs
- Can now if a something is a file, is directory, the size with
-
Read a file: sync, callback, promisify
- Can read a file sync, with callbacks and using promisify
- Caveat 🟨: only tested with
.txt
files
-
Read a file: IIFE, promises-then, async await (sequential), async await (parallel)
- Can read a file sync, with IIFE, promises-then, async await (sequential), async await (parallel)
- Caveat 🟨: only tested with
.txt
files
-
Path, with
node:path
is possible to:- Know the path separator for your actual OS
- Get the absolute ir relative path
- Know if a route is relative or absolute
- Know the file name from a given route
- Know the file extention from a file
- Know the file plus extension from a given route
-
LS: promises, promises-then
- This is a app that list the files from this folder in a promisify way and in a Sync way
-
Process: how to take arguments by terminal
- The
process.argv
give you access to argumentos of entry: with this you can configure things in the command line, if you made an API and you want put configurations there passing arguments to it. This is an array - With
process.on("exit", callback)
can do things when the process end, of the process, specific errors, and so son - The
process.cwd()
is the Current work directory (cwd): says where which folder we are running the process, not where is the file but from which folder the command was executed to run the file - The problem with
node
is it can access to.env
variables leading acccess to too many power like deleting files, for example
- The
-
LS advance: thenable, async await, arguments, prompt
- More advance
ls
with a thenable, async await, arguments and prompts on terminal
- More advance
-
Http server
- Creation of a http server only with
node
- Creation of a http server only with
-
Free port method
- Method to get a free port if the desired is used
class-2: HTTP && Express
-
HTTP Server
- HTTP is one of many protocols that are useful to transfer some type of data. In this case HTTP means HyperText Transfer Protocol (HTTP). This is the most used on internet to transfer data, specially web pages. Examples:
- A user have some device (a phone) and wants to reach some content. In order to reach it the user should make a request. The request have a:
- url (where are you making the request)
- headers (aditional information about the request like tokens, type of data we are especting to receive, we can send the cookies). Those are optional
- the method (the type fo request: GET —to request— or POST —to send— or others)
- and sometimes we send a body (data we want to send)
- The request reach a Server. The server will process it the request with everything sent from the user (it will go to a database, treath the data). That process will take some time (unknow time) and when this finish it will send a response to the user.
- The request and the response have different data and this is critical to understand how all of this work. Every part have to send different data
- The data that the response have is:
- statusCode (200, 404, 500, etc)
- body of the response: this are actually the data that you asked
- headers
- After receiving the data, the conextion should be closed unleass some header will say that it should keep open
- A user have some device (a phone) and wants to reach some content. In order to reach it the user should make a request. The request have a:
- Caveats 🟨:
- With the statusCode: in reality this is in the header but is important this to be alone because when the headers is writen first the statusCode is writen and after that the headers
- The HTTP protocol historically had so many security problems and therefore exist the HTTPS protocol. This can be used on localhost but is too complicated and it require a certification. Right now we are going to focus on the HTTP and the API. Another problem is having a service on HTTP on localhost that works correctly but when you deploy it you wrapp that in a service that use HTTPS, therefore interanally is HTTP but is wrapped in HTTPS so everything is encrypted and it doesn't have any problems
-
Status code:
- From 100 to 199: Informational
- From 200 to 299: Success
- From 300 to 399: Redirection
- From 400 to 499: Client error. The client tried: enter to a page that doesn't exist; send data in a wrong format; it doesn't have permission to access to something
- From 500 to 599: Server error
- Recommended source: https://developer.mozilla.org/en-US/docs/Web/HTTP/Status
-
Typical statusCode:
- 200: OK. This is the default, it can be omitted if everything goes okay
- 301: Moved permanently. The resource of this direction was moved to
- 400: Bad request
- 404: Not found
- 500: Internal server error. This is a tricky one because you will not know exactly what happened
-
Buffer data on the file
class-2/1.http.js
:- The "data" second argument here is a Buffer. A Buffer is a global class in nodejs that is useful to work with binary data: a when a .txt file or an image is received by nodejs is readed they binary data and is stored, temporary, in some place of the physical memory to work with them.
-
Before the read of the data nodejs doesn't know what it is: an image, a text or other, is just a binary data. The nodejs know that is an image when reach the "else" where the header is set to "Content-Type: image/
extension
". Here the codification magic happen: the browser know is an image because the Content-Type setted. - The buffers are useful to work with files, images, criptography and anything that is not plain text or jsons. Those are critical when you want to work with data transmision because how to file are readed or to received through the network
- HTTP is one of many protocols that are useful to transfer some type of data. In this case HTTP means HyperText Transfer Protocol (HTTP). This is the most used on internet to transfer data, specially web pages. Examples:
-
Routing
- In commonJS you can import json data directly and use it
- Methods of routing:
- GET: To get data
- HEAD: Is exactly the same as get but without the responding of the body. Is usually used to know if the user have permission to access to some content
- POST: To create data
- PUT: To update data, this replace the content
- PATCH: To modifiy partially some data
- DELETE: To delete data
- OPTIONS: This is used to know which communication are available for the target resource. This is usually the problem we have on CORS on browser. The browser make a request to a server and this server send a response with the type of comunication allowed. The OPTION return the headers CORS
- Caveats 🟨:
- There's some discusión about the use of POST versus PATCH. Search it
- In this class the file api.http was used
-
Express
- When you use express it add some header call X-Powered-By with the value of "Express". This could lead to security problems because everyone can know te technology you are using and try to exploit vulnerabilities there. is recommended to disable this with «app.disable("x-powered-by")»
- One of the magic thing of express is the use of middleware. This can be used to extract cookies, validate if the user is logged, extract the data from json or any type of logic. Is something previous to to do before it arraive to the request. When it's done it call the «next()» method to continue. The middleware is executed between the request and the response
-
Middleware:
- You can decide to which request the middleware will affect. For example:
- app.use("/pokemon/*", fn) → All the requests that start with "/pokemon/*" will be affected
- app.use("/", fn) → Only the request on home will be affected
- app.use(fn) → All the routes will be affected. This is the usual behavior
- The middleware can be used also for specific methods: only for GET, only for POST
- Caveats 🟨:
- You shouldn't forget the final «next()» method because if you forget it will wait infinitely for the next request
- A middleware can be used at first, in between or at last. The concept of this is "be in the middle" but technically the «app.use()» can be used as a middleware anywhere. Is like a proxy, intercep the request to respond it later. A proxy and a middleware intercep a request but the final goal is different: the Proxy will have the responsibility of orchestration but the Middleware will do that and apply some logic or task into it. A Middleware could reject a request
- You can decide to which request the middleware will affect. For example:
- On Express the method
app.use(express.json())
ccan be used to make something a json. See the fileclass-2/3.express.js
on line33
to learn it - Express allow you to use the route first and the callback after
- In the post, everything is the same as nodejs
- The calls of
app.*
is dependendat on the order - The API
app.liste
is the same as nodejs
class-3: CORS + API Rest with Express
-
API REST
- REST mean: Representational State Transfer an Software Architecture (not a framework, not a library, not an idea, not a pattern)
- Was created to transfer data specially on web
- Was created on the 2000 year by Roy Fielding
-
Principals features on REST:
- Scalability
- Simplicity
- Visibility
- Portability
- Realiability
- Easy to modify
- All Software Architecture should achieve a goal with some principals that can sustain over time the best possible way and simplify the creation of that piece of software. This is the goal of every Software Architecture
-
Fundamentals on REST:
- Resources: everything here is a resource (a user, book, some publication, an image or a collection of this resources, a list of users, books, and so on). Every resource will be identified with an URL
- Methods: what kind of action you want to do with the resource. This could be GET, POST, PUT, PATCH, DELETE, HEAD, CONNECT and TRACE. The most common actions made here are the "CRUD" → Create (POST), Read (GET), Update (PUT or PATCH), Delete (DELETE)
- Representation: This is how the resource is represented: the most common representation is JSON but is not mandatory, this could be also XML, HTML, CSV, etc. The client decide which representation be the resource, having none restriction on the format. One client can ask for a JSON while other client can ask for a XML representation
- Stateless: every request to the server should contain all the neccesary data to understand that request. This mean the server should not be able to remember anything about the request. For example it cannot save how many calls have been made to the server, it have to make pagination or not, that data should be always on the URL of the request. Sometimes some data can be save to help the client but in that case the REST architecture will be break. Another case is when we have some database on the backend.
- Unified interfaz: this is difficul to break it but it means that the interfaz between client and server should be consistent for every interaction. The URLs should always do the same, should always be called the same
- Separation of concepts: components of client and server should be separated. This allow the server and the client evolve independently
- Caveat 🟨:
- Sometimes you can make some API that is not REST, another architecture exist (like SOAP or GraphQL). Some people think that an API that return a JSON is immediately a REST API but it is not always the case
- Resources: sometimes you can decide to identify the resources with a path on the URL or with some queries. It will depend on the specific use case you want to achieve
-
Express use path-to-regex
- Is possible to put regex in the URL but express use this library: path-to-regex, like this
app.get("/movies/:id", fn)
- Is possible to use
/movies/:id/:couldBeMore/*:andAsMuchAsYouWant
where the:id
,:couldBeMore
,:andAsMuchAsYouWant
and*
are part of the URL separated by an slash. Is your decition using it this way or making them query params - Everytime you can, use path-to-regex because make the regex by you can lead into problems
- To know more check the github repository of pillarjs or the express explanation in their documentationr>
- Is possible to put regex in the URL but express use this library: path-to-regex, like this
-
POST, PATCH, PUT and Schema (Zod)
- To Understand the POST: You have to work all the time in the same route, is not like you can put here `app.post("/create-movies", fn)`, this is because the Resource is defined by the URL and is the verb which decide what's going to be done there: GET, POST, other
- ID on Post:
crypto.randomUUID()
- With Zod: You can validate the data with the method "parse" or you can use "safeParse". With "safeParse" you will have a object result with data or errors. You can even use the safeParseAsync to avoid blocking the request return movieSchema.parse(objectToValidate)
- On the error of the validation of schema (Zod):
- You can pass here a 422 instead a 400:
- The 400 status code is because the client did something to lead on this error: sintaxis error, the data sent was not correct. The important thing here is: the client cannot do a new request without modifications
- Other approach is 422: the server understood the request, type of content but the sintaxis of the resource was not possible to created because some validation or instruction was not correct. The same as the previous: client will not be able to make another request is it not change something
- Final though, use anything you want
- Remember, a REST API don't save data by their own. For that, use a database
- Idempotence and differences between POST, PUT and PATCH:
- Idempotence: is the property of realize an action several times and even though achieve the same result as you would get with the first try. Pure functions are idempotent. This property talk about the inner state of something. Now the methods
- Purpose of POST: create a new element/resource on server
- On URL: `/movies`
- Idempotence: this is not idempotente because every time you call this method a new resource is created
- Purpose of PUT: update an existing element/resource on server o create it if it doesn't exist
- On URL: `/movies/:id` → `/movies/123-456-789`
- Idempotence: this is idempotente the bast majority of the time, but it could not be sometimes
- Purpose of PATCH: update partially an existing element/resource on server
- On URL: `/movies/:id` → `/movies/123-456-789`
- Idempotence: this is not idempotente ithe bast majority of the time, but it could be sometimes
- One question, is it danger to create the ID from outside? The answer: it could be but this will depend of the context of the application. For example, sometimes this ID can come from outside: the email of an user for example or other thing that will identify that person as unique in the analog world
-
CORS: Cross Origin Resource Sharing
- This only works on browsers not in servers. The CORS is a mechanism that restrict if a resource can be used on some origin. The browsers make the request to this resource. Here the browser on origin
http://localhost:8080/
akamywebsite.com
ask tohttp://localhost:3000
akaAPI.com
Is true that mywebsite.com who is not you (of course the browser ask in this situation, if would not, it would not ask) is able to get resources from API.com? - When this is not possible the way from the API to say no is with the lack of headers
- This problem can only be solved in the backend: on the API, on proxy, in the router or on anything that can add the required header. Who should add that header? For now that's not important
- The way to to solve this in express is adding this to the routes you want to enable
res.header("Access-Control-Allow-Origin", "http://localhost:8080")
. In this casehttp://localhost:8080
would be mywebsite.com - You can also replace the specific
http
site for this*
, to enable all the request for anyone - Here is very possible that you don't know would be the origin, it would be
3000
,8080
,4500
,1234
? So, the solution for this could be:- Detect the origin and decide what to do. For example, you can have a list of
ACCEPTED_ORIGINS
- Detect the origin and decide what to do. For example, you can have a list of
-
A caveat here 🟨: the
origin
header is not always sent by the browser. This is not send by the browser when the request is from the same origin. This mean, if I'm in thehttp:localhost:3000
and I make a request tohttp:localhost:3000
noorigin
header will sent - Exist simples and complex methods with CORS:
- Simples:
GET
,HEAD
andPOST
- Complex:
PUT
,PATCH
andDELETE
- This methods have something call
Preflight
, this mean that you need to add a call with the methodOPTIONS
in order to make them acceptable
- This methods have something call
- Simples:
-
At the end the problem with
CORS
is a problem of headers. You should be able to useres.header("Access-Control-Allow-Origin", origin)
andres.header("Access-Control-Allow-Methods", "GET, POST, PUT, PATCH, DELETE")
to solve it in the correct place: in the middleware and/or where the request is made - Is it possible to solve this using express or you can use a third party library call
cors
. Check theapp.js
file to check how to use it. One caveat 🟨 with that solution: it will solve adding an*
to everything. In order to make that library behave as the native approach you have to pass it some options
- This only works on browsers not in servers. The CORS is a mechanism that restrict if a resource can be used on some origin. The browsers make the request to this resource. Here the browser on origin
class-4: MVC and Deploying of API
-
Environmental variables
- This should be always on
UPPERCASE
- On express it can be used like this to deploy it on some service:
const PORT = process.env.PORT ?? 3000
app.listen(PORT, () => { console.log(`Server listening on port http://localhost:${PORT}`)})
- This should be always on
-
Configuration on hosting
- Normally the host ask you for a
start
script on thepackage.json
to run the file or maybe it will ask on the configuration
- Normally the host ask you for a
-
ESModules
- In order to use the ESModules instead the commonJS approach, you can go into your package.json and add this
"type": "module"
. With that you will be able to use the ESModules without change the extension of the files. But at the same time, you will not be able to use the commonJS approach without change the extension of the file - When you import some module is a good practice put the extention, like this
import { QUERY_KEYS, moviesQueryParams } from "./utils/moviesQueryParams.js"
. As developer we are bas used to not put the extension at the end, because we are lazy, because TypeScript, because builders - On ESModules import json is not allow directly
import allMoviesJSON from "./data/movies.json"
you can do it with different approaches:import allMoviesJSON from "./data/movies.json" assert { type: "json" }
→ This is not recommended because theassert
will stop work at some pointimport allMoviesJSON from "./data/movies.json" with { type: "json" }
→ Change theassert
forwith
-
import fs from "node:fs"
const allMoviesJSON = JSON.parse(fs.readFileSync("./data/movies.json", "utf-8"))
-
Recommended (until the import of JSON will be native on ESModules): create a require (this is more performante)
import { createRequire } from "node:module"
const require = createRequire(import.meta.url)
const allMoviesJSON = require("./data/movies.json")
- In order to use the ESModules instead the commonJS approach, you can go into your package.json and add this
-
MVC: Model, View, Controller
- Exist some debate if the MVC is a
Design Pattern
or aArchitecture Patterns
. It seems more like an architecture. Nonetheless, it doesn't explain everything because it doesn't tell you how to implement theView
- This is highly used on web and mobile applications but other frameworks also work like this, like
ruby on rails
,Django
,ASP.net
and others - This architecture forces you to separate the application in three main component that work togheter, the Mode, the View and the Controller
- Exist several iteration of this architecture. But the one we going to see here is the most classic one
Model:
- This is the logic of the business, the data structure, inner rules of the business
- This is in charge of access the database, update the data, check if the integrity of the data are correct (for example, if you try to create and ID, that ID shouldn't exist)
View:
- This is the most important part for the user: with this the user will interact because the user cannot interact with the Model neither the Controller
Controller:
- This is an intermediary between the Model and the View, this respond to the entries of the user every time they make on. This part of the application is responsable for know what to do with the model. Is like an Orchestrator
-
This three parts should work togheter. First the controller will ask for data to the
Model
, the model will return the data to theController
and after that it will init theView
. After that the user throught theView
will interact wanting something happen. With that interact of the user theController
will act asking for the correct data to theModel
, generally speaking having theCRUD
approach here with them -
Remember here, from the
View
is not possible to interact directly with theModel
. But is possible indirectly because the user, at the end, make some request to theModel
through theController
-
The advantage of this is the separation of the responsabilities on the application, specially the Logic of the Business (
Model
), because this is the most important thing on the application when it have to connect to a database. This will help to scalability and test, to name some - Examples:
View
:React
Vue
Controller
:Express
DJango
Model
:mySQL
mongoDB
- Local
- The goal is have black boxes that interact with each other. Each one should know how to interact with the other but it doesn't whould know how them interanally make their things. This is the key of architecture and clean code: separation of by layers, separation of concepts
-
In the code is not neccesary that the
Model
and theControll
share the same names for the methods. Even sometimes you will need to call more than oneModel
from theController
- Validations:
- This happend along all the aplication:
Model
,View
,Controller
but is made in different ways depending on the category Controller
: usually here the validation is of format and coherence of the data received, to be possible to be procesed before send it to theModel
. When it comes from the input from the user, is a good thing to validate the data before to send it to theModel
. With this validation you allow the data is correct to be used or to avoid attacksModel
: usually the validation here are for the business rules, data coherence, data persistant in the database and others like check the ID- The
View
is the most useless for the business logic but is the most important in terms of user experience - Is debatable if the
Model
can have some method that say which field allow and with wich type, like a integer, a string and so son. That method can be exported into theController
to make the validation there. Here the validation will stay apply in theModel
but it will be used, also, by theController
- With this said: validation on
Model
andController
are mandatory, validations onView
are optional (very interesting)
- This happend along all the aplication:
- Exist some debate if the MVC is a
-
Difference between
Design Pattern
andArchitecture Pattern
- The
Design Pattern
: is an easy, repeteable, to solve something specific in a part of the code. For example:- Pattern Observer
- Pattern Factory
- Pattern Modules
- The
Architecture Pattern
has to do with all your application: how to implement everything - The architecture on software development make sense when you work on business with products or services. In order to be a Software Engineering, you need to create products that scale, be maintainable and work
- The
class-5: Creation of a database with mySQL and evoiding hackers (good practices)
- A database is a collection of data interrelated and saved without unnecessary redundancy
- All database should allow insertion, modification and delete of data
- There's two type fo data in a database:
- Date from users: created by the user
- Data of the system: data that the database use for their management. For example: which user have access to the database
-
The characteristics of a database:
- Versatile: depending of the user and application, it should behave acordly
- Performance: should have the enough speed for every client that make request to the database
- Low redundancy: should be the lowest possible
- High access capacity to gain the most possible time on requests
- High index of integrity: if any amount of user try to use the database, this should not fail for create new data, have redundancy or for slow updating
- Very high security and privacy. This taking in mind not only the software but also the hardware: fire, stealing, and so on
- Should receive periodic updates to avoid obsolescence
-
User should not know how the data is organized and saved. Becuase of this the data should be presented to the user in a easy way to be interpreted y modified. With this: exist three principals levels on for the user interact with the database:
- Intern level: closest level for the physical storage. It allow to write like is in the computer. Here you have the configuration files: files that have the data, direction of the files and organization
- Conceptual level: The data that will be used is presented without having in mind the Intern Level.
- Extern level: the closest to the user. Here the data that the user want is writen (totally or partially)
- The data within a database are naturally related, for example: a product belong a category and is associated with multiple tags. The term for this is
Relational Database
- A
Relational Database
is like a spreadsheet: atable
is a page, that containcolumns
androws
. Atable
can relate to anothertable
using various type of relationships likeone-to-one
andone-to-many
- What is
SQL
- The acronmyn
SQL
stands for Structured Query Language. This is the standarized language to access the database SQL
is composed of three parts:- Data Definition Language (
DDL
): includes statements for defining the database and its objects such as tables, views, triggers, stored procedures, etc - Data Manipulation Language (
DML
): contains statements for updating and querying data - Data Control Language (
DCL
): allows you to grant permissions to users to access specific data in the database
- Data Definition Language (
- The acronmyn
- Important
SQL
commands:start transaction;
: this is for make changes without commit it. With this you can make changes safely without worring to mess it up. In this state you can use therollback
to revert the changes. And when you be happy with your changes, you can use thecommit;
in order to apply all the changes
- What is
MySQL
- Is a robust database management system designed for managing relational databases. It is open-source software supported by
Oracle
, meaning that you can useMySQL
without any cost. Additionally, you will have the flexibility to modify its source code to tailor it to your specific requirements - When compared to other database software like
Oracle Database
orMicrosoft SQL Server
,MySQL
is relatively easy to master MySQL
is versatile and can run on various platforms, includingUNIX
,Linux
, andWindows
MySQL
is renowned for its reliability, scalability, and speed
- Is a robust database management system designed for managing relational databases. It is open-source software supported by
- In order to run some
sql
scripts you can:- Run a pluggin on vscode: MySQL by Weijan Chen, and this is the website database-client.com
- Or you can run by the
mySQL shell
following the nex steps:- Reach with the terminal the desired path or know the path of your file
-
Once you get the path run this on the terminal to open the
mySQL Command Line Client
:mysqlsh
-
You should explicty change use the
sql
shell with\sql
-
Now be sure that you are connected to the actual server running
\c [user]@[host_name]
: example\c root@localhost
. Maybe the terminal will ask you for a password -
Run the command
\. [name_of_script].sql
and done -
IMPORTANT: ⚡ Running the
sql
scripts this way will allow you to use theSOURCE
command, that comes from themySQL Command Line Client
which will help you to upload and run other scripts files in a more efficient way
- Dependency Inyection
- This is a
Design Pattern
to improve code efficiency eficciency, modularity, control, reusability and make the code testable. Also, the code is uncouple by design - The basic idea is: a
object
,class
orfunction
can receive their dependencies from outisde and the inner behavior change depending on how this information is provided
- This is a
- Creation of a database with mySQL and avoiding hackers (good practices)
- Connect mongoDB with express
- Perform a
CRUD
with the database using mongoDB - Special enphasis on
GET
with the query
- Learn how to use mongoose with express
- Perform a
CRUD
with the database using mongoose - Special enphasis on
GET
with the query
- Perform a
- Know how to make an dependency injection