@shapediver/viewer.shared.services 1.15.5 → 2.0.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.
- package/dist/converter/Converter.d.ts.map +1 -1
- package/dist/converter/Converter.js +2 -2
- package/dist/converter/Converter.js.map +1 -1
- package/dist/dom-event-engine/DomEventEngine.d.ts +1 -2
- package/dist/dom-event-engine/DomEventEngine.d.ts.map +1 -1
- package/dist/dom-event-engine/DomEventEngine.js +1 -2
- package/dist/dom-event-engine/DomEventEngine.js.map +1 -1
- package/dist/event-engine/EventEngine.d.ts +3 -3
- package/dist/event-engine/EventEngine.d.ts.map +1 -1
- package/dist/event-engine/EventEngine.js +2 -2
- package/dist/event-engine/EventEngine.js.map +1 -1
- package/dist/event-engine/EventTypes.d.ts +20 -24
- package/dist/event-engine/EventTypes.d.ts.map +1 -1
- package/dist/event-engine/EventTypes.js +55 -85
- package/dist/event-engine/EventTypes.js.map +1 -1
- package/dist/http-client/HttpClient.d.ts +11 -8
- package/dist/http-client/HttpClient.d.ts.map +1 -1
- package/dist/http-client/HttpClient.js +102 -27
- package/dist/http-client/HttpClient.js.map +1 -1
- package/dist/index.d.ts +4 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +10 -3
- package/dist/index.js.map +1 -1
- package/dist/input-validator/InputValidator.d.ts +3 -3
- package/dist/input-validator/InputValidator.d.ts.map +1 -1
- package/dist/input-validator/InputValidator.js +6 -2
- package/dist/input-validator/InputValidator.js.map +1 -1
- package/dist/logger/Logger.d.ts +16 -16
- package/dist/logger/Logger.d.ts.map +1 -1
- package/dist/logger/Logger.js +77 -76
- package/dist/logger/Logger.js.map +1 -1
- package/dist/logger/ShapeDiverError.d.ts +1 -1
- package/dist/logger/ShapeDiverError.d.ts.map +1 -1
- package/dist/logger/ShapeDiverError.js +1 -1
- package/dist/logger/ShapeDiverError.js.map +1 -1
- package/dist/logger/ShapeDiverViewerErrors.d.ts +24 -24
- package/dist/logger/ShapeDiverViewerErrors.d.ts.map +1 -1
- package/dist/logger/ShapeDiverViewerErrors.js +1 -1
- package/dist/logger/ShapeDiverViewerErrors.js.map +1 -1
- package/dist/performance-evaluator/PerformanceEvaluator.js +1 -1
- package/dist/performance-evaluator/PerformanceEvaluator.js.map +1 -1
- package/dist/settings-engine/SettingsEngine.d.ts +1 -1
- package/dist/settings-engine/SettingsEngine.d.ts.map +1 -1
- package/dist/settings-engine/SettingsEngine.js +16 -25
- package/dist/settings-engine/SettingsEngine.js.map +1 -1
- package/dist/state-engine/StateEngine.d.ts +7 -16
- package/dist/state-engine/StateEngine.d.ts.map +1 -1
- package/dist/state-engine/StateEngine.js +8 -21
- package/dist/state-engine/StateEngine.js.map +1 -1
- package/dist/system-info/SystemInfo.js +1 -1
- package/dist/system-info/SystemInfo.js.map +1 -1
- package/dist/type-check/TypeChecker.js +1 -1
- package/dist/type-check/TypeChecker.js.map +1 -1
- package/dist/uuid-generator/UuidGenerator.js +5 -5
- package/dist/uuid-generator/UuidGenerator.js.map +1 -1
- package/package.json +12 -9
- package/src/converter/Converter.ts +299 -0
- package/src/dom-event-engine/DomEventEngine.ts +334 -0
- package/src/dom-event-engine/IDomEventListener.ts +14 -0
- package/src/event-engine/EventEngine.ts +116 -0
- package/src/event-engine/EventTypes.ts +66 -0
- package/src/event-engine/interfaces/ICallback.ts +5 -0
- package/src/event-engine/interfaces/IEvent.ts +1 -0
- package/src/event-engine/interfaces/IListener.ts +8 -0
- package/src/http-client/HttpClient.ts +177 -0
- package/src/http-client/HttpResponse.ts +4 -0
- package/src/index.ts +82 -0
- package/src/input-validator/InputValidator.ts +100 -0
- package/src/logger/Logger.ts +297 -0
- package/src/logger/ShapeDiverError.ts +48 -0
- package/src/logger/ShapeDiverViewerErrors.ts +115 -0
- package/src/performance-evaluator/PerformanceEvaluator.ts +102 -0
- package/src/settings-engine/SettingsEngine.ts +176 -0
- package/src/state-engine/StateEngine.ts +73 -0
- package/src/state-engine/StatePromise.ts +54 -0
- package/src/system-info/SystemInfo.ts +117 -0
- package/src/type-check/TypeChecker.ts +13 -0
- package/src/uuid-generator/UuidGenerator.ts +41 -0
- package/tsconfig.json +17 -0
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
import { container, singleton } from 'tsyringe'
|
|
2
|
+
|
|
3
|
+
import { EVENTTYPE, MainEventTypes } from './EventTypes'
|
|
4
|
+
import { IListener } from './interfaces/IListener'
|
|
5
|
+
import { ICallback } from './interfaces/ICallback'
|
|
6
|
+
import { IEvent } from './interfaces/IEvent'
|
|
7
|
+
import { UuidGenerator } from '../uuid-generator/UuidGenerator'
|
|
8
|
+
import { Logger, LOGGING_TOPIC } from '../logger/Logger'
|
|
9
|
+
|
|
10
|
+
@singleton()
|
|
11
|
+
export class EventEngine {
|
|
12
|
+
// #region Properties (2)
|
|
13
|
+
|
|
14
|
+
protected readonly _uuidGenerator: UuidGenerator = <UuidGenerator>container.resolve(UuidGenerator);
|
|
15
|
+
protected readonly _logger: Logger = <Logger>container.resolve(Logger);
|
|
16
|
+
private _eventListeners: {
|
|
17
|
+
[key: string]: IListener[]
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
// #endregion Properties (2)
|
|
21
|
+
|
|
22
|
+
// #region Constructors (1)
|
|
23
|
+
|
|
24
|
+
constructor() {
|
|
25
|
+
this._eventListeners = {};
|
|
26
|
+
for (const type in EVENTTYPE) {
|
|
27
|
+
const subEventType = EVENTTYPE[type as keyof typeof EVENTTYPE];
|
|
28
|
+
this._eventListeners[type.toLowerCase()] = [];
|
|
29
|
+
for (const subtype in subEventType) {
|
|
30
|
+
this._eventListeners[subEventType[subtype as keyof typeof subEventType]] = [];
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// #endregion Constructors (1)
|
|
36
|
+
|
|
37
|
+
private convertTypeToString(type: string | MainEventTypes): string {
|
|
38
|
+
let typeString: string = '';
|
|
39
|
+
if(typeof type === 'string') typeString = type;
|
|
40
|
+
|
|
41
|
+
for (const mainType in EVENTTYPE)
|
|
42
|
+
if(type === EVENTTYPE[mainType as keyof typeof EVENTTYPE])
|
|
43
|
+
typeString = mainType.toLowerCase();
|
|
44
|
+
|
|
45
|
+
if(!typeString || !this._eventListeners[typeString]) {
|
|
46
|
+
this._logger.warn(LOGGING_TOPIC.GENERAL, 'EventEngine.convertTypeToString: No valid type provided.');
|
|
47
|
+
return '';
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
return typeString;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
// #region Public Methods (3)
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Adds a listener that listenes to the provided type. If no valid type is specified, an error is thrown.
|
|
57
|
+
*
|
|
58
|
+
* @param type the type of the event
|
|
59
|
+
* @param cb the callback that should be called
|
|
60
|
+
* @returns an unique token to be able to remove the listener
|
|
61
|
+
*/
|
|
62
|
+
public addListener(type: string | MainEventTypes, cb: ICallback): string {
|
|
63
|
+
const typeString: string = this.convertTypeToString(type);
|
|
64
|
+
if(!typeString) return '';
|
|
65
|
+
const token = this._uuidGenerator.create();
|
|
66
|
+
this._eventListeners[typeString]?.push({ token, cb });
|
|
67
|
+
return token;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Emits the event to all callbacks that listen to the type.
|
|
72
|
+
*
|
|
73
|
+
* @param type the type of the event
|
|
74
|
+
* @param event the event to emit
|
|
75
|
+
*/
|
|
76
|
+
public emitEvent(type: string | MainEventTypes, event: IEvent): void {
|
|
77
|
+
const typeString: string = this.convertTypeToString(type);
|
|
78
|
+
|
|
79
|
+
if (this._eventListeners[typeString] && this._eventListeners[typeString].length !== 0)
|
|
80
|
+
for (let i = 0; i < this._eventListeners[typeString]!.length; i++)
|
|
81
|
+
this._eventListeners[typeString]![i].cb(event);
|
|
82
|
+
|
|
83
|
+
if(typeString.includes('.'))
|
|
84
|
+
this.emitEvent(typeString.substr(0, typeString.indexOf('.')), event);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Removes a listener with the specified token.
|
|
89
|
+
*
|
|
90
|
+
* @param token the token of the listener
|
|
91
|
+
* @returns result of the targeted operation
|
|
92
|
+
*/
|
|
93
|
+
public removeListener(token: string): boolean {
|
|
94
|
+
for (const type in EVENTTYPE) {
|
|
95
|
+
const subEventType = EVENTTYPE[type as keyof typeof EVENTTYPE];
|
|
96
|
+
const typeLowerCase = type.toLowerCase();
|
|
97
|
+
for (let i = 0; i < this._eventListeners[typeLowerCase]!.length; i++) {
|
|
98
|
+
if (this._eventListeners[typeLowerCase]![i].token === token) {
|
|
99
|
+
this._eventListeners[typeLowerCase]!.splice(i, 1);
|
|
100
|
+
return true;
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
for (const subtype in subEventType) {
|
|
104
|
+
for (let i = 0; i < this._eventListeners[subEventType[subtype as keyof typeof subEventType]]!.length; i++) {
|
|
105
|
+
if (this._eventListeners[subEventType[subtype as keyof typeof subEventType]]![i].token === token) {
|
|
106
|
+
this._eventListeners[subEventType[subtype as keyof typeof subEventType]]!.splice(i, 1);
|
|
107
|
+
return true;
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
return false;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
// #endregion Public Methods (3)
|
|
116
|
+
}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
export enum EVENTTYPE_CAMERA {
|
|
2
|
+
CAMERA_START = "camera.start",
|
|
3
|
+
CAMERA_MOVE = "camera.move",
|
|
4
|
+
CAMERA_END = "camera.end",
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
export enum EVENTTYPE_RENDERING {
|
|
8
|
+
BEAUTY_RENDERING_FINISHED = "rendering.beautyRenderingFinished"
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export enum EVENTTYPE_SCENE {
|
|
12
|
+
SCENE_BOUNDING_BOX_CHANGE = "scene.boundingBoxChange"
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
// VIEWPORT
|
|
16
|
+
// FRAMERATE
|
|
17
|
+
// RENDER_INFO
|
|
18
|
+
// RENDER_BEAUTY_START
|
|
19
|
+
// RENDER_BEAUTY_CANCEL
|
|
20
|
+
// RENDER_BEAUTY_END
|
|
21
|
+
// VISIBILITY_ON
|
|
22
|
+
// VISIBILITY_OFF
|
|
23
|
+
|
|
24
|
+
export enum EVENTTYPE_VIEWPORT {
|
|
25
|
+
BUSY_MODE_ON = "viewport.busy.on",
|
|
26
|
+
BUSY_MODE_OFF = "viewport.busy.off",
|
|
27
|
+
VIEWPORT_CREATED = "viewport.created",
|
|
28
|
+
VIEWPORT_UPDATED = "viewport.updated",
|
|
29
|
+
VIEWPORT_CLOSED = "viewport.closed"
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export enum EVENTTYPE_SESSION {
|
|
33
|
+
SESSION_CREATED = "session.created",
|
|
34
|
+
SESSION_CUSTOMIZED = "session.customized",
|
|
35
|
+
SESSION_CLOSED = "session.closed",
|
|
36
|
+
SESSION_INITIAL_OUTPUTS_LOADED = 'session.initialOutputsLoaded'
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export enum EVENTTYPE_TASK {
|
|
40
|
+
TASK_START = "task.start",
|
|
41
|
+
TASK_PROCESS = "task.process",
|
|
42
|
+
TASK_END = "task.end",
|
|
43
|
+
TASK_CANCEL = "task.cancel",
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export enum EVENTTYPE_INTERACTION {
|
|
47
|
+
DRAG_START = "interaction.drag.start",
|
|
48
|
+
DRAG_MOVE = "interaction.drag.move",
|
|
49
|
+
DRAG_END = "interaction.drag.end",
|
|
50
|
+
HOVER_ON = "interaction.hover.on",
|
|
51
|
+
HOVER_OFF = "interaction.hover.off",
|
|
52
|
+
SELECT_ON = "interaction.select.on",
|
|
53
|
+
SELECT_OFF = "interaction.select.off",
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
export const EVENTTYPE = {
|
|
57
|
+
CAMERA: EVENTTYPE_CAMERA,
|
|
58
|
+
RENDERING: EVENTTYPE_RENDERING,
|
|
59
|
+
SCENE: EVENTTYPE_SCENE,
|
|
60
|
+
SESSION: EVENTTYPE_SESSION,
|
|
61
|
+
VIEWPORT: EVENTTYPE_VIEWPORT,
|
|
62
|
+
INTERACTION: EVENTTYPE_INTERACTION,
|
|
63
|
+
TASK: EVENTTYPE_TASK
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
export type MainEventTypes = typeof EVENTTYPE_CAMERA | typeof EVENTTYPE_RENDERING | typeof EVENTTYPE_SCENE | typeof EVENTTYPE_SESSION | typeof EVENTTYPE_VIEWPORT | typeof EVENTTYPE_INTERACTION | typeof EVENTTYPE_TASK;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export interface IEvent {};
|
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
import axios, { AxiosRequestConfig } from 'axios'
|
|
2
|
+
import { singleton } from 'tsyringe'
|
|
3
|
+
import { ShapeDiverViewerConnectionError } from '../logger/ShapeDiverViewerErrors';
|
|
4
|
+
import { HttpResponse } from './HttpResponse';
|
|
5
|
+
|
|
6
|
+
@singleton()
|
|
7
|
+
export class HttpClient {
|
|
8
|
+
// #region Properties (2)
|
|
9
|
+
|
|
10
|
+
private _dataCache: {
|
|
11
|
+
[key: string]: Promise<HttpResponse<any>>
|
|
12
|
+
} = {};
|
|
13
|
+
|
|
14
|
+
private _sessionLoading: {
|
|
15
|
+
[key: string]: {
|
|
16
|
+
getOutput: (sessionId: string, assetData: string) => Promise<[ArrayBuffer, string]>,
|
|
17
|
+
getTexture: (sessionId: string, assetData: string) => Promise<[ArrayBuffer, string]>,
|
|
18
|
+
getExport: (sessionId: string, assetData: string) => Promise<[ArrayBuffer, string]>,
|
|
19
|
+
downloadTexture: (sessionId: string, url: string) => Promise<[ArrayBuffer, string]>,
|
|
20
|
+
}
|
|
21
|
+
} = {};
|
|
22
|
+
|
|
23
|
+
// #endregion Properties (2)
|
|
24
|
+
|
|
25
|
+
// #region Constructors (1)
|
|
26
|
+
|
|
27
|
+
constructor() {
|
|
28
|
+
axios.interceptors.response.use(
|
|
29
|
+
response => {
|
|
30
|
+
return response;
|
|
31
|
+
},
|
|
32
|
+
error => {
|
|
33
|
+
throw new ShapeDiverViewerConnectionError(error.message, error.response.status, error);
|
|
34
|
+
});
|
|
35
|
+
axios.interceptors.request.use(
|
|
36
|
+
response => {
|
|
37
|
+
return response;
|
|
38
|
+
},
|
|
39
|
+
error => {
|
|
40
|
+
throw new ShapeDiverViewerConnectionError(error.message, undefined, error);
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
// #endregion Constructors (1)
|
|
45
|
+
|
|
46
|
+
// #region Public Methods (7)
|
|
47
|
+
|
|
48
|
+
private loadingCriterion(href: string): { sessionId: string, assetData: string, type: 'output' | 'export' | 'texture' } | undefined {
|
|
49
|
+
// searching for "/session/SESSION_ID/{'output' | 'export' | 'texture'}/ASSET_DATA"
|
|
50
|
+
const parts = href.split('/');
|
|
51
|
+
const sessionPartIndex = parts.indexOf('session');
|
|
52
|
+
|
|
53
|
+
// There have to be at exactly 4 parts, including the session
|
|
54
|
+
if (sessionPartIndex !== -1 && parts.length === sessionPartIndex + 4) {
|
|
55
|
+
const sessionId = parts[sessionPartIndex + 1];
|
|
56
|
+
// no such session has been registered, should never happen
|
|
57
|
+
if (!this._sessionLoading[sessionId]) return;
|
|
58
|
+
|
|
59
|
+
const type = parts[sessionPartIndex + 2];
|
|
60
|
+
// the type is not supported
|
|
61
|
+
if (type !== 'output' && type !== 'export' && type !== 'texture') return;
|
|
62
|
+
|
|
63
|
+
const assetData = parts[sessionPartIndex + 3];
|
|
64
|
+
|
|
65
|
+
return { sessionId, assetData, type };
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
public addDataLoading(sessionId: string, callbacks: {
|
|
72
|
+
getOutput: (sessionId: string, assetData: string) => Promise<[ArrayBuffer, string]>,
|
|
73
|
+
getTexture: (sessionId: string, assetData: string) => Promise<[ArrayBuffer, string]>,
|
|
74
|
+
getExport: (sessionId: string, assetData: string) => Promise<[ArrayBuffer, string]>,
|
|
75
|
+
downloadTexture: (sessionId: string, url: string) => Promise<[ArrayBuffer, string]>,
|
|
76
|
+
}) {
|
|
77
|
+
this._sessionLoading[sessionId] = callbacks;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
public async get(href: string, config: AxiosRequestConfig = { responseType: 'arraybuffer' }, textureLoading: boolean = false): Promise<HttpResponse<any>> {
|
|
81
|
+
const dataKey = btoa(href);
|
|
82
|
+
if (dataKey in this._dataCache) return await this._dataCache[dataKey];
|
|
83
|
+
|
|
84
|
+
const loadingInfo = this.loadingCriterion(href);
|
|
85
|
+
if (loadingInfo) {
|
|
86
|
+
switch (loadingInfo.type) {
|
|
87
|
+
case 'output':
|
|
88
|
+
this._dataCache[dataKey] = new Promise<HttpResponse<ArrayBuffer>>(resolve => {
|
|
89
|
+
this._sessionLoading[loadingInfo.sessionId]
|
|
90
|
+
.getOutput(loadingInfo.sessionId, loadingInfo.assetData)
|
|
91
|
+
.then(result => {
|
|
92
|
+
resolve({
|
|
93
|
+
data: result[0],
|
|
94
|
+
headers: {
|
|
95
|
+
'content-type': result[1]
|
|
96
|
+
}
|
|
97
|
+
})
|
|
98
|
+
})
|
|
99
|
+
|
|
100
|
+
});
|
|
101
|
+
break;
|
|
102
|
+
|
|
103
|
+
case 'export':
|
|
104
|
+
this._dataCache[dataKey] = new Promise<HttpResponse<ArrayBuffer>>(resolve => {
|
|
105
|
+
this._sessionLoading[loadingInfo.sessionId]
|
|
106
|
+
.getExport(loadingInfo.sessionId, loadingInfo.assetData)
|
|
107
|
+
.then(result => {
|
|
108
|
+
resolve({
|
|
109
|
+
data: result[0],
|
|
110
|
+
headers: {
|
|
111
|
+
'content-type': result[1]
|
|
112
|
+
}
|
|
113
|
+
})
|
|
114
|
+
})
|
|
115
|
+
|
|
116
|
+
});
|
|
117
|
+
break;
|
|
118
|
+
|
|
119
|
+
case 'texture':
|
|
120
|
+
this._dataCache[dataKey] = new Promise<HttpResponse<ArrayBuffer>>(resolve => {
|
|
121
|
+
this._sessionLoading[loadingInfo.sessionId]
|
|
122
|
+
.getTexture(loadingInfo.sessionId, loadingInfo.assetData)
|
|
123
|
+
.then(result => {
|
|
124
|
+
resolve({
|
|
125
|
+
data: result[0],
|
|
126
|
+
headers: {
|
|
127
|
+
'content-type': result[1]
|
|
128
|
+
}
|
|
129
|
+
})
|
|
130
|
+
})
|
|
131
|
+
|
|
132
|
+
});
|
|
133
|
+
break;
|
|
134
|
+
|
|
135
|
+
default:
|
|
136
|
+
this._dataCache[dataKey] = axios(href, Object.assign({ method: 'get' }, config));
|
|
137
|
+
}
|
|
138
|
+
} else {
|
|
139
|
+
// separation texture vs something else...
|
|
140
|
+
if(textureLoading) {
|
|
141
|
+
// we can load blobs and data urls directly
|
|
142
|
+
// if no session is registered, we have to load the texture directly
|
|
143
|
+
if(href.startsWith('blob:') || href.startsWith('data:') || Object.values(this._sessionLoading).length === 0) {
|
|
144
|
+
this._dataCache[dataKey] = axios(href, Object.assign({ method: 'get' }, config));
|
|
145
|
+
} else {
|
|
146
|
+
// take first session to load a texture that is not session related
|
|
147
|
+
const sessionId = Object.keys(this._sessionLoading)[0];
|
|
148
|
+
|
|
149
|
+
this._dataCache[dataKey] = new Promise<HttpResponse<any>>(resolve => {
|
|
150
|
+
this._sessionLoading[sessionId].downloadTexture(sessionId, href).then((result) => {
|
|
151
|
+
resolve({
|
|
152
|
+
data: result[0],
|
|
153
|
+
headers: {
|
|
154
|
+
'content-type': result[1]
|
|
155
|
+
}
|
|
156
|
+
})
|
|
157
|
+
});
|
|
158
|
+
});
|
|
159
|
+
}
|
|
160
|
+
} else {
|
|
161
|
+
this._dataCache[dataKey] = axios(href, Object.assign({ method: 'get' }, config));
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
return this._dataCache[dataKey];
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
public async loadTexture(href: string): Promise<HttpResponse<ArrayBuffer>> {
|
|
169
|
+
return this.get(href, undefined, true);
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
public removeDataLoading(sessionId: string) {
|
|
173
|
+
delete this._sessionLoading[sessionId];
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
// #endregion Public Methods (7)
|
|
177
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import { EventEngine } from './event-engine/EventEngine'
|
|
2
|
+
import { EVENTTYPE, EVENTTYPE_CAMERA, EVENTTYPE_INTERACTION, EVENTTYPE_RENDERING, EVENTTYPE_SCENE, EVENTTYPE_SESSION, EVENTTYPE_TASK, EVENTTYPE_VIEWPORT, MainEventTypes } from './event-engine/EventTypes'
|
|
3
|
+
import { SettingsEngine } from './settings-engine/SettingsEngine'
|
|
4
|
+
import { StateEngine } from './state-engine/StateEngine'
|
|
5
|
+
import { SystemInfo } from './system-info/SystemInfo'
|
|
6
|
+
import { DomEventEngine } from './dom-event-engine/DomEventEngine'
|
|
7
|
+
import { IDomEventListener } from './dom-event-engine/IDomEventListener'
|
|
8
|
+
import { IEvent } from './event-engine/interfaces/IEvent'
|
|
9
|
+
import { Converter } from './converter/Converter'
|
|
10
|
+
import { HttpClient } from './http-client/HttpClient'
|
|
11
|
+
import { InputValidator } from './input-validator/InputValidator'
|
|
12
|
+
import { TypeChecker } from './type-check/TypeChecker'
|
|
13
|
+
import { UuidGenerator } from './uuid-generator/UuidGenerator'
|
|
14
|
+
import { PerformanceEvaluator } from './performance-evaluator/PerformanceEvaluator'
|
|
15
|
+
import { Logger, LOGGING_LEVEL, LOGGING_TOPIC } from './logger/Logger'
|
|
16
|
+
import { StatePromise } from './state-engine/StatePromise'
|
|
17
|
+
import { ShapeDiverViewerArError, ShapeDiverViewerCameraError, ShapeDiverViewerDataProcessingError, ShapeDiverViewerEnvironmentMapError, ShapeDiverViewerLightError, ShapeDiverViewerSessionError, ShapeDiverViewerSettingsError, ShapeDiverViewerUnknownError, ShapeDiverViewerValidationError, ShapeDiverViewerGeneralError, ShapeDiverViewerWebGLError } from './logger/ShapeDiverViewerErrors'
|
|
18
|
+
import { ShapeDiverError as ShapeDiverBackendError } from '@shapediver/sdk.geometry-api-sdk-v2'
|
|
19
|
+
import { ShapeDiverViewerError } from './logger/ShapeDiverError'
|
|
20
|
+
import { HttpResponse } from './http-client/HttpResponse'
|
|
21
|
+
|
|
22
|
+
export {
|
|
23
|
+
EventEngine, EVENTTYPE, MainEventTypes, IEvent,
|
|
24
|
+
EVENTTYPE_CAMERA, EVENTTYPE_RENDERING, EVENTTYPE_SCENE, EVENTTYPE_SESSION, EVENTTYPE_VIEWPORT, EVENTTYPE_INTERACTION, EVENTTYPE_TASK
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export {
|
|
28
|
+
SettingsEngine
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export {
|
|
32
|
+
StateEngine, StatePromise
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export {
|
|
36
|
+
SystemInfo
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export {
|
|
40
|
+
IDomEventListener, DomEventEngine
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export {
|
|
44
|
+
HttpClient, HttpResponse
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export {
|
|
48
|
+
UuidGenerator
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export {
|
|
52
|
+
Converter
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
export {
|
|
56
|
+
TypeChecker
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
export {
|
|
60
|
+
InputValidator
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
export {
|
|
64
|
+
Logger, LOGGING_LEVEL, LOGGING_TOPIC,
|
|
65
|
+
ShapeDiverViewerError,
|
|
66
|
+
ShapeDiverViewerDataProcessingError,
|
|
67
|
+
ShapeDiverViewerEnvironmentMapError,
|
|
68
|
+
ShapeDiverViewerWebGLError,
|
|
69
|
+
ShapeDiverViewerSettingsError,
|
|
70
|
+
ShapeDiverViewerSessionError,
|
|
71
|
+
ShapeDiverViewerGeneralError,
|
|
72
|
+
ShapeDiverViewerUnknownError,
|
|
73
|
+
ShapeDiverViewerArError,
|
|
74
|
+
ShapeDiverViewerLightError,
|
|
75
|
+
ShapeDiverViewerCameraError,
|
|
76
|
+
ShapeDiverViewerValidationError,
|
|
77
|
+
ShapeDiverBackendError
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
export {
|
|
81
|
+
PerformanceEvaluator
|
|
82
|
+
}
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import { container, singleton } from 'tsyringe'
|
|
2
|
+
import DOMPurify from 'dompurify';
|
|
3
|
+
import { Logger, LOGGING_TOPIC } from '../logger/Logger'
|
|
4
|
+
import { ShapeDiverViewerValidationError } from '../logger/ShapeDiverViewerErrors';
|
|
5
|
+
import { TypeChecker } from '../type-check/TypeChecker'
|
|
6
|
+
|
|
7
|
+
export type Types = 'string' | 'boolean' | 'function' |
|
|
8
|
+
'HTMLCanvasElement' | 'enum' |
|
|
9
|
+
'number' | 'factor' | 'positive' |
|
|
10
|
+
'vec3' | 'mat4' | 'cubeMap' | 'array' | 'stringArray' | 'object' | 'file' | 'color';
|
|
11
|
+
|
|
12
|
+
@singleton()
|
|
13
|
+
export class InputValidator {
|
|
14
|
+
|
|
15
|
+
private readonly _logger: Logger = <Logger>container.resolve(Logger);
|
|
16
|
+
private readonly _typeChecker: TypeChecker = <TypeChecker>container.resolve(TypeChecker);
|
|
17
|
+
|
|
18
|
+
public validateAndError(topic: LOGGING_TOPIC, scope: string, value: any, type: Types, defined: boolean = true, enumValues: string[] = []) {
|
|
19
|
+
const res = this.validate(value, type, defined, enumValues);
|
|
20
|
+
if(res) return;
|
|
21
|
+
|
|
22
|
+
const error = new ShapeDiverViewerValidationError(`${scope}: Input could not be validated. ${value} is not of type ${type}.${defined === false ? ' (Can also be undefined)' : ''}`, value, type);
|
|
23
|
+
throw this._logger.handleError(LOGGING_TOPIC.GENERAL, 'InputValidator.validateAndError', error, false);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
private validate(value: any, stringLiteral: Types, defined: boolean = true, enumValues: string[] = []): boolean {
|
|
27
|
+
if (defined === false && typeof value === 'undefined') return true;
|
|
28
|
+
|
|
29
|
+
switch (stringLiteral) {
|
|
30
|
+
case 'array':
|
|
31
|
+
if(Array.isArray(value)) return true;
|
|
32
|
+
break;
|
|
33
|
+
case 'string':
|
|
34
|
+
if(this._typeChecker.isTypeOf(value, 'string')) return true;
|
|
35
|
+
break;
|
|
36
|
+
case 'boolean':
|
|
37
|
+
if(this._typeChecker.isTypeOf(value, 'boolean')) return true;
|
|
38
|
+
break;
|
|
39
|
+
case 'function':
|
|
40
|
+
if(this._typeChecker.isTypeOf(value, 'function')) return true;
|
|
41
|
+
break;
|
|
42
|
+
case 'number':
|
|
43
|
+
if(this._typeChecker.isTypeOf(value, 'number') && !isNaN(value)) return true;
|
|
44
|
+
break;
|
|
45
|
+
case 'factor':
|
|
46
|
+
if(this._typeChecker.isTypeOf(value, 'number') && value >= 0 && value <= 1) return true;
|
|
47
|
+
break;
|
|
48
|
+
case 'positive':
|
|
49
|
+
if(this._typeChecker.isTypeOf(value, 'number') && value >= 0) return true;
|
|
50
|
+
break;
|
|
51
|
+
case 'HTMLCanvasElement':
|
|
52
|
+
if(this._typeChecker.isHTMLCanvasElement(value)) return true;
|
|
53
|
+
break;
|
|
54
|
+
case 'enum':
|
|
55
|
+
if(this._typeChecker.isTypeOf(value, 'string') && enumValues.includes(value)) return true;
|
|
56
|
+
break;
|
|
57
|
+
case 'vec3':
|
|
58
|
+
if (value.constructor === Float32Array)
|
|
59
|
+
value = Array.from(value);
|
|
60
|
+
if(Array.isArray(value) && this._typeChecker.isTypeOf(value[0], 'number') && this._typeChecker.isTypeOf(value[1], 'number') && this._typeChecker.isTypeOf(value[2], 'number')) return true;
|
|
61
|
+
break;
|
|
62
|
+
case 'cubeMap':
|
|
63
|
+
if(Array.isArray(value) && value.length === 6 && this._typeChecker.isTypeOf(value[0], 'string') && this._typeChecker.isTypeOf(value[1], 'string') && this._typeChecker.isTypeOf(value[2], 'string') && this._typeChecker.isTypeOf(value[3], 'string') && this._typeChecker.isTypeOf(value[4], 'string') && this._typeChecker.isTypeOf(value[5], 'string')) return true;
|
|
64
|
+
if(this._typeChecker.isTypeOf(value, 'string')) return true;
|
|
65
|
+
break;
|
|
66
|
+
case 'stringArray':
|
|
67
|
+
if(Array.isArray(value)) {
|
|
68
|
+
let check = true;
|
|
69
|
+
for(let i = 0; i < value.length; i++)
|
|
70
|
+
if(typeof value[i] !== 'string') check = false;
|
|
71
|
+
if (check === true) return true;
|
|
72
|
+
}
|
|
73
|
+
break;
|
|
74
|
+
case 'object':
|
|
75
|
+
if(this._typeChecker.isTypeOf(value, 'object')) return true;
|
|
76
|
+
break;
|
|
77
|
+
case 'file':
|
|
78
|
+
if(this._typeChecker.isTypeOf(value, 'string') || value instanceof File || value instanceof Blob) return true;
|
|
79
|
+
break;
|
|
80
|
+
case 'color':
|
|
81
|
+
if(this._typeChecker.isTypeOf(value, 'string') || (Array.isArray(value) && this._typeChecker.isTypeOf(value[0], 'number') && this._typeChecker.isTypeOf(value[1], 'number') && this._typeChecker.isTypeOf(value[2], 'number')) || this._typeChecker.isTypeOf(value, 'number')) return true;
|
|
82
|
+
break;
|
|
83
|
+
case 'mat4':
|
|
84
|
+
if (value.constructor === Float32Array)
|
|
85
|
+
value = Array.from(value);
|
|
86
|
+
if(Array.isArray(value) && this._typeChecker.isTypeOf(value[0], 'number') && this._typeChecker.isTypeOf(value[1], 'number') && this._typeChecker.isTypeOf(value[2], 'number') && this._typeChecker.isTypeOf(value[3], 'number')
|
|
87
|
+
&& this._typeChecker.isTypeOf(value[4], 'number') && this._typeChecker.isTypeOf(value[5], 'number') && this._typeChecker.isTypeOf(value[6], 'number') && this._typeChecker.isTypeOf(value[7], 'number')
|
|
88
|
+
&& this._typeChecker.isTypeOf(value[8], 'number') && this._typeChecker.isTypeOf(value[9], 'number') && this._typeChecker.isTypeOf(value[10], 'number') && this._typeChecker.isTypeOf(value[11], 'number')
|
|
89
|
+
&& this._typeChecker.isTypeOf(value[12], 'number') && this._typeChecker.isTypeOf(value[13], 'number') && this._typeChecker.isTypeOf(value[14], 'number') && this._typeChecker.isTypeOf(value[15], 'number')) return true;
|
|
90
|
+
break;
|
|
91
|
+
default:
|
|
92
|
+
return false;
|
|
93
|
+
}
|
|
94
|
+
return false;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
public sanitize(input: string): string {
|
|
98
|
+
return DOMPurify.sanitize(input);
|
|
99
|
+
}
|
|
100
|
+
}
|