@equinor/fusion-framework-module-context 4.1.0 → 4.1.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.
@@ -1 +1 @@
1
- export declare const version = "4.1.0";
1
+ export declare const version = "4.1.1";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@equinor/fusion-framework-module-context",
3
- "version": "4.1.0",
3
+ "version": "4.1.1",
4
4
  "description": "",
5
5
  "main": "./dist/esm/index.js",
6
6
  "exports": {
@@ -21,6 +21,8 @@ export type ContextConfigBuilderCallback = <TDeps extends Array<AnyModule> = []>
21
21
  builder: ContextConfigBuilder<TDeps, ModuleInitializerArgs<IContextModuleConfigurator, TDeps>>,
22
22
  ) => void | Promise<void>;
23
23
 
24
+ // TODO - this should extend the BaseConfigBuilder
25
+
24
26
  export class ContextConfigBuilder<
25
27
  TModules extends Array<AnyModule> = [],
26
28
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
@@ -26,35 +26,114 @@ import Query from '@equinor/fusion-query';
26
26
  * WARNING: this is an initial out cast.
27
27
  * api clients will most probably not be exposed in future!
28
28
  */
29
+ /**
30
+ * Represents a context provider that manages the current context and provides methods for querying and manipulating context items.
31
+ */
29
32
  export interface IContextProvider {
30
33
  /** DANGER */
31
34
  readonly contextClient: ContextClient;
32
35
  /** DANGER */
33
36
  readonly queryClient: Query<ContextItem[], QueryContextParameters>;
34
37
 
38
+ // stream of current context
35
39
  readonly currentContext$: Observable<ContextItem | null | undefined>;
40
+
41
+ // current context of the current state
36
42
  currentContext: ContextItem | null | undefined;
43
+
44
+ /**
45
+ * Queries the context items based on the provided search string.
46
+ * @param search The search string.
47
+ * @returns An observable that emits an array of context items.
48
+ */
37
49
  queryContext(search: string): Observable<Array<ContextItem>>;
50
+
51
+ /**
52
+ * Queries the context items asynchronously based on the provided search string.
53
+ * @param search The search string.
54
+ * @returns A promise that resolves to an array of context items.
55
+ */
38
56
  queryContextAsync(search: string): Promise<Array<ContextItem>>;
57
+
58
+ /**
59
+ * Validates the given context item.
60
+ * @param item The context item to validate.
61
+ * @returns A boolean indicating whether the context item is valid or not.
62
+ */
39
63
  validateContext(item: ContextItem<Record<string, unknown>>): boolean;
64
+
65
+ /**
66
+ * Resolves the context item as a stream.
67
+ * @param current The current context item.
68
+ * @returns An observable that emits the resolved context item.
69
+ */
40
70
  resolveContext: (current: ContextItem) => Observable<ContextItem>;
71
+
72
+ /**
73
+ * Resolves the context item asynchronously.
74
+ * @param current The current context item.
75
+ * @returns A promise that resolves to the resolved context item.
76
+ */
41
77
  resolveContextAsync: (current: ContextItem) => Promise<ContextItem>;
78
+
79
+ /**
80
+ * Retrieves the related context items based on the provided parameters.
81
+ * @param args The parameters for retrieving related context items.
82
+ * @returns An observable that emits an array of related context items.
83
+ */
42
84
  relatedContexts: (
43
85
  args: RelatedContextParameters,
44
86
  ) => Observable<Array<ContextItem<Record<string, unknown>>>>;
87
+
88
+ /**
89
+ * Retrieves the related context items asynchronously based on the provided parameters.
90
+ * @param args The parameters for retrieving related context items.
91
+ * @returns A promise that resolves to an array of related context items.
92
+ */
45
93
  relatedContextsAsync: (
46
94
  args: RelatedContextParameters,
47
95
  ) => Promise<Array<ContextItem<Record<string, unknown>>>>;
96
+
97
+ /**
98
+ * Clears the current context.
99
+ */
48
100
  clearCurrentContext: VoidFunction;
49
101
 
102
+ /**
103
+ * Sets the current context item by its ID.
104
+ * @param id The ID of the context item.
105
+ * @returns An observable that emits the current context item.
106
+ */
50
107
  setCurrentContextById(id: string): Observable<ContextItem<Record<string, unknown>>>;
108
+
109
+ /**
110
+ * Sets the current context item by its ID asynchronously.
111
+ * @param id The ID of the context item.
112
+ * @returns A promise that resolves to the current context item.
113
+ */
51
114
  setCurrentContextByIdAsync(id: string): Promise<ContextItem<Record<string, unknown>>>;
52
115
 
116
+ /**
117
+ * Sets the current context item.
118
+ * @param context The context item to set as the current context.
119
+ * @param opt Optional settings for the operation.
120
+ * @param opt.validate Specifies whether to validate the context item. Default is `true`.
121
+ * @param opt.resolve Specifies whether to resolve the context item. Default is `true`.
122
+ * @returns An observable that emits the current context item or `null`.
123
+ */
53
124
  setCurrentContext(
54
125
  context: ContextItem<Record<string, unknown>> | null,
55
126
  opt?: { validate?: boolean; resolve?: boolean },
56
127
  ): Observable<ContextItem<Record<string, unknown>> | null>;
57
128
 
129
+ /**
130
+ * Sets the current context item asynchronously.
131
+ * @param context The context item to set as the current context.
132
+ * @param opt Optional settings for the operation.
133
+ * @param opt.validate Specifies whether to validate the context item. Default is `true`.
134
+ * @param opt.resolve Specifies whether to resolve the context item. Default is `true`.
135
+ * @returns A promise that resolves to the current context item or `null`.
136
+ */
58
137
  setCurrentContextAsync(
59
138
  context: ContextItem<Record<string, unknown>> | null,
60
139
  opt?: { validate?: boolean; resolve?: boolean },
@@ -72,7 +151,7 @@ export class ContextProvider implements IContextProvider {
72
151
 
73
152
  #contextType?: ContextModuleConfig['contextType'];
74
153
  #contextFilter: ContextModuleConfig['contextFilter'];
75
- #contextParameterFn: Required<ContextModuleConfig['contextParameterFn']>;
154
+ #contextParameterFn: Required<ContextModuleConfig>['contextParameterFn'];
76
155
 
77
156
  #contextQueue = new Subject<Observable<ContextItem<Record<string, unknown>>>>();
78
157
 
@@ -122,12 +201,14 @@ export class ContextProvider implements IContextProvider {
122
201
 
123
202
  this.#event = event;
124
203
 
204
+ // set the resolve and validate context functions
125
205
  config.resolveContext && (this.resolveContext = config.resolveContext?.bind(this));
126
206
  config.validateContext && (this.validateContext = config.validateContext?.bind(this));
127
207
 
128
208
  this.#contextType = config.contextType;
129
209
  this.#contextFilter = config.contextFilter;
130
210
 
211
+ // create clients
131
212
  this.#contextClient = new ContextClient(config.client.get);
132
213
  this.#contextQuery = new Query(config.client.query);
133
214
 
@@ -135,27 +216,36 @@ export class ContextProvider implements IContextProvider {
135
216
  this.#contextRelated = new Query(config.client.related);
136
217
  }
137
218
 
219
+ // set the context parameter function
138
220
  this.#contextParameterFn =
139
221
  config.contextParameterFn ??
222
+ // fallback to default
140
223
  ((args: Parameters<Required<ContextModuleConfig>['contextParameterFn']>[0]) => ({
141
224
  search: args.search,
142
225
  filter: { type: args.type },
143
226
  }));
144
227
 
228
+ // if event module is available, setup event listeners
145
229
  if (this.#event) {
146
230
  this.#subscriptions.add(
147
- this.currentContext$.pipe(pairwise()).subscribe(([previous, next]) => {
148
- this.#event?.dispatchEvent('onCurrentContextChanged', {
149
- source: this,
150
- canBubble: true,
151
- detail: { previous, next },
152
- });
153
- }),
231
+ // observe current context changes
232
+ this.currentContext$
233
+ .pipe(
234
+ // emit previous and next context
235
+ pairwise(),
236
+ )
237
+ .subscribe(([previous, next]) => {
238
+ this.#event?.dispatchEvent('onCurrentContextChanged', {
239
+ source: this,
240
+ canBubble: true,
241
+ detail: { previous, next },
242
+ });
243
+ }),
154
244
  );
