@equinor/fusion-framework-module-bookmark 4.0.2 → 4.0.4

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 (117) hide show
  1. package/CHANGELOG.md +19 -0
  2. package/dist/esm/BookmarkClient.js +18 -3
  3. package/dist/esm/BookmarkClient.js.map +1 -1
  4. package/dist/esm/{BookmarkProvider.error.js → BookmarkFlowError.js} +9 -7
  5. package/dist/esm/BookmarkFlowError.js.map +1 -0
  6. package/dist/esm/{BookmarkConfigurator.js → BookmarkModuleConfigurator.js} +38 -6
  7. package/dist/esm/BookmarkModuleConfigurator.js.map +1 -0
  8. package/dist/esm/BookmarkProvider.js +112 -23
  9. package/dist/esm/BookmarkProvider.js.map +1 -1
  10. package/dist/esm/BookmarkProvider.selectors.js +8 -0
  11. package/dist/esm/BookmarkProvider.selectors.js.map +1 -1
  12. package/dist/esm/BookmarkProviderError.js +20 -0
  13. package/dist/esm/BookmarkProviderError.js.map +1 -0
  14. package/dist/esm/{BookmarkProvider.actions.js → bookmark-actions.js} +1 -1
  15. package/dist/esm/bookmark-actions.js.map +1 -0
  16. package/dist/esm/bookmark-config.schema.js +2 -0
  17. package/dist/esm/bookmark-config.schema.js.map +1 -1
  18. package/dist/esm/bookmark-flows/bookmark-api-flows.js +28 -0
  19. package/dist/esm/bookmark-flows/bookmark-api-flows.js.map +1 -0
  20. package/dist/esm/bookmark-flows/handle-add-bookmark-as-favorite.js +27 -0
  21. package/dist/esm/bookmark-flows/handle-add-bookmark-as-favorite.js.map +1 -0
  22. package/dist/esm/bookmark-flows/handle-create-bookmark.js +27 -0
  23. package/dist/esm/bookmark-flows/handle-create-bookmark.js.map +1 -0
  24. package/dist/esm/bookmark-flows/handle-delete-bookmark.js +26 -0
  25. package/dist/esm/bookmark-flows/handle-delete-bookmark.js.map +1 -0
  26. package/dist/esm/bookmark-flows/handle-fetch-all-bookmark.js +29 -0
  27. package/dist/esm/bookmark-flows/handle-fetch-all-bookmark.js.map +1 -0
  28. package/dist/esm/bookmark-flows/handle-fetch-bookmark-data.js +26 -0
  29. package/dist/esm/bookmark-flows/handle-fetch-bookmark-data.js.map +1 -0
  30. package/dist/esm/bookmark-flows/handle-fetch-bookmark.js +30 -0
  31. package/dist/esm/bookmark-flows/handle-fetch-bookmark.js.map +1 -0
  32. package/dist/esm/bookmark-flows/handle-remove-bookmark-from-favorites.js +28 -0
  33. package/dist/esm/bookmark-flows/handle-remove-bookmark-from-favorites.js.map +1 -0
  34. package/dist/esm/bookmark-flows/handle-remove-bookmark.js +49 -0
  35. package/dist/esm/bookmark-flows/handle-remove-bookmark.js.map +1 -0
  36. package/dist/esm/bookmark-flows/handle-update-bookmark.js +28 -0
  37. package/dist/esm/bookmark-flows/handle-update-bookmark.js.map +1 -0
  38. package/dist/esm/bookmark-flows/index.js +11 -0
  39. package/dist/esm/bookmark-flows/index.js.map +1 -0
  40. package/dist/esm/bookmark-module.js +2 -2
  41. package/dist/esm/bookmark-module.js.map +1 -1
  42. package/dist/esm/bookmark.schemas.js +9 -3
  43. package/dist/esm/bookmark.schemas.js.map +1 -1
  44. package/dist/esm/create-bookmark-reducer.js +122 -0
  45. package/dist/esm/create-bookmark-reducer.js.map +1 -0
  46. package/dist/esm/{BookmarkProvider.store.js → create-bookmark-store.js} +3 -3
  47. package/dist/esm/create-bookmark-store.js.map +1 -0
  48. package/dist/esm/enable-bookmark.js +2 -1
  49. package/dist/esm/enable-bookmark.js.map +1 -1
  50. package/dist/esm/index.js +12 -1
  51. package/dist/esm/index.js.map +1 -1
  52. package/dist/esm/version.js +1 -1
  53. package/dist/tsconfig.tsbuildinfo +1 -1
  54. package/dist/types/BookmarkClient.d.ts +1 -0
  55. package/dist/types/{BookmarkProvider.error.d.ts → BookmarkFlowError.d.ts} +9 -4
  56. package/dist/types/{BookmarkConfigurator.d.ts → BookmarkModuleConfigurator.d.ts} +10 -4
  57. package/dist/types/BookmarkProvider.d.ts +81 -18
  58. package/dist/types/BookmarkProvider.interface.d.ts +1 -1
  59. package/dist/types/BookmarkProvider.selectors.d.ts +3 -3
  60. package/dist/types/BookmarkProviderError.d.ts +16 -0
  61. package/dist/types/{BookmarkProvider.actions.d.ts → bookmark-actions.d.ts} +3 -3
  62. package/dist/types/bookmark-flows/bookmark-api-flows.d.ts +11 -0
  63. package/dist/types/bookmark-flows/handle-add-bookmark-as-favorite.d.ts +10 -0
  64. package/dist/types/bookmark-flows/handle-create-bookmark.d.ts +10 -0
  65. package/dist/types/bookmark-flows/handle-delete-bookmark.d.ts +10 -0
  66. package/dist/types/bookmark-flows/handle-fetch-all-bookmark.d.ts +10 -0
  67. package/dist/types/bookmark-flows/handle-fetch-bookmark-data.d.ts +10 -0
  68. package/dist/types/bookmark-flows/handle-fetch-bookmark.d.ts +10 -0
  69. package/dist/types/bookmark-flows/handle-remove-bookmark-from-favorites.d.ts +10 -0
  70. package/dist/types/bookmark-flows/handle-remove-bookmark.d.ts +14 -0
  71. package/dist/types/bookmark-flows/handle-update-bookmark.d.ts +10 -0
  72. package/dist/types/bookmark-flows/index.d.ts +10 -0
  73. package/dist/types/bookmark-module.d.ts +1 -1
  74. package/dist/types/{BookmarkProvider.reducer.d.ts → create-bookmark-reducer.d.ts} +39 -39
  75. package/dist/types/{BookmarkProvider.store.d.ts → create-bookmark-store.d.ts} +2 -2
  76. package/dist/types/enable-bookmark.d.ts +1 -1
  77. package/dist/types/index.d.ts +12 -1
  78. package/dist/types/version.d.ts +1 -1
  79. package/package.json +11 -11
  80. package/src/BookmarkClient.ts +21 -3
  81. package/src/{BookmarkProvider.error.ts → BookmarkFlowError.ts} +9 -7
  82. package/src/{BookmarkConfigurator.ts → BookmarkModuleConfigurator.ts} +42 -12
  83. package/src/BookmarkProvider.interface.ts +3 -2
  84. package/src/BookmarkProvider.selectors.ts +10 -2
  85. package/src/BookmarkProvider.ts +112 -23
  86. package/src/BookmarkProviderError.ts +19 -0
  87. package/src/{BookmarkProvider.actions.ts → bookmark-actions.ts} +1 -1
  88. package/src/bookmark-config.schema.ts +2 -0
  89. package/src/bookmark-flows/bookmark-api-flows.ts +45 -0
  90. package/src/bookmark-flows/handle-add-bookmark-as-favorite.ts +49 -0
  91. package/src/bookmark-flows/handle-create-bookmark.ts +47 -0
  92. package/src/bookmark-flows/handle-delete-bookmark.ts +47 -0
  93. package/src/bookmark-flows/handle-fetch-all-bookmark.ts +53 -0
  94. package/src/bookmark-flows/handle-fetch-bookmark-data.ts +58 -0
  95. package/src/bookmark-flows/handle-fetch-bookmark.ts +64 -0
  96. package/src/bookmark-flows/handle-remove-bookmark-from-favorites.ts +49 -0
  97. package/src/bookmark-flows/handle-remove-bookmark.ts +76 -0
  98. package/src/bookmark-flows/handle-update-bookmark.ts +48 -0
  99. package/src/bookmark-flows/index.ts +10 -0
  100. package/src/bookmark-module.ts +2 -2
  101. package/src/bookmark.schemas.ts +10 -4
  102. package/src/create-bookmark-reducer.ts +149 -0
  103. package/src/{BookmarkProvider.store.ts → create-bookmark-store.ts} +4 -4
  104. package/src/enable-bookmark.ts +3 -2
  105. package/src/index.ts +12 -1
  106. package/src/version.ts +1 -1
  107. package/dist/esm/BookmarkConfigurator.js.map +0 -1
  108. package/dist/esm/BookmarkProvider.actions.js.map +0 -1
  109. package/dist/esm/BookmarkProvider.error.js.map +0 -1
  110. package/dist/esm/BookmarkProvider.flows.js +0 -217
  111. package/dist/esm/BookmarkProvider.flows.js.map +0 -1
  112. package/dist/esm/BookmarkProvider.reducer.js +0 -113
  113. package/dist/esm/BookmarkProvider.reducer.js.map +0 -1
  114. package/dist/esm/BookmarkProvider.store.js.map +0 -1
  115. package/dist/types/BookmarkProvider.flows.d.ts +0 -79
  116. package/src/BookmarkProvider.flows.ts +0 -421
  117. package/src/BookmarkProvider.reducer.ts +0 -144
