@iappx/entity-repo
v3.0.0
Published
A TypeScript library that abstracts data sources and provides a unified context-based access to entities, queries, and transports.
Downloads
25
Maintainers
Readme
About The Project
Entity Repo is a lightweight and flexible TypeScript library designed to abstract your data source and make entity access seamless through a unified context system.
It provides a clean way to describe entities, register transports (data providers), and build queries with a builder-like pattern.
Here's why Entity Repo might be useful:
- Decouple your business logic from the actual data source
- Keep your codebase consistent by accessing data only through contexts
- Extendable by custom transports, queries, and contexts
Core Concepts
The main components of Entity Repo are EntitySet, Entity, Context, and Transport.
RepoEntity
Base class for declaring entities.
Example:
export class Book extends RepoEntityBase<Book> {
@RepoEntityField({ isPrimaryKey: true })
id: number
@RepoEntityField()
name: string
}
export class Account extends RepoEntityBase<Account> {
@RepoEntityField({ isPrimaryKey: true })
id: string
@RepoEntityField()
email: string
@RepoEntityField({ nestedType: () => Book })
books: Book[]
}Transport
A transport handles communication with the data source and must implement the ITransport interface.
Example Axios transport:
export class AxiosTransport implements ITransport<AxiosRequestConfig> {
protected client: Axios
constructor(config?: AxiosRequestConfig) {
this.client = new Axios(config)
}
async send<TRes>(config: AxiosRequestConfig): Promise<TRes> {
return this.client.request(config)
}
}EntityQuery
Represents entity access logic and can implement custom query methods. It inherits from the base EntityQuery and can be used as a builder.
export type TRestEntitySetQueryParams = {
endpoint: string
}
export type TQueryParams = {
appId: string
}
export class RestEntityQuery<T extends RepoEntityBase> extends EntityQuery<T, AxiosTransport, TRestEntitySetQueryParams> {
private queryParams: TQueryParams
public addQueryParams(params: TQueryParams): RestEntityQuery<T> {
this.queryParams = {
...this.queryParams,
...params,
}
return this
}
public async getAll(): Promise<T[]> {
const response = await this.transport.send<any[]>({
url: this.options.endpoint,
})
return response.map(p => this.entityConstructor.build(p))
}
public async create(entity: T): Promise<T> {
const response = await this.transport.send<Record<string, any>>({
url: this.options.endpoint,
method: 'POST',
data: entity.getDataValues(),
})
return this.entityConstructor.build(response)
}
}EntityContext
Combines entities into a single access point, without direct dependency on repositories or other services.
export class EntityContext extends EntityContextBase<AxiosTransport> {
@RepoEntitySet(() => Account, () => RestEntityQuery, { endpoint: '/api/account' })
public accounts: RestEntityQuery<Account>
}Getting Started
Prerequisites
- Node.js >= 18
- npm or yarn
npm install npm@latest -gInstallation
npm install @iappx/entity-repo
# or
yarn add @iappx/entity-repoUsage
Here’s an example of how to combine everything:
const repo = EntityRepo.create()
.use(EntityContext, new AxiosTransport({ baseURL: 'https://api.your.app' }))
const context = repo.getContext(EntityContext)
const accounts = await context.accounts
.addQueryParams({ appId: 'test-app' })
.getAll()
console.log('accounts', accounts)
const newAccount = Account.build({ email: '[email protected]' })
await context.accounts
.addQueryParams({ appId: 'test-app' })
.create(newAccount)License
Distributed under the MIT License. See LICENSE for more information.
