@prosopo/procaptcha-pow 2.10.23 → 2.10.25

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.
Files changed (47) hide show
  1. package/.turbo/turbo-build$colon$cjs.log +12 -10
  2. package/.turbo/turbo-build$colon$tsc.log +19 -19
  3. package/.turbo/turbo-build.log +14 -11
  4. package/CHANGELOG.md +46 -0
  5. package/dist/_virtual/_rolldown/runtime.js +3 -0
  6. package/dist/cjs/components/ProcaptchaPoW.cjs +6 -9
  7. package/dist/cjs/components/ProcaptchaWidget.cjs +117 -127
  8. package/dist/cjs/index.cjs +2 -4
  9. package/dist/cjs/services/Manager.cjs +193 -277
  10. package/dist/components/ProcaptchaPoW.js +6 -8
  11. package/dist/components/ProcaptchaWidget.d.ts.map +1 -1
  12. package/dist/components/ProcaptchaWidget.js +117 -127
  13. package/dist/components/ProcaptchaWidget.js.map +1 -1
  14. package/dist/index.js +2 -4
  15. package/dist/services/Manager.d.ts.map +1 -1
  16. package/dist/services/Manager.js +189 -274
  17. package/dist/services/Manager.js.map +1 -1
  18. package/dist/tests/manager.unit.test.d.ts +2 -0
  19. package/dist/tests/manager.unit.test.d.ts.map +1 -0
  20. package/dist/tests/manager.unit.test.js +752 -0
  21. package/dist/tests/manager.unit.test.js.map +1 -0
  22. package/dist/tests/managerHarness.d.ts +17 -0
  23. package/dist/tests/managerHarness.d.ts.map +1 -0
  24. package/dist/tests/managerHarness.js +70 -0
  25. package/dist/tests/managerHarness.js.map +1 -0
  26. package/dist/tests/procaptchaPoW.unit.test.d.ts +2 -0
  27. package/dist/tests/procaptchaPoW.unit.test.d.ts.map +1 -0
  28. package/dist/tests/procaptchaPoW.unit.test.js +79 -0
  29. package/dist/tests/procaptchaPoW.unit.test.js.map +1 -0
  30. package/dist/tests/procaptchaPow.test-d.d.ts +2 -0
  31. package/dist/tests/procaptchaPow.test-d.d.ts.map +1 -0
  32. package/dist/tests/procaptchaPow.test-d.js +62 -0
  33. package/dist/tests/procaptchaPow.test-d.js.map +1 -0
  34. package/dist/tests/procaptchaWidget.unit.test.d.ts +2 -0
  35. package/dist/tests/procaptchaWidget.unit.test.d.ts.map +1 -0
  36. package/dist/tests/procaptchaWidget.unit.test.js +410 -0
  37. package/dist/tests/procaptchaWidget.unit.test.js.map +1 -0
  38. package/package.json +18 -13
  39. package/src/components/ProcaptchaWidget.tsx +22 -5
  40. package/src/services/Manager.ts +9 -5
  41. package/src/tests/manager.unit.test.ts +1105 -0
  42. package/src/tests/managerHarness.ts +135 -0
  43. package/src/tests/procaptchaPoW.unit.test.ts +120 -0
  44. package/src/tests/procaptchaPow.test-d.ts +122 -0
  45. package/src/tests/procaptchaWidget.unit.test.ts +571 -0
  46. package/tsconfig.tsbuildinfo +1 -1
  47. package/vite.test.config.ts +25 -0
