@reactive-cache/map 0.3.0 → 1.0.0

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/.gitattributes CHANGED
@@ -1,2 +1,2 @@
1
- # Auto detect text files and perform LF normalization
2
- * text=auto
1
+ # Auto detect text files and perform LF normalization
2
+ * text=auto
package/README.md CHANGED
@@ -1,28 +1,334 @@
1
- # Reactive Cache
1
+ # @reactive-cache/map
2
2
 
3
- <a href="https://www.npmjs.com/package/@reactive-cache/core?activeTab=readme">
3
+ <a href="https://www.npmjs.com/package/@reactive-cache/map">
4
4
  <img src="https://img.shields.io/badge/npm-CB3837?style=for-the-badge&logo=npm&logoColor=white" />
5
5
  </a>
6
6
 
7
+ A TypeScript library providing reactive, cached map data structures for Angular and RxJS-based projects. Part of the `@reactive-cache` ecosystem.
8
+
7
9
  ## Installation
8
10
 
9
11
  ```bash
10
- $ npm install @reactive-cache/map
12
+ npm install @reactive-cache/map
13
+ ```
14
+
15
+ ## Features
16
+
17
+ - **Reactive Caching**: Automatically caches values as RxJS Observables
18
+ - **Lazy Loading**: Values are only fetched when first requested
19
+ - **Multiple Map Types**: Choose between regular maps and weak maps
20
+ - **Mutable & Immutable Options**: Select constant (immutable) or mutable cache behavior
21
+ - **Flexible Input**: Accepts Observables, Promises, or raw values as factory functions
22
+ - **TypeScript Support**: Full type safety with generics
23
+ - **Memory Efficient**: WeakMap variants allow automatic garbage collection
24
+
25
+ ## Map Types
26
+
27
+ | Class | Key Type | Mutable | Use Case |
28
+ |-------|----------|---------|----------|
29
+ | `ReactiveMap` | `string \| number \| symbol` | Yes | General-purpose cached data with primitive keys |
30
+ | `WeakReactiveMap` | `object` | Yes | Object-keyed data with automatic memory cleanup |
31
+ | `ConstantReactiveMap` | `string \| number \| symbol` | No | Read-only cached data with primitive keys |
32
+ | `ConstantWeakReactiveMap` | `object` | No | Read-only object-keyed data with memory cleanup |
33
+
34
+ ## API Reference
35
+
36
+ ### ReactiveMap<K, V>
37
+
38
+ A reactive map with primitive keys that supports mutable operations.
39
+
40
+ ```typescript
41
+ import { ReactiveMap } from '@reactive-cache/map';
42
+
43
+ const map = new ReactiveMap<string, User>(
44
+ 'usersMap', // name for debugging
45
+ (key) => fetchUser(key) // factory function
46
+ );
47
+ ```
48
+
49
+ #### Constructor
50
+
51
+ ```typescript
52
+ new ReactiveMap<K, V>(
53
+ name: string,
54
+ machine: (key: K) => Observable<V> | Promise<V> | V,
55
+ params?: { constant?: boolean }
56
+ )
57
+ ```
58
+
59
+ #### Methods
60
+
61
+ | Method | Return Type | Description |
62
+ |--------|-------------|-------------|
63
+ | `get(key: K)` | `Observable<V>` | Get or create a cached observable for the key |
64
+ | `next(key: K, value: V)` | `void` | Emit a new value for the key |
65
+ | `reset(key: K)` | `void` | Reset the cache state for the key |
66
+ | `update(key: K)` | `Observable<V>` | Force refresh the cached value |
67
+ | `delete(key: K)` | `void` | Remove the key from the map |
68
+ | `has(key: K)` | `boolean` | Check if the key exists |
69
+ | `clear()` | `void` | Remove all entries |
70
+
71
+ ### WeakReactiveMap<K, V>
72
+
73
+ Same API as `ReactiveMap` but uses `WeakMap` internally. Keys must be objects.
74
+
75
+ ```typescript
76
+ import { WeakReactiveMap } from '@reactive-cache/map';
77
+
78
+ const map = new WeakReactiveMap<UserRef, UserData>(
79
+ 'weakUsersMap',
80
+ (userRef) => fetchUserData(userRef.id)
81
+ );
82
+ ```
83
+
84
+ ### ConstantReactiveMap<K, V>
85
+
86
+ An immutable reactive map with primitive keys. Does not support `next`, `reset`, or `update` methods.
87
+
88
+ ```typescript
89
+ import { ConstantReactiveMap } from '@reactive-cache/map';
90
+
91
+ const map = new ConstantReactiveMap<string, Config>(
92
+ 'configMap',
93
+ (key) => loadConfig(key)
94
+ );
95
+ ```
96
+
97
+ #### Methods
98
+
99
+ | Method | Return Type | Description |
100
+ |--------|-------------|-------------|
101
+ | `get(key: K)` | `Observable<V>` | Get or create a cached observable for the key |
102
+ | `delete(key: K)` | `void` | Remove the key from the map |
103
+ | `clear()` | `void` | Remove all entries |
104
+
105
+ ### ConstantWeakReactiveMap<K, V>
106
+
107
+ Same API as `ConstantReactiveMap` but uses `WeakMap` internally. Keys must be objects.
108
+
109
+ ```typescript
110
+ import { ConstantWeakReactiveMap } from '@reactive-cache/map';
111
+
112
+ const map = new ConstantWeakReactiveMap<Document, Metadata>(
113
+ 'docMetaMap',
114
+ (doc) => extractMetadata(doc)
115
+ );
116
+ ```
117
+
118
+ ## Usage Examples
119
+
120
+ ### Basic Usage with Synchronous Values
121
+
122
+ ```typescript
123
+ import { ReactiveMap } from '@reactive-cache/map';
124
+
125
+ const greetingMap = new ReactiveMap<string, string>(
126
+ 'greetings',
127
+ (name) => `Hello, ${name}!`
128
+ );
129
+
130
+ greetingMap.get('World').subscribe(console.log);
131
+ // Output: Hello, World!
132
+
133
+ // Update the value
134
+ greetingMap.next('World', 'Hi, World!');
135
+ greetingMap.get('World').subscribe(console.log);
136
+ // Output: Hi, World!
137
+ ```
138
+
139
+ ### Async Data Fetching
140
+
141
+ ```typescript
142
+ import { ReactiveMap } from '@reactive-cache/map';
143
+ import { Observable } from 'rxjs';
144
+
145
+ interface User {
146
+ id: number;
147
+ name: string;
148
+ email: string;
149
+ }
150
+
151
+ const usersMap = new ReactiveMap<number, User | null>(
152
+ 'users',
153
+ (userId) => ajax(`/api/users/${userId}`).pipe(
154
+ catchError((err) => null);
155
+ )
156
+ );
157
+
158
+ // First call fetches from API
159
+ usersMap.get(1).subscribe(user => {
160
+ console.log(user.name);
161
+ });
162
+
163
+ // Second call returns cached value
164
+ usersMap.get(1).subscribe(user => {
165
+ console.log(user.name); // No API call, uses cache
166
+ });
167
+
168
+ // Force refresh
169
+ usersMap.update(1).subscribe(user => {
170
+ console.log('Refreshed:', user.name);
171
+ });
172
+ ```
173
+
174
+ ### Using with Promises
175
+
176
+ ```typescript
177
+ import { ReactiveMap } from '@reactive-cache/map';
178
+
179
+ const dataMap = new ReactiveMap<string, any>(
180
+ 'apiData',
181
+ (endpoint) => fetch(`/api/${endpoint}`).then(res => res.json())
182
+ );
183
+
184
+ dataMap.get('posts').subscribe(posts => {
185
+ console.log('Posts:', posts);
186
+ });
11
187
  ```
