Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

@equinor/fusion-framework-module-context

Package Overview
Dependencies
Maintainers
4
Versions
146
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@equinor/fusion-framework-module-context - npm Package Compare versions

Comparing version 2.0.15 to 3.0.0

6

CHANGELOG.md

@@ -6,2 +6,8 @@ # Change Log

## 3.0.0 (2023-04-16)
### Features
- **modules/context:** resolve related context ([0e92583](https://github.com/equinor/fusion-framework/commit/0e925837a4f2651ff9f2a003d13731f6d866412d))
## 2.0.15 (2023-04-14)

@@ -8,0 +14,0 @@

11

dist/esm/configurator.js

@@ -16,3 +16,3 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {

var _ContextModuleConfigurator_configBuilders;
import { getContextSelector, queryContextSelector } from './selectors';
import { getContextSelector, queryContextSelector, relatedContextSelector } from './selectors';
import { ContextConfigBuilder } from './ContextConfigBuilder';

@@ -68,2 +68,11 @@ export class ContextModuleConfigurator {

},
related: {
client: {
fn: (args) => {
return contextClient.related('v1', { id: args.item.id, query: { filter: args.filter } }, { selector: relatedContextSelector });
},
},
key: (args) => JSON.stringify(args),
expire: this.defaultExpireTime,
},
};

@@ -70,0 +79,0 @@ }))());

@@ -31,2 +31,8 @@ var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {

}
setValidateContext(fn) {
this.config.validateContext = fn;
}
setResolveContext(fn) {
this.config.resolveContext = fn;
}
setContextClient(client, expire = 1 * 60 * 1000) {

@@ -53,2 +59,14 @@ this.config.client = {

};
if (client.related) {
this.config.client.related =
typeof client.related === 'function'
? {
key: (args) => JSON.stringify(args),
client: {
fn: client.related,
},
expire,
}
: client.related;
}
}

@@ -55,0 +73,0 @@ }

@@ -0,1 +1,10 @@

var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {

@@ -12,5 +21,5 @@ if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");

};
var _ContextProvider_contextClient, _ContextProvider_contextQuery, _ContextProvider_event, _ContextProvider_subscriptions, _ContextProvider_contextType, _ContextProvider_contextFilter, _ContextProvider_contextParameterFn;
import { lastValueFrom, Subscription } from 'rxjs';
import { map, pairwise } from 'rxjs/operators';
var _ContextProvider_contextClient, _ContextProvider_contextQuery, _ContextProvider_contextRelated, _ContextProvider_event, _ContextProvider_subscriptions, _ContextProvider_contextType, _ContextProvider_contextFilter, _ContextProvider_contextParameterFn;
import { lastValueFrom, Subscription, throwError } from 'rxjs';
import { filter, map, pairwise, switchMap } from 'rxjs/operators';
import { ContextClient } from './client/ContextClient';

@@ -32,24 +41,9 @@ import Query from '@equinor/fusion-query';

