@equinor/fusion-framework-module-context 9.0.0 → 9.0.1

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.
Files changed (42) hide show
  1. package/dist/esm/version.js +1 -1
  2. package/dist/tsconfig.tsbuildinfo +1 -1
  3. package/dist/types/version.d.ts +1 -1
  4. package/package.json +13 -10
  5. package/CHANGELOG.md +0 -1072
  6. package/docs/data-model.md +0 -134
  7. package/docs/lifecycle.md +0 -163
  8. package/docs/recipes.md +0 -89
  9. package/src/ContextModuleConfig.ts +0 -147
  10. package/src/ContextModuleConfigurator.interface.ts +0 -145
  11. package/src/ContextModuleConfigurator.ts +0 -295
  12. package/src/ContextProvider.ts +0 -1158
  13. package/src/__tests__/ContextModuleConfigurator.test.ts +0 -412
  14. package/src/__tests__/mock/context-mock.test.ts +0 -137
  15. package/src/__tests__/mock/create-context-item-factory.test.ts +0 -60
  16. package/src/__tests__/mock/create-context-items.test.ts +0 -58
  17. package/src/client/ContextClient.ts +0 -149
  18. package/src/errors/FusionContextSearchError.ts +0 -56
  19. package/src/errors/index.ts +0 -1
  20. package/src/index.ts +0 -29
  21. package/src/mock/ContextMockConfigurator.ts +0 -244
  22. package/src/mock/fixtures/create-context-item-factory.ts +0 -62
  23. package/src/mock/fixtures/create-context-items.ts +0 -80
  24. package/src/mock/fixtures/index.ts +0 -28
  25. package/src/mock/fixtures/string-to-seed.ts +0 -18
  26. package/src/mock/index.ts +0 -33
  27. package/src/mock/module.ts +0 -54
  28. package/src/module.ts +0 -178
  29. package/src/selectors/get-context-selector.ts +0 -14
  30. package/src/selectors/index.ts +0 -12
  31. package/src/selectors/query-context-selector.ts +0 -15
  32. package/src/selectors/related-context-selector.ts +0 -15
  33. package/src/types.ts +0 -98
  34. package/src/utils/enable-context.ts +0 -40
  35. package/src/utils/extract-context-id-from-path.ts +0 -39
  36. package/src/utils/index.ts +0 -15
  37. package/src/utils/parse-context-item.ts +0 -39
  38. package/src/utils/resolve-context-from-path.ts +0 -118
  39. package/src/utils/resolve-initial-context.ts +0 -58
  40. package/src/version.ts +0 -2
  41. package/tsconfig.json +0 -33
  42. package/vitest.config.ts +0 -11
