@o3r/core 15.3.0-prerelease.9 → 15.4.0-prerelease.0

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,521 +1,351 @@
1
- import { map, filter, EMPTY, from, isObservable, of, identity, BehaviorSubject, merge, observeOn, animationFrameScheduler } from 'rxjs';
2
- import { tap, startWith, pairwise, switchMap, catchError, filter as filter$1, delay, finalize, mergeMap, bufferCount, concatMap, scan } from 'rxjs/operators';
3
- import { v4 } from 'uuid';
4
-
5
- /* eslint-disable @typescript-eslint/naming-convention -- exception for `BuildTimeProperties` */
6
- /**
7
- * Library build time default properties
8
- */
1
+ import { BehaviorSubject, EMPTY, animationFrameScheduler, filter, from, identity, isObservable, map, merge, observeOn, of } from "rxjs";
2
+ import { bufferCount, catchError, concatMap, delay, filter as filter$1, finalize, mergeMap, pairwise, scan, startWith, switchMap, tap } from "rxjs/operators";
3
+ import { v4 } from "uuid";
9
4
  const DEFAULT_BUILD_PROPERTIES = {
10
- DEBUG_MODE: true,
11
- APP_BASE_HREF: '.',
12
- APP_VERSION: '0.0.0',
13
- DEFAULT_LOC_BUNDLE_NAME: '',
14
- DEVTOOL_HISTORY_SIZE: 20,
15
- ENABLE_GHOSTING: false,
16
- ENABLE_WEBSTORAGE: true,
17
- ENVIRONMENT: 'dev',
18
- LOCALIZATION_BUNDLES_OUTPUT: 'localizations/',
19
- USE_MOCKS: false
5
+ DEBUG_MODE: true,
6
+ APP_BASE_HREF: ".",
7
+ APP_VERSION: "0.0.0",
8
+ DEFAULT_LOC_BUNDLE_NAME: "",
9
+ DEVTOOL_HISTORY_SIZE: 20,
10
+ ENABLE_GHOSTING: false,
11
+ ENABLE_WEBSTORAGE: true,
12
+ ENVIRONMENT: "dev",
13
+ LOCALIZATION_BUNDLES_OUTPUT: "localizations/",
14
+ USE_MOCKS: false
20
15
  };
21
-
22
- /**
23
- * Private field where Otter component information are stored
24
- */
25
- const otterComponentInfoPropertyName = '__otter-info__';
26
- /**
27
- * Decorates an Angular component to provide Otter information
28
- * @param info Information to define the Otter component
29
- * @returns the component with the information
30
- */
31
- // eslint-disable-next-line @typescript-eslint/naming-convention -- decorator should be PascalCase
16
+ const otterComponentInfoPropertyName = "__otter-info__";
32
17
  function O3rComponent(info) {
33
- return (constructor) => {
34
- const componentName = constructor.name;
35
- constructor.prototype[otterComponentInfoPropertyName] = { ...info, componentName };
36
- return constructor;
37
- };
18
+ return (constructor) => {
19
+ const componentName = constructor.name;
20
+ constructor.prototype[otterComponentInfoPropertyName] = {
21
+ ...info,
22
+ componentName
23
+ };
24
+ return constructor;
25
+ };
38
26
  }
39
-
40
- /**
41
- * Compute the name of the component with the library's name to generate unique component identifier used in metadata and different modules
42
- * @param componentName Name of the component to get the configuration
43
- * @param libraryName Name of the library the component is coming from
44
- */
45
27
  function computeItemIdentifier(componentName, libraryName) {
46
- return (libraryName ? libraryName + '#' : '') + componentName;
28
+ return (libraryName ? libraryName + "#" : "") + componentName;
47
29
  }
48
-
49
- /** Type of a message exchanged within the Otter Framework */
50
- const otterMessageType = 'otter';
51
- /** Target of a message that should be handled by the application */
52
- const applicationMessageTarget = 'app';
53
-
54
- /**
55
- * Determine if a message should be handle by the application
56
- * @param message Message to analyze
57
- */
30
+ const otterMessageType = "otter";
31
+ const applicationMessageTarget = "app";
58
32
  const isToAppOtterMessage = (message) => {
59
- return message?.to === applicationMessageTarget;
33
+ return message?.to === "app";
60
34
  };
61
- /**
62
- * Determine if a message is emitted by an Otter tool
63
- * @param message Message to analyze
64
- */
65
35
  const isOtterMessage = (message) => {
66
- return message?.type === otterMessageType;
36
+ return message?.type === otterMessageType;
67
37
  };
