Skip to content

Commit

Permalink
Revert "feat(loader): Use @hcaptcha/loader package for loading script"
Browse files Browse the repository at this point in the history
  • Loading branch information
faris-imi authored Nov 9, 2023
1 parent 78126ef commit fe8c560
Show file tree
Hide file tree
Showing 13 changed files with 5,554 additions and 169 deletions.
1 change: 0 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,6 @@ return <HCaptcha ref={captchaRef} onLoad={onLoad} sitekey={sitekey} {...props} /
|`imghost`|String|No|`-`|See enterprise docs.|
|`reportapi`|String|No|`-`|See enterprise docs.|
|`sentry`|String|No|`-`|See enterprise docs.|
| `cleanup` | Boolean | No | `true` | Remove script tag after setup.|
|`custom`|Boolean|No|`-`|See enterprise docs.|
|`loadAsync`|Boolean|No|`true`|Set if the script should be loaded asynchronously.|
|`scriptLocation`|Element|No|`document.head`| Location of where to append the script tag. Make sure to add it to an area that will persist to prevent loading multiple times in the same document view. Note: If `null` is provided, the `document.head` will be used.|
Expand Down
3 changes: 1 addition & 2 deletions demo/app/examples/AsyncExample.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -64,11 +64,10 @@ export function AsyncExample() {
onClose={handleClose}
onError={handleError}
onChalExpired={handleChallengeExpired}
sentry={false}
/>
<button onClick={executeCaptcha}>Execute asynchronously</button>
<button onClick={getRespKey}>Get Response Key</button>
<button onClick={getResponse}>Get Response</button>
</div>
);
}
}
3 changes: 1 addition & 2 deletions demo/app/examples/ClassExample.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,6 @@ export class ClassExample extends React.Component {
onClose={this.handleClose}
onError={this.handleError}
onChalExpired={this.handleChallengeExpired}
sentry={false}
/>
{isVerified &&
<div>
Expand All @@ -85,4 +84,4 @@ export class ClassExample extends React.Component {
</div>
);
}
}
}
3 changes: 1 addition & 2 deletions demo/app/examples/FrameExample.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,6 @@ export function FrameExample({ document }) {
onChalExpired={handleChallengeExpired}
scriptLocation={document.head}
challenge-container={document.body}
sentry={false}
/>
);
}
}
17 changes: 3 additions & 14 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 2 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@hcaptcha/react-hcaptcha",
"version": "1.9.0",
"version": "1.8.1",
"types": "types/index.d.ts",
"main": "dist/index.js",
"module": "dist/esm/index.js",
Expand Down Expand Up @@ -58,7 +58,6 @@
"webpack-dev-server": "^4.13.1"
},
"dependencies": {
"@babel/runtime": "^7.17.9",
"@hcaptcha/loader": "^1.0.8"
"@babel/runtime": "^7.17.9"
}
}
13 changes: 0 additions & 13 deletions src/constants.js

This file was deleted.

135 changes: 67 additions & 68 deletions src/index.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,51 @@
import * as React from 'react';
import { hCaptchaLoader, initSentry } from '@hcaptcha/loader';
import { generateQuery, getFrame, getMountElement } from './utils.js';

import { getFrame, getMountElement } from './utils.js';
import { breadcrumbMessages, scopeTag } from "./constants";
const SCRIPT_ID = 'hcaptcha-api-script-id';
const HCAPTCHA_LOAD_FN_NAME = 'hcaptchaOnLoad';

// Prevent loading API script multiple times
const scripts = [];

// Generate hCaptcha API script
const mountCaptchaScript = (params = {}) => {
const element = getMountElement(params.scriptLocation);
delete params.scriptLocation;

const frame = getFrame(element);
const script = scripts.find(({ scope }) => scope === frame.window);

if (frame.document.getElementById(SCRIPT_ID) && script) {
// API was already requested
return script.promise;
}

const promise = new Promise((resolve, reject) => {
// Create global onload callback
frame.window[HCAPTCHA_LOAD_FN_NAME] = resolve;

const domain = params.apihost || "https://js.hcaptcha.com";
delete params.apihost;

const script = frame.document.createElement("script");
script.id = SCRIPT_ID;
script.src = `${domain}/1/api.js?render=explicit&onload=${HCAPTCHA_LOAD_FN_NAME}`;

script.async = params.loadAsync !== undefined? params.loadAsync : true;
delete params.loadAsync;

script.onerror = (event) => reject('script-error');

const query = generateQuery(params);
script.src += query !== ""? `&${query}` : "";

element.appendChild(script);
});

scripts.push({ promise, scope: frame.window });

return promise;
};