package/src/mock/index.ts DELETED
@@ -1,33 +0,0 @@
1
- /**
2
- * Mock context module for tests: real provider, real configurator, in-memory data.
3
- *
4
- * @remarks
5
- * Substituting the data source is the smallest change that removes the context
6
- * API, HTTP mocking, and service-discovery mocking from a test. Everything
7
- * above it — validation, resolution, parent-context propagation, initial-context
8
- * selection — is the production code path.
9
- *
10
- * This is one of two ways to mock context data in tests: a small, static,
11
- * in-memory pool (this module — no HTTP layer involved at all). The other is
12
- * mocking the context API's HTTP responses directly (e.g. with MSW), which
13
- * exercises the real `ContextModuleConfigurator`/services/HTTP pipeline —
14
- * reach for that instead when the test needs to cover that pipeline itself.
15
- * For fixture generators with realistic fake data, see
16
- * `@equinor/fusion-framework-module-context/mock/fixtures`.
17
- *
18
- * @example
19
- * ```typescript
20
- * import { enableContextMock } from '@equinor/fusion-framework-module-context/mock';
21
- *
22
- * enableContextMock(configurator, (mock) => {
23
- * mock.setCurrentContext({ id: 'my-ctx', type: { id: 'ProjectMaster' }, value: {} });
24
- * });
25
- * ```
26
- *
27
- * @packageDocumentation
28
- */
29
- export {
30
- ContextMockConfigurator,
31
- type ContextResolverFn,
32
- } from './ContextMockConfigurator';
33
- export { enableContextMock, contextMockModule, type ContextMockConfigFn } from './module';
@@ -1,54 +0,0 @@
1
- import type { IModulesConfigurator } from '@equinor/fusion-framework-module';
2
-
3
- import { module, type ContextModule } from '../module';
4
-
5
- import { ContextMockConfigurator } from './ContextMockConfigurator';
6
-
7
- /**
8
- * The context module with an in-memory mock configurator instead of a real
9
- * context API.
10
- *
11
- * @remarks
12
- * Only `configure` differs from the real module. `initialize` is the production
13
- * one, untouched, so a test exercises the real `ContextProvider` startup path,
14
- * `validateContext`/`resolveContext`, and parent-context propagation — a
15
- * rehearsal of the module, not a stand-in for it.
16
- */
17
- export const contextMockModule: ContextModule = {
18
- ...module,
19
- configure: () => new ContextMockConfigurator(),
20
- };
21
-
22
- /**
23
- * Configuration callback for {@link enableContextMock}.
24
- */
25
- export type ContextMockConfigFn = (mock: ContextMockConfigurator) => void | Promise<void>;
26
-
27
- /**
28
- * Enables the context module against in-memory seeded data, so a test needs no
29
- * context API, no HTTP mock, and no service-discovery mock.
30
- *
31
- * @remarks
32
- * Registered last, this replaces whichever context module the configurator
33
- * already carries, so it works on a `FrameworkConfigurator` that pre-registers
34
- * the real one.
35
- *
36
- * @param configurator - The modules configurator to register on.
37
- * @param configure - Optional callback to seed context items or override resolution.
38
- *
39
- * @example
40
- * ```ts
41
- * enableContextMock(configurator, (mock) => {
42
- * mock.setCurrentContext({ id: 'my-ctx', type: { id: 'ProjectMaster' }, value: {} });
43
- * });
44
- * ```
45
- */
46
- export const enableContextMock = (
47
- // biome-ignore lint/suspicious/noExplicitAny: must be any to support all module types
48
- configurator: IModulesConfigurator<any, any>,
49
- configure?: ContextMockConfigFn,
50
- ): void => {
51
- configurator.addConfig({ module: contextMockModule, configure } as {
52
- module: ContextModule;
53
- });
54
- };
package/src/module.ts DELETED
@@ -1,178 +0,0 @@
1
- import { catchError, EMPTY, from, Observable, switchMap, filter, Subscription } from 'rxjs';
2
-
3
- import type { Module, ModulesInstance } from '@equinor/fusion-framework-module';
4
-
5
- import type { EventModule } from '@equinor/fusion-framework-module-event';
6
- import type { ServicesModule } from '@equinor/fusion-framework-module-services';
7
- import type { NavigationModule } from '@equinor/fusion-framework-module-navigation';
8
- import {
9
- TelemetryLevel,
10
- TelemetryScope,
11
- type TelemetryModule,
12
- } from '@equinor/fusion-framework-module-telemetry';
13
-
14
- import {
15
- type IContextModuleConfigurator,
16
- ContextModuleConfigurator,
17
- } from './ContextModuleConfigurator';
18
- import { type IContextProvider, ContextProvider } from './ContextProvider';
19
- import type { ContextItem } from './types';
20
-
21
- /**
22
- * Literal type identifying the context module within the Fusion Framework module system.
23
- *
24
- * Used as the key when registering or looking up the module in a `Modules` map.
25
- */
26
- export type ContextModuleKey = 'context';
27
-
28
- /**
29
- * Module registration key for the context module.
30
- *
31
- * Pass this value—or reference it as `contextModuleKey`—when you need to
32
- * identify the context module by name at runtime (e.g., `hasModule(contextModuleKey)`).
33
- */
34
- export const moduleKey: ContextModuleKey = 'context';
35
-
36
- /**
37
- * Represents a module for managing context within the framework.
38
- *
39
- * @typeParam ContextModuleKey - The unique key identifying the context module.
40
- * @typeParam IContextProvider - The provider interface for context-related services.
41
- * @typeParam IContextModuleConfigurator - The configurator interface for customizing the context module.
42
- * @typeParam [ServicesModule, EventModule, NavigationModule, TelemetryModule] - The tuple of dependent modules required by the context module.
43
- *
44
- * @see Module
45
- */
46
- export type ContextModule = Module<
47
- ContextModuleKey,
48
- IContextProvider,
49
- IContextModuleConfigurator,
50
- [ServicesModule, EventModule, NavigationModule, TelemetryModule]
51
- >;
52
-
53
- /**
54
- * The `module` object implements the `ContextModule` interface and provides the configuration,
55
- * initialization, and lifecycle management for the context module within the Fusion Framework.
56
- *
57
- * @remarks
58
- * - The `configure` method returns a new `ContextModuleConfigurator` for module configuration.
59
- * - The `initialize` method asynchronously creates a `ContextProvider` using the provided configuration,
60
- * optional event module, and optional parent context provider. It also sets up resource disposal and
61
- * post-initialization logic.
62
- * - The `postInitialize` function (attached during initialization) resolves the initial context if available,
63
- * sets it as the current context, and connects to the parent context provider if configured to do so.
64
- * - The `dispose` function ensures proper cleanup by unsubscribing from the provider's subscription.
65
- *
66
- * @property {string} name - The unique key identifying the module.
67
- * @method configure - Returns a new instance of `ContextModuleConfigurator` for configuring the module.
68
- * @method initialize - Asynchronously initializes the context provider, sets up context resolution,
69
- * and manages lifecycle hooks.
70
- * @see ContextModule
71
- * @see ContextModuleConfigurator
72
- * @see ContextProvider
73
- */
74
- export const module: ContextModule = {
75
- name: moduleKey,
76
- configure: () => new ContextModuleConfigurator(),
77
- initialize: async function (args) {
78
- // create config from configurator
79
- const config = await (args.config as ContextModuleConfigurator).createConfigAsync(args);
80
-
81
- // get event module if available
82
- const event = args.hasModule('event') ? await args.requireInstance('event') : undefined;
83
-
84
- // get telemetry module if available, for tracking context resolution outcomes
85
- const telemetry = args.hasModule('telemetry')
86
- ? await args.requireInstance('telemetry')
87
- : undefined;
88
-
89
- // get parent context provider if available
90
- const parentProvider = (args.ref as ModulesInstance<[ContextModule]>)?.context;
91
-
92
- // create context provider; parent context is wired up later via connectParentContext, not the deprecated ctor arg
93
- const provider = new ContextProvider({ config, event });
94
-
95
- // create subscription for disposing the provider
96
- const subscription = new Subscription(() => provider.dispose());
97
-
98
- // setup post initialize to module
99
- this.postInitialize = (args) =>
100
- // create observable for resolving initial context
101
- new Observable((subscriber) => {
102
- // resolve initial context if available from config if available
103
- const resolveInitialContext$ = config.resolveInitialContext
104
- ? from(config.resolveInitialContext(args)).pipe(
105
- // filter out invalid context items
106
- filter((item): item is ContextItem => !!item),
107
- switchMap((item) =>
108
- // set current context with validation and resolution
109
- args.modules.context.setCurrentContext(item, {
110
- validate: true,
111
- resolve: true,
112
- }),
113
- ),
114
- )
115
- : EMPTY; // if no initial context is available, complete immediately
116
-
117
- // add teardown to resolve initial context
118
- subscriber.add(
119
- resolveInitialContext$
120
- .pipe(
121
- catchError((err) => {
122
- const exception = err instanceof Error ? err : new Error(String(err));
123
- // report through telemetry when available, otherwise fall back to console.warn below
124
- if (telemetry) {
125
- telemetry.trackException({
126
- name: 'Context::postInitialize.resolveInitialContext',
127
- exception,
128
- level: TelemetryLevel.Warning,
129
- scope: ['context', TelemetryScope.Framework],
130
- });
131
- } else {
132
- // no telemetry module registered - fall back to a visible warning so a
133
- // genuine resolution failure isn't silently swallowed
134
- console.warn('Context::postInitialize.resolveInitialContext', exception);
135
- }
136
- // failed to resolve initial context, complete immediately
137
- return EMPTY;
138
- }),
139
- )
140
- .subscribe({
141
- next: (item) => {
142
- telemetry?.trackEvent({
143
- name: 'Context::postInitialize.initialContextResolved',
144
- level: TelemetryLevel.Debug,
145
- scope: ['context', TelemetryScope.Framework],
146
- properties: { contextId: item ? item.id : 'none' },
147
- });
148
- },
149
- complete: () => {
150
- // connect parent context if available when stream completes
151
- if (config.connectParentContext !== false && parentProvider) {
152
- provider.connectParentContext(parentProvider);
153
- telemetry?.trackEvent({
154
- name: 'Context::postInitialize.parentContextConnected',
155
- level: TelemetryLevel.Debug,
156
- scope: ['context', TelemetryScope.Framework],
157
- });
158
- }
159
- subscriber.complete();
160
- },
161
- }),
162
- );
163
- });
164
-
165
- // add teardown to module
166
- this.dispose = () => subscription.unsubscribe();
167
-
168
- return provider;
169
- },
170
- };
171
-
172
- declare module '@equinor/fusion-framework-module' {
173
- interface Modules {
174
- context: ContextModule;
175
- }
176
- }
177
-
178
- export default module;
@@ -1,14 +0,0 @@
1
- import type { GetContextResponse } from '@equinor/fusion-framework-module-services/context/get';
2
-
3
- import { parseContextItem } from '../utils/parse-context-item';
4
- import type { ContextItem } from '../types';
5
-
6
- /**
7
- * Parse the response from the GetContext API into a context item.
8
- * @param response The response object containing the context item.
9
- * @returns A promise that resolves to the context item.
10
- */
11
- export const getContextSelector = async (response: Response): Promise<ContextItem> => {
12
- const result = (await response.json()) as GetContextResponse<'v1'>;
13
- return parseContextItem(result);
14
- };
@@ -1,12 +0,0 @@
1
- /**
2
- * Response selectors that parse raw context API responses into {@link ContextItem}s.
3
- *
4
- * - {@link getContextSelector} — parses a single-item GetContext response.
5
- * - {@link queryContextSelector} — parses a multi-item QueryContext response.
6
- * - {@link relatedContextSelector} — parses a multi-item RelatedContext response.
7
- *
8
- * @packageDocumentation
9
- */
10
- export { getContextSelector } from './get-context-selector';
11
- export { queryContextSelector } from './query-context-selector';
12
- export { relatedContextSelector } from './related-context-selector';
@@ -1,15 +0,0 @@
1
- import type { QueryContextResponse } from '@equinor/fusion-framework-module-services/context/query';
2
-
3
- import { parseContextItem } from '../utils/parse-context-item';
4
- import type { ContextItem } from '../types';
5
-
6
- /**
7
- * Parse the response from the QueryContext API into an array of context items.
8
- * @param response The response object.
9
- * @returns A promise that resolves to an array of context items.
10
- */
11
- export const queryContextSelector = async (response: Response): Promise<ContextItem[]> => {
12
- const result = (await response.json()) as QueryContextResponse<'v1'>;
13
- // parse each raw API entry into a ContextItem
14
- return result.map(parseContextItem);
15
- };
@@ -1,15 +0,0 @@
1
- import type { RelatedContextResponse } from '@equinor/fusion-framework-module-services/context/related';
2
-
3
- import { parseContextItem } from '../utils/parse-context-item';
4
- import type { ContextItem } from '../types';
5
-
6
- /**
7
- * Parse the response from the RelatedContext API into an array of context items.
8
- * @param response The response object containing the related context items.
9
- * @returns A promise that resolves to an array of ContextItem objects.
10
- */
11
- export const relatedContextSelector = async (response: Response): Promise<ContextItem[]> => {
12
- const result = (await response.json()) as RelatedContextResponse<'v1'>;
13
- // parse each raw API entry into a ContextItem
14
- return result.map(parseContextItem);
15
- };
package/src/types.ts DELETED
@@ -1,98 +0,0 @@
1
- /**
2
- * Represents a contextual item with associated metadata, value, and optional graphical or meta content.
3
- *
4
- * @typeParam TType - The type of the value property, defaults to a generic record.
5
- * @property id - Unique identifier for the context item.
6
- * @property externalId - Optional external identifier.
7
- * @property source - Optional source of the context item.
8
- * @property type - The type of the context item.
9
- * @property value - The value associated with the context item.
10
- * @property title - Optional title for display purposes.
11
- * @property subTitle - Optional subtitle for display purposes.
12
- * @property isActive - Optional flag indicating if the item is active.
13
- * @property isDeleted - Optional flag indicating if the item is deleted.
14
- * @property created - Optional creation date.
15
- * @property updated - Optional last updated date.
16
- * @property graphic - Optional graphical representation, either as a string or an object containing type and content.
17
- * @property meta - Optional meta information, either as a string or an object containing type and content.
18
- *
19
- * @todo(#5122) - convert to Zod schema for validation and type safety.
20
- */
21
- export type ContextItem<TType extends Record<string, unknown> = Record<string, unknown>> = {
22
- id: string;
23
- externalId?: string;
24
- source?: string;
25
- type: ContextItemType;
26
- value: TType;
27
- title?: string;
28
- subTitle?: string;
29
- isActive?: boolean;
30
- isDeleted?: boolean;
31
- created?: Date;
32
- updated?: Date;
33
- graphic?:
34
- | string
35
- | {
36
- type: 'html' | 'svg';
37
- content: string;
38
- };
39
- meta?:
40
- | string
41
- | {
42
- type: 'html' | 'svg';
43
- content: string;
44
- };
45
- };
46
-
47
- /**
48
- * Describes the type classification of a {@link ContextItem}.
49
- *
50
- * Every context item carries a `type` that identifies what kind of
51
- * entity it represents (e.g. `ProjectMaster`, `Facility`, `Contract`).
52
- * The optional hierarchy fields indicate parent–child relationships
53
- * between context types.
54
- */
55
- export interface ContextItemType {
56
- /** Unique identifier for the context type (e.g. `'ProjectMaster'`). */
57
- id: string;
58
- /** Whether this type is a child of another context type. */
59
- isChildType?: boolean;
60
- /** IDs of parent context types, when `isChildType` is `true`. */
61
- parentTypeIds?: string[];
62
- }
63
-
64
- /**
65
- * Parameters for querying context items from the context API.
66
- *
67
- * Used by {@link ContextProvider.queryContext} and the underlying
68
- * query client to search and filter context results.
69
- *
70
- * @property search - Free-text search term.
71
- * @property filter - Optional structured filters.
72
- * @property filter.type - Restrict results to specific context type IDs.
73
- * @property filter.externalId - Filter by an external system identifier.
74
- */
75
- export type QueryContextParameters = {
76
- search?: string;
77
- filter?: {
78
- type?: string[];
79
- externalId?: string;
80
- };
81
- };
82
-
83
- /**
84
- * Parameters for retrieving related context items.
85
- *
86
- * @property item - The context item to find relations for.
87
- * @property filter - Optional filter criteria.
88
- * @property filter.type - Optional array of types to filter related items by.
89
- */
90
- export type RelatedContextParameters = { item: ContextItem; filter?: { type?: string[] } };
91
-
92
- /**
93
- * A function type that filters an array of `ContextItem` objects.
94
- *
95
- * @param items - The array of `ContextItem` objects to be filtered.
96
- * @returns A new array of `ContextItem` objects after applying the filter.
97
- */
98
- export type ContextFilterFn = (items: ContextItem[]) => ContextItem[];
@@ -1,40 +0,0 @@
1
- import type { IModulesConfigurator } from '@equinor/fusion-framework-module';
2
- import type {
3
- ContextConfigBuilderCallback,
4
- IContextModuleConfigurator,
5
- } from '../ContextModuleConfigurator.interface';
6
-
7
- import { module } from '../module';
8
-
9
- /**
10
- * Enables context configuration for a given modules configurator.
11
- *
12
- * @param configurator - The modules configurator instance to which the context module will be added.
13
- * @param builder - An optional function that receives the {@link IContextModuleConfigurator}. This function can be used to further configure the context module. It can be asynchronous.
14
- *
15
- * @remarks
16
- * This utility function adds the context module to the provided configurator and optionally applies additional configuration using the provided builder function.
17
- *
18
- * @example
19
- * ```ts
20
- * import { enableContext } from '@equinor/fusion-framework-module-context';
21
- *
22
- * const configure = (configurator: IModulesConfigurator<any, any>) => {
23
- * enableContext(configurator, (builder) => {
24
- * // configure the context module here
25
- * });
26
- * };
27
- * ```
28
- */
29
- export const enableContext = (
30
- // biome-ignore lint/suspicious/noExplicitAny: must be any to support all module types
31
- configurator: IModulesConfigurator<any, any>,
32
- builder?: ContextConfigBuilderCallback,
33
- ): void => {
34
- configurator.addConfig({
35
- module,
36
- configure: (contextConfigurator) => {
37
- builder && contextConfigurator.addConfigBuilder(builder);
38
- },
39
- });
40
- };
@@ -1,39 +0,0 @@
1
- // GUID pattern
2
- const matchGUID =
3
- /^(?:(?:[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})$/;
4
-
5
- /**
6
- * Method will try to extract a context id from a path.
7
- * The default matcher is a GUID pattern.
8
- * Will iterate over the path and return the first match.
9
- *
10
- * @example
11
- * ```ts
12
- * const path = '/apps/context/7fd97952-7fe6-409b-a6dc-292dbf0e50d7?dsadasdas#example';
13
- * const contextId = extractContextIdFromPath(path); // '7fd97952-7fe6-409b-a6dc-292dbf0e50d7'
14
- *
15
- * // Custom matcher for numeric IDs
16
- * extractContextIdFromPath('/projects/42/details', /^\d+$/); // '42'
17
- *
18
- * // No match
19
- * extractContextIdFromPath('/apps/my-app/settings'); // undefined
20
- * ```
21
- *
22
- * @param path string - the path to extract the context id from
23
- * @param matcher RegExp - the pattern to match against
24
- * @returns string | undefined - the context id or undefined
25
- */
26
- export const extractContextIdFromPath = (
27
- path: string,
28
- matcher: RegExp = matchGUID,
29
- ): string | undefined =>
30
- //
31
- path
32
- // remove query-string and hash fragments before segment matching
33
- .split(/[?#]/)[0]
34
- // remove leading slashes
35
- .replace(/^\/+/, '')
36
- // split path by slashes
37
- .split('/')
38
- // find the first path fragment that matches the matcher
39
- .find((x) => x.match(matcher));
@@ -1,15 +0,0 @@
1
- /**
2
- * Utility functions for context module configuration and initialization.
3
- *
4
- * - {@link enableContext} — register the context module on a configurator.
5
- * - {@link resolveInitialContext} — default initial-context resolver (path → parent fallback).
6
- * - {@link extractContextIdFromPath} — extract a GUID context ID from a URL path.
7
- * - {@link resolveContextFromPath} — resolve a context item from a URL path.
8
- * - {@link parseContextItem} — parse a raw API context entity into a `ContextItem`.
9
- *
10
- * @packageDocumentation
11
- */
12
- export { enableContext } from './enable-context';
13
- export { resolveInitialContext } from './resolve-initial-context';
14
- export { extractContextIdFromPath, resolveContextFromPath } from './resolve-context-from-path';
15
- export { parseContextItem } from './parse-context-item';
@@ -1,39 +0,0 @@
1
- import type {
2
- ApiVersion,
3
- ApiContextEntity,
4
- } from '@equinor/fusion-framework-module-services/context';
5
- import type { GetContextResponse } from '@equinor/fusion-framework-module-services/context/get';
6
-
7
- import type { ContextItem, ContextItemType } from '../types';
8
-
9
- /**
10
- * Parses the context type from the response of the GetContext API.
11
- *
12
- * @param type The type property from the GetContext response.
13
- * @returns The parsed context item type.
14
- */
15
- const parseContextType = (type: GetContextResponse<'v1'>['type']): ContextItemType => ({
16
- id: type.id,
17
- isChildType: type.isChildType,
18
- parentTypeIds: type.parentTypeIds ?? [],
19
- });
20
-
21
- /**
22
- * Parses an ApiContextEntity object into a ContextItem object.
23
- * @param item The ApiContextEntity object to parse.
24
- * @returns The parsed ContextItem object.
25
- */
26
- export const parseContextItem = (item: ApiContextEntity<ApiVersion.v1>): ContextItem => {
27
- return {
28
- id: item.id,
29
- externalId: item.externalId ?? undefined,
30
- isActive: item.isActive,
31
- isDeleted: item.isDeleted,
32
- created: new Date(item.created),
33
- source: item.source ?? undefined,
34
- title: item.title ?? undefined,
35
- type: parseContextType(item.type),
36
- // TODO(#5115): parse and map the raw `value` payload into a typed context item value
37
- value: item.value ?? {},
38
- };
39
- };