@equinor/fusion-framework-module-context 4.0.2 → 4.0.4
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/CHANGELOG.md +12 -0
- package/dist/esm/ContextProvider.js +23 -13
- package/dist/esm/ContextProvider.js.map +1 -1
- package/dist/esm/module.js +1 -3
- package/dist/esm/module.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/dist/types/ContextProvider.d.ts +4 -0
- package/package.json +2 -2
- package/src/ContextProvider.ts +73 -20
- package/src/module.ts +1 -3
|
@@ -50,6 +50,10 @@ export declare class ContextProvider implements IContextProvider {
|
|
|
50
50
|
validate?: boolean;
|
|
51
51
|
resolve?: boolean;
|
|
52
52
|
}): Observable<T>;
|
|
53
|
+
protected _setCurrentContext<T extends ContextItem<Record<string, unknown>> | null>(context: T, opt?: {
|
|
54
|
+
validate?: boolean;
|
|
55
|
+
resolve?: boolean;
|
|
56
|
+
}): Observable<T>;
|
|
53
57
|
setCurrentContextAsync<T extends ContextItem<Record<string, unknown>> | null>(context: T, opt?: {
|
|
54
58
|
validate?: boolean;
|
|
55
59
|
resolve?: boolean;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@equinor/fusion-framework-module-context",
|
|
3
|
-
"version": "4.0.
|
|
3
|
+
"version": "4.0.4",
|
|
4
4
|
"description": "",
|
|
5
5
|
"main": "./dist/esm/index.js",
|
|
6
6
|
"exports": {
|
|
@@ -49,5 +49,5 @@
|
|
|
49
49
|
"@equinor/fusion-framework-module": ">=1.2.5",
|
|
50
50
|
"rxjs": "^7.5.7"
|
|
51
51
|
},
|
|
52
|
-
"gitHead": "
|
|
52
|
+
"gitHead": "b369a37e2b205b8d91d9b9a8907195f7f673a344"
|
|
53
53
|
}
|
package/src/ContextProvider.ts
CHANGED
|
@@ -1,13 +1,14 @@
|
|
|
1
|
+
import { EMPTY, lastValueFrom, Observable, of, Subject, Subscription, throwError } from 'rxjs';
|
|
1
2
|
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
3
|
+
catchError,
|
|
4
|
+
filter,
|
|
5
|
+
finalize,
|
|
6
|
+
map,
|
|
7
|
+
pairwise,
|
|
8
|
+
switchMap,
|
|
9
|
+
takeUntil,
|
|
10
|
+
tap,
|
|
11
|
+
} from 'rxjs/operators';
|
|
11
12
|
|
|
12
13
|
import { ContextModuleConfig } from './configurator';
|
|
13
14
|
|
|
@@ -73,6 +74,8 @@ export class ContextProvider implements IContextProvider {
|
|
|
73
74
|
#contextFilter: ContextModuleConfig['contextFilter'];
|
|
74
75
|
#contextParameterFn: Required<ContextModuleConfig['contextParameterFn']>;
|
|
75
76
|
|
|
77
|
+
#contextQueue = new Subject<Observable<ContextItem<Record<string, unknown>>>>();
|
|
78
|
+
|
|
76
79
|
public get contextClient() {
|
|
77
80
|
return this.#contextClient;
|
|
78
81
|
}
|
|
@@ -159,6 +162,15 @@ export class ContextProvider implements IContextProvider {
|
|
|
159
162
|
})
|
|
160
163
|
);
|
|
161
164
|
}
|
|
165
|
+
|
|
166
|
+
this.#subscriptions.add(
|
|
167
|
+
this.#contextQueue
|
|
168
|
+
.pipe(
|
|
169
|
+
switchMap((next) => next),
|
|
170
|
+
tap((x) => console.debug('ContextProvider::#contextQueue', x))
|
|
171
|
+
)
|
|
172
|
+
.subscribe((context) => this.#contextClient.setCurrentContext(context ?? null))
|
|
173
|
+
);
|
|
162
174
|
}
|
|
163
175
|
|
|
164
176
|
public connectParentContext(
|
|
@@ -167,7 +179,7 @@ export class ContextProvider implements IContextProvider {
|
|
|
167
179
|
): Subscription {
|
|
168
180
|
const parentContext$ = provider.currentContext$.pipe(
|
|
169
181
|
// do not set context if parent has not initialized
|
|
170
|
-
filter((x) => x !== undefined),
|
|
182
|
+
filter((x): x is ContextItem | null => x !== undefined),
|
|
171
183
|
filter((next, index) => {
|
|
172
184
|
if (opt?.skipFirst && index <= 1) {
|
|
173
185
|
console.debug(
|
|
@@ -177,7 +189,7 @@ export class ContextProvider implements IContextProvider {
|
|
|
177
189
|
);
|
|
178
190
|
return false;
|
|
179
191
|
}
|
|
180
|
-
return this.currentContext !== next;
|
|
192
|
+
return this.currentContext?.id !== next?.id;
|
|
181
193
|
}),
|
|
182
194
|
switchMap(async (next) => {
|
|
183
195
|
if (next) {
|
|
@@ -195,10 +207,6 @@ export class ContextProvider implements IContextProvider {
|
|
|
195
207
|
}),
|
|
196
208
|
filter((x) => !x.canceled),
|
|
197
209
|
switchMap(({ next }) => {
|
|
198
|
-
if (!next) {
|
|
199
|
-
this.clearCurrentContext();
|
|
200
|
-
return EMPTY;
|
|
201
|
-
}
|
|
202
210
|
return this.setCurrentContext(next, {
|
|
203
211
|
validate: true,
|
|
204
212
|
resolve: true,
|
|
@@ -241,12 +249,58 @@ export class ContextProvider implements IContextProvider {
|
|
|
241
249
|
}
|
|
242
250
|
|
|
243
251
|
public setCurrentContextByIdAsync(id: string): Promise<ContextItem<Record<string, unknown>>> {
|
|
244
|
-
return
|
|
252
|
+
return lastValueFrom(this.setCurrentContextById(id));
|
|
245
253
|
}
|
|
246
254
|
|
|
255
|
+
/**
|
|
256
|
+
* Setting context is a complex operation, and might not happen immediately.
|
|
257
|
+
* When setting the context, a task is created and added to the queue.
|
|
258
|
+
* Once the task is completed, the returned observable will emit the value which will be the next state.
|
|
259
|
+
*
|
|
260
|
+
* Even tho this function returns a `Observable`, the task will be queued even tho nobody subscribes.
|
|
261
|
+
*
|
|
262
|
+
* If the observable is subscribe, unsubscribing __WILL__ abort the task and remove it from queue
|
|
263
|
+
*
|
|
264
|
+
* @param context context item which would be queue to set as current
|
|
265
|
+
*/
|
|
247
266
|
public setCurrentContext<T extends ContextItem<Record<string, unknown>> | null>(
|
|
248
267
|
context: T,
|
|
249
268
|
opt?: { validate?: boolean; resolve?: boolean }
|
|
269
|
+
): Observable<T> {
|
|
270
|
+
/** signal for aborting the queue entry */
|
|
271
|
+
const abort$ = new Subject();
|
|
272
|
+
|
|
273
|
+
/** wrapper for returning an observable to the caller */
|
|
274
|
+
const subject$ = new Subject<T>();
|
|
275
|
+
|
|
276
|
+
const task$ = this._setCurrentContext(context, opt).pipe(
|
|
277
|
+
/** send context item which was set to the caller */
|
|
278
|
+
tap((x) => subject$.next(x)),
|
|
279
|
+
/** abort task on signal */
|
|
280
|
+
takeUntil(abort$),
|
|
281
|
+
/** close observable sent to caller */
|
|
282
|
+
finalize(() => subject$.complete()),
|
|
283
|
+
/** catch errors to not stall queue */
|
|
284
|
+
catchError((err) => {
|
|
285
|
+
/** send the error to the caller */
|
|
286
|
+
subject$.error(err);
|
|
287
|
+
/** skip setting any context */
|
|
288
|
+
return EMPTY;
|
|
289
|
+
})
|
|
290
|
+
);
|
|
291
|
+
|
|
292
|
+
/** add task to internal queue */
|
|
293
|
+
this.#contextQueue.next(task$ as Observable<ContextItem<Record<string, unknown>>>);
|
|
294
|
+
|
|
295
|
+
return subject$.pipe(
|
|
296
|
+
/** if caller subscribes, unsubscribe should abort queue entry */
|
|
297
|
+
finalize(() => abort$.next(true))
|
|
298
|
+
);
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
protected _setCurrentContext<T extends ContextItem<Record<string, unknown>> | null>(
|
|
302
|
+
context: T,
|
|
303
|
+
opt?: { validate?: boolean; resolve?: boolean }
|
|
250
304
|
): Observable<T> {
|
|
251
305
|
return new Observable((subscriber) => {
|
|
252
306
|
if (context === this.currentContext) {
|
|
@@ -331,7 +385,6 @@ export class ContextProvider implements IContextProvider {
|
|
|
331
385
|
})
|
|
332
386
|
)
|
|
333
387
|
.subscribe((context) => {
|
|
334
|
-
this.#contextClient.setCurrentContext(context ?? null);
|
|
335
388
|
subscriber.next(context);
|
|
336
389
|
subscriber.complete();
|
|
337
390
|
});
|
|
@@ -342,7 +395,7 @@ export class ContextProvider implements IContextProvider {
|
|
|
342
395
|
context: T,
|
|
343
396
|
opt?: { validate?: boolean; resolve?: boolean }
|
|
344
397
|
): Promise<T> {
|
|
345
|
-
return
|
|
398
|
+
return lastValueFrom(this.setCurrentContext(context, opt));
|
|
346
399
|
}
|
|
347
400
|
|
|
348
401
|
public queryContext(search: string): Observable<Array<ContextItem>> {
|
|
@@ -422,8 +475,8 @@ export class ContextProvider implements IContextProvider {
|
|
|
422
475
|
return lastValueFrom(this.relatedContexts(args));
|
|
423
476
|
}
|
|
424
477
|
|
|
425
|
-
public clearCurrentContext() {
|
|
426
|
-
this.
|
|
478
|
+
public clearCurrentContext(): void {
|
|
479
|
+
this.setCurrentContext(null);
|
|
427
480
|
}
|
|
428
481
|
|
|
429
482
|
dispose() {
|
package/src/module.ts
CHANGED
|
@@ -68,9 +68,7 @@ export const module: ContextModule = {
|
|
|
68
68
|
},
|
|
69
69
|
complete: () => {
|
|
70
70
|
// TODO - do we need to check first?
|
|
71
|
-
provider.connectParentContext(parentProvider
|
|
72
|
-
skipFirst: !!provider.currentContext,
|
|
73
|
-
});
|
|
71
|
+
provider.connectParentContext(parentProvider);
|
|
74
72
|
subscriber.complete();
|
|
75
73
|
},
|
|
76
74
|
})
|