@angular-cool/repository 21.0.0 → 21.0.2

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,14 +1,21 @@
1
1
  [npm-url]: https://npmjs.org/package/@angular-cool/repository
2
+
2
3
  [npm-image]: https://img.shields.io/npm/v/@angular-cool/repository.svg
4
+
3
5
  [downloads-image]: https://img.shields.io/npm/dm/@angular-cool/repository.svg
6
+
4
7
  [total-downloads-image]: https://img.shields.io/npm/dt/@angular-cool/repository.svg
5
8
 
6
9
  # @angular-cool/repository [![NPM version][npm-image]][npm-url] [![Downloads][downloads-image]][npm-url] [![Total Downloads][total-downloads-image]][npm-url]
10
+
7
11
  Cool stateful signal repository for angular
8
12
 
9
13
  An easy-to-use signal repository that helps you manage your data loading and caching in your angular applications.
10
14
 
15
+ Share data across multiple components and services with automatic reloading and state management.
16
+
11
17
  ## Install
18
+
12
19
  > npm install --save @angular-cool/repository
13
20
 
14
21
  ## Usage
@@ -18,14 +25,14 @@ An easy-to-use signal repository that helps you manage your data loading and cac
18
25
  ```typescript
19
26
  import { resourceRepository } from '@angular-cool/repository';
20
27
  import { inject, Injectable } from '@angular/core';
21
- import { ItemId } from './my-item.model';
28
+ import { ItemId, ItemDTO } from './my-item.model';
22
29
 
23
30
  @Injectable()
24
31
  export class MyService {
25
32
  private _http = inject(HttpClient);
26
33
 
27
- private items = resourceRepository<ItemId>({
28
- loader: ({ params }) => this._http.get(`https://myapi.com/items/${params}`).toPromise(),
34
+ private items = resourceRepository<ItemId, ItemDTO>({
35
+ loader: ({ params }) => this._http.get(`https://myapi.com/items/${ params }`).toPromise(),
29
36
  });
30
37
  }
31
38
  ```
@@ -35,24 +42,26 @@ export class MyService {
35
42
  ```typescript
36
43
  import { signal } from '@angular/common';
37
44
  import { MyService } from './my-service.service';
45
+ import { ItemId, ItemDTO } from './my-item.model';
38
46
 
39
47
  @Component(/*...*/)
40
48
  export class MyComponent {
41
49
  private _myService = inject(MyService);
42
50
 
43
- private idParam = signal('1');
51
+ private idParam = signal<ItemId>('1' as ItemId);
44
52
 
45
- protected myItem = this._myService.items.get(this.idParam);
53
+ protected myItem: Resource<ItemDTO | undefined> = this._myService.items.get(this.idParam);
46
54
 
47
55
  protected updateItem() {
48
56
  // Update item on the server here
49
57
 
50
- this._myService.items.reload(this.idParam());
58
+ this._myService.items.reload(this.idParam()); // This reloads the item from the server and updates the signal for all subscribers
51
59
  }
52
60
  }