155
245
  this.#subscriptions.add(
156
- /** observe event from child modules */
246
+ // observe current context changes from child modules
157
247
  this.#event.addEventListener('onCurrentContextChanged', (e) => {
158
- /** loop prevention */
248
+ // prevent infinite loop, only set context if source is not this
159
249
  if (e.source !== this && e.detail.next !== undefined) {
160
250
  this.setCurrentContext(e.detail.next);
161
251
  }
@@ -163,13 +253,18 @@ export class ContextProvider implements IContextProvider {
163
253
  );
164
254
  }
165
255
 
256
+ // wire up context queue
166
257
  this.#subscriptions.add(
167
258
  this.#contextQueue
168
259
  .pipe(
260
+ // resolve context item from queue
169
261
  switchMap((next) => next),
170
262
  tap((x) => console.debug('ContextProvider::#contextQueue', x)),
171
263
  )
172
- .subscribe((context) => this.#contextClient.setCurrentContext(context ?? null)),
264
+ .subscribe((context) => {
265
+ // set context from resolved context item from queue
266
+ this.#contextClient.setCurrentContext(context ?? null);
267
+ }),
173
268
  );
174
269
  }
175
270
 
@@ -181,6 +276,8 @@ export class ContextProvider implements IContextProvider {
181
276
  // do not set context if parent has not initialized
182
277
  filter((x): x is ContextItem | null => x !== undefined),
183
278
  filter((next, index) => {
279
+ // skip first item if opt.skipFirst is true
280
+ // TODO: this is a bit hacky, should be handled in a better way
184
281
  if (opt?.skipFirst && index <= 1) {
185
282
  console.debug(
186
283
  'ContextProvider::connectParentContext',
@@ -189,24 +286,29 @@ export class ContextProvider implements IContextProvider {
189
286
  );
190
287
  return false;
191
288
  }
289
+ // only set context if it has changed
192
290
  return this.currentContext?.id !== next?.id;
193
291
  }),
194
292
  switchMap(async (next) => {
195
- if (next) {
196
- const onParentContextChanged = await this.#event?.dispatchEvent(
197
- 'onParentContextChanged',
198
- {
199
- source: this,
200
- detail: next,
201
- cancelable: true,
202
- },
203
- );
204
- return { next, canceled: onParentContextChanged?.canceled };
293
+ if (!next) {
294
+ // if parent context is null, just return
295
+ return { next };
205
296
  }
206
- return { next };
297
+ // notify event observers that parent context is about to change and await for cancelation
298
+ const onParentContextChanged = await this.#event?.dispatchEvent(
299
+ 'onParentContextChanged',
300
+ {
301
+ source: this,
302
+ detail: next,
303
+ cancelable: true,
304
+ },
305
+ );
306
+ return { next, canceled: onParentContextChanged?.canceled };
207
307
  }),
308
+ // filter out canceled context changes
208
309
  filter((x) => !x.canceled),
209
310
  switchMap(({ next }) => {
311
+ // set current context with validation and resolution
210
312
  return this.setCurrentContext(next, {
211
313
  validate: true,
212
314
  resolve: true,
@@ -217,17 +319,22 @@ export class ContextProvider implements IContextProvider {
217
319
  'setCurrentContext',
218
320
  err,
219
321
  );
322
+ // do not emit any value if an error occurs
220
323
  return EMPTY;
221
324
  }),
222
325
  );
223
326
  }),
