@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
@@ -1,10 +1,10 @@
1
- import type { BookmarkState } from './BookmarkProvider.store';
2
- import type { BookmarkFlowError } from './BookmarkProvider.error';
1
+ import type { BookmarkState } from './create-bookmark-store';
2
+ import type { BookmarkFlowError } from './BookmarkFlowError';
3
3
  import type { BookmarkWithoutData } from './types';
4
4
  /**
5
5
  * Creates a reducer for managing the state of bookmarks.
6
6
  *
7
- * @todo add fast-deep-equal to compare bookmarks
7
+ * @todo TODO(#5135) - add fast-deep-equal to compare bookmarks
8
8
  *
9
9
  * @param initialState - The initial state of the bookmarks.
10
10
  * @returns A reducer function for managing the bookmarks state.
@@ -18,67 +18,67 @@ export declare const createBookmarkReducer: (initialState?: Partial<BookmarkStat
18
18
  } | {
19
19
  payload: import("./types").Bookmark<any> | null;
20
20
  type: "set_current_bookmark";
21
- } | import("@equinor/fusion-observable").PayloadAction<string, "fetch_bookmark::request", {
21
+ } | import("@equinor/fusion-observable").PayloadAction<string, "add_favourite_bookmark::request", {
22
22
  ref: string;
23
- } | undefined, never> | import("@equinor/fusion-observable").PayloadAction<string, "fetch_bookmark_payload::request", {
24
- ref: string;
25
- } | undefined, never> | import("@equinor/fusion-observable").PayloadAction<import("./BookmarkClient.interface").BookmarksFilter | undefined, "fetch_bookmarks::request", {
23
+ }, never> | import("@equinor/fusion-observable").PayloadAction<string, "add_favourite_bookmark::success", {
26
24
  ref: string;
27
- } | undefined, never> | import("@equinor/fusion-observable").PayloadAction<{
28
- bookmarkId: string;
29
- updates: import("./BookmarkClient.interface").BookmarkUpdate;
30
- }, "set_bookmark::request", {
25
+ }, never> | import("@equinor/fusion-observable").PayloadAction<string, "delete_bookmark::request", {
31
26
  ref: string;
32
- }, never> | import("@equinor/fusion-observable").PayloadAction<import("./BookmarkClient.interface").BookmarkNew, "create_bookmark::request", {
27
+ }, never> | import("@equinor/fusion-observable").PayloadAction<string, "delete_bookmark::success", {
33
28
  ref: string;
34
- }, never> | import("@equinor/fusion-observable").PayloadAction<string, "delete_bookmark::request", {
29
+ }, never> | import("@equinor/fusion-observable").PayloadAction<string, "fetch_bookmark::request", {
35
30
  ref: string;
36
- }, never> | import("@equinor/fusion-observable").PayloadAction<string, "remove_bookmark::request", {
31
+ } | undefined, never> | import("@equinor/fusion-observable").PayloadAction<string, "fetch_bookmark_payload::request", {
37
32
  ref: string;
38
- }, never> | import("@equinor/fusion-observable").PayloadAction<string, "add_favourite_bookmark::request", {
33
+ } | undefined, never> | import("@equinor/fusion-observable").PayloadAction<string, "remove_bookmark::request", {
39
34
  ref: string;
40
35
  }, never> | import("@equinor/fusion-observable").PayloadAction<string, "remove_favourite_bookmark::request", {
41
36
  ref: string;
42
- }, never> | import("@equinor/fusion-observable").PayloadAction<BookmarkWithoutData, "fetch_bookmark::success", {
37
+ }, never> | import("@equinor/fusion-observable").PayloadAction<string, "remove_favourite_bookmark::success", {
43
38
  ref: string;
44
- } | undefined, never> | import("@equinor/fusion-observable").PayloadAction<BookmarkFlowError, "fetch_bookmark::failure", {
39
+ }, never> | import("@equinor/fusion-observable").PayloadAction<import("./types").Bookmark<any>, "create_bookmark::success", {
45
40
  ref: string;
46
- } | undefined, never> | import("@equinor/fusion-observable").PayloadAction<{
47
- bookmarkId: string;
48
- data: import("./types").BookmarkData;
49
- }, "fetch_bookmark_payload::success", {
41
+ }, never> | import("@equinor/fusion-observable").PayloadAction<import("./types").Bookmark<any>, "set_bookmark::success", {
50
42
  ref: string;
51
- } | undefined, never> | import("@equinor/fusion-observable").PayloadAction<BookmarkFlowError, "fetch_bookmark_payload::failure", {
43
+ }, never> | import("@equinor/fusion-observable").PayloadAction<BookmarkFlowError, "add_favourite_bookmark::failure", {
52
44
  ref: string;
53
- } | undefined, never> | import("@equinor/fusion-observable").PayloadAction<import("./types").Bookmarks, "fetch_bookmarks::success", {
45
+ }, never> | import("@equinor/fusion-observable").PayloadAction<BookmarkFlowError, "create_bookmark::failure", {
46
+ ref: string;
47
+ }, never> | import("@equinor/fusion-observable").PayloadAction<BookmarkFlowError, "delete_bookmark::failure", {
48
+ ref: string;
49
+ }, never> | import("@equinor/fusion-observable").PayloadAction<BookmarkFlowError, "fetch_bookmark::failure", {
50
+ ref: string;
51
+ } | undefined, never> | import("@equinor/fusion-observable").PayloadAction<BookmarkFlowError, "fetch_bookmark_payload::failure", {
54
52
  ref: string;
55
53
  } | undefined, never> | import("@equinor/fusion-observable").PayloadAction<BookmarkFlowError, "fetch_bookmarks::failure", {
56
54
  ref: string;
57
- } | undefined, never> | import("@equinor/fusion-observable").PayloadAction<import("./types").Bookmark<any>, "set_bookmark::success", {
55
+ } | undefined, never> | import("@equinor/fusion-observable").PayloadAction<BookmarkFlowError, "remove_bookmark::failure", {
56
+ ref: string;
57
+ }, never> | import("@equinor/fusion-observable").PayloadAction<BookmarkFlowError, "remove_favourite_bookmark::failure", {
58
58
  ref: string;
59
59
  }, never> | import("@equinor/fusion-observable").PayloadAction<BookmarkFlowError, "set_bookmark::failure", {
60
60
  ref: string;
61
- }, never> | import("@equinor/fusion-observable").PayloadAction<import("./types").Bookmark<any>, "create_bookmark::success", {
61
+ }, never> | import("@equinor/fusion-observable").PayloadAction<import("./BookmarkClient.interface").BookmarkNew, "create_bookmark::request", {
62
62
  ref: string;
63
- }, never> | import("@equinor/fusion-observable").PayloadAction<BookmarkFlowError, "create_bookmark::failure", {
63
+ }, never> | import("@equinor/fusion-observable").PayloadAction<BookmarkWithoutData, "fetch_bookmark::success", {
64
64
  ref: string;
65
- }, never> | import("@equinor/fusion-observable").PayloadAction<string, "delete_bookmark::success", {
65
+ } | undefined, never> | import("@equinor/fusion-observable").PayloadAction<import("./types").Bookmarks, "fetch_bookmarks::success", {
66
66
  ref: string;
67
- }, never> | import("@equinor/fusion-observable").PayloadAction<BookmarkFlowError, "delete_bookmark::failure", {
67
+ } | undefined, never> | import("@equinor/fusion-observable").PayloadAction<{
68
+ bookmarkId: string;
69
+ data: import("./types").BookmarkData;
70
+ }, "fetch_bookmark_payload::success", {
71
+ ref: string;
72
+ } | undefined, never> | import("@equinor/fusion-observable").PayloadAction<{
73
+ bookmarkId: string;
74
+ updates: import("./BookmarkClient.interface").BookmarkUpdate;
75
+ }, "set_bookmark::request", {
68
76
  ref: string;
69
77
  }, never> | import("@equinor/fusion-observable").PayloadAction<{
70
- type: "delete_bookmark" | "remove_favourite_bookmark";
78
+ type: 'delete_bookmark' | 'remove_favourite_bookmark';
71
79
  bookmarkId: string;
72
80
  }, "remove_bookmark::success", {
73
81
  ref: string;
74
- }, never> | import("@equinor/fusion-observable").PayloadAction<BookmarkFlowError, "remove_bookmark::failure", {
75
- ref: string;
76
- }, never> | import("@equinor/fusion-observable").PayloadAction<string, "add_favourite_bookmark::success", {
77
- ref: string;
78
- }, never> | import("@equinor/fusion-observable").PayloadAction<BookmarkFlowError, "add_favourite_bookmark::failure", {
79
- ref: string;
80
- }, never> | import("@equinor/fusion-observable").PayloadAction<string, "remove_favourite_bookmark::success", {
81
- ref: string;
82
- }, never> | import("@equinor/fusion-observable").PayloadAction<BookmarkFlowError, "remove_favourite_bookmark::failure", {
82
+ }, never> | import("@equinor/fusion-observable").PayloadAction<import("./BookmarkClient.interface").BookmarksFilter | undefined, "fetch_bookmarks::request", {
83
83
  ref: string;
84
- }, never>>;
84
+ } | undefined, never>>;
@@ -1,6 +1,6 @@
1
1
  import { FlowSubject, type ActionBaseType } from '@equinor/fusion-observable';
2
- import type { BookmarkActions } from './BookmarkProvider.actions';
3
- import type { BookmarkFlowError } from './BookmarkProvider.error';
2
+ import type { BookmarkActions } from './bookmark-actions';
3
+ import type { BookmarkFlowError } from './BookmarkFlowError';
4
4
  import type { IBookmarkClient } from './BookmarkClient.interface';
5
5
  import type { Bookmark, BookmarkWithoutData } from './types';
6
6
  /**
@@ -1,5 +1,5 @@
1
1
  import type { IModulesConfigurator } from '@equinor/fusion-framework-module';
2
- import type { BookmarkModuleConfigurator } from './BookmarkConfigurator';
2
+ import type { BookmarkModuleConfigurator } from './BookmarkModuleConfigurator';
3
3
  /**
4
4
  * Enables the bookmark module on a Fusion Framework module configurator.
5
5
  *
@@ -1,4 +1,15 @@
1
- export { BookmarkModuleConfigurator } from './BookmarkConfigurator';
1
+ /**
2
+ * Bookmark module for the Fusion Framework.
3
+ *
4
+ * Provides bookmark management (create, update, delete, favourite) with
5
+ * application-scoped payloads and event-driven state updates.
6
+ *
7
+ * @see {@link enableBookmark} to enable the module in a configurator.
8
+ * @see {@link BookmarkProvider} for the runtime provider API.
9
+ *
10
+ * @packageDocumentation
11
+ */
12
+ export { BookmarkModuleConfigurator } from './BookmarkModuleConfigurator';
2
13
  export type { IBookmarkClient, BookmarkNew, BookmarkUpdate, BookmarksFilter, } from './BookmarkClient.interface';
