@equinor/fusion-framework-module-context 0.0.0-context-error-20240131144633
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 +522 -0
- package/LICENSE +21 -0
- package/dist/esm/ContextConfigBuilder.js +79 -0
- package/dist/esm/ContextConfigBuilder.js.map +1 -0
- package/dist/esm/ContextProvider.js +279 -0
- package/dist/esm/ContextProvider.js.map +1 -0
- package/dist/esm/client/ContextClient.js +62 -0
- package/dist/esm/client/ContextClient.js.map +1 -0
- package/dist/esm/configurator.js +86 -0
- package/dist/esm/configurator.js.map +1 -0
- package/dist/esm/errors.js +26 -0
- package/dist/esm/errors.js.map +1 -0
- package/dist/esm/index.js +6 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/esm/module.js +55 -0
- package/dist/esm/module.js.map +1 -0
- package/dist/esm/selectors.js +44 -0
- package/dist/esm/selectors.js.map +1 -0
- package/dist/esm/types.js +2 -0
- package/dist/esm/types.js.map +1 -0
- package/dist/esm/utils/enable-context.js +10 -0
- package/dist/esm/utils/enable-context.js.map +1 -0
- package/dist/esm/utils/index.js +3 -0
- package/dist/esm/utils/index.js.map +1 -0
- package/dist/esm/utils/resolve-context-from-path.js +17 -0
- package/dist/esm/utils/resolve-context-from-path.js.map +1 -0
- package/dist/esm/utils/resolve-initial-context.js +16 -0
- package/dist/esm/utils/resolve-initial-context.js.map +1 -0
- package/dist/esm/version.js +2 -0
- package/dist/esm/version.js.map +1 -0
- package/dist/tsconfig.tsbuildinfo +1 -0
- package/dist/types/ContextConfigBuilder.d.ts +25 -0
- package/dist/types/ContextProvider.d.ts +99 -0
- package/dist/types/client/ContextClient.d.ts +22 -0
- package/dist/types/configurator.d.ts +41 -0
- package/dist/types/errors.d.ts +8 -0
- package/dist/types/index.d.ts +5 -0
- package/dist/types/module.d.ts +20 -0
- package/dist/types/selectors.d.ts +4 -0
- package/dist/types/types.d.ts +34 -0
- package/dist/types/utils/enable-context.d.ts +4 -0
- package/dist/types/utils/index.d.ts +2 -0
- package/dist/types/utils/resolve-context-from-path.d.ts +8 -0
- package/dist/types/utils/resolve-initial-context.d.ts +7 -0
- package/dist/types/version.d.ts +1 -0
- package/package.json +65 -0
- package/src/ContextConfigBuilder.ts +131 -0
- package/src/ContextProvider.ts +555 -0
- package/src/client/ContextClient.ts +71 -0
- package/src/configurator.ts +158 -0
- package/src/errors.ts +19 -0
- package/src/index.ts +18 -0
- package/src/module.ts +91 -0
- package/src/selectors.ts +41 -0
- package/src/types.ts +33 -0
- package/src/utils/enable-context.ts +31 -0
- package/src/utils/index.ts +2 -0
- package/src/utils/resolve-context-from-path.ts +34 -0
- package/src/utils/resolve-initial-context.ts +29 -0
- package/src/version.ts +2 -0
- package/tsconfig.json +33 -0
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
import { ObservableInput } from 'rxjs';
|
|
2
|
+
|
|
3
|
+
import {
|
|
4
|
+
AnyModuleInstance,
|
|
5
|
+
ModuleInitializerArgs,
|
|
6
|
+
ModuleInstance,
|
|
7
|
+
ModulesInstanceType,
|
|
8
|
+
} from '@equinor/fusion-framework-module';
|
|
9
|
+
import { ServicesModule, IApiProvider } from '@equinor/fusion-framework-module-services';
|
|
10
|
+
import { NavigationModule } from '@equinor/fusion-framework-module-navigation';
|
|
11
|
+
import { getContextSelector, queryContextSelector, relatedContextSelector } from './selectors';
|
|
12
|
+
import { QueryCtorOptions } from '@equinor/fusion-query';
|
|
13
|
+
import {
|
|
14
|
+
ContextFilterFn,
|
|
15
|
+
ContextItem,
|
|
16
|
+
QueryContextParameters,
|
|
17
|
+
RelatedContextParameters,
|
|
18
|
+
} from './types';
|
|
19
|
+
import { GetContextParameters } from './client/ContextClient';
|
|
20
|
+
import { ContextConfigBuilder, ContextConfigBuilderCallback } from './ContextConfigBuilder';
|
|
21
|
+
import { type IContextProvider } from './ContextProvider';
|
|
22
|
+
import resolveInitialContext from './utils/resolve-initial-context';
|
|
23
|
+
|
|
24
|
+
export interface ContextModuleConfig {
|
|
25
|
+
client: {
|
|
26
|
+
get: QueryCtorOptions<ContextItem, GetContextParameters>;
|
|
27
|
+
query: QueryCtorOptions<ContextItem[], QueryContextParameters>;
|
|
28
|
+
related?: QueryCtorOptions<ContextItem[], RelatedContextParameters>;
|
|
29
|
+
};
|
|
30
|
+
contextType?: string[];
|
|
31
|
+
contextFilter?: ContextFilterFn;
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* connect context module to paren context module.
|
|
35
|
+
*
|
|
36
|
+
* _default: `true`_
|
|
37
|
+
*/
|
|
38
|
+
connectParentContext?: boolean;
|
|
39
|
+
|
|
40
|
+
/** set initial context from parent, will await resolve */
|
|
41
|
+
skipInitialContext?: boolean;
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Method for generating context query parameters.
|
|
45
|
+
*/
|
|
46
|
+
contextParameterFn?: (args: {
|
|
47
|
+
search: string;
|
|
48
|
+
type: ContextModuleConfig['contextType'];
|
|
49
|
+
}) => string | QueryContextParameters;
|
|
50
|
+
|
|
51
|
+
resolveContext?: (
|
|
52
|
+
this: IContextProvider,
|
|
53
|
+
item: ContextItem | null,
|
|
54
|
+
) => ReturnType<IContextProvider['resolveContext']>;
|
|
55
|
+
|
|
56
|
+
validateContext?: (
|
|
57
|
+
this: IContextProvider,
|
|
58
|
+
item: ContextItem | null,
|
|
59
|
+
) => ReturnType<IContextProvider['validateContext']>;
|
|
60
|
+
|
|
61
|
+
resolveInitialContext?: (args: {
|
|
62
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
63
|
+
ref?: AnyModuleInstance | any;
|
|
64
|
+
modules: ModuleInstance;
|
|
65
|
+
}) => ObservableInput<ContextItem | void>;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
export interface IContextModuleConfigurator {
|
|
69
|
+
addConfigBuilder: (init: ContextConfigBuilderCallback) => void;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
export class ContextModuleConfigurator implements IContextModuleConfigurator {
|
|
73
|
+
defaultExpireTime = 1 * 60 * 1000;
|
|
74
|
+
|
|
75
|
+
#configBuilders: Array<ContextConfigBuilderCallback> = [];
|
|
76
|
+
|
|
77
|
+
addConfigBuilder(init: ContextConfigBuilderCallback): void {
|
|
78
|
+
this.#configBuilders.push(init);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
protected async _getServiceProvider(
|
|
82
|
+
init: ModuleInitializerArgs<IContextModuleConfigurator, [ServicesModule]>,
|
|
83
|
+
): Promise<IApiProvider> {
|
|
84
|
+
if (init.hasModule('services')) {
|
|
85
|
+
return init.requireInstance('services');
|
|
86
|
+
} else {
|
|
87
|
+
const parentServiceModule = (init.ref as ModulesInstanceType<[ServicesModule]>)
|
|
88
|
+
?.services;
|
|
89
|
+
if (parentServiceModule) {
|
|
90
|
+
return parentServiceModule;
|
|
91
|
+
}
|
|
92
|
+
throw Error('no service services provider configures [ServicesModule]');
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
public async createConfig(
|
|
97
|
+
init: ModuleInitializerArgs<IContextModuleConfigurator, [ServicesModule, NavigationModule]>,
|
|
98
|
+
): Promise<ContextModuleConfig> {
|
|
99
|
+
const config = await this.#configBuilders.reduce(
|
|
100
|
+
async (cur, cb) => {
|
|
101
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
102
|
+
const builder = new ContextConfigBuilder<any, any>(init, await cur);
|
|
103
|
+
await Promise.resolve(cb(builder));
|
|
104
|
+
return Object.assign(cur, builder.config);
|
|
105
|
+
},
|
|
106
|
+
Promise.resolve({} as Partial<ContextModuleConfig>),
|
|
107
|
+
);
|
|
108
|
+
|
|
109
|
+
config.resolveInitialContext ??= resolveInitialContext();
|
|
110
|
+
|
|
111
|
+
// TODO - make less lazy
|
|
112
|
+
config.client ??= await (async (): Promise<ContextModuleConfig['client']> => {
|
|
113
|
+
const apiProvider = await this._getServiceProvider(init);
|
|
114
|
+
const contextClient = await apiProvider.createContextClient('json$');
|
|
115
|
+
return {
|
|
116
|
+
get: {
|
|
117
|
+
client: {
|
|
118
|
+
fn: (args) =>
|
|
119
|
+
contextClient.get('v1', args, { selector: getContextSelector }),
|
|
120
|
+
},
|
|
121
|
+
key: ({ id }) => id,
|
|
122
|
+
expire: this.defaultExpireTime,
|
|
123
|
+
},
|
|
124
|
+
query: {
|
|
125
|
+
client: {
|
|
126
|
+
fn: (query) =>
|
|
127
|
+
contextClient.query(
|
|
128
|
+
'v1',
|
|
129
|
+
{ query },
|
|
130
|
+
{ selector: queryContextSelector },
|
|
131
|
+
),
|
|
132
|
+
},
|
|
133
|
+
// TODO - might cast to checksum
|
|
134
|
+
key: (args) => JSON.stringify(args),
|
|
135
|
+
expire: this.defaultExpireTime,
|
|
136
|
+
},
|
|
137
|
+
related: {
|
|
138
|
+
client: {
|
|
139
|
+
fn: (args) => {
|
|
140
|
+
return contextClient.related(
|
|
141
|
+
'v1',
|
|
142
|
+
{ id: args.item.id, query: { filter: args.filter } },
|
|
143
|
+
{ selector: relatedContextSelector },
|
|
144
|
+
);
|
|
145
|
+
},
|
|
146
|
+
},
|
|
147
|
+
// TODO - might cast to checksum
|
|
148
|
+
key: (args) => JSON.stringify(args),
|
|
149
|
+
expire: this.defaultExpireTime,
|
|
150
|
+
},
|
|
151
|
+
};
|
|
152
|
+
})();
|
|
153
|
+
|
|
154
|
+
return config as ContextModuleConfig;
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
export default ContextModuleConfigurator;
|
package/src/errors.ts
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
export class FusionContextSearchError extends Error {
|
|
2
|
+
#details;
|
|
3
|
+
|
|
4
|
+
get title(): string {
|
|
5
|
+
return this.#details.title;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
constructor(
|
|
9
|
+
details: {
|
|
10
|
+
title: string;
|
|
11
|
+
description?: string;
|
|
12
|
+
},
|
|
13
|
+
options?: ErrorOptions,
|
|
14
|
+
) {
|
|
15
|
+
super(details.description ?? details.title, options);
|
|
16
|
+
this.#details = details;
|
|
17
|
+
this.name = 'FusionContextSearchError';
|
|
18
|
+
}
|
|
19
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export {
|
|
2
|
+
ContextModuleConfigurator,
|
|
3
|
+
IContextModuleConfigurator,
|
|
4
|
+
ContextModuleConfig,
|
|
5
|
+
} from './configurator';
|
|
6
|
+
|
|
7
|
+
export { IContextProvider, ContextProvider } from './ContextProvider';
|
|
8
|
+
|
|
9
|
+
export {
|
|
10
|
+
default,
|
|
11
|
+
ContextModule,
|
|
12
|
+
module as contextModule,
|
|
13
|
+
moduleKey as contextModuleKey,
|
|
14
|
+
} from './module';
|
|
15
|
+
|
|
16
|
+
export { enableContext } from './utils/enable-context';
|
|
17
|
+
|
|
18
|
+
export * from './types';
|
package/src/module.ts
ADDED
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import { catchError, EMPTY, from, Observable, switchMap, filter, Subscription } from 'rxjs';
|
|
2
|
+
|
|
3
|
+
import { Module, ModulesInstance } from '@equinor/fusion-framework-module';
|
|
4
|
+
|
|
5
|
+
import { EventModule } from '@equinor/fusion-framework-module-event';
|
|
6
|
+
import { ServicesModule } from '@equinor/fusion-framework-module-services';
|
|
7
|
+
import { NavigationModule } from '@equinor/fusion-framework-module-navigation';
|
|
8
|
+
|
|
9
|
+
import { IContextModuleConfigurator, ContextModuleConfigurator } from './configurator';
|
|
10
|
+
import { IContextProvider, ContextProvider } from './ContextProvider';
|
|
11
|
+
import { ContextItem } from './types';
|
|
12
|
+
|
|
13
|
+
export type ContextModuleKey = 'context';
|
|
14
|
+
|
|
15
|
+
export const moduleKey: ContextModuleKey = 'context';
|
|
16
|
+
|
|
17
|
+
export type ContextModule = Module<
|
|
18
|
+
ContextModuleKey,
|
|
19
|
+
IContextProvider,
|
|
20
|
+
IContextModuleConfigurator,
|
|
21
|
+
[ServicesModule, EventModule, NavigationModule]
|
|
22
|
+
>;
|
|
23
|
+
|
|
24
|
+
export const module: ContextModule = {
|
|
25
|
+
name: moduleKey,
|
|
26
|
+
configure: () => new ContextModuleConfigurator(),
|
|
27
|
+
initialize: async function (args) {
|
|
28
|
+
const config = await (args.config as ContextModuleConfigurator).createConfig(args);
|
|
29
|
+
const event = args.hasModule('event') ? await args.requireInstance('event') : undefined;
|
|
30
|
+
const parentProvider = (args.ref as ModulesInstance<[ContextModule]>)?.context;
|
|
31
|
+
const provider = new ContextProvider({ config, event, parentContext: parentProvider });
|
|
32
|
+
|
|
33
|
+
const subscription = new Subscription(() => provider.dispose());
|
|
34
|
+
|
|
35
|
+
this.postInitialize = (args) =>
|
|
36
|
+
new Observable((subscriber) => {
|
|
37
|
+
const resolveInitialContext$ = config.resolveInitialContext
|
|
38
|
+
? from(config.resolveInitialContext(args)).pipe(
|
|
39
|
+
filter((item): item is ContextItem => !!item),
|
|
40
|
+
switchMap((item) =>
|
|
41
|
+
args.modules.context.setCurrentContext(item, {
|
|
42
|
+
validate: true,
|
|
43
|
+
resolve: true,
|
|
44
|
+
}),
|
|
45
|
+
),
|
|
46
|
+
)
|
|
47
|
+
: EMPTY;
|
|
48
|
+
|
|
49
|
+
subscriber.add(
|
|
50
|
+
resolveInitialContext$
|
|
51
|
+
.pipe(
|
|
52
|
+
catchError((err) => {
|
|
53
|
+
console.warn(
|
|
54
|
+
'ContextModule.postInitialize',
|
|
55
|
+
'failed to resolve initial context',
|
|
56
|
+
err,
|
|
57
|
+
);
|
|
58
|
+
return EMPTY;
|
|
59
|
+
}),
|
|
60
|
+
)
|
|
61
|
+
.subscribe({
|
|
62
|
+
next: (item) => {
|
|
63
|
+
console.debug(
|
|
64
|
+
'ContextModule.postInitialize',
|
|
65
|
+
`initial context was resolved to [${item ? item.id : 'none'}]`,
|
|
66
|
+
item,
|
|
67
|
+
);
|
|
68
|
+
},
|
|
69
|
+
complete: () => {
|
|
70
|
+
if (config.connectParentContext !== false && parentProvider) {
|
|
71
|
+
provider.connectParentContext(parentProvider);
|
|
72
|
+
}
|
|
73
|
+
subscriber.complete();
|
|
74
|
+
},
|
|
75
|
+
}),
|
|
76
|
+
);
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
this.dispose = () => subscription.unsubscribe();
|
|
80
|
+
|
|
81
|
+
return provider;
|
|
82
|
+
},
|
|
83
|
+
};
|
|
84
|
+
|
|
85
|
+
declare module '@equinor/fusion-framework-module' {
|
|
86
|
+
interface Modules {
|
|
87
|
+
context: ContextModule;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
export default module;
|
package/src/selectors.ts
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { ApiVersion, ApiContextEntity } from '@equinor/fusion-framework-module-services/context';
|
|
2
|
+
import type { GetContextResponse } from '@equinor/fusion-framework-module-services/context/get';
|
|
3
|
+
import type { QueryContextResponse } from '@equinor/fusion-framework-module-services/context/query';
|
|
4
|
+
import type { RelatedContextResponse } from '@equinor/fusion-framework-module-services/context/related';
|
|
5
|
+
import type { ContextItem, ContextItemType } from './types';
|
|
6
|
+
|
|
7
|
+
const parseContextType = (type: GetContextResponse<'v1'>['type']): ContextItemType => ({
|
|
8
|
+
id: type.id,
|
|
9
|
+
isChildType: type.isChildType,
|
|
10
|
+
parentTypeIds: type.parentTypeIds ?? [],
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
const parseContextItem = (item: ApiContextEntity<ApiVersion.v1>): ContextItem => {
|
|
14
|
+
return {
|
|
15
|
+
id: item.id,
|
|
16
|
+
externalId: item.externalId ?? undefined,
|
|
17
|
+
isActive: item.isActive,
|
|
18
|
+
isDeleted: item.isDeleted,
|
|
19
|
+
created: new Date(item.created),
|
|
20
|
+
source: item.source ?? undefined,
|
|
21
|
+
title: item.title ?? undefined,
|
|
22
|
+
type: parseContextType(item.type),
|
|
23
|
+
// TODO
|
|
24
|
+
value: item.value ?? {},
|
|
25
|
+
};
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
export const getContextSelector = async (response: Response): Promise<ContextItem> => {
|
|
29
|
+
const result = (await response.json()) as GetContextResponse<'v1'>;
|
|
30
|
+
return parseContextItem(result);
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
export const queryContextSelector = async (response: Response): Promise<ContextItem[]> => {
|
|
34
|
+
const result = (await response.json()) as QueryContextResponse<'v1'>;
|
|
35
|
+
return result.map(parseContextItem);
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
export const relatedContextSelector = async (response: Response): Promise<ContextItem[]> => {
|
|
39
|
+
const result = (await response.json()) as RelatedContextResponse<'v1'>;
|
|
40
|
+
return result.map(parseContextItem);
|
|
41
|
+
};
|
package/src/types.ts
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
export type ContextItem<TType extends Record<string, unknown> = Record<string, unknown>> = {
|
|
2
|
+
id: string;
|
|
3
|
+
externalId?: string;
|
|
4
|
+
source?: string;
|
|
5
|
+
type: ContextItemType;
|
|
6
|
+
value: TType;
|
|
7
|
+
title?: string;
|
|
8
|
+
subTitle?: string;
|
|
9
|
+
isActive?: boolean;
|
|
10
|
+
isDeleted?: boolean;
|
|
11
|
+
created?: Date;
|
|
12
|
+
updated?: Date;
|
|
13
|
+
graphic?: string;
|
|
14
|
+
meta?: string;
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
export interface ContextItemType {
|
|
18
|
+
id: string;
|
|
19
|
+
isChildType?: boolean;
|
|
20
|
+
parentTypeIds?: string[];
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export type QueryContextParameters = {
|
|
24
|
+
search?: string;
|
|
25
|
+
filter?: {
|
|
26
|
+
type?: string[];
|
|
27
|
+
externalId?: string;
|
|
28
|
+
};
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
export type RelatedContextParameters = { item: ContextItem; filter?: { type?: string[] } };
|
|
32
|
+
|
|
33
|
+
export type ContextFilterFn = (items: ContextItem[]) => ContextItem[];
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
IModulesConfigurator,
|
|
3
|
+
AnyModule,
|
|
4
|
+
ModuleInitializerArgs,
|
|
5
|
+
} from '@equinor/fusion-framework-module';
|
|
6
|
+
import type { IContextModuleConfigurator } from '../configurator';
|
|
7
|
+
import type { ContextConfigBuilder } from '../ContextConfigBuilder';
|
|
8
|
+
|
|
9
|
+
import { module } from '../module';
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Method for enabling the Service module
|
|
13
|
+
* @param configurator - configuration object
|
|
14
|
+
*/
|
|
15
|
+
export const enableContext = (
|
|
16
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
17
|
+
configurator: IModulesConfigurator<any, any>,
|
|
18
|
+
builder?: <TDeps extends Array<AnyModule> = []>(
|
|
19
|
+
builder: ContextConfigBuilder<
|
|
20
|
+
TDeps,
|
|
21
|
+
ModuleInitializerArgs<IContextModuleConfigurator, TDeps>
|
|
22
|
+
>,
|
|
23
|
+
) => void | Promise<void>,
|
|
24
|
+
): void => {
|
|
25
|
+
configurator.addConfig({
|
|
26
|
+
module,
|
|
27
|
+
configure: (contextConfigurator) => {
|
|
28
|
+
builder && contextConfigurator.addConfigBuilder(builder);
|
|
29
|
+
},
|
|
30
|
+
});
|
|
31
|
+
};
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { EMPTY } from 'rxjs';
|
|
2
|
+
|
|
3
|
+
import { ModuleType } from '@equinor/fusion-framework-module';
|
|
4
|
+
|
|
5
|
+
import { type ContextModule } from '../module';
|
|
6
|
+
|
|
7
|
+
export type ContextPathResolveArgs = {
|
|
8
|
+
extract?: (path: string) => string | undefined;
|
|
9
|
+
validate?: (contextId: string) => boolean;
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
const matchGUID =
|
|
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
|
+
|
|
15
|
+
const extractContextIdFromPath = (path: string): string | undefined =>
|
|
16
|
+
path.replace(/^\/+/, '').split('/').shift();
|
|
17
|
+
|
|
18
|
+
const validateContextId = (contextId: string): boolean => !!contextId.match(matchGUID);
|
|
19
|
+
|
|
20
|
+
export const resolveContextFromPath =
|
|
21
|
+
(context: ModuleType<ContextModule>, args?: ContextPathResolveArgs) => (path: string) => {
|
|
22
|
+
const { extract = extractContextIdFromPath, validate = validateContextId } = args ?? {};
|
|
23
|
+
const contextId = extract(path);
|
|
24
|
+
if (!contextId) {
|
|
25
|
+
return EMPTY;
|
|
26
|
+
}
|
|
27
|
+
if (validate(contextId)) {
|
|
28
|
+
return context.contextClient.resolveContext(contextId);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
throw Error(`Failed to validate context [${contextId}] from path [${path}]`);
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
export default resolveContextFromPath;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { ModulesInstance } from '@equinor/fusion-framework-module';
|
|
2
|
+
import { ContextModule } from '../module';
|
|
3
|
+
import { type ContextModuleConfig } from '../configurator';
|
|
4
|
+
import { concat, EMPTY, first, of } from 'rxjs';
|
|
5
|
+
|
|
6
|
+
import { ContextPathResolveArgs, resolveContextFromPath } from './resolve-context-from-path';
|
|
7
|
+
|
|
8
|
+
export const resolveContextFromParent: ContextModuleConfig['resolveInitialContext'] = ({ ref }) => {
|
|
9
|
+
const parentContext = (ref as ModulesInstance<[ContextModule]>)?.context;
|
|
10
|
+
if (!parentContext) {
|
|
11
|
+
throw Error(['resolveContextFromNavigation', 'ref does not support context!'].join('\n'));
|
|
12
|
+
}
|
|
13
|
+
return parentContext.currentContext ? of(parentContext.currentContext) : EMPTY;
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
export const resolveInitialContext =
|
|
17
|
+
(options?: {
|
|
18
|
+
path?: ContextPathResolveArgs;
|
|
19
|
+
}): Required<ContextModuleConfig>['resolveInitialContext'] =>
|
|
20
|
+
({ ref, modules }) => {
|
|
21
|
+
const { context, navigation } = modules;
|
|
22
|
+
const pathResolver = resolveContextFromPath(context, options?.path);
|
|
23
|
+
return concat(
|
|
24
|
+
navigation ? pathResolver(navigation.path.pathname) : EMPTY,
|
|
25
|
+
resolveContextFromParent({ ref, modules }),
|
|
26
|
+
).pipe(first());
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
export default resolveInitialContext;
|
package/src/version.ts
ADDED
package/tsconfig.json
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
{
|
|
2
|
+
"extends": "../../../tsconfig.base.json",
|
|
3
|
+
"compilerOptions": {
|
|
4
|
+
"outDir": "dist/esm",
|
|
5
|
+
"rootDir": "src",
|
|
6
|
+
"declarationDir": "./dist/types",
|
|
7
|
+
|
|
8
|
+
},
|
|
9
|
+
"references": [
|
|
10
|
+
{
|
|
11
|
+
"path": "../../utils/query"
|
|
12
|
+
},
|
|
13
|
+
{
|
|
14
|
+
"path": "../module"
|
|
15
|
+
},
|
|
16
|
+
{
|
|
17
|
+
"path": "../navigation"
|
|
18
|
+
},
|
|
19
|
+
{
|
|
20
|
+
"path": "../event"
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
"path": "../services"
|
|
24
|
+
},
|
|
25
|
+
],
|
|
26
|
+
"include": [
|
|
27
|
+
"src/**/*",
|
|
28
|
+
],
|
|
29
|
+
"exclude": [
|
|
30
|
+
"node_modules",
|
|
31
|
+
"dist"
|
|
32
|
+
]
|
|
33
|
+
}
|