@prosopo/procaptcha-puzzle 2.10.39 → 2.10.41

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 (59) hide show
  1. package/.turbo/turbo-build$colon$cjs.log +13 -11
  2. package/.turbo/turbo-build$colon$tsc.log +19 -19
  3. package/.turbo/turbo-build.log +15 -12
  4. package/CHANGELOG.md +41 -0
  5. package/dist/_virtual/_rolldown/runtime.js +3 -0
  6. package/dist/cjs/components/ProcaptchaPuzzle.cjs +6 -9
  7. package/dist/cjs/components/ProcaptchaWidget.cjs +191 -213
  8. package/dist/cjs/components/PuzzleCanvas.cjs +228 -270
  9. package/dist/cjs/index.cjs +2 -4
  10. package/dist/cjs/services/Manager.cjs +209 -289
  11. package/dist/components/ProcaptchaPuzzle.js +6 -8
  12. package/dist/components/ProcaptchaWidget.d.ts.map +1 -1
  13. package/dist/components/ProcaptchaWidget.js +190 -212
  14. package/dist/components/ProcaptchaWidget.js.map +1 -1
  15. package/dist/components/PuzzleCanvas.js +229 -271
  16. package/dist/index.js +2 -4
  17. package/dist/services/Manager.d.ts.map +1 -1
  18. package/dist/services/Manager.js +205 -286
  19. package/dist/services/Manager.js.map +1 -1
  20. package/dist/tests/manager.unit.test.d.ts +2 -0
  21. package/dist/tests/manager.unit.test.d.ts.map +1 -0
  22. package/dist/tests/manager.unit.test.js +506 -0
  23. package/dist/tests/manager.unit.test.js.map +1 -0
  24. package/dist/tests/managerHarness.d.ts +20 -0
  25. package/dist/tests/managerHarness.d.ts.map +1 -0
  26. package/dist/tests/managerHarness.js +86 -0
  27. package/dist/tests/managerHarness.js.map +1 -0
  28. package/dist/tests/procaptchaPuzzle.test-d.d.ts +2 -0
  29. package/dist/tests/procaptchaPuzzle.test-d.d.ts.map +1 -0
  30. package/dist/tests/procaptchaPuzzle.test-d.js +97 -0
  31. package/dist/tests/procaptchaPuzzle.test-d.js.map +1 -0
  32. package/dist/tests/procaptchaPuzzle.unit.test.d.ts +2 -0
  33. package/dist/tests/procaptchaPuzzle.unit.test.d.ts.map +1 -0
  34. package/dist/tests/procaptchaPuzzle.unit.test.js +81 -0
  35. package/dist/tests/procaptchaPuzzle.unit.test.js.map +1 -0
  36. package/dist/tests/procaptchaWidget.unit.test.d.ts +2 -0
  37. package/dist/tests/procaptchaWidget.unit.test.d.ts.map +1 -0
  38. package/dist/tests/procaptchaWidget.unit.test.js +547 -0
  39. package/dist/tests/procaptchaWidget.unit.test.js.map +1 -0
  40. package/dist/tests/puzzleCanvas.unit.test.d.ts +2 -0
  41. package/dist/tests/puzzleCanvas.unit.test.d.ts.map +1 -0
  42. package/dist/tests/puzzleCanvas.unit.test.js +312 -0
  43. package/dist/tests/puzzleCanvas.unit.test.js.map +1 -0
  44. package/dist/tests/setup.d.ts +5 -0
  45. package/dist/tests/setup.d.ts.map +1 -0
  46. package/dist/tests/setup.js +3 -0
  47. package/dist/tests/setup.js.map +1 -0
  48. package/package.json +17 -12
  49. package/src/components/ProcaptchaWidget.tsx +17 -6
  50. package/src/services/Manager.ts +14 -10
  51. package/src/tests/manager.unit.test.ts +763 -0
  52. package/src/tests/managerHarness.ts +169 -0
  53. package/src/tests/procaptchaPuzzle.test-d.ts +191 -0
  54. package/src/tests/procaptchaPuzzle.unit.test.ts +123 -0
  55. package/src/tests/procaptchaWidget.unit.test.ts +789 -0
  56. package/src/tests/puzzleCanvas.unit.test.ts +418 -0
  57. package/src/tests/setup.ts +26 -0
  58. package/tsconfig.tsbuildinfo +1 -1
  59. package/vite.test.config.ts +27 -0
@@ -1,5 +1,5 @@
1
1
 
2
- > @prosopo/procaptcha-puzzle@2.10.39 build:cjs
2
+ > @prosopo/procaptcha-puzzle@2.10.41 build:cjs
3
3
  > NODE_ENV=${NODE_ENV:-development}; vite build --config vite.cjs.config.ts --mode $NODE_ENV
4
4
 
5
5
  ViteCommonJSConfig: .