224
327
  catchError((err) => {
225
328
  console.warn('ContextProvider::onParentContextChanged', 'unhandled exception', err);
329
+ // do not emit any value if an error occurs
226
330
  return EMPTY;
227
331
  }),
228
332
  );
229
333
 
334
+ // subscribe to parent context changes
230
335
  const subscription = parentContext$.subscribe();
336
+
337
+ // add subscription to internal teardown
231
338
  this.#subscriptions.add(subscription);
232
339
  return subscription;
233
340
  }
@@ -236,19 +343,24 @@ export class ContextProvider implements IContextProvider {
236
343
  return new Observable((subscriber) => {
237
344
  try {
238
345
  this.#contextClient
346
+ // resolve context item by id
239
347
  .resolveContext(id)
240
348
  .pipe(
349
+ // filter out invalid context items
241
350
  filter((item): item is ContextItem => !!item),
351
+ // set current context with validation and resolution
242
352
  switchMap((item) => this.setCurrentContext(item)),
243
353
  )
244
354
  .subscribe(subscriber);
245
355
  } catch (err) {
356
+ // catch any unhandled exceptions and emit error
246
357
  subscriber.error(err);
247
358
  }
248
359
  });
249
360
  }
250
361
 
251
362
  public setCurrentContextByIdAsync(id: string): Promise<ContextItem<Record<string, unknown>>> {
363
+ // return last value from observable
252
364
  return lastValueFrom(this.setCurrentContextById(id));
253
365
  }