set currentContext(context) {
if (__classPrivateFieldGet(this, _ContextProvider_event, "f")) {
__classPrivateFieldGet(this, _ContextProvider_event, "f")
.dispatchEvent('onCurrentContextChange', {
source: this,
canBubble: true,
cancelable: true,
detail: { context },
})
.then((e) => {
if (!e.canceled) {
__classPrivateFieldGet(this, _ContextProvider_contextClient, "f").setCurrentContext(context);
}
});
}
else {
__classPrivateFieldGet(this, _ContextProvider_contextClient, "f").setCurrentContext(context);
}
context ? this.setCurrentContext(context) : this.clearCurrentContext();
}
constructor(args) {
var _a;
var _a, _b, _c;
_ContextProvider_contextClient.set(this, void 0);
_ContextProvider_contextQuery.set(this, void 0);
_ContextProvider_contextRelated.set(this, void 0);
_ContextProvider_event.set(this, void 0);

@@ -61,2 +55,4 @@ _ContextProvider_subscriptions.set(this, new Subscription());

const { config, event, parentContext } = args;
config.resolveContext && (this.resolveContext = (_a = config.resolveContext) === null || _a === void 0 ? void 0 : _a.bind(this));
config.validateContext && (this.validateContext = (_b = config.validateContext) === null || _b === void 0 ? void 0 : _b.bind(this));
__classPrivateFieldSet(this, _ContextProvider_contextType, config.contextType, "f");

@@ -66,3 +62,6 @@ __classPrivateFieldSet(this, _ContextProvider_contextFilter, config.contextFilter, "f");

__classPrivateFieldSet(this, _ContextProvider_contextQuery, new Query(config.client.query), "f");
__classPrivateFieldSet(this, _ContextProvider_contextParameterFn, (_a = config.contextParameterFn) !== null && _a !== void 0 ? _a : ((args) => ({
if (config.client.related) {
__classPrivateFieldSet(this, _ContextProvider_contextRelated, new Query(config.client.related), "f");
}
__classPrivateFieldSet(this, _ContextProvider_contextParameterFn, (_c = config.contextParameterFn) !== null && _c !== void 0 ? _c : ((args) => ({
search: args.search,

@@ -89,5 +88,81 @@ filter: { type: args.type },

if (parentContext) {
__classPrivateFieldGet(this, _ContextProvider_subscriptions, "f").add(parentContext.contextClient.currentContext$.subscribe((next) => (this.currentContext = next)));
__classPrivateFieldGet(this, _ContextProvider_subscriptions, "f").add(parentContext.contextClient.currentContext$
.pipe(switchMap((next) => __awaiter(this, void 0, void 0, function* () {
var _d;
if (next) {
const onParentContextChanged = yield ((_d = __classPrivateFieldGet(this, _ContextProvider_event, "f")) === null || _d === void 0 ? void 0 : _d.dispatchEvent('onParentContextChanged', {
source: this,
detail: next,
cancelable: true,
}));
return { next, canceled: onParentContextChanged === null || onParentContextChanged === void 0 ? void 0 : onParentContextChanged.canceled };
}
return { next };
})), filter((x) => !x.canceled), map(({ next }) => next))
.subscribe((next) => {
if (next) {
try {
this.setCurrentContext(next, {
validate: true,
resolve: true,
});
}
catch (err) {
console.warn('ContextProvider::onParentContextChanged', err);
}
}
else {
this.clearCurrentContext();
}
}));
}
}
setCurrentContext(context, opt) {
var _a, _b, _c;
return __awaiter(this, void 0, void 0, function* () {
if (context === this.currentContext) {
return context;
}
if ((opt === null || opt === void 0 ? void 0 : opt.validate) && !this.validateContext(context)) {
if (opt.resolve) {
const onSetContextResolve = yield ((_a = __classPrivateFieldGet(this, _ContextProvider_event, "f")) === null || _a === void 0 ? void 0 : _a.dispatchEvent('onSetContextResolve', {
source: this,
cancelable: true,
detail: { context },
}));
if (onSetContextResolve === null || onSetContextResolve === void 0 ? void 0 : onSetContextResolve.canceled) {
throw Error('resolving of context was canceled');
}
try {
const resolvedContext = yield this.resolveContextAsync(context);
const onSetContextResolved = yield ((_b = __classPrivateFieldGet(this, _ContextProvider_event, "f")) === null || _b === void 0 ? void 0 : _b.dispatchEvent('onSetContextResolved', {
source: this,
cancelable: true,
detail: { input: context, result: resolvedContext },
}));
if (onSetContextResolved === null || onSetContextResolved === void 0 ? void 0 : onSetContextResolved.canceled) {
throw Error('resolving of context was canceled');
}
return this.setCurrentContext(resolvedContext);
}
catch (err) {
console.error('failed to resolve context', context, err);
this.clearCurrentContext();
}
}
throw Error('failed to validate provided context');
}
const onCurrentContextChange = yield ((_c = __classPrivateFieldGet(this, _ContextProvider_event, "f")) === null || _c === void 0 ? void 0 : _c.dispatchEvent('onCurrentContextChange', {
source: this,
canBubble: true,
cancelable: true,
detail: { context: context },
}));
if (onCurrentContextChange === null || onCurrentContextChange === void 0 ? void 0 : onCurrentContextChange.canceled) {
throw Error('change of context was aborted');
}
__classPrivateFieldGet(this, _ContextProvider_contextClient, "f").setCurrentContext(context);
return context;
});
}
queryContext(search) {

@@ -102,4 +177,33 @@ const query$ = this.queryClient

}
validateContext(item) {
if (!__classPrivateFieldGet(this, _ContextProvider_contextType, "f"))
return true;
return __classPrivateFieldGet(this, _ContextProvider_contextType, "f").map((x) => x.toLowerCase()).includes(item.type.id.toLowerCase());
}
resolveContext(item) {
return this.relatedContexts({ item, filter: { type: __classPrivateFieldGet(this, _ContextProvider_contextType, "f") } }).pipe(map((x) => x.filter((item) => this.validateContext(item))), map((values) => {
const value = values.shift();
if (!value) {
throw Error('failed to resolve context');
}
if (values.length) {
console.warn('ContextProvider::relatedContext', 'multiple items found 🤣', values);
}
return value;
}));
}
resolveContextAsync(item) {
return lastValueFrom(this.resolveContext(item));
}
relatedContexts(args) {
if (!__classPrivateFieldGet(this, _ContextProvider_contextRelated, "f")) {
return throwError(() => Error('ContextProvider::relatedContexts - no client defined for resolving related context'));
}
return __classPrivateFieldGet(this, _ContextProvider_contextRelated, "f").query(args).pipe(map(({ value }) => value));
}
relatedContextsAsync(args) {
return lastValueFrom(this.relatedContexts(args));
}
clearCurrentContext() {
this.currentContext = undefined;
__classPrivateFieldGet(this, _ContextProvider_contextClient, "f").setCurrentContext(undefined);
}

@@ -110,4 +214,4 @@ dispose() {

}
_ContextProvider_contextClient = new WeakMap(), _ContextProvider_contextQuery = new WeakMap(), _ContextProvider_event = new WeakMap(), _ContextProvider_subscriptions = new WeakMap(), _ContextProvider_contextType = new WeakMap(), _ContextProvider_contextFilter = new WeakMap(), _ContextProvider_contextParameterFn = new WeakMap();
_ContextProvider_contextClient = new WeakMap(), _ContextProvider_contextQuery = new WeakMap(), _ContextProvider_contextRelated = new WeakMap(), _ContextProvider_event = new WeakMap(), _ContextProvider_subscriptions = new WeakMap(), _ContextProvider_contextType = new WeakMap(), _ContextProvider_contextFilter = new WeakMap(), _ContextProvider_contextParameterFn = new WeakMap();
export default ContextProvider;
//# sourceMappingURL=ContextProvider.js.map

@@ -40,2 +40,6 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {

});
export const relatedContextSelector = (response) => __awaiter(void 0, void 0, void 0, function* () {
const result = (yield response.json());
return result.map(parseContextItem);
});
//# sourceMappingURL=selectors.js.map
import { ModuleInitializerArgs } from '@equinor/fusion-framework-module';
import { ServicesModule, IApiProvider } from '@equinor/fusion-framework-module-services';
import { QueryCtorOptions } from '@equinor/fusion-query';
import { ContextFilterFn, ContextItem, QueryContextParameters } from './types';
import { ContextFilterFn, ContextItem, QueryContextParameters, RelatedContextParameters } from './types';
import { GetContextParameters } from './client/ContextClient';
import { ContextConfigBuilderCallback } from './ContextConfigBuilder';
import { IContextProvider } from 'ContextProvider';
export interface ContextModuleConfig {

@@ -11,2 +12,3 @@ client: {

query: QueryCtorOptions<ContextItem[], QueryContextParameters>;
related?: QueryCtorOptions<ContextItem[], RelatedContextParameters>;
};

@@ -19,2 +21,4 @@ contextType?: string[];

}) => string | QueryContextParameters;
resolveContext?: (this: IContextProvider, item: ContextItem | null) => ReturnType<IContextProvider['resolveContext']>;
validateContext?: (this: IContextProvider, item: ContextItem | null) => ReturnType<IContextProvider['validateContext']>;
}

@@ -21,0 +25,0 @@ export interface IContextModuleConfigurator {

5

dist/types/ContextConfigBuilder.d.ts

@@ -5,3 +5,3 @@ import type { AnyModule, ModuleInitializerArgs, Modules, ModuleType } from '@equinor/fusion-framework-module';

import type { ContextModuleConfig, ContextModuleConfigurator, IContextModuleConfigurator } from './configurator';
import type { ContextItem, QueryContextParameters } from './types';
import type { ContextItem, QueryContextParameters, RelatedContextParameters } from './types';
export type ContextConfigBuilderCallback = <TDeps extends Array<AnyModule> = []>(builder: ContextConfigBuilder<TDeps, ModuleInitializerArgs<IContextModuleConfigurator, TDeps>>) => void | Promise<void>;

@@ -17,6 +17,9 @@ export declare class ContextConfigBuilder<TModules extends Array<AnyModule> = [], TInit extends ModuleInitializerArgs<any, any> = ModuleInitializerArgs<ContextModuleConfigurator, TModules>> {

setContextParameterFn(fn: ContextModuleConfig['contextParameterFn']): void;
setValidateContext(fn: ContextModuleConfig['validateContext']): void;
setResolveContext(fn: ContextModuleConfig['resolveContext']): void;
setContextClient(client: {
get: QueryFn<ContextItem, GetContextParameters> | QueryCtorOptions<ContextItem, GetContextParameters>;
query: QueryFn<ContextItem[], QueryContextParameters> | QueryCtorOptions<ContextItem[], QueryContextParameters>;
related?: QueryFn<ContextItem[], RelatedContextParameters> | QueryCtorOptions<ContextItem[], RelatedContextParameters>;
}, expire?: number): void;
}
import { Observable } from 'rxjs';
import { ContextModuleConfig } from './configurator';
import { ContextClient } from './client/ContextClient';
import { ContextItem, QueryContextParameters } from './types';
import { ContextItem, QueryContextParameters, RelatedContextParameters } from './types';
import { ModuleType } from '@equinor/fusion-framework-module';

@@ -15,2 +15,7 @@ import { EventModule, FrameworkEvent, FrameworkEventInit } from '@equinor/fusion-framework-module-event';

queryContextAsync(search: string): Promise<Array<ContextItem>>;
validateContext(item: ContextItem<Record<string, unknown>>): boolean;
resolveContext: (current: ContextItem) => Observable<ContextItem>;
resolveContextAsync: (current: ContextItem) => Promise<ContextItem>;
relatedContexts: (args: RelatedContextParameters) => Observable<Array<ContextItem<Record<string, unknown>>>>;
relatedContextsAsync: (args: RelatedContextParameters) => Promise<Array<ContextItem<Record<string, unknown>>>>;
clearCurrentContext: VoidFunction;

@@ -30,4 +35,13 @@ }

});
setCurrentContext(context: ContextItem<Record<string, unknown>>, opt?: {
validate?: boolean;
resolve?: boolean;
}): Promise<ContextItem<Record<string, unknown>>>;
queryContext(search: string): Observable<Array<ContextItem>>;
queryContextAsync(search: string): Promise<Array<ContextItem>>;
validateContext(item: ContextItem<Record<string, unknown>>): boolean;
resolveContext(item: ContextItem<Record<string, unknown>>): Observable<ContextItem<Record<string, unknown>>>;
resolveContextAsync(item: ContextItem<Record<string, unknown>>): Promise<ContextItem<Record<string, unknown>>>;
relatedContexts(args: RelatedContextParameters): Observable<Array<ContextItem<Record<string, unknown>>>>;
relatedContextsAsync(args: RelatedContextParameters): Promise<Array<ContextItem<Record<string, unknown>>>>;
clearCurrentContext(): void;

@@ -46,3 +60,13 @@ dispose(): void;

}, IContextProvider>>;
onParentContextChanged: FrameworkEvent<FrameworkEventInit<{
context: ContextItem | undefined;
}, IContextProvider>>;
onSetContextResolve: FrameworkEvent<FrameworkEventInit<{
context: ContextItem;
}, IContextProvider>>;
onSetContextResolved: FrameworkEvent<FrameworkEventInit<{
input: ContextItem;
result?: ContextItem | null;
}, IContextProvider>>;
}
}
import type { ContextItem } from './types';
export declare const getContextSelector: (response: Response) => Promise<ContextItem>;
export declare const queryContextSelector: (response: Response) => Promise<ContextItem[]>;
export declare const relatedContextSelector: (response: Response) => Promise<ContextItem[]>;