@@ -39,15 +39,17 @@ ViteCommonJSConfig: .
39
39
  '@prosopo/keyring'
40
40
  ]
41
41
  }
42
- vite v6.4.1 building SSR bundle for production...
42
+ The plugin "vite-tsconfig-paths" is detected. Vite now supports tsconfig paths resolution natively via the resolve.tsconfigPaths option. You can remove the plugin and set resolve.tsconfigPaths: true in your Vite config instead.
43
+ vite v8.1.5 building ssr environment for production...
43
44
  Bundle build started
44
- transforming...
45
- Build end
46
- ✓ 5 modules transformed.
45
+ 
46
+ ✓ 6 modules transformed.
47
47
  rendering chunks...
48
- dist/cjs/index.cjs  0.27 kB
49
- dist/cjs/components/ProcaptchaPuzzle.cjs  0.70 kB
50
- dist/cjs/components/ProcaptchaWidget.cjs  7.33 kB
51
- dist/cjs/components/PuzzleCanvas.cjs 10.24 kB
52
- dist/cjs/services/Manager.cjs 10.38 kB
53
- ✓ built in 257ms
48
+ computing gzip size...
49
+ dist/cjs/index.cjs 0.22 kB │ gzip: 0.15 kB
50
+ dist/cjs/components/ProcaptchaPuzzle.cjs 0.52 kB │ gzip: 0.27 kB
51
+ dist/cjs/components/ProcaptchaWidget.cjs 6.96 kB │ gzip: 1.94 kB
52
+ dist/cjs/components/PuzzleCanvas.cjs 8.35 kB │ gzip: 2.51 kB
53
+ dist/cjs/services/Manager.cjs 9.00 kB │ gzip: 2.48 kB
54
+
55
+ ✓ built in 71ms
@@ -1,8 +1,8 @@
1
1
 
2
- > @prosopo/procaptcha-puzzle@2.10.39 build:tsc
2
+ > @prosopo/procaptcha-puzzle@2.10.41 build:tsc
3
3
  > tsc --build --verbose
4
4
 
5
- 10:22:53 PM - Projects in this build:
5
+ 12:36:38 PM - Projects in this build:
6
6
  * ../../dev/config/tsconfig.json
7
7
  * ../locale/tsconfig.json
8
8
  * ../util/tsconfig.json
@@ -20,37 +20,37 @@
20
20
  * ../procaptcha-common/tsconfig.json
21
21
  * tsconfig.json
22
22
 
23
- 10:22:53 PM - Project '../../dev/config/tsconfig.json' is up to date because newest input '../../dev/config/src/webpack/webpack.config.ts' is older than output '../../dev/config/tsconfig.tsbuildinfo'
23
+ 12:36:38 PM - Project '../../dev/config/tsconfig.json' is up to date because newest input '../../dev/config/src/webpack/index.ts' is older than output '../../dev/config/tsconfig.tsbuildinfo'
24
24
 
25
- 10:22:53 PM - Project '../locale/tsconfig.json' is up to date because newest input '../locale/src/translationKey.ts' is older than output '../locale/tsconfig.tsbuildinfo'
25
+ 12:36:38 PM - Project '../locale/tsconfig.json' is up to date because newest input '../locale/src/translationKey.ts' is older than output '../locale/tsconfig.tsbuildinfo'
26
26
 
27
- 10:22:53 PM - Project '../util/tsconfig.json' is up to date because newest input '../util/src/url.ts' is older than output '../util/tsconfig.tsbuildinfo'
27
+ 12:36:38 PM - Project '../util/tsconfig.json' is up to date because newest input '../util/src/url.ts' is older than output '../util/tsconfig.tsbuildinfo'
28
28
 
29
- 10:22:54 PM - Project '../util-crypto/tsconfig.json' is up to date because newest input '../util-crypto/src/types.ts' is older than output '../util-crypto/tsconfig.tsbuildinfo'
29
+ 12:36:38 PM - Project '../util-crypto/tsconfig.json' is up to date because newest input '../util-crypto/src/types.ts' is older than output '../util-crypto/tsconfig.tsbuildinfo'
30
30
 
31
- 10:22:54 PM - Project '../types/tsconfig.json' is up to date because newest input '../types/src/procaptcha/api.ts' is older than output '../types/tsconfig.tsbuildinfo'
31
+ 12:36:38 PM - Project '../types/tsconfig.json' is up to date because newest input '../types/src/provider/api.ts' is older than output '../types/tsconfig.tsbuildinfo'
32
32
 
33
- 10:22:54 PM - Project '../api/tsconfig.json' is up to date because newest input '../api/src/index.ts' is older than output '../api/tsconfig.tsbuildinfo'
33
+ 12:36:38 PM - Project '../api/tsconfig.json' is up to date because newest input '../api/src/tests/apiHarness.ts' is older than output '../api/tsconfig.tsbuildinfo'
34
34
 