68
- /**
69
- * Send an Otter Message
70
- * @param dataType Type of the message
71
- * @param content content of the message
72
- * @param preStringify determine if the message should JSON.stringify before being send (will use the default mechanism otherwise)
73
- */
74
38
  const sendOtterMessage = (dataType, content, preStringify = true) => {
75
- const message = {
76
- type: otterMessageType,
77
- content: {
78
- ...content,
79
- dataType
80
- }
81
- };
82
- return window.postMessage(preStringify ? JSON.stringify(message) : message, '*');
39
+ const message = {
40
+ type: otterMessageType,
41
+ content: {
42
+ ...content,
43
+ dataType
44
+ }
45
+ };
46
+ return window.postMessage(preStringify ? JSON.stringify(message) : message, "*");
83
47
  };
84
- /**
85
- * Filter the Otter message that should be handle by the application and returns it content
86
- * @param predicate condition to filter the message
87
- * @returns content of the message
88
- */
89
- /**
90
- * Operator to get only Otter messages that match the predicate
91
- * @param predicate
92
- */
93
48
  function filterMessageContent(predicate) {
94
- return (source$) => {
95
- const obs = source$.pipe(map((event) => {
96
- const data = event.data;
97
- return typeof data === 'string' ? JSON.parse(data) : data;
98
- }), filter(isOtterMessage), filter(isToAppOtterMessage), map((message) => message.content));
99
- if (predicate) {
100
- return obs.pipe(filter(predicate));
101
- }
102
- return obs;
103
- };
49
+ return (source$) => {
50
+ const obs = source$.pipe(map((event) => {
51
+ const data = event.data;
52
+ return typeof data === "string" ? JSON.parse(data) : data;
53
+ }), filter(isOtterMessage), filter(isToAppOtterMessage), map((message) => message.content));
54
+ if (predicate) return obs.pipe(filter(predicate));
55
+ return obs;
56
+ };
104
57
  }