@@ -0,0 +1,410 @@
1
+ import { ModeEnum, } from "@prosopo/types";
2
+ import { act, createElement } from "react";
3
+ import { createRoot } from "react-dom/client";
4
+ import { afterEach, beforeEach, describe, expect, test, vi, } from "vitest";
5
+ import Procaptcha from "../components/ProcaptchaWidget.js";
6
+ import { config, frictionless } from "./managerHarness.js";
7
+ const mocks = vi.hoisted(() => {
8
+ const start = vi.fn();
9
+ const resetState = vi.fn();
10
+ const constructions = [];
11
+ const loadI18next = vi.fn();
12
+ const checkboxProps = { current: undefined };
13
+ const honeypotQuestions = [];
14
+ const translationsReady = { current: true };
15
+ return {
16
+ translationsReady,
17
+ start,
18
+ resetState,
19
+ constructions,
20
+ loadI18next,
21
+ checkboxProps,
22
+ honeypotQuestions,
23
+ };
24
+ });
25
+ vi.mock("../services/Manager.js", () => ({
26
+ Manager: (_config, _state, updateState, _callbacks, _frictionlessState, _onEscalate, getHoneypotValue) => {
27
+ mocks.constructions.push({ updateState, getHoneypotValue });
28
+ return { start: mocks.start, resetState: mocks.resetState };
29
+ },
30
+ }));
31
+ vi.mock("@prosopo/procaptcha-common", async (importOriginal) => {
32
+ const actual = await importOriginal();
33
+ const { createElement, forwardRef } = await import("react");
34
+ const Checkbox = (props) => {
35
+ mocks.checkboxProps.current = props;
36
+ return createElement("input", {
37
+ type: "checkbox",
38
+ readOnly: true,
39
+ checked: props.checked,
40
+ "aria-label": props.labelText,
41
+ "data-error": props.error,
42
+ "data-loading": String(props.loading),
43
+ });
44
+ };
45
+ const Honeypot = forwardRef(({ encodedQuestion }, ref) => {
46
+ mocks.honeypotQuestions.push(encodedQuestion);
47
+ return createElement("input", { type: "text", ref, name: "honeypot" });
48
+ });
49
+ return { ...actual, Checkbox, Honeypot };
50
+ });
51
+ vi.mock("@prosopo/locale", async (importOriginal) => {
52
+ const actual = await importOriginal();
53
+ return {
54
+ ...actual,
55
+ loadI18next: mocks.loadI18next,
56
+ useTranslation: () => ({
57
+ t: (key) => key,
58
+ ready: mocks.translationsReady.current,
59
+ }),
60
+ };
61
+ });
62
+ let container;
63
+ let root;
64
+ const i18nStub = (language, changeLanguage) => ({ language, changeLanguage });
65
+ const props = (overrides = {}) => ({
66
+ config: config(),
67
+ callbacks: {},
68
+ i18n: undefined,
69
+ ...overrides,
70
+ });
71
+ const render = (widgetProps) => {
72
+ act(() => {
73
+ root.render(createElement(Procaptcha, widgetProps));
74
+ });
75
+ };
76
+ beforeEach(() => {
77
+ vi.clearAllMocks();
78
+ mocks.constructions.length = 0;
79
+ mocks.honeypotQuestions.length = 0;
80
+ mocks.translationsReady.current = true;
81
+ mocks.checkboxProps.current = undefined;
82
+ mocks.start.mockResolvedValue(undefined);
83
+ mocks.loadI18next.mockResolvedValue(undefined);
84
+ container = document.createElement("div");
85
+ document.body.appendChild(container);
86
+ act(() => {
87
+ root = createRoot(container);
88
+ });
89
+ });
90
+ afterEach(() => {
91
+ act(() => {
92
+ root.unmount();
93
+ });
94
+ container.remove();
95
+ vi.restoreAllMocks();
96
+ });
97
+ const checkbox = () => {
98
+ const element = container.querySelector('input[type="checkbox"]');
99
+ if (!element)
100
+ throw new Error("expected a checkbox to be rendered");
101
+ return element;
102
+ };
103
+ const honeypotInput = () => {
104
+ const element = container.querySelector('input[name="honeypot"]');
105
+ if (!element)
106
+ throw new Error("expected a honeypot to be rendered");
107
+ return element;
108
+ };
109
+ const click = (options = {}) => {
110
+ const nativeEvent = {
111
+ isTrusted: options.trusted ?? true,
112
+ clientX: options.clientX ?? 0,
113
+ clientY: options.clientY ?? 0,
114
+ ...(options.touches ? { touches: options.touches } : {}),
115
+ };
116
+ act(() => {
117
+ void mocks.checkboxProps.current?.onChange({ nativeEvent });
118
+ });
119
+ };
120
+ describe("what the widget renders", () => {
121
+ test("a visible widget shows a checkbox", () => {
122
+ render(props());
123
+ expect(checkbox()).toBeDefined();
124
+ });
125
+ test("an invisible widget shows no checkbox at all", () => {
126
+ render(props({ config: config({ mode: ModeEnum.invisible }) }));
127
+ expect(container.querySelector('[aria-label="human checkbox"]')).toBeNull();
128
+ });
129
+ test("a session with a honeypot question renders the honeypot", () => {
130
+ render(props({ frictionlessState: frictionless({ hp: "question" }) }));
131
+ expect(honeypotInput()).toBeDefined();
132
+ expect(mocks.honeypotQuestions.at(-1)).toBe("question");
133
+ });
134
+ test("a session without one renders no bait at all", () => {
135
+ render(props({ frictionlessState: frictionless() }));
136
+ expect(container.querySelector('input[name="honeypot"]')).toBeNull();
137
+ });
138
+ test("an invisible widget still renders the honeypot, as bait", () => {
139
+ render(props({
140
+ config: config({ mode: ModeEnum.invisible }),
141
+ frictionlessState: frictionless({ hp: "question" }),
142
+ }));
143
+ expect(honeypotInput()).toBeDefined();
144
+ });
145
+ test("the manager can read the honeypot input the widget rendered", () => {
146
+ render(props({ frictionlessState: frictionless({ hp: "question" }) }));
147
+ honeypotInput().value = "bot@example.com";
148
+ expect(mocks.constructions[0]?.getHoneypotValue?.()).toBe("bot@example.com");
149
+ });
150
+ test("a dark-themed widget still renders its checkbox", () => {
151
+ render(props({ config: config({ theme: "dark" }) }));
152
+ expect(checkbox()).toBeDefined();
153
+ });
154
+ test("the checkbox is labelled once the translations are ready", () => {
155
+ render(props());
156
+ expect(mocks.checkboxProps.current?.labelText).toBe("WIDGET.I_AM_HUMAN");
157
+ });
158
+ test("the checkbox is left unlabelled until the translations load", () => {
159
+ mocks.translationsReady.current = false;
160
+ render(props());
161
+ expect(mocks.checkboxProps.current?.labelText).toBe("");
162
+ });
163
+ test("a page that registered no callbacks still renders", () => {
164
+ render(props({
165
+ callbacks: undefined,
166
+ }));
167
+ expect(checkbox()).toBeDefined();
168
+ });
169
+ test("the checkbox shows the current error", () => {
170
+ render(props());
171
+ act(() => {
172
+ mocks.constructions[0]?.updateState({
173
+ error: { message: "no session", key: "API.UNKNOWN_ERROR" },
174
+ });
175
+ });
176
+ expect(mocks.checkboxProps.current?.error).toBe("no session");
177
+ });
178
+ test("an unfilled honeypot reads as nothing, not as an empty answer", () => {
179
+ render(props({ frictionlessState: frictionless({ hp: "question" }) }));
180
+ expect(mocks.constructions[0]?.getHoneypotValue?.()).toBeUndefined();
181
+ });
182
+ test("with no honeypot rendered the reader still answers safely", () => {
183
+ render(props());
184
+ expect(mocks.constructions[0]?.getHoneypotValue?.()).toBeUndefined();
185
+ });
186
+ });
187
+ describe("starting a solve", () => {
188
+ test("a click starts the manager with the coordinates of the click", () => {
189
+ render(props());
190
+ click({ clientX: 12, clientY: 34 });
191
+ expect(mocks.start).toHaveBeenCalledWith(12, 34);
192
+ });
193
+ test("a tap is read from the touch that produced it", () => {
194
+ render(props());
195
+ click({ touches: [{ clientX: 7, clientY: 9 }] });
196
+ expect(mocks.start).toHaveBeenCalledWith(7, 9);
197
+ });
198
+ test("a tap with no touches falls back to the pointer coordinates", () => {
199
+ render(props());
200
+ click({ touches: [], clientX: 3, clientY: 4 });
201
+ expect(mocks.start).toHaveBeenCalledWith(3, 4);
202
+ });
203
+ test("an untrusted click solves, but its coordinates are discarded", () => {
204
+ render(props());
205
+ click({ trusted: false, clientX: 12, clientY: 34 });
206
+ expect(mocks.start).toHaveBeenCalledWith(0, 0);
207
+ });
208
+ test("an event that reports no position at all is treated as the origin", () => {
209
+ render(props());
210
+ act(() => {
211
+ void mocks.checkboxProps.current?.onChange({
212
+ nativeEvent: { isTrusted: true },
213
+ });
214
+ });
215
+ expect(mocks.start).toHaveBeenCalledWith(0, 0);
216
+ });
217
+ test("the checkbox shows a spinner for as long as the solve runs", async () => {
218
+ let release = () => undefined;
219
+ mocks.start.mockImplementation(() => new Promise((resolve) => {
220
+ release = () => resolve();
221
+ }));
222
+ render(props());
223
+ click();
224
+ expect(mocks.checkboxProps.current?.loading).toBe(true);
225
+ await act(async () => {
226
+ release();
227
+ });
228
+ expect(mocks.checkboxProps.current?.loading).toBe(false);
229
+ });
230
+ test("a solve that rejects still clears the spinner", async () => {
231
+ vi.spyOn(console, "error").mockImplementation(() => undefined);
232
+ mocks.start.mockRejectedValue(new Error("provider down"));
233
+ render(props({ autoStart: true }));
234
+ await act(async () => undefined);
235
+ expect(mocks.checkboxProps.current?.loading).toBe(false);
236
+ });
237
+ test("a click whose solve rejects clears the spinner too", async () => {
238
+ vi.spyOn(console, "error").mockImplementation(() => undefined);
239
+ mocks.start.mockRejectedValue(new Error("provider down"));
240
+ render(props());
241
+ await act(async () => {
242
+ await mocks.checkboxProps.current?.onChange({
243
+ nativeEvent: { isTrusted: true, clientX: 1, clientY: 2 },
244
+ });
245
+ });
246
+ expect(mocks.checkboxProps.current?.loading).toBe(false);
247
+ });
248
+ test("a second click while the first solve is running is ignored", async () => {
249
+ let release = () => undefined;
250
+ mocks.start.mockImplementation(() => new Promise((resolve) => {
251
+ release = () => resolve();
252
+ }));
253
+ render(props());
254
+ click();
255
+ click();
256
+ expect(mocks.start).toHaveBeenCalledTimes(1);
257
+ await act(async () => {
258
+ release();
259
+ });
260
+ });
261
+ test("an autoStart widget solves without waiting for a click", () => {
262
+ render(props({ autoStart: true }));
263
+ expect(mocks.start).toHaveBeenCalledWith(0, 0);
264
+ });
265
+ test("an autoStart widget resumes with the coordinates it was handed", () => {
266
+ render(props({ autoStart: true, startCoords: { x: 5, y: 6 } }));
267
+ expect(mocks.start).toHaveBeenCalledWith(5, 6);
268
+ });
269
+ test("a widget that was not asked to autoStart stays idle", () => {
270
+ render(props());
271
+ expect(mocks.start).not.toHaveBeenCalled();
272
+ });
273
+ });
274
+ describe("the invisible-mode execute event", () => {
275
+ const execute = () => {
276
+ act(() => {
277
+ document.dispatchEvent(new Event("procaptcha:execute"));
278
+ });
279
+ };
280
+ test("starts a solve", () => {
281
+ render(props({ config: config({ mode: ModeEnum.invisible }) }));
282
+ execute();
283
+ expect(mocks.start).toHaveBeenCalledTimes(1);
284
+ });
285
+ test("is ignored by a visible widget", () => {
286
+ render(props());
287
+ execute();
288
+ expect(mocks.start).not.toHaveBeenCalled();
289
+ });
290
+ test("stops being listened for once the widget is gone", () => {
291
+ render(props({ config: config({ mode: ModeEnum.invisible }) }));
292
+ act(() => {
293
+ root.unmount();
294
+ root = createRoot(container);
295
+ });
296
+ execute();
297
+ expect(mocks.start).not.toHaveBeenCalled();
298
+ });
299
+ test("a manager that throws on start does not take the page down with it", () => {
300
+ vi.spyOn(console, "error").mockImplementation(() => undefined);
301
+ mocks.start.mockImplementation(() => {
302
+ throw new Error("no provider");
303
+ });
304
+ render(props({ config: config({ mode: ModeEnum.invisible }) }));
305
+ expect(execute).not.toThrow();
306
+ });
307
+ test("a solve that rejects is reported rather than left unhandled", async () => {
308
+ const reported = vi
309
+ .spyOn(console, "error")
310
+ .mockImplementation(() => undefined);
311
+ mocks.start.mockRejectedValue(new Error("no provider"));
312
+ render(props({ config: config({ mode: ModeEnum.invisible }) }));
313
+ execute();
314
+ await act(async () => undefined);
315
+ expect(reported).toHaveBeenCalled();
316
+ });
317
+ });
318
+ describe("an invalidated session", () => {
319
+ const fail = (key) => {
320
+ act(() => {
321
+ mocks.constructions[0]?.updateState({
322
+ error: { message: "boom", key },
323
+ });
324
+ });
325
+ };
326
+ test("is handed to the recovery-aware parent, with the original click", () => {
327
+ const onSessionInvalidated = vi.fn();
328
+ render(props({ onSessionInvalidated }));
329
+ click({ clientX: 9, clientY: 8 });
330
+ fail("CAPTCHA.NO_SESSION_FOUND");
331
+ expect(onSessionInvalidated).toHaveBeenCalledWith(9, 8);
332
+ });
333
+ test("is escalated once only, so a failing retry cannot loop", () => {
334
+ const onSessionInvalidated = vi.fn();
335
+ const restart = vi.fn();
336
+ vi.useFakeTimers();
337
+ render(props({
338
+ onSessionInvalidated,
339
+ frictionlessState: frictionless({ restart }),
340
+ }));
341
+ fail("CAPTCHA.NO_SESSION_FOUND");
342
+ act(() => {
343
+ mocks.constructions[0]?.updateState({ error: undefined });
344
+ });
345
+ fail("CAPTCHA.NO_SESSION_FOUND");
346
+ expect(onSessionInvalidated).toHaveBeenCalledTimes(1);
347
+ act(() => {
348
+ vi.advanceTimersByTime(100);
349
+ });
350
+ expect(restart).toHaveBeenCalledTimes(1);
351
+ vi.useRealTimers();
352
+ });
353
+ test("without a recovery-aware parent the frictionless session restarts", () => {
354
+ const restart = vi.fn();
355
+ vi.useFakeTimers();
356
+ render(props({ frictionlessState: frictionless({ restart }) }));
357
+ fail("CAPTCHA.NO_SESSION_FOUND");
358
+ expect(restart).not.toHaveBeenCalled();
359
+ act(() => {
360
+ vi.advanceTimersByTime(100);
361
+ });
362
+ expect(restart).toHaveBeenCalledTimes(1);
363
+ vi.useRealTimers();
364
+ });
365
+ test("any other error is left for the widget to display", () => {
366
+ const onSessionInvalidated = vi.fn();
367
+ const restart = vi.fn();
368
+ render(props({
369
+ onSessionInvalidated,
370
+ frictionlessState: frictionless({ restart }),
371
+ }));
372
+ fail("API.UNKNOWN_ERROR");
373
+ expect(onSessionInvalidated).not.toHaveBeenCalled();
374
+ expect(restart).not.toHaveBeenCalled();
375
+ });
376
+ test("an error with nowhere to escalate to is simply shown", () => {
377
+ render(props());
378
+ expect(() => fail("CAPTCHA.NO_SESSION_FOUND")).not.toThrow();
379
+ });
380
+ });
381
+ describe("language", () => {
382
+ test("a configured language with no i18n instance boots one", () => {
383
+ render(props({ config: config({ language: "fr" }) }));
384
+ expect(mocks.loadI18next).toHaveBeenCalledWith(false, "fr");
385
+ });
386
+ test("an existing i18n instance is switched rather than re-booted", () => {
387
+ const changeLanguage = vi.fn();
388
+ render(props({
389
+ config: config({ language: "fr" }),
390
+ i18n: i18nStub("en", changeLanguage),
391
+ }));
392
+ expect(changeLanguage).toHaveBeenCalledWith("fr");
393
+ expect(mocks.loadI18next).not.toHaveBeenCalled();
394
+ });
395
+ test("an instance already in the right language is left alone", () => {
396
+ const changeLanguage = vi.fn();
397
+ render(props({
398
+ config: config({ language: "fr" }),
399
+ i18n: i18nStub("fr", changeLanguage),
400
+ }));
401
+ expect(changeLanguage).not.toHaveBeenCalled();
402
+ });
403
+ test("no configured language means the page's own choice stands", () => {
404
+ const changeLanguage = vi.fn();
405
+ render(props({ i18n: i18nStub("en", changeLanguage) }));
406
+ expect(changeLanguage).not.toHaveBeenCalled();
407
+ expect(mocks.loadI18next).not.toHaveBeenCalled();
408
+ });
409
+ });
410
+ //# sourceMappingURL=procaptchaWidget.unit.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"procaptchaWidget.unit.test.js","sourceRoot":"","sources":["../../src/tests/procaptchaWidget.unit.test.ts"],"names":[],"mappings":"AAeA,OAAO,EACN,QAAQ,GAGR,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAqB,GAAG,EAAE,aAAa,EAAE,MAAM,OAAO,CAAC;AAC9D,OAAO,EAAa,UAAU,EAAE,MAAM,kBAAkB,CAAC;AACzD,OAAO,EAEN,SAAS,EACT,UAAU,EACV,QAAQ,EACR,MAAM,EACN,IAAI,EACJ,EAAE,GACF,MAAM,QAAQ,CAAC;AAChB,OAAO,UAAU,MAAM,mCAAmC,CAAC;AAC3D,OAAO,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAO3D,MAAM,KAAK,GAAG,EAAE,CAAC,OAAO,CAAC,GAAG,EAAE;IAC7B,MAAM,KAAK,GAAG,EAAE,CAAC,EAAE,EAA6C,CAAC;IACjE,MAAM,UAAU,GAAG,EAAE,CAAC,EAAE,EAAc,CAAC;IACvC,MAAM,aAAa,GAGb,EAAE,CAAC;IACT,MAAM,WAAW,GAAG,EAAE,CAAC,EAAE,EAAiD,CAAC;IAC3E,MAAM,aAAa,GAUf,EAAE,OAAO,EAAE,SAAS,EAAE,CAAC;IAC3B,MAAM,iBAAiB,GAAa,EAAE,CAAC;IACvC,MAAM,iBAAiB,GAAG,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;IAC5C,OAAO;QACN,iBAAiB;QACjB,KAAK;QACL,UAAU;QACV,aAAa;QACb,WAAW;QACX,aAAa;QACb,iBAAiB;KACjB,CAAC;AACH,CAAC,CAAC,CAAC;AAEH,EAAE,CAAC,IAAI,CAAC,wBAAwB,EAAE,GAAG,EAAE,CAAC,CAAC;IACxC,OAAO,EAAE,CACR,OAAgB,EAChB,MAAuB,EACvB,WAAqD,EACrD,UAAmB,EACnB,kBAA2B,EAC3B,WAAoB,EACpB,gBAA2C,EAC1C,EAAE;QACH,KAAK,CAAC,aAAa,CAAC,IAAI,CAAC,EAAE,WAAW,EAAE,gBAAgB,EAAE,CAAC,CAAC;QAC5D,OAAO,EAAE,KAAK,EAAE,KAAK,CAAC,KAAK,EAAE,UAAU,EAAE,KAAK,CAAC,UAAU,EAAE,CAAC;IAC7D,CAAC;CACD,CAAC,CAAC,CAAC;AAOJ,EAAE,CAAC,IAAI,CAAC,4BAA4B,EAAE,KAAK,EAAE,cAAc,EAAE,EAAE;IAC9D,MAAM,MAAM,GACX,MAAM,cAAc,EAA+C,CAAC;IACrE,MAAM,EAAE,aAAa,EAAE,UAAU,EAAE,GAAG,MAAM,MAAM,CAAC,OAAO,CAAC,CAAC;IAQ5D,MAAM,QAAQ,GAAG,CAAC,KAAwB,EAAE,EAAE;QAC7C,KAAK,CAAC,aAAa,CAAC,OAAO,GAAG,KAAK,CAAC;QACpC,OAAO,aAAa,CAAC,OAAO,EAAE;YAC7B,IAAI,EAAE,UAAU;YAChB,QAAQ,EAAE,IAAI;YACd,OAAO,EAAE,KAAK,CAAC,OAAO;YACtB,YAAY,EAAE,KAAK,CAAC,SAAS;YAC7B,YAAY,EAAE,KAAK,CAAC,KAAK;YACzB,cAAc,EAAE,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC;SACrC,CAAC,CAAC;IACJ,CAAC,CAAC;IACF,MAAM,QAAQ,GAAG,UAAU,CAC1B,CAAC,EAAE,eAAe,EAAE,EAAE,GAAG,EAAE,EAAE;QAC5B,KAAK,CAAC,iBAAiB,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC;QAC9C,OAAO,aAAa,CAAC,OAAO,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,IAAI,EAAE,UAAU,EAAE,CAAC,CAAC;IACxE,CAAC,CACD,CAAC;IACF,OAAO,EAAE,GAAG,MAAM,EAAE,QAAQ,EAAE,QAAQ,EAAE,CAAC;AAC1C,CAAC,CAAC,CAAC;AAEH,EAAE,CAAC,IAAI,CAAC,iBAAiB,EAAE,KAAK,EAAE,cAAc,EAAE,EAAE;IACnD,MAAM,MAAM,GAAG,MAAM,cAAc,EAAoC,CAAC;IACxE,OAAO;QACN,GAAG,MAAM;QACT,WAAW,EAAE,KAAK,CAAC,WAAW;QAC9B,cAAc,EAAE,GAAG,EAAE,CAAC,CAAC;YACtB,CAAC,EAAE,CAAC,GAAW,EAAE,EAAE,CAAC,GAAG;YACvB,KAAK,EAAE,KAAK,CAAC,iBAAiB,CAAC,OAAO;SACtC,CAAC;KACF,CAAC;AACH,CAAC,CAAC,CAAC;AAEH,IAAI,SAAyB,CAAC;AAC9B,IAAI,IAAU,CAAC;AAEf,MAAM,QAAQ,GAAG,CAChB,QAAgB,EAChB,cAAyC,EACxC,EAAE,CAAC,CAAC,EAAE,QAAQ,EAAE,cAAc,EAAE,CAAqB,CAAC;AAExD,MAAM,KAAK,GAAG,CAAC,YAAsC,EAAE,EAAmB,EAAE,CAAC,CAAC;IAC7E,MAAM,EAAE,MAAM,EAAE;IAChB,SAAS,EAAE,EAAE;IACb,IAAI,EAAE,SAA6B;IACnC,GAAG,SAAS;CACZ,CAAC,CAAC;AAEH,MAAM,MAAM,GAAG,CAAC,WAA4B,EAAQ,EAAE;IACrD,GAAG,CAAC,GAAG,EAAE;QACR,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,UAAU,EAAE,WAAW,CAAiB,CAAC,CAAC;IACrE,CAAC,CAAC,CAAC;AACJ,CAAC,CAAC;AAEF,UAAU,CAAC,GAAG,EAAE;IACf,EAAE,CAAC,aAAa,EAAE,CAAC;IACnB,KAAK,CAAC,aAAa,CAAC,MAAM,GAAG,CAAC,CAAC;IAC/B,KAAK,CAAC,iBAAiB,CAAC,MAAM,GAAG,CAAC,CAAC;IACnC,KAAK,CAAC,iBAAiB,CAAC,OAAO,GAAG,IAAI,CAAC;IACvC,KAAK,CAAC,aAAa,CAAC,OAAO,GAAG,SAAS,CAAC;IACxC,KAAK,CAAC,KAAK,CAAC,iBAAiB,CAAC,SAAS,CAAC,CAAC;IACzC,KAAK,CAAC,WAAW,CAAC,iBAAiB,CAAC,SAAS,CAAC,CAAC;IAC/C,SAAS,GAAG,QAAQ,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC;IAC1C,QAAQ,CAAC,IAAI,CAAC,WAAW,CAAC,SAAS,CAAC,CAAC;IACrC,GAAG,CAAC,GAAG,EAAE;QACR,IAAI,GAAG,UAAU,CAAC,SAAS,CAAC,CAAC;IAC9B,CAAC,CAAC,CAAC;AACJ,CAAC,CAAC,CAAC;AAEH,SAAS,CAAC,GAAG,EAAE;IACd,GAAG,CAAC,GAAG,EAAE;QACR,IAAI,CAAC,OAAO,EAAE,CAAC;IAChB,CAAC,CAAC,CAAC;IACH,SAAS,CAAC,MAAM,EAAE,CAAC;IACnB,EAAE,CAAC,eAAe,EAAE,CAAC;AACtB,CAAC,CAAC,CAAC;AAEH,MAAM,QAAQ,GAAG,GAAqB,EAAE;IACvC,MAAM,OAAO,GAAG,SAAS,CAAC,aAAa,CACtC,wBAAwB,CACxB,CAAC;IACF,IAAI,CAAC,OAAO;QAAE,MAAM,IAAI,KAAK,CAAC,oCAAoC,CAAC,CAAC;IACpE,OAAO,OAAO,CAAC;AAChB,CAAC,CAAC;AAEF,MAAM,aAAa,GAAG,GAAqB,EAAE;IAC5C,MAAM,OAAO,GAAG,SAAS,CAAC,aAAa,CACtC,wBAAwB,CACxB,CAAC;IACF,IAAI,CAAC,OAAO;QAAE,MAAM,IAAI,KAAK,CAAC,oCAAoC,CAAC,CAAC;IACpE,OAAO,OAAO,CAAC;AAChB,CAAC,CAAC;AAUF,MAAM,KAAK,GAAG,CAAC,UAAwB,EAAE,EAAQ,EAAE;IAClD,MAAM,WAAW,GAAG;QACnB,SAAS,EAAE,OAAO,CAAC,OAAO,IAAI,IAAI;QAClC,OAAO,EAAE,OAAO,CAAC,OAAO,IAAI,CAAC;QAC7B,OAAO,EAAE,OAAO,CAAC,OAAO,IAAI,CAAC;QAC7B,GAAG,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,OAAO,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KACxD,CAAC;IACF,GAAG,CAAC,GAAG,EAAE;QACR,KAAK,KAAK,CAAC,aAAa,CAAC,OAAO,EAAE,QAAQ,CAAC,EAAE,WAAW,EAAE,CAAC,CAAC;IAC7D,CAAC,CAAC,CAAC;AACJ,CAAC,CAAC;AAEF,QAAQ,CAAC,yBAAyB,EAAE,GAAG,EAAE;IACxC,IAAI,CAAC,mCAAmC,EAAE,GAAG,EAAE;QAC9C,MAAM,CAAC,KAAK,EAAE,CAAC,CAAC;QAChB,MAAM,CAAC,QAAQ,EAAE,CAAC,CAAC,WAAW,EAAE,CAAC;IAClC,CAAC,CAAC,CAAC;IAEH,IAAI,CAAC,8CAA8C,EAAE,GAAG,EAAE;QACzD,MAAM,CAAC,KAAK,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,IAAI,EAAE,QAAQ,CAAC,SAAS,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;QAChE,MAAM,CAAC,SAAS,CAAC,aAAa,CAAC,+BAA+B,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC;IAC7E,CAAC,CAAC,CAAC;IAEH,IAAI,CAAC,yDAAyD,EAAE,GAAG,EAAE;QACpE,MAAM,CAAC,KAAK,CAAC,EAAE,iBAAiB,EAAE,YAAY,CAAC,EAAE,EAAE,EAAE,UAAU,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;QACvE,MAAM,CAAC,aAAa,EAAE,CAAC,CAAC,WAAW,EAAE,CAAC;QACtC,MAAM,CAAC,KAAK,CAAC,iBAAiB,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;IACzD,CAAC,CAAC,CAAC;IAEH,IAAI,CAAC,8CAA8C,EAAE,GAAG,EAAE;QACzD,MAAM,CAAC,KAAK,CAAC,EAAE,iBAAiB,EAAE,YAAY,EAAE,EAAE,CAAC,CAAC,CAAC;QACrD,MAAM,CAAC,SAAS,CAAC,aAAa,CAAC,wBAAwB,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC;IACtE,CAAC,CAAC,CAAC;IAEH,IAAI,CAAC,yDAAyD,EAAE,GAAG,EAAE;QACpE,MAAM,CACL,KAAK,CAAC;YACL,MAAM,EAAE,MAAM,CAAC,EAAE,IAAI,EAAE,QAAQ,CAAC,SAAS,EAAE,CAAC;YAC5C,iBAAiB,EAAE,YAAY,CAAC,EAAE,EAAE,EAAE,UAAU,EAAE,CAAC;SACnD,CAAC,CACF,CAAC;QACF,MAAM,CAAC,aAAa,EAAE,CAAC,CAAC,WAAW,EAAE,CAAC;IACvC,CAAC,CAAC,CAAC;IAEH,IAAI,CAAC,6DAA6D,EAAE,GAAG,EAAE;QACxE,MAAM,CAAC,KAAK,CAAC,EAAE,iBAAiB,EAAE,YAAY,CAAC,EAAE,EAAE,EAAE,UAAU,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;QACvE,aAAa,EAAE,CAAC,KAAK,GAAG,iBAAiB,CAAC;QAC1C,MAAM,CAAC,KAAK,CAAC,aAAa,CAAC,CAAC,CAAC,EAAE,gBAAgB,EAAE,EAAE,CAAC,CAAC,IAAI,CACxD,iBAAiB,CACjB,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,IAAI,CAAC,iDAAiD,EAAE,GAAG,EAAE;QAC5D,MAAM,CAAC,KAAK,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;QACrD,MAAM,CAAC,QAAQ,EAAE,CAAC,CAAC,WAAW,EAAE,CAAC;IAClC,CAAC,CAAC,CAAC;IAEH,IAAI,CAAC,0DAA0D,EAAE,GAAG,EAAE;QACrE,MAAM,CAAC,KAAK,EAAE,CAAC,CAAC;QAChB,MAAM,CAAC,KAAK,CAAC,aAAa,CAAC,OAAO,EAAE,SAAS,CAAC,CAAC,IAAI,CAAC,mBAAmB,CAAC,CAAC;IAC1E,CAAC,CAAC,CAAC;IAEH,IAAI,CAAC,6DAA6D,EAAE,GAAG,EAAE;QAExE,KAAK,CAAC,iBAAiB,CAAC,OAAO,GAAG,KAAK,CAAC;QACxC,MAAM,CAAC,KAAK,EAAE,CAAC,CAAC;QAChB,MAAM,CAAC,KAAK,CAAC,aAAa,CAAC,OAAO,EAAE,SAAS,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACzD,CAAC,CAAC,CAAC;IAEH,IAAI,CAAC,mDAAmD,EAAE,GAAG,EAAE;QAG9D,MAAM,CACL,KAAK,CAAC;YACL,SAAS,EAAE,SAAoD;SAC/D,CAAC,CACF,CAAC;QACF,MAAM,CAAC,QAAQ,EAAE,CAAC,CAAC,WAAW,EAAE,CAAC;IAClC,CAAC,CAAC,CAAC;IAEH,IAAI,CAAC,sCAAsC,EAAE,GAAG,EAAE;QACjD,MAAM,CAAC,KAAK,EAAE,CAAC,CAAC;QAChB,GAAG,CAAC,GAAG,EAAE;YACR,KAAK,CAAC,aAAa,CAAC,CAAC,CAAC,EAAE,WAAW,CAAC;gBACnC,KAAK,EAAE,EAAE,OAAO,EAAE,YAAY,EAAE,GAAG,EAAE,mBAAmB,EAAE;aAC1D,CAAC,CAAC;QACJ,CAAC,CAAC,CAAC;QACH,MAAM,CAAC,KAAK,CAAC,aAAa,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;IAC/D,CAAC,CAAC,CAAC;IAEH,IAAI,CAAC,+DAA+D,EAAE,GAAG,EAAE;QAC1E,MAAM,CAAC,KAAK,CAAC,EAAE,iBAAiB,EAAE,YAAY,CAAC,EAAE,EAAE,EAAE,UAAU,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;QACvE,MAAM,CAAC,KAAK,CAAC,aAAa,CAAC,CAAC,CAAC,EAAE,gBAAgB,EAAE,EAAE,CAAC,CAAC,aAAa,EAAE,CAAC;IACtE,CAAC,CAAC,CAAC;IAEH,IAAI,CAAC,2DAA2D,EAAE,GAAG,EAAE;QACtE,MAAM,CAAC,KAAK,EAAE,CAAC,CAAC;QAChB,MAAM,CAAC,KAAK,CAAC,aAAa,CAAC,CAAC,CAAC,EAAE,gBAAgB,EAAE,EAAE,CAAC,CAAC,aAAa,EAAE,CAAC;IACtE,CAAC,CAAC,CAAC;AACJ,CAAC,CAAC,CAAC;AAEH,QAAQ,CAAC,kBAAkB,EAAE,GAAG,EAAE;IACjC,IAAI,CAAC,8DAA8D,EAAE,GAAG,EAAE;QACzE,MAAM,CAAC,KAAK,EAAE,CAAC,CAAC;QAChB,KAAK,CAAC,EAAE,OAAO,EAAE,EAAE,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC,CAAC;QACpC,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,oBAAoB,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC;IAClD,CAAC,CAAC,CAAC;IAEH,IAAI,CAAC,+CAA+C,EAAE,GAAG,EAAE;QAC1D,MAAM,CAAC,KAAK,EAAE,CAAC,CAAC;QAChB,KAAK,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;QACjD,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,oBAAoB,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IAChD,CAAC,CAAC,CAAC;IAEH,IAAI,CAAC,6DAA6D,EAAE,GAAG,EAAE;QACxE,MAAM,CAAC,KAAK,EAAE,CAAC,CAAC;QAChB,KAAK,CAAC,EAAE,OAAO,EAAE,EAAE,EAAE,OAAO,EAAE,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,CAAC,CAAC;QAC/C,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,oBAAoB,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IAChD,CAAC,CAAC,CAAC;IAEH,IAAI,CAAC,8DAA8D,EAAE,GAAG,EAAE;QAGzE,MAAM,CAAC,KAAK,EAAE,CAAC,CAAC;QAChB,KAAK,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC,CAAC;QACpD,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,oBAAoB,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IAChD,CAAC,CAAC,CAAC;IAEH,IAAI,CAAC,mEAAmE,EAAE,GAAG,EAAE;QAC9E,MAAM,CAAC,KAAK,EAAE,CAAC,CAAC;QAChB,GAAG,CAAC,GAAG,EAAE;YACR,KAAK,KAAK,CAAC,aAAa,CAAC,OAAO,EAAE,QAAQ,CAAC;gBAC1C,WAAW,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE;aAChC,CAAC,CAAC;QACJ,CAAC,CAAC,CAAC;QACH,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,oBAAoB,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IAChD,CAAC,CAAC,CAAC;IAEH,IAAI,CAAC,4DAA4D,EAAE,KAAK,IAAI,EAAE;QAC7E,IAAI,OAAO,GAAG,GAAS,EAAE,CAAC,SAAS,CAAC;QACpC,KAAK,CAAC,KAAK,CAAC,kBAAkB,CAC7B,GAAG,EAAE,CACJ,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,EAAE;YAC7B,OAAO,GAAG,GAAG,EAAE,CAAC,OAAO,EAAE,CAAC;QAC3B,CAAC,CAAC,CACH,CAAC;QACF,MAAM,CAAC,KAAK,EAAE,CAAC,CAAC;QAChB,KAAK,EAAE,CAAC;QACR,MAAM,CAAC,KAAK,CAAC,aAAa,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACxD,MAAM,GAAG,CAAC,KAAK,IAAI,EAAE;YACpB,OAAO,EAAE,CAAC;QACX,CAAC,CAAC,CAAC;QACH,MAAM,CAAC,KAAK,CAAC,aAAa,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAC1D,CAAC,CAAC,CAAC;IAEH,IAAI,CAAC,+CAA+C,EAAE,KAAK,IAAI,EAAE;QAGhE,EAAE,CAAC,KAAK,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC,kBAAkB,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC;QAC/D,KAAK,CAAC,KAAK,CAAC,iBAAiB,CAAC,IAAI,KAAK,CAAC,eAAe,CAAC,CAAC,CAAC;QAC1D,MAAM,CAAC,KAAK,CAAC,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;QACnC,MAAM,GAAG,CAAC,KAAK,IAAI,EAAE,CAAC,SAAS,CAAC,CAAC;QACjC,MAAM,CAAC,KAAK,CAAC,aAAa,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAC1D,CAAC,CAAC,CAAC;IAEH,IAAI,CAAC,oDAAoD,EAAE,KAAK,IAAI,EAAE;QACrE,EAAE,CAAC,KAAK,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC,kBAAkB,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC;QAC/D,KAAK,CAAC,KAAK,CAAC,iBAAiB,CAAC,IAAI,KAAK,CAAC,eAAe,CAAC,CAAC,CAAC;QAC1D,MAAM,CAAC,KAAK,EAAE,CAAC,CAAC;QAChB,MAAM,GAAG,CAAC,KAAK,IAAI,EAAE;YACpB,MAAM,KAAK,CAAC,aAAa,CAAC,OAAO,EAAE,QAAQ,CAAC;gBAC3C,WAAW,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE;aACxD,CAAC,CAAC;QACJ,CAAC,CAAC,CAAC;QACH,MAAM,CAAC,KAAK,CAAC,aAAa,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAC1D,CAAC,CAAC,CAAC;IAEH,IAAI,CAAC,4DAA4D,EAAE,KAAK,IAAI,EAAE;QAC7E,IAAI,OAAO,GAAG,GAAS,EAAE,CAAC,SAAS,CAAC;QACpC,KAAK,CAAC,KAAK,CAAC,kBAAkB,CAC7B,GAAG,EAAE,CACJ,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,EAAE;YAC7B,OAAO,GAAG,GAAG,EAAE,CAAC,OAAO,EAAE,CAAC;QAC3B,CAAC,CAAC,CACH,CAAC;QACF,MAAM,CAAC,KAAK,EAAE,CAAC,CAAC;QAChB,KAAK,EAAE,CAAC;QACR,KAAK,EAAE,CAAC;QACR,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,qBAAqB,CAAC,CAAC,CAAC,CAAC;QAC7C,MAAM,GAAG,CAAC,KAAK,IAAI,EAAE;YACpB,OAAO,EAAE,CAAC;QACX,CAAC,CAAC,CAAC;IACJ,CAAC,CAAC,CAAC;IAEH,IAAI,CAAC,wDAAwD,EAAE,GAAG,EAAE;QACnE,MAAM,CAAC,KAAK,CAAC,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;QACnC,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,oBAAoB,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IAChD,CAAC,CAAC,CAAC;IAEH,IAAI,CAAC,gEAAgE,EAAE,GAAG,EAAE;QAC3E,MAAM,CAAC,KAAK,CAAC,EAAE,SAAS,EAAE,IAAI,EAAE,WAAW,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC;QAChE,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,oBAAoB,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IAChD,CAAC,CAAC,CAAC;IAEH,IAAI,CAAC,qDAAqD,EAAE,GAAG,EAAE;QAChE,MAAM,CAAC,KAAK,EAAE,CAAC,CAAC;QAChB,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,gBAAgB,EAAE,CAAC;IAC5C,CAAC,CAAC,CAAC;AACJ,CAAC,CAAC,CAAC;AAEH,QAAQ,CAAC,kCAAkC,EAAE,GAAG,EAAE;IACjD,MAAM,OAAO,GAAG,GAAS,EAAE;QAC1B,GAAG,CAAC,GAAG,EAAE;YACR,QAAQ,CAAC,aAAa,CAAC,IAAI,KAAK,CAAC,oBAAoB,CAAC,CAAC,CAAC;QACzD,CAAC,CAAC,CAAC;IACJ,CAAC,CAAC;IAEF,IAAI,CAAC,gBAAgB,EAAE,GAAG,EAAE;QAC3B,MAAM,CAAC,KAAK,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,IAAI,EAAE,QAAQ,CAAC,SAAS,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;QAChE,OAAO,EAAE,CAAC;QACV,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,qBAAqB,CAAC,CAAC,CAAC,CAAC;IAC9C,CAAC,CAAC,CAAC;IAEH,IAAI,CAAC,gCAAgC,EAAE,GAAG,EAAE;QAC3C,MAAM,CAAC,KAAK,EAAE,CAAC,CAAC;QAChB,OAAO,EAAE,CAAC;QACV,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,gBAAgB,EAAE,CAAC;IAC5C,CAAC,CAAC,CAAC;IAEH,IAAI,CAAC,kDAAkD,EAAE,GAAG,EAAE;QAC7D,MAAM,CAAC,KAAK,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,IAAI,EAAE,QAAQ,CAAC,SAAS,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;QAChE,GAAG,CAAC,GAAG,EAAE;YACR,IAAI,CAAC,OAAO,EAAE,CAAC;YACf,IAAI,GAAG,UAAU,CAAC,SAAS,CAAC,CAAC;QAC9B,CAAC,CAAC,CAAC;QACH,OAAO,EAAE,CAAC;QACV,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,gBAAgB,EAAE,CAAC;IAC5C,CAAC,CAAC,CAAC;IAEH,IAAI,CAAC,oEAAoE,EAAE,GAAG,EAAE;QAC/E,EAAE,CAAC,KAAK,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC,kBAAkB,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC;QAC/D,KAAK,CAAC,KAAK,CAAC,kBAAkB,CAAC,GAAG,EAAE;YACnC,MAAM,IAAI,KAAK,CAAC,aAAa,CAAC,CAAC;QAChC,CAAC,CAAC,CAAC;QACH,MAAM,CAAC,KAAK,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,IAAI,EAAE,QAAQ,CAAC,SAAS,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;QAChE,MAAM,CAAC,OAAO,CAAC,CAAC,GAAG,CAAC,OAAO,EAAE,CAAC;IAC/B,CAAC,CAAC,CAAC;IAEH,IAAI,CAAC,6DAA6D,EAAE,KAAK,IAAI,EAAE;QAC9E,MAAM,QAAQ,GAAG,EAAE;aACjB,KAAK,CAAC,OAAO,EAAE,OAAO,CAAC;aACvB,kBAAkB,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC;QACtC,KAAK,CAAC,KAAK,CAAC,iBAAiB,CAAC,IAAI,KAAK,CAAC,aAAa,CAAC,CAAC,CAAC;QACxD,MAAM,CAAC,KAAK,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,IAAI,EAAE,QAAQ,CAAC,SAAS,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;QAChE,OAAO,EAAE,CAAC;QACV,MAAM,GAAG,CAAC,KAAK,IAAI,EAAE,CAAC,SAAS,CAAC,CAAC;QACjC,MAAM,CAAC,QAAQ,CAAC,CAAC,gBAAgB,EAAE,CAAC;IACrC,CAAC,CAAC,CAAC;AACJ,CAAC,CAAC,CAAC;AAEH,QAAQ,CAAC,wBAAwB,EAAE,GAAG,EAAE;IACvC,MAAM,IAAI,GAAG,CAAC,GAAW,EAAQ,EAAE;QAClC,GAAG,CAAC,GAAG,EAAE;YACR,KAAK,CAAC,aAAa,CAAC,CAAC,CAAC,EAAE,WAAW,CAAC;gBACnC,KAAK,EAAE,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE;aAC/B,CAAC,CAAC;QACJ,CAAC,CAAC,CAAC;IACJ,CAAC,CAAC;IAEF,IAAI,CAAC,iEAAiE,EAAE,GAAG,EAAE;QAC5E,MAAM,oBAAoB,GAAG,EAAE,CAAC,EAAE,EAAoC,CAAC;QACvE,MAAM,CAAC,KAAK,CAAC,EAAE,oBAAoB,EAAE,CAAC,CAAC,CAAC;QACxC,KAAK,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,CAAC,CAAC;QAClC,IAAI,CAAC,0BAA0B,CAAC,CAAC;QACjC,MAAM,CAAC,oBAAoB,CAAC,CAAC,oBAAoB,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IACzD,CAAC,CAAC,CAAC;IAEH,IAAI,CAAC,wDAAwD,EAAE,GAAG,EAAE;QACnE,MAAM,oBAAoB,GAAG,EAAE,CAAC,EAAE,EAAoC,CAAC;QACvE,MAAM,OAAO,GAAG,EAAE,CAAC,EAAE,EAAc,CAAC;QACpC,EAAE,CAAC,aAAa,EAAE,CAAC;QACnB,MAAM,CACL,KAAK,CAAC;YACL,oBAAoB;YACpB,iBAAiB,EAAE,YAAY,CAAC,EAAE,OAAO,EAAE,CAAC;SAC5C,CAAC,CACF,CAAC;QACF,IAAI,CAAC,0BAA0B,CAAC,CAAC;QACjC,GAAG,CAAC,GAAG,EAAE;YACR,KAAK,CAAC,aAAa,CAAC,CAAC,CAAC,EAAE,WAAW,CAAC,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC,CAAC;QAC3D,CAAC,CAAC,CAAC;QACH,IAAI,CAAC,0BAA0B,CAAC,CAAC;QACjC,MAAM,CAAC,oBAAoB,CAAC,CAAC,qBAAqB,CAAC,CAAC,CAAC,CAAC;QACtD,GAAG,CAAC,GAAG,EAAE;YACR,EAAE,CAAC,mBAAmB,CAAC,GAAG,CAAC,CAAC;QAC7B,CAAC,CAAC,CAAC;QACH,MAAM,CAAC,OAAO,CAAC,CAAC,qBAAqB,CAAC,CAAC,CAAC,CAAC;QACzC,EAAE,CAAC,aAAa,EAAE,CAAC;IACpB,CAAC,CAAC,CAAC;IAEH,IAAI,CAAC,mEAAmE,EAAE,GAAG,EAAE;QAC9E,MAAM,OAAO,GAAG,EAAE,CAAC,EAAE,EAAc,CAAC;QACpC,EAAE,CAAC,aAAa,EAAE,CAAC;QACnB,MAAM,CAAC,KAAK,CAAC,EAAE,iBAAiB,EAAE,YAAY,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;QAChE,IAAI,CAAC,0BAA0B,CAAC,CAAC;QACjC,MAAM,CAAC,OAAO,CAAC,CAAC,GAAG,CAAC,gBAAgB,EAAE,CAAC;QACvC,GAAG,CAAC,GAAG,EAAE;YACR,EAAE,CAAC,mBAAmB,CAAC,GAAG,CAAC,CAAC;QAC7B,CAAC,CAAC,CAAC;QACH,MAAM,CAAC,OAAO,CAAC,CAAC,qBAAqB,CAAC,CAAC,CAAC,CAAC;QACzC,EAAE,CAAC,aAAa,EAAE,CAAC;IACpB,CAAC,CAAC,CAAC;IAEH,IAAI,CAAC,mDAAmD,EAAE,GAAG,EAAE;QAC9D,MAAM,oBAAoB,GAAG,EAAE,CAAC,EAAE,EAAoC,CAAC;QACvE,MAAM,OAAO,GAAG,EAAE,CAAC,EAAE,EAAc,CAAC;QACpC,MAAM,CACL,KAAK,CAAC;YACL,oBAAoB;YACpB,iBAAiB,EAAE,YAAY,CAAC,EAAE,OAAO,EAAE,CAAC;SAC5C,CAAC,CACF,CAAC;QACF,IAAI,CAAC,mBAAmB,CAAC,CAAC;QAC1B,MAAM,CAAC,oBAAoB,CAAC,CAAC,GAAG,CAAC,gBAAgB,EAAE,CAAC;QACpD,MAAM,CAAC,OAAO,CAAC,CAAC,GAAG,CAAC,gBAAgB,EAAE,CAAC;IACxC,CAAC,CAAC,CAAC;IAEH,IAAI,CAAC,sDAAsD,EAAE,GAAG,EAAE;QACjE,MAAM,CAAC,KAAK,EAAE,CAAC,CAAC;QAChB,MAAM,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,0BAA0B,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,EAAE,CAAC;IAC9D,CAAC,CAAC,CAAC;AACJ,CAAC,CAAC,CAAC;AAEH,QAAQ,CAAC,UAAU,EAAE,GAAG,EAAE;IACzB,IAAI,CAAC,uDAAuD,EAAE,GAAG,EAAE;QAClE,MAAM,CAAC,KAAK,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;QACtD,MAAM,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC,oBAAoB,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;IAC7D,CAAC,CAAC,CAAC;IAEH,IAAI,CAAC,6DAA6D,EAAE,GAAG,EAAE;QACxE,MAAM,cAAc,GAAG,EAAE,CAAC,EAAE,EAAuB,CAAC;QACpD,MAAM,CACL,KAAK,CAAC;YACL,MAAM,EAAE,MAAM,CAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;YAClC,IAAI,EAAE,QAAQ,CAAC,IAAI,EAAE,cAAc,CAAC;SACpC,CAAC,CACF,CAAC;QACF,MAAM,CAAC,cAAc,CAAC,CAAC,oBAAoB,CAAC,IAAI,CAAC,CAAC;QAClD,MAAM,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC,GAAG,CAAC,gBAAgB,EAAE,CAAC;IAClD,CAAC,CAAC,CAAC;IAEH,IAAI,CAAC,yDAAyD,EAAE,GAAG,EAAE;QACpE,MAAM,cAAc,GAAG,EAAE,CAAC,EAAE,EAAuB,CAAC;QACpD,MAAM,CACL,KAAK,CAAC;YACL,MAAM,EAAE,MAAM,CAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;YAClC,IAAI,EAAE,QAAQ,CAAC,IAAI,EAAE,cAAc,CAAC;SACpC,CAAC,CACF,CAAC;QACF,MAAM,CAAC,cAAc,CAAC,CAAC,GAAG,CAAC,gBAAgB,EAAE,CAAC;IAC/C,CAAC,CAAC,CAAC;IAEH,IAAI,CAAC,2DAA2D,EAAE,GAAG,EAAE;QACtE,MAAM,cAAc,GAAG,EAAE,CAAC,EAAE,EAAuB,CAAC;QACpD,MAAM,CAAC,KAAK,CAAC,EAAE,IAAI,EAAE,QAAQ,CAAC,IAAI,EAAE,cAAc,CAAC,EAAE,CAAC,CAAC,CAAC;QACxD,MAAM,CAAC,cAAc,CAAC,CAAC,GAAG,CAAC,gBAAgB,EAAE,CAAC;QAC9C,MAAM,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC,GAAG,CAAC,gBAAgB,EAAE,CAAC;IAClD,CAAC,CAAC,CAAC;AACJ,CAAC,CAAC,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@prosopo/procaptcha-pow",
3
- "version": "2.10.23",
3
+ "version": "2.10.25",
4
4
  "author": "PROSOPO LIMITED <info@prosopo.io>",