35
- 10:22:54 PM - Project '../logger/tsconfig.json' is up to date because newest input '../logger/src/index.ts' is older than output '../logger/tsconfig.tsbuildinfo'
35
+ 12:36:38 PM - Project '../logger/tsconfig.json' is up to date because newest input '../logger/src/index.ts' is older than output '../logger/tsconfig.tsbuildinfo'
36
36
 
37
- 10:22:54 PM - Project '../common/tsconfig.json' is up to date because newest input '../common/src/error.ts' is older than output '../common/tsconfig.tsbuildinfo'
37
+ 12:36:38 PM - Project '../common/tsconfig.json' is up to date because newest input '../common/src/index.ts' is older than output '../common/tsconfig.tsbuildinfo'
38
38
 
39
- 10:22:54 PM - Project '../load-balancer/tsconfig.json' is up to date because newest input '../load-balancer/src/balancer.ts' is older than output '../load-balancer/tsconfig.tsbuildinfo'
39
+ 12:36:38 PM - Project '../load-balancer/tsconfig.json' is up to date because newest input '../load-balancer/src/tests/providers.unit.test.ts' is older than output '../load-balancer/tsconfig.tsbuildinfo'
40
40
 
41
- 10:22:54 PM - Project '../widget-skeleton/tsconfig.json' is up to date because newest input '../widget-skeleton/src/index.ts' is older than output '../widget-skeleton/tsconfig.tsbuildinfo'
41
+ 12:36:38 PM - Project '../widget-skeleton/tsconfig.json' is up to date because newest input '../widget-skeleton/src/webComponent/createWidget.ts' is older than output '../widget-skeleton/tsconfig.tsbuildinfo'
42
42
 
43
- 10:22:54 PM - Project '../fingerprintjs/tsconfig.json' is up to date because newest input '../fingerprintjs/src/utils/browser.ts' is older than output '../fingerprintjs/tsconfig.tsbuildinfo'
43
+ 12:36:38 PM - Project '../fingerprintjs/tsconfig.json' is up to date because newest input '../fingerprintjs/src/utils/browser.ts' is older than output '../fingerprintjs/tsconfig.tsbuildinfo'
44
44
 
45
- 10:22:54 PM - Project '../fingerprint/tsconfig.json' is up to date because newest input '../fingerprint/src/index.ts' is older than output '../fingerprint/tsconfig.tsbuildinfo'
45
+ 12:36:38 PM - Project '../fingerprint/tsconfig.json' is up to date because newest input '../fingerprint/src/index.ts' is older than output '../fingerprint/tsconfig.tsbuildinfo'
46
46
 
47
- 10:22:54 PM - Project '../keyring/tsconfig.json' is up to date because newest input '../keyring/src/index.ts' is older than output '../keyring/tsconfig.tsbuildinfo'
47
+ 12:36:38 PM - Project '../keyring/tsconfig.json' is up to date because newest input '../keyring/src/keyring/keyring.ts' is older than output '../keyring/tsconfig.tsbuildinfo'
48
48
 
49
- 10:22:54 PM - Project '../account/tsconfig.json' is up to date because newest input '../account/src/custom.d.ts' is older than output '../account/tsconfig.tsbuildinfo'
49
+ 12:36:39 PM - Project '../account/tsconfig.json' is up to date because newest input '../account/src/custom.d.ts' is older than output '../account/tsconfig.tsbuildinfo'
50
50
 
51
- 10:22:54 PM - Project '../procaptcha-common/tsconfig.json' is up to date because newest input '../procaptcha-common/src/reactComponents/Honeypot.tsx' is older than output '../procaptcha-common/tsconfig.tsbuildinfo'
51
+ 12:36:39 PM - Project '../procaptcha-common/tsconfig.json' is up to date because newest input '../procaptcha-common/src/simdReadings.ts' is older than output '../procaptcha-common/tsconfig.tsbuildinfo'
52
52
 
53
- 10:22:54 PM - Project 'tsconfig.json' is out of date because output file 'tsconfig.tsbuildinfo' does not exist
53
+ 12:36:39 PM - Project 'tsconfig.json' is out of date because output file 'tsconfig.tsbuildinfo' does not exist
54
54
 
55
- 10:22:54 PM - Building project '/home/runner/work/captcha/captcha/packages/procaptcha-puzzle/tsconfig.json'...
55
+ 12:36:39 PM - Building project '/home/runner/work/captcha/captcha/packages/procaptcha-puzzle/tsconfig.json'...
56
56
 
@@ -1,9 +1,9 @@
1
1
 
2
- > @prosopo/procaptcha-puzzle@2.10.39 build
2
+ > @prosopo/procaptcha-puzzle@2.10.41 build
3
3
  > npm run build:cross-env -- --mode ${NODE_ENV:-development}
4
4
 
5
5
 
