@equinor/fusion-framework-module-context 4.1.1 → 4.2.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.
@@ -1,2 +1,3 @@
1
1
  export { enableContext } from './enable-context';
2
2
  export { resolveInitialContext } from './resolve-initial-context';
3
+ export { extractContextIdFromPath, resolveContextFromPath } from './resolve-context-from-path';
@@ -1,8 +1,17 @@
1
- import { ModuleType } from '@equinor/fusion-framework-module';
1
+ import { Observable } from 'rxjs';
2
+ import { type ModuleType } from '@equinor/fusion-framework-module';
2
3
  import { type ContextModule } from '../module';
4
+ import { type ContextItem } from '../types';
3
5
  export type ContextPathResolveArgs = {
4
6
  extract?: (path: string) => string | undefined;
5
7
  validate?: (contextId: string) => boolean;
6
8
  };
7
- export declare const resolveContextFromPath: (context: ModuleType<ContextModule>, args?: ContextPathResolveArgs) => (path: string) => import("rxjs").Observable<import("..").ContextItem>;
9
+ export declare const extractContextIdFromPath: (path: string, matcher?: RegExp) => string | undefined;
10
+ export interface resolveContextFromPath {
11
+ (context: ModuleType<ContextModule>): (path: string) => Observable<ContextItem>;
12
+ }
13
+ export interface resolveContextFromPath {
14
+ (context: ModuleType<ContextModule>, args: ContextPathResolveArgs): (path: string) => Observable<ContextItem>;
15
+ }
16
+ export declare function resolveContextFromPath(context: ModuleType<ContextModule>, args?: ContextPathResolveArgs): (path: string) => Observable<ContextItem>;
8
17
  export default resolveContextFromPath;
@@ -1,5 +1,5 @@
1
1
  import { type ContextModuleConfig } from '../configurator';
2
- import { ContextPathResolveArgs } from './resolve-context-from-path';
2
+ import { type ContextPathResolveArgs } from './resolve-context-from-path';
3
3
  export declare const resolveContextFromParent: ContextModuleConfig['resolveInitialContext'];