12
188
 
189
+ ### Angular Service Example
190
+
191
+ ```typescript
192
+ import { Injectable } from '@angular/core';
193
+ import { ReactiveMap } from '@reactive-cache/map';
194
+ import { HttpClient } from '@angular/common/http';
195
+ import { Observable } from 'rxjs';
196
+
197
+ interface Product {
198
+ id: number;
199
+ name: string;
200
+ price: number;
201
+ }
202
+
203
+ @Injectable({ providedIn: 'root' })
204
+ export class ProductService {
205
+ private productsMap = new ReactiveMap<number, Product>(
206
+ 'products',
207
+ (id) => this.http.get<Product>(`/api/products/${id}`)
208
+ );
209
+
210
+ constructor(private http: HttpClient) {}
211
+
212
+ getProduct(id: number): Observable<Product> {
213
+ return this.productsMap.get(id);
214
+ }
215
+
216
+ refreshProduct(id: number): Observable<Product> {
217
+ return this.productsMap.update(id);
218
+ }
219
+
220
+ updateProductLocally(id: number, product: Product): void {
221
+ this.productsMap.next(id, product);
222
+ }
223
+
224
+ clearCache(): void {
225
+ this.productsMap.clear();
226
+ }
227
+ }
228
+ ```
229
+
230
+ ### Using WeakReactiveMap for Object Keys
231
+
232
+ ```typescript
233
+ import { WeakReactiveMap } from '@reactive-cache/map';
234
+
235
+ interface Component {
236
+ id: string;
237
+ type: string;
238
+ }
239
+
240
+ interface ComponentState {
241
+ isLoaded: boolean;
242
+ data: any;
243
+ }
244
+
245
+ const componentStates = new WeakReactiveMap<Component, ComponentState>(
246
+ 'componentStates',
247
+ (component) => ({
248
+ isLoaded: false,
249
+ data: null
250
+ })
251
+ );
13
252
 
14
- ## Usage
253
+ const myComponent = { id: '1', type: 'widget' };
254
+
255
+ componentStates.get(myComponent).subscribe(state => {
256
+ console.log('State:', state);
257
+ });
258
+
259
+ // Update state
260
+ componentStates.next(myComponent, {
261
+ isLoaded: true,
262
+ data: { content: 'Hello' }
263
+ });
264
+
265
+ // When myComponent is garbage collected, the cache entry is automatically removed
266
+ ```
267
+
268
+ ### Immutable Configuration Cache
15
269
 