3
14
  export { default, BookmarkModule, module as bookmarkModule, moduleKey as bookmarkModuleKey, } from './bookmark-module';
4
15
  export { BookmarkProvider } from './BookmarkProvider';
@@ -1 +1 @@
1
- export declare const version = "4.0.2";
1
+ export declare const version = "4.0.4";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@equinor/fusion-framework-module-bookmark",
3
- "version": "4.0.2",
3
+ "version": "4.0.4",
4
4
  "description": "",
5
5
  "main": "./dist/esm/index.js",
6
6
  "types": "./dist/types/index.d.ts",
@@ -41,19 +41,19 @@
41
41
  "immer": "^11.0.0",
42
42
  "rxjs": "^7.8.1",
43
43
  "uuid": "^14.0.0",
44
- "@equinor/fusion-framework-module": "^6.0.0",
45
- "@equinor/fusion-observable": "^9.0.1",
46
- "@equinor/fusion-log": "^2.0.0",
47
- "@equinor/fusion-query": "^7.0.1"
44
+ "@equinor/fusion-framework-module": "^6.1.1",
45
+ "@equinor/fusion-log": "^2.0.2",
46
+ "@equinor/fusion-observable": "^9.1.1",
47
+ "@equinor/fusion-query": "^7.0.3"
48
48
  },