105
-
106
58
  const asyncStoreItemAdapter = {
107
- addRequest: (item, requestId) => {
108
- return {
109
- ...item,
110
- requestIds: [...item.requestIds, requestId],
111
- isFailure: item.requestIds.length === 0 ? false : item.isFailure,
112
- isPending: true
113
- };
114
- },
115
- failRequest: (item, requestId) => {
116
- const requestIds = requestId ? item.requestIds.filter((id) => id !== requestId) : item.requestIds;
117
- return {
118
- ...item,
119
- isFailure: true,
120
- isPending: requestIds.length > 0,
121
- requestIds
122
- };
123
- },
124
- resolveRequest: (item, requestId) => {
125
- const requestIds = requestId ? item.requestIds.filter((id) => id !== requestId) : item.requestIds;
126
- return {
127
- ...item,
128
- requestIds,
129
- isPending: requestIds.length > 0
130
- };
131
- },
132
- initialize: (entityItem) => {
133
- return {
134
- ...entityItem,
135
- requestIds: []
136
- };
137
- },
138
- extractAsyncStoreItem: (entityItem) => {
139
- return {
140
- requestIds: [...entityItem.requestIds],
141
- isFailure: entityItem.isFailure,
142
- isPending: entityItem.isPending
143
- };
144
- },
145
- clearAsyncStoreItem: (entityItem) => {
146
- const { isPending, isFailure, ...newResponse } = { ...entityItem, requestIds: [] };
147
- return newResponse;
148
- },
149
- merge: (...items) => {
150
- return items.reduce((mergedItem, item) => item
151
- ? {
152
- requestIds: [...mergedItem.requestIds, ...item.requestIds],
153
- isFailure: mergedItem.isFailure || item.isFailure,
154
- isPending: mergedItem.isPending || item.isPending
155
- }
156
- : mergedItem, asyncStoreItemAdapter.initialize({}));
157
- },
158
- entityStatusAddRequest: (status, subResource, requestId) => {
159
- const currentSubStatus = status[subResource] || asyncStoreItemAdapter.initialize({});
160
- return {
161
- ...status,
162
- [subResource]: asyncStoreItemAdapter.addRequest(currentSubStatus, requestId)
163
- };
164
- },
165
- entityStatusResolveRequest: (status, subResource, requestId) => {
166
- const currentSubStatus = status[subResource];
167
- return {
168
- ...status,
169
- [subResource]: currentSubStatus ? asyncStoreItemAdapter.resolveRequest(currentSubStatus, requestId) : { requestIds: [] }
170
- };
171
- },
172
- entityStatusFailRequest: (status, subResource, requestId) => {
173
- const currentSubStatus = status[subResource];
174
- return {
175
- ...status,
176
- [subResource]: currentSubStatus ? asyncStoreItemAdapter.failRequest(currentSubStatus, requestId) : { requestIds: [], isFailure: true }
177
- };
178
- },
179
- entityStatusResetFailure: (status, subResource) => {
180
- const currentSubStatus = status[subResource];
181
- return {
182
- ...status,
183
- [subResource]: currentSubStatus ? asyncStoreItemAdapter.resetFailureStatus(currentSubStatus) : { requestIds: [] }
184
- };
185
- },
186
- resetFailureStatus: (entityItem) => {
187
- return {
188
- ...entityItem,
189
- isFailure: false
190
- };
191
- },
192
- setLoadingStatus: (entityItem) => {
193
- return {
194
- ...entityItem,
195
- isPending: true
196
- };
197
- }
59
+ addRequest: (item, requestId) => {
60
+ return {
61
+ ...item,
62
+ requestIds: [...item.requestIds, requestId],
63
+ isFailure: item.requestIds.length === 0 ? false : item.isFailure,
64
+ isPending: true
65
+ };
66
+ },
67
+ failRequest: (item, requestId) => {
68
+ const requestIds = requestId ? item.requestIds.filter((id) => id !== requestId) : item.requestIds;
69
+ return {
70
+ ...item,
71
+ isFailure: true,
72
+ isPending: requestIds.length > 0,
73
+ requestIds
74
+ };
75
+ },
76
+ resolveRequest: (item, requestId) => {
77
+ const requestIds = requestId ? item.requestIds.filter((id) => id !== requestId) : item.requestIds;
78
+ return {
79
+ ...item,
80
+ requestIds,
81
+ isPending: requestIds.length > 0
82
+ };
83
+ },
84
+ initialize: (entityItem) => {
85
+ return {
86
+ ...entityItem,
87
+ requestIds: []
88
+ };
89
+ },
90
+ extractAsyncStoreItem: (entityItem) => {
91
+ return {
92
+ requestIds: [...entityItem.requestIds],
93
+ isFailure: entityItem.isFailure,
94
+ isPending: entityItem.isPending
95
+ };
96
+ },
97
+ clearAsyncStoreItem: (entityItem) => {
98
+ const { isPending, isFailure, ...newResponse } = {
99
+ ...entityItem,
100
+ requestIds: []
101
+ };
102
+ return newResponse;
103
+ },
104
+ merge: (...items) => {
105
+ return items.reduce((mergedItem, item) => item ? {
106
+ requestIds: [...mergedItem.requestIds, ...item.requestIds],
107
+ isFailure: mergedItem.isFailure || item.isFailure,
108
+ isPending: mergedItem.isPending || item.isPending
109
+ } : mergedItem, asyncStoreItemAdapter.initialize({}));
110
+ },
111
+ entityStatusAddRequest: (status, subResource, requestId) => {
112
+ const currentSubStatus = status[subResource] || asyncStoreItemAdapter.initialize({});
113
+ return {
114
+ ...status,
115
+ [subResource]: asyncStoreItemAdapter.addRequest(currentSubStatus, requestId)
116
+ };
117
+ },
118
+ entityStatusResolveRequest: (status, subResource, requestId) => {
119
+ const currentSubStatus = status[subResource];
120
+ return {
121
+ ...status,
122
+ [subResource]: currentSubStatus ? asyncStoreItemAdapter.resolveRequest(currentSubStatus, requestId) : { requestIds: [] }
123
+ };
124
+ },
125
+ entityStatusFailRequest: (status, subResource, requestId) => {
126
+ const currentSubStatus = status[subResource];
127
+ return {
128
+ ...status,
129
+ [subResource]: currentSubStatus ? asyncStoreItemAdapter.failRequest(currentSubStatus, requestId) : {
130
+ requestIds: [],
131
+ isFailure: true
132
+ }
133
+ };
134
+ },
135
+ entityStatusResetFailure: (status, subResource) => {
136
+ const currentSubStatus = status[subResource];
137
+ return {
138
+ ...status,
139
+ [subResource]: currentSubStatus ? asyncStoreItemAdapter.resetFailureStatus(currentSubStatus) : { requestIds: [] }
140
+ };
141
+ },
142
+ resetFailureStatus: (entityItem) => {
143
+ return {
144
+ ...entityItem,
145
+ isFailure: false
146
+ };
147
+ },
148
+ setLoadingStatus: (entityItem) => {
149
+ return {
150
+ ...entityItem,
151
+ isPending: true
152
+ };
153
+ }
198
154
  };
