@nestjs/azure-database
v3.0.0
Published
The Azure Table Storage module for Nest framework (node.js)
Downloads
11,012
Readme
Description
Azure Database (Table Storage, Cosmos DB - NoSQL) module for Nest framework (node.js)
Disclaimer
You are reading documentation for version 3. If you are looking for version 2 documentation, click here. Please also note that version 2 is no longer maintained and will not receive any updates!
Before Installation
For Table Storage
- Create a Storage account and resource (read more)
- Note down the "Connection string" - You will need it later
For Cosmos DB (NoSQL ONLY)
- Create a Cosmos DB account and resource (read more)
- Note down the "URI", Database name and the "Primary Key" (or "Secondary Key") - You will need them later
Installation
$ npm i --save @nestjs/azure-database
Usage
For Azure Table Storage support
- Create or update your existing
.env
file with the following content:
AZURE_STORAGE_CONNECTION_STRING=
IMPORTANT: Make sure to add your
.env
file to your .gitignore! The.env
file MUST NOT be versioned on Git.Make sure to include the following call to your
main.ts
file:
if (process.env.NODE_ENV !== 'production') require('dotenv').config();
This line must be added before any other imports!
- The
AzureTableStorageModule
will automatically read theAZURE_STORAGE_CONNECTION_STRING
environment variable and use it to connect to your Azure Storage account.
Example
Check out the Table Storage example project included in the sample folder
Prepare your entity
- Create a new feature module, eg. with the nest CLI:
$ nest generate module event
- Create a Data Transfer Object (DTO) inside a file named
event.dto.ts
:
export class EventDTO {
name: string;
type: string;
}
- Create a file called
event.entity.ts
and describe the entity model using plain JavaScript objects. The only requirement is to provide apartitionKey
and arowKey
properties. For instance, the shape of the following entity:
export class Event {
partitionKey: string; // required
rowKey: string; // required
name: string;
type: string;
}
- Import the
AzureTableStorageModule
inside your Nest feature moduleevent.module.ts
:
import { Module } from '@nestjs/common';
import { AzureTableStorageModule } from '@nestjs/azure-database';
@Module({
imports: [AzureTableStorageModule.forFeature(Event)],
})
export class EventModule {}
You can optionally pass in the following arguments:
import { Module } from '@nestjs/common';
import { AzureTableStorageModule } from '@nestjs/azure-database';
@Module({
imports: [
AzureTableStorageModule.forFeature(Event, {
table: 'foobar',
createTableIfNotExists: true,
}),
],
})
export class EventModule {}
table: string
: The name of the table. If not provided, the name of theEvent
entity will be used as a table namecreateTableIfNotExists: boolean
: Whether to automatically create the table if it doesn't exists or not:- If
true
the table will be created during the startup of the app. - If
false
the table will not be created. You will have to create the table by yourself before querying it!
- If
CRUD operations
- Create a service that will abstract the CRUD operations:
$ nest generate service event
- Use the
@InjectRepository(Event)
to get an instance of the AzureRepository
for the entity definition created earlier:
import { InjectRepository, Repository } from '@nestjs/azure-database';
import { Injectable } from '@nestjs/common';
import { Event } from './event.entity';
@Injectable()
export class EventService {
constructor(
@InjectRepository(Event)
private readonly eventRepository: Repository<Event>,
) {}
}
The AzureTableStorageRepository
provides a list of public methods for managing various CRUD operations:
CREATE
create(entity: T): Promise<T | null>
: creates a new entity.
async create(event: Event): Promise<Event> {
return await this.eventRepository.create(event);
}
READ
find(partitionKey: string, rowKey: string): Promise<T>
: finds one entity using its partitionKey
and rowKey
.
async find(partitionKey: string, rowKey: string): Promise<Event> {
return await this.eventRepository.find(partitionKey, rowKey);
}
findAll(): Promise<T[]>
: finds all entities (NOTE: odata filters are not supported yet).
async findAll(): Promise<Event[]> {
return await this.eventRepository.findAll();
}
UPDATE
update(partitionKey: string, rowKey: string, entity: T): Promise<T>
: Updates an entity using a "merge" strategy.
async update(
partitionKey: string,
rowKey: string,
event: Event,
): Promise<Event> {
return await this.eventRepository.update(partitionKey, rowKey, event);
}
DELETE
delete(partitionKey: string, rowKey: string): Promise<DeleteTableEntityResponse>
: Removes an entity from the table.
async delete(partitionKey: string, rowKey: string): Promise<void> {
await this.eventRepository.delete(partitionKey, rowKey);
}
For Azure Cosmos DB support
- Create or update your existing
.env
file with the following content:
AZURE_COSMOS_DB_NAME=
AZURE_COSMOS_DB_ENDPOINT=
AZURE_COSMOS_DB_KEY=
IMPORTANT: Make sure to add your
.env
file to your .gitignore! The.env
file MUST NOT be versioned on Git.Make sure to include the following call to your
main.ts
file:
if (process.env.NODE_ENV !== 'production') require('dotenv').config();
This line must be added before any other imports!
Example
Note: Check out the CosmosDB example project included in the sample folder
Prepare your entity
- Create a new feature module, eg. with the nest CLI:
$ nest generate module event
- Create a Data Transfer Object (DTO) inside a file named
event.dto.ts
:
export class EventDTO {
id?: string;
name: string;
type: string;
createdAt: Date;
}
- Create a file called
event.entity.ts
and describe the entity model using the provided decorators:
@CosmosPartitionKey(value: string)
: Represents thePartitionKey
of the entity (required).@CosmosDateTime(value?: string)
: For DateTime values.
For instance, the shape of the following entity:
import { CosmosDateTime, CosmosPartitionKey } from '@nestjs/azure-database';
@CosmosPartitionKey('type')
export class Event {
name: string;
type: string;
@CosmosDateTime() createdAt: Date;
}
Will be automatically converted to:
{
"name": "NestJS Meetup",
"type": "Meetup",
"createdAt": "2019-11-15T17:05:25.427Z"
}
- Import the
AzureCosmosDbModule
inside your Nest feature moduleevent.module.ts
:
import { AzureCosmosDbModule } from '@nestjs/azure-database';
import { Module } from '@nestjs/common';
import { Event } from './event.entity';
@Module({
imports: [
AzureCosmosDbModule.forRoot({
dbName: process.env.AZURE_COSMOS_DB_NAME,
endpoint: process.env.AZURE_COSMOS_DB_ENDPOINT,
key: process.env.AZURE_COSMOS_DB_KEY,
retryAttempts: 1,
}),
AzureCosmosDbModule.forFeature([{ dto: Event }]),
],
})
export class EventModule {}
CRUD operations
- Create a service that will abstract the CRUD operations:
$ nest generate service event
- Use the
@InjectModel(Event)
to get an instance of the Azure Cosmos DB Container for the entity definition created earlier:
import { InjectModel } from '@nestjs/azure-database';
import type { Container } from '@azure/cosmos';
import { Injectable } from '@nestjs/common';
import { Event } from './event.entity';
@Injectable()
export class EventService {
constructor(
@InjectModel(Event)
private readonly eventContainer: Container,
) {}
}
@InjectModel(Event)
will inject an Azure Cosmos DB Container
instance for the Event
entity. The Container
provides a list of public methods for managing the database.
IMPORTANT: Please note that the Container
instance is not a NestJS repository. It is the actual instance provided by the official Azure Cosmos DB SDK.
CREATE
create(entity: T): Promise<T>
: creates a new entity.
async create(eventDto: EventDTO): Promise<Event> {
const { resource } = await this.eventContainer.items.create<Event>(
eventDto,
);
return resource;
}
READ
Items.query<T>(query: string | SqlQuerySpec, options?: FeedOptions): QueryIterator<T>
: Queries the database using a SQL query.
QueryIterator<Event>.fetchAll(): Promise<FeedResponse<Event>>
: Fetches all the results of the query.
async getEvents(): Promise<Event[]> {
const querySpec = {
query: 'SELECT * FROM events',
};
const { resources } = await this.eventContainer.items
.query<Event>(querySpec)
.fetchAll();
return resources;
}
UPDATE
Item.replace<
T& Resource>(body:
T & Resource, options?: RequestOptions): Promise<ItemResponse<
T & Resource>>
: Replaces an item in the database.
async updateEvent(
id: string,
type: string,
eventData: EventDTO,
): Promise<Event> {
let { resource: item } = await this.eventContainer
.item(id, type)
.read<Event>();
item = {
...item,
...eventData,
};
const { resource: replaced } = await this.eventContainer
.item(id, type)
.replace(item);
return replaced;
}
DELETE
Item.delete<T>(options?: RequestOptions): Promise<ItemResponse<T>>
: Deletes an item from the database.
async deleteEvent(id: string, type: string): Promise<Event> {
const { resource: deleted } = await this.eventContainer
.item(id, type)
.delete<Event>();
return deleted;
}
Support
Nest is an MIT-licensed open source project. It can grow thanks to the sponsors and support by the amazing backers. If you'd like to join them, please read more here.
Stay in touch
- Author - Wassim Chegham
- Website - https://wassim.dev
- Twitter - @manekinekko
License
Nest is MIT licensed.