49
49
  "devDependencies": {
50
- "typescript": "^6.0.3",
50
+ "typescript": "^7.0.2",
51
51
  "zod": "^4.4.3",
52
- "@equinor/fusion-framework-module-event": "^6.0.0",
53
- "@equinor/fusion-framework-module-app": "^8.0.2",
54
- "@equinor/fusion-framework-module-http": "^8.0.1",
55
- "@equinor/fusion-framework-module-context": "^8.0.0",
56
- "@equinor/fusion-framework-module-services": "^8.0.1"
52
+ "@equinor/fusion-framework-module-app": "^8.0.4",
53
+ "@equinor/fusion-framework-module-context": "^8.0.1",
54
+ "@equinor/fusion-framework-module-event": "^6.0.1",
55
+ "@equinor/fusion-framework-module-http": "^8.0.5",
56
+ "@equinor/fusion-framework-module-services": "^8.0.3"
57
57
  },
58
58
  "scripts": {
59
59
  "build": "tsc -b"
@@ -82,6 +82,7 @@ export class BookmarkClient implements IBookmarkClient {
82
82
  * Constructs a new `BookmarkClient` instance with the provided `BookmarksApiClient`.
83
83
  *
84
84
  * @param api - The `BookmarksApiClient` instance to use for making API requests.
85
+ * @param options - Optional client options, such as the cache expiry time.
85
86
  */
86
87
  constructor(api: BookmarksApiClient<'json$'>, options?: { expire?: number }) {
87
88
  this.#api = api;
@@ -92,6 +93,7 @@ export class BookmarkClient implements IBookmarkClient {
92
93
  this.#queryBookmark = new Query({
93
94
  client: {
94
95
  fn: (args: { bookmarkId: string }) => {
96
+ // strip the payload from the fetched bookmark before caching
95
97
  return this.#api.get('v2', args).pipe(map(parseBookmarkWithoutPayload));
96
98
  },
97
99
  },
@@ -103,9 +105,13 @@ export class BookmarkClient implements IBookmarkClient {
103
105
  this.#queryBookmarks = new Query({
104
106
  client: {
105
107
  fn: (filter?: BookmarksFilter) => {
106
- return this.#api
107
- .query('v2', { filter })
108
- .pipe(map((res) => res.map(parseBookmarkWithoutPayload)));
108
+ // strip the payload from each fetched bookmark before caching
109
+ return this.#api.query('v2', { filter }).pipe(
110
+ map((res) =>
111
+ // strip the payload field from each bookmark
112
+ res.map(parseBookmarkWithoutPayload),
113
+ ),
114
+ );
109
115
  },
110
116
  },
111
117
  key: (args) => JSON.stringify(args ?? ''),
@@ -115,6 +121,7 @@ export class BookmarkClient implements IBookmarkClient {
115
121
  this.#queryBookmarkData = new Query({
116
122
  client: {
117
123
  fn: (args: { bookmarkId: string }) => {
124
+ // extract only the payload from the API response
118
125
  return this.#api.getPayload('v1', args).pipe(map((res) => res.payload));
119
126
  },
120
127
  },
@@ -130,16 +137,19 @@ export class BookmarkClient implements IBookmarkClient {
130
137
 
131
138
  /** @inheritdoc */
132
139
  public getAllBookmarks(filter?: BookmarksFilter): ObservableInput<Bookmark[]> {
140
+ // unwrap the query result value
133
141
  return this.#queryBookmarks.query(filter).pipe(map((res) => res.value as Bookmark[]));
134
142
  }
135
143
 
136
144
  /** @inheritdoc */
137
145
  public getBookmarkById(bookmarkId: string): ObservableInput<BookmarkWithoutData> {
146
+ // unwrap the query result value
138
147
  return this.#queryBookmark.query({ bookmarkId }).pipe(map((res) => res.value));
139
148
  }
140
149
 
141
150
  /** @inheritdoc */
142
151
  public getBookmarkData<T extends BookmarkData>(bookmarkId: string): ObservableInput<T> {
152
+ // unwrap the query result value
143
153
  return this.#queryBookmarkData.query({ bookmarkId }).pipe(map((res): T => res.value as T));
144
154
  }
145
155
 
@@ -148,9 +158,11 @@ export class BookmarkClient implements IBookmarkClient {
148
158
  bookmarkId: string,
149
159
  data: T,
150
160
  ): ObservableInput<T> {
161
+ // update the payload cache once the mutation succeeds
151
162
  return this.#api.patch('v1', { bookmarkId, updates: { payload: data } }).pipe(
152
163
  map((res) => res.payload as T),
153
164
  tap((updatedData) => {
165
+ // only update the cache when data was actually returned
154
166
  if (updatedData) {
155
167
  this.#queryBookmarkData.mutate(
156
168
  { bookmarkId },
@@ -166,6 +178,7 @@ export class BookmarkClient implements IBookmarkClient {
166
178
  public createBookmark<T extends BookmarkData>(
167
179
  newBookmark: BookmarkNew<T>,
168
180
  ): ObservableInput<Bookmark<T>> {
181
+ // parse the response and update caches once the bookmark is created
169
182
  return this.#api.create('v1', newBookmark).pipe(
170
183
  map((response) => parseBookmark<T>(response)),
171
184
  /** update the bookmark cache */
@@ -177,6 +190,7 @@ export class BookmarkClient implements IBookmarkClient {
177
190
  { value: bookmark, updated: Date.now() },
178
191
  { allowCreation: true },
179
192
  );
193
+ // only cache the payload if the created bookmark has one
180
194
  if (payload) {
181
195
  this.#queryBookmarkData.mutate(
182
196
  { bookmarkId: bookmark.id },
@@ -194,6 +208,7 @@ export class BookmarkClient implements IBookmarkClient {
194
208
  bookmarkId: string,
195
209
  updates: BookmarkUpdate<T>,
196
210
  ): ObservableInput<Bookmark<T>> {
211
+ // parse the response and share it across the cache-update subscriptions below
197
212
  const update$ = this.#api.patch('v1', { bookmarkId, updates: updates }).pipe(
198
213
  map((response) => parseBookmark<T>(response)),
199
214
  shareReplay(),
@@ -217,6 +232,7 @@ export class BookmarkClient implements IBookmarkClient {
217
232
  subscriber.add(
218
233
  update$.subscribe((updatedBookmark) => {
219
234
  const { payload } = updatedBookmark;
235
+ // only cache the payload when present, otherwise clear any stale cache entry
220
236
  if (payload) {
221
237
  this.#queryBookmarkData.mutate(
222
238
  {
@@ -253,6 +269,7 @@ export class BookmarkClient implements IBookmarkClient {
253
269
 
254
270
  /** @inheritdoc */
255
271
  public addBookmarkToFavorites(bookmarkId: string): ObservableInput<boolean> {
272
+ // invalidate the bookmarks list cache once favorited
256
273
  return this.#api
257
274
  .addFavourite('v1', { bookmarkId })
258
275
  .pipe(tap(() => this.#queryBookmarks.invalidate()));
@@ -260,6 +277,7 @@ export class BookmarkClient implements IBookmarkClient {
260
277
 
261
278
  /** @inheritdoc */
262
279
  public removeBookmarkFromFavorites(bookmarkId: string): ObservableInput<boolean> {
280
+ // invalidate the bookmarks list cache once unfavorited
263
281
  return this.#api
264
282
  .removeFavourite('v1', { bookmarkId })
265
283
  .pipe(tap(() => this.#queryBookmarks.invalidate()));
@@ -1,6 +1,6 @@
1
1
  import type { ActionWithSuffix } from '@equinor/fusion-observable';
2
2
 
3
- import type { BookmarkActions } from './BookmarkProvider.actions';
3
+ import type { BookmarkActions } from './bookmark-actions';
4
4
 
5
5
  /**
6
6
  * Error thrown inside bookmark store flows (side-effect pipelines) when an
@@ -10,6 +10,13 @@ import type { BookmarkActions } from './BookmarkProvider.actions';
10
10
  * correlate errors back to specific operations.
11
11
  */
12
12
  export class BookmarkFlowError extends Error {
13
+ /**
14
+ * Constructs a new `BookmarkFlowError`.
15
+ *
16
+ * @param message - Human-readable error message.
17
+ * @param action - The request action that triggered the failed flow.
18
+ * @param options - Optional `ErrorOptions` (e.g. `cause`).
19
+ */
13
20
  constructor(
14
21
  message: string,
15
22
  /** The request action that triggered the failed flow. */
@@ -28,9 +35,4 @@ export class BookmarkFlowError extends Error {
28
35
  * Distinct from {@link BookmarkFlowError}, which is scoped to internal
29
36
  * store flow pipelines.
30
37
  */
31
- export class BookmarkProviderError extends Error {
32
- constructor(message: string, options?: ErrorOptions) {
33
- super(message, options);
34
- this.name = 'BookmarkProviderError';
35
- }
36
- }
38
+ export { BookmarkProviderError } from './BookmarkProviderError';
@@ -1,4 +1,4 @@
1
- import type { z, ZodError } from 'zod';
1
+ import type { ZodError } from 'zod';
2
2
 
3
3
  import {
4
4
  BaseConfigBuilder,
@@ -43,8 +43,16 @@ const parseInitialBookmarkConfigConfig = (initial?: unknown): BookmarkModuleConf
43
43
  */
44
44
  export class BookmarkModuleConfigurator extends BaseConfigBuilder<BookmarkModuleConfig> {
45
45
  #log?: ILogger;
46
- defaultExpireTime = 1 * 60 * 1000; // Default expiration time for bookmarks
46
+ /** Default expiration time, in milliseconds, for bookmarks. */
47
+ defaultExpireTime = 1 * 60 * 1000;
47
48
 
49
+ /**
50
+ * Constructs a new `BookmarkModuleConfigurator`.
51
+ *
52
+ * @param options - Optional configurator options.
53
+ * @param options.log - Logger instance inherited from the parent module, if any.
54
+ * @param options.ref - Reference to sibling module instances available during configuration.
55
+ */
48
56
  constructor(options?: { log?: ILogger; ref?: ModulesInstanceType<[BookmarkModule]> }) {
49
57
  super();
50
58
  const { log } = options ?? {};
@@ -64,6 +72,7 @@ export class BookmarkModuleConfigurator extends BaseConfigBuilder<BookmarkModule
64
72
  */
65
73
  public setLogLevel(level: LogLevel) {
66
74
  this._set('logLevel', async () => level);
75
+ // propagate the level to the configurator's own logger, if one is set
67
76
  if (this.#log) {
68
77
  this.#log.level = level;
69
78
  }
@@ -84,6 +93,7 @@ export class BookmarkModuleConfigurator extends BaseConfigBuilder<BookmarkModule
84
93
  public setClient(
85
94
  client: ConfigBuilderCallback<BookmarkModuleConfig['client']> | BookmarkModuleConfig['client'],
86
95
  ) {
96
+ // a callback receives the module initializer and resolves the client itself
87
97
  if (typeof client === 'function') {
88
98
  this._set('client', (init) => client(init));
89
99
  } else {
@@ -102,6 +112,7 @@ export class BookmarkModuleConfigurator extends BaseConfigBuilder<BookmarkModule
102
112
  public setParent(
103
113
  parent: ConfigBuilderCallback<BookmarkModuleConfig['parent']> | BookmarkModuleConfig['parent'],
104
114
  ) {
115
+ // a callback receives the module initializer and resolves the parent itself
105
116
  if (typeof parent === 'function') {
106
117
  this._set('parent', (init) => parent(init));
107
118
  } else {
@@ -128,6 +139,7 @@ export class BookmarkModuleConfigurator extends BaseConfigBuilder<BookmarkModule
128
139
  | ConfigBuilderCallback<BookmarkModuleConfig['sourceSystem']>
129
140
  | BookmarkModuleConfig['sourceSystem'],
130
141
  ) {
142
+ // a callback receives the module initializer and resolves the source system itself
131
143
  if (typeof sourceSystem === 'function') {
132
144
  this._set('sourceSystem', sourceSystem);
133
145
  } else {
@@ -167,6 +179,7 @@ export class BookmarkModuleConfigurator extends BaseConfigBuilder<BookmarkModule
167
179
 
168
180
  /**
169
181
  * Sets a filter for the bookmark module.
182
+ * @template TKey - The filter key being set.
170
183
  * @param key - The key of the filter to set.
171
184
  * @param value - The value to set for the filter.
172
185
  *
@@ -179,7 +192,7 @@ export class BookmarkModuleConfigurator extends BaseConfigBuilder<BookmarkModule
179
192
  value: BookmarkModuleConfig['filters'][TKey],
180
193
  ) {
181
194
  // eslint-disable-next-line @typescript-eslint/ban-ts-comment
182
- // @ts-ignore
195
+ // @ts-expect-error
183
196
  this._set(`filters.${key}`, async () => value);
184
197
  }
185
198
 
@@ -204,12 +217,14 @@ export class BookmarkModuleConfigurator extends BaseConfigBuilder<BookmarkModule
204
217
 
205
218
  // Check if parent and parent version compatible
206
219
  const parentModules = init.ref as ModulesInstanceType<[BookmarkModule]>;
220
+ // only use the parent module's bookmark provider if it's actually present
207
221
  if (parentModules && 'bookmark' in parentModules) {
208
222
  const parent = parentModules.bookmark;
209
- if (
210
- 'version' in parent &&
211
- (parent as unknown as BookmarkProvider).version.satisfies('>=2.0.0')
212
- ) {
223
+ // `parent` is narrowed to `{ version: unknown }` by the `'version' in parent` check below,
224
+ // so it must be cast through `unknown` to access `BookmarkProvider`-specific members.
225
+ const parentProvider = parent as unknown as BookmarkProvider;
226
+ // only inherit from a parent whose version satisfies the minimum supported range
227
+ if ('version' in parent && parentProvider.version.satisfies('>=2.0.0')) {
213
228
  this._set('parent', async () => parent);
214
229
  } else {
215
230
  this.#log?.warn('invalid version of parent BookmarkProvider provided');
@@ -254,7 +269,7 @@ export class BookmarkModuleConfigurator extends BaseConfigBuilder<BookmarkModule
254
269
  */
255
270
  protected async _createDefaultContextResolver(
256
271
  init: ConfigBuilderCallbackArgs,
257
- ): Promise<BookmarkModuleConfig['resolve']['context'] | void> {
272
+ ): Promise<BookmarkModuleConfig['resolve']['context'] | undefined> {
258
273
  // Check if context module is available and use context provider if available
259
274
  if (init.hasModule('context')) {
260
275
  this.#log?.debug('Context module available, awaiting instance');
@@ -276,7 +291,7 @@ export class BookmarkModuleConfigurator extends BaseConfigBuilder<BookmarkModule
276
291
  */
277
292
  protected async _createDefaultApplicationResolver(
278
293
  init: ConfigBuilderCallbackArgs,
279
- ): Promise<BookmarkModuleConfig['resolve']['application'] | void> {
294
+ ): Promise<BookmarkModuleConfig['resolve']['application'] | undefined> {
280
295
  // Check if app module is available and use app provider if available
281
296
  if (init.hasModule('app')) {
282
297
  this.#log?.debug('App module available, awaiting instance');
@@ -285,6 +300,7 @@ export class BookmarkModuleConfigurator extends BaseConfigBuilder<BookmarkModule
285
300
  this.#log?.debug('App provider available, creating application resolver');
286
301
  return async () => {
287
302
  const app = appProvider.current;
303
+ // only resolve the application if there is a currently loaded app
288
304
  if (app) {
289
305
  return {
290
306
  appKey: app.appKey,
@@ -297,6 +313,11 @@ export class BookmarkModuleConfigurator extends BaseConfigBuilder<BookmarkModule
297
313
  }
298
314
  }
299
315
 
316
+ /**
317
+ * @internal Resolves the {@link AppModuleProvider} for the bookmark module.
318
+ * @param init - The configuration initialization object.
319
+ * @returns A promise that resolves to the app module provider, or undefined if unavailable.
320
+ */
300
321
  protected async _resolveAppProvider(
301
322
  init: ConfigBuilderCallbackArgs,
302
323
  ): Promise<AppModuleProvider | undefined> {
@@ -316,7 +337,7 @@ export class BookmarkModuleConfigurator extends BaseConfigBuilder<BookmarkModule
316
337
  */
317
338
  protected async _resolveEventProvider(
318
339
  init: ConfigBuilderCallbackArgs,
319
- ): Promise<BookmarkModuleConfig['eventProvider'] | void> {
340
+ ): Promise<BookmarkModuleConfig['eventProvider'] | undefined> {
320
341
  // Check if event module is available
321
342
  if (init.hasModule('event')) {
322
343
  this.#log?.debug('Event module available, awaiting instance');
@@ -331,12 +352,12 @@ export class BookmarkModuleConfigurator extends BaseConfigBuilder<BookmarkModule
331
352
  */
332
353
  protected async _createDefaultClient(
333
354
  init: ConfigBuilderCallbackArgs,
334
- ): Promise<BookmarkModuleConfig['client'] | void> {
355
+ ): Promise<BookmarkModuleConfig['client'] | undefined> {
335
356
  try {
336
357
  const apiProvider = await this._getServiceProvider(init);
337
358
  const api = await apiProvider.createBookmarksClient('json$');
338
359
  return new BookmarkClient(api);
339
- } catch (err) {
360
+ } catch (_err) {
340
361
  this.#log?.warn('Failed to create bookmark api client');
341
362
  }
342
363
  }
@@ -345,6 +366,7 @@ export class BookmarkModuleConfigurator extends BaseConfigBuilder<BookmarkModule
345
366
  * @internal retrieves the service provider from the configuration initialization object.
346
367
  * @param init - The configuration initialization object.
347
368
  * @returns A promise that resolves to the service provider.
369
+ * @throws {Error} When no services module or parent service module is available.
348
370
  */
349
371
  protected async _getServiceProvider(init: ConfigBuilderCallbackArgs): Promise<IApiProvider> {
350
372
  // check if services module is available
@@ -357,6 +379,7 @@ export class BookmarkModuleConfigurator extends BaseConfigBuilder<BookmarkModule
357
379
 
358
380
  // check if parent has services module
359
381
  const parentServiceModule = (init.ref as ModulesInstanceType<[ServicesModule]>)?.services;
382
+ // reuse the parent's service module if one is available
360
383
  if (parentServiceModule) {
361
384
  return parentServiceModule;
362
385
  }
@@ -366,6 +389,13 @@ export class BookmarkModuleConfigurator extends BaseConfigBuilder<BookmarkModule
366
389
  throw Error('[BookmarkConfigurator] No service provider configures [ServicesModule] ');
367
390
  }
368
391
 
392
+ /**
393
+ * @internal Validates and normalizes the resolved config before it's returned from `build`.
394
+ * @param config - The partially-resolved bookmark module config.
395
+ * @param _init - The configuration initialization object (unused).
396
+ * @returns The validated {@link BookmarkModuleConfig}.
397
+ * @throws {ZodError} When the config fails schema validation.
398
+ */
369
399
  protected async _processConfig(
370
400
  config: Partial<BookmarkModuleConfig>,
371
401
  _init: ConfigBuilderCallbackArgs,
@@ -1,9 +1,9 @@
1
- /* eslint-disable @typescript-eslint/no-explicit-any */
1
+ // biome-ignore-all lint/suspicious/noExplicitAny: `BookmarkData = any` generic defaults must remain bivariant — `unknown` breaks assignability of concrete `Bookmark<T>`/`BookmarkPayloadGenerator<TData>` instances to the default-typed generic
2
2
  import type { Observable, ObservableInput } from 'rxjs';
3
3
  import type { Bookmark, BookmarkData, BookmarkWithoutData } from './types';
4
4
  import type { BookmarkNew, BookmarkUpdate } from './BookmarkClient.interface';
5
5
  import type { BookmarkProviderEventMap } from './BookmarkProvider.events';
6
- import type { BookmarkState } from './BookmarkProvider.store';
6
+ import type { BookmarkState } from './create-bookmark-store';
7
7
 
8
8
  /**
9
9
  * Arguments for creating a bookmark via {@link IBookmarkProvider.createBookmark}.
@@ -45,6 +45,7 @@ export type BookmarkUpdateOptions = {
45
45
  export type BookmarkPayloadGenerator<TData extends BookmarkData = any> = (
46
46
  payload?: Partial<TData> | null,
47
47
  initial?: Partial<TData> | null,
48
+ // biome-ignore lint/suspicious/noConfusingVoidType: `void` here relies on TypeScript's special-cased "void-returning callback accepts any return value" behavior for draft-mutating generators — `undefined` would break assignability of generators that only conditionally return a partial payload
48
49
  ) => Promise<Partial<TData> | void> | Partial<TData> | void;
49
50
 
50
51
  /**
@@ -1,5 +1,5 @@
1
- import type { BookmarkFlowError } from './BookmarkProvider.error';
2
- import type { BookmarkState } from './BookmarkProvider.store';
1
+ import type { BookmarkFlowError } from './BookmarkFlowError';
2
+ import type { BookmarkState } from './create-bookmark-store';
3
3
  import type { Bookmark, BookmarkData } from './types';
4
4
 
5
5
  /**
@@ -20,6 +20,8 @@ export const bookmarksSelector = (state: BookmarkState): Bookmark[] => {
20
20
  * @param id - The bookmark identifier to look up.
21
21
  * @returns The matching bookmark, or `undefined` if not found.
22
22
  */
23
+ // tightly coupled group of store selectors
24
+ // fusion-lint-disable-next-line single-export-per-file
23
25
  export const bookmarkSelector = <T extends BookmarkData>(
24
26
  state: BookmarkState,
25
27
  id: string,
@@ -34,6 +36,8 @@ export const bookmarkSelector = <T extends BookmarkData>(
34
36
  * @param state - The current bookmark store state.
35
37
  * @returns The active bookmark, `null` if explicitly cleared, or `undefined` if never set.
36
38
  */
39
+ // tightly coupled group of store selectors
40
+ // fusion-lint-disable-next-line single-export-per-file
37
41
  export const activeBookmarkSelector = <T extends BookmarkData>(
38
42
  state: BookmarkState,
39
43
  ): Bookmark<T> | null | undefined => {
@@ -46,6 +50,8 @@ export const activeBookmarkSelector = <T extends BookmarkData>(
46
50
  * @param state - The bookmark state.
47
51
  * @returns The status from the bookmark state.
48
52
  */
53
+ // tightly coupled group of store selectors
54
+ // fusion-lint-disable-next-line single-export-per-file
49
55
  export const statusSelector = (state: BookmarkState): BookmarkState['status'] => {
50
56
  return state.status;
51
57
  };
@@ -56,6 +62,8 @@ export const statusSelector = (state: BookmarkState): BookmarkState['status'] =>
56
62
  * @param state - The bookmark state.
57
63
  * @returns An array of bookmark flow errors.
58
64
  */
65
+ // tightly coupled group of store selectors
66
+ // fusion-lint-disable-next-line single-export-per-file
59
67
  export const errorsSelector = (state: BookmarkState): Array<BookmarkFlowError> => {
60
68
  return Object.values(state.errors);
61
69
  };