199
-
200
- /**
201
- * Create an Asynchronous Request Entity Adapter
202
- * @param adapter Entity Adapter
203
- */
204
155
  function createEntityAsyncRequestAdapter(adapter) {
205
- const addRequestOne = (state, id, requestId) => {
206
- const currentEntity = typeof id !== 'undefined' && id !== null && state.entities[id];
207
- if (currentEntity) {
208
- const changes = asyncStoreItemAdapter.addRequest(asyncStoreItemAdapter.extractAsyncStoreItem(currentEntity), requestId);
209
- return adapter.updateOne({ id, changes }, state);
210
- }
211
- return asyncStoreItemAdapter.addRequest(state, requestId);
212
- };
213
- const addRequestMany = (state, ids, requestId) => adapter.updateMany(ids.filter((id) => !!state.entities[id]).map((id) => ({
214
- id,
215
- changes: asyncStoreItemAdapter.addRequest(asyncStoreItemAdapter.extractAsyncStoreItem(state.entities[id]), requestId)
216
- })), state);
217
- const resolveRequestOne = (state, entity, requestId, idProperty = 'id') => {
218
- const currentEntity = state.entities[entity[idProperty]];
219
- const newEntity = currentEntity
220
- ? asyncStoreItemAdapter.resolveRequest({ ...entity, ...asyncStoreItemAdapter.extractAsyncStoreItem(currentEntity) }, requestId)
221
- : asyncStoreItemAdapter.initialize(entity);
222
- state = asyncStoreItemAdapter.resolveRequest(state, requestId);
223
- return adapter.upsertOne(newEntity, state);
224
- };
225
- const resolveRequestMany = (state, entities, requestId, idProperty = 'id') => adapter.updateMany(entities.filter((entity) => !!state.entities[entity[idProperty]]).map((entity) => {
226
- const model = { ...entity, ...asyncStoreItemAdapter.extractAsyncStoreItem(state.entities[entity[idProperty]]) };
227
- return { id: entity[idProperty], changes: asyncStoreItemAdapter.resolveRequest(model, requestId) };
228
- }), state);
229
- const failRequestMany = (state, ids = [], requestId) => {
230
- if (ids.length > 0 && !ids.some((id) => state.entities[id] === undefined)) {
231
- return adapter.updateMany(ids.map((id) => ({
232
- id,
233
- changes: asyncStoreItemAdapter.failRequest(asyncStoreItemAdapter.extractAsyncStoreItem(state.entities[id]), requestId)
234
- })), state);
235
- }
236
- return asyncStoreItemAdapter.failRequest(state, requestId);
237
- };
238
- return {
239
- ...adapter,
240
- failRequestMany,
241
- addRequestOne,
242
- addRequestMany,
243
- resolveRequestOne,
244
- resolveRequestMany
245
- };
156
+ const addRequestOne = (state, id, requestId) => {
157
+ const currentEntity = typeof id !== "undefined" && id !== null && state.entities[id];
158
+ if (currentEntity) {
159
+ const changes = asyncStoreItemAdapter.addRequest(asyncStoreItemAdapter.extractAsyncStoreItem(currentEntity), requestId);
160
+ return adapter.updateOne({
161
+ id,
162
+ changes
163
+ }, state);
164
+ }
165
+ return asyncStoreItemAdapter.addRequest(state, requestId);
166
+ };
167
+ const addRequestMany = (state, ids, requestId) => adapter.updateMany(ids.filter((id) => !!state.entities[id]).map((id) => ({
168
+ id,
169
+ changes: asyncStoreItemAdapter.addRequest(asyncStoreItemAdapter.extractAsyncStoreItem(state.entities[id]), requestId)
170
+ })), state);
171
+ const resolveRequestOne = (state, entity, requestId, idProperty = "id") => {
172
+ const currentEntity = state.entities[entity[idProperty]];
173
+ const newEntity = currentEntity ? asyncStoreItemAdapter.resolveRequest({
174
+ ...entity,
175
+ ...asyncStoreItemAdapter.extractAsyncStoreItem(currentEntity)
176
+ }, requestId) : asyncStoreItemAdapter.initialize(entity);
177
+ state = asyncStoreItemAdapter.resolveRequest(state, requestId);
178
+ return adapter.upsertOne(newEntity, state);
179
+ };
180
+ const resolveRequestMany = (state, entities, requestId, idProperty = "id") => adapter.updateMany(entities.filter((entity) => !!state.entities[entity[idProperty]]).map((entity) => {
181
+ const model = {
182
+ ...entity,
183
+ ...asyncStoreItemAdapter.extractAsyncStoreItem(state.entities[entity[idProperty]])
184
+ };
185
+ return {
186
+ id: entity[idProperty],
187
+ changes: asyncStoreItemAdapter.resolveRequest(model, requestId)
188
+ };
189
+ }), state);
190
+ const failRequestMany = (state, ids = [], requestId) => {
191
+ if (ids.length > 0 && !ids.some((id) => state.entities[id] === void 0)) return adapter.updateMany(ids.map((id) => ({
192
+ id,
193
+ changes: asyncStoreItemAdapter.failRequest(asyncStoreItemAdapter.extractAsyncStoreItem(state.entities[id]), requestId)
194
+ })), state);
195
+ return asyncStoreItemAdapter.failRequest(state, requestId);
196
+ };
197
+ return {
198
+ ...adapter,
199
+ failRequestMany,
200
+ addRequestOne,
201
+ addRequestMany,
202
+ resolveRequestOne,
203
+ resolveRequestMany
204
+ };
246
205
  }