254
366
 
@@ -267,33 +379,33 @@ export class ContextProvider implements IContextProvider {
267
379
  context: T,
268
380
  opt?: { validate?: boolean; resolve?: boolean },
269
381
  ): Observable<T> {
270
- /** signal for aborting the queue entry */
382
+ // signal for aborting the queue entry
271
383
  const abort$ = new Subject();
272
384
 
273
- /** wrapper for returning an observable to the caller */
385
+ // wrapper for returning an observable to the caller
274
386
  const subject$ = new Subject<T>();
275
387
 
276
388
  const task$ = this._setCurrentContext(context, opt).pipe(
277
- /** send context item which was set to the caller */
389
+ // send context item which was set to the caller
278
390
  tap((x) => subject$.next(x)),
279
- /** abort task on signal */
391
+ // abort task on signal
280
392
  takeUntil(abort$),
281
- /** close observable sent to caller */
393
+ // close the observable sent to the caller
282
394
  finalize(() => subject$.complete()),
283
- /** catch errors to not stall queue */
395
+ // catch any unhandled exceptions to not stall the queue
284
396
  catchError((err) => {
285
- /** send the error to the caller */
397
+ // emit error to caller
286
398
  subject$.error(err);
287
- /** skip setting any context */
399
+ // skip setting any context
288
400
  return EMPTY;
289
401
  }),
290
402
  );
291
403
 
292
- /** add task to internal queue */
404
+ // add task to internal queue
293
405
  this.#contextQueue.next(task$ as Observable<ContextItem<Record<string, unknown>>>);
294
406
 
295
407
  return subject$.pipe(
296
- /** if caller subscribes, unsubscribe should abort queue entry */
408
+ // if caller subscribes, unsubscribe should abort queue entry
297
409
  finalize(() => abort$.next(true)),
298
410
  );
299
411
  }
