En la publicación anterior de esta serie se ha visto una propuesta para organizar el código del proyecto. Una vez organizado el código es el momento de configurar una base de datos para persistir los datos. Para lo que se usará TypeORM. Un ORM (Object-relational mapping) para TypeScript mediante el cual se puede emplear una gran cantidad de motores de base de datos relacionales como MySQL, SQLite, PostgreSQL, Microsoft SQL Server u Oracle. Veamos cómo se puede configurar TypeORM en el proyecto.
¿Por qué usar un ORM?
Aunque en Node se puede acceder a la mayoría de las bases de datos sin la necesidad de un ORM. El uso de estas herramientas puede simplificar considerablemente el desarrollo de las aplicaciones. Especialmente si la base de datos puede cambiar durante el desarrollo del proyecto.
Un ORM no es más que una librería con la que se pueden mapear las estructuras de las bases de datos sobre estructuras lógicas de entidades, gracias a las cuales se puede simplificar el desarrollo de las aplicaciones. Así ya no sea necesario pensar en términos de tablas y sus relaciones, sino que en términos de objetos.
Instalación de TypeORM
La instalación de TypeORM se realiza como cualquier otro paquete de Node mediante el comando npm
. En este caso también se debe instalar el controlador del motor de base de datos que se desee usar junto al ORM. A modo de ejemplo, para evitar la necesidad de configurar un motor de base de datos, vamos a usar SQLite en este proyecto. Así, el comando que se debe ejecutar en este caso es el siguiente
npm install typeorm sqlite3
Mediante el cual se instalará TypeORM y el controlador de SQLite 3.
Además de esto, debido a que TypeORM usa decoradores, es necesario modificar tres propiedades en el archivo tsconfig.json
. En concreto se tiene que configurar las propiedades experimentalDecorators
y emitDecoratorMetadata
a verdadero, para se puedan usar decoradores, y strictPropertyInitialization
a falso, para que al compilar las entidades no de un error de compilación porque los valores de las propiedades no están inicializados.
Configuración de TypeORM
Ahora que se ha instalado TypeORM junto al controlador de la base de datos podemos proceder a la configuración de este. Para ello se debe crear un archivo datsource.ts
con el siguiente código.
import * as path from 'path'; import { DataSource } from 'typeorm'; let entities = ['dist/entities/**/*.js']; if (path.extname(__filename) === '.ts') { entities = ['src/entities/**/*.ts']; } const datasource = new DataSource({ type: 'sqlite', database: 'database.db', entities, synchronize: true, }); export default datasource;
En este se crea una conexión a la base de datos con la clase DataSource
, pasándole para ello un objeto con las opciones necesarias. Para el caso de SQLite solamente hay que indicar el tipo de driver type
, el archivo en el que se encuentra la base de datos database
, la carpeta donde se encuentra la definición de las entidades entities
y una opción para que los cambios en las definiciones de las entidades se sincronicen de forma automática.
Nótese que al comienzo del archivo se define las entidades en función que la extensión del archivo se ts
, esto es, cuando se está ejecutando el programa con ts-node
. Algo que se hace para que el mismo código pueda funcionar tanto si el programa se ejecuta con ts-node
en desarrollo como si se hace ya compilado con node
.
Creación de una entidad con TypeORM
Ahora, una vez instalado y configurado TypeORM, se debe crear una entidad en la que almacenar datos. Posiblemente una de las más sencillas sea crear un usuario, para lo que se puede escribir en /src/entities
el siguiente archivo como user.ts
.
import { Entity, Column, PrimaryGeneratedColumn } from 'typeorm'; @Entity() export class User { @PrimaryGeneratedColumn() id: number; @Column() firstName: string; @Column() lastName: string; }
Nótese que la forma de crear la entidad es sencilla extremadamente sencilla. Simplemente se crea una clase y se usan los embellecedores de TypeORM para indicar que esta es una entidad (@Entity()
) y cada uno de los tipos de datos que representan las propiedades (@PrimaryGeneratedColumn()
o @Column()
). En este ejemplo se crea una entidad llamada User
con un id
numérico autogenerado y dos columnas de texto firstName
y lastName
. Aunque se puede configurar, en la mayoría de los casos no es necesario prestar atención al tipo de dato necesario en la base de datos.
Conexión con la base de datos y creación de un registro
Ahora, para conectar con la base de datos solamente hay que importar e iniciar datasource
. En el caso de que la conexión se inicie de forma correcta ya se podrá acceder a las entidades sin mayor problema. Para crear un nuevo registro solamente hay que crear un objeto y guardar éste en la fuente de datos. Esto es lo que se muestra en el siguiente ejemplo.
import datasource from './datasource'; import { User } from './entities/user'; // Conexión a la base de datos datasource .initialize() .then(async () => { const user = new User(); user.firstName = 'Nombre'; user.lastName = 'Apellido'; const result = await datasource.getRepository(User).save(user); console.log(result); }) .catch((err) => { console.error('Error during Data Source initialization:', err); });
En este ejemplo se inicia la fuente de datos mediante la propiedad initialize()
. En el caso de que se pueda realizar la conexión con la base de datos, se crea un nuevo registro y se guarda en la base de datos. El resultado de esto es un objeto que se puede ver por pantalla.
Por otro lado, si la conexión con la base de datos produjese un error, este se indicará por pantalla.
Comprobación de los cambios en la base de datos
Si se ejecuta el código anterior se creará un archivo database.db
en la raíz del proyecto con una base de datos SQLlite. Al abrir este archivo con un programa se podrá ver el esquema de la base de datos y que el registro se ha agregado a la tabla.
En concreto, en el ejemplo la tabla user se ha creado con un campo id
de tipo entorno no nulo y que es clave principal. Además de esto, se han creado dos campos de tipo varchar que tampoco pueden ser nulos.
Conclusiones
En esta tercera publicación de la serie se han visto los pasos necesarios para agregar y configurar TypeORM en el proyecto. La semana que viene se verá cómo crear nuestra primera API para agregar y eliminar usuarios.
Imagen de Tayeb MEZAHDIA en Pixabay