@eac-arch/infrastructure-persistence 1.0.1 → 1.0.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md
CHANGED
|
@@ -1,63 +1,71 @@
|
|
|
1
|
-
#
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
##
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
##
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
```bash
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
1
|
+
# @eac-arch/infrastructure-persistence
|
|
2
|
+
|
|
3
|
+
Angular infrastructure library with HTTP repository/query abstractions for data access.
|
|
4
|
+
|
|
5
|
+
## Purpose
|
|
6
|
+
|
|
7
|
+
`@eac-arch/infrastructure-persistence` provides reusable base classes to implement repositories and query services over HTTP, keeping client code aligned with DDD/CQRS contracts from shared-kernel.
|
|
8
|
+
|
|
9
|
+
## Main Capabilities
|
|
10
|
+
|
|
11
|
+
- `ReadOnlyHttpRepository<TEntity, TDto, TQueryOptions>`
|
|
12
|
+
: Read operations (`getAll`, `getById`, `exists`) with DTO -> entity mapping.
|
|
13
|
+
- `GenericHttpRepository<...>`
|
|
14
|
+
: Extends read-only base with `create`, `upsert`, `updatePartial`, and `delete`.
|
|
15
|
+
- `HttpRepository<...>`
|
|
16
|
+
: Thin alias for common full CRUD use cases.
|
|
17
|
+
- `HttpQueryService<TModel, TQueryOptions>`
|
|
18
|
+
: Base read-model query service with pagination, specification support, sort formatting, and sparse field selection.
|
|
19
|
+
|
|
20
|
+
## Public API
|
|
21
|
+
|
|
22
|
+
```ts
|
|
23
|
+
export { ReadOnlyHttpRepository };
|
|
24
|
+
export { GenericHttpRepository };
|
|
25
|
+
export { HttpRepository };
|
|
26
|
+
export { HttpQueryService, type BaseQueryOptions };
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
## Usage Pattern
|
|
30
|
+
|
|
31
|
+
1. Extend a repository base.
|
|
32
|
+
2. Implement transport delegates (`doGetAll`, `doGetById`, `doCreate`, etc.).
|
|
33
|
+
3. Implement DTO mapping (`mapToEntity`, `extractId`, optional `rehydrate`).
|
|
34
|
+
4. Reuse `HttpQueryService` for read-side pagination/filtering.
|
|
35
|
+
|
|
36
|
+
## Dependencies
|
|
37
|
+
|
|
38
|
+
- `@eac-arch/shared-kernel`
|
|
39
|
+
- `@eac-arch/infrastructure-http`
|
|
40
|
+
- Angular core/common
|
|
41
|
+
- `tslib`
|
|
42
|
+
|
|
43
|
+
## Development
|
|
44
|
+
|
|
45
|
+
From `eac-arch-infrastructure-persistence`:
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
npm install
|
|
49
|
+
npm run build
|
|
50
|
+
npm test
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
## Created By
|
|
55
|
+
|
|
56
|
+
**Erick Arostegui Cunza**
|
|
57
|
+
Enterprise Solutions Architect
|
|
58
|
+
|
|
59
|
+
Professional Profile:
|
|
60
|
+
- LinkedIn: https://www.linkedin.com/in/erick-arostegui-cunza/
|
|
61
|
+
|
|
62
|
+
Articles:
|
|
63
|
+
- Medium: https://medium.com/@scorpius86
|
|
64
|
+
|
|
65
|
+
Channels and Media:
|
|
66
|
+
- Facebook: https://www.facebook.com/Erick.Arostegui.Cunza
|
|
67
|
+
- TikTok: https://www.tiktok.com/@erick_arostegui_cunza
|
|
68
|
+
- Instagram: https://www.instagram.com/erickarosteguicunza/
|
|
69
|
+
- Spotify: https://open.spotify.com/show/2JQxlxcRg7k7cJ1hB52Ge5
|
|
70
|
+
|
|
71
|
+
Created by Erick Arostegui Cunza.
|
|
@@ -1,30 +1,129 @@
|
|
|
1
|
-
import
|
|
2
|
-
import { Component } from '@angular/core';
|
|
1
|
+
import { createPagedList, QuerySpecification, formatSortFields } from '@eac-arch/shared-kernel';
|
|
3
2
|
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
3
|
+
// Client-side mirror of the server's ReadOnlyRepository<TEntity, TDbContext>.
|
|
4
|
+
// Provides read operations backed by an HTTP agent instead of EF Core.
|
|
5
|
+
//
|
|
6
|
+
// Subclasses provide:
|
|
7
|
+
// - mapToEntity() — maps a raw API model to the domain entity (used in getAll).
|
|
8
|
+
// - rehydrate() — virtual override for getById when child collections must be loaded.
|
|
9
|
+
// - doGetAll() — delegate to agent.getAll*() method.
|
|
10
|
+
// - doGetById() — delegate to agent.getById*() method.
|
|
11
|
+
// - doExists() — delegate to agent.exists*() method.
|
|
12
|
+
class ReadOnlyHttpRepository {
|
|
13
|
+
// Override when getById must reconstruct a fully-loaded aggregate (e.g. with child collections).
|
|
14
|
+
// Default: delegates to mapToEntity.
|
|
15
|
+
rehydrate(id, dto) {
|
|
16
|
+
return Promise.resolve(this.mapToEntity(dto));
|
|
17
|
+
}
|
|
18
|
+
// -- ReadOnlyHttpRepository implementation --
|
|
19
|
+
async getAll(pageNumber, pageSize, options) {
|
|
20
|
+
const page = await this.doGetAll(pageNumber, pageSize, options);
|
|
21
|
+
return createPagedList([...page.items].map(m => this.mapToEntity(m)), page.totalCount, page.currentPage, page.pageSize);
|
|
22
|
+
}
|
|
23
|
+
async getById(id) {
|
|
24
|
+
const dto = await this.doGetById(id);
|
|
25
|
+
if (!dto)
|
|
26
|
+
return null;
|
|
27
|
+
return this.rehydrate(id, dto);
|
|
28
|
+
}
|
|
29
|
+
exists(id) {
|
|
30
|
+
return this.doExists(id);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
// Client-side mirror of the server's GenericRepository<TEntity, TDbContext>.
|
|
35
|
+
// Extends ReadOnlyHttpRepository with full CRUD operations.
|
|
36
|
+
//
|
|
37
|
+
// Subclasses must additionally implement:
|
|
38
|
+
// - doCreate() — delegate to agent.create*() method.
|
|
39
|
+
// - doUpsert() — delegate to agent.upsert*() method.
|
|
40
|
+
// - doUpdatePartial() — delegate to agent.updatePartial*() method.
|
|
41
|
+
// - doDelete() — delegate to agent.delete*() method.
|
|
42
|
+
class GenericHttpRepository extends ReadOnlyHttpRepository {
|
|
43
|
+
// -- HttpRepository implementation --
|
|
44
|
+
async create(data) {
|
|
45
|
+
const dto = await this.doCreate(data);
|
|
46
|
+
return this.rehydrate(this.extractId(dto), dto);
|
|
47
|
+
}
|
|
48
|
+
async upsert(id, data) {
|
|
49
|
+
const dto = await this.doUpsert(id, data);
|
|
50
|
+
return dto ? this.rehydrate(id, dto) : null;
|
|
51
|
+
}
|
|
52
|
+
updatePartial(id, changes) {
|
|
53
|
+
return this.doUpdatePartial(id, changes);
|
|
54
|
+
}
|
|
55
|
+
delete(id) {
|
|
56
|
+
return this.doDelete(id);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
// Client-side mirror of the server's Repository<TEntity, TDbContext>.
|
|
61
|
+
// Thin alias over GenericHttpRepository — entry point for most use cases.
|
|
62
|
+
class HttpRepository extends GenericHttpRepository {
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
// Client-side mirror of the server's QueryService<T, TDbContext>.
|
|
66
|
+
// Provides the full QueryService<TModel> contract plus shared helpers:
|
|
67
|
+
// - buildOptions() — builds TQueryOptions from Specification + SortField[].
|
|
68
|
+
// - toPagedList() — converts an agent PagedList response to the shared format.
|
|
69
|
+
//
|
|
70
|
+
// Root resource query services (e.g. AuthorQueryServiceImpl) override doGetAll/doGetById
|
|
71
|
+
// and gain getAll/getById/getPagedList for free.
|
|
72
|
+
//
|
|
73
|
+
// Sub-resource query services (e.g. AwardQueryServiceImpl) extend this for buildOptions
|
|
74
|
+
// and toPagedList only; their parent-scoped methods use these helpers directly.
|
|
75
|
+
class HttpQueryService {
|
|
76
|
+
// Override in root resource query services.
|
|
77
|
+
// Default: throws because sub-resource query services require a parent ID.
|
|
78
|
+
doGetAll(_pageNumber, _pageSize, _options) {
|
|
79
|
+
throw new Error('getAll is not supported by this query service');
|
|
80
|
+
}
|
|
81
|
+
// Override in root resource query services.
|
|
82
|
+
doGetById(_id) {
|
|
83
|
+
throw new Error('getById is not supported by this query service');
|
|
84
|
+
}
|
|
85
|
+
// -- QueryService<TModel> implementation --
|
|
86
|
+
async getAll() {
|
|
87
|
+
const result = await this.doGetAll(1, Number.MAX_SAFE_INTEGER);
|
|
88
|
+
return [...result.items];
|
|
89
|
+
}
|
|
90
|
+
getById(id) {
|
|
91
|
+
return this.doGetById(id);
|
|
92
|
+
}
|
|
93
|
+
async getPagedList(pageNumber, pageSize, spec, sortFields, fields) {
|
|
94
|
+
const options = this.buildOptions(spec, sortFields, fields);
|
|
95
|
+
const result = await this.doGetAll(pageNumber, pageSize, options);
|
|
96
|
+
return this.toPagedList(result);
|
|
97
|
+
}
|
|
98
|
+
// -- Shared helpers --
|
|
99
|
+
// Converts a Specification + SortField[] into the agent-compatible TQueryOptions shape.
|
|
100
|
+
// All subclasses share this exact logic — previously duplicated in every impl.
|
|
101
|
+
buildOptions(spec, sortFields, fields) {
|
|
102
|
+
const options = {};
|
|
103
|
+
if (spec instanceof QuerySpecification)
|
|
104
|
+
Object.assign(options, spec.toQueryParams());
|
|
105
|
+
if (sortFields?.length)
|
|
106
|
+
options.sort = formatSortFields(sortFields);
|
|
107
|
+
if (fields?.length)
|
|
108
|
+
options.fields = fields.join(',');
|
|
109
|
+
return options;
|
|
110
|
+
}
|
|
111
|
+
// Converts an agent PagedList<TModel> into the shared PagedList format from @eac-arch/shared-kernel.
|
|
112
|
+
toPagedList(source) {
|
|
113
|
+
return createPagedList([...source.items], source.totalCount, source.currentPage, source.pageSize);
|
|
114
|
+
}
|
|
11
115
|
}
|
|
12
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: EacArchInfrastructurePersistence, decorators: [{
|
|
13
|
-
type: Component,
|
|
14
|
-
args: [{ selector: 'eac-arch-eac-arch-infrastructure-persistence', imports: [], template: `
|
|
15
|
-
<p>
|
|
16
|
-
eac-arch-infrastructure-persistence works!
|
|
17
|
-
</p>
|
|
18
|
-
` }]
|
|
19
|
-
}] });
|
|
20
116
|
|
|
21
117
|
/*
|
|
22
118
|
* Public API Surface of eac-arch-infrastructure-persistence
|
|
23
119
|
*/
|
|
120
|
+
/*
|
|
121
|
+
* Public API Surface of @eac-arch/infrastructure-persistence
|
|
122
|
+
*/
|
|
24
123
|
|
|
25
124
|
/**
|
|
26
125
|
* Generated bundle index. Do not edit.
|
|
27
126
|
*/
|
|
28
127
|
|
|
29
|
-
export {
|
|
128
|
+
export { GenericHttpRepository, HttpQueryService, HttpRepository, ReadOnlyHttpRepository };
|
|
30
129
|
//# sourceMappingURL=eac-arch-infrastructure-persistence.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"eac-arch-infrastructure-persistence.mjs","sources":["../../../projects/eac-arch-infrastructure-persistence/src/lib/eac-arch-infrastructure-persistence.ts","../../../projects/eac-arch-infrastructure-persistence/src/public-api.ts","../../../projects/eac-arch-infrastructure-persistence/src/eac-arch-infrastructure-persistence.ts"],"sourcesContent":["import { Component } from '@angular/core';\r\n\r\n@Component({\r\n selector: 'eac-arch-eac-arch-infrastructure-persistence',\r\n imports: [],\r\n template: `\r\n <p>\r\n eac-arch-infrastructure-persistence works!\r\n </p>\r\n `,\r\n styles: ``,\r\n})\r\nexport class EacArchInfrastructurePersistence {\r\n\r\n}\r\n","/*\r\n * Public API Surface of eac-arch-infrastructure-persistence\r\n */\r\n\r\nexport * from './lib/eac-arch-infrastructure-persistence';\r\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":";;;MAYa,gCAAgC,CAAA;uGAAhC,gCAAgC,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA;AAAhC,IAAA,OAAA,IAAA,GAAA,EAAA,CAAA,oBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,QAAA,EAAA,IAAA,EAAA,gCAAgC,EAAA,YAAA,EAAA,IAAA,EAAA,QAAA,EAAA,8CAAA,EAAA,QAAA,EAAA,EAAA,EAAA,QAAA,EAPjC,CAAA;;;;AAIT,EAAA,CAAA,EAAA,QAAA,EAAA,IAAA,EAAA,MAAA,EAAA,CAAA,EAAA,CAAA,EAAA,CAAA;;2FAGU,gCAAgC,EAAA,UAAA,EAAA,CAAA;kBAV5C,SAAS;+BACE,8CAA8C,EAAA,OAAA,EAC/C,EAAE,EAAA,QAAA,EACD,CAAA;;;;AAIT,EAAA,CAAA,EAAA;;;ACTH;;AAEG;;ACFH;;AAEG;;;;"}
|
|
1
|
+
{"version":3,"file":"eac-arch-infrastructure-persistence.mjs","sources":["../../../projects/eac-arch-infrastructure-persistence/src/lib/repositories/read-only-http-repository.ts","../../../projects/eac-arch-infrastructure-persistence/src/lib/repositories/generic-http-repository.ts","../../../projects/eac-arch-infrastructure-persistence/src/lib/repositories/http-repository.ts","../../../projects/eac-arch-infrastructure-persistence/src/lib/query-services/http-query-service.ts","../../../projects/eac-arch-infrastructure-persistence/src/public-api.ts","../../../projects/eac-arch-infrastructure-persistence/src/eac-arch-infrastructure-persistence.ts"],"sourcesContent":["import { PagedList as InfraPagedList } from '@eac-arch/infrastructure-http';\nimport { createPagedList, type PagedList } from '@eac-arch/shared-kernel';\nimport type { IReadOnlyHttpRepository } from '@eac-arch/shared-kernel';\n\n// Client-side mirror of the server's ReadOnlyRepository<TEntity, TDbContext>.\n// Provides read operations backed by an HTTP agent instead of EF Core.\n//\n// Subclasses provide:\n// - mapToEntity() — maps a raw API model to the domain entity (used in getAll).\n// - rehydrate() — virtual override for getById when child collections must be loaded.\n// - doGetAll() — delegate to agent.getAll*() method.\n// - doGetById() — delegate to agent.getById*() method.\n// - doExists() — delegate to agent.exists*() method.\nexport abstract class ReadOnlyHttpRepository<\n TEntity,\n TDto,\n TQueryOptions = Record<string, unknown>,\n> implements IReadOnlyHttpRepository<TEntity, TQueryOptions> {\n\n // -- Mapping --\n\n protected abstract mapToEntity(dto: TDto): TEntity;\n\n // Override when getById must reconstruct a fully-loaded aggregate (e.g. with child collections).\n // Default: delegates to mapToEntity.\n protected rehydrate(id: string, dto: TDto): Promise<TEntity> {\n return Promise.resolve(this.mapToEntity(dto));\n }\n\n // -- Agent delegates --\n\n protected abstract doGetAll(pageNumber: number, pageSize: number, options?: TQueryOptions): Promise<InfraPagedList<TDto>>;\n protected abstract doGetById(id: string): Promise<TDto | null>;\n protected abstract doExists(id: string): Promise<boolean>;\n\n // -- ReadOnlyHttpRepository implementation --\n\n async getAll(pageNumber: number, pageSize: number, options?: TQueryOptions): Promise<PagedList<TEntity>> {\n const page = await this.doGetAll(pageNumber, pageSize, options);\n return createPagedList<TEntity>(\n [...page.items].map(m => this.mapToEntity(m)),\n page.totalCount,\n page.currentPage,\n page.pageSize,\n );\n }\n\n async getById(id: string): Promise<TEntity | null> {\n const dto = await this.doGetById(id);\n if (!dto) return null;\n return this.rehydrate(id, dto);\n }\n\n exists(id: string): Promise<boolean> {\n return this.doExists(id);\n }\n}\n","import type { IHttpRepository } from '@eac-arch/shared-kernel';\nimport { ReadOnlyHttpRepository } from './read-only-http-repository';\n\n// Client-side mirror of the server's GenericRepository<TEntity, TDbContext>.\n// Extends ReadOnlyHttpRepository with full CRUD operations.\n//\n// Subclasses must additionally implement:\n// - doCreate() — delegate to agent.create*() method.\n// - doUpsert() — delegate to agent.upsert*() method.\n// - doUpdatePartial() — delegate to agent.updatePartial*() method.\n// - doDelete() — delegate to agent.delete*() method.\nexport abstract class GenericHttpRepository<\n TEntity,\n TDto,\n TCreateData,\n TUpsertData,\n TQueryOptions = Record<string, unknown>,\n TChanges = unknown,\n> extends ReadOnlyHttpRepository<TEntity, TDto, TQueryOptions>\n implements IHttpRepository<TEntity, TCreateData, TUpsertData, TQueryOptions, TChanges> {\n\n // -- Mapping --\n\n protected abstract extractId(dto: TDto): string;\n\n // -- Agent delegates --\n\n protected abstract doCreate(data: TCreateData): Promise<TDto>;\n protected abstract doUpsert(id: string, data: TUpsertData): Promise<TDto | null>;\n protected abstract doUpdatePartial(id: string, changes: TChanges): Promise<void>;\n protected abstract doDelete(id: string): Promise<void>;\n\n // -- HttpRepository implementation --\n\n async create(data: TCreateData): Promise<TEntity> {\n const dto = await this.doCreate(data);\n return this.rehydrate(this.extractId(dto), dto);\n }\n\n async upsert(id: string, data: TUpsertData): Promise<TEntity | null> {\n const dto = await this.doUpsert(id, data);\n return dto ? this.rehydrate(id, dto) : null;\n }\n\n updatePartial(id: string, changes: TChanges): Promise<void> {\n return this.doUpdatePartial(id, changes);\n }\n\n delete(id: string): Promise<void> {\n return this.doDelete(id);\n }\n}\n","import { GenericHttpRepository } from './generic-http-repository';\n\n// Client-side mirror of the server's Repository<TEntity, TDbContext>.\n// Thin alias over GenericHttpRepository — entry point for most use cases.\nexport abstract class HttpRepository<\n TEntity,\n TDto,\n TCreateData,\n TUpsertData,\n TQueryOptions = Record<string, unknown>,\n TChanges = unknown,\n> extends GenericHttpRepository<TEntity, TDto, TCreateData, TUpsertData, TQueryOptions, TChanges> {}\n","import {\n type PagedList,\n type IQueryService,\n type Specification,\n type SortField,\n QuerySpecification,\n createPagedList,\n formatSortFields,\n} from '@eac-arch/shared-kernel';\n\n// Minimum shape required from any query options object.\n// All concrete query option interfaces (AuthorQueryOptions, AwardQueryOptions, etc.)\n// must declare at least sort and fields to be compatible with this base.\nexport interface BaseQueryOptions {\n sort?: string;\n fields?: string;\n}\n\n// Client-side mirror of the server's QueryService<T, TDbContext>.\n// Provides the full QueryService<TModel> contract plus shared helpers:\n// - buildOptions() — builds TQueryOptions from Specification + SortField[].\n// - toPagedList() — converts an agent PagedList response to the shared format.\n//\n// Root resource query services (e.g. AuthorQueryServiceImpl) override doGetAll/doGetById\n// and gain getAll/getById/getPagedList for free.\n//\n// Sub-resource query services (e.g. AwardQueryServiceImpl) extend this for buildOptions\n// and toPagedList only; their parent-scoped methods use these helpers directly.\nexport abstract class HttpQueryService<\n TModel,\n TQueryOptions extends BaseQueryOptions = BaseQueryOptions,\n> implements IQueryService<TModel> {\n\n // Override in root resource query services.\n // Default: throws because sub-resource query services require a parent ID.\n protected doGetAll(\n _pageNumber: number,\n _pageSize: number,\n _options?: TQueryOptions,\n ): Promise<PagedList<TModel>> {\n throw new Error('getAll is not supported by this query service');\n }\n\n // Override in root resource query services.\n protected doGetById(_id: string): Promise<TModel | null> {\n throw new Error('getById is not supported by this query service');\n }\n\n // -- QueryService<TModel> implementation --\n\n async getAll(): Promise<TModel[]> {\n const result = await this.doGetAll(1, Number.MAX_SAFE_INTEGER);\n return [...result.items];\n }\n\n getById(id: string): Promise<TModel | null> {\n return this.doGetById(id);\n }\n\n async getPagedList(\n pageNumber: number,\n pageSize: number,\n spec?: Specification<TModel>,\n sortFields?: SortField[],\n fields?: string[],\n ): Promise<PagedList<TModel>> {\n const options = this.buildOptions(spec, sortFields, fields);\n const result = await this.doGetAll(pageNumber, pageSize, options);\n return this.toPagedList(result);\n }\n\n // -- Shared helpers --\n\n // Converts a Specification + SortField[] into the agent-compatible TQueryOptions shape.\n // All subclasses share this exact logic — previously duplicated in every impl.\n protected buildOptions(\n spec?: Specification<TModel>,\n sortFields?: SortField[],\n fields?: string[],\n ): TQueryOptions {\n const options = {} as TQueryOptions;\n if (spec instanceof QuerySpecification) Object.assign(options, spec.toQueryParams());\n if (sortFields?.length) options.sort = formatSortFields(sortFields);\n if (fields?.length) options.fields = fields.join(',');\n return options;\n }\n\n // Converts an agent PagedList<TModel> into the shared PagedList format from @eac-arch/shared-kernel.\n protected toPagedList(source: {\n items: readonly TModel[];\n totalCount: number;\n currentPage: number;\n pageSize: number;\n }): PagedList<TModel> {\n return createPagedList([...source.items], source.totalCount, source.currentPage, source.pageSize);\n }\n}\n","/*\n * Public API Surface of eac-arch-infrastructure-persistence\n */\n\n/*\n * Public API Surface of @eac-arch/infrastructure-persistence\n */\n\nexport { ReadOnlyHttpRepository } from './lib/repositories/read-only-http-repository';\nexport { GenericHttpRepository } from './lib/repositories/generic-http-repository';\nexport { HttpRepository } from './lib/repositories/http-repository';\nexport { HttpQueryService, type BaseQueryOptions } from './lib/query-services/http-query-service';\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@eac-arch/infrastructure-persistence",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.6",
|
|
4
4
|
"peerDependencies": {
|
|
5
5
|
"@angular/common": "^21.1.0",
|
|
6
6
|
"@angular/core": "^21.1.0"
|
|
7
7
|
},
|
|
8
8
|
"dependencies": {
|
|
9
|
-
"tslib": "^2.3.0"
|
|
9
|
+
"tslib": "^2.3.0",
|
|
10
|
+
"@eac-arch/shared-kernel": "1.0.6",
|
|
11
|
+
"@eac-arch/infrastructure-http": "1.0.6"
|
|
10
12
|
},
|
|
11
13
|
"sideEffects": false,
|
|
12
14
|
"module": "fesm2022/eac-arch-infrastructure-persistence.mjs",
|
|
@@ -20,4 +22,4 @@
|
|
|
20
22
|
"default": "./fesm2022/eac-arch-infrastructure-persistence.mjs"
|
|
21
23
|
}
|
|
22
24
|
}
|
|
23
|
-
}
|
|
25
|
+
}
|
|
@@ -1,8 +1,50 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { PagedList } from '@eac-arch/infrastructure-http';
|
|
2
|
+
import { IReadOnlyHttpRepository, PagedList as PagedList$1, IHttpRepository, IQueryService, Specification, SortField } from '@eac-arch/shared-kernel';
|
|
2
3
|
|
|
3
|
-
declare class
|
|
4
|
-
|
|
5
|
-
|
|
4
|
+
declare abstract class ReadOnlyHttpRepository<TEntity, TDto, TQueryOptions = Record<string, unknown>> implements IReadOnlyHttpRepository<TEntity, TQueryOptions> {
|
|
5
|
+
protected abstract mapToEntity(dto: TDto): TEntity;
|
|
6
|
+
protected rehydrate(id: string, dto: TDto): Promise<TEntity>;
|
|
7
|
+
protected abstract doGetAll(pageNumber: number, pageSize: number, options?: TQueryOptions): Promise<PagedList<TDto>>;
|
|
8
|
+
protected abstract doGetById(id: string): Promise<TDto | null>;
|
|
9
|
+
protected abstract doExists(id: string): Promise<boolean>;
|
|
10
|
+
getAll(pageNumber: number, pageSize: number, options?: TQueryOptions): Promise<PagedList$1<TEntity>>;
|
|
11
|
+
getById(id: string): Promise<TEntity | null>;
|
|
12
|
+
exists(id: string): Promise<boolean>;
|
|
6
13
|
}
|
|
7
14
|
|
|
8
|
-
|
|
15
|
+
declare abstract class GenericHttpRepository<TEntity, TDto, TCreateData, TUpsertData, TQueryOptions = Record<string, unknown>, TChanges = unknown> extends ReadOnlyHttpRepository<TEntity, TDto, TQueryOptions> implements IHttpRepository<TEntity, TCreateData, TUpsertData, TQueryOptions, TChanges> {
|
|
16
|
+
protected abstract extractId(dto: TDto): string;
|
|
17
|
+
protected abstract doCreate(data: TCreateData): Promise<TDto>;
|
|
18
|
+
protected abstract doUpsert(id: string, data: TUpsertData): Promise<TDto | null>;
|
|
19
|
+
protected abstract doUpdatePartial(id: string, changes: TChanges): Promise<void>;
|
|
20
|
+
protected abstract doDelete(id: string): Promise<void>;
|
|
21
|
+
create(data: TCreateData): Promise<TEntity>;
|
|
22
|
+
upsert(id: string, data: TUpsertData): Promise<TEntity | null>;
|
|
23
|
+
updatePartial(id: string, changes: TChanges): Promise<void>;
|
|
24
|
+
delete(id: string): Promise<void>;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
declare abstract class HttpRepository<TEntity, TDto, TCreateData, TUpsertData, TQueryOptions = Record<string, unknown>, TChanges = unknown> extends GenericHttpRepository<TEntity, TDto, TCreateData, TUpsertData, TQueryOptions, TChanges> {
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
interface BaseQueryOptions {
|
|
31
|
+
sort?: string;
|
|
32
|
+
fields?: string;
|
|
33
|
+
}
|
|
34
|
+
declare abstract class HttpQueryService<TModel, TQueryOptions extends BaseQueryOptions = BaseQueryOptions> implements IQueryService<TModel> {
|
|
35
|
+
protected doGetAll(_pageNumber: number, _pageSize: number, _options?: TQueryOptions): Promise<PagedList$1<TModel>>;
|
|
36
|
+
protected doGetById(_id: string): Promise<TModel | null>;
|
|
37
|
+
getAll(): Promise<TModel[]>;
|
|
38
|
+
getById(id: string): Promise<TModel | null>;
|
|
39
|
+
getPagedList(pageNumber: number, pageSize: number, spec?: Specification<TModel>, sortFields?: SortField[], fields?: string[]): Promise<PagedList$1<TModel>>;
|
|
40
|
+
protected buildOptions(spec?: Specification<TModel>, sortFields?: SortField[], fields?: string[]): TQueryOptions;
|
|
41
|
+
protected toPagedList(source: {
|
|
42
|
+
items: readonly TModel[];
|
|
43
|
+
totalCount: number;
|
|
44
|
+
currentPage: number;
|
|
45
|
+
pageSize: number;
|
|
46
|
+
}): PagedList$1<TModel>;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export { GenericHttpRepository, HttpQueryService, HttpRepository, ReadOnlyHttpRepository };
|
|
50
|
+
export type { BaseQueryOptions };
|