@@ -6,10 +6,10 @@ import deepEqual from 'fast-deep-equal/es6';
6
6
  import { FrameworkEvent, } from '@equinor/fusion-framework-module-event';
7
7
  import { isFailureAction } from '@equinor/fusion-observable';
8
8
  import { SemanticVersion } from '@equinor/fusion-framework-module';
9
- import { bookmarkActions } from './BookmarkProvider.actions';
10
- import { createBookmarkStore, } from './BookmarkProvider.store';
9
+ import { bookmarkActions } from './bookmark-actions';
10
+ import { createBookmarkStore, } from './create-bookmark-store';
11
11
  import { activeBookmarkSelector, bookmarkSelector, bookmarksSelector, errorsSelector, } from './BookmarkProvider.selectors';
12
- import { BookmarkProviderError } from './BookmarkProvider.error';
12
+ import { BookmarkProviderError } from './BookmarkFlowError';
13
13
  import { version } from './version';
14
14
  // Default timeout for bookmark operations (2 minutes)
15
15
  const defaultTimeout = 2 * 60 * 1000;
@@ -38,7 +38,7 @@ export class BookmarkProvider {
38
38
  return {
39
39
  getCurrentAppIdentification() {
40
40
  // eslint-disable-next-line @typescript-eslint/ban-ts-comment
41
- // @ts-ignore
41
+ // @ts-expect-error
42
42
  return window.Fusion.modules.app.current.appKey;
43
43
  },
44
44
  };
@@ -46,6 +46,9 @@ export class BookmarkProvider {
46
46
  /**
47
47
  * @deprecated
48
48
  * this will be removed as soon as applications have been migrated to use the bookmark provider
49
+ * @param fn - The payload generator callback to register.
50
+ * @template T - The bookmark data type produced by the generator.
51
+ * @returns A function that unregisters the payload generator when called.
49
52
  */
50
53
  addStateCreator(fn) {
51
54
  console.warn('addStateCreator is deprecated, use addPayloadGenerator instead');
@@ -54,6 +57,7 @@ export class BookmarkProvider {
54
57
  /**
55
58
  * @deprecated
56
59
  * this will be removed as soon as applications have been migrated to use the bookmark provider
60
+ * @param id - The ID of the bookmark to delete.
57
61
  */
58
62
  deleteBookmarkByIdAsync(id) {
59
63
  console.warn('deleteBookmarkByIdAsync is deprecated, use deleteBookmarkAsync instead');
@@ -62,6 +66,8 @@ export class BookmarkProvider {
62
66
  /**
63
67
  * @deprecated
64
68
  * this will be removed as soon as applications have been migrated to use the bookmark provider
69
+ * @param id - The ID of the bookmark to add as a favorite.
70
+ * @returns The updated bookmark, or undefined if it could not be found.
65
71
  */
66
72
  addBookmarkFavoriteAsync(id) {
67
73
  console.warn('addBookmarkFavoriteAsync is deprecated, use addBookmarkToFavoritesAsync instead');
@@ -70,6 +76,7 @@ export class BookmarkProvider {
70
76
  /**
71
77
  * @deprecated
72
78
  * this will be removed as soon as applications have been migrated to use the bookmark provider
79
+ * @param id - The ID of the bookmark to remove as a favorite.
73
80
  */
74
81
  removeBookmarkFavoriteAsync(id) {
75
82
  console.warn('removeBookmarkFavoriteAsync is deprecated, use removeBookmarkAsFavoriteAsync instead');
@@ -78,6 +85,8 @@ export class BookmarkProvider {
78
85
  /**
79
86
  * @deprecated
80
87
  * this will be removed as soon as applications have been migrated to use the bookmark provider
88
+ * @param id - The ID of the bookmark to get.
89
+ * @returns The bookmark, or null if it could not be found.
81
90
  */
82
91
  getBookmarkById(id) {
83
92
  console.warn('getBookmarkById is deprecated, use getBookmarkAsync instead');
@@ -85,28 +94,33 @@ export class BookmarkProvider {
85
94
  }
86
95
  /**
87
96
  * Gets the semantic version of the bookmark provider.
97
+ * @returns The semantic version of the bookmark provider.
88
98
  */
89
99
  get version() {
90
100
  return new SemanticVersion(version);
91
101
  }
102
+ /** @returns The configured bookmark filters. */
92
103
  get filters() {
93
- // TODO - freeze the config object?
104
+ // TODO(#5136) - freeze the config object?
94
105
  return this.#config.filters;
95
106
  }
96
107
  /**
97
108
  * Gets the `IBookmarkClient` instance used by this `BookmarkProvider`.
109
+ * @returns The `IBookmarkClient` instance.
98
110
  */
99
111
  get client() {
100
112
  return this.#config.client;
101
113
  }
102
114
  /**
103
115
  * Gets the currently active bookmark (if any).
116
+ * @returns An observable of the currently active bookmark.
104
117
  */
105
118
  get currentBookmark$() {
106
119
  return this.#store.select(activeBookmarkSelector);
107
120
  }
108
121
  /**
109
122
  * Gets an observable that emits the current list of bookmarks.
123
+ * @returns An observable of the current list of bookmarks.
110
124
  */
111
125
  get bookmarks$() {
112
126
  this.getAllBookmarksAsync();
@@ -114,12 +128,14 @@ export class BookmarkProvider {
114
128
  }
115
129
  /**
116
130
  * Gets the current list of bookmarks.
131
+ * @returns The current list of bookmarks.
117
132
  */
118
133
  get bookmarks() {
119
134
  return bookmarksSelector(this.#store.value);
120
135
  }
121
136
  /**
122
137
  * Gets the currently active bookmark.
138
+ * @returns The currently active bookmark, or null/undefined if there is none.
123
139
  */
124
140
  get currentBookmark() {
125
141
  const bookmark = activeBookmarkSelector(this.#store.value);
@@ -127,65 +143,78 @@ export class BookmarkProvider {
127
143
  }
128
144
  /**
129
145
  * Represents an observable stream of the bookmark status.
146
+ * @returns An observable of the bookmark status.
130
147
  */
131
148
  get status$() {
132
149
  return this.#store.select((x) => x.status);
133
150
  }
134
151
  /**
135
152
  * Gets an observable that emits the current list of bookmark errors.
153
+ * @returns An observable of the current list of bookmark errors.
136
154
  */
137
155
  get errors$() {
138
- // TODO - add deep diff
156
+ // TODO(#5137) - add deep diff
139
157
  return this.#store.select(errorsSelector, deepEqual);
140
158
  }
141
159
  /**
142
160
  * Determines whether there are any bookmark creators configured.
143
- * `true` if there are any bookmark creators configured, `false` otherwise.
161
+ * @returns `true` if there are any bookmark creators configured, `false` otherwise.
144
162
  */
145
163
  get canCreateBookmarks() {
146
164
  return this.#payloadGenerators.length > 0;
147
165
  }
148
166
  /**
149
167
  * Gets the source system value from the configuration.
168
+ * @returns The source system value.
150
169
  */
151
170
  get sourceSystem() {
152
171
  return this.#config.sourceSystem;
153
172
  }
154
173
  /**
155
174
  * Gets the resolved application from the bookmark module configuration.
175
+ * @returns The resolved application resolver.
156
176
  */
157
177
  get resolvedApplication() {
158
178
  return this.#config.resolve.application;
159
179
  }
160
180
  /**
161
181
  * Gets the resolved context from the bookmark module configuration.
182
+ * @returns The resolved context resolver.
162
183
  */
163
184
  get resolvedContext() {
164
185
  return this.#config.resolve.context;
165
186
  }
187
+ /**
188
+ * @internal The API client used to communicate with the bookmark backend.
189
+ * @returns The configured `IBookmarkClient` instance.
190
+ */
166
191
  get _apiClient() {
167
192
  return this.#config.client;
168
193
  }
169
194
  /**
170
195
  * configured logger instance.
196
+ * @returns The configured logger.
171
197
  */
172
198
  get _log() {
173
199
  return this.#config.log;
174
200
  }
175
201
  /**
176
202
  * configured resolvers
203
+ * @returns The configured resolvers.
177
204
  */
178
205
  get _resolve() {
179
206
  return this.#config.resolve;
180
207
  }
181
208
  /**
182
209
  * configured event provider.
210
+ * @returns The configured event provider.
183
211
  */
184
212
  get _event() {
185
213
  return this.#config.eventProvider;
186
214
  }
187
215
  /**
188
216
  * configured parent bookmark provider
217
+ * @returns The configured parent bookmark provider.
189
218
  */
190
219
  get _parent() {
191
220
  return this.#config.parent;
@@ -205,6 +234,7 @@ export class BookmarkProvider {
205
234
  this.#subscriptions.add(() => this.#store.complete());
206
235
  // subscribe to the store actions and log them
207
236
  this.#subscriptions.add(this.#store.action$.subscribe((action) => {
237
+ // log failure actions as errors, everything else as debug
208
238
  if (isFailureAction(action)) {
209
239
  this._log?.error(`Action: ${action.type}`, action);
210
240
  }
@@ -220,7 +250,7 @@ export class BookmarkProvider {
220
250
  }
221
251
  }));
222
252
  // subscribe to child bookmark provider changes
223
- // TODO - add support for disabling this feature
253
+ // TODO(#5138) - add support for disabling this feature
224
254
  if (this._event) {
225
255
  this._event.addEventListener('onCurrentBookmarkChanged', (event) => {
226
256
  const { source, detail } = event;
@@ -233,10 +263,11 @@ export class BookmarkProvider {
233
263
  }
234
264
  });
235
265
  }
266
+ // if a parent bookmark provider is configured, subscribe to its current bookmark changes
236
267
  if (this._parent) {
237
- // if a parent bookmark provider is configured, subscribe to its current bookmark changes
238
268
  try {
239
269
  this.#subscriptions.add(this._parent.currentBookmark$
270
+ // only forward defined bookmarks that differ from the current one
240
271
  .pipe(filter((x) => x !== undefined), filter((x) => x !== this.currentBookmark))
241
272
  .subscribe((bookmark) => {
242
273
  this.#store.next(bookmarkActions.setCurrentBookmark(bookmark));
@@ -250,12 +281,14 @@ export class BookmarkProvider {
250
281
  /**
251
282
  * Registers an event listener for the specified event on the BookmarkProvider.
252
283
  *
284
+ * @template TType - The key of the `BookmarkProviderEventMap` identifying the event.
253
285
  * @param eventName - The name of the event to listen for. Must be a key of the `BookmarkProviderEventMap` type.
254
286
  * @param callback - The callback function to be invoked when the event is triggered.
255
287
  * The callback will receive the event object as its parameter, which will be of the type corresponding to the `eventName`.
256
288
  * @returns A function that can be called to remove the event listener.
257
289
  */
258
290
  on(eventName, callback) {
291
+ // without an event provider, registering a listener would be a no-op
259
292
  if (!this._event) {
260
293
  this._log?.warn('Failed to register event listener, event provider not configured');
261
294
  return () => {
@@ -263,6 +296,7 @@ export class BookmarkProvider {
263
296
  };
264
297
  }
265
298
  return this._event.addEventListener(eventName, (event) => {
299
+ // only forward events originating from this provider instance
266
300
  if (event.source === this) {
267
301
  callback(event);
268
302
  }
@@ -272,6 +306,7 @@ export class BookmarkProvider {
272
306
  * Adds a new payload generator function to the BookmarkProvider.
273
307
  * The payload generator function will be used to generate the payload for a bookmark-related action.
274
308
  *
309
+ * @template T - The type of the bookmark data the payload generator produces.
275
310
  * @param fn - The payload generator function to add. It should be of type `PayloadGenerator<T>`, where `T` is the type of the bookmark data.
276
311
  * @returns A function that can be called to remove the added payload generator.
277
312
  */
@@ -286,6 +321,7 @@ export class BookmarkProvider {
286
321
  // return a function to remove the added payload generator
287
322
  return () => {
288
323
  this._log?.debug(`removing bookmark payload generator: ${fn.name}`);
324
+ // drop the matching generator reference from the registered list
289
325
  this.#payloadGenerators = this.#payloadGenerators.filter((g) => g !== fn);
290
326
  };
291
327
  }
@@ -348,6 +384,7 @@ export class BookmarkProvider {
348
384
  * @param bookmarkId The unique identifier of the bookmark.
349
385
  * @param options An optional object that allows excluding the bookmark payload from the result.
350
386
  * @returns An observable that emits the combined result of fetching the bookmark and bookmark data.
387
+ * @throws The error encountered while fetching the bookmark or its data, after logging it.
351
388
  */
352
389
  getBookmark(bookmarkId, options) {
353
390
  this._log?.debug(`fetching bookmark: ${bookmarkId}`, options);
@@ -367,6 +404,7 @@ export class BookmarkProvider {
367
404
  /**
368
405
  * Retrieves a bookmark asynchronously.
369
406
  *
407
+ * @template T - The type of the bookmark payload.
370
408
  * @param id - The ID of the bookmark to retrieve.
371
409
  * @param options - Optional parameters for the retrieval.
372
410
  * @param options.excludePayload - Specifies whether to exclude the payload from the bookmark.
@@ -483,6 +521,7 @@ export class BookmarkProvider {
483
521
  * @param bookmark_or_id - The bookmark or ID to set as the current bookmark.
484
522
  * @returns An observable that emits the next bookmark or null.
485
523
  * @template T - The type of the bookmark data.
524
+ * @throws {BookmarkProviderError} If the onCurrentBookmarkChange event is canceled by a listener, or resolving the bookmark fails.
486
525
  */
487
526
  setCurrentBookmark(bookmark_or_id) {
488
527
  this._log?.debug('setting current bookmark', bookmark_or_id);
@@ -490,11 +529,13 @@ export class BookmarkProvider {
490
529
  const next$ = typeof bookmark_or_id === 'string'
491
530
  ? this.getBookmark(bookmark_or_id)
492
531
  : of(bookmark_or_id ?? null);
532
+ // notify listeners before committing the next bookmark to the store
493
533
  return next$.pipe(switchMap(async (next) => {
494
534
  const current = this.currentBookmark;
495
535
  const { type, canceled } = await this._dispatchEvent('onCurrentBookmarkChange', {
496
536
  detail: { current, next },
497
537
  });
538
+ // throw an error if the event is canceled
498
539
  if (canceled) {
499
540
  const error = new BookmarkProviderError(`event: ${type} was canceled by listener for change to ${next?.id ?? 'none'}, from ${current?.id ?? 'none'}`);
500
541
  this._log?.info(error.message);
@@ -511,14 +552,11 @@ export class BookmarkProvider {
511
552
  }));
512
553
  }
513
554
  /**
514
- * Sets the current bookmark.
515
- * This method dispatches an event to notify listeners of a change in the current bookmark,
516
- * and then dispatches a request to set the active bookmark in the application state.
555
+ * Sets the current bookmark asynchronously.
517
556
  *
518
- * The request will be canceled if the subscription is unsubscribed before the request completes.
519
- *
520
- * @param bookmarkId - The ID of the bookmark to set as the current bookmark.
521
- * @returns A subscription to the operation that sets the current bookmark.
557
+ * @template T - The type of the bookmark data.
558
+ * @param bookmark_or_id - The bookmark or ID to set as the current bookmark.
559
+ * @returns A promise that resolves to the next bookmark or null.
522
560
  */
523
561
  setCurrentBookmarkAsync(bookmark_or_id) {
524
562
  return lastValueFrom(this.setCurrentBookmark(bookmark_or_id));
@@ -529,6 +567,7 @@ export class BookmarkProvider {
529
567
  * @template T - The type of bookmark data.
530
568
  * @param {BookmarkCreateArgs<T>} newBookmarkData - The data for creating the bookmark.
531
569
  * @returns {Observable<Bookmark<T>>} - An observable that emits the created bookmark.
570
+ * @throws {BookmarkProviderError} If resolving the bookmark data fails, the onBookmarkCreate event is canceled, the create request fails, or the request times out.
532
571
  */
533
572
  createBookmark(newBookmarkData) {
534
573
  const { ref, action$ } = this._useScopedActions();
@@ -538,6 +577,7 @@ export class BookmarkProvider {
538
577
  appKey: newBookmarkData.appKey
539
578
  ? of(newBookmarkData.appKey)
540
579
  : defer(() => this._resolve.application()).pipe(map((app) => {
580
+ // the application must resolve to a valid appKey to attribute the bookmark
541
581
  if (!app?.appKey) {
542
582
  throw new BookmarkProviderError('Failed to resolve application key');
543
583
  }
@@ -610,7 +650,8 @@ export class BookmarkProvider {
610
650
  /**
611
651
  * Asynchronously creates a new bookmark.
612
652
  *
613
- * @param bookmark - The new bookmark to create.
653
+ * @template T - The type of bookmark data.
654
+ * @param args - The data for creating the bookmark.
614
655
  * @returns A promise that resolves to the created bookmark with its associated data.
615
656
  */
616
657
  createBookmarkAsync(args) {
@@ -625,8 +666,10 @@ export class BookmarkProvider {
625
666
  * @param {BookmarkUpdate<T>} [bookmarkUpdates] - The updates to apply to the bookmark.
626
667
  * @param {BookmarkUpdateOptions} [options] - The options for updating the bookmark.
627
668
  * @returns {Observable<Bookmark<T>>} - An observable that emits the updated bookmark.
669
+ * @throws {BookmarkProviderError} If bookmarkUpdates is omitted while excludePayloadGeneration is set, generating the payload fails, the onBookmarkUpdate event is canceled, the update request fails, or the request times out.
628
670
  */
629
671
  updateBookmark(bookmarkId, bookmarkUpdates, options) {
672
+ // bookmarkUpdates is required unless the caller opts out of payload generation entirely
630
673
  if (!bookmarkUpdates && options?.excludePayloadGeneration) {
631
674
  throw new BookmarkProviderError('Cannot update bookmark without updates and excludePayloadGeneration option');
632
675
  }
@@ -653,6 +696,7 @@ export class BookmarkProvider {
653
696
  },
654
697
  cancelable: true,
655
698
  });
699
+ // throw an error if the event is canceled
656
700
  if (canceled) {
657
701
  const error = new BookmarkProviderError(`event: ${type} was canceled by listener for updating bookmark: ${bookmarkId}, ref: ${ref}`);
658
702
  this._log?.warn(error.message, updates);
@@ -685,7 +729,7 @@ export class BookmarkProvider {
685
729
  }));
686
730
  // monitor the success case when updating a bookmark
687
731
  const request$ = action$.pipe(filter(bookmarkActions.updateBookmark.success.match), map(
688
- // TODO: add payload if current bookmark is the same as the updated bookmark
732
+ // TODO(#5139): add payload if current bookmark is the same as the updated bookmark
689
733
  ({ payload }) => ({
690
734
  ...bookmarkSelector(this.#store.value, payload.id),
691
735
  payload: payload.payload,
@@ -704,16 +748,23 @@ export class BookmarkProvider {
704
748
  /**
705
749
  * Updates a bookmark asynchronously.
706
750
  *
707
- * @todo - remove the deprecated method in the next major version
751
+ * @todo TODO(#5140) - remove the deprecated overload accepting a full bookmark in the next major version
708
752
  *
709
- * @param bookmark - The bookmark to update.
753
+ * @template T - The type of the bookmark data.
754
+ * @param id_or_bookmark - The ID of the bookmark to update, or (deprecated) the full bookmark object.
755
+ * @param updates_or_options - The updates to apply, or (deprecated) the update options when using the bookmark overload.
756
+ * @param options - The options for updating the bookmark.
710
757
  * @returns A promise that resolves to the updated bookmark with its associated data.
711
758
  */
712
759
  updateBookmarkAsync(id_or_bookmark, updates_or_options, options) {
760
+ // support the deprecated overload that accepted a full bookmark instead of an id
713
761
  if (typeof id_or_bookmark === 'object') {
714
762
  // @deprecated
715
763
  console.warn('updateBookmarkAsync(bookmark, updates, options) is deprecated, use updateBookmarkAsync(id, updates, options) instead');
716
764
  const { id, ...updates } = id_or_bookmark;
765
+ // `updates_or_options` is a union of `BookmarkUpdate<T> | BookmarkUpdateOptions` here,
766
+ // neither of which declares `updatePayload` — cast through `unknown` to probe for the
767
+ // legacy options shape at runtime.
717
768
  return lastValueFrom(this.updateBookmark(id, updates, {
718
769
  excludePayloadGeneration: !updates_or_options.updatePayload,
719
770
  }));
@@ -740,6 +791,7 @@ export class BookmarkProvider {
740
791
  detail: bookmark,
741
792
  cancelable: true,
742
793
  })).pipe(map(({ canceled, type, detail }) => {
794
+ // throw an error if the event is canceled
743
795
  if (canceled) {
744
796
  const error = new BookmarkProviderError(`event: ${type} was canceled by listener for removing bookmark: ${bookmarkId}, ref: ${ref}`);
745
797
  this._log?.warn(error.message);
@@ -793,10 +845,11 @@ export class BookmarkProvider {
793
845
  return lastValueFrom(this.deleteBookmark(bookmarkId));
794
846
  }
795
847
  /**
796
- * Adds a bookmark to the favorites.
848
+ * Adds a bookmark to favorites.
797
849
  *
798
850
  * @param bookmarkId - The ID of the bookmark to add.
799
- * @returns A Promise that resolves to the added bookmark, or null if the bookmark was not added.
851
+ * @returns An observable that emits the added bookmark, or undefined if it could not be resolved.
852
+ * @throws {BookmarkProviderError} If the onBookmarkFavouriteAdd event is canceled, the add request fails, or the request times out.
800
853
  */
801
854
  addBookmarkToFavorites(bookmarkId) {
802
855
  /**
@@ -811,6 +864,7 @@ export class BookmarkProvider {
811
864
  detail: { id: bookmarkId },
812
865
  cancelable: true,
813
866
  })).pipe(map(({ canceled, type }) => {
867
+ // throw an error if the event is canceled
814
868
  if (canceled) {
815
869
  const error = new BookmarkProviderError(`event: ${type} was canceled by listener for adding favourite bookmark: ${bookmarkId}, ref: ${ref}`);
816
870
  this._log?.info(error.message);
@@ -875,6 +929,7 @@ export class BookmarkProvider {
875
929
  detail: bookmark,
876
930
  cancelable: true,
877
931
  })).pipe(map(({ canceled, type, detail }) => {
932
+ // throw an error if the event is canceled
878
933
  if (canceled) {
879
934
  const error = new BookmarkProviderError(`event: ${type} was canceled by listener for removing favourite bookmark: ${bookmarkId}, ref: ${ref}`);
880
935
  this._log?.warn(error.message);
@@ -925,7 +980,8 @@ export class BookmarkProvider {
925
980
  /**
926
981
  * Checks if a bookmark is in the favorites.
927
982
  * @param bookmarkId - The ID of the bookmark to check.
928
- * @returns A promise that resolves to a boolean indicating whether the bookmark is in the favorites.
983
+ * @returns An observable that emits a boolean indicating whether the bookmark is in the favorites.
984
+ * @throws {BookmarkProviderError} If checking the favorite status fails.
929
985
  */
930
986
  isBookmarkInFavorites(bookmarkId) {
931
987
  this._log?.debug(`Checking if bookmark: ${bookmarkId} is in favourites`);
@@ -947,6 +1003,14 @@ export class BookmarkProvider {
947
1003
  isBookmarkInFavoritesAsync(bookmarkId) {
948
1004
  return lastValueFrom(this.isBookmarkInFavorites(bookmarkId));
949
1005
  }
1006
+ /**
1007
+ * Fetches a single bookmark's metadata (without payload) via the store.
1008
+ *
1009
+ * @param bookmarkId - The unique identifier of the bookmark to fetch.
1010
+ * @param options - Optional settings, including a custom `timeout` in milliseconds.
1011
+ * @returns An observable that emits the bookmark's metadata once fetched.
1012
+ * @throws {BookmarkProviderError} If the fetch fails or times out.
1013
+ */
950
1014
  _getBookmarkInfo(bookmarkId, options) {
951
1015
  // only actions with the specified reference are considered
952
1016
  const { action$ } = this._useScopedActions(bookmarkId);
@@ -962,8 +1026,18 @@ export class BookmarkProvider {
962
1026
  },
963
1027
  }));
964
1028
  this.#store.next(bookmarkActions.fetchBookmark(bookmarkId, { ref: bookmarkId }));
1029
+ // race the success and failure streams, whichever resolves first wins
965
1030
  return success$.pipe(raceWith(failure$));
966
1031
  }
1032
+ /**
1033
+ * Fetches a single bookmark's payload data via the store.
1034
+ *
1035
+ * @template T - The type of the bookmark payload.
1036
+ * @param bookmarkId - The unique identifier of the bookmark whose data to fetch.
1037
+ * @param options - Optional settings, including a custom `timeout` in milliseconds.
1038
+ * @returns An observable that emits the bookmark's payload data once fetched.
1039
+ * @throws {BookmarkProviderError} If the fetch fails or times out.
1040
+ */
967
1041
  _getBookmarkData(bookmarkId, options) {
968
1042
  // only actions with the specified reference are considered
969
1043
  const { action$ } = this._useScopedActions(bookmarkId);
@@ -980,11 +1054,13 @@ export class BookmarkProvider {
980
1054
  }));
981
1055
  // request the store to fetch the bookmark data
982
1056
  this.#store.next(bookmarkActions.fetchBookmarkData(bookmarkId, { ref: bookmarkId }));
1057
+ // race the success and failure streams, whichever resolves first wins
983
1058
  return success$.pipe(raceWith(failure$));
984
1059
  }
985
1060
  /**
986
1061
  * Dispatches an event of the specified type with the provided arguments.
987
1062
  *
1063
+ * @template TType - The specific event type key being dispatched.
988
1064
  * @param type - The type of the event to dispatch.
989
1065
  * @param args - The arguments to pass to the event.
990
1066
  * @returns A promise that resolves with the result of the event dispatch.
@@ -996,15 +1072,25 @@ export class BookmarkProvider {
996
1072
  canBubble: true,
997
1073
  ...args,
998
1074
  });
1075
+ // only dispatch through the event bus when one is available
999
1076
  if (this._event) {
1000
1077
  this._log?.debug(`dispatching event ${type}`, args);
1001
1078
  const { canceled } = await this._event.dispatchEvent(event);
1079
+ // log when a listener canceled the event
1002
1080
  if (canceled) {
1003
1081
  this._log?.debug(`event ${type} was canceled`, args);
1004
1082
  }
1005
1083
  }
1006
1084
  return event;
1007
1085
  }
1086
+ /**
1087
+ * Creates a scoped action reference and a filtered action stream containing only
1088
+ * actions tagged with that reference (or the provided `ref`, if given).
1089
+ *
1090
+ * @template TAction - The specific action type emitted on the scoped stream.
1091
+ * @param ref - An existing reference to scope actions to; a new GUID is generated when omitted.
1092
+ * @returns An object containing the resolved `ref` and the `action$` stream filtered to it.
1093
+ */
1008
1094
  _useScopedActions(ref) {
1009
1095
  /**
1010
1096
  * Generates a unique identifier for the operation
@@ -1023,6 +1109,9 @@ export class BookmarkProvider {
1023
1109
  this._log?.debug('disposing BookmarkProvider');
1024
1110
  this.#subscriptions.unsubscribe();
1025
1111
  }
1112
+ /**
1113
+ * Disposes the BookmarkProvider via the `Symbol.dispose` protocol.
1114
+ */
1026
1115
  [Symbol.dispose]() {
1027
1116
  this.dispose();
1028
1117
  }