53
61
  ```
54
62
 
55
63
  ## License
64
+
56
65
  > The MIT License (MIT)
57
66
 
58
67
  > Copyright (c) 2025 Hacklone
@@ -43,10 +43,11 @@ class ResourceRepository {
43
43
  return rxResource({
44
44
  params: () => key(),
45
45
  stream: ({ params }) => {
46
- let cache = this._cacheStore.get(params);
46
+ const cacheKey = this._createCacheKey(params);
47
+ let cache = this._cacheStore.get(cacheKey);
47
48
  if (!cache) {
48
49
  cache = new ResourceCache(((p) => () => this.options.loader(p))(params), this.options.maxAge ?? DEFAULT_MAX_AGE);
49
- this._cacheStore.set(params, cache);
50
+ this._cacheStore.set(cacheKey, cache);
50
51
  }
51
52
  // Do not wait for it to load
52
53
  cache.keepDataFreshAsync();
@@ -62,13 +63,17 @@ class ResourceRepository {
62
63
  * @throws {Error} If no cache is found for the provided key or if data loading fails.
63
64
  */
64
65
  async reload(key) {
65
- const cache = this._cacheStore.get(key);
66
+ const cacheKey = this._createCacheKey(key);
67
+ const cache = this._cacheStore.get(cacheKey);
66
68
  if (!cache) {
67
69
  throw new Error(`No cache found for the given key: ${key}`);
68
70
  }
69
71
  cache.invalidate();
70
72
  await cache.keepDataFreshAsync();
71
73
  }
74
+ _createCacheKey(params) {
75
+ return (this.options.cacheKeyGenerator ?? JSON.stringify)(params);
76
+ }
72
77
  }
73
78
  /**
74
79
  * Creates a new instance of a ResourceRepository with the specified options.
@@ -1 +1 @@
1
- {"version":3,"file":"angular-cool-repository.mjs","sources":["../../../projects/repository/src/lib/resource-cache.ts","../../../projects/repository/src/lib/resource-repository.ts","../../../projects/repository/src/angular-cool-repository.ts"],"sourcesContent":["import { ReplaySubject } from 'rxjs';\n\nexport class ResourceCache<TItem> {\n private _subject = new ReplaySubject<TItem | undefined>();\n private _validUntil: number | null = null;\n\n public get isInvalid(): boolean {\n return this._validUntil === null || Date.now() > this._validUntil;\n }\n\n constructor(\n private loader: () => Promise<TItem | undefined>,\n private maxAge: number,\n ) {\n }\n\n public getObservable() {\n return this._subject.asObservable();\n }\n\n public async keepDataFreshAsync() {\n if (!this.isInvalid) {\n return;\n }\n\n const data = await this.loader();\n\n this._validUntil = Date.now() + this.maxAge;\n this._subject.next(data);\n }\n\n public invalidate() {\n this._validUntil = null;\n }\n}\n","import { Resource, Signal } from '@angular/core';\nimport { rxResource } from '@angular/core/rxjs-interop';\nimport { ResourceCache } from './resource-cache';\n\nconst DEFAULT_MAX_AGE = 5 * 60 * 1000;\n\nclass ResourceRepository<TParams, TItem> {\n private _cacheStore = new Map<TParams, ResourceCache<TItem>>();\n\n constructor(private options: ResourceRepositoryOptions<TParams, TItem>) {\n }\n\n /**\n * Retrieves a resource cache\n *\n * @param {Signal<TParams>} key - A signal function used to resolve the parameters for retrieving or initializing the resource.\n * @return {Resource<TItem | undefined>} A read-only resource containing the item associated with the provided key, already cached.\n */\n public get(key: Signal<TParams>): Resource<TItem | undefined> {\n return rxResource<TItem | undefined, TParams>({\n params: () => key(),\n stream: ({ params }) => {\n let cache = this._cacheStore.get(params);\n\n if (!cache) {\n cache = new ResourceCache(\n ((p) => () => this.options.loader(p))(params),\n this.options.maxAge ?? DEFAULT_MAX_AGE,\n );\n\n this._cacheStore.set(params, cache);\n }\n\n // Do not wait for it to load\n cache.keepDataFreshAsync();\n\n return cache.getObservable();\n }\n }).asReadonly();\n }\n\n /**\n * Reloads the cache associated with the given key, ensuring it is updated with fresh data.\n *\n * @param {TParams} key - The key used to identify the specific cache entry to reload.\n * @return {Promise<void>} A promise that resolves when the cache has been refreshed.\n * @throws {Error} If no cache is found for the provided key or if data loading fails.\n */\n public async reload(key: TParams): Promise<void> {\n const cache = this._cacheStore.get(key);\n\n if (!cache) {\n throw new Error(`No cache found for the given key: ${key}`);\n }\n\n cache.invalidate();\n\n await cache.keepDataFreshAsync();\n }\n}\n\n/**\n * Options to configure the behavior of the ResourceRepository.\n *\n * @template TParams The type of the parameters used by the loader function.\n * @template TItem The type of the items returned by the loader function.\n *\n * @property {function(TParams): Promise<TItem>} loader\n * A function that loads a resource based on provided parameters and returns a promise that resolves to the resource.\n *\n * @property {number} [maxAge]\n * The optional maximum age (in milliseconds) for caching the loaded resource. Default: 5 minutes\n */\nexport interface ResourceRepositoryOptions<TParams, TItem> {\n loader: (params: TParams) => Promise<TItem>;\n\n maxAge?: number;\n}\n\n/**\n * Creates a new instance of a ResourceRepository with the specified options.\n *\n * @param {ResourceRepositoryOptions<TParams, TItem>} options - The configuration options for the resource repository.\n * @return {ResourceRepository<TParams, TItem>} A new instance of ResourceRepository configured with the given options.\n */\nexport function resourceRepository<TParams, TItem>(options: ResourceRepositoryOptions<TParams, TItem>): ResourceRepository<TParams, TItem> {\n return new ResourceRepository<TParams, TItem>(options);\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":";;;MAEa,aAAa,CAAA;AAIxB,IAAA,IAAW,SAAS,GAAA;AAClB,QAAA,OAAO,IAAI,CAAC,WAAW,KAAK,IAAI,IAAI,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,WAAW;IACnE;IAEA,WAAA,CACU,MAAwC,EACxC,MAAc,EAAA;QADd,IAAA,CAAA,MAAM,GAAN,MAAM;QACN,IAAA,CAAA,MAAM,GAAN,MAAM;AATR,QAAA,IAAA,CAAA,QAAQ,GAAG,IAAI,aAAa,EAAqB;QACjD,IAAA,CAAA,WAAW,GAAkB,IAAI;IAUzC;IAEO,aAAa,GAAA;AAClB,QAAA,OAAO,IAAI,CAAC,QAAQ,CAAC,YAAY,EAAE;IACrC;AAEO,IAAA,MAAM,kBAAkB,GAAA;AAC7B,QAAA,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE;YACnB;QACF;AAEA,QAAA,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,MAAM,EAAE;QAEhC,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,MAAM;AAC3C,QAAA,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC;IAC1B;IAEO,UAAU,GAAA;AACf,QAAA,IAAI,CAAC,WAAW,GAAG,IAAI;IACzB;AACD;;AC9BD,MAAM,eAAe,GAAG,CAAC,GAAG,EAAE,GAAG,IAAI;AAErC,MAAM,kBAAkB,CAAA;AAGtB,IAAA,WAAA,CAAoB,OAAkD,EAAA;QAAlD,IAAA,CAAA,OAAO,GAAP,OAAO;AAFnB,QAAA,IAAA,CAAA,WAAW,GAAG,IAAI,GAAG,EAAiC;IAG9D;AAEA;;;;;AAKG;AACI,IAAA,GAAG,CAAC,GAAoB,EAAA;AAC7B,QAAA,OAAO,UAAU,CAA6B;AAC5C,YAAA,MAAM,EAAE,MAAM,GAAG,EAAE;AACnB,YAAA,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,KAAI;gBACrB,IAAI,KAAK,GAAG,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,MAAM,CAAC;gBAExC,IAAI,CAAC,KAAK,EAAE;AACV,oBAAA,KAAK,GAAG,IAAI,aAAa,CACvB,CAAC,CAAC,CAAC,KAAK,MAAM,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,MAAM,CAAC,EAC7C,IAAI,CAAC,OAAO,CAAC,MAAM,IAAI,eAAe,CACvC;oBAED,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,MAAM,EAAE,KAAK,CAAC;gBACrC;;gBAGA,KAAK,CAAC,kBAAkB,EAAE;AAE1B,gBAAA,OAAO,KAAK,CAAC,aAAa,EAAE;YAC9B;SACD,CAAC,CAAC,UAAU,EAAE;IACjB;AAEA;;;;;;AAMG;IACI,MAAM,MAAM,CAAC,GAAY,EAAA;QAC9B,MAAM,KAAK,GAAG,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,GAAG,CAAC;QAEvC,IAAI,CAAC,KAAK,EAAE;AACV,YAAA,MAAM,IAAI,KAAK,CAAC,qCAAqC,GAAG,CAAA,CAAE,CAAC;QAC7D;QAEA,KAAK,CAAC,UAAU,EAAE;AAElB,QAAA,MAAM,KAAK,CAAC,kBAAkB,EAAE;IAClC;AACD;AAoBD;;;;;AAKG;AACG,SAAU,kBAAkB,CAAiB,OAAkD,EAAA;AACnG,IAAA,OAAO,IAAI,kBAAkB,CAAiB,OAAO,CAAC;AACxD;;ACvFA;;AAEG;;;;"}
1
+ {"version":3,"file":"angular-cool-repository.mjs","sources":["../../../projects/repository/src/lib/resource-cache.ts","../../../projects/repository/src/lib/resource-repository.ts","../../../projects/repository/src/angular-cool-repository.ts"],"sourcesContent":["import { ReplaySubject } from 'rxjs';\n\nexport class ResourceCache<TItem> {\n private _subject = new ReplaySubject<TItem | undefined>();\n private _validUntil: number | null = null;\n\n public get isInvalid(): boolean {\n return this._validUntil === null || Date.now() > this._validUntil;\n }\n\n constructor(\n private loader: () => Promise<TItem | undefined>,\n private maxAge: number,\n ) {\n }\n\n public getObservable() {\n return this._subject.asObservable();\n }\n\n public async keepDataFreshAsync() {\n if (!this.isInvalid) {\n return;\n }\n\n const data = await this.loader();\n\n this._validUntil = Date.now() + this.maxAge;\n this._subject.next(data);\n }\n\n public invalidate() {\n this._validUntil = null;\n }\n}\n","import { Resource, Signal } from '@angular/core';\nimport { rxResource } from '@angular/core/rxjs-interop';\nimport { ResourceCache } from './resource-cache';\n\nconst DEFAULT_MAX_AGE = 5 * 60 * 1000;\n\ntype CacheKey = string;\n\nclass ResourceRepository<TParams, TItem> {\n private _cacheStore = new Map<CacheKey, ResourceCache<TItem>>();\n\n constructor(private options: ResourceRepositoryOptions<TParams, TItem>) {\n }\n\n /**\n * Retrieves a resource cache\n *\n * @param {Signal<TParams>} key - A signal function used to resolve the parameters for retrieving or initializing the resource.\n * @return {Resource<TItem | undefined>} A read-only resource containing the item associated with the provided key, already cached.\n */\n public get(key: Signal<TParams>): Resource<TItem | undefined> {\n return rxResource<TItem | undefined, TParams>({\n params: () => key(),\n stream: ({ params }) => {\n const cacheKey = this._createCacheKey(params);\n\n let cache = this._cacheStore.get(cacheKey);\n\n if (!cache) {\n cache = new ResourceCache(\n ((p) => () => this.options.loader(p))(params),\n this.options.maxAge ?? DEFAULT_MAX_AGE,\n );\n\n this._cacheStore.set(cacheKey, cache);\n }\n\n // Do not wait for it to load\n cache.keepDataFreshAsync();\n\n return cache.getObservable();\n }\n }).asReadonly();\n }\n\n /**\n * Reloads the cache associated with the given key, ensuring it is updated with fresh data.\n *\n * @param {TParams} key - The key used to identify the specific cache entry to reload.\n * @return {Promise<void>} A promise that resolves when the cache has been refreshed.\n * @throws {Error} If no cache is found for the provided key or if data loading fails.\n */\n public async reload(key: TParams): Promise<void> {\n const cacheKey = this._createCacheKey(key);\n\n const cache = this._cacheStore.get(cacheKey);\n\n if (!cache) {\n throw new Error(`No cache found for the given key: ${key}`);\n }\n\n cache.invalidate();\n\n await cache.keepDataFreshAsync();\n }\n\n private _createCacheKey(params: TParams): CacheKey {\n return (this.options.cacheKeyGenerator ?? JSON.stringify)(params) as CacheKey;\n }\n}\n\n/**\n * Configuration options for a ResourceRepository.\n * This interface provides options for customizing the behavior\n * of resource loading and caching mechanisms.\n *\n * @template TParams The type of the parameters used to load a resource.\n * @template TItem The type of the items being loaded or cached.\n *\n * @property loader A function responsible for loading a resource. It receives\n * parameters of type `TParams` and returns a Promise resolving to an item of type `TItem`.\n *\n * @property [maxAge] Optional. Specifies the maximum duration (in milliseconds)\n * for which a cached resource remains valid. Default: 5 minutes\n *\n * @property [cacheKeyGenerator] Optional. A function used to generate a unique\n * cache key based on the input parameters of type `TParams`. Default: JSON.stringify()\n */\nexport interface ResourceRepositoryOptions<TParams, TItem> {\n loader: (params: TParams) => Promise<TItem>;\n\n maxAge?: number;\n\n cacheKeyGenerator?: (params: TParams) => string;\n}\n\n/**\n * Creates a new instance of a ResourceRepository with the specified options.\n *\n * @param {ResourceRepositoryOptions<TParams, TItem>} options - The configuration options for the resource repository.\n * @return {ResourceRepository<TParams, TItem>} A new instance of ResourceRepository configured with the given options.\n */\nexport function resourceRepository<TParams, TItem>(options: ResourceRepositoryOptions<TParams, TItem>): ResourceRepository<TParams, TItem> {\n return new ResourceRepository<TParams, TItem>(options);\n}\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,7 +1,7 @@
1
1
  {
2
2
  "name": "@angular-cool/repository",
3
3
  "description": "Cool stateful signal repository for angular",
4
- "version": "21.0.0",
4
+ "version": "21.0.2",
5
5
  "peerDependencies": {
6
6
  "@angular/common": ">=21.0.0",
7
7
  "@angular/core": ">=21.0.0"
@@ -15,6 +15,7 @@
15
15
  },
16
16
  "keywords": [
17
17
  "angular",
18
+ "signal",
18
19
  "repository",
19
20
  "cache",
20
21
  "pattern",
@@ -19,22 +19,29 @@ declare class ResourceRepository<TParams, TItem> {
19
19
  * @throws {Error} If no cache is found for the provided key or if data loading fails.
20
20
  */
21
21
  reload(key: TParams): Promise<void>;
22
+ private _createCacheKey;
22
23
  }
23
24
  /**
24
- * Options to configure the behavior of the ResourceRepository.
25
+ * Configuration options for a ResourceRepository.
26
+ * This interface provides options for customizing the behavior
27
+ * of resource loading and caching mechanisms.
25
28
  *
26
- * @template TParams The type of the parameters used by the loader function.
27
- * @template TItem The type of the items returned by the loader function.
29
+ * @template TParams The type of the parameters used to load a resource.
30
+ * @template TItem The type of the items being loaded or cached.
28
31
  *
29
- * @property {function(TParams): Promise<TItem>} loader
30
- * A function that loads a resource based on provided parameters and returns a promise that resolves to the resource.
32
+ * @property loader A function responsible for loading a resource. It receives
33
+ * parameters of type `TParams` and returns a Promise resolving to an item of type `TItem`.
31
34
  *
32
- * @property {number} [maxAge]
33
- * The optional maximum age (in milliseconds) for caching the loaded resource. Default: 5 minutes
35
+ * @property [maxAge] Optional. Specifies the maximum duration (in milliseconds)
36
+ * for which a cached resource remains valid. Default: 5 minutes
37
+ *
38
+ * @property [cacheKeyGenerator] Optional. A function used to generate a unique
39
+ * cache key based on the input parameters of type `TParams`. Default: JSON.stringify()
34
40
  */
35
41
  interface ResourceRepositoryOptions<TParams, TItem> {
36
42
  loader: (params: TParams) => Promise<TItem>;
37
43
  maxAge?: number;
44
+ cacheKeyGenerator?: (params: TParams) => string;
38
45
  }
39
46
  /**
40
47
  * Creates a new instance of a ResourceRepository with the specified options.