247
-
248
- /**
249
- * Determine if the action is an AsyncRequest action
250
- * @param action Redux Action
251
- */
252
206
  function isCallAction(action) {
253
- if (!action) {
254
- return false;
255
- }
256
- return !!action.call && action.call instanceof Promise;
207
+ if (!action) return false;
208
+ return !!action.call && action.call instanceof Promise;
257
209
  }
258
- /**
259
- * Determine if the action is an AsyncRequest action with a Request ID
260
- * @param action Redux Action
261
- */
262
210
  function isIdentifiedCallAction(action) {
263
- return isCallAction(action) && typeof action.requestId !== 'undefined';
211
+ return isCallAction(action) && typeof action.requestId !== "undefined";
264
212
  }
265
- /**
266
- * Determine if the given item implements the AsyncRequest interface
267
- * @param item
268
- */
269
213
  function isAsyncRequest(item) {
270
- return typeof item.requestId !== 'undefined';
214
+ return typeof item.requestId !== "undefined";
271
215
  }
272
-
273
- /**
274
- * Determine if the given parameter is a Promise
275
- * @param object
276
- */
277
- const isPromise = (object) => object && typeof object === 'object' && typeof object.then !== 'undefined';
278
- /**
279
- * Custom operator to use instead of SwitchMap with effects based on FromApi actions.
280
- * It makes sure to emit an action when the inner subscription is unsubscribed in order to keep the store up-to-date with pending information.
281
- * @param successHandler function that returns the action to emit in case the FromApi call is a success
282
- * @param errorHandler function that returns the action to emit in case the FromApi call fails
283
- * @param cancelRequestActionFactory function that returns the action to emit in case the FromApi action is 'cancelled' because a new action was received by the switchMap
284
- */
216
+ const isPromise = (object) => object && typeof object === "object" && typeof object.then !== "undefined";
285
217
  function fromApiEffectSwitchMap(successHandler, errorHandler, cancelRequestActionFactory) {
286
- const pendingRequestIdsContext = {};
287
- return (source$) => source$.pipe(tap((action) => {
288
- if (isIdentifiedCallAction(action)) {
289
- pendingRequestIdsContext[action.requestId] = true;
290
- }
291
- }), startWith(undefined), pairwise(), switchMap(([previousAction, action]) => {
292
- if (!action) {
293
- return EMPTY;
294
- }
295
- const isPreviousActionStillRunning = isIdentifiedCallAction(previousAction) && pendingRequestIdsContext[previousAction.requestId];
296
- const cleanStack = () => {
297
- if (isIdentifiedCallAction(action)) {
298
- delete pendingRequestIdsContext[action.requestId];
299
- }
300
- };
301
- return from(action.call).pipe(tap(cleanStack), switchMap((result) => {
302
- const success = successHandler(result, action);
303
- return isObservable(success) ? success : (isPromise(success) ? success : of(success));
304
- }), catchError((error) => {
305
- cleanStack();
306
- return errorHandler?.(error, action) || EMPTY;
307
- }), isPreviousActionStillRunning && cancelRequestActionFactory ? startWith(cancelRequestActionFactory({ requestId: previousAction.requestId }, action)) : identity);
308
- }));
218
+ const pendingRequestIdsContext = {};
219
+ return (source$) => source$.pipe(tap((action) => {
220
+ if (isIdentifiedCallAction(action)) pendingRequestIdsContext[action.requestId] = true;
221
+ }), startWith(void 0), pairwise(), switchMap(([previousAction, action]) => {
222
+ if (!action) return EMPTY;
223
+ const isPreviousActionStillRunning = isIdentifiedCallAction(previousAction) && pendingRequestIdsContext[previousAction.requestId];
224
+ const cleanStack = () => {
225
+ if (isIdentifiedCallAction(action)) delete pendingRequestIdsContext[action.requestId];
226
+ };
227
+ return from(action.call).pipe(tap(cleanStack), switchMap((result) => {
228
+ const success = successHandler(result, action);
229
+ return isObservable(success) ? success : isPromise(success) ? success : of(success);
230
+ }), catchError((error) => {
231
+ cleanStack();
232
+ return errorHandler?.(error, action) || EMPTY;
233
+ }), isPreviousActionStillRunning && cancelRequestActionFactory ? startWith(cancelRequestActionFactory({ requestId: previousAction.requestId }, action)) : identity);
234
+ }));
309
235
  }
