@equinor/fusion-framework-module-context 3.1.1 → 4.0.0-next.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/CHANGELOG.md +4 -0
- package/dist/esm/ContextConfigBuilder.js +3 -0
- package/dist/esm/ContextConfigBuilder.js.map +1 -1
- package/dist/esm/ContextProvider.js +129 -67
- package/dist/esm/ContextProvider.js.map +1 -1
- package/dist/esm/client/ContextClient.js +3 -0
- package/dist/esm/client/ContextClient.js.map +1 -1
- package/dist/esm/configurator.js.map +1 -1
- package/dist/esm/module.js +13 -2
- package/dist/esm/module.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/dist/types/ContextConfigBuilder.d.ts +1 -0
- package/dist/types/ContextProvider.d.ts +20 -1
- package/dist/types/client/ContextClient.d.ts +1 -0
- package/dist/types/configurator.d.ts +1 -0
- package/package.json +3 -3
- package/src/ContextConfigBuilder.ts +4 -0
- package/src/ContextProvider.ts +217 -100
- package/src/client/ContextClient.ts +4 -0
- package/src/configurator.ts +3 -0
- package/src/module.ts +15 -2
|
@@ -15,6 +15,7 @@ export declare class ContextConfigBuilder<TModules extends Array<AnyModule> = []
|
|
|
15
15
|
setContextParameterFn(fn: ContextModuleConfig['contextParameterFn']): void;
|
|
16
16
|
setValidateContext(fn: ContextModuleConfig['validateContext']): void;
|
|
17
17
|
setResolveContext(fn: ContextModuleConfig['resolveContext']): void;
|
|
18
|
+
setSkipInitialContext(skip: ContextModuleConfig['skipInitialContext']): void;
|
|
18
19
|
setContextClient(client: {
|
|
19
20
|
get: QueryFn<ContextItem, GetContextParameters> | QueryCtorOptions<ContextItem, GetContextParameters>;
|
|
20
21
|
query: QueryFn<ContextItem[], QueryContextParameters> | QueryCtorOptions<ContextItem[], QueryContextParameters>;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Observable } from 'rxjs';
|
|
1
|
+
import { Observable, Subscription } from 'rxjs';
|
|
2
2
|
import { ContextModuleConfig } from './configurator';
|
|
3
3
|
import { ContextClient } from './client/ContextClient';
|
|
4
4
|
import { ContextItem, QueryContextParameters, RelatedContextParameters } from './types';
|
|
@@ -18,6 +18,16 @@ export interface IContextProvider {
|
|
|
18
18
|
relatedContexts: (args: RelatedContextParameters) => Observable<Array<ContextItem<Record<string, unknown>>>>;
|
|
19
19
|
relatedContextsAsync: (args: RelatedContextParameters) => Promise<Array<ContextItem<Record<string, unknown>>>>;
|
|
20
20
|
clearCurrentContext: VoidFunction;
|
|
21
|
+
setCurrentContextById(id: string): Observable<ContextItem<Record<string, unknown>>>;
|
|
22
|
+
setCurrentContextByIdAsync(id: string): Promise<ContextItem<Record<string, unknown>>>;
|
|
23
|
+
setCurrentContext(context: ContextItem<Record<string, unknown>>, opt?: {
|
|
24
|
+
validate?: boolean;
|
|
25
|
+
resolve?: boolean;
|
|
26
|
+
}): Observable<ContextItem<Record<string, unknown>>>;
|
|
27
|
+
setCurrentContextAsync(context: ContextItem<Record<string, unknown>>, opt?: {
|
|
28
|
+
validate?: boolean;
|
|
29
|
+
resolve?: boolean;
|
|
30
|
+
}): Promise<ContextItem<Record<string, unknown>>>;
|
|
21
31
|
}
|
|
22
32
|
export declare class ContextProvider implements IContextProvider {
|
|
23
33
|
#private;
|
|
@@ -31,9 +41,18 @@ export declare class ContextProvider implements IContextProvider {
|
|
|
31
41
|
event?: ModuleType<EventModule>;
|
|
32
42
|
parentContext?: IContextProvider;
|
|
33
43
|
});
|
|
44
|
+
connectParentContextAsync(provider: IContextProvider, opt?: {
|
|
45
|
+
setCurrent?: boolean;
|
|
46
|
+
}): Promise<Subscription>;
|
|
47
|
+
setCurrentContextById(id: string): Observable<ContextItem<Record<string, unknown>>>;
|
|
48
|
+
setCurrentContextByIdAsync(id: string): Promise<ContextItem<Record<string, unknown>>>;
|
|
34
49
|
setCurrentContext(context: ContextItem<Record<string, unknown>>, opt?: {
|
|
35
50
|
validate?: boolean;
|
|
36
51
|
resolve?: boolean;
|
|
52
|
+
}): Observable<ContextItem<Record<string, unknown>>>;
|
|
53
|
+
setCurrentContextAsync(context: ContextItem<Record<string, unknown>>, opt?: {
|
|
54
|
+
validate?: boolean;
|
|
55
|
+
resolve?: boolean;
|
|
37
56
|
}): Promise<ContextItem<Record<string, unknown>>>;
|
|
38
57
|
queryContext(search: string): Observable<Array<ContextItem>>;
|
|
39
58
|
queryContextAsync(search: string): Promise<Array<ContextItem>>;
|
|
@@ -14,5 +14,6 @@ export declare class ContextClient extends Observable<ContextItem> {
|
|
|
14
14
|
constructor(options: QueryCtorOptions<ContextItem, GetContextParameters>);
|
|
15
15
|
setCurrentContext(idOrItem?: string | ContextItem): void;
|
|
16
16
|
resolveContext(id: string): Observable<ContextItem>;
|
|
17
|
+
dispose(): void;
|
|
17
18
|
}
|
|
18
19
|
export default ContextClient;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@equinor/fusion-framework-module-context",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "4.0.0-next.0",
|
|
4
4
|
"description": "",
|
|
5
5
|
"main": "./dist/esm/index.js",
|
|
6
6
|
"exports": {
|
|
@@ -37,12 +37,12 @@
|
|
|
37
37
|
"devDependencies": {
|
|
38
38
|
"@equinor/fusion-framework-module": "^3.0.0",
|
|
39
39
|
"@equinor/fusion-framework-module-event": "^3.0.0",
|
|
40
|
-
"@equinor/fusion-framework-module-services": "^3.0.
|
|
40
|
+
"@equinor/fusion-framework-module-services": "^3.0.3",
|
|
41
41
|
"rxjs": "^7.5.7"
|
|
42
42
|
},
|
|
43
43
|
"peerDependencies": {
|
|
44
44
|
"@equinor/fusion-framework-module": ">=1.2.5",
|
|
45
45
|
"rxjs": "^7.5.7"
|
|
46
46
|
},
|
|
47
|
-
"gitHead": "
|
|
47
|
+
"gitHead": "cdf3599bbf7ed06c1664edd9cb755a6f7b0284dd"
|
|
48
48
|
}
|
package/src/ContextProvider.ts
CHANGED
|
@@ -1,5 +1,13 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
1
|
+
import {
|
|
2
|
+
EMPTY,
|
|
3
|
+
firstValueFrom,
|
|
4
|
+
lastValueFrom,
|
|
5
|
+
Observable,
|
|
6
|
+
of,
|
|
7
|
+
Subscription,
|
|
8
|
+
throwError,
|
|
9
|
+
} from 'rxjs';
|
|
10
|
+
import { catchError, filter, map, pairwise, switchMap } from 'rxjs/operators';
|
|
3
11
|
|
|
4
12
|
import { ContextModuleConfig } from './configurator';
|
|
5
13
|
|
|
@@ -37,6 +45,19 @@ export interface IContextProvider {
|
|
|
37
45
|
args: RelatedContextParameters
|
|
38
46
|
) => Promise<Array<ContextItem<Record<string, unknown>>>>;
|
|
39
47
|
clearCurrentContext: VoidFunction;
|
|
48
|
+
|
|
49
|
+
setCurrentContextById(id: string): Observable<ContextItem<Record<string, unknown>>>;
|
|
50
|
+
setCurrentContextByIdAsync(id: string): Promise<ContextItem<Record<string, unknown>>>;
|
|
51
|
+
|
|
52
|
+
setCurrentContext(
|
|
53
|
+
context: ContextItem<Record<string, unknown>>,
|
|
54
|
+
opt?: { validate?: boolean; resolve?: boolean }
|
|
55
|
+
): Observable<ContextItem<Record<string, unknown>>>;
|
|
56
|
+
|
|
57
|
+
setCurrentContextAsync(
|
|
58
|
+
context: ContextItem<Record<string, unknown>>,
|
|
59
|
+
opt?: { validate?: boolean; resolve?: boolean }
|
|
60
|
+
): Promise<ContextItem<Record<string, unknown>>>;
|
|
40
61
|
}
|
|
41
62
|
|
|
42
63
|
export class ContextProvider implements IContextProvider {
|
|
@@ -68,16 +89,32 @@ export class ContextProvider implements IContextProvider {
|
|
|
68
89
|
return this.#contextClient.currentContext;
|
|
69
90
|
}
|
|
70
91
|
|
|
92
|
+
/** @deprecated do not use, will be removed */
|
|
71
93
|
set currentContext(context: ContextItem | undefined) {
|
|
72
|
-
|
|
94
|
+
console.warn(
|
|
95
|
+
'@deprecated',
|
|
96
|
+
'ContextProvider.currentContext',
|
|
97
|
+
'use setCurrentContextById|setCurrentContext|clearCurrentContext'
|
|
98
|
+
);
|
|
99
|
+
context ? this.setCurrentContextAsync(context) : this.clearCurrentContext();
|
|
73
100
|
}
|
|
74
101
|
|
|
75
102
|
constructor(args: {
|
|
76
103
|
config: ContextModuleConfig;
|
|
77
104
|
event?: ModuleType<EventModule>;
|
|
105
|
+
/** @deprecated use ContextProvider.connectParentContext */
|
|
78
106
|
parentContext?: IContextProvider;
|
|
79
107
|
}) {
|
|
80
|
-
const { config, event
|
|
108
|
+
const { config, event } = args;
|
|
109
|
+
|
|
110
|
+
if (args.parentContext) {
|
|
111
|
+
console.warn(
|
|
112
|
+
'@deprecated',
|
|
113
|
+
'parentContext as arg is deprecated, use ContextProvider.connectParentContext'
|
|
114
|
+
);
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
this.#event = event;
|
|
81
118
|
|
|
82
119
|
config.resolveContext && (this.resolveContext = config.resolveContext?.bind(this));
|
|
83
120
|
config.validateContext && (this.validateContext = config.validateContext?.bind(this));
|
|
@@ -99,25 +136,21 @@ export class ContextProvider implements IContextProvider {
|
|
|
99
136
|
filter: { type: args.type },
|
|
100
137
|
}));
|
|
101
138
|
|
|
102
|
-
if (event) {
|
|
103
|
-
this.#event = event;
|
|
104
|
-
|
|
105
|
-
/** this might be moved to client, to await prevention of event */
|
|
139
|
+
if (this.#event) {
|
|
106
140
|
this.#subscriptions.add(
|
|
107
141
|
this.#contextClient.currentContext$
|
|
108
142
|
.pipe(pairwise())
|
|
109
143
|
.subscribe(([previous, next]) => {
|
|
110
|
-
event
|
|
144
|
+
this.#event?.dispatchEvent('onCurrentContextChanged', {
|
|
111
145
|
source: this,
|
|
112
146
|
canBubble: true,
|
|
113
147
|
detail: { previous, next },
|
|
114
148
|
});
|
|
115
149
|
})
|
|
116
150
|
);
|
|
117
|
-
|
|
118
151
|
this.#subscriptions.add(
|
|
119
152
|
/** observe event from child modules */
|
|
120
|
-
event.addEventListener('onCurrentContextChanged', (e) => {
|
|
153
|
+
this.#event.addEventListener('onCurrentContextChanged', (e) => {
|
|
121
154
|
/** loop prevention */
|
|
122
155
|
if (e.source !== this) {
|
|
123
156
|
this.currentContext = e.detail.next;
|
|
@@ -125,112 +158,195 @@ export class ContextProvider implements IContextProvider {
|
|
|
125
158
|
})
|
|
126
159
|
);
|
|
127
160
|
}
|
|
161
|
+
}
|
|
128
162
|
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
return { next, canceled: onParentContextChanged?.canceled };
|
|
144
|
-
}
|
|
145
|
-
return { next };
|
|
146
|
-
}),
|
|
147
|
-
filter((x) => !x.canceled),
|
|
148
|
-
map(({ next }) => next)
|
|
149
|
-
)
|
|
150
|
-
.subscribe(async (next) => {
|
|
151
|
-
if (next) {
|
|
152
|
-
try {
|
|
153
|
-
await this.setCurrentContext(next, {
|
|
154
|
-
validate: true,
|
|
155
|
-
resolve: true,
|
|
156
|
-
});
|
|
157
|
-
} catch (err) {
|
|
158
|
-
console.warn('ContextProvider::onParentContextChanged', err);
|
|
159
|
-
}
|
|
160
|
-
} else {
|
|
161
|
-
this.clearCurrentContext();
|
|
163
|
+
public async connectParentContextAsync(
|
|
164
|
+
provider: IContextProvider,
|
|
165
|
+
opt?: { setCurrent?: boolean }
|
|
166
|
+
): Promise<Subscription> {
|
|
167
|
+
const parentContext$ = provider.currentContext$.pipe(
|
|
168
|
+
filter((next) => this.currentContext !== next),
|
|
169
|
+
switchMap(async (next) => {
|
|
170
|
+
if (next) {
|
|
171
|
+
const onParentContextChanged = await this.#event?.dispatchEvent(
|
|
172
|
+
'onParentContextChanged',
|
|
173
|
+
{
|
|
174
|
+
source: this,
|
|
175
|
+
detail: next,
|
|
176
|
+
cancelable: true,
|
|
162
177
|
}
|
|
178
|
+
);
|
|
179
|
+
return { next, canceled: onParentContextChanged?.canceled };
|
|
180
|
+
}
|
|
181
|
+
return { next };
|
|
182
|
+
}),
|
|
183
|
+
filter((x) => !x.canceled),
|
|
184
|
+
switchMap(({ next }) => {
|
|
185
|
+
if (!next) {
|
|
186
|
+
this.clearCurrentContext();
|
|
187
|
+
return EMPTY;
|
|
188
|
+
}
|
|
189
|
+
return this.setCurrentContext(next, {
|
|
190
|
+
validate: true,
|
|
191
|
+
resolve: true,
|
|
192
|
+
}).pipe(
|
|
193
|
+
catchError((err) => {
|
|
194
|
+
console.warn(
|
|
195
|
+
'ContextProvider::onParentContextChanged',
|
|
196
|
+
'setCurrentContext',
|
|
197
|
+
err
|
|
198
|
+
);
|
|
199
|
+
return EMPTY;
|
|
163
200
|
})
|
|
164
|
-
|
|
165
|
-
|
|
201
|
+
);
|
|
202
|
+
}),
|
|
203
|
+
catchError((err) => {
|
|
204
|
+
console.warn('ContextProvider::onParentContextChanged', 'unhandled exception', err);
|
|
205
|
+
return EMPTY;
|
|
206
|
+
})
|
|
207
|
+
);
|
|
208
|
+
|
|
209
|
+
const subscription = parentContext$.subscribe();
|
|
210
|
+
this.#subscriptions.add(subscription);
|
|
211
|
+
|
|
212
|
+
return new Promise((resolve, reject) => {
|
|
213
|
+
if (opt?.setCurrent && provider.currentContext) {
|
|
214
|
+
subscription.add(reject);
|
|
215
|
+
subscription.add(
|
|
216
|
+
this.setCurrentContext(provider.currentContext, {
|
|
217
|
+
validate: true,
|
|
218
|
+
resolve: true,
|
|
219
|
+
}).subscribe({
|
|
220
|
+
error: (err) => {
|
|
221
|
+
subscription.remove(reject);
|
|
222
|
+
reject(err);
|
|
223
|
+
},
|
|
224
|
+
complete: () => {
|
|
225
|
+
subscription.remove(reject);
|
|
226
|
+
resolve(subscription);
|
|
227
|
+
},
|
|
228
|
+
})
|
|
229
|
+
);
|
|
230
|
+
} else {
|
|
231
|
+
return resolve(subscription);
|
|
232
|
+
}
|
|
233
|
+
});
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
public setCurrentContextById(id: string): Observable<ContextItem<Record<string, unknown>>> {
|
|
237
|
+
return new Observable((subscriber) => {
|
|
238
|
+
try {
|
|
239
|
+
this.#contextClient
|
|
240
|
+
.resolveContext(id)
|
|
241
|
+
.pipe(switchMap((item) => this.setCurrentContext(item)))
|
|
242
|
+
.subscribe(subscriber);
|
|
243
|
+
} catch (err) {
|
|
244
|
+
subscriber.error(err);
|
|
245
|
+
}
|
|
246
|
+
});
|
|
166
247
|
}
|
|
167
248
|
|
|
168
|
-
public
|
|
249
|
+
public setCurrentContextByIdAsync(id: string): Promise<ContextItem<Record<string, unknown>>> {
|
|
250
|
+
return firstValueFrom(this.setCurrentContextById(id));
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
public setCurrentContext(
|
|
169
254
|
context: ContextItem<Record<string, unknown>>,
|
|
170
255
|
opt?: { validate?: boolean; resolve?: boolean }
|
|
171
|
-
):
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
{
|
|
256
|
+
): Observable<ContextItem<Record<string, unknown>>> {
|
|
257
|
+
return new Observable((subscriber) => {
|
|
258
|
+
if (context === this.currentContext) {
|
|
259
|
+
subscriber.next(context);
|
|
260
|
+
return subscriber.complete();
|
|
261
|
+
}
|
|
262
|
+
if (opt?.validate && !this.validateContext(context)) {
|
|
263
|
+
if (!opt.resolve) {
|
|
264
|
+
/** cannot resolve context, and provided is invalid */
|
|
265
|
+
this.#event?.dispatchEvent('onSetContextValidationFailed', {
|
|
181
266
|
source: this,
|
|
182
|
-
cancelable: true,
|
|
183
267
|
detail: { context },
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
if (onSetContextResolve?.canceled) {
|
|
187
|
-
throw Error('resolving of context was canceled');
|
|
268
|
+
});
|
|
269
|
+
return subscriber.error(Error('failed to validate provided context'));
|
|
188
270
|
}
|
|
271
|
+
if (opt.resolve) {
|
|
272
|
+
return of(context)
|
|
273
|
+
.pipe(
|
|
274
|
+
/** notify event observers that context is about to get resolved */
|
|
275
|
+
switchMap(async (context) => {
|
|
276
|
+
const event = await this.#event?.dispatchEvent(
|
|
277
|
+
'onSetContextResolve',
|
|
278
|
+
{
|
|
279
|
+
source: this,
|
|
280
|
+
cancelable: true,
|
|
281
|
+
detail: { context },
|
|
282
|
+
}
|
|
283
|
+
);
|
|
284
|
+
if (event?.canceled) {
|
|
285
|
+
throw Error('resolving of context was canceled');
|
|
286
|
+
}
|
|
287
|
+
return context;
|
|
288
|
+
}),
|
|
289
|
+
/** execute resolve */
|
|
290
|
+
switchMap((context) =>
|
|
291
|
+
this.resolveContext(context).pipe(
|
|
292
|
+
map((resolved) => ({
|
|
293
|
+
context,
|
|
294
|
+
resolved,
|
|
295
|
+
}))
|
|
296
|
+
)
|
|
297
|
+
),
|
|
298
|
+
/** notify event observers that context was resolved */
|
|
299
|
+
switchMap(async ({ context, resolved }) => {
|
|
300
|
+
const event = await this.#event?.dispatchEvent(
|
|
301
|
+
'onSetContextResolved',
|
|
302
|
+
{
|
|
303
|
+
source: this,
|
|
304
|
+
cancelable: true,
|
|
305
|
+
detail: { context, resolved },
|
|
306
|
+
}
|
|
307
|
+
);
|
|
308
|
+
if (event?.canceled) {
|
|
309
|
+
throw Error('resolving of context was canceled');
|
|
310
|
+
}
|
|
311
|
+
return resolved;
|
|
312
|
+
}),
|
|
313
|
+
/** recursive set current context without validation and resolve */
|
|
314
|
+
switchMap((resolved) => this.setCurrentContext(resolved))
|
|
315
|
+
)
|
|
316
|
+
.subscribe(subscriber);
|
|
317
|
+
}
|
|
318
|
+
}
|
|
189
319
|
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
'onSetContextResolved',
|
|
195
|
-
{
|
|
320
|
+
return of(context)
|
|
321
|
+
.pipe(
|
|
322
|
+
switchMap(async (context) => {
|
|
323
|
+
const event = await this.#event?.dispatchEvent('onCurrentContextChange', {
|
|
196
324
|
source: this,
|
|
325
|
+
canBubble: true,
|
|
197
326
|
cancelable: true,
|
|
198
|
-
detail: { context
|
|
327
|
+
detail: { context: context },
|
|
328
|
+
});
|
|
329
|
+
|
|
330
|
+
if (event?.canceled) {
|
|
331
|
+
throw Error('change of context was aborted');
|
|
199
332
|
}
|
|
200
|
-
);
|
|
201
|
-
if (onSetContextResolved?.canceled) {
|
|
202
|
-
throw Error('resolving of context was canceled');
|
|
203
|
-
}
|
|
204
|
-
return this.setCurrentContext(resolved);
|
|
205
|
-
} catch (error) {
|
|
206
|
-
console.error('failed to resolve context', context, error);
|
|
207
|
-
this.#event?.dispatchEvent('onSetContextResolveFailed', {
|
|
208
|
-
source: this,
|
|
209
|
-
detail: { context, error },
|
|
210
|
-
});
|
|
211
|
-
}
|
|
212
|
-
}
|
|
213
|
-
this.#event?.dispatchEvent('onSetContextValidationFailed', {
|
|
214
|
-
source: this,
|
|
215
|
-
detail: { context },
|
|
216
|
-
});
|
|
217
|
-
throw Error('failed to validate provided context');
|
|
218
|
-
}
|
|
219
333
|
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
334
|
+
return context;
|
|
335
|
+
})
|
|
336
|
+
)
|
|
337
|
+
.subscribe((context) => {
|
|
338
|
+
this.#contextClient.setCurrentContext(context);
|
|
339
|
+
subscriber.next(context);
|
|
340
|
+
subscriber.complete();
|
|
341
|
+
});
|
|
225
342
|
});
|
|
343
|
+
}
|
|
226
344
|
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
}
|
|
230
|
-
|
|
231
|
-
this
|
|
232
|
-
|
|
233
|
-
return context;
|
|
345
|
+
public async setCurrentContextAsync(
|
|
346
|
+
context: ContextItem<Record<string, unknown>>,
|
|
347
|
+
opt?: { validate?: boolean; resolve?: boolean }
|
|
348
|
+
): Promise<ContextItem<Record<string, unknown>>> {
|
|
349
|
+
return firstValueFrom(this.setCurrentContext(context, opt));
|
|
234
350
|
}
|
|
235
351
|
|
|
236
352
|
public queryContext(search: string): Observable<Array<ContextItem>> {
|
|
@@ -308,6 +424,7 @@ export class ContextProvider implements IContextProvider {
|
|
|
308
424
|
|
|
309
425
|
dispose() {
|
|
310
426
|
this.#subscriptions.unsubscribe();
|
|
427
|
+
this.#contextClient.dispose();
|
|
311
428
|
}
|
|
312
429
|
}
|
|
313
430
|
|
|
@@ -47,6 +47,10 @@ export class ContextClient extends Observable<ContextItem> {
|
|
|
47
47
|
public resolveContext(id: string): Observable<ContextItem> {
|
|
48
48
|
return this.#client.query({ id }).pipe(map((x) => x.value));
|
|
49
49
|
}
|
|
50
|
+
|
|
51
|
+
public dispose(): void {
|
|
52
|
+
this.#currentContext$.complete();
|
|
53
|
+
}
|
|
50
54
|
}
|
|
51
55
|
|
|
52
56
|
export default ContextClient;
|
package/src/configurator.ts
CHANGED
|
@@ -21,6 +21,9 @@ export interface ContextModuleConfig {
|
|
|
21
21
|
contextType?: string[];
|
|
22
22
|
contextFilter?: ContextFilterFn;
|
|
23
23
|
|
|
24
|
+
/** set initial context from parent, will await resolve */
|
|
25
|
+
skipInitialContext?: boolean;
|
|
26
|
+
|
|
24
27
|
/**
|
|
25
28
|
* Method for generating context query parameters.
|
|
26
29
|
*/
|
package/src/module.ts
CHANGED
|
@@ -23,8 +23,21 @@ export const module: ContextModule = {
|
|
|
23
23
|
initialize: async (args) => {
|
|
24
24
|
const config = await (args.config as ContextModuleConfigurator).createConfig(args);
|
|
25
25
|
const event = args.hasModule('event') ? await args.requireInstance('event') : undefined;
|
|
26
|
-
const
|
|
27
|
-
|
|
26
|
+
const parentProvider = (args.ref as ModulesInstance<[ContextModule]>)?.context;
|
|
27
|
+
const provider = new ContextProvider({ config, event, parentContext: parentProvider });
|
|
28
|
+
|
|
29
|
+
// TODO add option for skipping this step
|
|
30
|
+
if (parentProvider) {
|
|
31
|
+
try {
|
|
32
|
+
await provider.connectParentContextAsync(parentProvider, {
|
|
33
|
+
setCurrent: !config.skipInitialContext,
|
|
34
|
+
});
|
|
35
|
+
} catch (err) {
|
|
36
|
+
console.warn('provider.connectParentContext', 'failed to set parent context', err);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
return provider;
|
|
28
41
|
},
|
|
29
42
|
|
|
30
43
|
dispose: (args) => {
|