16
270
  ```typescript
17
- import { ReactiveMap } from 'reactive-cache/map';
271
+ import { ConstantReactiveMap } from '@reactive-cache/map';
18
272
 
19
- const map = new ReactiveMap<string, object>('map', (key: string) => {
20
- return fetch('http://...' + key)
273
+ interface FeatureConfig {
274
+ enabled: boolean;
275
+ settings: Record<string, any>;
276
+ }
277
+
278
+ const configMap = new ConstantReactiveMap<string, FeatureConfig>(
279
+ 'featureConfigs',
280
+ (featureName) => fetch(`/api/config/${featureName}`).then(r => r.json())
281
+ );
282
+
283
+ // Values cannot be modified after initial fetch
284
+ configMap.get('darkMode').subscribe(config => {
285
+ console.log('Dark mode enabled:', config.enabled);
21
286
  });
22
287
 
23
- map.get('1').subscribe(console.log);
24
- // data is fetched only once
25
- setTimeout(() => {
26
- map.get('1').subscribe()
27
- }, 5000)
28
- ```
288
+ // configMap.next() - Not available on ConstantReactiveMap
289
+ // configMap.reset() - Not available on ConstantReactiveMap
290
+ ```
291
+
292
+ ## Type Definitions
293
+
294
+ ```typescript
295
+ // Input type for factory functions
296
+ type ArgType<T> = Observable<T> | Promise<T> | T;
297
+
298
+ // Key types
299
+ type PrimitiveKey = string | number | symbol;
300
+ type ObjectKey = object;
301
+ ```
302
+
303
+ ## When to Use Each Map Type
304
+
305
+ | Scenario | Recommended Type |
306
+ |----------|------------------|
307
+ | API responses that may need updating | `ReactiveMap` |
308
+ | Static configuration data | `ConstantReactiveMap` |
309
+ | Component instances as keys | `WeakReactiveMap` |
310
+ | DOM elements as keys (read-only) | `ConstantWeakReactiveMap` |
311
+ | User session data | `ReactiveMap` |
312
+ | Translated strings | `ConstantReactiveMap` |
313
+ | Temporary object associations | `WeakReactiveMap` |
314
+
315
+ ## Dependencies
316
+
317
+ - [rxjs](https://rxjs.dev/) ^7.8.1
318
+ - [@reactive-cache/core](https://www.npmjs.com/package/@reactive-cache/core) ^3.2.0
319
+
320
+ ## Related Packages
321
+
322
+ - [@reactive-cache/core](https://www.npmjs.com/package/@reactive-cache/core) - Core reactive caching functionality
323
+
324
+ ## License
325
+
326
+ ISC
327
+
328
+ ## Author
329
+
330
+ [Jor-ban](https://github.com/Jor-ban)
331
+
332
+ ## Repository
333
+
334
+ [https://github.com/Jor-ban/reactive-cache](https://github.com/Jor-ban/reactive-cache)
package/package.json CHANGED
@@ -1,39 +1,39 @@
1
- {
2
- "name": "@reactive-cache/map",
3
- "version": "0.3.0",
4
- "type": "module",
5
- "scripts": {
6
- "test": "npx tsc && tsx watch src/test.ts && echo 'all tests are complete!'",
7
- "prepare": "npx tsc && rm -f ./dist/test.js"
8
- },
9
- "devDependencies": {
10
- "axios": "^1.7.9",
11
- "ts-node": "^10.9.2",
12
- "tsx": "^4.19.2",
13
- "typescript": "^5.5.3"
14
- },
15
- "dependencies": {
16
- "rxjs": "^7.8.1",
17
- "@reactive-cache/core": "^2.6.0"
18
- },
19
- "description": "reactive map for angular and rxjs projects",
20
- "main": "dist/index.js",
21
- "repository": {
22
- "type": "git",
23
- "url": "git+https://github.com/Jor-ban/reactive-cache.git"
24
- },
25
- "keywords": [
26
- "angular",
27
- "rxjs",
28
- "signal",
29
- "cache",
30
- "state-manager",
31
- "state"
32
- ],
33
- "author": "https://github.com/Jor-ban",
34
- "license": "ISC",
35
- "bugs": {
36
- "url": "https://github.com/Jor-ban/reactive-cache/issues"
37
- },
38
- "homepage": "https://github.com/Jor-ban/reactive-cache#readme"
39
- }
1
+ {
2
+ "name": "@reactive-cache/map",
3
+ "version": "1.0.0",
4
+ "type": "module",
5
+ "scripts": {
6
+ "test": "npx tsc && tsx watch src/test.ts && echo 'all tests are complete!'",
7
+ "prepare": "npx tsc && rm -f ./dist/test.js"
8
+ },
9
+ "devDependencies": {
10
+ "axios": "^1.7.9",
11
+ "ts-node": "^10.9.2",
12
+ "tsx": "^4.19.2",
13
+ "typescript": "^5.5.3"
14
+ },
15
+ "dependencies": {
16
+ "rxjs": "^7.8.1",
17
+ "@reactive-cache/core": "^3.2.0"
18
+ },
19
+ "description": "reactive map for angular and rxjs projects",
20
+ "main": "dist/index.js",
21
+ "repository": {
22
+ "type": "git",
23
+ "url": "git+https://github.com/Jor-ban/reactive-cache.git"
24
+ },
25
+ "keywords": [
26
+ "angular",
27
+ "rxjs",
28
+ "signal",
29
+ "cache",
30
+ "state-manager",
31
+ "state"
32
+ ],
33
+ "author": "https://github.com/Jor-ban",
34
+ "license": "ISC",
35
+ "bugs": {
36
+ "url": "https://github.com/Jor-ban/reactive-cache/issues"
37
+ },
38
+ "homepage": "https://github.com/Jor-ban/reactive-cache#readme"
39
+ }
package/src/index.ts CHANGED
@@ -1,203 +1,203 @@
1
- import {
2
- __createReactiveCache__,
3
- ConstantReactiveCacheObservable,
4
- ReactiveCacheObservable,
5
- __REACTIVE_CACHE_WINDOW_PROP_NAME__,
6
- ReactiveCacheObservableParameters
7
- } from "@reactive-cache/core"
8
- import {Observable, Subject} from "rxjs";
9
-
10
- export type ArgType<T> = Observable<T> | Promise<T> | T
11
- export type __ReactiveMapType__ = ReactiveMap<any, any> | WeakReactiveMap<any, any> | ConstantReactiveMap<any, any> | ConstantWeakReactiveMap<any, any>
12
-
13
- const __REACTIVE_MAPS_LIST__: __ReactiveMapType__[] = []
14
- const __REACTIVE_MAPS_ON_UPDATE_MAP__: WeakMap<__ReactiveMapType__, Observable<any>> = new WeakMap()
15
- const __REACTIVE_MAPS_LIST_UPDATE_OBSERVABLE__: Subject<void> = new Subject<void>()
16
-
17
- try {
18
- const WINDOW = this || global || window
19
- if(WINDOW && typeof WINDOW === 'object') {
20
- // @ts-ignore
21
- window.addEventListener('load', () => {
22
- // @ts-ignore
23
- if(!WINDOW.__REACTIVE_CACHE_WINDOW_PROP_NAME__) {
24
- // @ts-ignore
25
- WINDOW.__REACTIVE_CACHE_WINDOW_PROP_NAME__ = {}
26
- }
27
- // @ts-ignore
28
- WINDOW.__REACTIVE_CACHE_WINDOW_PROP_NAME__['__REACTIVE_MAPS_LIST__'] = __REACTIVE_MAPS_LIST__
29
- // @ts-ignore
30
- WINDOW.__REACTIVE_CACHE_WINDOW_PROP_NAME__['__REACTIVE_MAPS_LIST_UPDATE_OBSERVABLE__'] = __REACTIVE_MAPS_LIST_UPDATE_OBSERVABLE__
31
- // @ts-ignore
32
- WINDOW.__REACTIVE_CACHE_WINDOW_PROP_NAME__['__REACTIVE_MAPS_ON_UPDATE_MAP__'] = __REACTIVE_MAPS_ON_UPDATE_MAP__
33
- })
34
- }
35
- } catch(_ignored) {}
36
-
37
- export class ReactiveMap<K extends string | number | symbol, V> {
38
- private readonly map = new Map<K, ReactiveCacheObservable<V>>()
39
- private readonly onUpdateSubject = new Subject<V | Symbol>()
40
- public constructor(public readonly name: string, private readonly machine: (value: K) => ArgType<V>, params?: { constant?: boolean }) {
41
- __REACTIVE_MAPS_LIST__.push(this)
42
- __REACTIVE_MAPS_LIST_UPDATE_OBSERVABLE__.next()
43
- __REACTIVE_MAPS_ON_UPDATE_MAP__.set(this, this.onUpdateSubject)
44
- }
45
-
46
- public get(key: K): Observable<V> {
47
- const value = this.map.get(key)
48
- if (value) {
49
- return value
50
- }
51
- const { rc } = __createReactiveCache__(this.machine(key), {}, (v) => {
52
- this.onUpdateSubject.next(v)
53
- })
54
- this.map.set(key, rc as ReactiveCacheObservable<V>)
55
- return rc
56
- }
57
-
58
- public next(key: K, value: V): void {
59
- const subject = this.map.get(key)
60
- if (subject) {
61
- subject.next(value)
62
- }
63
- }
64
-
65
- public reset(key: K): void {
66
- const subject = this.map.get(key)
67
- if (subject) {
68
- subject.resetState()
69
- }
70
- }
71
-
72
- public delete(key: K): void {
73
- this.map.delete(key)
74
- }
75
-
76
- public update(key: K): Observable<V> {
77
- const subject = this.map.get(key)
78
- if (subject) {
79
- return subject.update()
80
- }
81
- return this.get(key)
82
- }
83
-
84
- public has(key: K): boolean {
85
- return this.map.has(key)
86
- }
87
-
88
- public clear(): void {
89
- this.map.clear()
90
- }
91
- }
92
-
93
- export class WeakReactiveMap<K extends object, V> {
94
- private readonly map = new WeakMap<K, ReactiveCacheObservable<V>>()
95
- private readonly onUpdateSubject = new Subject<V | Symbol>()
96
- public constructor(public readonly name: string, private readonly machine: (value: K) => ArgType<V>, params?: { constant?: boolean }) {
97
- __REACTIVE_MAPS_LIST__.push(this)
98
- __REACTIVE_MAPS_LIST_UPDATE_OBSERVABLE__.next()
99
- __REACTIVE_MAPS_ON_UPDATE_MAP__.set(this, this.onUpdateSubject)
100
- }
101
-
102
- public get(key: K): Observable<V> {
103
- const value = this.map.get(key)
104
- if (value) {
105
- return value
106
- }
107
- const { rc } = __createReactiveCache__(this.machine(key), {}, (v) => {
108
- this.onUpdateSubject.next(v)
109
- })
110
- this.map.set(key, rc as ReactiveCacheObservable<V>)
111
- return rc
112
- }
113
-
114
- public next(key: K, value: V): void {
115
- const subject = this.map.get(key)
116
- if (subject) {
117
- subject.next(value)
118
- }
119
- }
120
-
121
- public reset(key: K): void {
122
- const subject = this.map.get(key)
123
- if (subject) {
124
- subject.resetState()
125
- }
126
- }
127
-
128
- public delete(key: K): void {
129
- this.map.delete(key)
130
- }
131
-
132
- public update(key: K): Observable<V> {
133
- const subject = this.map.get(key)
134
- if (subject) {
135
- return subject.update()
136
- }
137
- return this.get(key)
138
- }
139
-
140
- public has(key: K): boolean {
141
- return this.map.has(key)
142
- }
143
- }
144
-
145
- export class ConstantReactiveMap<K extends string | number | symbol, V> {
146
- private readonly map = new Map<K, ConstantReactiveCacheObservable<V>>()
147
- private readonly onUpdateSubject = new Subject<V | Symbol>()
148
- public constructor(public readonly name: string, private readonly machine: (value: K) => ArgType<V>) {
149
- __REACTIVE_MAPS_LIST__.push(this)
150
- __REACTIVE_MAPS_LIST_UPDATE_OBSERVABLE__.next()
151
- __REACTIVE_MAPS_ON_UPDATE_MAP__.set(this, this.onUpdateSubject)
152
- }
153
-
154
- public get(key: K): Observable<V> {
155
- const value = this.map.get(key)
156
- if (value) {
157
- return value
158
- }
159
- const { rc } = __createReactiveCache__(this.machine(key), { constant: true }, (v) => {
160
- this.onUpdateSubject.next(v)
161
- })
162
- this.map.set(key, rc as ConstantReactiveCacheObservable<V>)
163
- return rc
164
- }
165
-
166
- public delete(key: K): void {
167
- this.map.delete(key)
168
- }
169
-
170
- public clear(): void {
171
- this.map.clear()
172
- }
173
- }
174
-
175
- export class ConstantWeakReactiveMap<K extends object, V> {
176
- private readonly map = new Map<K, ConstantReactiveCacheObservable<V>>()
177
- private readonly onUpdateSubject = new Subject<V | Symbol>()
178
- public constructor(public readonly name: string, private readonly machine: (value: K) => ArgType<V>) {
179
- __REACTIVE_MAPS_LIST__.push(this)
180
- __REACTIVE_MAPS_LIST_UPDATE_OBSERVABLE__.next()
181
- __REACTIVE_MAPS_ON_UPDATE_MAP__.set(this, this.onUpdateSubject)
182
- }
183
-
184
- public get(key: K): Observable<V> {
185
- const value = this.map.get(key)
186
- if (value) {
187
- return value
188
- }
189
- const { rc } = __createReactiveCache__(this.machine(key), { constant: true }, (v) => {
190
- this.onUpdateSubject.next(v)
191
- })
192
- this.map.set(key, rc as ConstantReactiveCacheObservable<V>)
193
- return rc
194
- }
195
-
196
- public delete(key: K): void {
197
- this.map.delete(key)
198
- }
199
-
200
- public clear(): void {
201
- this.map.clear()
202
- }
1
+ import {
2
+ __createReactiveCache__,
3
+ ConstantReactiveCacheObservable,
4
+ ReactiveCacheObservable,
5
+ __REACTIVE_CACHE_WINDOW_PROP_NAME__,
6
+ ReactiveCacheObservableParameters
7
+ } from "@reactive-cache/core"
8
+ import {Observable, Subject} from "rxjs";
9
+
10
+ export type ArgType<T> = Observable<T> | Promise<T> | T
11
+ export type __ReactiveMapType__ = ReactiveMap<any, any> | WeakReactiveMap<any, any> | ConstantReactiveMap<any, any> | ConstantWeakReactiveMap<any, any>
12
+
13
+ const __REACTIVE_MAPS_LIST__: __ReactiveMapType__[] = []
14
+ const __REACTIVE_MAPS_ON_UPDATE_MAP__: WeakMap<__ReactiveMapType__, Observable<any>> = new WeakMap()
15
+ const __REACTIVE_MAPS_LIST_UPDATE_OBSERVABLE__: Subject<void> = new Subject<void>()
16
+
17
+ try {
18
+ const WINDOW = this || global || window
19
+ if(WINDOW && typeof WINDOW === 'object') {
20
+ // @ts-ignore
21
+ window.addEventListener('load', () => {
22
+ // @ts-ignore
23
+ if(!WINDOW.__REACTIVE_CACHE_WINDOW_PROP_NAME__) {
24
+ // @ts-ignore
25
+ WINDOW.__REACTIVE_CACHE_WINDOW_PROP_NAME__ = {}
26
+ }
27
+ // @ts-ignore
28
+ WINDOW.__REACTIVE_CACHE_WINDOW_PROP_NAME__['__REACTIVE_MAPS_LIST__'] = __REACTIVE_MAPS_LIST__
29
+ // @ts-ignore
30
+ WINDOW.__REACTIVE_CACHE_WINDOW_PROP_NAME__['__REACTIVE_MAPS_LIST_UPDATE_OBSERVABLE__'] = __REACTIVE_MAPS_LIST_UPDATE_OBSERVABLE__
31
+ // @ts-ignore
32
+ WINDOW.__REACTIVE_CACHE_WINDOW_PROP_NAME__['__REACTIVE_MAPS_ON_UPDATE_MAP__'] = __REACTIVE_MAPS_ON_UPDATE_MAP__
33
+ })
34
+ }
35
+ } catch(_ignored) {}
36
+
37
+ export class ReactiveMap<K extends string | number | symbol, V> {
38
+ private readonly map = new Map<K, ReactiveCacheObservable<V>>()
39
+ private readonly onUpdateSubject = new Subject<V | Symbol>()
40
+ public constructor(public readonly name: string, private readonly machine: (value: K) => ArgType<V>, params?: { constant?: boolean }) {
41
+ __REACTIVE_MAPS_LIST__.push(this)
42
+ __REACTIVE_MAPS_LIST_UPDATE_OBSERVABLE__.next()
43
+ __REACTIVE_MAPS_ON_UPDATE_MAP__.set(this, this.onUpdateSubject)
44
+ }
45
+
46
+ public get(key: K): Observable<V> {
47
+ const value = this.map.get(key)
48
+ if (value) {
49
+ return value
50
+ }
51
+ const { rc } = __createReactiveCache__(this.machine(key), {}, (v) => {
52
+ this.onUpdateSubject.next(v)
53
+ })
54
+ this.map.set(key, rc as ReactiveCacheObservable<V>)
55
+ return rc
56
+ }
57
+
58
+ public next(key: K, value: V): void {
59
+ const subject = this.map.get(key)
60
+ if (subject) {
61
+ subject.next(value)
62
+ }
63
+ }
64
+
65
+ public reset(key: K): void {
66
+ const subject = this.map.get(key)
67
+ if (subject) {
68
+ subject.resetState()
69
+ }
70
+ }
71
+
72
+ public delete(key: K): void {
73
+ this.map.delete(key)
74
+ }
75
+
76
+ public update(key: K): Observable<V> {
77
+ const subject = this.map.get(key)
78
+ if (subject) {
79
+ return subject.update()
80
+ }
81
+ return this.get(key)
82
+ }
83
+
84
+ public has(key: K): boolean {
85
+ return this.map.has(key)
86
+ }
87
+
88
+ public clear(): void {
89
+ this.map.clear()
90
+ }
91
+ }
92
+
93
+ export class WeakReactiveMap<K extends object, V> {
94
+ private readonly map = new WeakMap<K, ReactiveCacheObservable<V>>()
95
+ private readonly onUpdateSubject = new Subject<V | Symbol>()
96
+ public constructor(public readonly name: string, private readonly machine: (value: K) => ArgType<V>, params?: { constant?: boolean }) {
97
+ __REACTIVE_MAPS_LIST__.push(this)
98
+ __REACTIVE_MAPS_LIST_UPDATE_OBSERVABLE__.next()
99
+ __REACTIVE_MAPS_ON_UPDATE_MAP__.set(this, this.onUpdateSubject)
100
+ }
101
+
102
+ public get(key: K): Observable<V> {
103
+ const value = this.map.get(key)
104
+ if (value) {
105
+ return value
106
+ }
107
+ const { rc } = __createReactiveCache__(this.machine(key), {}, (v) => {
108
+ this.onUpdateSubject.next(v)
109
+ })
110
+ this.map.set(key, rc as ReactiveCacheObservable<V>)
111
+ return rc
112
+ }
113
+
114
+ public next(key: K, value: V): void {
115
+ const subject = this.map.get(key)
116
+ if (subject) {
117
+ subject.next(value)
118
+ }
119
+ }
120
+
121
+ public reset(key: K): void {
122
+ const subject = this.map.get(key)
123
+ if (subject) {
124
+ subject.resetState()
125
+ }
126
+ }
127
+
128
+ public delete(key: K): void {
129
+ this.map.delete(key)
130
+ }
131
+
132
+ public update(key: K): Observable<V> {
133
+ const subject = this.map.get(key)
134
+ if (subject) {
135
+ return subject.update()
136
+ }
137
+ return this.get(key)
138
+ }
139
+
140
+ public has(key: K): boolean {
141
+ return this.map.has(key)
142
+ }
143
+ }
144
+
145
+ export class ConstantReactiveMap<K extends string | number | symbol, V> {
146
+ private readonly map = new Map<K, ConstantReactiveCacheObservable<V>>()
147
+ private readonly onUpdateSubject = new Subject<V | Symbol>()
148
+ public constructor(public readonly name: string, private readonly machine: (value: K) => ArgType<V>) {
149
+ __REACTIVE_MAPS_LIST__.push(this)
150
+ __REACTIVE_MAPS_LIST_UPDATE_OBSERVABLE__.next()
151
+ __REACTIVE_MAPS_ON_UPDATE_MAP__.set(this, this.onUpdateSubject)
152
+ }
153
+
154
+ public get(key: K): Observable<V> {
155
+ const value = this.map.get(key)
156
+ if (value) {
157
+ return value
158
+ }
159
+ const { rc } = __createReactiveCache__(this.machine(key), { constant: true }, (v) => {
160
+ this.onUpdateSubject.next(v)
161
+ })
162
+ this.map.set(key, rc as ConstantReactiveCacheObservable<V>)
163
+ return rc
164
+ }
165
+
166
+ public delete(key: K): void {
167
+ this.map.delete(key)
168
+ }
169
+
170
+ public clear(): void {
171
+ this.map.clear()
172
+ }
173
+ }
174
+
175
+ export class ConstantWeakReactiveMap<K extends object, V> {
176
+ private readonly map = new Map<K, ConstantReactiveCacheObservable<V>>()
177
+ private readonly onUpdateSubject = new Subject<V | Symbol>()
178
+ public constructor(public readonly name: string, private readonly machine: (value: K) => ArgType<V>) {
179
+ __REACTIVE_MAPS_LIST__.push(this)
180
+ __REACTIVE_MAPS_LIST_UPDATE_OBSERVABLE__.next()
181
+ __REACTIVE_MAPS_ON_UPDATE_MAP__.set(this, this.onUpdateSubject)
182
+ }
183
+
184
+ public get(key: K): Observable<V> {
185
+ const value = this.map.get(key)
186
+ if (value) {
187
+ return value
188
+ }
189
+ const { rc } = __createReactiveCache__(this.machine(key), { constant: true }, (v) => {
190
+ this.onUpdateSubject.next(v)
191
+ })
192
+ this.map.set(key, rc as ConstantReactiveCacheObservable<V>)
193
+ return rc
194
+ }
195
+
196
+ public delete(key: K): void {
197
+ this.map.delete(key)
198
+ }
199
+
200
+ public clear(): void {
201
+ this.map.clear()
202
+ }
203
203
  }
@@ -1,13 +0,0 @@
1
- <?xml version="1.0" encoding="UTF-8"?>
2
- <project version="4">
3
- <component name="MaterialThemeProjectNewConfig">
4
- <option name="metadata">
5
- <MTProjectMetadataState>
6
- <option name="migrated" value="true" />
7
- <option name="pristineConfig" value="false" />
8
- <option name="userId" value="-4b6355e5:18c908035a5:-8000" />
9
- <option name="version" value="8.13.2" />
10
- </MTProjectMetadataState>
11
- </option>
12
- </component>
13
- </project>
package/.idea/modules.xml DELETED
@@ -1,8 +0,0 @@
1
- <?xml version="1.0" encoding="UTF-8"?>
2
- <project version="4">
3
- <component name="ProjectModuleManager">
4
- <modules>
5
- <module fileurl="file://$PROJECT_DIR$/.idea/reactive-map.iml" filepath="$PROJECT_DIR$/.idea/reactive-map.iml" />
6
- </modules>
7
- </component>
8
- </project>
@@ -1,12 +0,0 @@
1
- <?xml version="1.0" encoding="UTF-8"?>
2
- <module type="WEB_MODULE" version="4">
3
- <component name="NewModuleRootManager">
4
- <content url="file://$MODULE_DIR$">
5
- <excludeFolder url="file://$MODULE_DIR$/.tmp" />
6
- <excludeFolder url="file://$MODULE_DIR$/temp" />
7
- <excludeFolder url="file://$MODULE_DIR$/tmp" />
8
- </content>
9
- <orderEntry type="inheritedJdk" />
10
- <orderEntry type="sourceFolder" forTests="false" />
11
- </component>
12
- </module>
package/.idea/vcs.xml DELETED
@@ -1,6 +0,0 @@
1
- <?xml version="1.0" encoding="UTF-8"?>
2
- <project version="4">
3
- <component name="VcsDirectoryMappings">
4
- <mapping directory="" vcs="Git" />
5
- </component>
6
- </project>
package/dist/index.d.ts DELETED
@@ -1,44 +0,0 @@
1
- import {Observable, Subject} from "rxjs";
2
- import {__createReactiveCache__, ConstantReactiveCacheObservable} from "@reactive-cache/core";
3
-
4
- export type ArgType<T> = Observable<T> | Promise<T> | T
5
- export type __ReactiveMapType__ = ReactiveMap<any, any> | WeakReactiveMap<any, any> | ConstantReactiveMap<any, any>
6
-
7
- const __REACTIVE_MAPS_LIST__: __ReactiveMapType__[] = []
8
- const __REACTIVE_MAPS_ON_UPDATE_MAP__: WeakMap<__ReactiveMapType__, Observable<any>> = new WeakMap()
9
- const __REACTIVE_MAPS_LIST_UPDATE_OBSERVABLE__: Subject<void> = new Subject<void>()
10
-
11
- export class ReactiveMap<K extends string | number | symbol, V> {
12
- public constructor(public readonly name: string, private readonly machine: (value: K) => ArgType<V>)
13
- public get(key: K): Observable<V>
14
- public next(key: K, value: V): void
15
- public reset(key: K): void
16
- public delete(key: K): void
17
- public update(key: K): Observable<V>
18
- public has(key: K): boolean
19
- public clear(): void
20
- }
21
-
22
- export class WeakReactiveMap<K extends object, V> {
23
- public constructor(public readonly name: string, private readonly machine: (value: K) => ArgType<V>)
24
- public get(key: K): Observable<V>
25
- public next(key: K, value: V): void
26
- public reset(key: K): void
27
- public delete(key: K): void
28
- public update(key: K): Observable<V>
29
- public has(key: K): boolean
30
- }
31
-
32
- export class ConstantReactiveMap<K extends string | number | symbol, V> {
33
- public constructor(public readonly name: string, private readonly machine: (value: K) => ArgType<V>)
34
- public get(key: K): Observable<V>
35
- public delete(key: K): void
36
- public clear(): void
37
- }
38
-
39
- export class ConstantWeakReactiveMap<K extends object, V> {
40
- public constructor(public readonly name: string, private readonly machine: (value: K) => ArgType<V>)
41
- public get(key: K): Observable<V>
42
- public delete(key: K): void
43
- public clear(): void
44
- }