310
- /**
311
- * Same as {@link fromApiEffectSwitchMap}, instead one inner subscription is kept by id.
312
- * @param successHandler
313
- * @param errorHandler
314
- * @param cancelRequestActionFactory
315
- * @param cleanUpTimer
316
- */
317
236
  function fromApiEffectSwitchMapById(successHandler, errorHandler, cancelRequestActionFactory, cleanUpTimer) {
318
- const innerSourcesById = {};
319
- return (source$) => {
320
- return source$.pipe(filter$1((action) => {
321
- if (!isIdentifiedCallAction(action) || !action.id) {
322
- return false;
323
- }
324
- if (isIdentifiedCallAction(action) && innerSourcesById[action.id]) {
325
- innerSourcesById[action.id][0].next(action);
326
- return false;
327
- }
328
- return true;
329
- }), switchMap((action) => {
330
- const newIdSubject = new BehaviorSubject(action);
331
- const newId$ = newIdSubject.pipe(fromApiEffectSwitchMap(successHandler, errorHandler, cancelRequestActionFactory));
332
- innerSourcesById[action.id] = [newIdSubject, newId$];
333
- if (cleanUpTimer !== undefined) {
334
- newIdSubject.pipe(switchMap((myAction) => from(myAction.call).pipe(delay(cleanUpTimer), finalize(() => {
335
- delete innerSourcesById[myAction.id];
336
- newIdSubject.complete();
337
- })))).subscribe();
338
- }
339
- const streams = Object.values(innerSourcesById).map(([_, obs]) => obs);
340
- return merge(...streams);
341
- }));
342
- };
237
+ const innerSourcesById = {};
238
+ return (source$) => {
239
+ return source$.pipe(filter$1((action) => {
240
+ if (!isIdentifiedCallAction(action) || !action.id) return false;
241
+ if (isIdentifiedCallAction(action) && innerSourcesById[action.id]) {
242
+ innerSourcesById[action.id][0].next(action);
243
+ return false;
244
+ }
245
+ return true;
246
+ }), switchMap((action) => {
247
+ const newIdSubject = new BehaviorSubject(action);
248
+ const newId$ = newIdSubject.pipe(fromApiEffectSwitchMap(successHandler, errorHandler, cancelRequestActionFactory));
249
+ innerSourcesById[action.id] = [newIdSubject, newId$];
250
+ if (cleanUpTimer !== void 0) newIdSubject.pipe(switchMap((myAction) => from(myAction.call).pipe(delay(cleanUpTimer), finalize(() => {
251
+ delete innerSourcesById[myAction.id];
252
+ newIdSubject.complete();
253
+ })))).subscribe();
254
+ const streams = Object.values(innerSourcesById).map(([_, obs]) => obs);
255
+ return merge(...streams);
256
+ }));
257
+ };
343
258
  }
344
-
345
- /**
346
- * Returns a creator that makes sure that requestId is defined in the action's properties by generating one
347
- * if needed.
348
- */
349
259
  const asyncProps = () => {
350
- return (props) => isAsyncRequest(props) ? props : { ...props, requestId: v4() };
260
+ return (props) => isAsyncRequest(props) ? props : {
261
+ ...props,
262
+ requestId: v4()
263
+ };
351
264
  };
352
-
353
- /**
354
- * Serializer for asynchronous store.
355
- * @param state State of an asynchronous store to serialize
356
- * @returns a plain json object to pass to json.stringify
357
- */
358
265
  function asyncSerializer(state) {
359
- return asyncStoreItemAdapter.clearAsyncStoreItem(state);
266
+ return asyncStoreItemAdapter.clearAsyncStoreItem(state);
360
267
  }
361
- /**
362
- * Serializer for asynchronous entity store.
363
- * @param state State of an asynchronous entity store to serialize
364
- * @returns a plain json object to pass to json.stringify
365
- */
366
268
  function asyncEntitySerializer(state) {
367
- const entities = state.ids.reduce((entitiesAcc, entityId) => {
368
- entitiesAcc[entityId] = asyncStoreItemAdapter.clearAsyncStoreItem(state.entities[entityId]);
369
- return entitiesAcc;
370
- }, {});
371
- return { ...asyncStoreItemAdapter.clearAsyncStoreItem(state), entities };
269
+ const entities = state.ids.reduce((entitiesAcc, entityId) => {
270
+ entitiesAcc[entityId] = asyncStoreItemAdapter.clearAsyncStoreItem(state.entities[entityId]);
271
+ return entitiesAcc;
272
+ }, {});
273
+ return {
274
+ ...asyncStoreItemAdapter.clearAsyncStoreItem(state),
275
+ entities
276
+ };
372
277
  }