@@ -26,2 +26,8 @@ export type ContextItem<TType extends Record<string, unknown> = Record<string, unknown>> = {

};
export type RelatedContextParameters = {
item: ContextItem;
filter?: {
type?: string[];
};
};
export type ContextFilterFn = (items: ContextItem[]) => ContextItem[];
{
"name": "@equinor/fusion-framework-module-context",
"version": "2.0.15",
"version": "3.0.0",
"description": "",

@@ -34,9 +34,9 @@ "main": "./dist/esm/index.js",

"dependencies": {
"@equinor/fusion-query": "^2.0.7",
"@equinor/fusion-query": "^3.0.0",
"fast-deep-equal": "^3.1.3"
},
"devDependencies": {
"@equinor/fusion-framework-module": "^2.0.1",
"@equinor/fusion-framework-module-event": "^2.0.1",
"@equinor/fusion-framework-module-services": "^2.6.0",
"@equinor/fusion-framework-module": "^3.0.0",
"@equinor/fusion-framework-module-event": "^3.0.0",
"@equinor/fusion-framework-module-services": "^3.0.0",
"rxjs": "^7.5.7"

@@ -48,3 +48,3 @@ },

},
"gitHead": "58e2b934160c8bfe90be1e8de7706bf1d339e303"
"gitHead": "3462d21feac22290eec2dce3b00602da22a7a74d"
}
import { ModuleInitializerArgs, ModulesInstanceType } from '@equinor/fusion-framework-module';
import { ServicesModule, IApiProvider } from '@equinor/fusion-framework-module-services';
import { getContextSelector, queryContextSelector } from './selectors';
import { getContextSelector, queryContextSelector, relatedContextSelector } from './selectors';
import { QueryCtorOptions } from '@equinor/fusion-query';
import { ContextFilterFn, ContextItem, QueryContextParameters } from './types';
import {
ContextFilterFn,
ContextItem,
QueryContextParameters,
RelatedContextParameters,
} from './types';
import { GetContextParameters } from './client/ContextClient';
import { ContextConfigBuilder, ContextConfigBuilderCallback } from './ContextConfigBuilder';
import { IContextProvider } from 'ContextProvider';