5
5
  "license": "Apache-2.0",
6
6
  "main": "dist/index.js",
@@ -25,36 +25,41 @@
25
25
  "build:cross-env": "vite build --config vite.esm.config.ts",
26
26
  "build:tsc": "tsc --build --verbose",
27
27
  "build:cjs": "NODE_ENV=${NODE_ENV:-development}; vite build --config vite.cjs.config.ts --mode $NODE_ENV",
28
- "typecheck": "tsc --project tsconfig.types.json"
28
+ "typecheck": "tsc --project tsconfig.types.json",
29
+ "test": "NODE_ENV=${NODE_ENV:-test}; npx vitest run --config ./vite.test.config.ts",
30
+ "test:watch": "NODE_ENV=${NODE_ENV:-test}; npx vitest --config ./vite.test.config.ts",
31
+ "test:coverage": "NODE_ENV=${NODE_ENV:-test}; npx vitest run --coverage --config ./vite.test.config.ts"
29
32
  },
30
33
  "browserslist": ["> 0.5%, last 2 versions, not dead"],
31
34
  "dependencies": {
32
35
  "@polkadot/util": "13.5.7",
33
- "@prosopo/api": "3.5.19",
34
- "@prosopo/common": "3.1.47",
35
- "@prosopo/fingerprint": "2.7.18",
36
- "@prosopo/locale": "3.2.7",
37
- "@prosopo/procaptcha-common": "2.11.17",
38
- "@prosopo/types": "4.9.12",
39
- "@prosopo/util": "3.3.4",
36
+ "@prosopo/api": "3.5.21",
37
+ "@prosopo/common": "3.1.48",
38
+ "@prosopo/fingerprint": "2.7.19",
39
+ "@prosopo/locale": "3.2.8",
40
+ "@prosopo/procaptcha-common": "2.11.18",
41
+ "@prosopo/types": "4.10.0",
42
+ "@prosopo/util": "3.3.5",
40
43
  "@prosopo/util-crypto": "13.5.30",
41
44
  "@prosopo/widget-skeleton": "2.8.4",
42
45
  "react": "18.3.1"
43
46
  },