373
- /**
374
- * Serializer for asynchronous entity store with status.
375
- * @param state State of an asynchronous entity store with status to serialize
376
- * @returns a plain json object to pass to json.stringify
377
- */
378
278
  function asyncEntityWithStatusSerializer(state) {
379
- const entities = state.ids.reduce((entitiesAcc, entityId) => {
380
- entitiesAcc[entityId] = { ...asyncStoreItemAdapter.clearAsyncStoreItem(state.entities[entityId]), status: {} };
381
- return entitiesAcc;
382
- }, {});
383
- return { ...asyncStoreItemAdapter.clearAsyncStoreItem(state), entities };
384
- }
385
-
386
- class StateSerializer {
387
- constructor(serializer) {
388
- this.reviver = (_, value) => value;
389
- this.serialize = serializer.serialize || this.serialize;
390
- this.deserialize = serializer.deserialize || this.deserialize;
391
- this.reviver = serializer.reviver || this.reviver;
392
- this.replacer = serializer.replacer || this.replacer;
393
- this.initialState = serializer.initialState || this.initialState;
394
- }
279
+ const entities = state.ids.reduce((entitiesAcc, entityId) => {
280
+ entitiesAcc[entityId] = {
281
+ ...asyncStoreItemAdapter.clearAsyncStoreItem(state.entities[entityId]),
282
+ status: {}
283
+ };
284
+ return entitiesAcc;
285
+ }, {});
286
+ return {
287
+ ...asyncStoreItemAdapter.clearAsyncStoreItem(state),
288
+ entities
289
+ };
395
290
  }
396
-
397
- /**
398
- * Pad number
399
- * @param val
400
- * @param digits
401
- */
291
+ var StateSerializer = class {
292
+ constructor(serializer) {
293
+ this.reviver = (_, value) => value;
294
+ this.serialize = serializer.serialize || this.serialize;
295
+ this.deserialize = serializer.deserialize || this.deserialize;
296
+ this.reviver = serializer.reviver || this.reviver;
297
+ this.replacer = serializer.replacer || this.replacer;
298
+ this.initialState = serializer.initialState || this.initialState;
299
+ }
300
+ };
402
301
  function padNumber(val, digits = 2) {
403
- const str = `${val}`;
404
- return '0'.repeat(Math.max(0, digits - str.length)) + str;
302
+ const str = `${val}`;
303
+ return "0".repeat(Math.max(0, digits - str.length)) + str;
405
304
  }
406
- /**
407
- * Returns TRUE if bootstrap config environment is production FALSE otherwise
408
- * @param dataset
409
- * @returns TRUE if bootstrap config environment is production FALSE otherwise
410
- */
411
305
  function isProductionEnvironment(dataset) {
412
- const bootstrapConfig = dataset.bootstrapconfig && JSON.parse(dataset.bootstrapconfig);
413
- return bootstrapConfig?.environment === 'prod';
306
+ return (dataset.bootstrapconfig && JSON.parse(dataset.bootstrapconfig))?.environment === "prod";
414
307
  }
415
-
416
308
  const defaultConstruct = (data) => data;
417
309
  const isDate = (data) => data instanceof Date && !Number.isNaN(data);
418
- /**
419
- * Check if an object is not an array or a date
420
- * @param obj
421
- * @param additionalMappers
422
- */
423
310
  function isObject(obj, additionalMappers) {
424
- return obj instanceof Object && !Array.isArray(obj) && !additionalMappers?.some((mapper) => mapper.condition(obj)) && !isDate(obj);
311
+ return obj instanceof Object && !Array.isArray(obj) && !additionalMappers?.some((mapper) => mapper.condition(obj)) && !isDate(obj);
425
312
  }
426
- /**
427
- * Return a new reference of the given object
428
- * @param obj
429
- * @param additionalMappers
430
- */
431
313
  function immutablePrimitive(obj, additionalMappers) {
432
- if (Array.isArray(obj)) {
433
- return obj.slice();
434
- }
435
- const matchingPrimitive = additionalMappers?.find((mapper) => mapper.condition(obj));
436
- const resolvedType = matchingPrimitive && ((matchingPrimitive.construct || defaultConstruct)(obj));
437
- if (resolvedType !== undefined) {
438
- return resolvedType;
439
- }
440
- if (isDate(obj)) {
441
- return new Date(obj);
442
- }
443
- else if (obj instanceof Object) {
444
- return deepFill(obj, obj, additionalMappers);
445
- }
446
- else {
447
- return obj;
448
- }
314
+ if (Array.isArray(obj)) return obj.slice();
315
+ const matchingPrimitive = additionalMappers?.find((mapper) => mapper.condition(obj));
316
+ const resolvedType = matchingPrimitive && (matchingPrimitive.construct || defaultConstruct)(obj);
317
+ if (resolvedType !== void 0) return resolvedType;
318
+ if (isDate(obj)) return new Date(obj);
319
+ else if (obj instanceof Object) return deepFill(obj, obj, additionalMappers);
320
+ else return obj;
449
321
  }