@@ -13,2 +19,3 @@ export interface ContextModuleConfig {

query: QueryCtorOptions<ContextItem[], QueryContextParameters>;
related?: QueryCtorOptions<ContextItem[], RelatedContextParameters>;
};

@@ -25,2 +32,12 @@ contextType?: string[];

}) => string | QueryContextParameters;
resolveContext?: (
this: IContextProvider,
item: ContextItem | null
) => ReturnType<IContextProvider['resolveContext']>;
validateContext?: (
this: IContextProvider,
item: ContextItem | null
) => ReturnType<IContextProvider['validateContext']>;
}

@@ -92,2 +109,16 @@

},
related: {
client: {
fn: (args) => {
return contextClient.related(
'v1',
{ id: args.item.id, query: { filter: args.filter } },
{ selector: relatedContextSelector }
);
},
},
// TODO - might cast to checksum
key: (args) => JSON.stringify(args),
expire: this.defaultExpireTime,
},
};

@@ -94,0 +125,0 @@ })();

@@ -18,3 +18,3 @@ import type {

import type { ContextItem, QueryContextParameters } from './types';
import type { ContextItem, QueryContextParameters, RelatedContextParameters } from './types';

@@ -61,2 +61,10 @@ export type ContextConfigBuilderCallback = <TDeps extends Array<AnyModule> = []>(

setValidateContext(fn: ContextModuleConfig['validateContext']) {
this.config.validateContext = fn;
}
setResolveContext(fn: ContextModuleConfig['resolveContext']) {
this.config.resolveContext = fn;
}
setContextClient(

@@ -70,2 +78,5 @@ client: {

| QueryCtorOptions<ContextItem[], QueryContextParameters>;
related?:
| QueryFn<ContextItem[], RelatedContextParameters>
| QueryCtorOptions<ContextItem[], RelatedContextParameters>;
},

@@ -97,3 +108,17 @@ expire = 1 * 60 * 1000

};
if (client.related) {
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
this.config.client!.related =
typeof client.related === 'function'
? {
// TODO - might cast to checksum
key: (args) => JSON.stringify(args),
client: {
fn: client.related,
},
expire,
}
: client.related;
}
}
}