6
- > @prosopo/procaptcha-puzzle@2.10.39 build:cross-env
6
+ > @prosopo/procaptcha-puzzle@2.10.41 build:cross-env
7
7
  > vite build --config vite.esm.config.ts --mode production
8
8
 
9
9
  ViteEsmConfig: .
@@ -43,15 +43,18 @@ ViteEsmConfig: .
43
43
  '@prosopo/keyring'
44
44
  ]
45
45
  }
46
- vite v6.4.1 building SSR bundle for production...
46
+ The plugin "vite-tsconfig-paths" is detected. Vite now supports tsconfig paths resolution natively via the resolve.tsconfigPaths option. You can remove the plugin and set resolve.tsconfigPaths: true in your Vite config instead.
47
+ vite v8.1.5 building ssr environment for production...
47
48
  Bundle build started
48
- transforming...
49
- Build end
50
- ✓ 5 modules transformed.
49
+ 
50
+ ✓ 6 modules transformed.
51
51
  rendering chunks...
52
- dist/index.js  0.14 kB
53
- dist/components/ProcaptchaPuzzle.js  0.34 kB
54
- dist/components/ProcaptchaWidget.js  7.13 kB
55
- dist/components/PuzzleCanvas.js  9.97 kB
56
- dist/services/Manager.js 10.22 kB
57
- ✓ built in 241ms
52
+ computing gzip size...
53
+ dist/_virtual/_rolldown/runtime.js 0.04 kB │ gzip: 0.06 kB
54
+ dist/index.js 0.14 kB │ gzip: 0.11 kB
55
+ dist/components/ProcaptchaPuzzle.js 0.38 kB │ gzip: 0.24 kB
56
+ dist/components/ProcaptchaWidget.js 6.47 kB │ gzip: 1.91 kB
57
+ dist/components/PuzzleCanvas.js 7.89 kB │ gzip: 2.48 kB
58
+ dist/services/Manager.js 8.48 kB │ gzip: 2.44 kB
59
+
60
+ ✓ built in 82ms
package/CHANGELOG.md CHANGED
@@ -1,5 +1,46 @@
1
1
  # @prosopo/procaptcha-puzzle
2
2
 
3
+ ## 2.10.41
4
+ ### Patch Changes
5
+
6
+ - 3f75ac4: Add unit and type test coverage for the puzzle widget, and fix two defects it uncovered: the checkbox click coordinates were wiped before reaching the solution salt, and a rejected challenge fetch left the spinner up with an unhandled rejection.
7
+ - Updated dependencies [1e0cf14]
8
+ - @prosopo/api@3.5.21
9
+
10
+ ## 2.10.40
11
+ ### Patch Changes
12
+
13
+ - ab3499c: feat(procaptcha): block on SIMD readings at solution submit
14
+
15
+ Solution submit is the last hop the client controls, so it's the last chance to
16
+ attach the catcher's WASM SIMD readings for a session. The image, PoW and puzzle
17
+ managers now wait for the benchmark there via a shared
18
+ `getSimdReadingsForSubmit` helper, capped at 5s, instead of attaching only
19
+ whatever the prefetch happened to have resolved.
20
+
21
+ The helper passes the budget down to the detector *and* races it locally — the
22
+ detector ships prebuilt, so a bundle that ignores `timeoutMs` (or a benchmark
23
+ wedged on a busy main thread) can't hang the submission. It never rejects: a
24
+ missing accessor, a rejection, a synchronous throw and a timeout all resolve to
25
+ `undefined` and the solution is submitted without readings, so a user is never
26
+ failed over telemetry.
27
+
28
+ The earlier frictionless POST and challenge GET hops are unchanged and remain
29
+ non-blocking.
30
+ - e14fce6: chore(deps): bump vite to 6.4.3 and mongoose to 8.24.1, and adjust types for the mongoose 8.24 Document/ObjectId changes
31
+ - Updated dependencies [2c47bb7]
32
+ - Updated dependencies [ab3499c]
33
+ - Updated dependencies [0e1171c]
34
+ - Updated dependencies [103318c]
35
+ - Updated dependencies [270a8d8]
36
+ - Updated dependencies [e14fce6]
37
+ - @prosopo/util@3.3.5
38
+ - @prosopo/procaptcha-common@2.11.18
39
+ - @prosopo/locale@3.2.8
40
+ - @prosopo/types@4.10.0
41
+ - @prosopo/api@3.5.20
42
+ - @prosopo/common@3.1.48
43
+
3
44
  ## 2.10.39
4
45
  ### Patch Changes
5
46
 