450
- /**
451
- * Deep fill of base object using source
452
- * It will do a deep merge of the objects, overriding arrays
453
- * All properties not present in source, but present in base, will remain
454
- * @param base
455
- * @param source
456
- * @param additionalMappers Map of conditions of type mapper
457
- */
458
322
  function deepFill(base, source, additionalMappers) {
459
- if (typeof source === 'undefined') {
460
- return deepFill(base, base, additionalMappers);
461
- }
462
- if (!isObject(base, additionalMappers)) {
463
- return immutablePrimitive(typeof source === 'undefined' ? base : source, additionalMappers);
464
- }
465
- const newObj = { ...base };
466
- for (const key in base) {
467
- if (source[key] === null) {
468
- newObj[key] = immutablePrimitive(null, additionalMappers);
469
- }
470
- else if (key in source && typeof base[key] === typeof source[key]) {
471
- const keyOfSource = source[key];
472
- newObj[key] = typeof keyOfSource === 'undefined' ? immutablePrimitive(base[key], additionalMappers) : deepFill(base[key], keyOfSource, additionalMappers);
473
- }
474
- else {
475
- newObj[key] = immutablePrimitive(base[key], additionalMappers);
476
- }
477
- }
478
- // getting keys present in source and not present in base
479
- for (const key in source) {
480
- if (!(key in newObj)) {
481
- newObj[key] = immutablePrimitive(source[key], additionalMappers);
482
- }
483
- }
484
- return newObj;
323
+ if (typeof source === "undefined") return deepFill(base, base, additionalMappers);
324
+ if (!isObject(base, additionalMappers)) return immutablePrimitive(typeof source === "undefined" ? base : source, additionalMappers);
325
+ const newObj = { ...base };
326
+ for (const key in base) if (source[key] === null) newObj[key] = immutablePrimitive(null, additionalMappers);
327
+ else if (key in source && typeof base[key] === typeof source[key]) {
328
+ const keyOfSource = source[key];
329
+ newObj[key] = typeof keyOfSource === "undefined" ? immutablePrimitive(base[key], additionalMappers) : deepFill(base[key], keyOfSource, additionalMappers);
330
+ } else newObj[key] = immutablePrimitive(base[key], additionalMappers);
331
+ for (const key in source) if (!(key in newObj)) newObj[key] = immutablePrimitive(source[key], additionalMappers);
332
+ return newObj;
485
333
  }
486
-
487
- /**
488
- * Buffers and emits data for lazy/progressive rendering of big lists
489
- * That could solve issues with long-running tasks when trying to render an array
490
- * of similar components.
491
- * @param delayMs Delay between data emits
492
- * @param concurrency Amount of elements that should be emitted at once
493
- */
494
334
  function lazyArray(delayMs = 0, concurrency = 2) {
495
- let isFirstEmission = true;
496
- return (source$) => {
497
- return source$.pipe(mergeMap((items) => {
498
- if (!isFirstEmission) {
499
- return of(items);
500
- }
501
- const items$ = from(items);
502
- return items$.pipe(bufferCount(concurrency), concatMap((value, index) => {
503
- return of(value).pipe(observeOn(animationFrameScheduler), delay(index * delayMs));
504
- }), scan((acc, steps) => {
505
- return [...acc, ...steps];
506
- }, []), tap((scannedItems) => {
507
- const scanDidComplete = scannedItems.length === items.length;
508
- if (scanDidComplete) {
509
- isFirstEmission = false;
510
- }
511
- }));
512
- }));
513
- };
335
+ let isFirstEmission = true;
336
+ return (source$) => {
337
+ return source$.pipe(mergeMap((items) => {
338
+ if (!isFirstEmission) return of(items);
339
+ return from(items).pipe(bufferCount(concurrency), concatMap((value, index) => {
340
+ return of(value).pipe(observeOn(animationFrameScheduler), delay(index * delayMs));
341
+ }), scan((acc, steps) => {
342
+ return [...acc, ...steps];
343
+ }, []), tap((scannedItems) => {
344
+ if (scannedItems.length === items.length) isFirstEmission = false;
345
+ }));
346
+ }));
347
+ };
514
348
  }
515
-
516
- /**
517
- * Generated bundle index. Do not edit.
518
- */
519
-
520
349
  export { DEFAULT_BUILD_PROPERTIES, O3rComponent, StateSerializer, applicationMessageTarget, asyncEntitySerializer, asyncEntityWithStatusSerializer, asyncProps, asyncSerializer, asyncStoreItemAdapter, computeItemIdentifier, createEntityAsyncRequestAdapter, deepFill, filterMessageContent, fromApiEffectSwitchMap, fromApiEffectSwitchMapById, immutablePrimitive, isAsyncRequest, isCallAction, isIdentifiedCallAction, isObject, isOtterMessage, isProductionEnvironment, isToAppOtterMessage, lazyArray, otterComponentInfoPropertyName, otterMessageType, padNumber, sendOtterMessage };
521
- //# sourceMappingURL=o3r-core.mjs.map
350
+
351
+ //# sourceMappingURL=o3r-core.mjs.map