@@ -1,3 +0,3 @@

import { lastValueFrom, Observable, Subscription } from 'rxjs';
import { map, pairwise } from 'rxjs/operators';
import { lastValueFrom, Observable, Subscription, throwError } from 'rxjs';
import { filter, map, pairwise, switchMap } from 'rxjs/operators';

@@ -7,3 +7,3 @@ import { ContextModuleConfig } from './configurator';

import { ContextClient } from './client/ContextClient';
import { ContextItem, QueryContextParameters } from './types';
import { ContextItem, QueryContextParameters, RelatedContextParameters } from './types';
import { ModuleType } from '@equinor/fusion-framework-module';

@@ -31,2 +31,11 @@ import {

queryContextAsync(search: string): Promise<Array<ContextItem>>;
validateContext(item: ContextItem<Record<string, unknown>>): boolean;
resolveContext: (current: ContextItem) => Observable<ContextItem>;
resolveContextAsync: (current: ContextItem) => Promise<ContextItem>;
relatedContexts: (
args: RelatedContextParameters
) => Observable<Array<ContextItem<Record<string, unknown>>>>;
relatedContextsAsync: (
args: RelatedContextParameters
) => Promise<Array<ContextItem<Record<string, unknown>>>>;
clearCurrentContext: VoidFunction;

@@ -38,2 +47,3 @@ }

