@prosopo/procaptcha-common 2.9.19 → 2.10.17

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 (107) hide show
  1. package/.turbo/turbo-build$colon$cjs.log +22 -15
  2. package/.turbo/turbo-build$colon$tsc.log +52 -0
  3. package/.turbo/turbo-build.log +26 -16
  4. package/CHANGELOG.md +392 -0
  5. package/dist/callbacks/defaultCallbacks.d.ts +4 -0
  6. package/dist/callbacks/defaultCallbacks.d.ts.map +1 -0
  7. package/dist/callbacks/defaultCallbacks.js.map +1 -0
  8. package/dist/callbacks/defaultEvents.d.ts +14 -0
  9. package/dist/callbacks/defaultEvents.d.ts.map +1 -0
  10. package/dist/callbacks/defaultEvents.js.map +1 -0
  11. package/dist/cjs/elements/form.cjs +8 -2
  12. package/dist/cjs/elements/window.cjs +7 -0
  13. package/dist/cjs/index.cjs +5 -0
  14. package/dist/cjs/reactComponents/Checkbox.cjs +11 -7
  15. package/dist/cjs/reactComponents/Honeypot.cjs +67 -0
  16. package/dist/cjs/reactComponents/TestModeBanner.cjs +47 -0
  17. package/dist/elements/form.d.ts +5 -0
  18. package/dist/elements/form.d.ts.map +1 -0
  19. package/dist/elements/form.js +8 -2
  20. package/dist/elements/form.js.map +1 -0
  21. package/dist/elements/window.d.ts +3 -0
  22. package/dist/elements/window.d.ts.map +1 -0
  23. package/dist/elements/window.js +8 -1
  24. package/dist/elements/window.js.map +1 -0
  25. package/dist/extensionLoader.d.ts +2 -0
  26. package/dist/extensionLoader.d.ts.map +1 -0
  27. package/dist/extensionLoader.js.map +1 -0
  28. package/dist/index.d.ts +11 -0
  29. package/dist/index.d.ts.map +1 -0
  30. package/dist/index.js +6 -1
  31. package/dist/index.js.map +1 -0
  32. package/dist/providers.d.ts +4 -0
  33. package/dist/providers.d.ts.map +1 -0
  34. package/dist/providers.js.map +1 -0
  35. package/dist/reactComponents/Checkbox.d.ts +13 -0
  36. package/dist/reactComponents/Checkbox.d.ts.map +1 -0
  37. package/dist/reactComponents/Checkbox.js +11 -7
  38. package/dist/reactComponents/Checkbox.js.map +1 -0
  39. package/dist/reactComponents/Honeypot.d.ts +6 -0
  40. package/dist/reactComponents/Honeypot.d.ts.map +1 -0
  41. package/dist/reactComponents/Honeypot.js +67 -0
  42. package/dist/reactComponents/Honeypot.js.map +1 -0
  43. package/dist/reactComponents/Reload.d.ts +8 -0
  44. package/dist/reactComponents/Reload.d.ts.map +1 -0
  45. package/dist/reactComponents/Reload.js.map +1 -0
  46. package/dist/reactComponents/TestModeBanner.d.ts +7 -0
  47. package/dist/reactComponents/TestModeBanner.d.ts.map +1 -0
  48. package/dist/reactComponents/TestModeBanner.js +47 -0
  49. package/dist/reactComponents/TestModeBanner.js.map +1 -0
  50. package/dist/state/builder.d.ts +9 -0
  51. package/dist/state/builder.d.ts.map +1 -0
  52. package/dist/state/builder.js.map +1 -0
  53. package/dist/tests/defaultCallbacks.test.d.ts +2 -0
  54. package/dist/tests/defaultCallbacks.test.d.ts.map +1 -0
  55. package/dist/tests/defaultCallbacks.test.js +219 -0
  56. package/dist/tests/defaultCallbacks.test.js.map +1 -0
  57. package/dist/tests/defaultEvents.test.d.ts +2 -0
  58. package/dist/tests/defaultEvents.test.d.ts.map +1 -0
  59. package/dist/tests/defaultEvents.test.js +54 -0
  60. package/dist/tests/defaultEvents.test.js.map +1 -0
  61. package/dist/tests/extensionLoader.test.d.ts +2 -0
  62. package/dist/tests/extensionLoader.test.d.ts.map +1 -0
  63. package/dist/tests/extensionLoader.test.js +21 -0
  64. package/dist/tests/extensionLoader.test.js.map +1 -0
  65. package/dist/tests/form.test.d.ts +2 -0
  66. package/dist/tests/form.test.d.ts.map +1 -0
  67. package/dist/tests/form.test.js +98 -0
  68. package/dist/tests/form.test.js.map +1 -0
  69. package/dist/tests/providers.test.d.ts +2 -0
  70. package/dist/tests/providers.test.d.ts.map +1 -0
  71. package/dist/tests/providers.test.js +111 -0
  72. package/dist/tests/providers.test.js.map +1 -0
  73. package/dist/tests/state-builder.test.d.ts +2 -0
  74. package/dist/tests/state-builder.test.d.ts.map +1 -0
  75. package/dist/tests/state-builder.test.js +193 -0
  76. package/dist/tests/state-builder.test.js.map +1 -0
  77. package/dist/tests/window.test.d.ts +2 -0
  78. package/dist/tests/window.test.d.ts.map +1 -0
  79. package/dist/tests/window.test.js +80 -0
  80. package/dist/tests/window.test.js.map +1 -0
  81. package/package.json +13 -9
  82. package/src/callbacks/defaultCallbacks.ts +197 -0
  83. package/src/callbacks/defaultEvents.ts +21 -0
  84. package/src/elements/form.ts +41 -0
  85. package/src/elements/window.ts +39 -0
  86. package/src/extensionLoader.ts +17 -0
  87. package/src/index.ts +24 -0
  88. package/src/providers.ts +49 -0
  89. package/src/reactComponents/Checkbox.tsx +203 -0
  90. package/src/reactComponents/Honeypot.tsx +133 -0
  91. package/src/reactComponents/Reload.tsx +99 -0
  92. package/src/reactComponents/TestModeBanner.tsx +75 -0
  93. package/src/state/builder.ts +137 -0
  94. package/src/tests/defaultCallbacks.test.ts +372 -0
  95. package/src/tests/defaultEvents.test.ts +80 -0
  96. package/src/tests/extensionLoader.test.ts +41 -0
  97. package/src/tests/form.test.ts +154 -0
  98. package/src/tests/providers.test.ts +175 -0
  99. package/src/tests/state-builder.test.ts +264 -0
  100. package/src/tests/window.test.ts +137 -0
  101. package/tsconfig.cjs.json +32 -0
  102. package/tsconfig.json +33 -0
  103. package/tsconfig.tsbuildinfo +1 -0
  104. package/tsconfig.types.json +9 -0
  105. package/vite.cjs.config.ts +1 -1
  106. package/vite.esm.config.ts +1 -1
  107. package/vite.test.config.ts +1 -1
