@shapediver/viewer.session-engine.session-engine 2.8.4 → 2.9.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,12 +1,11 @@
1
- import { HttpClient, HttpResponse, PerformanceEvaluator, UuidGenerator, SystemInfo, Logger, ShapeDiverViewerSessionError, ShapeDiverViewerError, Converter, SettingsEngine, EVENTTYPE, EventEngine, StateEngine, ShapeDiverViewerSettingsError } from '@shapediver/viewer.shared.services'
1
+ import { HttpClient, HttpResponse, PerformanceEvaluator, UuidGenerator, SystemInfo, Logger, ShapeDiverViewerSessionError, ShapeDiverViewerError, Converter, SettingsEngine, EVENTTYPE, EventEngine, StateEngine, ShapeDiverViewerSettingsError, ShapeDiverGeometryBackendResponseError, ShapeDiverGeometryBackendRequestError } from '@shapediver/viewer.shared.services'
2
2
 
3
3
  import { OutputDelayException } from './OutputDelayException'
4
- import { OutputLoader } from './OutputLoader'
4
+ import { OutputLoader, OutputLoaderTaskEventInfo } from './OutputLoader'
5
5
  import { SessionTreeNode } from './SessionTreeNode'
6
6
  import { ISessionEngine, ISettingsSections, PARAMETER_TYPE } from '../interfaces/ISessionEngine'
7
7
  import { SessionData } from './SessionData'
8
- import { create, ShapeDiverError as ShapeDiverBackendError, ShapeDiverResponseErrorType, ShapeDiverRequestGltfUploadQueryConversion, ShapeDiverResponseDto, ShapeDiverResponseError, ShapeDiverResponseExport, ShapeDiverResponseExportDefinitionType, ShapeDiverResponseOutput, ShapeDiverResponseParameter, ShapeDiverSdk, ShapeDiverSdkConfigType, ShapeDiverResponseModelComputationStatus } from '@shapediver/sdk.geometry-api-sdk-v2'
9
- import { AxiosRequestConfig } from 'axios'
8
+ import { create, ShapeDiverError as ShapeDiverBackendError, ShapeDiverResponseErrorType, ShapeDiverRequestGltfUploadQueryConversion, ShapeDiverResponseDto, ShapeDiverResponseError, ShapeDiverResponseExport, ShapeDiverResponseExportDefinitionType, ShapeDiverResponseOutput, ShapeDiverResponseParameter, ShapeDiverSdk, ShapeDiverSdkConfigType, ShapeDiverResponseModelComputationStatus, ShapeDiverRequestError } from '@shapediver/sdk.geometry-api-sdk-v2'
10
9
  import { ISessionTreeNode } from '../interfaces/ISessionTreeNode'
11
10
  import { ITree, ITreeNode, Tree, TreeNode } from '@shapediver/viewer.shared.node-tree'
12
11
  import { ITaskEvent, TASK_TYPE } from '@shapediver/viewer.shared.types'
@@ -19,7 +18,7 @@ import { Parameter } from './dto/Parameter'
19
18
  import { vec3 } from 'gl-matrix'
20
19
  import { Export } from './dto/Export'
21
20
  import { Output } from './dto/Output'
22
- import { convert, ISettingsV3_3, latestVersion, validate, versions } from '@shapediver/viewer.settings'
21
+ import { convert, ISettingsV3_4, latestVersion, validate, versions } from '@shapediver/viewer.settings'
23
22
 
