@hcaptcha/react-hcaptcha 0.3.5 → 0.3.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -33,13 +33,6 @@ import HCaptcha from '@hcaptcha/react-hcaptcha';
33
33
  </FormComponent>
34
34
  ```
35
35
 
36
- #### Usage with TypeScript
37
- Add the types from DefinitelyTyped
38
-
39
- ```
40
- npm i -D @types/hcaptcha__react-hcaptcha
41
- ```
42
-
43
36
  **A note about TypeScript usage:** If you want to reassign the component name, you could consider making a util that imports the component, then re-exports it as a default. Example:
44
37
 
45
38
  ```ts
@@ -78,6 +71,7 @@ In these instances, you'll most likely want to use `ref` to handle the callbacks
78
71
  |`imghost`|String|No|`-`|See enterprise docs.|
79
72
  |`reportapi`|String|No|`-`|See enterprise docs.|
80
73
  |`sentry`|String|No|`-`|See enterprise docs.|
74
+ |`custom`|Boolean|No|`-`|See enterprise docs.|
81
75
 
82
76
  ### Events
83
77
 
@@ -86,12 +80,13 @@ In these instances, you'll most likely want to use `ref` to handle the callbacks
86
80
  |`onError`|`err`|When an error occurs. Component will reset immediately after an error.|
87
81
  |`onVerify`|`token, eKey`|When challenge is completed. The response `token` and an `eKey` (session id) are passed along.|
88
82
  |`onExpire`|-|When the current token expires.|
83
+ |`onLoad`|-|When the hCaptcha API loads.|
89
84
 
90
85
  ### Methods
91
86
 
92
87
  |Method|Description|
93
88
  |---|---|
94
- |`execute()`|Programmatically trigger a challenge request|
89
+ |`execute()`|Programmatically trigger a challenge request. Additionally, this method can be run asynchronously and returns a promise with the `token` and `eKey` when the challenge is completed.|
95
90
  |`resetCaptcha()`|Reset the current challenge|
96
91
 
97
92
 
package/dist/index.js CHANGED
@@ -1,33 +1,31 @@
1
1
  "use strict";
2
2
 
3
- function _typeof(obj) { "@babel/helpers - typeof"; if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); }
3
+ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
4
4
 
5
- function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; }
5
+ var _typeof2 = _interopRequireDefault(require("@babel/runtime/helpers/typeof"));
6
6
 
7
- function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; }
7
+ var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
8
8
 
9
- function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
9
+ var _classCallCheck2 = _interopRequireDefault(require("@babel/runtime/helpers/classCallCheck"));
10
10
 
11
- function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
11
+ var _createClass2 = _interopRequireDefault(require("@babel/runtime/helpers/createClass"));
12
12
 
13
- function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }
13
+ var _assertThisInitialized2 = _interopRequireDefault(require("@babel/runtime/helpers/assertThisInitialized"));
14
14
 
15
- function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }
15
+ var _inherits2 = _interopRequireDefault(require("@babel/runtime/helpers/inherits"));
16
16
 
17
- function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); }
17
+ var _possibleConstructorReturn2 = _interopRequireDefault(require("@babel/runtime/helpers/possibleConstructorReturn"));
18
18
 
19
- function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }
19
+ var _getPrototypeOf2 = _interopRequireDefault(require("@babel/runtime/helpers/getPrototypeOf"));
20
20
 
