typeOrm
Typescript
Node
postgres
Express
🍬 Technologies: TypeORM, TypeScript, Node.js, Express.js, Postgres
Crear una API es básicamente crear una lista de endpoints que quieres que otros desarrolladores soliciten cada vez que necesiten interactuar con tu base de datos para Crear, Actualizar, Borrar o Leer información. Cuando usas Express.js esos endpoints tienen que ser añadidos a tu API usando la función router.get (o post, put o delete). Por ejemplo:
1router.get("/users", getUser)
La línea anterior, especifica un nuevo endpoint que otros desarrolladores podrán llamar solicitando GET /users
.
Después de declarar tu ruta, también tienes que declarar tu función que manejará esa petición (en este caso getUser
)
Los dos ficheros principales que te interesan son ./src/<private|public>_routes.ts
y ./src/actions.ts
y tendrás que modificar ambos cada vez que crees un nuevo endpoint.
En primer lugar, debe pensar en la seguridad de su ruta: ¿quién utilizará esta ruta? ¿Cualquier usuario público o sólo los usuarios registrados?
Hay dos archivos y debes actualizar uno u otro para cada endpoint que crees:
public_routes.ts
es para URLs API que van a ser utilizadas por cualquiera, sin ningún tipo de seguridad, por ejemplo: Todo el mundo puede registrarse, todo el mundo puede intentar iniciar sesión, etc. - private_routes.ts
estas URLs serán sólo para usuarios registrados, por ejemplo: Obtener mi lista de favoritos, u obtener mi información, etc.Abre el archivo ./src/<private|public>_routes.ts
que hayas elegido y añade una nueva ruta a la lista de endpoints, por ejemplo, si queremos construir un endpoint para recuperar la información de un único usuario por un ID dado, por ejemplo: GET /user/2
.
1import { Router } from 'express'; 2import { safe } from './utils'; 3import { getUser } from './actions'; 4const router = Router(); 5 6 7router.get('/user/:id', safe(getUser));
👉 Nota: tenga en cuenta que la función
safe
debe llamarse siempre antes de su acción o los errores de la API serán silenciosos.
Abre el archivo ./src/actions.ts
y añade o reutiliza una de las funciones de acción, por ejemplo:
1export const getUser = async (req: Request, res: Response): Promise<Response> =>{ 2 3 const users = await getRepository(Users).findOne(req.params.id); 4 return res.json(users); 5}
Los desarrolladores junior siempre asumen que todo va a ir bien, mientras que los senior están preparados para los peores escenarios posibles.
Por ejemplo, hay que asumir que la información llega en un formato incorrecto: Los correos electrónicos no tienen el nombre de dominio dentro, los números de teléfono tienen letras, etc.
Hay tres posibles tipos de validaciones que recomendamos hacer:
El payload de la petición puede ser recuperado haciendo req.body
, este es un ejemplo de cómo validar si el cuerpo de la petición contiene la propiedad first_name
:
1export const getUser = async (req: Request, res:Response): Promise<Response> =>{ 2 3 // validate that first_name exists or throw a new exception if not. 4 if(!req.body.first_name) throw new Exception("Please provide a first_name") 5 6 // the rest of your function code goes here 7 8})
Si la URL de tu endpoint espera un parámetro puedes acceder a él escribiendo req.params
, por ejemplo, si el endpoint GET /user/:id
es llamado con GET /user/23
, podemos recuperar el valor así:
1 const user = await getRepository(Users).findOne(req.params.id); 2 if(!user) throw new Exception("User not found", 404)
Básicamente estamos consultando la base de datos para obtener el usuario con ese ID dado y asegurarnos de que existe.
En el siguiente archivo 🔥🔥🔥 puedes encontrar más ejemplos de validación.
TypeORM tiene un montón de maneras de recuperar información de la base de datos, vamos a mostrar los ejemplos más utilizados aquí, y puede consultar este documento para formas más avanzadas de consultar información.
⚠️ Importante: Siempre debe comenzar declarando un nuevo
repositorio
para esa entidad.
1const user = repository.create({ 2 id: 1, 3 firstName: "Timber", 4 lastName: "Saw", 5}) // lo mismo que const user = new User(); user.firstName = "Timber"; user.lastName = "Saw";
Después de tener el objeto repositorio puede iniciar su consulta, por ejemplo:
Buscar el usuario con el nombre "Bob".
1userRepository.find({ where: { firstName: "Bob", lastName: "Saw" } });
Find the user with the first name "Bob"
1userRepository.find({ where: { firstName: "Bob", lastName: "Saw" } });
Encontrar el usuario con el nombre "Bob"
1userRepository.findOne(1, { 2 where: { firstName: "Bob" } 3})
🔥🔥🔥 Haga clic aquí para ver más ejemplos de consultas avanzadas
TypeORM es una de las librerías ORM más sencillas de usar.
He aquí un ejemplo muy sencillo de cómo crear un nuevo usuario:
1const user = repository.create({ 2 id: 1, 3 firstName: "Timber", 4 lastName: "Saw" 5}); // mismo que const user = new User(); user.firstName = "Timber"; user.lastName = "Saw";
Suponiendo que desea eliminar el usuario con ID=1
1await repository.delete(1);
Suponiendo que desea actualizar el usuario con el ID=1 y establecer su nombre a Rizzrak:
1await repository.update(1, { firstName: "Rizzrak" });
🔥🔥🔥 Aquí puede encontrar otros ejemplos de operaciones CRUD más complejas.
Usted no tiene que utilizar las migraciones en el modo de desarrollo porque TypeORM ya lo hace por usted, pero antes de pasar a la producción tiene que ejecutar el siguiente comando para crear sus migraciones:
1npm run makemigrations
1npm run migrate
Esto te proporcionará un servidor PostgreSQL de auto-inicio (debería auto-iniciarse cada vez que abras un nuevo Terminal), además de unos cuantos scripts de utilidades que puedes ejecutar en un Terminal o en un comando .gitpod.yml:
pg_start: inicia el servicio PostgreSQL
pg_stop: detiene el servicio PostgreSQL
pg_ctl status: comprueba si el servicio PostgreSQL se está ejecutando
Una vez que el servidor PostgreSQL se está ejecutando, puede utilizar la CLI psql como de costumbre:
$ psql -h localhost -d postgres
psql (10.8 (Ubuntu 10.8-0ubuntu0.18.10.1))
Type "help" for help.
postgres=#
En éste artículo encontrarás todos los detalles de cómo implementar este esquema en tu API Flask