class HCaptcha extends React.Component {
Expand Down Expand Up @@ -35,7 +78,6 @@ class HCaptcha extends React.Component {

this.ref = React.createRef();
this.apiScriptRequested = false;
this.sentryHub = null;

this.state = {
isApiReady: false,
Expand All @@ -52,13 +94,6 @@ class HCaptcha extends React.Component {

const isApiReady = typeof this._hcaptcha !== 'undefined';

this.sentryHub = initSentry(this.props.sentry, scopeTag);

this.sentryHub.addBreadcrumb({
category: scopeTag.value,
message: breadcrumbMessages.mounted,
});

/*
* Check if hCaptcha has already been loaded,
* If Yes, render the captcha
Expand Down Expand Up @@ -91,11 +126,6 @@ class HCaptcha extends React.Component {
// Reset any stored variables / timers when unmounting
hcaptcha.reset(captchaId);
hcaptcha.remove(captchaId);

this.sentryHub.addBreadcrumb({
category: scopeTag.value,
message: breadcrumbMessages.unmounted,
});
}

shouldComponentUpdate(nextProps, nextState) {
Expand Down Expand Up @@ -138,30 +168,26 @@ class HCaptcha extends React.Component {
sentry,
custom,
loadAsync,
scriptLocation,
cleanup = true,
scriptLocation
} = this.props;
const mountParams = {
render: 'explicit',
apihost,
assethost,
endpoint,
hl,
host,
imghost,
recaptchacompat: reCaptchaCompat === false? 'off' : null,
recaptchacompat: reCaptchaCompat === false? "off" : null,
reportapi,
sentry,
custom,
loadAsync,
scriptLocation,
cleanup
};

hCaptchaLoader(mountParams)
.then(this.handleOnLoad, this.handleError)
.catch(this.handleError);

mountCaptchaScript(mountParams)
.then(this.handleOnLoad)
.catch(this.handleError);
this.apiScriptRequested = true;
}

Expand Down Expand Up @@ -199,11 +225,6 @@ class HCaptcha extends React.Component {
}
// Reset captcha state, removes stored token and unticks checkbox
hcaptcha.reset(captchaId)

this.sentryHub.addBreadcrumb({
category: scopeTag.value,
message: breadcrumbMessages.reset,
});
}

removeCaptcha(callback) {
Expand All @@ -218,33 +239,21 @@ class HCaptcha extends React.Component {
hcaptcha.remove(captchaId);
callback && callback()
});


this.sentryHub.addBreadcrumb({
category: scopeTag.value,
message: breadcrumbMessages.removed,
});
}

handleOnLoad () {
handleOnLoad () {
this.setState({ isApiReady: true }, () => {
try {
const element = getMountElement(this.props.scriptLocation);
const frame = getFrame(element);

this._hcaptcha = frame.window.hcaptcha;
const element = getMountElement(this.props.scriptLocation);
const frame = getFrame(element);

this._hcaptcha = frame.window.hcaptcha;

// render captcha and wait for captcha id
this.renderCaptcha(() => {
// render captcha and wait for captcha id
this.renderCaptcha(() => {
// trigger onLoad if it exists

const { onLoad } = this.props;
if (onLoad) onLoad();
});
} catch (error) {
this.sentryHub.captureException(error);
}
});
});
}

Expand Down Expand Up @@ -272,11 +281,6 @@ class HCaptcha extends React.Component {
hcaptcha.reset(captchaId) // If hCaptcha runs into error, reset captcha - hCaptcha

if (onExpire) onExpire();

this.sentryHub.addBreadcrumb({
category: scopeTag.value,
message: breadcrumbMessages.expired,
});
}

handleError (event) {
Expand Down Expand Up @@ -323,23 +327,18 @@ class HCaptcha extends React.Component {
}

execute (opts = null) {
try {
const { captchaId } = this.state;
const hcaptcha = this._hcaptcha;


if (!this.isReady()) {
return;
}
const { captchaId } = this.state;
const hcaptcha = this._hcaptcha;

if (opts && typeof opts !== "object") {
opts = null;
}
if (!this.isReady()) {
return;
}

return hcaptcha.execute(captchaId, opts);
} catch (error) {
this.sentryHub.captureException(error);
if (opts && typeof opts !== "object") {
opts = null;
}

return hcaptcha.execute(captchaId, opts);
}

setData (data) {
Expand Down
11 changes: 10 additions & 1 deletion src/utils.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,11 @@
function generateQuery(params) {
return Object.entries(params)
.filter(([key, value]) => value || value === false)
.map(([key, value]) => {
return `${encodeURIComponent(key)}=${encodeURIComponent(value)}`
}).join("&");
};

function getFrame(element) {
const doc = (element && element.ownerDocument) || document;
const win = doc.defaultView || doc.parentWindow || window;
Expand All @@ -10,6 +18,7 @@ function getMountElement(element) {
}

export {
generateQuery,
getFrame,
getMountElement
};
};
Loading

0 comments on commit fe8c560

Please sign in to comment.