@@ -303,24 +415,29 @@ export class ContextProvider implements IContextProvider {
303
415
  opt?: { validate?: boolean; resolve?: boolean },
304
416
  ): Observable<T> {
305
417
  return new Observable((subscriber) => {
418
+ // if context is the same as current, just emit and complete
306
419
  if (context === this.currentContext) {
307
420
  subscriber.next(context);
308
421
  return subscriber.complete();
309
422
  }
423
+ // check if context is provided and should be validated
310
424
  if (context && opt?.validate && !this.validateContext(context)) {
425
+ // check if the resolve context is provided
311
426
  if (!opt.resolve) {
312
- /** cannot resolve context, and provided is invalid */
427
+ // notify event observers that context validation failed since resolve is not provided
313
428
  this.#event?.dispatchEvent('onSetContextValidationFailed', {
314
429
  source: this,
315
430
  detail: { context },
316
431
  });
432
+ // emit error and complete
317
433
  return subscriber.error(Error('failed to validate provided context'));
318
434
  }
319
435
  if (opt.resolve) {
320
436
  return of(context)
321
437
  .pipe(
322
- /** notify event observers that context is about to get resolved */
438
+ // notify event observers that context is about to get resolved
323
439
  switchMap(async (context) => {
440
+ // wait for event listeners to handle the event
324
441
  const event = await this.#event?.dispatchEvent(
325
442
  'onSetContextResolve',
326
443
  {
@@ -329,12 +446,13 @@ export class ContextProvider implements IContextProvider {
329
446
  detail: { context },
330
447
  },
331
448
  );
449
+ // check if event was canceled and abort if so
332
450
  if (event?.canceled) {
333
451
  throw Error('resolving of context was canceled');
334
452
  }
335
453
  return context;
336
454
  }),
337
- /** execute resolve */
455
+ // resolve context
338
456
  switchMap((context) =>
339
457
  this.resolveContext(context).pipe(
340
458
  map((resolved) => ({
@@ -343,8 +461,9 @@ export class ContextProvider implements IContextProvider {
343
461
  })),
344
462
  ),
345
463
  ),
346
- /** notify event observers that context was resolved */
464
+ // notify event listeners that context was resolved
347
465
  switchMap(async ({ context, resolved }) => {
466
+ // wait for event listeners to handle the event
348
467
  const event = await this.#event?.dispatchEvent(
349
468
  'onSetContextResolved',
350
469
  {
@@ -353,12 +472,13 @@ export class ContextProvider implements IContextProvider {
353
472
  detail: { context, resolved },
354
473
  },
355
474
  );
475
+ // check if event was canceled and abort if so
356
476
  if (event?.canceled) {
357
477
  throw Error('resolving of context was canceled');
358
478
  }
359
479
  return resolved;
360
480
  }),
361
- /** recursive set current context without validation and resolve */
481
+ // recursive call to set current context without validation and resolution
362
482
  switchMap((resolved) =>
363
483
  this._setCurrentContext(resolved as unknown as T),
364
484
  ),
@@ -367,8 +487,10 @@ export class ContextProvider implements IContextProvider {
367
487
  }
368
488
  }
369
489
 
490
+ // make the context an observable
370
491
  return of(context)
371
492
  .pipe(
493
+ // alert event listeners that context is about to change
372
494
  switchMap(async (context) => {
373
495
  const event = await this.#event?.dispatchEvent('onCurrentContextChange', {
374
496
  source: this,
@@ -377,6 +499,7 @@ export class ContextProvider implements IContextProvider {
377
499
  detail: { context: context },
378
500
  });
379
501
 
502
+ // check if event was canceled and abort if so
380
503
  if (event?.canceled) {
381
504
  throw Error('change of context was aborted');
382
505
  }
@@ -385,7 +508,9 @@ export class ContextProvider implements IContextProvider {
385
508
  }),
386
509
  )
387
510
  .subscribe((context) => {
511
+ // emit context to the caller
388
512
  subscriber.next(context);
513
+ // only take the first value and complete
389
514
  subscriber.complete();
390
515
  });
391
516
  });
@@ -401,13 +526,15 @@ export class ContextProvider implements IContextProvider {
401
526
  public queryContext(search: string): Observable<Array<ContextItem>> {
402
527
  const query$ = this.queryClient
403
528
  .query(
404
- // TODO
405
- // eslint-disable-next-line @typescript-eslint/ban-ts-comment
406
- /* @ts-ignore */
407
- this.#contextParameterFn({ search, type: this.#contextType }),
529
+ // generate query parameters
530
+ this.#contextParameterFn({
531
+ search,
532
+ type: this.#contextType,
533
+ }) as QueryContextParameters,
408
534
  )
409
535
  .pipe(
410
536
  catchError((err) => {
537
+ // if query client throws a QueryClientError, extract the cause and throw it
411
538
  if (err.name === 'QueryClientError') {
412
539
  throw err.cause;
413
540
  }
@@ -416,6 +543,7 @@ export class ContextProvider implements IContextProvider {
416
543
  map((x) => x.value),
417
544
  );
418
545
 
546
+ // apply context filter if available
419
547
  return this.#contextFilter ? query$.pipe(map(this.#contextFilter)) : query$;
420
548
  }
421
549
 
@@ -431,13 +559,20 @@ export class ContextProvider implements IContextProvider {
431
559
  public resolveContext(
432
560
  item: ContextItem<Record<string, unknown>>,
433
561
  ): Observable<ContextItem<Record<string, unknown>>> {
562
+ // request related context items for the given context item with the same context type which the provider is configured with
434
563
  return this.relatedContexts({ item, filter: { type: this.#contextType } }).pipe(
564
+ // filter out invalid context items
435
565
  map((x) => x.filter((item) => this.validateContext(item))),
436
566
  map((values) => {
567
+ // related context should be resolved to a single context item
437
568
  const value = values.shift();
569
+
570
+ // if no value is found, throw an error
438
571
  if (!value) {
439
572
  throw Error('failed to resolve context');
440
573
  }
574
+
575
+ // if multiple items are found, log a warning
441
576
  if (values.length) {
442
577
  console.warn(
443
578
  'ContextProvider::relatedContext',
@@ -445,6 +580,8 @@ export class ContextProvider implements IContextProvider {
445
580
  values,
446
581
  );
447
582
  }
583
+
584
+ // return the resolved context item
448
585
  return value;
449
586
  }),
450
587
  );
@@ -459,6 +596,7 @@ export class ContextProvider implements IContextProvider {
459
596
  public relatedContexts(
460
597
  args: RelatedContextParameters,
461
598
  ): Observable<Array<ContextItem<Record<string, unknown>>>> {
599
+ // check if related context client is available
462
600
  if (!this.#contextRelated) {
463
601
  return throwError(() =>
464
602
  Error(
@@ -466,6 +604,8 @@ export class ContextProvider implements IContextProvider {
466
604
  ),
467
605
  );
468
606
  }
607
+
608
+ // request related context items
469
609
  return this.#contextRelated.query(args).pipe(
470
610
  map(({ value }) => value),
471
611
  catchError((err) => {
@@ -497,7 +637,7 @@ export default ContextProvider;
497
637
 
498
638
  declare module '@equinor/fusion-framework-module-event' {
499
639
  interface FrameworkEventMap {
500
- /** dispatch before context changes */
640
+ // event which is dispatched before the context changes
501
641
  onCurrentContextChange: FrameworkEvent<
502
642
  FrameworkEventInit<
503
643
  {
@@ -506,7 +646,7 @@ declare module '@equinor/fusion-framework-module-event' {
506
646
  IContextProvider
507
647
  >
508
648
  >;
509
- /** dispatch after context changed */
649
+ // event which is dispatched after the context changes
510
650
  onCurrentContextChanged: FrameworkEvent<
511
651
  FrameworkEventInit<
512
652
  {
@@ -516,6 +656,8 @@ declare module '@equinor/fusion-framework-module-event' {
516
656
  IContextProvider
517
657
  >
518
658
  >;
659
+
660
+ // event which is dispatched before the parent context changes
519
661
  onParentContextChanged: FrameworkEvent<
520
662
  FrameworkEventInit<
521
663
  {
@@ -525,6 +667,7 @@ declare module '@equinor/fusion-framework-module-event' {
525
667
  >
526
668
  >;
527
669
 
670
+ // event which is dispatched before the context will be resolved
528
671
  onSetContextResolve: FrameworkEvent<
529
672
  FrameworkEventInit<
530
673
  {
@@ -533,6 +676,8 @@ declare module '@equinor/fusion-framework-module-event' {
533
676
  IContextProvider
534
677
  >
535
678
  >;
679
+
680
+ // event which is dispatched after the context was resolved
536
681
  onSetContextResolved: FrameworkEvent<
537
682
  FrameworkEventInit<
538
683
  {
@@ -542,6 +687,8 @@ declare module '@equinor/fusion-framework-module-event' {
542
687
  IContextProvider
543
688
  >
544
689
  >;
690
+
691
+ // event which is dispatched if the context validation failed
545
692
  onSetContextValidationFailed: FrameworkEvent<
546
693
  FrameworkEventInit<
547
694
  {
@@ -550,6 +697,8 @@ declare module '@equinor/fusion-framework-module-event' {
550
697
  IContextProvider
551
698
  >
552
699
  >;
700
+
701
+ // event which is dispatched if the context resolve failed
553
702
  onSetContextResolveFailed: FrameworkEvent<
554
703
  FrameworkEventInit<
555
704
  {
package/src/errors.ts CHANGED
@@ -1,17 +1,37 @@
1
+ /**
2
+ * Represents an error that occurs during a search in the Fusion Context.
3
+ */
1
4
  export class FusionContextSearchError extends Error {
2
5
  #details;
3
6
 
7
+ /**
8
+ * The title of the error.
9
+ */
4
10
  get title(): string {
5
11
  return this.#details.title;
6
12
  }
7
13
 
14
+ /**
15
+ * The description of the error, if available.
16
+ */
8
17
  get description(): string | undefined {
9
18
  return this.#details.description;
10
19
  }
11
20
 
21
+ /**
22
+ * Creates a new instance of FusionContextSearchError.
23
+ * @param details - The details of the error.
24
+ * @param options - Optional parameters for the error.
25
+ */
12
26
  constructor(
13
27
  details: {
28
+ /**
29
+ * The title of the error.
30
+ */
14
31
  title: string;
32
+ /**
33
+ * The description of the error, if available.
34
+ */
15
35
  description?: string;
16
36
  },
17
37
  options?: ErrorOptions,