@equinor/fusion-framework-module-context 4.0.0-next.12 → 4.0.0-next.13

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.
@@ -8,8 +8,8 @@ import Query from '@equinor/fusion-query';
8
8
  export interface IContextProvider {
9
9
  readonly contextClient: ContextClient;
10
10
  readonly queryClient: Query<ContextItem[], QueryContextParameters>;
11
- readonly currentContext$: Observable<ContextItem | undefined>;
12
- currentContext: ContextItem | undefined;
11
+ readonly currentContext$: Observable<ContextItem | null | undefined>;
12
+ currentContext: ContextItem | null | undefined;
13
13
  queryContext(search: string): Observable<Array<ContextItem>>;
14
14
  queryContextAsync(search: string): Promise<Array<ContextItem>>;
15
15
  validateContext(item: ContextItem<Record<string, unknown>>): boolean;
@@ -20,22 +20,22 @@ export interface IContextProvider {
20
20
  clearCurrentContext: VoidFunction;
21
21
  setCurrentContextById(id: string): Observable<ContextItem<Record<string, unknown>>>;
22
22
  setCurrentContextByIdAsync(id: string): Promise<ContextItem<Record<string, unknown>>>;
23
- setCurrentContext(context: ContextItem<Record<string, unknown>>, opt?: {
23
+ setCurrentContext(context: ContextItem<Record<string, unknown>> | null, opt?: {
24
24
  validate?: boolean;
25
25
  resolve?: boolean;
26
- }): Observable<ContextItem<Record<string, unknown>>>;
27
- setCurrentContextAsync(context: ContextItem<Record<string, unknown>>, opt?: {
26
+ }): Observable<ContextItem<Record<string, unknown>> | null>;
27
+ setCurrentContextAsync(context: ContextItem<Record<string, unknown>> | null, opt?: {
28
28
  validate?: boolean;
29
29
  resolve?: boolean;
30
- }): Promise<ContextItem<Record<string, unknown>>>;
30
+ }): Promise<ContextItem<Record<string, unknown>> | null>;
31
31
  }
32
32
  export declare class ContextProvider implements IContextProvider {
33
33
  #private;
34
34
  get contextClient(): ContextClient;
35
35
  get queryClient(): Query<ContextItem<Record<string, unknown>>[], QueryContextParameters>;
36
- get currentContext$(): Observable<ContextItem | undefined>;
37
- get currentContext(): ContextItem | undefined;
38
- set currentContext(context: ContextItem | undefined);
36
+ get currentContext$(): Observable<ContextItem | null | undefined>;
37
+ get currentContext(): ContextItem | undefined | null;
38
+ set currentContext(context: ContextItem | null | undefined);
39
39
  constructor(args: {
40
40
  config: ContextModuleConfig;
41
41
  event?: ModuleType<EventModule>;
@@ -46,14 +46,14 @@ export declare class ContextProvider implements IContextProvider {
46
46
  }): Subscription;
47
47
  setCurrentContextById(id: string): Observable<ContextItem<Record<string, unknown>>>;
48
48
  setCurrentContextByIdAsync(id: string): Promise<ContextItem<Record<string, unknown>>>;
49
- setCurrentContext(context: ContextItem<Record<string, unknown>>, opt?: {
49
+ setCurrentContext<T extends ContextItem<Record<string, unknown>> | null>(context: T, opt?: {
50
50
  validate?: boolean;
51
51
  resolve?: boolean;
52
- }): Observable<ContextItem<Record<string, unknown>>>;
53
- setCurrentContextAsync(context: ContextItem<Record<string, unknown>>, opt?: {
52
+ }): Observable<T>;
53
+ setCurrentContextAsync<T extends ContextItem<Record<string, unknown>> | null>(context: T, opt?: {
54
54
  validate?: boolean;
55
55
  resolve?: boolean;
56
- }): Promise<ContextItem<Record<string, unknown>>>;
56
+ }): Promise<T>;
57
57
  queryContext(search: string): Observable<Array<ContextItem>>;
58
58
  queryContextAsync(search: string): Promise<Array<ContextItem>>;
59
59
  validateContext(item: ContextItem<Record<string, unknown>>): boolean;
@@ -68,14 +68,14 @@ export default ContextProvider;
68
68
  declare module '@equinor/fusion-framework-module-event' {
69
69
  interface FrameworkEventMap {
70
70
  onCurrentContextChange: FrameworkEvent<FrameworkEventInit<{
71
- context: ContextItem | undefined;
71
+ context: ContextItem | null;
72
72
  }, IContextProvider>>;
73
73
  onCurrentContextChanged: FrameworkEvent<FrameworkEventInit<{
74
- next: ContextItem | undefined;
75
- previous: ContextItem | undefined;
74
+ next: ContextItem | null;
75
+ previous?: ContextItem | null;
76
76
  }, IContextProvider>>;
77
77
  onParentContextChanged: FrameworkEvent<FrameworkEventInit<{
78
- context: ContextItem | undefined;
78
+ context: ContextItem | null;
79
79
  }, IContextProvider>>;
80
80
  onSetContextResolve: FrameworkEvent<FrameworkEventInit<{
81
81
  context: ContextItem;
@@ -4,15 +4,15 @@ import { ContextItem } from '../types';
4
4
  export type GetContextParameters = {
5
5
  id: string;
6
6
  };
7
- export declare class ContextClient extends Observable<ContextItem> {
7
+ export declare class ContextClient extends Observable<ContextItem | null> {
8
8
  #private;
9
- get currentContext(): ContextItem | undefined;
10
- get currentContext$(): Observable<ContextItem | undefined>;
9
+ get currentContext(): ContextItem | null | undefined;
10
+ get currentContext$(): Observable<ContextItem | null | undefined>;
11
11
  get client(): Query<ContextItem, {
12
12
  id: string;
13
13
  }>;
14
14
  constructor(options: QueryCtorOptions<ContextItem, GetContextParameters>);
15
- setCurrentContext(idOrItem?: string | ContextItem): void;
15
+ setCurrentContext(idOrItem?: string | ContextItem | null): void;
16
16
  resolveContext(id: string): Observable<ContextItem>;
17
17
  resolveContextAsync(id: string, opt?: {
18
18
  awaitResolve: boolean;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@equinor/fusion-framework-module-context",
3
- "version": "4.0.0-next.12",
3
+ "version": "4.0.0-next.13",
4
4
  "description": "",
5
5
  "main": "./dist/esm/index.js",
6
6
  "exports": {
@@ -35,19 +35,19 @@
35
35
  "directory": "packages/modules/context"
36
36
  },
37
37
  "dependencies": {
38
- "@equinor/fusion-query": "^3.0.1-next.3",
38
+ "@equinor/fusion-query": "^3.0.1-next.4",
39
39
  "fast-deep-equal": "^3.1.3"
40
40
  },
41
41
  "devDependencies": {
42
- "@equinor/fusion-framework-module": "^4.0.0-next.0",
43
- "@equinor/fusion-framework-module-event": "^4.0.0-next.0",
44
- "@equinor/fusion-framework-module-navigation": "^2.1.0-next.0",
45
- "@equinor/fusion-framework-module-services": "^3.1.0-next.4",
42
+ "@equinor/fusion-framework-module": "^4.0.0-next.1",
43
+ "@equinor/fusion-framework-module-event": "^4.0.0-next.1",
44
+ "@equinor/fusion-framework-module-navigation": "^2.1.0-next.1",
45
+ "@equinor/fusion-framework-module-services": "^3.1.0-next.5",
46
46
  "rxjs": "^7.5.7"
47
47
  },
48
48
  "peerDependencies": {
49
49
  "@equinor/fusion-framework-module": ">=1.2.5",
50
50
  "rxjs": "^7.5.7"
51
51
  },
52
- "gitHead": "a2d5050515d375c7546b321aba27d11239869d97"
52
+ "gitHead": "4e9c1d4fffaf455043b1fcf40a48744092f0cc71"
53
53
  }
@@ -31,8 +31,8 @@ export interface IContextProvider {
31
31
  /** DANGER */
32
32
  readonly queryClient: Query<ContextItem[], QueryContextParameters>;
33
33
 
34
- readonly currentContext$: Observable<ContextItem | undefined>;
35
- currentContext: ContextItem | undefined;
34
+ readonly currentContext$: Observable<ContextItem | null | undefined>;
35
+ currentContext: ContextItem | null | undefined;
36
36
  queryContext(search: string): Observable<Array<ContextItem>>;
37
37
  queryContextAsync(search: string): Promise<Array<ContextItem>>;
38
38
  validateContext(item: ContextItem<Record<string, unknown>>): boolean;
@@ -50,14 +50,14 @@ export interface IContextProvider {
50
50
  setCurrentContextByIdAsync(id: string): Promise<ContextItem<Record<string, unknown>>>;
51
51
 
52
52
  setCurrentContext(
53
- context: ContextItem<Record<string, unknown>>,
53
+ context: ContextItem<Record<string, unknown>> | null,
54
54
  opt?: { validate?: boolean; resolve?: boolean }
55
- ): Observable<ContextItem<Record<string, unknown>>>;
55
+ ): Observable<ContextItem<Record<string, unknown>> | null>;
56
56
 
57
57
  setCurrentContextAsync(
58
- context: ContextItem<Record<string, unknown>>,
58
+ context: ContextItem<Record<string, unknown>> | null,
59
59
  opt?: { validate?: boolean; resolve?: boolean }
60
- ): Promise<ContextItem<Record<string, unknown>>>;
60
+ ): Promise<ContextItem<Record<string, unknown>> | null>;
61
61
  }
62
62
 
63
63
  export class ContextProvider implements IContextProvider {
@@ -81,22 +81,25 @@ export class ContextProvider implements IContextProvider {
81
81
  return this.#contextQuery;
82
82
  }
83
83
 
84
- get currentContext$(): Observable<ContextItem | undefined> {
84
+ get currentContext$(): Observable<ContextItem | null | undefined> {
85
85
  return this.#contextClient.currentContext$;
86
86
  }
87
87
 
88
- get currentContext(): ContextItem | undefined {
88
+ get currentContext(): ContextItem | undefined | null {
89
89
  return this.#contextClient.currentContext;
90
90
  }
91
91
 
92
92
  /** @deprecated do not use, will be removed */
93
- set currentContext(context: ContextItem | undefined) {
93
+ set currentContext(context: ContextItem | null | undefined) {
94
94
  console.warn(
95
95
  '@deprecated',
96
96
  'ContextProvider.currentContext',
97
97
  'use setCurrentContextById|setCurrentContext|clearCurrentContext'
98
98
  );
99
- context ? this.setCurrentContextAsync(context) : this.clearCurrentContext();
99
+ if (context === undefined) {
100
+ throw Error('not allowed to set current context as undefined undefined!');
101
+ }
102
+ this.setCurrentContextAsync(context);
100
103
  }
101
104
 
102
105
  constructor(args: {
@@ -150,8 +153,8 @@ export class ContextProvider implements IContextProvider {
150
153
  /** observe event from child modules */
151
154
  this.#event.addEventListener('onCurrentContextChanged', (e) => {
152
155
  /** loop prevention */
153
- if (e.source !== this) {
154
- this.currentContext = e.detail.next;
156
+ if (e.source !== this && e.detail.next !== undefined) {
157
+ this.setCurrentContext(e.detail.next);
155
158
  }
156
159
  })
157
160
  );
@@ -224,7 +227,10 @@ export class ContextProvider implements IContextProvider {
224
227
  try {
225
228
  this.#contextClient
226
229
  .resolveContext(id)
227
- .pipe(switchMap((item) => this.setCurrentContext(item)))
230
+ .pipe(
231
+ filter((item): item is ContextItem => !!item),
232
+ switchMap((item) => this.setCurrentContext(item))
233
+ )
228
234
  .subscribe(subscriber);
229
235
  } catch (err) {
230
236
  subscriber.error(err);
@@ -236,16 +242,16 @@ export class ContextProvider implements IContextProvider {
236
242
  return firstValueFrom(this.setCurrentContextById(id));
237
243
  }
238
244
 
239
- public setCurrentContext(
240
- context: ContextItem<Record<string, unknown>>,
245
+ public setCurrentContext<T extends ContextItem<Record<string, unknown>> | null>(
246
+ context: T,
241
247
  opt?: { validate?: boolean; resolve?: boolean }
242
- ): Observable<ContextItem<Record<string, unknown>>> {
248
+ ): Observable<T> {
243
249
  return new Observable((subscriber) => {
244
250
  if (context === this.currentContext) {
245
251
  subscriber.next(context);
246
252
  return subscriber.complete();
247
253
  }
248
- if (opt?.validate && !this.validateContext(context)) {
254
+ if (context && opt?.validate && !this.validateContext(context)) {
249
255
  if (!opt.resolve) {
250
256
  /** cannot resolve context, and provided is invalid */
251
257
  this.#event?.dispatchEvent('onSetContextValidationFailed', {
@@ -297,7 +303,9 @@ export class ContextProvider implements IContextProvider {
297
303
  return resolved;
298
304
  }),
299
305
  /** recursive set current context without validation and resolve */
300
- switchMap((resolved) => this.setCurrentContext(resolved))
306
+ switchMap((resolved) =>
307
+ this.setCurrentContext(resolved as unknown as T)
308
+ )
301
309
  )
302
310
  .subscribe(subscriber);
303
311
  }
@@ -321,17 +329,17 @@ export class ContextProvider implements IContextProvider {
321
329
  })
322
330
  )
323
331
  .subscribe((context) => {
324
- this.#contextClient.setCurrentContext(context);
332
+ this.#contextClient.setCurrentContext(context ?? null);
325
333
  subscriber.next(context);
326
334
  subscriber.complete();
327
335
  });
328
336
  });
329
337
  }
330
338
 
331
- public async setCurrentContextAsync(
332
- context: ContextItem<Record<string, unknown>>,
339
+ public async setCurrentContextAsync<T extends ContextItem<Record<string, unknown>> | null>(
340
+ context: T,
333
341
  opt?: { validate?: boolean; resolve?: boolean }
334
- ): Promise<ContextItem<Record<string, unknown>>> {
342
+ ): Promise<T> {
335
343
  return firstValueFrom(this.setCurrentContext(context, opt));
336
344
  }
337
345
 
@@ -413,7 +421,7 @@ export class ContextProvider implements IContextProvider {
413
421
  }
414
422
 
415
423
  public clearCurrentContext() {
416
- this.#contextClient.setCurrentContext(undefined);
424
+ this.setCurrentContextAsync(null);
417
425
  }
418
426
 
419
427
  dispose() {
@@ -430,7 +438,7 @@ declare module '@equinor/fusion-framework-module-event' {
430
438
  onCurrentContextChange: FrameworkEvent<
431
439
  FrameworkEventInit<
432
440
  {
433
- context: ContextItem | undefined;
441
+ context: ContextItem | null;
434
442
  },
435
443
  IContextProvider
436
444
  >
@@ -439,8 +447,8 @@ declare module '@equinor/fusion-framework-module-event' {
439
447
  onCurrentContextChanged: FrameworkEvent<
440
448
  FrameworkEventInit<
441
449
  {
442
- next: ContextItem | undefined;
443
- previous: ContextItem | undefined;
450
+ next: ContextItem | null;
451
+ previous?: ContextItem | null;
444
452
  },
445
453
  IContextProvider
446
454
  >
@@ -448,7 +456,7 @@ declare module '@equinor/fusion-framework-module-event' {
448
456
  onParentContextChanged: FrameworkEvent<
449
457
  FrameworkEventInit<
450
458
  {
451
- context: ContextItem | undefined;
459
+ context: ContextItem | null;
452
460
  },
453
461
  IContextProvider
454
462
  >
@@ -9,16 +9,16 @@ import { ContextItem } from '../types';
9
9
 
10
10
  export type GetContextParameters = { id: string };
11
11
 
12
- export class ContextClient extends Observable<ContextItem> {
12
+ export class ContextClient extends Observable<ContextItem | null> {
13
13
  #client: Query<ContextItem, { id: string }>;
14
14
  /** might change to reactive state, for comparing state with reducer */
15
- #currentContext$: BehaviorSubject<ContextItem | undefined>;
15
+ #currentContext$: BehaviorSubject<ContextItem | null | undefined>;
16
16
 
17
- get currentContext(): ContextItem | undefined {
17
+ get currentContext(): ContextItem | null | undefined {
18
18
  return this.#currentContext$.value;
19
19
  }
20
20
 
21
- get currentContext$(): Observable<ContextItem | undefined> {
21
+ get currentContext$(): Observable<ContextItem | null | undefined> {
22
22
  return this.#currentContext$.asObservable();
23
23
  }
24
24
 
@@ -29,10 +29,10 @@ export class ContextClient extends Observable<ContextItem> {
29
29
  constructor(options: QueryCtorOptions<ContextItem, GetContextParameters>) {
30
30
  super((observer) => this.#currentContext$.subscribe(observer));
31
31
  this.#client = new Query(options);
32
- this.#currentContext$ = new BehaviorSubject<ContextItem | undefined>(undefined);
32
+ this.#currentContext$ = new BehaviorSubject<ContextItem | null | undefined>(undefined);
33
33
  }
34
34
 
35
- public setCurrentContext(idOrItem?: string | ContextItem) {
35
+ public setCurrentContext(idOrItem?: string | ContextItem | null) {
36
36
  if (typeof idOrItem === 'string') {
37
37
  // TODO - compare context
38
38
  this.resolveContext(idOrItem)
package/src/module.ts CHANGED
@@ -1,3 +1,5 @@
1
+ import { catchError, EMPTY, from, Observable, switchMap, filter, Subscription } from 'rxjs';
2
+
1
3
  import { Module, ModulesInstance } from '@equinor/fusion-framework-module';
2
4
 
3
5
  import { EventModule } from '@equinor/fusion-framework-module-event';
@@ -6,7 +8,6 @@ import { NavigationModule } from '@equinor/fusion-framework-module-navigation';
6
8
 
7
9
  import { IContextModuleConfigurator, ContextModuleConfigurator } from './configurator';
8
10
  import { IContextProvider, ContextProvider } from './ContextProvider';
9
- import { catchError, EMPTY, from, Observable, switchMap, filter, Subscription } from 'rxjs';
10
11
  import { ContextItem } from 'types';
11
12
 
12
13
  export type ContextModuleKey = 'context';
@@ -61,7 +62,7 @@ export const module: ContextModule = {
61
62
  next: (item) => {
62
63
  console.debug(
63
64
  'ContextModule.postInitialize',
64
- `initial context was resolved to [${item.id}]`,
65
+ `initial context was resolved to [${item ? item.id : 'none'}]`,
65
66
  item
66
67
  );
67
68
  },
@@ -71,25 +72,6 @@ export const module: ContextModule = {
71
72
  },
72
73
  })
73
74
  );
74
-
75
- if (args.modules.navigation) {
76
- subscription.add(
77
- provider.currentContext$.subscribe((item) => {
78
- if (!item) {
79
- return args.modules.navigation.replace('/');
80
- }
81
- const { path } = args.modules.navigation;
82
- const partial = path.pathname.split('/') ?? [];
83
- if (partial[0] !== item.id) {
84
- partial[0] = item?.id;
85
- args.modules.navigation.replace({
86
- ...path,
87
- pathname: partial.join('/'),
88
- });
89
- }
90
- })
91
- );
92
- }
93
75
  });
94
76
 
95
77
  this.dispose = () => subscription.unsubscribe();
@@ -12,7 +12,8 @@ export type ContextPathResolveArgs = {
12
12
  const matchGUID =
13
13
  /^(?:(?:[0-9a-fA-F]){8}-(?:[0-9a-fA-F]){4}-(?:[0-9a-fA-F]){4}-(?:[0-9a-fA-F]){4}-(?:[0-9a-fA-F]){12})$/;
14
14
 
15
- const extractContextIdFromPath = (path: string): string | undefined => path.split('/')[0];
15
+ const extractContextIdFromPath = (path: string): string | undefined =>
16
+ path.replace(/^\/+/, '').split('/').shift();
16
17
 
17
18
  const validateContextId = (contextId: string): boolean => !!contextId.match(matchGUID);
18
19
 
@@ -22,7 +22,7 @@ export const resolveInitialContext =
22
22
  const pathResolver = resolveContextFromPath(context, options?.path);
23
23
  return concat(
24
24
  navigation ? pathResolver(navigation.path.pathname) : EMPTY,
25
- resolveContextFromParent(ref)
25
+ resolveContextFromParent({ ref, modules })
26
26
  ).pipe(first());
27
27
  };
28
28