44
47
  "devDependencies": {
45
- "@prosopo/config": "3.3.4",
46
48
  "@emotion/react": "11.11.1",
47
49
  "@emotion/styled": "11.11.0",
50
+ "@prosopo/config": "3.3.5",
48
51
  "@types/node": "22.10.2",
49
- "@vitest/coverage-v8": "3.2.4",
52
+ "@vitest/coverage-v8": "4.1.10",
50
53
  "concurrently": "9.0.1",
51
54
  "del-cli": "6.0.0",
55
+ "jsdom": "26.1.0",
52
56
  "npm-run-all": "4.1.5",
57
+ "react-dom": "18.3.1",
53
58
  "tslib": "2.7.0",
54
59
  "tsx": "4.20.3",
55
60
  "typescript": "5.6.2",
56
- "vite": "6.4.1",
57
- "vitest": "3.2.4"
61
+ "vite": "8.1.5",
62
+ "vitest": "4.1.10"
58
63
  },
59
64
  "repository": {
60
65
  "type": "git",
@@ -76,9 +76,17 @@ const Procaptcha = (props: ProcaptchaProps) => {
76
76
  setLoading(true);
77
77
  const coords = props.startCoords;
78
78
  lastCoordsRef.current = coords ?? null;
79
- manager.current.start(coords?.x ?? 0, coords?.y ?? 0).finally(() => {
80
- setLoading(false);
81
- });
79
+ manager.current
80
+ .start(coords?.x ?? 0, coords?.y ?? 0)
81
+ // The manager handles its own failures, but anything it doesn't (a
82
+ // reset that throws, say) would otherwise escape as an unhandled
83
+ // rejection and leave the widget stuck showing a spinner.
84
+ .catch((error: unknown) => {
85
+ console.error("Error starting PoW verification:", error);
86
+ })
87
+ .finally(() => {
88
+ setLoading(false);
89
+ });
82
90
  }, [props.autoStart, props.startCoords]);