@@ -0,0 +1,3 @@
1
+ import "node:module";
2
+ //#endregion
3
+ export {};
@@ -1,10 +1,7 @@
1
- "use strict";
2
- Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
- const jsxRuntime = require("@emotion/react/jsx-runtime");
4
- const react = require("react");
5
- const _interopNamespaceDefaultOnly = (e) => Object.freeze(Object.defineProperty({ __proto__: null, default: e }, Symbol.toStringTag, { value: "Module" }));
6
- const ProcaptchaWidget = react.lazy(
7
- async () => Promise.resolve().then(() => /* @__PURE__ */ _interopNamespaceDefaultOnly(require("./ProcaptchaWidget.cjs")))
8
- );
9
- const ProcaptchaPuzzle = (props) => /* @__PURE__ */ jsxRuntime.jsx(react.Suspense, { children: /* @__PURE__ */ jsxRuntime.jsx(ProcaptchaWidget, { ...props }) });
1
+ let react = require("react");
2
+ let _emotion_react_jsx_runtime = require("@emotion/react/jsx-runtime");
3
+ //#region src/components/ProcaptchaPuzzle.tsx
4
+ var ProcaptchaWidget = (0, react.lazy)(async () => Promise.resolve().then(() => require("./ProcaptchaWidget.cjs")));
5
+ var ProcaptchaPuzzle = (props) => /* @__PURE__ */ (0, _emotion_react_jsx_runtime.jsx)(react.Suspense, { children: /* @__PURE__ */ (0, _emotion_react_jsx_runtime.jsx)(ProcaptchaWidget, { ...props }) });
6
+ //#endregion
10
7
  exports.ProcaptchaPuzzle = ProcaptchaPuzzle;