@@ -0,0 +1,193 @@
1
+ import { describe, expect, it, vi } from "vitest";
2
+ import { buildUpdateState, useProcaptcha } from "../state/builder.js";
3
+ describe("state/builder", () => {
4
+ describe("buildUpdateState", () => {
5
+ it("should mutate state and call onStateUpdate with partial state", () => {
6
+ const state = {
7
+ isHuman: false,
8
+ index: 0,
9
+ solutions: [],
10
+ captchaApi: undefined,
11
+ showModal: false,
12
+ challenge: undefined,
13
+ loading: false,
14
+ account: undefined,
15
+ dappAccount: undefined,
16
+ submission: undefined,
17
+ timeout: undefined,
18
+ successfullChallengeTimeout: undefined,
19
+ sendData: false,
20
+ attemptCount: 0,
21
+ error: undefined,
22
+ sessionId: undefined,
23
+ };
24
+ const onStateUpdate = vi.fn();
25
+ const updateState = buildUpdateState(state, onStateUpdate);
26
+ const partialState = { isHuman: true, attemptCount: 1 };
27
+ updateState(partialState);
28
+ expect(state.isHuman).toBe(true);
29
+ expect(state.attemptCount).toBe(1);
30
+ expect(onStateUpdate).toHaveBeenCalledWith(partialState);
31
+ });
32
+ it("should handle multiple property updates in order", () => {
33
+ const state = {
34
+ isHuman: false,
35
+ index: 0,
36
+ solutions: [],
37
+ captchaApi: undefined,
38
+ showModal: false,
39
+ challenge: undefined,
40
+ loading: false,
41
+ account: undefined,
42
+ dappAccount: undefined,
43
+ submission: undefined,
44
+ timeout: undefined,
45
+ successfullChallengeTimeout: undefined,
46
+ sendData: false,
47
+ attemptCount: 0,
48
+ error: undefined,
49
+ sessionId: undefined,
50
+ };
51
+ const onStateUpdate = vi.fn();
52
+ const updateState = buildUpdateState(state, onStateUpdate);
53
+ updateState({ loading: true, index: 5, showModal: true });
54
+ expect(state.loading).toBe(true);
55
+ expect(state.index).toBe(5);
56
+ expect(state.showModal).toBe(true);
57
+ });
58
+ it("should update error state correctly", () => {
59
+ const state = {
60
+ isHuman: false,
61
+ index: 0,
62
+ solutions: [],
63
+ captchaApi: undefined,
64
+ showModal: false,
65
+ challenge: undefined,
66
+ loading: false,
67
+ account: undefined,
68
+ dappAccount: undefined,
69
+ submission: undefined,
70
+ timeout: undefined,
71
+ successfullChallengeTimeout: undefined,
72
+ sendData: false,
73
+ attemptCount: 0,
74
+ error: undefined,
75
+ sessionId: undefined,
76
+ };
77
+ const onStateUpdate = vi.fn();
78
+ const updateState = buildUpdateState(state, onStateUpdate);
79
+ const errorObj = { message: "Test error", key: "test" };
80
+ updateState({ error: errorObj });
81
+ expect(state.error).toEqual(errorObj);
82
+ expect(onStateUpdate).toHaveBeenCalledWith({ error: errorObj });
83
+ });
84
+ });
85
+ describe("useProcaptcha", () => {
86
+ it("should initialize with default state values", () => {
87
+ const useState = vi.fn((defaultValue) => [defaultValue, vi.fn()]);
88
+ const useRef = vi.fn((defaultValue) => ({ current: defaultValue }));
89
+ const [state, updateFn] = useProcaptcha(useState, useRef);
90
+ expect(state.isHuman).toBe(false);
91
+ expect(state.index).toBe(0);
92
+ expect(state.solutions).toEqual([]);
93
+ expect(state.showModal).toBe(false);
94
+ expect(state.loading).toBe(false);
95
+ expect(state.sendData).toBe(false);
96
+ expect(state.attemptCount).toBe(0);
97
+ expect(state.account).toBeUndefined();
98
+ expect(state.captchaApi).toBeUndefined();
99
+ expect(state.challenge).toBeUndefined();
100
+ expect(state.error).toBeUndefined();
101
+ expect(typeof updateFn).toBe("function");
102
+ });
103
+ it("should call appropriate setters when updating state", () => {
104
+ const setters = {};
105
+ const useState = vi.fn((defaultValue) => {
106
+ const key = typeof defaultValue === "boolean"
107
+ ? `boolean-${defaultValue}`
108
+ : typeof defaultValue === "number"
109
+ ? `number-${defaultValue}`
110
+ : Array.isArray(defaultValue)
111
+ ? "array"
112
+ : "other";
113
+ if (!setters[key]) {
114
+ setters[key] = vi.fn();
115
+ }
116
+ return [defaultValue, setters[key]];
117
+ });
118
+ const useRef = vi.fn((defaultValue) => ({ current: defaultValue }));
119
+ const [state, updateFn] = useProcaptcha(useState, useRef);
120
+ updateFn({
121
+ isHuman: true,
122
+ index: 5,
123
+ loading: true,
124
+ attemptCount: 3,
125
+ });
126
+ expect(setters["boolean-false"]).toHaveBeenCalledWith(true);
127
+ expect(setters["number-0"]).toHaveBeenCalledWith(5);
128
+ expect(setters["number-0"]).toHaveBeenCalledWith(3);
129
+ });
130
+ it("should handle solutions array correctly with slice", () => {
131
+ const setSolutions = vi.fn();
132
+ let solutionsValue = [];
133
+ const useState = vi.fn((defaultValue) => {
134
+ if (Array.isArray(defaultValue)) {
135
+ return [
136
+ solutionsValue,
137
+ (newValue) => {
138
+ solutionsValue = newValue;
139
+ setSolutions(newValue);
140
+ },
141
+ ];
142
+ }
143
+ return [defaultValue, vi.fn()];
144
+ });
145
+ const useRef = vi.fn((defaultValue) => ({ current: defaultValue }));
146
+ const [state, updateFn] = useProcaptcha(useState, useRef);
147
+ const newSolutions = [[["test", 1, 2]]];
148
+ updateFn({ solutions: newSolutions });
149
+ expect(setSolutions).toHaveBeenCalled();
150
+ const callArg = setSolutions.mock.calls[0]?.[0];
151
+ expect(callArg).toBeDefined();
152
+ expect(callArg).not.toBe(newSolutions);
153
+ expect(callArg).toEqual(newSolutions);
154
+ });
155
+ it("should not call setters for undefined values in partial update", () => {
156
+ const setIsHuman = vi.fn();
157
+ const setIndex = vi.fn();
158
+ let isHumanSetter;
159
+ let indexSetter;
160
+ const useState = vi.fn((defaultValue) => {
161
+ if (defaultValue === false) {
162
+ isHumanSetter = setIsHuman;
163
+ return [false, setIsHuman];
164
+ }
165
+ if (defaultValue === 0) {
166
+ indexSetter = setIndex;
167
+ return [0, setIndex];
168
+ }
169
+ return [defaultValue, vi.fn()];
170
+ });
171
+ const useRef = vi.fn((defaultValue) => ({ current: defaultValue }));
172
+ const [state, updateFn] = useProcaptcha(useState, useRef);
173
+ updateFn({ isHuman: true });
174
+ expect(setIsHuman).toHaveBeenCalledWith(true);
175
+ expect(setIndex).not.toHaveBeenCalled();
176
+ });
177
+ it("should handle error state update", () => {
178
+ const setError = vi.fn();
179
+ const useState = vi.fn((defaultValue) => {
180
+ if (defaultValue === undefined && setError.mock.calls.length === 0) {
181
+ return [undefined, setError];
182
+ }
183
+ return [defaultValue, vi.fn()];
184
+ });
185
+ const useRef = vi.fn((defaultValue) => ({ current: defaultValue }));
186
+ const [state, updateFn] = useProcaptcha(useState, useRef);
187
+ const errorObj = { message: "Test error", key: "testKey" };
188
+ updateFn({ error: errorObj });
189
+ expect(setError).toHaveBeenCalledWith(errorObj);
190
+ });
191
+ });
192
+ });
193
+ //# sourceMappingURL=state-builder.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"state-builder.test.js","sourceRoot":"","sources":["../../src/tests/state-builder.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=window.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"window.test.d.ts","sourceRoot":"","sources":["../../src/tests/window.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,80 @@
1
+ import { afterEach, describe, expect, it } from "vitest";
2
+ import { getWindowCallback, isSecureBrowserContext, } from "../elements/window.js";
3
+ describe("elements/window", () => {
4
+ describe("getWindowCallback", () => {
5
+ const originalWindow = global.window;
6
+ afterEach(() => {
7
+ const keys = Object.keys(window);
8
+ for (const key of keys) {
9
+ if (key.startsWith("test")) {
10
+ delete window[key];
11
+ }
12
+ }
13
+ });
14
+ it("should retrieve a function from window object", () => {
15
+ const testFn = () => "test";
16
+ window.testCallback = testFn;
17
+ const result = getWindowCallback("testCallback");
18
+ expect(result).toBe(testFn);
19
+ });
20
+ it("should handle window. prefix in callback name", () => {
21
+ const testFn = () => "test";
22
+ window.testCallback = testFn;
23
+ const result = getWindowCallback("window.testCallback");
24
+ expect(result).toBe(testFn);
25
+ });
26
+ it("should throw error if callback is not a function", () => {
27
+ window.testCallback = "not a function";
28
+ expect(() => getWindowCallback("testCallback")).toThrow("Callback testCallback is not defined on the window object");
29
+ });
30
+ it("should throw error if callback does not exist", () => {
31
+ expect(() => getWindowCallback("nonExistentCallback")).toThrow("Callback nonExistentCallback is not defined on the window object");
32
+ });
33
+ it("should handle callback that is undefined", () => {
34
+ window.testCallback = undefined;
35
+ expect(() => getWindowCallback("testCallback")).toThrow("Callback testCallback is not defined on the window object");
36
+ });
37
+ it("should handle callback that is null", () => {
38
+ window.testCallback = null;
39
+ expect(() => getWindowCallback("testCallback")).toThrow("Callback testCallback is not defined on the window object");
40
+ });
41
+ it("should work with arrow functions", () => {
42
+ const arrowFn = (x) => x * 2;
43
+ window.testArrowCallback = arrowFn;
44
+ const result = getWindowCallback("testArrowCallback");
45
+ expect(result).toBe(arrowFn);
46
+ expect(result(5)).toBe(10);
47
+ });
48
+ it("should work with regular functions", () => {
49
+ function regularFn(x) {
50
+ return x * 2;
51
+ }
52
+ window.testRegularCallback = regularFn;
53
+ const result = getWindowCallback("testRegularCallback");
54
+ expect(result).toBe(regularFn);
55
+ expect(result(5)).toBe(10);
56
+ });
57
+ });
58
+ describe("isSecureBrowserContext", () => {
59
+ const originalIsSecureContext = window.isSecureContext;
60
+ const setIsSecureContext = (value) => {
61
+ Object.defineProperty(window, "isSecureContext", {
62
+ value,
63
+ configurable: true,
64
+ writable: true,
65
+ });
66
+ };
67
+ afterEach(() => {
68
+ setIsSecureContext(originalIsSecureContext);
69
+ });
70
+ it("should return true in a secure context (HTTPS/localhost)", () => {
71
+ setIsSecureContext(true);
72
+ expect(isSecureBrowserContext()).toBe(true);
73
+ });
74
+ it("should return false in an insecure context (plain HTTP)", () => {
75
+ setIsSecureContext(false);
76
+ expect(isSecureBrowserContext()).toBe(false);
77
+ });
78
+ });
79
+ });
80
+ //# sourceMappingURL=window.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"window.test.js","sourceRoot":"","sources":["../../src/tests/window.test.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@prosopo/procaptcha-common",
3
- "version": "2.9.19",
3
+ "version": "2.10.17",
4
4
  "author": "PROSOPO LIMITED <info@prosopo.io>",