83
91
 
84
92
  useEffect(() => {
@@ -113,7 +121,9 @@ const Procaptcha = (props: ProcaptchaProps) => {
113
121
  // Directly start the verification process without showing any UI
114
122
  try {
115
123
  // Start the PoW verification process
116
- manager.current.start();
124
+ void manager.current.start().catch((error: unknown) => {
125
+ console.error("Error starting PoW verification:", error);
126
+ });
117
127
  } catch (error) {
118
128
  console.error("Error starting PoW verification:", error);
119
129
  }
@@ -181,7 +191,14 @@ const Procaptcha = (props: ProcaptchaProps) => {
181
191
  }
182
192
 
183
193
  lastCoordsRef.current = { x, y };
184
- await manager.current.start(x, y);
194
+ try {
195
+ await manager.current.start(x, y);
196
+ } catch (error) {
197
+ // React ignores the promise this handler returns, so a
198
+ // rejection here would surface as an unhandled rejection and
199
+ // the spinner would never clear.
200
+ console.error("Error starting PoW verification:", error);
201
+ }
185
202
  setLoading(false);
186
203
  }}
187
204
  labelText={isTranslationReady ? t("WIDGET.I_AM_HUMAN") : ""}
@@ -23,11 +23,12 @@ import {
23
23
  import {
24
24
  ExtensionLoader,
25
25
  buildUpdateState,
26
+ getDefaultEvents,
26
27
  getProcaptchaRandomActiveProvider,
28
+ getSimdReadingsForSubmit,
27
29
  pickIpMode,
28
30
  providerRetry,
29
31
  } from "@prosopo/procaptcha-common";
30
- import { getDefaultEvents } from "@prosopo/procaptcha-common";
31
32
  import {
32
33
  type Account,
33
34
  ApiParams,
@@ -337,9 +338,9 @@ export const Manager = (
337
338
  }
338
339
  }
339
340
 
340
- const simdReadings = frictionlessState?.getSimdReadings
341
- ? await frictionlessState.getSimdReadings()
342
- : undefined;
341
+ // Wait 5 secs for ongoing SIMD, else submit without
342
+ const simdReadings =
343
+ await getSimdReadingsForSubmit(frictionlessState);
343
344
  const hpValue = getHoneypotValue?.();
344
345
  const clientMetaData = hpValue ? { hp: hpValue } : undefined;
345
346
  // Best-effort proof of fingerprint; submission proceeds without it
@@ -436,7 +437,10 @@ export const Manager = (
436
437
  }
437
438
  }
438
439
  },
439
- start,
440
+ // Retry with the same coordinates: a bare `start` restarts at the
441
+ // default (0, 0), which reads as "no real click" further down and
442
+ // costs the escalated widget the entry-point telemetry.
443
+ () => start(x, y),
440
444
  () => {
441
445
  resetState();
442
446
  },