@@ -1,214 +1,192 @@
1
- "use strict";
2
- const jsxRuntime = require("@emotion/react/jsx-runtime");
3
- const locale = require("@prosopo/locale");
4
- const procaptchaCommon = require("@prosopo/procaptcha-common");
5
- const types = require("@prosopo/types");
6
- const widgetSkeleton = require("@prosopo/widget-skeleton");
7
- const react = require("react");
8
- const Manager = require("../services/Manager.cjs");
9
- const PuzzleCanvas = require("./PuzzleCanvas.cjs");
10
- const PROCAPTCHA_EXECUTE_EVENT = "procaptcha:execute";
11
- const Procaptcha = (props) => {
12
- const { t, ready: isTranslationReady } = locale.useTranslation();
13
- const config = props.config;
14
- const i18n = props.i18n;
15
- const theme = "light" === config.theme ? widgetSkeleton.lightTheme : widgetSkeleton.darkTheme;
16
- const frictionlessState = props.frictionlessState;
17
- const callbacks = props.callbacks || {};
18
- const [state, _updateState] = procaptchaCommon.useProcaptcha(react.useState, react.useRef);
19
- const [loading, setLoading] = react.useState(false);
20
- const [puzzlePhase, setPuzzlePhase] = react.useState("checkbox");
21
- const [challengeData, setChallengeData] = react.useState(null);
22
- const [showRetry, setShowRetry] = react.useState(false);
23
- const updateState = procaptchaCommon.buildUpdateState(state, _updateState);
24
- const hpRef = react.useRef(null);
25
- const manager = react.useRef(
26
- Manager.Manager(
27
- config,
28
- state,
29
- updateState,
30
- callbacks,
31
- frictionlessState,
32
- () => hpRef.current?.value || void 0
33
- )
34
- );
35
- const lastCoordsRef = react.useRef(null);
36
- const sessionInvalidatedFiredRef = react.useRef(false);
37
- react.useEffect(() => {
38
- if (!config.language) return;
39
- if (i18n) {
40
- if (i18n.language !== config.language) {
41
- void i18n.changeLanguage(config.language);
42
- }
43
- return;
44
- }
45
- void locale.loadI18next(false, config.language);
46
- }, [i18n, config.language]);
47
- react.useEffect(() => {
48
- if (!props.autoStart) return;
49
- setLoading(true);
50
- setShowRetry(false);
51
- const coords = props.startCoords;
52
- lastCoordsRef.current = coords ?? null;
53
- manager.current.start(coords?.x ?? 0, coords?.y ?? 0).then(
54
- (challenge) => {
55
- if (challenge) {
56
- setChallengeData(challenge);
57
- setPuzzlePhase("dragging");
58
- }
59
- setLoading(false);
60
- },
61
- () => setLoading(false)
62
- );
63
- }, [props.autoStart, props.startCoords]);
64
- react.useEffect(() => {
65
- if (!state.error) return void 0;
66
- setLoading(false);
67
- setPuzzlePhase("checkbox");
68
- setChallengeData(null);
69
- setShowRetry(false);
70
- if (state.error.key !== "CAPTCHA.NO_SESSION_FOUND") return void 0;
71
- if (props.onSessionInvalidated && !sessionInvalidatedFiredRef.current) {
72
- sessionInvalidatedFiredRef.current = true;
73
- const coords = lastCoordsRef.current;
74
- props.onSessionInvalidated(coords?.x, coords?.y);
75
- return void 0;
76
- }
77
- if (frictionlessState) {
78
- const timer = setTimeout(() => {
79
- frictionlessState.restart();
80
- }, 100);
81
- return () => clearTimeout(timer);
82
- }
83
- return void 0;
84
- }, [state.error, frictionlessState, props.onSessionInvalidated]);
85
- react.useEffect(() => {
86
- if (config.mode === types.ModeEnum.invisible) {
87
- const handleExecuteEvent = async () => {
88
- if (loading) {
89
- return;
90
- }
91
- setLoading(true);
92
- setShowRetry(false);
93
- try {
94
- const challenge = await manager.current.start();
95
- if (challenge) {
96
- setChallengeData(challenge);
97
- setPuzzlePhase("dragging");
98
- }
99
- } catch (error) {
100
- callbacks.onError?.(
101
- error instanceof Error ? error : new Error(String(error))
102
- );
103
- } finally {
104
- setLoading(false);
105
- }
106
- };
107
- document.addEventListener(PROCAPTCHA_EXECUTE_EVENT, handleExecuteEvent);
108
- return () => {
109
- document.removeEventListener(
110
- PROCAPTCHA_EXECUTE_EVENT,
111
- handleExecuteEvent
112
- );
113
- };
114
- }
115
- return () => {
116
- };
117
- }, [config.mode, callbacks.onError, loading]);
118
- const handlePuzzleComplete = react.useCallback(
119
- async (finalX, finalY, puzzleEvents) => {
120
- setPuzzlePhase("submitting");
121
- let verified = false;
122
- try {
123
- verified = await manager.current.submitSolution(
124
- finalX,
125
- finalY,
126
- puzzleEvents
127
- );
128
- } catch (error) {
129
- callbacks.onError?.(
130
- error instanceof Error ? error : new Error(String(error))
131
- );
132
- }
133
- if (verified) {
134
- setPuzzlePhase("checkbox");
135
- setChallengeData(null);
136
- setShowRetry(false);
137
- setLoading(false);
138
- return;
139
- }
140
- setShowRetry(true);
141
- setPuzzlePhase("dragging");
142
- try {
143
- const newChallenge = await manager.current.start();
144
- if (newChallenge) {
145
- setChallengeData(newChallenge);
146
- } else {
147
- setPuzzlePhase("checkbox");
148
- setChallengeData(null);
149
- setShowRetry(false);
150
- }
151
- } catch {
152
- setPuzzlePhase("checkbox");
153
- setChallengeData(null);
154
- setShowRetry(false);
155
- }
156
- setLoading(false);
157
- },
158
- [callbacks.onError]
159
- );
160
- const isInvisible = config.mode === types.ModeEnum.invisible;
161
- const showPuzzleOverlay = (puzzlePhase === "dragging" || puzzlePhase === "submitting") && challengeData;
162
- return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
163
- frictionlessState?.hp && /* @__PURE__ */ jsxRuntime.jsx(procaptchaCommon.Honeypot, { ref: hpRef, encodedQuestion: frictionlessState.hp }),
164
- showPuzzleOverlay && /* @__PURE__ */ jsxRuntime.jsx(
165
- PuzzleCanvas.PuzzleCanvas,
166
- {
167
- originX: challengeData.originX,
168
- originY: challengeData.originY,
169
- targetX: challengeData.targetX,
170
- targetY: challengeData.targetY,
171
- onComplete: handlePuzzleComplete,
172
- showRetry,
173
- submitting: puzzlePhase === "submitting"
174
- }
175
- ),
176
- !isInvisible && /* @__PURE__ */ jsxRuntime.jsx(
177
- procaptchaCommon.Checkbox,
178
- {
179
- checked: state.isHuman,
180
- theme,
181
- onChange: async (event) => {
182
- if (loading) {
183
- return;
184
- }
185
- setLoading(true);
186
- setShowRetry(false);
187
- let x = 0;
188
- let y = 0;
189
- const mouseOrTouchEvent = event.nativeEvent;
190
- if (!mouseOrTouchEvent.isTrusted) {
191
- } else if ("touches" in mouseOrTouchEvent && mouseOrTouchEvent.touches.length > 0 && mouseOrTouchEvent.touches[0]) {
192
- x = mouseOrTouchEvent.touches[0].clientX;
193
- y = mouseOrTouchEvent.touches[0].clientY;
194
- } else if ("clientX" in mouseOrTouchEvent && "clientY" in mouseOrTouchEvent) {
195
- x = mouseOrTouchEvent.clientX;
196
- y = mouseOrTouchEvent.clientY;
197
- }
198
- lastCoordsRef.current = { x, y };
199
- const challenge = await manager.current.start(x, y);
200
- if (challenge) {
201
- setChallengeData(challenge);
202
- setPuzzlePhase("dragging");
203
- }
204
- setLoading(false);
205
- },
206
- labelText: isTranslationReady ? t("WIDGET.I_AM_HUMAN") : "",
207
- error: state.error?.message,
208
- "aria-label": "human checkbox",
209
- loading: loading || puzzlePhase === "submitting"
210
- }
211
- )
212
- ] });
1
+ const require_Manager = require("../services/Manager.cjs");
2
+ const require_PuzzleCanvas = require("./PuzzleCanvas.cjs");
3
+ let _prosopo_locale = require("@prosopo/locale");
4
+ let _prosopo_procaptcha_common = require("@prosopo/procaptcha-common");
5
+ let _prosopo_types = require("@prosopo/types");
6
+ let _prosopo_widget_skeleton = require("@prosopo/widget-skeleton");
7
+ let react = require("react");
8
+ let _emotion_react_jsx_runtime = require("@emotion/react/jsx-runtime");
9
+ //#region src/components/ProcaptchaWidget.tsx
10
+ var PROCAPTCHA_EXECUTE_EVENT = "procaptcha:execute";
11
+ var Procaptcha = (props) => {
12
+ const { t, ready: isTranslationReady } = (0, _prosopo_locale.useTranslation)();
13
+ const config = props.config;
14
+ const i18n = props.i18n;
15
+ const theme = "light" === config.theme ? _prosopo_widget_skeleton.lightTheme : _prosopo_widget_skeleton.darkTheme;
16
+ const frictionlessState = props.frictionlessState;
17
+ const callbacks = props.callbacks || {};
18
+ const [state, _updateState] = (0, _prosopo_procaptcha_common.useProcaptcha)(react.useState, react.useRef);
19
+ const [loading, setLoading] = (0, react.useState)(false);
20
+ const [puzzlePhase, setPuzzlePhase] = (0, react.useState)("checkbox");
21
+ const [challengeData, setChallengeData] = (0, react.useState)(null);
22
+ const [showRetry, setShowRetry] = (0, react.useState)(false);
23
+ const updateState = (0, _prosopo_procaptcha_common.buildUpdateState)(state, _updateState);
24
+ const hpRef = (0, react.useRef)(null);
25
+ const manager = (0, react.useRef)(require_Manager.Manager(config, state, updateState, callbacks, frictionlessState, () => hpRef.current?.value || void 0));
26
+ const lastCoordsRef = (0, react.useRef)(null);
27
+ const sessionInvalidatedFiredRef = (0, react.useRef)(false);
28
+ (0, react.useEffect)(() => {
29
+ if (!config.language) return;
30
+ if (i18n) {
31
+ if (i18n.language !== config.language) i18n.changeLanguage(config.language);
32
+ return;
33
+ }
34
+ (0, _prosopo_locale.loadI18next)(false, config.language);
35
+ }, [i18n, config.language]);
36
+ (0, react.useEffect)(() => {
37
+ if (!props.autoStart) return;
38
+ setLoading(true);
39
+ setShowRetry(false);
40
+ const coords = props.startCoords;
41
+ lastCoordsRef.current = coords ?? null;
42
+ manager.current.start(coords?.x ?? 0, coords?.y ?? 0).then((challenge) => {
43
+ if (challenge) {
44
+ setChallengeData(challenge);
45
+ setPuzzlePhase("dragging");
46
+ }
47
+ setLoading(false);
48
+ }, () => setLoading(false));
49
+ }, [props.autoStart, props.startCoords]);
50
+ (0, react.useEffect)(() => {
51
+ if (!state.error) return void 0;
52
+ setLoading(false);
53
+ setPuzzlePhase("checkbox");
54
+ setChallengeData(null);
55
+ setShowRetry(false);
56
+ if (state.error.key !== "CAPTCHA.NO_SESSION_FOUND") return void 0;
57
+ if (props.onSessionInvalidated && !sessionInvalidatedFiredRef.current) {
58
+ sessionInvalidatedFiredRef.current = true;
59
+ const coords = lastCoordsRef.current;
60
+ props.onSessionInvalidated(coords?.x, coords?.y);
61
+ return;
62
+ }
63
+ if (frictionlessState) {
64
+ const timer = setTimeout(() => {
65
+ frictionlessState.restart();
66
+ }, 100);
67
+ return () => clearTimeout(timer);
68
+ }
69
+ }, [
70
+ state.error,
71
+ frictionlessState,
72
+ props.onSessionInvalidated
73
+ ]);
74
+ (0, react.useEffect)(() => {
75
+ if (config.mode === _prosopo_types.ModeEnum.invisible) {
76
+ const handleExecuteEvent = async () => {
77
+ if (loading) return;
78
+ setLoading(true);
79
+ setShowRetry(false);
80
+ try {
81
+ const challenge = await manager.current.start();
82
+ if (challenge) {
83
+ setChallengeData(challenge);
84
+ setPuzzlePhase("dragging");
85
+ }
86
+ } catch (error) {
87
+ callbacks.onError?.(error instanceof Error ? error : new Error(String(error)));
88
+ } finally {
89
+ setLoading(false);
90
+ }
91
+ };
92
+ document.addEventListener(PROCAPTCHA_EXECUTE_EVENT, handleExecuteEvent);
93
+ return () => {
94
+ document.removeEventListener(PROCAPTCHA_EXECUTE_EVENT, handleExecuteEvent);
95
+ };
96
+ }
97
+ return () => {};
98
+ }, [
99
+ config.mode,
100
+ callbacks.onError,
101
+ loading
102
+ ]);
103
+ const handlePuzzleComplete = (0, react.useCallback)(async (finalX, finalY, puzzleEvents) => {
104
+ setPuzzlePhase("submitting");
105
+ let verified = false;
106
+ try {
107
+ verified = await manager.current.submitSolution(finalX, finalY, puzzleEvents);
108
+ } catch (error) {
109
+ callbacks.onError?.(error instanceof Error ? error : new Error(String(error)));
110
+ }
111
+ if (verified) {
112
+ setPuzzlePhase("checkbox");
113
+ setChallengeData(null);
114
+ setShowRetry(false);
115
+ setLoading(false);
116
+ return;
117
+ }
118
+ setShowRetry(true);
119
+ setPuzzlePhase("dragging");
120
+ try {
121
+ const newChallenge = await manager.current.start();
122
+ if (newChallenge) setChallengeData(newChallenge);
123
+ else {
124
+ setPuzzlePhase("checkbox");
125
+ setChallengeData(null);
126
+ setShowRetry(false);
127
+ }
128
+ } catch {
129
+ setPuzzlePhase("checkbox");
130
+ setChallengeData(null);
131
+ setShowRetry(false);
132
+ }
133
+ setLoading(false);
134
+ }, [callbacks.onError]);
135
+ const isInvisible = config.mode === _prosopo_types.ModeEnum.invisible;
136
+ const showPuzzleOverlay = (puzzlePhase === "dragging" || puzzlePhase === "submitting") && challengeData;
137
+ return /* @__PURE__ */ (0, _emotion_react_jsx_runtime.jsxs)(_emotion_react_jsx_runtime.Fragment, { children: [
138
+ frictionlessState?.hp && /* @__PURE__ */ (0, _emotion_react_jsx_runtime.jsx)(_prosopo_procaptcha_common.Honeypot, {
139
+ ref: hpRef,
140
+ encodedQuestion: frictionlessState.hp
141
+ }),
142
+ showPuzzleOverlay && /* @__PURE__ */ (0, _emotion_react_jsx_runtime.jsx)(require_PuzzleCanvas.PuzzleCanvas, {
143
+ originX: challengeData.originX,
144
+ originY: challengeData.originY,
145
+ targetX: challengeData.targetX,
146
+ targetY: challengeData.targetY,
147
+ onComplete: handlePuzzleComplete,
148
+ showRetry,
149
+ submitting: puzzlePhase === "submitting"
150
+ }),
151
+ !isInvisible && /* @__PURE__ */ (0, _emotion_react_jsx_runtime.jsx)(_prosopo_procaptcha_common.Checkbox, {
152
+ checked: state.isHuman,
153
+ theme,
154
+ onChange: async (event) => {
155
+ if (loading) return;
156
+ setLoading(true);
157
+ setShowRetry(false);
158
+ let x = 0;
159
+ let y = 0;
160
+ const mouseOrTouchEvent = event.nativeEvent;
161
+ if (!mouseOrTouchEvent.isTrusted) {} else if ("touches" in mouseOrTouchEvent && mouseOrTouchEvent.touches.length > 0 && mouseOrTouchEvent.touches[0]) {
162
+ x = mouseOrTouchEvent.touches[0].clientX;
163
+ y = mouseOrTouchEvent.touches[0].clientY;
164
+ } else if ("clientX" in mouseOrTouchEvent && "clientY" in mouseOrTouchEvent) {
165
+ x = mouseOrTouchEvent.clientX;
166
+ y = mouseOrTouchEvent.clientY;
167
+ }
168
+ lastCoordsRef.current = {
169
+ x,
170
+ y
171
+ };
172
+ try {
173
+ const challenge = await manager.current.start(x, y);
174
+ if (challenge) {
175
+ setChallengeData(challenge);
176
+ setPuzzlePhase("dragging");
177
+ }
178
+ } catch (error) {
179
+ callbacks.onError?.(error instanceof Error ? error : new Error(String(error)));
180
+ } finally {
181
+ setLoading(false);
182
+ }
183
+ },
184
+ labelText: isTranslationReady ? t("WIDGET.I_AM_HUMAN") : "",
185
+ error: state.error?.message,
186
+ "aria-label": "human checkbox",
187
+ loading: loading || puzzlePhase === "submitting"
188
+ })
189
+ ] });
213
190
  };
214
- module.exports = Procaptcha;
191
+ //#endregion
192
+ exports.default = Procaptcha;