24
23
  export class SessionEngine implements ISessionEngine {
25
24
  // #region Properties (40)
@@ -66,11 +65,12 @@ export class SessionEngine implements ISessionEngine {
66
65
  private _refreshBearerToken?: () => Promise<string>;
67
66
  private _responseDto?: ShapeDiverResponseDto;
68
67
  private _retryCounter = 0;
69
- private _sdk: ShapeDiverSdk;
68
+ private _sdk!: ShapeDiverSdk;
70
69
  private _sessionId?: string;
71
70
  private _updateCallback: ((newNode: ITreeNode, oldNode: ITreeNode) => void) | null = null;
72
71
  private _viewerSettings?: object;
73
72
  private _viewerSettingsVersion: string = latestVersion;
73
+ private _viewerSettingsVersionBackend: string = latestVersion;
74
74
 
75
75
  #customizationProcess!: string;
76
76
  #parameterHistory: {
@@ -106,8 +106,12 @@ export class SessionEngine implements ISessionEngine {
106
106
  this._headers['X-ShapeDiver-BuildVersion'] = properties.buildVersion;
107
107
  this._outputLoader = new OutputLoader(this);
108
108
 
109
- this._sdk = create(this._modelViewUrl, this._bearerToken);
110
- this._sdk.setConfigurationValue(ShapeDiverSdkConfigType.REQUEST_HEADERS, this._headers);
109
+ try {
110
+ this._sdk = create(this._modelViewUrl, this._bearerToken);
111
+ this._sdk.setConfigurationValue(ShapeDiverSdkConfigType.REQUEST_HEADERS, this._headers);
112
+ } catch (e) {
113
+ throw this._httpClient.convertError(e);
114
+ }
111
115
  }
112
116
 
113
117
  // #endregion Constructors (1)
@@ -129,7 +133,11 @@ export class SessionEngine implements ISessionEngine {
129
133
 
130
134
  public set bearerToken(value: string | undefined) {
131
135
  this._bearerToken = value;
132
- this._sdk.setConfigurationValue(ShapeDiverSdkConfigType.JWT_TOKEN, value);
136
+ try {
137
+ this._sdk.setConfigurationValue(ShapeDiverSdkConfigType.JWT_TOKEN, value);
138
+ } catch (e) {
139
+ throw this._httpClient.convertError(e);
140
+ }
133
141
  }
134
142
 
135
143
  public get canUploadGLTF(): boolean {
@@ -254,7 +262,7 @@ export class SessionEngine implements ISessionEngine {
254
262
  throw new ShapeDiverViewerSettingsError('Session.applySettings: Was not able to validate config object.');
255
263
  }
256
264
 
257
- const settings = <ISettingsV3_3>convert(config, latestVersion);
265
+ const settings = <ISettingsV3_4>convert(config, latestVersion);
258
266
 
259
267
  const exportMappingUid: { [key: string]: string | undefined } = {};
260
268
  if (sections.session.export.displayname || sections.session.export.order || sections.session.export.hidden)
@@ -335,6 +343,7 @@ export class SessionEngine implements ISessionEngine {
335
343
  }
336
344
 
337
345
  if (sections.viewport.general) {
346
+ currentSettings.general.defaultMaterialColor = settings.general.defaultMaterialColor;
338
347
  currentSettings.general.commitParameters = settings.general.commitParameters;
339
348
  currentSettings.general.pointSize = settings.general.pointSize;
340
349
  }
@@ -345,6 +354,9 @@ export class SessionEngine implements ISessionEngine {
345
354
  currentSettings.environment.clearColor = settings.environment.clearColor;
346
355
  currentSettings.environment.map = settings.environment.map;
347
356
  currentSettings.environment.mapAsBackground = settings.environment.mapAsBackground;
357
+ currentSettings.environment.rotation = settings.environment.rotation;
358
+ currentSettings.environment.blurriness = settings.environment.blurriness;
359
+ currentSettings.environment.intensity = settings.environment.intensity;
348
360
  }
349
361
  }
350
362
 
@@ -464,12 +476,20 @@ export class SessionEngine implements ISessionEngine {
464
476
  this.parameterValues[parameterId] = parameterSet[parameterId].valueString;
465
477
  this._logger.info(`Session(${this.id}).customize: Customizing session with parameters ${JSON.stringify(this.parameterValues)}.`);
466
478
 
467
- const eventRequest: ITaskEvent = { type: TASK_TYPE.SESSION_CUSTOMIZATION, id: eventId, progress: 0.25, data: { sessionId: this.id }, status: 'Sending customization request' };
479
+ const eventRequest: ITaskEvent = { type: TASK_TYPE.SESSION_CUSTOMIZATION, id: eventId, progress: 0.1, data: { sessionId: this.id }, status: 'Sending customization request' };
468
480
  this._eventEngine.emitEvent(EVENTTYPE.TASK.TASK_PROCESS, eventRequest);
469
481
 
470
- const newNode = await this.customizeInternal(() => this.#customizationProcess !== customizationId);
471
-
472
- const eventSceneUpdate: ITaskEvent = { type: TASK_TYPE.SESSION_CUSTOMIZATION, id: eventId, progress: 0.75, data: { sessionId: this.id }, status: 'Updating scene' };
482
+ const newNode = await this.customizeInternal(() => this.#customizationProcess !== customizationId, {
483
+ eventId,
484
+ type: TASK_TYPE.SESSION_CUSTOMIZATION,
485
+ progressRange: {
486
+ min: 0.1,
487
+ max: 0.9
488
+ },
489
+ data: { sessionId: this.id }
490
+ });
491
+
492
+ const eventSceneUpdate: ITaskEvent = { type: TASK_TYPE.SESSION_CUSTOMIZATION, id: eventId, progress: 0.9, data: { sessionId: this.id }, status: 'Updating scene' };
473
493
  this._eventEngine.emitEvent(EVENTTYPE.TASK.TASK_PROCESS, eventSceneUpdate);
474
494
 
475
495
  // OPTION TO SKIP - PART 2
@@ -537,11 +557,16 @@ export class SessionEngine implements ISessionEngine {
537
557
  if (this._stateEngine.renderingEngines[r].busy.includes(customizationId))
538
558
  this._stateEngine.renderingEngines[r].busy.splice(this._stateEngine.renderingEngines[r].busy.indexOf(customizationId), 1);
539
559
 
540
- throw e;
560
+ throw this._httpClient.convertError(e);
541
561
  }
542
562
  }
543
563
 
544
564
  public async customizeParallel(parameterValues: { [key: string]: string }): Promise<ITreeNode> {
565
+ const eventId = this._uuidGenerator.create();
566
+
567
+ const eventStart: ITaskEvent = { type: TASK_TYPE.SESSION_CUSTOMIZATION, id: eventId, progress: 0, data: { sessionId: this.id }, status: 'Customizing session' };
568
+ this._eventEngine.emitEvent(EVENTTYPE.TASK.TASK_START, eventStart);
569
+
545
570
  const parameterSet: {
546
571
  [key: string]: string
547
572
  } = {};
@@ -550,8 +575,20 @@ export class SessionEngine implements ISessionEngine {
550
575
  for (const parameterId in this.parameters)
551
576
  parameterSet[parameterId] = parameterValues[parameterId] !== undefined ? (' ' + parameterValues[parameterId]).slice(1) : this.parameters[parameterId].stringify()
552
577
 
553
- const newNode = await this.customizeSession(parameterSet, () => false, true);
578
+ const newNode = await this.customizeSession(parameterSet, () => false, {
579
+ eventId,
580
+ type: TASK_TYPE.SESSION_CUSTOMIZATION,
581
+ progressRange: {
582
+ min: 0.0,
583
+ max: 1
584
+ },
585
+ data: { sessionId: this.id }
586
+ }, true);
554
587
  newNode.excludeViewports = JSON.parse(JSON.stringify(this._excludeViewports));
588
+
589
+
590
+ const eventEnd: ITaskEvent = { type: TASK_TYPE.SESSION_CUSTOMIZATION, id: eventId, progress: 1, data: { sessionId: this.id }, status: 'Session customized' };
591
+ this._eventEngine.emitEvent(EVENTTYPE.TASK.TASK_END, eventEnd);
555
592
  return newNode;
556
593
  }
557
594
 
@@ -620,8 +657,7 @@ export class SessionEngine implements ISessionEngine {
620
657
  this._performanceEvaluator.endSection('sessionResponse');
621
658
 
622
659
  this._viewerSettings = this._responseDto.viewer?.config;
623
- this._viewerSettingsVersion = this._responseDto.viewerSettingsVersion || latestVersion;
624
- this._settingsEngine.loadSettings(this._viewerSettings);
660
+ this._viewerSettingsVersionBackend = this._responseDto.viewerSettingsVersion || latestVersion;
625
661
  this._sessionId = this._responseDto.sessionId;
626
662
  this._modelId = this._responseDto.model?.id;
627
663
 
@@ -630,6 +666,8 @@ export class SessionEngine implements ISessionEngine {
630
666
  downloadTexture: this._sdk.asset.downloadImage.bind(this._sdk.asset),
631
667
  })
632
668
 
669
+ this._settingsEngine.loadSettings(this._viewerSettings);
670
+
633
671
  if (!this._sessionId)
634
672
  throw new ShapeDiverViewerSessionError(`Session.init: Initialization of session failed. ResponseDto did not have a sessionId.`)
635
673
  if (!this._modelId)
@@ -652,7 +690,7 @@ export class SessionEngine implements ISessionEngine {
652
690
  * @param outputs the outputs to load
653
691
  * @returns promise with a scene graph node
654
692
  */
655
- public async loadOutputsParallel(responseDto: ShapeDiverResponseDto, cancelRequest: () => boolean = () => false, retry = false): Promise<ISessionTreeNode> {
693
+ public async loadOutputsParallel(responseDto: ShapeDiverResponseDto, cancelRequest: () => boolean = () => false, taskEventInfo: OutputLoaderTaskEventInfo, retry = false): Promise<ISessionTreeNode> {
656
694
  this.checkAvailability();
657
695
 
658
696
  let outputs: {
@@ -669,7 +707,7 @@ export class SessionEngine implements ISessionEngine {
669
707
  }
670
708
 
671
709
  try {
672
- const node = await this._outputLoader.loadOutputs(this._responseDto!.model?.name || 'model', outputs, outputsFreeze);
710
+ const node = await this._outputLoader.loadOutputs(this._responseDto!.model?.name || 'model', outputs, outputsFreeze, taskEventInfo);
673
711
  node.data.push(new SessionData(responseDto));
674
712
  return node;
675
713
  }
@@ -679,7 +717,7 @@ export class SessionEngine implements ISessionEngine {
679
717
  } else {
680
718
  await this.handleError(e, retry);
681
719
  if (cancelRequest()) return new SessionTreeNode();
682
- return await this.loadOutputsParallel(responseDto, cancelRequest, true);
720
+ return await this.loadOutputsParallel(responseDto, cancelRequest, taskEventInfo, true);
683
721
  }
684
722
 
685
723
  if (cancelRequest()) return new SessionTreeNode();
@@ -691,11 +729,11 @@ export class SessionEngine implements ISessionEngine {
691
729
  const responseDto = await this._sdk.output.getCache(this._sessionId!, outputMapping);
692
730
  if (cancelRequest()) return new SessionTreeNode();
693
731
  this.updateResponseDto(responseDto);
694
- return await this.loadOutputsParallel(responseDto, cancelRequest);
732
+ return await this.loadOutputsParallel(responseDto, cancelRequest, taskEventInfo);
695
733
  } catch (e) {
696
734
  await this.handleError(e, retry);
697
735
  if (cancelRequest()) return new SessionTreeNode();
698
- return await this.loadOutputsParallel(responseDto, cancelRequest, true);
736
+ return await this.loadOutputsParallel(responseDto, cancelRequest, taskEventInfo, true);
699
737
  }
700
738
  }
701
739
  }
@@ -708,13 +746,13 @@ export class SessionEngine implements ISessionEngine {
708
746
  * @param outputs the outputs to load
709
747
  * @returns promise with a scene graph node
710
748
  */
711
- public async loadOutputs(cancelRequest: () => boolean = () => false, retry = false): Promise<ISessionTreeNode> {
749
+ public async loadOutputs(cancelRequest: () => boolean = () => false, taskEventInfo: OutputLoaderTaskEventInfo, retry = false): Promise<ISessionTreeNode> {
712
750
  this.checkAvailability();
713
751
 
714
752
  const o = Object.assign({}, this._outputs);
715
753
  const of = Object.assign({}, this._outputsFreeze);
716
754
  try {
717
- const node = await this._outputLoader.loadOutputs(this._responseDto!.model?.name || 'model', o, of);
755
+ const node = await this._outputLoader.loadOutputs(this._responseDto!.model?.name || 'model', o, of, taskEventInfo);
718
756
  node.data.push(new SessionData(this._responseDto!));
719
757
 
720
758
  if (cancelRequest()) return node;
@@ -733,7 +771,7 @@ export class SessionEngine implements ISessionEngine {
733
771
  } else {
734
772
  await this.handleError(e, retry);
735
773
  if (cancelRequest()) return new SessionTreeNode();
736
- return await this.loadOutputs(cancelRequest, true);
774
+ return await this.loadOutputs(cancelRequest, taskEventInfo, true);
737
775
  }
738
776
 
739
777
  if (cancelRequest()) return new SessionTreeNode();
@@ -745,11 +783,11 @@ export class SessionEngine implements ISessionEngine {
745
783
  const responseDto = await this._sdk.output.getCache(this._sessionId!, outputMapping);
746
784
  if (cancelRequest()) return new SessionTreeNode();
747
785
  this.updateResponseDto(responseDto);
748
- return await this.loadOutputs(cancelRequest);
786
+ return await this.loadOutputs(cancelRequest, taskEventInfo);
749
787
  } catch (e) {
750
788
  await this.handleError(e, retry);
751
789
  if (cancelRequest()) return new SessionTreeNode();
752
- return await this.loadOutputs(cancelRequest, true);
790
+ return await this.loadOutputs(cancelRequest, taskEventInfo, true);
753
791
  }
754
792
  }
755
793
  }
@@ -889,6 +927,11 @@ export class SessionEngine implements ISessionEngine {
889
927
 
890
928
  try {
891
929
  validate(json, <versions>this._viewerSettingsVersion)
930
+
931
+ // if viewer settings version is higher than backend settings version
932
+ // convert to backend settings version
933
+ if(+this._viewerSettingsVersion > +this._viewerSettingsVersionBackend)
934
+ json = convert(json, <versions>this._viewerSettingsVersionBackend)
892
935
  } catch (e) {
893
936
  throw new ShapeDiverViewerSettingsError('Session.saveSettings: Settings could not be validated. ' + (<Error>e).message, <Error>e);
894
937
  }
@@ -949,7 +992,7 @@ export class SessionEngine implements ISessionEngine {
949
992
  const responseO = Object.values(properties).length !== 0 ? await this.saveOutputProperties(properties) : true;
950
993
 
951
994
  // save partial settings
952
- const response = saveInSettings ? await this.saveSettings(this._settingsEngine.convertToTargetVersion()) : true;
995
+ const response = saveInSettings ? await this.saveSettings(this._settingsEngine.settings) : true;
953
996
 
954
997
  if (response && responseP && responseO && responseE) {
955
998
  this._logger.debug(`Session(${this.id}).saveSessionProperties: Saved session properties.`);
@@ -959,12 +1002,17 @@ export class SessionEngine implements ISessionEngine {
959
1002
  return response && responseP && responseO && responseE;
960
1003
  }
961
1004
 
962
- public async updateOutputs(): Promise<ITreeNode> {
963
- const eventId = this._uuidGenerator.create();
964
- const customizationId = this._uuidGenerator.create();
965
- const eventStart: ITaskEvent = { type: TASK_TYPE.SESSION_OUTPUTS_UPDATE, id: eventId, progress: 0, data: { sessionId: this.id }, status: 'Updating outputs' };
966
- this._eventEngine.emitEvent(EVENTTYPE.TASK.TASK_START, eventStart);
1005
+ public async updateOutputs(taskEventInfo?: OutputLoaderTaskEventInfo): Promise<ITreeNode> {
1006
+ const eventId = taskEventInfo ? taskEventInfo.eventId : this._uuidGenerator.create();
1007
+ const eventType = taskEventInfo ? taskEventInfo.type : TASK_TYPE.SESSION_OUTPUTS_UPDATE;
1008
+ const eventData = taskEventInfo ? taskEventInfo.data : { sessionId: this.id };
1009
+
1010
+ if(!taskEventInfo) {
1011
+ const eventStart: ITaskEvent = { type: eventType, id: eventId, progress: 0, data: eventData, status: 'Updating outputs' };
1012
+ this._eventEngine.emitEvent(EVENTTYPE.TASK.TASK_START, eventStart);
1013
+ }
967
1014
 
1015
+ const customizationId = this._uuidGenerator.create();
968
1016
  const oldNode = this.node.cloneInstance();
969
1017
  this.#customizationProcess = customizationId;
970
1018
 
@@ -973,12 +1021,20 @@ export class SessionEngine implements ISessionEngine {
973
1021
  for (let r in this._stateEngine.renderingEngines)
974
1022
  this._stateEngine.renderingEngines[r].busy.push(customizationId);
975
1023
 
976
- const eventRequest: ITaskEvent = { type: TASK_TYPE.SESSION_OUTPUTS_UPDATE, id: eventId, progress: 0.25, data: { sessionId: this.id }, status: 'Loading outputs' };
1024
+ const eventRequest: ITaskEvent = { type: eventType, id: eventId, progress: taskEventInfo ? (taskEventInfo.progressRange.max - taskEventInfo.progressRange.min) * 0.1 + taskEventInfo.progressRange.min : 0.1, data: eventData, status: 'Loading outputs' };
977
1025
  this._eventEngine.emitEvent(EVENTTYPE.TASK.TASK_PROCESS, eventRequest);
978
1026
 
979
- const newNode = await this.loadOutputs(() => this.#customizationProcess !== customizationId);
980
-
981
- const eventSceneUpdate: ITaskEvent = { type: TASK_TYPE.SESSION_OUTPUTS_UPDATE, id: eventId, progress: 0.75, data: { sessionId: this.id }, status: 'Updating scene' };
1027
+ const newNode = await this.loadOutputs(() => this.#customizationProcess !== customizationId, {
1028
+ eventId,
1029
+ type: eventType,
1030
+ progressRange: {
1031
+ min: taskEventInfo ? (taskEventInfo.progressRange.max - taskEventInfo.progressRange.min) * 0.1 + taskEventInfo.progressRange.min : 0.1,
1032
+ max: taskEventInfo ? (taskEventInfo.progressRange.max - taskEventInfo.progressRange.min) * 0.9 + taskEventInfo.progressRange.min : 0.9
1033
+ },
1034
+ data: eventData
1035
+ });
1036
+
1037
+ const eventSceneUpdate: ITaskEvent = { type: eventType, id: eventId, progress: taskEventInfo ? (taskEventInfo.progressRange.max - taskEventInfo.progressRange.min) * 0.9 + taskEventInfo.progressRange.min : 0.9, data: eventData, status: 'Updating scene' };
982
1038
  this._eventEngine.emitEvent(EVENTTYPE.TASK.TASK_PROCESS, eventSceneUpdate);
983
1039
 
984
1040
  // OPTION TO SKIP - PART 1
@@ -987,7 +1043,7 @@ export class SessionEngine implements ISessionEngine {
987
1043
  if (this._stateEngine.renderingEngines[r].busy.includes(customizationId))
988
1044
  this._stateEngine.renderingEngines[r].busy.splice(this._stateEngine.renderingEngines[r].busy.indexOf(customizationId), 1);
989
1045
 
990
- const eventCancel1: ITaskEvent = { type: TASK_TYPE.SESSION_OUTPUTS_UPDATE, id: eventId, progress: 1, data: { sessionId: this.id }, status: 'Output updating was exceeded by other customization request' };
1046
+ const eventCancel1: ITaskEvent = { type: eventType, id: eventId, progress: taskEventInfo ? (taskEventInfo.progressRange.max - taskEventInfo.progressRange.min) * 1 + taskEventInfo.progressRange.min : 1, data: eventData, status: 'Output updating was exceeded by other customization request' };
991
1047
  this._eventEngine.emitEvent(EVENTTYPE.TASK.TASK_CANCEL, eventCancel1);
992
1048
  this._logger.debug(`Session(${this.id}).updateOutputs: Output updating was exceeded by other request.`);
993
1049
  return newNode;
@@ -1021,9 +1077,11 @@ export class SessionEngine implements ISessionEngine {
1021
1077
  this._stateEngine.renderingEngines[r].busy.splice(this._stateEngine.renderingEngines[r].busy.indexOf(customizationId), 1);
1022
1078
 
1023
1079
  this._logger.debug(`Session(${this.id}).updateOutputs: Updated outputs.`);
1024
-
1025
- const eventEnd: ITaskEvent = { type: TASK_TYPE.SESSION_OUTPUTS_UPDATE, id: eventId, progress: 1, data: { sessionId: this.id }, status: 'Outputs updated' };
1026
- this._eventEngine.emitEvent(EVENTTYPE.TASK.TASK_END, eventEnd);
1080
+
1081
+ if(!taskEventInfo) {
1082
+ const eventEnd: ITaskEvent = { type: eventType, id: eventId, progress: 1, data: eventData, status: 'Outputs updated' };
1083
+ this._eventEngine.emitEvent(EVENTTYPE.TASK.TASK_END, eventEnd);
1084
+ }
1027
1085
 
1028
1086
  return this.node;
1029
1087
  }
@@ -1153,11 +1211,11 @@ export class SessionEngine implements ISessionEngine {
1153
1211
  throw new ShapeDiverViewerSessionError(`Session.checkAvailability: action ${action} not available.`);
1154
1212
  }
1155
1213
 
1156
- private async customizeInternal(cancelRequest: () => boolean): Promise<ISessionTreeNode> {
1157
- return this.customizeSession(this._parameterValues, cancelRequest);
1214
+ private async customizeInternal(cancelRequest: () => boolean, taskEventInfo: OutputLoaderTaskEventInfo): Promise<ISessionTreeNode> {
1215
+ return this.customizeSession(this._parameterValues, cancelRequest, taskEventInfo);
1158
1216
  }
1159
1217
 
1160
- private async customizeSession(parameters: { [key: string]: string }, cancelRequest: () => boolean, parallel = false, retry = false): Promise<ISessionTreeNode> {
1218
+ private async customizeSession(parameters: { [key: string]: string }, cancelRequest: () => boolean, taskEventInfo: OutputLoaderTaskEventInfo, parallel = false, retry = false): Promise<ISessionTreeNode> {
1161
1219
  this.checkAvailability('customize');
1162
1220
  try {
1163
1221
  this._performanceEvaluator.startSection('sessionResponse');
@@ -1165,11 +1223,11 @@ export class SessionEngine implements ISessionEngine {
1165
1223
  this._performanceEvaluator.endSection('sessionResponse');
1166
1224
  if (cancelRequest()) return new SessionTreeNode();
1167
1225
  if (parallel === false) this.updateResponseDto(responseDto);
1168
- return parallel === false ? this.loadOutputs(cancelRequest) : this.loadOutputsParallel(responseDto, cancelRequest);
1226
+ return parallel === false ? this.loadOutputs(cancelRequest, taskEventInfo) : this.loadOutputsParallel(responseDto, cancelRequest, taskEventInfo);
1169
1227
  } catch (e) {
1170
1228
  await this.handleError(e, retry);
1171
1229
  if (cancelRequest()) return new SessionTreeNode();
1172
- return await this.customizeSession(parameters, cancelRequest, parallel, true);
1230
+ return await this.customizeSession(parameters, cancelRequest, taskEventInfo, parallel, true);
1173
1231
  }
1174
1232
  }
1175
1233
 
@@ -1180,6 +1238,7 @@ export class SessionEngine implements ISessionEngine {
1180
1238
  // we try to re-initialize the session 3 times, if that does not work, we close it
1181
1239
 
1182
1240
  this._logger.warn(`The session has been closed, trying to re-initialize.`);
1241
+ if(this._sessionId) this._httpClient.removeDataLoading(this._sessionId)
1183
1242
 
1184
1243
  if (this._retryCounter < 3) {
1185
1244
  // we retry this 3 times, the `retry` option in the init function is set to true and passed on
@@ -1190,7 +1249,7 @@ export class SessionEngine implements ISessionEngine {
1190
1249
  // the retries were exceeded, we close the session
1191
1250
  this._logger.warn('Tried to retry the connect multiple times, bearer token still not valid. Closing Session.');
1192
1251
  try { await this._closeOnFailure(); } catch (e) { }
1193
- throw e;
1252
+ throw this._httpClient.convertError(e);
1194
1253
  }
1195
1254
  } else if (e.error === ShapeDiverResponseErrorType.JWT_VALIDATION_ERROR) {
1196
1255
  // if any of the above errors occur, we try to get a new bearer token
@@ -1204,19 +1263,19 @@ export class SessionEngine implements ISessionEngine {
1204
1263
  // no bearer tokens are supplied, we close the session
1205
1264
  this._logger.warn('No retry possible, no new bearer token was supplied. Closing Session.');
1206
1265
  try { await this._closeOnFailure(); } catch (e) { }
1207
- throw e;
1266
+ throw this._httpClient.convertError(e);
1208
1267
  }
1209
1268
  } else {
1210
1269
  // the retries were exceeded, we close the session
1211
1270
  this._logger.warn('Tried to retry the connect multiple times, bearer token still not valid. Closing Session.');
1212
1271
  try { await this._closeOnFailure(); } catch (e) { }
1213
- throw e;
1272
+ throw this._httpClient.convertError(e);
1214
1273
  }
1215
1274
  } else {
1216
- throw e;
1275
+ throw this._httpClient.convertError(e);
1217
1276
  }
1218
1277
  } else {
1219
- throw e;
1278
+ throw this._httpClient.convertError(e);
1220
1279
  }
1221
1280
  }
1222
1281
 
@@ -1293,8 +1352,22 @@ export class SessionEngine implements ISessionEngine {
1293
1352
  break;
1294
1353
  }
1295
1354
 
1296
- if(initialParameters && initialParameters[parameterId] !== undefined)
1297
- this.parameters[parameterId].value = initialParameters[parameterId]
1355
+ // we don't have to do larger restrictions for this as the backend would have already thrown an error if the values were not correct
1356
+ if(initialParameters) {
1357
+ // check if the id is within the initial parameters
1358
+ if(initialParameters[parameterId] !== undefined) {
1359
+ this.parameters[parameterId].value = initialParameters[parameterId]
1360
+ }
1361
+ // check if the name is within the initial parameters
1362
+ else if(initialParameters[this.parameters[parameterId].name] !== undefined) {
1363
+ this.parameters[parameterId].value = initialParameters[this.parameters[parameterId].name];
1364
+ }
1365
+ // NOTE: At some point the checking may also be done with the displayname, this is the code for it
1366
+ // // check if the displayname is within the initial parameters
1367
+ // else if(this.parameters[parameterId].displayname && initialParameters[this.parameters[parameterId].displayname!] !== undefined) {
1368
+ // this.parameters[parameterId].value = initialParameters[this.parameters[parameterId].displayname!];
1369
+ // }
1370
+ }
1298
1371
 
1299
1372
  parameterSet[parameterId] = {
1300
1373
  value: this.parameters[parameterId].value,
@@ -1,5 +1,5 @@
1
1
  import { ShapeDiverResponseExport, ShapeDiverResponseExportContent, ShapeDiverResponseExportDefinitionType, ShapeDiverResponseExportResult, ShapeDiverResponseModelComputationStatus, ShapeDiverResponseParameterGroup } from "@shapediver/sdk.geometry-api-sdk-v2";
2
- import { EventEngine, EVENTTYPE, InputValidator, Logger, ShapeDiverBackendError, ShapeDiverViewerError, UuidGenerator } from "@shapediver/viewer.shared.services";
2
+ import { EventEngine, EVENTTYPE, InputValidator, Logger, UuidGenerator } from "@shapediver/viewer.shared.services";
3
3
  import { ITaskEvent, TASK_TYPE } from "@shapediver/viewer.shared.types";
4
4
  import { IExport } from "../../interfaces/dto/IExport";
5
5
  import { SessionEngine } from "../SessionEngine";
@@ -1,6 +1,6 @@
1
1
  import { ShapeDiverResponseModelComputationStatus, ShapeDiverResponseOutput } from "@shapediver/sdk.geometry-api-sdk-v2";
2
2
  import { ITreeNode, TreeNode } from "@shapediver/viewer.shared.node-tree";
3
- import { InputValidator, UuidGenerator, ShapeDiverViewerError, ShapeDiverBackendError, Logger } from "@shapediver/viewer.shared.services";
3
+ import { InputValidator, UuidGenerator, Logger } from "@shapediver/viewer.shared.services";
4
4
  import { IOutput, ShapeDiverResponseOutputContent, ShapeDiverResponseOutputChunk } from "../../interfaces/dto/IOutput";
5
5
  import { SessionEngine } from "../SessionEngine";
6
6
 
@@ -1,6 +1,7 @@
1
1
  import { ShapeDiverRequestGltfUploadQueryConversion, ShapeDiverResponseDto, ShapeDiverResponseExport, ShapeDiverResponseOutput, ShapeDiverResponseParameter } from '@shapediver/sdk.geometry-api-sdk-v2';
2
2
  import { ITreeNode, TreeNode } from '@shapediver/viewer.shared.node-tree'
3
3
  import { SettingsEngine } from '@shapediver/viewer.shared.services';
4
+ import { OutputLoaderTaskEventInfo } from '../implementation/OutputLoader';
4
5
  import { IExport } from './dto/IExport';
5
6
  import { IOutput } from './dto/IOutput';
6
7
  import { IParameter } from './dto/IParameter';
@@ -126,14 +127,14 @@ export interface ISessionEngine {
126
127
  goBack(): Promise<ITreeNode>;
127
128
  goForward(): Promise<ITreeNode>;
128
129
  init(parameterValues?: { [key: string]: string; }): Promise<void>;
129
- loadOutputs(cancelRequest: () => boolean): Promise<ITreeNode>;
130
- loadOutputsParallel(responseDto: ShapeDiverResponseDto, cancelRequest: () => boolean): Promise<ITreeNode>;
130
+ loadOutputs(cancelRequest: () => boolean, taskEventInfo: OutputLoaderTaskEventInfo): Promise<ITreeNode>;
131
+ loadOutputsParallel(responseDto: ShapeDiverResponseDto, cancelRequest: () => boolean, taskEventInfo: OutputLoaderTaskEventInfo): Promise<ITreeNode>;
131
132
  requestExport(exportId: string, parameters: { [key: string]: string }, maxWaitTime: number): Promise<ShapeDiverResponseExport>;
132
133
  resetSettings(sections?: ISettingsSections): void;
133
134
  saveDefaultParameterValues(): Promise<boolean>;
134
135
  saveSettings(viewportId?: string): Promise<boolean>;
135
136
  saveUiProperties(): Promise<boolean>;
136
- updateOutputs(): Promise<ITreeNode>;
137
+ updateOutputs(taskEventInfo?: OutputLoaderTaskEventInfo): Promise<ITreeNode>;
137
138
  uploadFile(parameterId: string, data: File, type: string): Promise<string>;
138
139
  uploadGLTF(blob: Blob, conversion?: ShapeDiverRequestGltfUploadQueryConversion): Promise<ShapeDiverResponseDto>;
139
140