@swan-admin/swan-ai-measurements 1.1.21 → 1.1.23

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,209 +1,209 @@
1
- import axios, { AxiosResponse } from "axios";
2
- import { API_ENDPOINTS, APP_AUTH_BASE_URL, APP_BASE_WEBSOCKET_URL, REQUIRED_MESSAGE } from "./constants.js";
3
- import { checkParameters, getUrl } from "./utils.js";
4
-
5
- interface TryOnSocketOptions {
6
- shopDomain: string;
7
- scanId: string;
8
- productName: string;
9
- onError?: (error: any) => void;
10
- onSuccess?: (data: any) => void;
11
- onClose?: () => void;
12
- onOpen?: () => void;
13
- }
14
-
15
- interface MeasurementSocketOptions {
16
- scanId: string;
17
- onError?: (error: any) => void;
18
- onSuccess?: (data: any) => void;
19
- onClose?: () => void;
20
- onOpen?: () => void;
21
- }
22
-
23
- interface GetMeasurementsCheckOptions {
24
- scanId: string;
25
- onSuccess?: (data: any) => void;
26
- onError?: (error: any) => void;
27
- }
28
-
29
- interface HandlePollingOptions {
30
- scanId: string;
31
- onSuccess?: (data: any) => void;
32
- onError?: (error: any) => void;
33
- }
34
-
35
- interface HandleTimeOutOptions {
36
- scanId: string;
37
- onSuccess?: (data: any) => void;
38
- onError?: (error: any) => void;
39
- }
40
-
41
- class Measurement {
42
- #tryOnSocketRef: WebSocket | null = null;
43
- #measurementSocketRef: WebSocket | null = null;
44
- #timerPollingRef: NodeJS.Timeout | null = null;
45
- #timerWaitingRef: NodeJS.Timeout | null = null;
46
- #count: number = 1;
47
- #accessKey: string;
48
- #stagingUrl: boolean;
49
-
50
- constructor(accessKey: string, stagingUrl = false) {
51
- this.#accessKey = accessKey;
52
- this.#stagingUrl = stagingUrl;
53
- }
54
-
55
- getMeasurementResult(scanId: string): Promise<AxiosResponse<any>> {
56
- if (!checkParameters(scanId)) {
57
- throw new Error(REQUIRED_MESSAGE);
58
- }
59
- const url = `${getUrl({ urlName: APP_AUTH_BASE_URL, stagingUrl: this.#stagingUrl })}/measurements?scanId=${scanId}`;
60
- return axios.get(url, {
61
- headers: { "X-Api-Key": this.#accessKey },
62
- });
63
- }
64
-
65
- getTryOnMeasurements({ scanId, shopDomain, productName }: TryOnSocketOptions): Promise<AxiosResponse<any>> {
66
- if (!checkParameters(scanId, shopDomain, productName)) {
67
- throw new Error(REQUIRED_MESSAGE);
68
- }
69
- const tryOnUrl = `${getUrl({ urlName: APP_AUTH_BASE_URL, stagingUrl: this.#stagingUrl })}${
70
- API_ENDPOINTS.TRY_ON_SCAN
71
- }/${scanId}/shop/${shopDomain}/product/${productName}`;
72
- return axios.get(tryOnUrl, { headers: { "X-Api-Key": this.#accessKey } });
73
- }
74
-
75
- handleTryOnSocket(options: TryOnSocketOptions): void {
76
- const { shopDomain, scanId, productName, onError, onSuccess, onClose, onOpen } = options;
77
-
78
- if (!checkParameters(shopDomain, scanId, productName)) {
79
- throw new Error(REQUIRED_MESSAGE);
80
- }
81
-
82
- this.#tryOnSocketRef?.close();
83
- const url = `${getUrl({
84
- urlName: APP_BASE_WEBSOCKET_URL,
85
- stagingUrl: this.#stagingUrl,
86
- })}/develop?store_url=${shopDomain}&product_name=${productName}&scan_id=${scanId}`;
87
- this.#tryOnSocketRef = new WebSocket(url);
88
-
89
- this.#tryOnSocketRef.onopen = () => {
90
- onOpen?.();
91
- };
92
-
93
- this.#tryOnSocketRef.onmessage = (event) => {
94
- const data = JSON.parse(event.data);
95
- if (data?.tryOnProcessStatus === "available") {
96
- onSuccess?.(data);
97
- } else {
98
- onError?.({ message: "failed to get image urls" });
99
- }
100
- };
101
-
102
- this.#tryOnSocketRef.onclose = () => {
103
- onClose?.();
104
- };
105
-
106
- this.#tryOnSocketRef.onerror = (event) => {
107
- onError?.(event);
108
- };
109
- }
110
-
111
- async #getMeasurementsCheck(options: GetMeasurementsCheckOptions): Promise<void> {
112
- const { scanId, onSuccess, onError } = options;
113
-
114
- try {
115
- const res = await this.getMeasurementResult(scanId);
116
- if (res?.data && res?.data?.isMeasured === true) {
117
- onSuccess?.(res.data);
118
- if (this.#timerPollingRef) {
119
- clearInterval(this.#timerPollingRef);
120
- }
121
- } else {
122
- if (this.#count < 8) {
123
- this.#count++;
124
- this.#handlePolling({ scanId, onSuccess, onError });
125
- } else {
126
- this.#count = 1;
127
- if (this.#timerPollingRef) {
128
- clearInterval(this.#timerPollingRef);
129
- }
130
- onError?.({ scanStatus: "failed", message: "Scan not found", isMeasured: false });
131
- }
132
- }
133
- } catch (e) {
134
- if (this.#timerPollingRef) {
135
- clearInterval(this.#timerPollingRef);
136
- }
137
- onError?.(e);
138
- }
139
- }
140
-
141
- #handlePolling(options: HandlePollingOptions): void {
142
- const { scanId, onSuccess, onError } = options;
143
-
144
- if (this.#timerPollingRef) {
145
- clearInterval(this.#timerPollingRef);
146
- }
147
-
148
- this.#timerPollingRef = setTimeout(() => {
149
- this.#getMeasurementsCheck({ scanId, onSuccess, onError });
150
- }, this.#count * 5000);
151
- }
152
-
153
- #disconnectSocket(): void {
154
- this.#measurementSocketRef?.close();
155
- if (this.#timerWaitingRef) {
156
- clearTimeout(this.#timerWaitingRef);
157
- }
158
- }
159
-
160
- #handleTimeOut(options: HandleTimeOutOptions): void {
161
- const { scanId, onSuccess, onError } = options;
162
-
163
- this.#count = 1;
164
- this.#timerWaitingRef = setTimeout(() => {
165
- this.#handlePolling({ scanId, onSuccess, onError });
166
- this.#disconnectSocket();
167
- }, 2 * 60000);
168
- }
169
-
170
- handleMeasurementSocket(options: MeasurementSocketOptions): void {
171
- const { scanId, onError, onSuccess, onClose, onOpen } = options;
172
-
173
- if (!checkParameters(scanId)) {
174
- throw new Error(REQUIRED_MESSAGE);
175
- }
176
-
177
- setTimeout(() => {
178
- this.#disconnectSocket();
179
- const url = `${getUrl({ urlName: APP_BASE_WEBSOCKET_URL, stagingUrl: this.#stagingUrl })}${API_ENDPOINTS.SCANNING}?scanId=${scanId}`;
180
- this.#measurementSocketRef = new WebSocket(url);
181
- this.#measurementSocketRef.onopen = () => {
182
- onOpen?.();
183
- this.#handleTimeOut({ scanId, onSuccess, onError });
184
- };
185
-
186
- this.#measurementSocketRef.onmessage = (event: MessageEvent) => {
187
- const data = JSON.parse(event.data);
188
- if (data?.code === 200 && data?.scanStatus === "success") {
189
- onSuccess?.(data);
190
- } else {
191
- onError?.(data);
192
- }
193
- if (this.#timerWaitingRef) {
194
- clearTimeout(this.#timerWaitingRef);
195
- }
196
- };
197
-
198
- this.#measurementSocketRef.onclose = () => {
199
- onClose?.();
200
- };
201
-
202
- this.#measurementSocketRef.onerror = (event: Event) => {
203
- onError?.(event);
204
- };
205
- }, 5000);
206
- }
207
- }
208
-
209
- export default Measurement;
1
+ import axios, { AxiosResponse } from "axios";
2
+ import { API_ENDPOINTS, APP_AUTH_BASE_URL, APP_BASE_WEBSOCKET_URL, REQUIRED_MESSAGE } from "./constants.js";
3
+ import { checkParameters, getUrl } from "./utils.js";
4
+
5
+ interface TryOnSocketOptions {
6
+ shopDomain: string;
7
+ scanId: string;
8
+ productName: string;
9
+ onError?: (error: any) => void;
10
+ onSuccess?: (data: any) => void;
11
+ onClose?: () => void;
12
+ onOpen?: () => void;
13
+ }
14
+
15
+ interface MeasurementSocketOptions {
16
+ scanId: string;
17
+ onError?: (error: any) => void;
18
+ onSuccess?: (data: any) => void;
19
+ onClose?: () => void;
20
+ onOpen?: () => void;
21
+ }
22
+
23
+ interface GetMeasurementsCheckOptions {
24
+ scanId: string;
25
+ onSuccess?: (data: any) => void;
26
+ onError?: (error: any) => void;
27
+ }
28
+
29
+ interface HandlePollingOptions {
30
+ scanId: string;
31
+ onSuccess?: (data: any) => void;
32
+ onError?: (error: any) => void;
33
+ }
34
+
35
+ interface HandleTimeOutOptions {
36
+ scanId: string;
37
+ onSuccess?: (data: any) => void;
38
+ onError?: (error: any) => void;
39
+ }
40
+
41
+ class Measurement {
42
+ #tryOnSocketRef: WebSocket | null = null;
43
+ #measurementSocketRef: WebSocket | null = null;
44
+ #timerPollingRef: NodeJS.Timeout | null = null;
45
+ #timerWaitingRef: NodeJS.Timeout | null = null;
46
+ #count: number = 1;
47
+ #accessKey: string;
48
+ #stagingUrl: boolean;
49
+
50
+ constructor(accessKey: string, stagingUrl = false) {
51
+ this.#accessKey = accessKey;
52
+ this.#stagingUrl = stagingUrl;
53
+ }
54
+
55
+ getMeasurementResult(scanId: string): Promise<AxiosResponse<any>> {
56
+ if (!checkParameters(scanId)) {
57
+ throw new Error(REQUIRED_MESSAGE);
58
+ }
59
+ const url = `${getUrl({ urlName: APP_AUTH_BASE_URL, stagingUrl: this.#stagingUrl })}/measurements?scanId=${scanId}`;
60
+ return axios.get(url, {
61
+ headers: { "X-Api-Key": this.#accessKey },
62
+ });
63
+ }
64
+
65
+ getTryOnMeasurements({ scanId, shopDomain, productName }: TryOnSocketOptions): Promise<AxiosResponse<any>> {
66
+ if (!checkParameters(scanId, shopDomain, productName)) {
67
+ throw new Error(REQUIRED_MESSAGE);
68
+ }
69
+ const tryOnUrl = `${getUrl({ urlName: APP_AUTH_BASE_URL, stagingUrl: this.#stagingUrl })}${
70
+ API_ENDPOINTS.TRY_ON_SCAN
71
+ }/${scanId}/shop/${shopDomain}/product/${productName}`;
72
+ return axios.get(tryOnUrl, { headers: { "X-Api-Key": this.#accessKey } });
73
+ }
74
+
75
+ handleTryOnSocket(options: TryOnSocketOptions): void {
76
+ const { shopDomain, scanId, productName, onError, onSuccess, onClose, onOpen } = options;
77
+
78
+ if (!checkParameters(shopDomain, scanId, productName)) {
79
+ throw new Error(REQUIRED_MESSAGE);
80
+ }
81
+
82
+ this.#tryOnSocketRef?.close();
83
+ const url = `${getUrl({
84
+ urlName: APP_BASE_WEBSOCKET_URL,
85
+ stagingUrl: this.#stagingUrl,
86
+ })}/develop?store_url=${shopDomain}&product_name=${productName}&scan_id=${scanId}`;
87
+ this.#tryOnSocketRef = new WebSocket(url);
88
+
89
+ this.#tryOnSocketRef.onopen = () => {
90
+ onOpen?.();
91
+ };
92
+
93
+ this.#tryOnSocketRef.onmessage = (event) => {
94
+ const data = JSON.parse(event.data);
95
+ if (data?.tryOnProcessStatus === "available") {
96
+ onSuccess?.(data);
97
+ } else {
98
+ onError?.({ message: "failed to get image urls" });
99
+ }
100
+ };
101
+
102
+ this.#tryOnSocketRef.onclose = () => {
103
+ onClose?.();
104
+ };
105
+
106
+ this.#tryOnSocketRef.onerror = (event) => {
107
+ onError?.(event);
108
+ };
109
+ }
110
+
111
+ async #getMeasurementsCheck(options: GetMeasurementsCheckOptions): Promise<void> {
112
+ const { scanId, onSuccess, onError } = options;
113
+
114
+ try {
115
+ const res = await this.getMeasurementResult(scanId);
116
+ if (res?.data && res?.data?.isMeasured === true) {
117
+ onSuccess?.(res.data);
118
+ if (this.#timerPollingRef) {
119
+ clearInterval(this.#timerPollingRef);
120
+ }
121
+ } else {
122
+ if (this.#count < 8) {
123
+ this.#count++;
124
+ this.#handlePolling({ scanId, onSuccess, onError });
125
+ } else {
126
+ this.#count = 1;
127
+ if (this.#timerPollingRef) {
128
+ clearInterval(this.#timerPollingRef);
129
+ }
130
+ onError?.({ scanStatus: "failed", message: "Scan not found", isMeasured: false });
131
+ }
132
+ }
133
+ } catch (e) {
134
+ if (this.#timerPollingRef) {
135
+ clearInterval(this.#timerPollingRef);
136
+ }
137
+ onError?.(e);
138
+ }
139
+ }
140
+
141
+ #handlePolling(options: HandlePollingOptions): void {
142
+ const { scanId, onSuccess, onError } = options;
143
+
144
+ if (this.#timerPollingRef) {
145
+ clearInterval(this.#timerPollingRef);
146
+ }
147
+
148
+ this.#timerPollingRef = setTimeout(() => {
149
+ this.#getMeasurementsCheck({ scanId, onSuccess, onError });
150
+ }, this.#count * 5000);
151
+ }
152
+
153
+ #disconnectSocket(): void {
154
+ this.#measurementSocketRef?.close();
155
+ if (this.#timerWaitingRef) {
156
+ clearTimeout(this.#timerWaitingRef);
157
+ }
158
+ }
159
+
160
+ #handleTimeOut(options: HandleTimeOutOptions): void {
161
+ const { scanId, onSuccess, onError } = options;
162
+
163
+ this.#count = 1;
164
+ this.#timerWaitingRef = setTimeout(() => {
165
+ this.#handlePolling({ scanId, onSuccess, onError });
166
+ this.#disconnectSocket();
167
+ }, 2 * 60000);
168
+ }
169
+
170
+ handleMeasurementSocket(options: MeasurementSocketOptions): void {
171
+ const { scanId, onError, onSuccess, onClose, onOpen } = options;
172
+
173
+ if (!checkParameters(scanId)) {
174
+ throw new Error(REQUIRED_MESSAGE);
175
+ }
176
+
177
+ setTimeout(() => {
178
+ this.#disconnectSocket();
179
+ const url = `${getUrl({ urlName: APP_BASE_WEBSOCKET_URL, stagingUrl: this.#stagingUrl })}${API_ENDPOINTS.SCANNING}?scanId=${scanId}`;
180
+ this.#measurementSocketRef = new WebSocket(url);
181
+ this.#measurementSocketRef.onopen = () => {
182
+ onOpen?.();
183
+ this.#handleTimeOut({ scanId, onSuccess, onError });
184
+ };
185
+
186
+ this.#measurementSocketRef.onmessage = (event: MessageEvent) => {
187
+ const data = JSON.parse(event.data);
188
+ if (data?.code === 200 && data?.scanStatus === "success") {
189
+ onSuccess?.(data);
190
+ } else {
191
+ onError?.(data);
192
+ }
193
+ if (this.#timerWaitingRef) {
194
+ clearTimeout(this.#timerWaitingRef);
195
+ }
196
+ };
197
+
198
+ this.#measurementSocketRef.onclose = () => {
199
+ onClose?.();
200
+ };
201
+
202
+ this.#measurementSocketRef.onerror = (event: Event) => {
203
+ onError?.(event);
204
+ };
205
+ }, 5000);
206
+ }
207
+ }
208
+
209
+ export default Measurement;
@@ -1,70 +1,70 @@
1
- import { io, Socket } from "socket.io-client";
2
- import { APP_POSE_DETECTION_WEBSOCKET_URL } from "./constants.js";
3
- import { getUrl } from "./utils.js";
4
-
5
-
6
- interface VideoEmitOptions {
7
- image: string;
8
- scanId: string;
9
- }
10
-
11
- type PoseStatusCallback = (data: any) => void;
12
-
13
- class PoseDetection {
14
- #socketRef: Socket | null = null;
15
- #accessKey: string;
16
- #stagingUrl: boolean;
17
- constructor(accessKey: string, stagingUrl = false) {
18
- this.#accessKey = accessKey;
19
- this.#stagingUrl = stagingUrl;
20
- }
21
-
22
- connect(): Promise<string> {
23
- return new Promise((resolve, reject) => {
24
- this.#socketRef = io(getUrl({ urlName: APP_POSE_DETECTION_WEBSOCKET_URL, stagingUrl: this.#stagingUrl }));
25
- this.#socketRef.on("connect", () => {
26
- const socketId = this.#socketRef?.id;
27
- if (socketId) {
28
- resolve(socketId);
29
- } else {
30
- reject("Failed to obtain socket ID.");
31
- }
32
- });
33
-
34
- this.#socketRef.on("connect_error", (err) => {
35
- reject(err);
36
- });
37
- });
38
- }
39
-
40
- videoEmit({ image, scanId }: VideoEmitOptions): void {
41
- if (!this.#socketRef) {
42
- throw new Error("Socket is not connected");
43
- }
44
-
45
- this.#socketRef.emit("video", {
46
- image,
47
- user_unique_key: scanId,
48
- });
49
- }
50
-
51
- disconnect(): void {
52
- this.#socketRef?.disconnect();
53
- }
54
-
55
- poseStatus(callBack: PoseStatusCallback): void {
56
- if (!this.#socketRef) {
57
- throw new Error("Socket is not connected");
58
- }
59
-
60
- this.#socketRef.on("pose_status", (data) => {
61
- callBack?.(data);
62
- });
63
- }
64
-
65
- connected(): boolean {
66
- return !!this.#socketRef?.connected;
67
- }
68
- }
69
-
70
- export default PoseDetection;
1
+ import { io, Socket } from "socket.io-client";
2
+ import { APP_POSE_DETECTION_WEBSOCKET_URL } from "./constants.js";
3
+ import { getUrl } from "./utils.js";
4
+
5
+
6
+ interface VideoEmitOptions {
7
+ image: string;
8
+ scanId: string;
9
+ }
10
+
11
+ type PoseStatusCallback = (data: any) => void;
12
+
13
+ class PoseDetection {
14
+ #socketRef: Socket | null = null;
15
+ #accessKey: string;
16
+ #stagingUrl: boolean;
17
+ constructor(accessKey: string, stagingUrl = false) {
18
+ this.#accessKey = accessKey;
19
+ this.#stagingUrl = stagingUrl;
20
+ }
21
+
22
+ connect(): Promise<string> {
23
+ return new Promise((resolve, reject) => {
24
+ this.#socketRef = io(getUrl({ urlName: APP_POSE_DETECTION_WEBSOCKET_URL, stagingUrl: this.#stagingUrl }));
25
+ this.#socketRef.on("connect", () => {
26
+ const socketId = this.#socketRef?.id;
27
+ if (socketId) {
28
+ resolve(socketId);
29
+ } else {
30
+ reject("Failed to obtain socket ID.");
31
+ }
32
+ });
33
+
34
+ this.#socketRef.on("connect_error", (err) => {
35
+ reject(err);
36
+ });
37
+ });
38
+ }
39
+
40
+ videoEmit({ image, scanId }: VideoEmitOptions): void {
41
+ if (!this.#socketRef) {
42
+ throw new Error("Socket is not connected");
43
+ }
44
+
45
+ this.#socketRef.emit("video", {
46
+ image,
47
+ user_unique_key: scanId,
48
+ });
49
+ }
50
+
51
+ disconnect(): void {
52
+ this.#socketRef?.disconnect();
53
+ }
54
+
55
+ poseStatus(callBack: PoseStatusCallback): void {
56
+ if (!this.#socketRef) {
57
+ throw new Error("Socket is not connected");
58
+ }
59
+
60
+ this.#socketRef.on("pose_status", (data) => {
61
+ callBack?.(data);
62
+ });
63
+ }
64
+
65
+ connected(): boolean {
66
+ return !!this.#socketRef?.connected;
67
+ }
68
+ }
69
+
70
+ export default PoseDetection;