21
- function _createSuper(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct(); return function _createSuperInternal() { var Super = _getPrototypeOf(Derived), result; if (hasNativeReflectConstruct) { var NewTarget = _getPrototypeOf(this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return _possibleConstructorReturn(this, result); }; }
21
+ function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; }
22
22
 
23
- function _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === "object" || typeof call === "function")) { return call; } return _assertThisInitialized(self); }
23
+ function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { (0, _defineProperty2["default"])(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; }
24
24
 
25
- function _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; }
25
+ function _createSuper(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct(); return function _createSuperInternal() { var Super = (0, _getPrototypeOf2["default"])(Derived), result; if (hasNativeReflectConstruct) { var NewTarget = (0, _getPrototypeOf2["default"])(this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return (0, _possibleConstructorReturn2["default"])(this, result); }; }
26
26
 
27
27
  function _isNativeReflectConstruct() { if (typeof Reflect === "undefined" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === "function") return true; try { Date.prototype.toString.call(Reflect.construct(Date, [], function () {})); return true; } catch (e) { return false; } }
28
28
 
29
- function _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }
30
-
31
29
  var React = require('react');
32
30
 
33
31
  var _require = require("./utils.js"),
@@ -60,25 +58,24 @@ var mountCaptchaScript = function mountCaptchaScript() {
60
58
  };
61
59
 
62
60
  var HCaptcha = /*#__PURE__*/function (_React$Component) {
63
- _inherits(HCaptcha, _React$Component);
61
+ (0, _inherits2["default"])(HCaptcha, _React$Component);
64
62
 
65
63
  var _super = _createSuper(HCaptcha);
66
64
 
67
65
  function HCaptcha(props) {
68
66
  var _this;
69
67
 
70
- _classCallCheck(this, HCaptcha);
71
-
68
+ (0, _classCallCheck2["default"])(this, HCaptcha);
72
69
  _this = _super.call(this, props); // API Methods
73
70
 
74
- _this.renderCaptcha = _this.renderCaptcha.bind(_assertThisInitialized(_this));
75
- _this.resetCaptcha = _this.resetCaptcha.bind(_assertThisInitialized(_this));
76
- _this.removeCaptcha = _this.removeCaptcha.bind(_assertThisInitialized(_this)); // Event Handlers
71
+ _this.renderCaptcha = _this.renderCaptcha.bind((0, _assertThisInitialized2["default"])(_this));
72
+ _this.resetCaptcha = _this.resetCaptcha.bind((0, _assertThisInitialized2["default"])(_this));
73
+ _this.removeCaptcha = _this.removeCaptcha.bind((0, _assertThisInitialized2["default"])(_this)); // Event Handlers
77
74
 
78
- _this.handleOnLoad = _this.handleOnLoad.bind(_assertThisInitialized(_this));
79
- _this.handleSubmit = _this.handleSubmit.bind(_assertThisInitialized(_this));
80
- _this.handleExpire = _this.handleExpire.bind(_assertThisInitialized(_this));
81
- _this.handleError = _this.handleError.bind(_assertThisInitialized(_this));
75
+ _this.handleOnLoad = _this.handleOnLoad.bind((0, _assertThisInitialized2["default"])(_this));
76
+ _this.handleSubmit = _this.handleSubmit.bind((0, _assertThisInitialized2["default"])(_this));
77
+ _this.handleExpire = _this.handleExpire.bind((0, _assertThisInitialized2["default"])(_this));
78
+ _this.handleError = _this.handleError.bind((0, _assertThisInitialized2["default"])(_this));
82
79
  var isApiReady = typeof hcaptcha !== 'undefined';
83
80
  _this.ref = React.createRef();
84
81
  _this.state = {
@@ -90,7 +87,7 @@ var HCaptcha = /*#__PURE__*/function (_React$Component) {
90
87
  return _this;
91
88
  }
92
89
 
93
- _createClass(HCaptcha, [{
90
+ (0, _createClass2["default"])(HCaptcha, [{
94
91
  key: "componentDidMount",
95
92
  value: function componentDidMount() {
96
93
  //Once captcha is mounted intialize hCaptcha - hCaptcha
@@ -103,7 +100,8 @@ var HCaptcha = /*#__PURE__*/function (_React$Component) {
103
100
  hl = _this$props.languageOverride,
104
101
  reCaptchaCompat = _this$props.reCaptchaCompat,
105
102
  reportapi = _this$props.reportapi,
106
- sentry = _this$props.sentry;
103
+ sentry = _this$props.sentry,
104
+ custom = _this$props.custom;
107
105
  var isApiReady = this.state.isApiReady;
108
106
 
109
107
  if (!isApiReady) {
@@ -119,7 +117,8 @@ var HCaptcha = /*#__PURE__*/function (_React$Component) {
119
117
  imghost: imghost,
120
118
  recaptchacompat: reCaptchaCompat === false ? "off" : null,
121
119
  reportapi: reportapi,
122
- sentry: sentry
120
+ sentry: sentry,
121
+ custom: custom
123
122
  });
124
123
  } // Add onload callback to global onload listeners
125
124
 
@@ -171,7 +170,7 @@ var HCaptcha = /*#__PURE__*/function (_React$Component) {
171
170
  }
172
171
  }, {
173
172
  key: "renderCaptcha",
174
- value: function renderCaptcha() {
173
+ value: function renderCaptcha(onReady) {
175
174
  var isApiReady = this.state.isApiReady;
176
175
  if (!isApiReady) return; //Render hCaptcha widget and provide necessary callbacks - hCaptcha
177
176
 
@@ -183,6 +182,8 @@ var HCaptcha = /*#__PURE__*/function (_React$Component) {
183
182
  this.setState({
184
183
  isRemoved: false,
185
184
  captchaId: captchaId
185
+ }, function () {
186
+ onReady && onReady();
186
187
  });
187
188
  }
188
189
  }, {
@@ -219,7 +220,12 @@ var HCaptcha = /*#__PURE__*/function (_React$Component) {
219
220
  this.setState({
220
221
  isApiReady: true
221
222
  }, function () {
222
- _this3.renderCaptcha();
223
+ // render captcha and wait for captcha id
224
+ _this3.renderCaptcha(function () {
225
+ // trigger onLoad if it exists
226
+ var onLoad = _this3.props.onLoad;
227
+ if (onLoad) onLoad();
228
+ });
223
229
  });
224
230
  }
225
231
  }, {
@@ -265,12 +271,18 @@ var HCaptcha = /*#__PURE__*/function (_React$Component) {
265
271
  }, {
266
272
  key: "execute",
267
273
  value: function execute() {
274
+ var opts = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null;
268
275
  var _this$state7 = this.state,
269
276
  isApiReady = _this$state7.isApiReady,
270
277
  isRemoved = _this$state7.isRemoved,
271
278
  captchaId = _this$state7.captchaId;
272
279
  if (!isApiReady || isRemoved) return;
273
- hcaptcha.execute(captchaId);
280
+
281
+ if (opts && (0, _typeof2["default"])(opts) !== "object") {
282
+ opts = null;
283
+ }
284
+
285
+ return hcaptcha.execute(captchaId, opts);
274
286
  }
275
287
  }, {
276
288
  key: "render",
@@ -282,7 +294,6 @@ var HCaptcha = /*#__PURE__*/function (_React$Component) {
282
294
  });
283
295
  }
284
296
  }]);
285
-
286
297
  return HCaptcha;
287
298
  }(React.Component);
288
299
 
package/dist/utils.js CHANGED
@@ -1,26 +1,18 @@
1
1
  "use strict";
2
2
 
3
- function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest(); }
3
+ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
4
4
 
5
- function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
6
-
7
- function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
8
-
9
- function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) { arr2[i] = arr[i]; } return arr2; }
10
-
11
- function _iterableToArrayLimit(arr, i) { if (typeof Symbol === "undefined" || !(Symbol.iterator in Object(arr))) return; var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"] != null) _i["return"](); } finally { if (_d) throw _e; } } return _arr; }
12
-
13
- function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }
5
+ var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
14
6
 
15
7
  function generateQuery(params) {
16
8
  return Object.entries(params).filter(function (_ref) {
17
- var _ref2 = _slicedToArray(_ref, 2),
9
+ var _ref2 = (0, _slicedToArray2["default"])(_ref, 2),
18
10
  key = _ref2[0],
19
11
  value = _ref2[1];
20
12
 
21
13
  return value || value === false;
22
14
  }).map(function (_ref3) {
23
- var _ref4 = _slicedToArray(_ref3, 2),
15
+ var _ref4 = (0, _slicedToArray2["default"])(_ref3, 2),
24
16
  key = _ref4[0],
25
17
  value = _ref4[1];
26
18
 
package/package.json CHANGED
@@ -1,11 +1,18 @@
1
1
  {
2
2
  "name": "@hcaptcha/react-hcaptcha",
3
- "version": "0.3.5",
4
- "description": "A React library for hCaptcha",
3
+ "version": "0.3.9",
4
+ "types": "types/index.d.ts",
5
5
  "main": "dist/index.js",
6
+ "files": [
7
+ "src",
8
+ "dist",
9
+ "types/index.d.ts"
10
+ ],
11
+ "description": "A React library for hCaptcha",
6
12
  "scripts": {
7
13
  "start": "webpack-dev-server --config ./webpack.config.js --mode development",
8
14
  "test": "jest",
15
+ "watch": "babel src -d dist --copy-files --watch",
9
16
  "transpile": "babel src -d dist --copy-files",
10
17
  "build": "npm run transpile",
11
18
  "prepublishOnly": "npm run transpile"
@@ -25,6 +32,7 @@
25
32
  "devDependencies": {
26
33
  "@babel/cli": "^7.12.10",
27
34
  "@babel/core": "^7.12.10",
35
+ "@babel/plugin-transform-runtime": "^7.14.5",
28
36
  "@babel/preset-env": "^7.12.11",
29
37
  "@babel/preset-react": "^7.12.10",
30
38
  "babel-loader": "^8.2.2",
package/src/index.js CHANGED
@@ -59,7 +59,7 @@ class HCaptcha extends React.Component {
59
59
  }
60
60
 
61
61
  componentDidMount () { //Once captcha is mounted intialize hCaptcha - hCaptcha
62
- const { apihost, assethost, endpoint, host, imghost, languageOverride:hl, reCaptchaCompat, reportapi, sentry } = this.props;
62
+ const { apihost, assethost, endpoint, host, imghost, languageOverride:hl, reCaptchaCompat, reportapi, sentry, custom } = this.props;
63
63
  const { isApiReady } = this.state;
64
64
 
65
65
  if (!isApiReady) { //Check if hCaptcha has already been loaded, if not create script tag and wait to render captcha
@@ -75,7 +75,8 @@ class HCaptcha extends React.Component {
75
75
  imghost,
76
76
  recaptchacompat: reCaptchaCompat === false? "off" : null,
77
77
  reportapi,
78
- sentry
78
+ sentry,
79
+ custom
79
80
  });
80
81
  }
81
82
 
@@ -118,7 +119,7 @@ class HCaptcha extends React.Component {
118
119
  }
119
120
  }
120
121
 
121
- renderCaptcha() {
122
+ renderCaptcha(onReady) {
122
123
  const { isApiReady } = this.state;
123
124
  if (!isApiReady) return;
124
125
 
@@ -126,12 +127,14 @@ class HCaptcha extends React.Component {
126
127
  const captchaId = hcaptcha.render(this.ref.current,
127
128
  {
128
129
  ...this.props,
129
- "error-callback" : this.handleError,
130
- "expired-callback": this.handleExpire,
131
- "callback" : this.handleSubmit
130
+ "error-callback" : this.handleError,
131
+ "expired-callback" : this.handleExpire,
132
+ "callback" : this.handleSubmit,
132
133
  });
133
134
 
134
- this.setState({ isRemoved: false, captchaId });
135
+ this.setState({ isRemoved: false, captchaId }, () => {
136
+ onReady && onReady();
137
+ });
135
138
  }
136
139
 
137
140
  resetCaptcha() {
@@ -155,7 +158,13 @@ class HCaptcha extends React.Component {
155
158
 
156
159
  handleOnLoad () {
157
160
  this.setState({ isApiReady: true }, () => {
158
- this.renderCaptcha();
161
+
162
+ // render captcha and wait for captcha id
163
+ this.renderCaptcha(() => {
164
+ // trigger onLoad if it exists
165
+ const { onLoad } = this.props;
166
+ if (onLoad) onLoad();
167
+ });
159
168
  });
160
169
  }
161
170
 
@@ -190,12 +199,16 @@ class HCaptcha extends React.Component {
190
199
  if (onError) onError(event);
191
200
  }
192
201
 
193
- execute () {
202
+ execute (opts = null) {
194
203
  const { isApiReady, isRemoved, captchaId } = this.state;
195
204
 
196
- if (!isApiReady || isRemoved) return
205
+ if (!isApiReady || isRemoved) return;
206
+
207
+ if (opts && typeof opts !== "object") {
208
+ opts = null;
209
+ }
197
210
 
198
- hcaptcha.execute(captchaId)
211
+ return hcaptcha.execute(captchaId, opts);
199
212
  }
200
213
 
201
214
  render () {
@@ -0,0 +1,44 @@
1
+ // Type definitions for @hcaptcha/react-hcaptcha 0.1
2
+ // Project: https://github.com/hCaptcha/react-hcaptcha
3
+ // Definitions by: Matt Sutkowski <https://github.com/msutkowski>
4
+ // Original Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped
5
+ // TypeScript Version: 2.8
6
+
7
+ import * as React from "react";
8
+
9
+ interface HCaptchaState {
10
+ isApiReady: boolean;
11
+ isRemoved: boolean;
12
+ elementId: string;
13
+ captchaId: string;
14
+ }
15
+
16
+ interface HCaptchaProps {
17
+ onExpire?: () => any;
18
+ onError?: (event: string) => any;
19
+ onVerify?: (token: string) => any;
20
+ onLoad?: () => any;
21
+ languageOverride?: string;
22
+ sitekey: string;
23
+ size?: "normal" | "compact" | "invisible";
24
+ theme?: "light" | "dark";
25
+ tabIndex?: number;
26
+ id?: string;
27
+ reCaptchaCompat?: boolean;
28
+ }
29
+
30
+ interface ExecuteResponse {
31
+ response: string;
32
+ key: string;
33
+ }
34
+
35
+ declare class HCaptcha extends React.Component<HCaptchaProps, HCaptchaState> {
36
+ resetCaptcha(): void;
37
+ renderCaptcha(): void;
38
+ removeCaptcha(): void;
39
+ execute(opts: { async: true }): Promise<ExecuteResponse>
40
+ execute(opts?: { async: false }): void;
41
+ execute(opts?: { async: boolean }): Promise<ExecuteResponse> | void;
42
+ }
43
+
44
+ export = HCaptcha;
package/.babelrc DELETED
@@ -1,6 +0,0 @@
1
- {
2
- "presets": [
3
- "@babel/env",
4
- "@babel/react"
5
- ]
6
- }
package/.gitattributes DELETED
@@ -1 +0,0 @@
1
- * text=auto
@@ -1,12 +0,0 @@
1
- name: CI
2
- on: push
3
- jobs:
4
- build:
5
- name: Build & Test
6
- runs-on: ubuntu-latest
7
- steps:
8
- - name: Checkout code
9
- uses: actions/checkout@v2
10
- - run: npm ci
11
- - run: npm run transpile
12
- - run: npm run test
@@ -1,71 +0,0 @@
1
- # For most projects, this workflow file will not need changing; you simply need
2
- # to commit it to your repository.
3
- #
4
- # You may wish to alter this file to override the set of languages analyzed,
5
- # or to provide custom queries or build logic.
6
- name: "CodeQL"
7
-
8
- on:
9
- push:
10
- branches: [master]
11
- pull_request:
12
- # The branches below must be a subset of the branches above
13
- branches: [master]
14
- schedule:
15
- - cron: '0 20 * * 3'
16
-
17
- jobs:
18
- analyze:
19
- name: Analyze
20
- runs-on: ubuntu-latest
21
-
22
- strategy:
23
- fail-fast: false
24
- matrix:
25
- # Override automatic language detection by changing the below list
26
- # Supported options are ['csharp', 'cpp', 'go', 'java', 'javascript', 'python']
27
- language: ['javascript']
28
- # Learn more...
29
- # https://docs.github.com/en/github/finding-security-vulnerabilities-and-errors-in-your-code/configuring-code-scanning#overriding-automatic-language-detection
30
-
31
- steps:
32
- - name: Checkout repository
33
- uses: actions/checkout@v2
34
- with:
35
- # We must fetch at least the immediate parents so that if this is
36
- # a pull request then we can checkout the head.
37
- fetch-depth: 2
38
-
39
- # If this run was triggered by a pull request event, then checkout
40
- # the head of the pull request instead of the merge commit.
41
- - run: git checkout HEAD^2
42
- if: ${{ github.event_name == 'pull_request' }}
43
-
44
- # Initializes the CodeQL tools for scanning.
45
- - name: Initialize CodeQL
46
- uses: github/codeql-action/init@v1
47
- with:
48
- languages: ${{ matrix.language }}
49
- # If you wish to specify custom queries, you can do so here or in a config file.
50
- # By default, queries listed here will override any specified in a config file.
51
- # Prefix the list here with "+" to use these queries and those in the config file.
52
- # queries: ./path/to/local/query, your-org/your-repo/queries@main
53
-
54
- # Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
55
- # If this step fails, then you should remove it and run the build manually (see below)
56
- - name: Autobuild
57
- uses: github/codeql-action/autobuild@v1
58
-
59
- # ℹ️ Command-line programs to run using the OS shell.
60
- # 📚 https://git.io/JvXDl
61
-
62
- # ✏️ If the Autobuild fails above, remove it and uncomment the following three lines
63
- # and modify them (or add more) to build your code if your project
64
- # uses a compiled language
65
-
66
- #- run: |
67
- # make bootstrap
68
- # make release
69
-
70
- - name: Perform CodeQL Analysis
71
- uses: github/codeql-action/analyze@v1
@@ -1,22 +0,0 @@
1
- name: Publish NPM
2
- on:
3
- release:
4
- types: [ created ]
5
- jobs:
6
- build:
7
- name: Build & Test & Publish
8
- runs-on: ubuntu-latest
9
- steps:
10
- - name: Checkout code
11
- uses: actions/checkout@v2
12
- # Setup .npmrc file to publish to npm
13
- - uses: actions/setup-node@v1
14
- with:
15
- node-version: '12.x'
16
- registry-url: 'https://registry.npmjs.org'
17
- - run: npm ci
18
- - run: npm run transpile
19
- - run: npm run test
20
- - run: npm publish
21
- env:
22
- NODE_AUTH_TOKEN: ${{ secrets.NPM_AUTH_TOKEN }}
@@ -1,9 +0,0 @@
1
- <!DOCTYPE html>
2
- <html>
3
- <head>
4
- <title>hCaptcha React Demo</title>
5
- </head>
6
- <body>
7
- <div id="app"></div>
8
- </body>
9
- </html>
@@ -1,89 +0,0 @@
1
- const React = require('react');
2
- const {render} = require('react-dom');
3
- const HCaptcha = require('../../dist/');
4
-
5
- class ReactDemo extends React.Component {
6
-
7
- constructor(props) {
8
- super(props);
9
-
10
- this.state = {isVerified: false};
11
- this.captcha = React.createRef();
12
-
13
- this.handleChange = this.handleChange.bind(this);
14
- this.handleReset = this.handleReset.bind(this);
15
- this.onVerifyCaptcha = this.onVerifyCaptcha.bind(this);
16
- // Leave languageOverride unset or null for browser autodetection.
17
- // To force a language, use the code: https://hcaptcha.com/docs/languages
18
- this.languageOverride = null; // "fr";
19
- }
20
-
21
- handleChange(event) {
22
- this.setState({isVerified: true});
23
- }
24
-
25
- onVerifyCaptcha (token) {
26
- console.log("Verified: " + token);
27
- this.setState({isVerified: true})
28
- }
29
-
30
- handleSubmit(event) {
31
- event.preventDefault()
32
- this.child.execute()
33
- }
34
-
35
- handleReset(event) {
36
- event.preventDefault()
37
- this.captcha.current.resetCaptcha()
38
- this.setState({isVerified: false})
39
- }
40
-
41
- render() {
42
- const { isVerified } = this.state;
43
-
44
- return (
45
- <div>
46
- <p>
47
- Set your sitekey and onVerify callback as props, and drop into your form. From here, we'll take care of the rest.
48
- </p>
49
- <div>
50
- <HCaptcha ref={this.captcha} onVerify={this.onVerifyCaptcha} languageOverride={this.languageOverride}
51
- sitekey="917ba1eb-0b37-486e-9c90-39f3cb7b2579"
52
- theme="light"
53
- />
54
- </div>
55
-
56
- <div>
57
- <HCaptcha ref={this.captcha} onVerify={this.onVerifyCaptcha} languageOverride={this.languageOverride}
58
- sitekey="917ba1eb-0b37-486e-9c90-39f3cb7b2579"
59
- theme="dark"
60
- />
61
- </div>
62
-
63
- <div>
64
- <HCaptcha ref={this.captcha} onVerify={this.onVerifyCaptcha} languageOverride={this.languageOverride}
65
- sitekey="917ba1eb-0b37-486e-9c90-39f3cb7b2579"
66
- size="compact"
67
- theme="dark"
68
- />
69
- </div>
70
-
71
- {isVerified &&
72
- <div>
73
- <p>Open your console to see the Verified response.</p>
74
- <button onClick={this.handleReset}>Reset Captcha</button>
75
- </div>
76
- }
77
-
78
- </div>
79
- );
80
- }
81
- }
82
-
83
- render(
84
- <div>
85
- <h1>HCaptcha React Demo</h1>
86
- <ReactDemo/>
87
- </div>,
88
- document.getElementById('app')
89
- );
package/jest.config.js DELETED
@@ -1,15 +0,0 @@
1
- "use strict";
2
-
3
- // For a detailed explanation regarding each configuration property, visit:
4
- // https://jestjs.io/docs/en/configuration.html
5
-
6
- module.exports = {
7
- // Automatically clear mock calls and instances between every test
8
- clearMocks: true,
9
-
10
- // The glob patterns Jest uses to detect test files
11
- testMatch: ["**/?(*.)+(spec|test).js?(x)"],
12
-
13
- // An array of regexp pattern strings that are matched against all test paths, matched tests are skipped
14
- testPathIgnorePatterns: ["/node_modules/", "webpack.config.test.js"],
15
- };
@@ -1,19 +0,0 @@
1
- export const MOCK_WIDGET_ID = 'mock-widget-id';
2
- export const MOCK_TOKEN = 'mock-token';
3
- export const MOCK_EKEY = 'mock-ekey';
4
-
5
- /*global jest*/
6
-
7
- export function getMockedHcaptcha() {
8
- return {
9
- // eslint-disable-next-line no-unused-vars
10
- setData: jest.fn((id, data) => {}),
11
- // eslint-disable-next-line no-unused-vars
12
- render: jest.fn((container, opt) => MOCK_WIDGET_ID),
13
- getResponse: jest.fn(() => MOCK_TOKEN),
14
- getRespKey: jest.fn(() => MOCK_EKEY),
15
- reset: jest.fn(),
16
- execute: jest.fn(),
17
- remove: jest.fn(),
18
- };
19
- }
@@ -1,281 +0,0 @@
1
- import React from "react";
2
- import ReactDOM from "react-dom";
3
- import ReactTestUtils, { act } from "react-dom/test-utils";
4
- import {getMockedHcaptcha, MOCK_EKEY, MOCK_TOKEN, MOCK_WIDGET_ID} from "./hcaptcha.mock";
5
-
6
- let HCaptcha;
7
-
8
- const TEST_PROPS = {
9
- sitekey: "10000000-ffff-ffff-ffff-000000000001",
10
- theme: "light",
11
- size: "invisible",
12
- tabindex: 0,
13
- };
14
-
15
- describe("hCaptcha", () => {
16
- let instance;
17
- let mockFns;
18
-
19
- beforeEach(() => {
20
- jest.isolateModules(() => {
21
- // Use node's `require` because `jest.isolateModules` cannot be async to use it with `await import()`
22
- HCaptcha = require('../src/index');
23
- });
24
-
25
- mockFns = {
26
- onChange: jest.fn(),
27
- onVerify: jest.fn(),
28
- onError: jest.fn(),
29
- onExpire: jest.fn(),
30
- };
31
- window.hcaptcha = getMockedHcaptcha();
32
- instance = ReactTestUtils.renderIntoDocument(
33
- <HCaptcha
34
- sitekey={TEST_PROPS.sitekey}
35
- theme={TEST_PROPS.theme}
36
- size={TEST_PROPS.size}
37
- tabindex={TEST_PROPS.tabindex}
38
- onChange={mockFns.onChange}
39
- onVerify={mockFns.onVerify}
40
- onError={mockFns.onError}
41
- onExpire={mockFns.onExpire}
42
- />,
43
- );
44
- });
45
-
46
- it("renders into a div", () => {
47
- expect(ReactDOM.findDOMNode(instance).nodeName).toBe("DIV");
48
- });
49
-
50
- it("has functions", () => {
51
- expect(typeof instance.execute).toBe("function");
52
- expect(typeof instance.resetCaptcha).toBe("function");
53
- expect(instance.execute).toBeDefined();
54
- expect(instance.resetCaptcha).toBeDefined();
55
- });
56
-
57
- it("can execute", () => {
58
- expect(window.hcaptcha.execute.mock.calls.length).toBe(0);
59
- instance.execute();
60
- expect(window.hcaptcha.execute.mock.calls.length).toBe(1);
61
- expect(window.hcaptcha.execute.mock.calls[0][0]).toBe(MOCK_WIDGET_ID);
62
- });
63
-
64
- it("can reset", () => {
65
- expect(window.hcaptcha.reset.mock.calls.length).toBe(0);
66
- instance.resetCaptcha();
67
- expect(window.hcaptcha.reset.mock.calls.length).toBe(1);
68
- expect(window.hcaptcha.reset.mock.calls[0][0]).toBe(MOCK_WIDGET_ID);
69
- });
70
-
71
- it("can remove", () => {
72
- expect(window.hcaptcha.remove.mock.calls.length).toBe(0);
73
- instance.removeCaptcha();
74
- expect(window.hcaptcha.remove.mock.calls.length).toBe(1);
75
- expect(window.hcaptcha.remove.mock.calls[0][0]).toBe(MOCK_WIDGET_ID);
76
- });
77
-
78
- it("emits verify with token and eKey", () => {
79
- expect(mockFns.onVerify.mock.calls.length).toBe(0);
80
- instance.handleSubmit();
81
- expect(mockFns.onVerify.mock.calls.length).toBe(1);
82
- expect(mockFns.onVerify.mock.calls[0][0]).toBe(MOCK_TOKEN);
83
- expect(mockFns.onVerify.mock.calls[0][1]).toBe(MOCK_EKEY);
84
- });
85
-
86
- it("emits error and calls reset", () => {
87
- expect(mockFns.onError.mock.calls.length).toBe(0);
88
- const error = "invalid-input-response";
89
- instance.handleError(error);
90
- expect(mockFns.onError.mock.calls.length).toBe(1);
91
- expect(mockFns.onError.mock.calls[0][0]).toBe(error);
92
- expect(window.hcaptcha.reset.mock.calls.length).toBe(1);
93
- });
94
-
95
- it("emits expire and calls reset", () => {
96
- expect(mockFns.onExpire.mock.calls.length).toBe(0);
97
- instance.handleExpire();
98
- expect(mockFns.onExpire.mock.calls.length).toBe(1);
99
- expect(window.hcaptcha.reset.mock.calls.length).toBe(1);
100
- });
101
-
102
- it("el renders after api loads and a widget id is set", () => {
103
- expect(instance.state.captchaId).toBe(MOCK_WIDGET_ID);
104
- expect(window.hcaptcha.render.mock.calls.length).toBe(1);
105
- expect(window.hcaptcha.render.mock.calls[0][1]).toMatchObject({
106
- sitekey: TEST_PROPS.sitekey,
107
- theme: TEST_PROPS.theme,
108
- size: TEST_PROPS.size,
109
- tabindex: TEST_PROPS.tabindex
110
- });
111
- });
112
-
113
- it("should set id if id prop is passed", () => {
114
- instance = ReactTestUtils.renderIntoDocument(
115
- <HCaptcha
116
- sitekey={TEST_PROPS.sitekey}
117
- id="test-id-1"
118
- />,
119
- );
120
- const node = ReactDOM.findDOMNode(instance);
121
- expect(node.getAttribute("id")).toBe("test-id-1");
122
- });
123
-
124
- it("should not set id if no id prop is passed", () => {
125
- process.env.NODE_ENV = "development";
126
- instance = ReactTestUtils.renderIntoDocument(
127
- <HCaptcha
128
- sitekey={TEST_PROPS.sitekey}
129
- />,
130
- );
131
- const node = ReactDOM.findDOMNode(instance);
132
- expect(node.getAttribute("id")).toBe(null);
133
- });
134
-
135
- describe("Query parameter", () => {
136
-
137
- beforeEach(() => {
138
- // Setup hCaptcha as undefined to load script
139
- window.hcaptcha = undefined;
140
- });
141
-
142
- afterEach(() => {
143
- // Clean up created script tag
144
- document.querySelectorAll("head > script")
145
- .forEach(script => document.head.removeChild(script));
146
- });
147
-
148
- it("validate src without", () => {
149
- instance = ReactTestUtils.renderIntoDocument(<HCaptcha
150
- sitekey={TEST_PROPS.sitekey}
151
- />);
152
-
153
- const script = document.querySelector("head > script");
154
- expect(script.src).toEqual("https://hcaptcha.com/1/api.js?render=explicit&onload=hcaptchaOnLoad");
155
- });
156
-
157
- it("apihost should change script src, but not be added as query", () => {
158
- const ExpectHost = "https://test.com";
159
-
160
- instance = ReactTestUtils.renderIntoDocument(<HCaptcha
161
- apihost={ExpectHost}
162
- sitekey={TEST_PROPS.sitekey}
163
- />);
164
-
165
- const script = document.querySelector("head > script");
166
- expect(script.src).toContain(ExpectHost);
167
- expect(script.src).not.toContain(`apihost=${encodeURIComponent(ExpectHost)}`);
168
- });
169
-
170
- it("assethost should be found when prop is set", () => {
171
- const ExpectHost = "https://test.com";
172
-
173
- instance = ReactTestUtils.renderIntoDocument(<HCaptcha
174
- assethost={ExpectHost}
175
- sitekey={TEST_PROPS.sitekey}
176
- />);
177
-
178
- const script = document.querySelector("head > script");
179
- expect(script.src).toContain(`assethost=${encodeURIComponent(ExpectHost)}`);
180
- });
181
-
182
- it("endpoint should be found when prop is set", () => {
183
- const ExpectHost = "https://test.com";
184
-
185
- instance = ReactTestUtils.renderIntoDocument(<HCaptcha
186
- endpoint={ExpectHost}
187
- sitekey={TEST_PROPS.sitekey}
188
- />);
189
-
190
- const script = document.querySelector("head > script");
191
- expect(script.src).toContain(`endpoint=${encodeURIComponent(ExpectHost)}`);
192
- });
193
-
194
- it("imghost should be found when prop is set", () => {
195
- const ExpectHost = "https://test.com";
196
-
197
- instance = ReactTestUtils.renderIntoDocument(<HCaptcha
198
- imghost={ExpectHost}
199
- sitekey={TEST_PROPS.sitekey}
200
- />);
201
-
202
- const script = document.querySelector("head > script");
203
- expect(script.src).toContain(`imghost=${encodeURIComponent(ExpectHost)}`);
204
- });
205
-
206
- it("reportapi should be found when prop is set", () => {
207
- const ExpectHost = "https://test.com";
208
-
209
- instance = ReactTestUtils.renderIntoDocument(<HCaptcha
210
- reportapi={ExpectHost}
211
- sitekey={TEST_PROPS.sitekey}
212
- />);
213
-
214
- const script = document.querySelector("head > script");
215
- expect(script.src).toContain(`reportapi=${encodeURIComponent(ExpectHost)}`);
216
- });
217
-
218
- it("hl should be found when prop languageOverride is set", () => {
219
- instance = ReactTestUtils.renderIntoDocument(<HCaptcha
220
- languageOverride="fr"
221
- sitekey={TEST_PROPS.sitekey}
222
- />);
223
-
224
- const script = document.querySelector("head > script");
225
- expect(script.src).toContain("hl=fr");
226
- });
227
-
228
- it("reCaptchaCompat should be found when prop is set to false", () => {
229
- instance = ReactTestUtils.renderIntoDocument(<HCaptcha
230
- reCaptchaCompat={false}
231
- sitekey={TEST_PROPS.sitekey}
232
- />);
233
-
234
- const script = document.querySelector("head > script");
235
- expect(script.src).toContain("recaptchacompat=off");
236
- });
237
-
238
- it("reCaptchaCompat should not be found when prop is set to anything except false", () => {
239
- instance = ReactTestUtils.renderIntoDocument(<HCaptcha
240
- reCaptchaCompat={true}
241
- sitekey={TEST_PROPS.sitekey}
242
- />);
243
-
244
- const script = document.querySelector("head > script");
245
- expect(script.src).not.toContain("recaptchacompat");
246
- });
247
-
248
- it("sentry should be found when prop is set", () => {
249
- instance = ReactTestUtils.renderIntoDocument(<HCaptcha
250
- sentry={true}
251
- sitekey={TEST_PROPS.sitekey}
252
- />);
253
-
254
- const script = document.querySelector("head > script");
255
- expect(script.src).toContain("sentry=true");
256
- });
257
-
258
- it("host should be found when prop is set", () => {
259
- instance = ReactTestUtils.renderIntoDocument(<HCaptcha
260
- host="test.com"
261
- sitekey={TEST_PROPS.sitekey}
262
- />);
263
-
264
- const script = document.querySelector("head > script");
265
- expect(script.src).toContain("host=test.com");
266
- });
267
-
268
- it("shouldn't create multiple scripts for multiple captchas", () => {
269
- ReactTestUtils.renderIntoDocument(<HCaptcha
270
- sitekey={TEST_PROPS.sitekey}
271
- />);
272
- ReactTestUtils.renderIntoDocument(<HCaptcha
273
- sitekey={TEST_PROPS.sitekey}
274
- />);
275
-
276
- const scripts = document.querySelectorAll("head > script");
277
-
278
- expect(scripts.length).toBe(1);
279
- })
280
- });
281
- });
@@ -1,44 +0,0 @@
1
- import { generateQuery } from "../src/utils.js";
2
-
3
- describe("Encode query", () => {
4
-
5
- it("Property foo to equal bar as string foo=bar:", () => {
6
- const params = {
7
- foo: "bar"
8
- };
9
- expect(generateQuery(params)).toBe("foo=bar");
10
- });
11
-
12
- it("Spaces to be encoded with %20", () => {
13
- const params = {
14
- foo: "bar baz bah"
15
- };
16
- expect(generateQuery(params)).toBe("foo=bar%20baz%20bah");
17
- });
18
-
19
- it("Chain multiple parameters", () => {
20
- const params = {
21
- foo: "bar",
22
- baz: true
23
- };
24
- expect(generateQuery(params)).toBe("foo=bar&baz=true");
25
- });
26
-
27
- it("false should be a valid query value", () => {
28
- const params = {
29
- foo: false
30
- };
31
- expect(generateQuery(params)).toBe("foo=false");
32
- });
33
-
34
- it("Null, undefined, and empty string values should be removed", () => {
35
- const params = {
36
- foo: "",
37
- bar: null,
38
- baz: undefined,
39
- bah: true
40
- };
41
- expect(generateQuery(params)).toBe("bah=true");
42
- });
43
-
44
- });
package/webpack.config.js DELETED
@@ -1,42 +0,0 @@
1
- // NPM Modules
2
- const Webpack = require('webpack');
3
- const Path = require('path');
4
- const HtmlWebpackPlugin = require("html-webpack-plugin");
5
-
6
- // Webpack Plugins
7
- const htmlPlugin = new HtmlWebpackPlugin({
8
- template: Path.join(__dirname, "./examples/src/index.html"),
9
- filename: "./index.html"
10
- });
11
-
12
- module.exports = {
13
- entry: Path.join(__dirname, "./examples/src/index.js"),
14
-
15
- module: {
16
- rules: [
17
- {
18
- test: /\.(js|jsx)$/,
19
- exclude: /node_modules/,
20
- use: ['babel-loader']
21
- }
22
- ]
23
- },
24
-
25
- resolve: {
26
- extensions: ['*', '.js', '.jsx']
27
- },
28
-
29
- output: {
30
- path: __dirname + '/dist',
31
- publicPath: '/',
32
- filename: 'bundle.js'
33
- },
34
-
35
- plugins: [
36
- htmlPlugin
37
- ],
38
-
39
- devServer: {
40
- port: 9000
41
- }
42
- };