-
Notifications
You must be signed in to change notification settings - Fork 12
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #162 from conceptadev/tnramalho-feature/cache-module
Tnramalho feature/cache module
- Loading branch information
Showing
53 changed files
with
3,738 additions
and
613 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,227 @@ | ||
# Rockets NestJS Cache | ||
|
||
A module for managing a basic Cache entity, including controller with full CRUD, DTOs, sample data factory and seeder. | ||
|
||
## Project | ||
|
||
[![NPM Latest](https://img.shields.io/npm/v/@concepta/nestjs-user)](https://www.npmjs.com/package/@concepta/nestjs-user) | ||
[![NPM Downloads](https://img.shields.io/npm/dw/@conceptadev/nestjs-user)](https://www.npmjs.com/package/@concepta/nestjs-user) | ||
[![GH Last Commit](https://img.shields.io/github/last-commit/conceptadev/rockets?logo=github)](https://github.com/conceptadev/rockets) | ||
[![GH Contrib](https://img.shields.io/github/contributors/conceptadev/rockets?logo=github)](https://github.com/conceptadev/rockets/graphs/contributors) | ||
[![NestJS Dep](https://img.shields.io/github/package-json/dependency-version/conceptadev/rockets/@nestjs/common?label=NestJS&logo=nestjs&filename=packages%2Fnestjs-core%2Fpackage.json)](https://www.npmjs.com/package/@nestjs/common) | ||
|
||
## Table of Contents | ||
|
||
- [Introduction](#introduction) | ||
- [Installation](#installation) | ||
- [Usage](#usage) | ||
- [Configuration Details](#configuration-details) | ||
- [Setup](#setup) | ||
- [Configuration Options Explained](#configuration-options-explained) | ||
|
||
## Introduction | ||
|
||
This module is a basic implementation of a caching mechanism for your application. It allows you to cache data in a database and retrieve it later, ensuring that your application is not repeatedly fetching the same data from a database. | ||
|
||
Installation | ||
To install the module, use the following command: | ||
|
||
## Installation | ||
|
||
`yarn add @concepta/nestjs-cache` | ||
|
||
## Configuration | ||
|
||
The Cache Module allows for detailed configuration to link your application's data models with caching mechanisms. | ||
|
||
### Configuration Options Explained | ||
|
||
- **settings**: Manages how entities are assigned for caching. | ||
- **entities**: Specifies which entities are to be cached. | ||
|
||
## Usage | ||
|
||
To utilize the caching module, you need to define the entities and configure the module appropriately. | ||
|
||
## Example | ||
Define your UserEntityFixture and UserCacheEntityFixture entities as follows: | ||
|
||
```ts | ||
@Entity() | ||
export class UserEntityFixture implements ReferenceIdInterface { | ||
@PrimaryGeneratedColumn('uuid') | ||
id!: string; | ||
|
||
@Column({ default: false }) | ||
isActive!: boolean; | ||
|
||
@OneToMany(() => UserCacheEntityFixture, (userCache) => userCache.assignee) | ||
userCaches!: UserCacheEntityFixture[]; | ||
} | ||
|
||
``` | ||
|
||
```typescript | ||
@Entity() | ||
export class UserCacheEntityFixture extends CacheSqliteEntity { | ||
@ManyToOne(() => UserEntityFixture, (user) => user.userCaches) | ||
assignee!: ReferenceIdInterface; | ||
} | ||
``` | ||
## Setup | ||
|
||
### Define Entities | ||
Ensure that you have defined the entities in your project that you wish to cache. For instance, a UserEntityFixture might be used for storing user information. | ||
|
||
### Configure the Cache Module | ||
Incorporate the Cache Module into your application module and configure it for your specific needs: | ||
|
||
```ts | ||
// ... | ||
|
||
@Module({ | ||
imports: [ | ||
TypeOrmExtModule.forRoot({ | ||
type: 'postgres', | ||
url: 'postgres://user:pass@localhost:5432/postgres', | ||
}), | ||
CacheModule.register({ | ||
settings: { | ||
assignments: { | ||
user: { entityKey: 'userCache' }, | ||
}, | ||
}, | ||
entities: { | ||
userCache: { | ||
entity: UserCacheEntityFixture, | ||
}, | ||
}, | ||
}), | ||
CacheModule.forRoot({}), | ||
], | ||
}) | ||
export class AppModule {} | ||
``` | ||
|
||
### Client-side Interaction with CRUD Endpoints | ||
|
||
The Cache API provides RESTful endpoints for managing cached data. The endpoint path follows the format `cache/:assignment`, where `:assignment` is defined in your module configuration. For example, if you have the configuration: | ||
|
||
```typescript | ||
CacheModule.register({ | ||
settings: { | ||
assignments: { | ||
user: { entityKey: 'userCache' }, | ||
}, | ||
}, | ||
entities: { | ||
userCache: { | ||
entity: UserCacheEntityFixture, | ||
}, | ||
}, | ||
}) | ||
``` | ||
The endpoint will be cache/user. Below are examples of how to interact with the API using curl. | ||
|
||
### Create (POST) | ||
To create a new cache entry, the request body should match the CacheCreatableInterface: | ||
|
||
```ts | ||
export interface CacheCreatableInterface extends Pick<CacheInterface, 'key' | 'type' | 'data' | 'assignee'> { | ||
expiresIn: string | null; | ||
} | ||
``` | ||
Example curl command: | ||
|
||
```sh | ||
curl -X POST http://your-api-url/cache/user \ | ||
-H "Content-Type: application/json" \ | ||
-d '{ | ||
"key": "exampleKey", | ||
"type": "exampleType", | ||
"data": "{data: 'example'}", | ||
"assignee": { id: 'exampleId'}, | ||
"expiresIn": "1h" | ||
}' | ||
|
||
``` | ||
### Read (GET) | ||
To read a cache entry by its ID: | ||
|
||
```sh | ||
curl -X GET http://your-api-url/cache/user/{id} | ||
``` | ||
|
||
### Update (PUT) | ||
To update an existing cache entry, the request body should match the CacheUpdatableInterface: | ||
|
||
```ts | ||
export interface CacheUpdatableInterface extends Pick<CacheInterface, 'key' | 'type' | 'data' | 'assignee'> { | ||
expiresIn: string | null; | ||
} | ||
|
||
``` | ||
Example curl command: | ||
|
||
```sh | ||
curl -X PUT http://your-api-url/cache/user/{id} \ | ||
-H "Content-Type: application/json" \ | ||
-d '{ | ||
"key": "updatedKey", | ||
"type": "updatedType", | ||
"data": "updatedData", | ||
"assignee": "updatedAssignee", | ||
"expiresIn": "2d" | ||
}' | ||
|
||
``` | ||
### Delete (DELETE) | ||
To delete a cache entry by its ID: | ||
|
||
```sh | ||
curl -X DELETE http://your-api-url/cache/user/{id} | ||
``` | ||
|
||
Replace http://your-api-url with the actual base URL of your API, and {id} with the actual ID of the cache entry you wish to interact with. | ||
|
||
By following these examples, you can perform Create, Read, Update, and Delete operations on your cache data using the provided endpoints. | ||
|
||
## How the Module Works | ||
|
||
### Overview | ||
|
||
The Rockets NestJS Cache module is designed to provide an easy and efficient way to manage cached data in your application. Here's a simple explanation of how it works: | ||
|
||
### Dynamic Controller Generation | ||
|
||
The module automatically creates controllers based on the settings you provide. This means you can set up different cache entities and their endpoints without writing extra code. The endpoints are created based on the assignments you define in the module configuration. | ||
|
||
### CRUD Operations | ||
|
||
The module supports all basic operations: Create, Read, Update, and Delete (CRUD). These operations are managed by a controller that uses special decorators to define and control access. The operations are routed based on the cache assignment specified in the request. | ||
|
||
### Service Injection | ||
|
||
The module uses a technique called dependency injection to manage its settings and services. It injects configuration settings that define cache assignments and expiration times, as well as a list of CRUD services. This allows the module to dynamically choose the right service for each cache assignment. | ||
|
||
### Handling Assignments | ||
|
||
In the module configuration, you specify different cache assignments. Each assignment is linked to a specific entity and CRUD service. When a request is made to the cache endpoint, the module uses the assignment in the request to determine which entity and service to use. | ||
|
||
### Exception Handling | ||
|
||
The module has built-in error handling to manage invalid assignments or entity keys. It throws specific errors when something goes wrong, ensuring that your application can handle these issues gracefully and provide clear error messages to the client. | ||
|
||
### Summary | ||
|
||
The Rockets NestJS Cache module provides a powerful and flexible way to manage cached data. By automatically generating controllers, using dependency injection, and handling various types of cached data dynamically, it ensures your application can run efficiently without redundant database queries. | ||
|
||
|
||
#### ENV | ||
|
||
Configurations available via environment. | ||
|
||
| Variable | Type | Default | | | ||
| -------------------------- | ---------- | ------- | ------------------------------------ | | ||
| `CACHE_MODULE_SEEDER_AMOUNT` | `<number>` | `50` | number of additional users to create | | ||
| `CACHE_EXPIRE_IN` | `<string>` | `1d` | string for the amount of time to expire the cache | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
{ | ||
"name": "@concepta/nestjs-cache", | ||
"version": "4.0.0-alpha.44", | ||
"description": "Rockets NestJS User", | ||
"main": "dist/index.js", | ||
"types": "dist/index.d.ts", | ||
"license": "BSD-3-Clause", | ||
"publishConfig": { | ||
"access": "public" | ||
}, | ||
"files": [ | ||
"dist/**/!(*.spec|*.e2e-spec|*.fixture).{js,d.ts}" | ||
], | ||
"dependencies": { | ||
"@concepta/nestjs-access-control": "^4.0.0-alpha.44", | ||
"@concepta/nestjs-common": "^4.0.0-alpha.44", | ||
"@concepta/nestjs-core": "^4.0.0-alpha.44", | ||
"@concepta/nestjs-crud": "^4.0.0-alpha.44", | ||
"@concepta/nestjs-exception": "^4.0.0-alpha.44", | ||
"@concepta/nestjs-typeorm-ext": "^4.0.0-alpha.44", | ||
"@concepta/ts-common": "^4.0.0-alpha.44", | ||
"@concepta/ts-core": "^4.0.0-alpha.44", | ||
"@concepta/typeorm-common": "^4.0.0-alpha.44", | ||
"@nestjs/common": "^9.0.0", | ||
"@nestjs/config": "^2.2.0", | ||
"@nestjs/swagger": "^6.0.0", | ||
"ms": "^2.1.3" | ||
}, | ||
"devDependencies": { | ||
"@concepta/typeorm-seeding": "^4.0.0-beta.0", | ||
"@faker-js/faker": "^6.0.0-alpha.6", | ||
"@nestjs/testing": "^9.0.0", | ||
"@nestjs/typeorm": "^9.0.0", | ||
"@types/ms": "^0.7.31", | ||
"@types/supertest": "^2.0.11", | ||
"jest-mock-extended": "^2.0.4", | ||
"supertest": "^6.1.3" | ||
}, | ||
"peerDependencies": { | ||
"class-transformer": "*", | ||
"class-validator": "*", | ||
"typeorm": "^0.3.0" | ||
} | ||
} |
32 changes: 32 additions & 0 deletions
32
packages/nestjs-cache/src/__fixtures__/app.module.fixture.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
import { Module } from '@nestjs/common'; | ||
import { TypeOrmExtModule } from '@concepta/nestjs-typeorm-ext'; | ||
import { CrudModule } from '@concepta/nestjs-crud'; | ||
|
||
import { CacheModule } from '../cache.module'; | ||
import { UserEntityFixture } from './entities/user-entity.fixture'; | ||
import { UserCacheEntityFixture } from './entities/user-cache-entity.fixture'; | ||
|
||
@Module({ | ||
imports: [ | ||
TypeOrmExtModule.forRoot({ | ||
type: 'sqlite', | ||
database: ':memory:', | ||
synchronize: true, | ||
entities: [UserEntityFixture, UserCacheEntityFixture], | ||
}), | ||
CacheModule.register({ | ||
entities: { | ||
userCache: { | ||
entity: UserCacheEntityFixture, | ||
}, | ||
}, | ||
settings: { | ||
assignments: { | ||
user: { entityKey: 'userCache' }, | ||
}, | ||
}, | ||
}), | ||
CrudModule.forRoot({}), | ||
], | ||
}) | ||
export class AppModuleFixture {} |
13 changes: 13 additions & 0 deletions
13
packages/nestjs-cache/src/__fixtures__/entities/user-cache-entity.fixture.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
import { Entity, ManyToOne } from 'typeorm'; | ||
import { ReferenceIdInterface } from '@concepta/ts-core'; | ||
import { UserEntityFixture } from './user-entity.fixture'; | ||
import { CacheSqliteEntity } from '../../entities/cache-sqlite.entity'; | ||
|
||
/** | ||
* Cache Entity Fixture | ||
*/ | ||
@Entity() | ||
export class UserCacheEntityFixture extends CacheSqliteEntity { | ||
@ManyToOne(() => UserEntityFixture, (user) => user.userCaches) | ||
assignee!: ReferenceIdInterface; | ||
} |
18 changes: 18 additions & 0 deletions
18
packages/nestjs-cache/src/__fixtures__/entities/user-entity.fixture.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
import { Column, Entity, OneToMany, PrimaryGeneratedColumn } from 'typeorm'; | ||
import { ReferenceIdInterface } from '@concepta/ts-core'; | ||
import { UserCacheEntityFixture } from './user-cache-entity.fixture'; | ||
|
||
/** | ||
* User Entity Fixture | ||
*/ | ||
@Entity() | ||
export class UserEntityFixture implements ReferenceIdInterface { | ||
@PrimaryGeneratedColumn('uuid') | ||
id!: string; | ||
|
||
@Column({ default: false }) | ||
isActive!: boolean; | ||
|
||
@OneToMany(() => UserCacheEntityFixture, (userCache) => userCache.assignee) | ||
userCaches!: UserCacheEntityFixture[]; | ||
} |
20 changes: 20 additions & 0 deletions
20
packages/nestjs-cache/src/__fixtures__/factories/user-cache.factory.fixture.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
import Faker from '@faker-js/faker'; | ||
import { Factory } from '@concepta/typeorm-seeding'; | ||
import { UserCacheEntityFixture } from '../entities/user-cache-entity.fixture'; | ||
|
||
export class UserCacheFactoryFixture extends Factory<UserCacheEntityFixture> { | ||
protected options = { | ||
entity: UserCacheEntityFixture, | ||
}; | ||
|
||
protected async entity( | ||
userCache: UserCacheEntityFixture, | ||
): Promise<UserCacheEntityFixture> { | ||
userCache.key = Faker.name.jobArea(); | ||
userCache.type = 'filter'; | ||
userCache.data = JSON.stringify({ sortBy: 'name' }); | ||
userCache.expirationDate = new Date(); | ||
|
||
return userCache; | ||
} | ||
} |
Oops, something went wrong.