5
5
  "license": "Apache-2.0",
6
6
  "main": "dist/index.js",
@@ -21,7 +21,8 @@
21
21
  "source": "./src/index.ts",
22
22
  "scripts": {
23
23
  "clean": "del-cli --verbose dist tsconfig.tsbuildinfo",
24
- "build": "NODE_ENV=${NODE_ENV:-development}; vite build --config vite.esm.config.ts --mode $NODE_ENV",
24
+ "build": "npm run build:cross-env -- --mode ${NODE_ENV:-development}",
25
+ "build:cross-env": "vite build --config vite.esm.config.ts",
25
26
  "build:tsc": "tsc --build --verbose",
26
27
  "build:cjs": "NODE_ENV=${NODE_ENV:-development}; vite build --config vite.cjs.config.ts --mode $NODE_ENV",
27
28
  "typecheck": "tsc --project tsconfig.types.json",
@@ -33,17 +34,19 @@
33
34
  "dependencies": {
34
35
  "@emotion/react": "11.11.1",
35
36
  "@emotion/styled": "11.11.0",
36
- "@prosopo/account": "2.7.43",
37
- "@prosopo/load-balancer": "2.8.13",
38
- "@prosopo/types": "3.6.4",
39
- "@prosopo/widget-skeleton": "2.7.12",
40
- "react": "18.3.1"
37
+ "@prosopo/account": "2.8.35",
38
+ "@prosopo/load-balancer": "2.9.10",
39
+ "@prosopo/types": "4.3.0",
40
+ "@prosopo/widget-skeleton": "2.8.3",
41
+ "react": "18.3.1",
42
+ "react-dom": "18.3.1"
41
43
  },
42
44
  "devDependencies": {
43
- "@prosopo/config": "3.1.26",
45
+ "@prosopo/config": "3.3.1",
44
46
  "@types/jsdom": "21.1.7",
45
47
  "@types/node": "22.10.2",
46
48
  "@types/react": "18.3.1",
49
+ "@types/react-dom": "18.3.1",
47
50
  "@vitest/coverage-v8": "3.2.4",
48
51
  "concurrently": "9.0.1",
49
52
  "del-cli": "6.0.0",
@@ -58,7 +61,8 @@
58
61
  },
59
62
  "repository": {
60
63
  "type": "git",
61
- "url": "git+https://github.com/prosopo/captcha.git"
64
+ "url": "git+https://github.com/prosopo/captcha.git",
65
+ "directory": "packages/procaptcha-common"
62
66
  },
63
67
  "bugs": {
64
68
  "url": "https://github.com/prosopo/captcha/issues"
@@ -0,0 +1,197 @@
1
+ // Copyright 2021-2026 Prosopo (UK) Ltd.
2
+ //
3
+ // Licensed under the Apache License, Version 2.0 (the "License");
4
+ // you may not use this file except in compliance with the License.
5
+ // You may obtain a copy of the License at
6
+ //
7
+ // http://www.apache.org/licenses/LICENSE-2.0
8
+ //
9
+ // Unless required by applicable law or agreed to in writing, software
10
+ // distributed under the License is distributed on an "AS IS" BASIS,
11
+ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ // See the License for the specific language governing permissions and
13
+ // limitations under the License.
14
+ import {
15
+ ApiParams,
16
+ type Callbacks,
17
+ type ProcaptchaRenderOptions,
18
+ type ProcaptchaToken,
19
+ } from "@prosopo/types";
20
+ import { getParentForm, removeProcaptchaResponse } from "../elements/form.js";
21
+ import { getWindowCallback } from "../elements/window.js";
22
+
23
+ export const getDefaultCallbacks = (element?: Element): Callbacks => ({
24
+ onHuman: (token: ProcaptchaToken) => handleOnHuman(token, element),
25
+ onChallengeExpired: () => {
26
+ removeProcaptchaResponse();
27
+ console.log("Challenge expired");
28
+ },
29
+ onExtensionNotFound: () => {
30
+ console.error("Extension not found");
31
+ },
32
+ onExpired: () => {
33
+ removeProcaptchaResponse();
34
+ },
35
+ onError: (error: Error) => {
36
+ removeProcaptchaResponse();
37
+ console.error(error);
38
+ },
39
+ onClose: () => {
40
+ console.log("Challenge closed");
41
+ },
42
+ onOpen: () => {
43
+ console.log("Challenge opened");
44
+ },
45
+ onFailed: () => {
46
+ alert("Captcha challenge failed. Please try again");
47
+ console.log("Challenge failed");
48
+ },
49
+ onReset: () => {
50
+ removeProcaptchaResponse();
51
+ console.log("Captcha widget reset");
52
+ },
53
+ onReload: () => {
54
+ console.log("Challenge reloaded");
55
+ },
56
+ });
57
+
58
+ /**
59
+ * Set the a user callback function for an element. Data tags take precedence over renderOptions.
60
+ */
61
+ const getUserCallback = (
62
+ callback: string,
63
+ element: Element,
64
+ callbackFnOrName: string | ((token: string) => void) | undefined,
65
+ ) => {
66
+ const callbackFnName = element.getAttribute(`data-${callback}`);
67
+ if (callbackFnName) {
68
+ const callbackFn = getWindowCallback(callbackFnName);
69
+ if (callbackFn) {
70
+ return callbackFn;
71
+ }
72
+ }
73
+ if (typeof callbackFnOrName === "function") {
74
+ return callbackFnOrName;
75
+ }
76
+ if (typeof callbackFnOrName === "string") {
77
+ return getWindowCallback(callbackFnOrName);
78
+ }
79
+ };
80
+
81
+ export function setUserCallbacks(
82
+ renderOptions: ProcaptchaRenderOptions | undefined,
83
+ callbacks: Callbacks,
84
+ element: Element,
85
+ ) {
86
+ const humanCallback = getUserCallback(
87
+ "callback",
88
+ element,
89
+ renderOptions?.callback,
90
+ );
91
+ if (humanCallback) {
92
+ // wrap the user's callback in a function that also calls handleOnHuman
93
+ callbacks.onHuman = (token: ProcaptchaToken) => {
94
+ handleOnHuman(token, element);
95
+ humanCallback(token);
96
+ };
97
+ }
98
+
99
+ const chalExpiredCallback = getUserCallback(
100
+ "chalexpired-callback",
101
+ element,
102
+ renderOptions?.["chalexpired-callback"],
103
+ );
104
+ if (chalExpiredCallback) {
105
+ callbacks.onChallengeExpired = () => {
106
+ removeProcaptchaResponse();
107
+ chalExpiredCallback();
108
+ };
109
+ }
110
+
111
+ const expiredCallback = getUserCallback(
112
+ "expired-callback",
113
+ element,
114
+ renderOptions?.["expired-callback"],
115
+ );
116
+ if (expiredCallback) {
117
+ callbacks.onExpired = () => {
118
+ removeProcaptchaResponse();
119
+ expiredCallback();
120
+ };
121
+ }
122
+
123
+ const errorCallback = getUserCallback(
124
+ "error-callback",
125
+ element,
126
+ renderOptions?.["error-callback"],
127
+ );
128
+ if (errorCallback) {
129
+ callbacks.onError = (error: Error) => {
130
+ removeProcaptchaResponse();
131
+ errorCallback(error);
132
+ };
133
+ }
134
+
135
+ const closeCallback = getUserCallback(
136
+ "close-callback",
137
+ element,
138
+ renderOptions?.["close-callback"],
139
+ );
140
+ if (closeCallback) {
141
+ callbacks.onClose = () => {
142
+ closeCallback();
143
+ };
144
+ }
145
+
146
+ const openCallback = getUserCallback(
147
+ "open-callback",
148
+ element,
149
+ renderOptions?.["open-callback"],
150
+ );
151
+ if (openCallback) {
152
+ callbacks.onOpen = () => {
153
+ openCallback();
154
+ };
155
+ }
156
+
157
+ const failedCallback = getUserCallback(
158
+ "failed-callback",
159
+ element,
160
+ renderOptions?.["failed-callback"],
161
+ );
162
+ if (failedCallback) {
163
+ callbacks.onFailed = () => {
164
+ failedCallback();
165
+ };
166
+ }
167
+
168
+ const resetCallback = getUserCallback(
169
+ "reset-callback",
170
+ element,
171
+ renderOptions?.["reset-callback"],
172
+ );
173
+ if (resetCallback) {
174
+ callbacks.onReset = () => {
175
+ removeProcaptchaResponse();
176
+ resetCallback();
177
+ };
178
+ }
179
+ }
180
+
181
+ const handleOnHuman = (token: ProcaptchaToken, element?: Element) => {
182
+ removeProcaptchaResponse();
183
+ if (element) {
184
+ const form = getParentForm(element);
185
+
186
+ if (!form) {
187
+ console.error("Parent form not found for the element:", element);
188
+ return;
189
+ }
190
+
191
+ const input = document.createElement("input");
192
+ input.type = "hidden";
193
+ input.name = ApiParams.procaptchaResponse;
194
+ input.value = token;
195
+ form.appendChild(input);
196
+ }
197
+ };
@@ -0,0 +1,21 @@
1
+ // Copyright 2021-2026 Prosopo (UK) Ltd.
2
+ //
3
+ // Licensed under the Apache License, Version 2.0 (the "License");
4
+ // you may not use this file except in compliance with the License.
5
+ // You may obtain a copy of the License at
6
+ //
7
+ // http://www.apache.org/licenses/LICENSE-2.0
8
+ //
9
+ // Unless required by applicable law or agreed to in writing, software
10
+ // distributed under the License is distributed on an "AS IS" BASIS,
11
+ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ // See the License for the specific language governing permissions and
13
+ // limitations under the License.
14
+
15
+ import type { Callbacks } from "@prosopo/types";
16
+ import { getDefaultCallbacks } from "./defaultCallbacks.js";
17
+
18
+ export const getDefaultEvents = (callbacks: Partial<Callbacks>) => ({
19
+ ...getDefaultCallbacks(undefined),
20
+ ...callbacks,
21
+ });
@@ -0,0 +1,41 @@
1
+ // Copyright 2021-2026 Prosopo (UK) Ltd.
2
+ //
3
+ // Licensed under the Apache License, Version 2.0 (the "License");
4
+ // you may not use this file except in compliance with the License.
5
+ // You may obtain a copy of the License at
6
+ //
7
+ // http://www.apache.org/licenses/LICENSE-2.0
8
+ //
9
+ // Unless required by applicable law or agreed to in writing, software
10
+ // distributed under the License is distributed on an "AS IS" BASIS,
11
+ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ // See the License for the specific language governing permissions and
13
+ // limitations under the License.
14
+
15
+ import { ApiParams } from "@prosopo/types";
16
+
17
+ type ParentForm = HTMLFormElement | null;
18
+
19
+ export function getParentForm(widgetElement: Element): ParentForm {
20
+ const parentForm = widgetElement.closest("form") as ParentForm;
21
+
22
+ if (parentForm) {
23
+ return parentForm;
24
+ }
25
+
26
+ // fallback for widgets inside a shadow DOM
27
+
28
+ const rootWidgetNode = widgetElement.getRootNode();
29
+ if (rootWidgetNode instanceof ShadowRoot) {
30
+ return rootWidgetNode.host.closest("form") as ParentForm;
31
+ }
32
+
33
+ return null;
34
+ }
35
+
36
+ export const removeProcaptchaResponse = () => {
37
+ const element = Array.from(
38
+ document.getElementsByName(ApiParams.procaptchaResponse),
39
+ );
40
+ element.map((el) => el.remove());
41
+ };
@@ -0,0 +1,39 @@
1
+ // Copyright 2021-2026 Prosopo (UK) Ltd.
2
+ //
3
+ // Licensed under the Apache License, Version 2.0 (the "License");
4
+ // you may not use this file except in compliance with the License.
5
+ // You may obtain a copy of the License at
6
+ //
7
+ // http://www.apache.org/licenses/LICENSE-2.0
8
+ //
9
+ // Unless required by applicable law or agreed to in writing, software
10
+ // distributed under the License is distributed on an "AS IS" BASIS,
11
+ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ // See the License for the specific language governing permissions and
13
+ // limitations under the License.
14
+
15
+ export const getWindowCallback = (callbackName: string) => {
16
+ // biome-ignore lint/suspicious/noExplicitAny: TODO fix any
17
+ const fn = (window as any)[callbackName.replace("window.", "")];
18
+ if (typeof fn !== "function") {
19
+ throw new Error(
20
+ `Callback ${callbackName} is not defined on the window object`,
21
+ );
22
+ }
23
+ return fn;
24
+ };
25
+
26
+ /**
27
+ * Procaptcha depends on secure-context-only browser APIs (e.g. SubtleCrypto)
28
+ * to run a challenge. These are unavailable when the widget is served over
29
+ * plain HTTP, which otherwise surfaces as a cryptic provider-selection
30
+ * failure. The browser already treats HTTPS and localhost as secure contexts,
31
+ * so this only flags genuine HTTP origins. Non-browser (SSR) environments are
32
+ * treated as secure since the HTTP restriction does not apply there.
33
+ */
34
+ export const isSecureBrowserContext = (): boolean => {
35
+ if (typeof window === "undefined") {
36
+ return true;
37
+ }
38
+ return window.isSecureContext === true;
39
+ };