4
4
  export declare const resolveInitialContext: (options?: {
5
5
  path?: ContextPathResolveArgs;
@@ -1 +1 @@
1
- export declare const version = "4.1.1";
1
+ export declare const version = "4.2.0";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@equinor/fusion-framework-module-context",
3
- "version": "4.1.1",
3
+ "version": "4.2.0",
4
4
  "description": "",
5
5
  "main": "./dist/esm/index.js",
6
6
  "exports": {
@@ -51,8 +51,8 @@
51
51
  "rxjs": "^7.8.1",
52
52
  "typescript": "^5.1.3",
53
53
  "@equinor/fusion-framework-module": "^4.2.7",
54
- "@equinor/fusion-framework-module-navigation": "^3.1.4",
55
54
  "@equinor/fusion-framework-module-event": "^4.0.8",
55
+ "@equinor/fusion-framework-module-navigation": "^3.1.4",
56
56
  "@equinor/fusion-framework-module-services": "^3.2.4"
57
57
  },
58
58
  "peerDependencies": {
@@ -1,2 +1,3 @@
1
1
  export { enableContext } from './enable-context';
2
2
  export { resolveInitialContext } from './resolve-initial-context';
3
+ export { extractContextIdFromPath, resolveContextFromPath } from './resolve-context-from-path';
@@ -1,24 +1,116 @@
1
- import { EMPTY } from 'rxjs';
1
+ import { EMPTY, Observable } from 'rxjs';
2
2
 
3
- import { ModuleType } from '@equinor/fusion-framework-module';
3
+ import { type ModuleType } from '@equinor/fusion-framework-module';
4
4
 
5
5
  import { type ContextModule } from '../module';
6
+ import { type ContextItem } from '../types';
6
7
 
8
+ /**
9
+ * Arguments for resolving a context from a path.
10
+ */
7
11
  export type ContextPathResolveArgs = {
12
+ /**
13
+ * Callback to extract a context id from a path.
14
+ * @param path string - the path to extract the context id from
15
+ * @returns string | undefined - the context id or undefined
16
+ */
8
17
  extract?: (path: string) => string | undefined;
18
+ /**
19
+ * Callback to validate a context id.
20
+ * @param contextId string - the context id to validate
21
+ * @returns boolean - true if the context id is valid
22
+ */
9
23
  validate?: (contextId: string) => boolean;
10
24
  };
11
25
 
26
+ // GUID pattern
12
27
  const matchGUID =
13
28
  /^(?:(?:[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
29
 
15
- const extractContextIdFromPath = (path: string): string | undefined =>
16
- path.replace(/^\/+/, '').split('/').shift();
30
+ /**
31
+ * Method will try to extract a context id from a path.
32
+ * The default matcher is a GUID pattern.
33
+ * Will iterate over the path and return the first match.
34
+ *
35
+ * @example
36
+ * ```ts
37
+ * const path = '/apps/context/7fd97952-7fe6-409b-a6dc-292dbf0e50d7?dsadasdas#example';
38
+ * const contextId = extractContextIdFromPath(path); // '7fd97952-7fe6-409b-a6dc-292dbf0e50d7'
39
+ * ```
40
+ *
41
+ * @param path string - the path to extract the context id from
42
+ * @param matcher RegExp - the pattern to match against
43
+ * @returns string | undefined - the context id or undefined
44
+ */
45
+ export const extractContextIdFromPath = (
46
+ path: string,
47
+ matcher: RegExp = matchGUID,
48
+ ): string | undefined =>
49
+ path
50
+ // remove leading slashes
51
+ .replace(/^\/+/, '')
52
+ // split path by slashes
53
+ .split('/')
54
+ // find the first path fragment that matches the matcher
55
+ .find((x) => x.match(matcher));
17
56
 
18
57
  const validateContextId = (contextId: string): boolean => !!contextId.match(matchGUID);
19
58
 
20
- export const resolveContextFromPath =
21
- (context: ModuleType<ContextModule>, args?: ContextPathResolveArgs) => (path: string) => {
59
+ /**
60
+ * Method will try to resolve a context from a path.
61
+ * The method will return a function that takes a path and returns an observable of the resolved context.
62
+ * The method will use the context module to resolve the context.
63
+ * The method will use the extract and validate methods from the args to extract and validate the context id.
64
+ * If the context id is not valid, the method will throw an error.
65
+ * If the context id is valid, the method will return an observable of the resolved context.
66
+ * If the context id is not found, the method will return an empty observable.
67
+ *
68
+ * @example
69
+ * ```ts
70
+ * const resolve = resolveContextFromPath(modules.context);
71
+ * resolve(
72
+ * '/apps/context/7fd97952-7fe6-409b-a6dc-292dbf0e50d7?foobar#example'
73
+ * ).subscribe(console.log);
74
+ * ```
75
+ *
76
+ * @param context The context module.
77
+ * @returns A function that takes a path and returns an Observable of the resolved context item.
78
+ */
79
+ export interface resolveContextFromPath {
80
+ (context: ModuleType<ContextModule>): (path: string) => Observable<ContextItem>;
81
+ }
82
+
83
+ /**
84
+ *
85
+ * @example
86
+ * ```ts
87
+ * const resolve = resolveContextFromPath(
88
+ * modules.context,
89
+ * {
90
+ * extract: (path) => path.find(extractingContextFromPath),
91
+ * validate: (id) => isValidContextId(id)
92
+ * });
93
+ * resolve(
94
+ * '/apps/context/7fd97952-7fe6-409b-a6dc-292dbf0e50d7?foobar#example'
95
+ * ).subscribe(console.log);
96
+ * ```
97
+ *
98
+ * @param context The context module.
99
+ * @param args The arguments for resolving the path.
100
+ * @returns A function that takes a path and returns an Observable of the resolved context item.
101
+ */
102
+ export interface resolveContextFromPath {
103
+ (
104
+ context: ModuleType<ContextModule>,
105
+ args: ContextPathResolveArgs,
106
+ ): (path: string) => Observable<ContextItem>;
107
+ }
108
+
109
+ export function resolveContextFromPath(
110
+ context: ModuleType<ContextModule>,
111
+ args?: ContextPathResolveArgs,
112
+ ) {
113
+ return (path: string) => {
22
114
  const { extract = extractContextIdFromPath, validate = validateContextId } = args ?? {};
23
115
  const contextId = extract(path);
24
116
  if (!contextId) {
@@ -30,5 +122,6 @@ export const resolveContextFromPath =
30
122
 
31
123
  throw Error(`Failed to validate context [${contextId}] from path [${path}]`);
32
124
  };
125
+ }
33
126
 
34
127
  export default resolveContextFromPath;
@@ -1,27 +1,50 @@
1
- import { ModulesInstance } from '@equinor/fusion-framework-module';
2
- import { ContextModule } from '../module';
1
+ import { type ModulesInstance } from '@equinor/fusion-framework-module';
2
+ import { type ContextModule } from '../module';
3
3
  import { type ContextModuleConfig } from '../configurator';
4
4
  import { concat, EMPTY, first, of } from 'rxjs';
5
5
 
6
- import { ContextPathResolveArgs, resolveContextFromPath } from './resolve-context-from-path';
6
+ import { type ContextPathResolveArgs, resolveContextFromPath } from './resolve-context-from-path';
7
+ import { type NavigationModule } from '@equinor/fusion-framework-module-navigation';
7
8
 
9
+ /**
10
+ * Resolves the initial context from the parent module.
11
+ *
12
+ * @param ref - parent modules.
13
+ * @returns An Observable of the resolved initial context.
14
+ */
8
15
  export const resolveContextFromParent: ContextModuleConfig['resolveInitialContext'] = ({ ref }) => {
9
16
  const parentContext = (ref as ModulesInstance<[ContextModule]>)?.context;
17
+ // check if the parent has context module
10
18
  if (!parentContext) {
11
19
  throw Error(['resolveContextFromNavigation', 'ref does not support context!'].join('\n'));
12
20
  }
21
+ // return the current context from the parent or empty if the parent does not have a context
13
22
  return parentContext.currentContext ? of(parentContext.currentContext) : EMPTY;
14
23
  };
15
24
 
25
+ /**
26
+ * Resolves the initial context for a Fusion Framework context module.
27
+ *
28
+ * will try to resolve the initial context from the path, and if that fails, it will try to resolve the context from the parent.
29
+ *
30
+ * @param options - Optional configuration for resolving the context path.
31
+ * @returns A function that accepts the module's reference and modules, and returns an Observable of the resolved initial context.
32
+ */
16
33
  export const resolveInitialContext =
17
34
  (options?: {
18
35
  path?: ContextPathResolveArgs;
19
36
  }): Required<ContextModuleConfig>['resolveInitialContext'] =>
20
37
  ({ ref, modules }) => {
21
38
  const { context, navigation } = modules;
39
+ // create a path resolver from the context module
22
40
  const pathResolver = resolveContextFromPath(context, options?.path);
41
+ // use the path from the navigation module, or the path from the parent navigation module
42
+ const pathname =
43
+ navigation?.path.pathname ??
44
+ (ref as Partial<ModulesInstance<[NavigationModule]>>).navigation?.path.pathname;
45
+ // try to resolve the context from the path, and if that fails, try to resolve the context from the parent
23
46
  return concat(
24
- navigation ? pathResolver(navigation.path.pathname) : EMPTY,
47
+ pathname ? pathResolver(pathname) : EMPTY,
25
48
  resolveContextFromParent({ ref, modules }),
26
49
  ).pipe(first());
27
50
  };
package/src/version.ts CHANGED
@@ -1,2 +1,2 @@
1
1
  // Generated by genversion.
2
- export const version = '4.1.1';
2
+ export const version = '4.2.0';