@polyguard/sdk 1.0.8 → 1.1.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/sdk.js CHANGED
@@ -10950,6 +10950,22 @@
10950
10950
 
10951
10951
  // src/PolyguardWebsocketClientImpl.js
10952
10952
  var import_qrcode = __toESM(require_browser());
10953
+ var LOADING_SPINNER = `<svg xmlns="http://www.w3.org/2000/svg" width="200" height="200" viewBox="0 0 200 200" fill="none">
10954
+ <style>
10955
+ .spinner-circle {
10956
+ animation: spin 1s linear infinite;
10957
+ transform-origin: 100px 100px;
10958
+ }
10959
+ @keyframes spin {
10960
+ from { transform: rotate(0deg); }
10961
+ to { transform: rotate(360deg); }
10962
+ }
10963
+ </style>
10964
+ <circle cx="100" cy="100" r="80" stroke="#e0e0e0" stroke-width="8" fill="none" />
10965
+ <circle cx="100" cy="100" r="80" stroke="#7be7c2" stroke-width="8" fill="none"
10966
+ stroke-dasharray="251.2" stroke-dashoffset="188.4"
10967
+ class="spinner-circle" stroke-linecap="round" />
10968
+ </svg>`;
10953
10969
  var PolyguardWebsocketClientImpl = class {
10954
10970
  constructor(params = {}) {
10955
10971
  this.apiClient = new ApiClient_default();
@@ -10977,7 +10993,7 @@
10977
10993
  this.callbackUrl = callbackUrl;
10978
10994
  this.cookieName = cookieName;
10979
10995
  }
10980
- async verify() {
10996
+ buildModal() {
10981
10997
  const modal = document.createElement("div");
10982
10998
  modal.style.position = "fixed";
10983
10999
  modal.style.top = "0";
@@ -11006,13 +11022,21 @@
11006
11022
  <button id="polyguard-modal-cancel" style="background: #7be7c2; color: #222; font-weight: 600; border-radius: 8px; border: none; padding: 10px 32px; font-size: 16px; cursor: pointer; margin-top: 8px; width: 100%; max-width: 240px;">Cancel</button>
11007
11023
  </div>
11008
11024
  `;
11025
+ return modal;
11026
+ }
11027
+ async verify() {
11028
+ const modal = this.buildModal();
11029
+ document.body.appendChild(modal);
11030
+ const qrDiv = modal.querySelector("#polyguard-qr");
11031
+ if (qrDiv) {
11032
+ qrDiv.innerHTML = LOADING_SPINNER;
11033
+ }
11009
11034
  function cleanup() {
11010
11035
  if (modal.parentNode) modal.parentNode.removeChild(modal);
11011
11036
  }
11012
11037
  return new Promise(async (resolve, reject) => {
11013
11038
  let ws = null;
11014
11039
  let closed = false;
11015
- let modalShown = false;
11016
11040
  function showError(msg) {
11017
11041
  const errDiv = modal.querySelector("#polyguard-error");
11018
11042
  if (errDiv) {
@@ -11030,11 +11054,8 @@
11030
11054
  cleanup();
11031
11055
  reject(new Error("User cancelled"));
11032
11056
  }
11033
- function showModal() {
11034
- document.body.appendChild(modal);
11035
- modal.querySelector("#polyguard-modal-close").onclick = handleClose;
11036
- modal.querySelector("#polyguard-modal-cancel").onclick = handleClose;
11037
- }
11057
+ modal.querySelector("#polyguard-modal-close").onclick = handleClose;
11058
+ modal.querySelector("#polyguard-modal-cancel").onclick = handleClose;
11038
11059
  try {
11039
11060
  clearError();
11040
11061
  const wsProtocol = window.location.protocol === "https:" ? "wss" : "ws";
@@ -11066,23 +11087,19 @@
11066
11087
  window.location.assign(data.url);
11067
11088
  return;
11068
11089
  } else if (data && data.qr_url) {
11069
- if (!modalShown) {
11070
- showModal();
11071
- modalShown = true;
11072
- }
11073
11090
  const pcre = data.qr_url.match(/pcre=([^&]*)/);
11074
11091
  console.log("pcre", pcre);
11075
11092
  if (pcre) {
11076
11093
  ws.send(JSON.stringify({ type: "pong", seq: pcre[1] }));
11077
11094
  }
11078
- const qrDiv = modal.querySelector("#polyguard-qr");
11079
- if (!qrDiv) return;
11095
+ const qrDiv2 = modal.querySelector("#polyguard-qr");
11096
+ if (!qrDiv2) return;
11080
11097
  const isMobile = /Mobi|Android/i.test(navigator.userAgent);
11081
11098
  if (isMobile) {
11082
- qrDiv.innerHTML = `<button id="polyguard-open-app-button" style="background: #7be7c2; color: #222; font-weight: 600; border-radius: 8px; border: none; padding: 10px 32px; font-size: 16px; cursor: pointer;">Open Polyguard App</button>`;
11083
- qrDiv.style.background = "transparent";
11084
- qrDiv.querySelector("#polyguard-open-app-button").onclick = () => window.location.assign(data.qr_url);
11085
- const instructionText = qrDiv.nextElementSibling;
11099
+ qrDiv2.innerHTML = `<button id="polyguard-open-app-button" style="background: #7be7c2; color: #222; font-weight: 600; border-radius: 8px; border: none; padding: 10px 32px; font-size: 16px; cursor: pointer;">Open Polyguard App</button>`;
11100
+ qrDiv2.style.background = "transparent";
11101
+ qrDiv2.querySelector("#polyguard-open-app-button").onclick = () => window.location.assign(data.qr_url);
11102
+ const instructionText = qrDiv2.nextElementSibling;
11086
11103
  if (instructionText) {
11087
11104
  instructionText.textContent = "Tap the button to verify with the Polyguard app.";
11088
11105
  }
@@ -11094,36 +11111,24 @@
11094
11111
  const startTime = Date.now();
11095
11112
  console.log("time before qr code", startTime);
11096
11113
  import_qrcode.default.toString(data.qr_url, { type: "svg" }, (err, svg) => {
11097
- if (!err) qrDiv.innerHTML = svg;
11114
+ if (!err) qrDiv2.innerHTML = svg;
11098
11115
  });
11099
11116
  console.log("time to generate qr code", Date.now() - startTime);
11100
11117
  }
11101
11118
  return;
11102
11119
  } else if (data && data.jwt) {
11103
11120
  cleanup();
11104
- resolve(data.jwt);
11105
11121
  ws.close();
11122
+ resolve(data.jwt);
11106
11123
  return;
11107
11124
  } else if (data && data.status) {
11108
- const qrDiv = modal.querySelector("#polyguard-qr");
11109
- if (!qrDiv) return;
11110
- const spinner = `<svg xmlns="http://www.w3.org/2000/svg" width="200" height="200" viewBox="0 0 200 200" fill="none">
11111
- <style>
11112
- .spinner-circle {
11113
- animation: spin 1s linear infinite;
11114
- transform-origin: 100px 100px;
11115
- }
11116
- @keyframes spin {
11117
- from { transform: rotate(0deg); }
11118
- to { transform: rotate(360deg); }
11119
- }
11120
- </style>
11121
- <circle cx="100" cy="100" r="80" stroke="#e0e0e0" stroke-width="8" fill="none" />
11122
- <circle cx="100" cy="100" r="80" stroke="#7be7c2" stroke-width="8" fill="none"
11123
- stroke-dasharray="251.2" stroke-dashoffset="188.4"
11124
- class="spinner-circle" stroke-linecap="round" />
11125
- </svg>`;
11126
- qrDiv.innerHTML = spinner;
11125
+ const qrDiv2 = modal.querySelector("#polyguard-qr");
11126
+ if (!qrDiv2) return;
11127
+ qrDiv2.innerHTML = LOADING_SPINNER;
11128
+ return;
11129
+ } else if (data && data.error) {
11130
+ showError(data.error);
11131
+ ws.close();
11127
11132
  return;
11128
11133
  } else {
11129
11134
  console.error("Unknown message type from server", data);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@polyguard/sdk",
3
- "version": "1.0.8",
3
+ "version": "1.1.0",
4
4
  "main": "dist/sdk.js",
5
5
  "module": "dist/sdk.js",
6
6
  "browser": "dist/sdk.js",
@@ -2,6 +2,24 @@ import ReconnectingWebSocket from 'reconnecting-websocket';
2
2
  import * as PolyguardApi from './generated/src';
3
3
  import QRCode from 'qrcode';
4
4
 
5
+ // Animated spinner SVG
6
+ const LOADING_SPINNER = `<svg xmlns="http://www.w3.org/2000/svg" width="200" height="200" viewBox="0 0 200 200" fill="none">
7
+ <style>
8
+ .spinner-circle {
9
+ animation: spin 1s linear infinite;
10
+ transform-origin: 100px 100px;
11
+ }
12
+ @keyframes spin {
13
+ from { transform: rotate(0deg); }
14
+ to { transform: rotate(360deg); }
15
+ }
16
+ </style>
17
+ <circle cx="100" cy="100" r="80" stroke="#e0e0e0" stroke-width="8" fill="none" />
18
+ <circle cx="100" cy="100" r="80" stroke="#7be7c2" stroke-width="8" fill="none"
19
+ stroke-dasharray="251.2" stroke-dashoffset="188.4"
20
+ class="spinner-circle" stroke-linecap="round" />
21
+ </svg>`;
22
+
5
23
  // Implementation class for websocket integration
6
24
  export class PolyguardWebsocketClientImpl {
7
25
  constructor(params = {}) {
@@ -33,9 +51,7 @@ export class PolyguardWebsocketClientImpl {
33
51
  this.cookieName = cookieName;
34
52
  }
35
53
 
36
- async verify() {
37
- // Only websocket integration is supported for modal
38
- // Create modal DOM
54
+ buildModal() {
39
55
  const modal = document.createElement('div');
40
56
  modal.style.position = 'fixed';
41
57
  modal.style.top = '0';
@@ -64,17 +80,31 @@ export class PolyguardWebsocketClientImpl {
64
80
  <button id="polyguard-modal-cancel" style="background: #7be7c2; color: #222; font-weight: 600; border-radius: 8px; border: none; padding: 10px 32px; font-size: 16px; cursor: pointer; margin-top: 8px; width: 100%; max-width: 240px;">Cancel</button>
65
81
  </div>
66
82
  `;
83
+ return modal;
84
+ }
85
+
86
+ async verify() {
87
+ // Only websocket integration is supported for modal
88
+ // Create modal DOM
89
+ const modal = this.buildModal();
90
+
91
+ // Show modal immediately with spinner
92
+ document.body.appendChild(modal);
93
+
94
+ // Initialize QR div with spinner
95
+ const qrDiv = modal.querySelector('#polyguard-qr');
96
+ if (qrDiv) {
97
+ qrDiv.innerHTML = LOADING_SPINNER;
98
+ }
67
99
 
68
100
  // Helper to cleanup modal
69
101
  function cleanup() {
70
102
  if (modal.parentNode) modal.parentNode.removeChild(modal);
71
103
  }
72
-
73
104
  // Promise for JWT
74
105
  return new Promise(async (resolve, reject) => {
75
106
  let ws = null;
76
107
  let closed = false;
77
- let modalShown = false;
78
108
 
79
109
  function showError(msg) {
80
110
  const errDiv = modal.querySelector('#polyguard-error');
@@ -94,14 +124,10 @@ export class PolyguardWebsocketClientImpl {
94
124
  cleanup();
95
125
  reject(new Error('User cancelled'));
96
126
  }
97
-
98
- // Helper to show modal (only called when QR code is received)
99
- function showModal() {
100
- document.body.appendChild(modal);
101
- // Set up close/cancel handlers after modal is in DOM
102
- modal.querySelector('#polyguard-modal-close').onclick = handleClose;
103
- modal.querySelector('#polyguard-modal-cancel').onclick = handleClose;
104
- }
127
+
128
+ // Set up close/cancel handlers
129
+ modal.querySelector('#polyguard-modal-close').onclick = handleClose;
130
+ modal.querySelector('#polyguard-modal-cancel').onclick = handleClose;
105
131
 
106
132
  // Start ticket/ws flow
107
133
  try {
@@ -137,11 +163,7 @@ export class PolyguardWebsocketClientImpl {
137
163
  window.location.assign(data.url);
138
164
  return;
139
165
  } else if (data && data.qr_url) {
140
- // Show modal only when QR code is received
141
- if (!modalShown) {
142
- showModal();
143
- modalShown = true;
144
- }
166
+ // Replace spinner with QR code content
145
167
 
146
168
  const pcre = data.qr_url.match(/pcre=([^&]*)/);
147
169
  console.log('pcre', pcre);
@@ -181,31 +203,19 @@ export class PolyguardWebsocketClientImpl {
181
203
  return;
182
204
  } else if (data && data.jwt) {
183
205
  cleanup();
184
- resolve(data.jwt);
185
206
  ws.close();
207
+ resolve(data.jwt);
186
208
  return;
187
209
  } else if (data && data.status) {
188
210
  // ignore
189
211
  // generate a spinner in svg and set the qr code to it
190
212
  const qrDiv = modal.querySelector('#polyguard-qr');
191
213
  if (!qrDiv) return;
192
- const spinner = `<svg xmlns="http://www.w3.org/2000/svg" width="200" height="200" viewBox="0 0 200 200" fill="none">
193
- <style>
194
- .spinner-circle {
195
- animation: spin 1s linear infinite;
196
- transform-origin: 100px 100px;
197
- }
198
- @keyframes spin {
199
- from { transform: rotate(0deg); }
200
- to { transform: rotate(360deg); }
201
- }
202
- </style>
203
- <circle cx="100" cy="100" r="80" stroke="#e0e0e0" stroke-width="8" fill="none" />
204
- <circle cx="100" cy="100" r="80" stroke="#7be7c2" stroke-width="8" fill="none"
205
- stroke-dasharray="251.2" stroke-dashoffset="188.4"
206
- class="spinner-circle" stroke-linecap="round" />
207
- </svg>`;
208
- qrDiv.innerHTML = spinner;
214
+ qrDiv.innerHTML = LOADING_SPINNER;
215
+ return;
216
+ } else if (data && data.error) {
217
+ showError(data.error);
218
+ ws.close();
209
219
  return;
210
220
  } else {
211
221
  console.error('Unknown message type from server', data);