#contextQuery: Query<Array<ContextItem>, QueryContextParameters>;
#contextRelated?: Query<Array<ContextItem>, RelatedContextParameters>;

@@ -65,20 +75,3 @@ #event?: ModuleType<EventModule>;

set currentContext(context: ContextItem | undefined) {
if (this.#event) {
/** notify listeners that context is about to change */
this.#event
.dispatchEvent('onCurrentContextChange', {
source: this,
canBubble: true,
cancelable: true,
detail: { context },
})
.then((e) => {
/** check if setting context was prevented by listener */
if (!e.canceled) {
this.#contextClient.setCurrentContext(context);
}
});
} else {
this.#contextClient.setCurrentContext(context);
}
context ? this.setCurrentContext(context) : this.clearCurrentContext();
}

@@ -93,2 +86,5 @@

config.resolveContext && (this.resolveContext = config.resolveContext?.bind(this));
config.validateContext && (this.validateContext = config.validateContext?.bind(this));
this.#contextType = config.contextType;

@@ -99,2 +95,7 @@ this.#contextFilter = config.contextFilter;

this.#contextQuery = new Query(config.client.query);
if (config.client.related) {
this.#contextRelated = new Query(config.client.related);
}
this.#contextParameterFn =

@@ -136,5 +137,35 @@ config.contextParameterFn ??

this.#subscriptions.add(
parentContext.contextClient.currentContext$.subscribe(
(next) => (this.currentContext = next)
)
parentContext.contextClient.currentContext$
.pipe(
switchMap(async (next) => {
if (next) {
const onParentContextChanged = await this.#event?.dispatchEvent(
'onParentContextChanged',
{
source: this,
detail: next,
cancelable: true,
}
);
return { next, canceled: onParentContextChanged?.canceled };
}
return { next };
}),
filter((x) => !x.canceled),
map(({ next }) => next)
)
.subscribe((next) => {
if (next) {
try {
this.setCurrentContext(next, {
validate: true,
resolve: true,
});
} catch (err) {
console.warn('ContextProvider::onParentContextChanged', err);
}
} else {
this.clearCurrentContext();
}
})
);

@@ -144,2 +175,63 @@ }

public async setCurrentContext(
context: ContextItem<Record<string, unknown>>,
opt?: { validate?: boolean; resolve?: boolean }
): Promise<ContextItem<Record<string, unknown>>> {
if (context === this.currentContext) {
return context;
}
if (opt?.validate && !this.validateContext(context)) {
if (opt.resolve) {
/** notify listeners about to resolve invalid context */
const onSetContextResolve = await this.#event?.dispatchEvent(
'onSetContextResolve',
{
source: this,
cancelable: true,
detail: { context },
}
);
if (onSetContextResolve?.canceled) {
throw Error('resolving of context was canceled');
}
try {
const resolvedContext = await this.resolveContextAsync(context);
/** notify listeners about to resolved invalid context */
const onSetContextResolved = await this.#event?.dispatchEvent(
'onSetContextResolved',
{
source: this,
cancelable: true,
detail: { input: context, result: resolvedContext },
}
);
if (onSetContextResolved?.canceled) {
throw Error('resolving of context was canceled');
}
return this.setCurrentContext(resolvedContext);
} catch (err) {
console.error('failed to resolve context', context, err);
this.clearCurrentContext();
}
}
throw Error('failed to validate provided context');
}
const onCurrentContextChange = await this.#event?.dispatchEvent('onCurrentContextChange', {
source: this,
canBubble: true,
cancelable: true,
detail: { context: context },
});
if (onCurrentContextChange?.canceled) {
throw Error('change of context was aborted');
}
this.#contextClient.setCurrentContext(context);
return context;
}
public queryContext(search: string): Observable<Array<ContextItem>> {

@@ -162,4 +254,56 @@ const query$ = this.queryClient

public validateContext(item: ContextItem<Record<string, unknown>>): boolean {
if (!this.#contextType) return true;
return this.#contextType.map((x) => x.toLowerCase()).includes(item.type.id.toLowerCase());
}
public resolveContext(
item: ContextItem<Record<string, unknown>>
): Observable<ContextItem<Record<string, unknown>>> {
return this.relatedContexts({ item, filter: { type: this.#contextType } }).pipe(
map((x) => x.filter((item) => this.validateContext(item))),
map((values) => {
const value = values.shift();
if (!value) {
throw Error('failed to resolve context');
}
if (values.length) {
console.warn(
'ContextProvider::relatedContext',
'multiple items found 🤣',
values
);
}
return value;
})
);
}
public resolveContextAsync(
item: ContextItem<Record<string, unknown>>
): Promise<ContextItem<Record<string, unknown>>> {
return lastValueFrom(this.resolveContext(item));
}
public relatedContexts(
args: RelatedContextParameters
): Observable<Array<ContextItem<Record<string, unknown>>>> {
if (!this.#contextRelated) {
return throwError(() =>
Error(
'ContextProvider::relatedContexts - no client defined for resolving related context'
)
);
}
return this.#contextRelated.query(args).pipe(map(({ value }) => value));
}
public relatedContextsAsync(
args: RelatedContextParameters
): Promise<Array<ContextItem<Record<string, unknown>>>> {
return lastValueFrom(this.relatedContexts(args));
}
public clearCurrentContext() {
this.currentContext = undefined;
this.#contextClient.setCurrentContext(undefined);
}

@@ -195,3 +339,29 @@

>;
onParentContextChanged: FrameworkEvent<
FrameworkEventInit<
{
context: ContextItem | undefined;
},
IContextProvider
>
>;
onSetContextResolve: FrameworkEvent<
FrameworkEventInit<
{
context: ContextItem;
},
IContextProvider
>
>;
onSetContextResolved: FrameworkEvent<
FrameworkEventInit<
{
input: ContextItem;
result?: ContextItem | null;
},
IContextProvider
>
>;
}
}
import { ApiVersion, ApiContextEntity } from '@equinor/fusion-framework-module-services/context';
import type { GetContextResponse } from '@equinor/fusion-framework-module-services/context/get';
import type { QueryContextResponse } from '@equinor/fusion-framework-module-services/context/query';
import type { RelatedContextResponse } from '@equinor/fusion-framework-module-services/context/related';
import type { ContextItem, ContextItemType } from './types';

@@ -36,1 +37,6 @@

};
export const relatedContextSelector = async (response: Response): Promise<ContextItem[]> => {
const result = (await response.json()) as RelatedContextResponse<'v1'>;
return result.map(parseContextItem);
};

@@ -29,2 +29,4 @@ export type ContextItem<TType extends Record<string, unknown> = Record<string, unknown>> = {

export type RelatedContextParameters = { item: ContextItem; filter?: { type?: string[] } };
export type ContextFilterFn = (items: ContextItem[]) => ContextItem[];

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc