@friendlycaptcha/server-sdk 0.1.2 → 0.2.0
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/CHANGELOG.md +6 -0
- package/README.md +1 -1
- package/dist/api/types.d.ts +13 -1
- package/dist/api/typesRiskIntelligence.d.ts +778 -0
- package/dist/api/typesRiskIntelligence.js +25 -0
- package/dist/api/typesRiskIntelligence.js.map +1 -0
- package/dist/client/client.d.ts +15 -0
- package/dist/client/client.js +28 -8
- package/dist/client/client.js.map +1 -1
- package/dist/client/version.gen.d.ts +1 -1
- package/dist/client/version.gen.js +1 -1
- package/dist/index.d.ts +829 -0
- package/package.json +16 -2
- package/.github/workflows/ci.yml +0 -50
- package/.github/workflows/publish.yml +0 -18
- package/.prettierrc +0 -3
- package/docs/index.md +0 -12
- package/docs/server-sdk.failed_due_to_client_error_code.md +0 -15
- package/docs/server-sdk.failed_to_decode_response_error_code.md +0 -13
- package/docs/server-sdk.failed_to_encode_error_code.md +0 -13
- package/docs/server-sdk.friendlycaptchaclient._constructor_.md +0 -20
- package/docs/server-sdk.friendlycaptchaclient.md +0 -26
- package/docs/server-sdk.friendlycaptchaclient.verifycaptcharesponse.md +0 -30
- package/docs/server-sdk.friendlycaptchaoptions.apikey.md +0 -13
- package/docs/server-sdk.friendlycaptchaoptions.fetch.md +0 -13
- package/docs/server-sdk.friendlycaptchaoptions.md +0 -24
- package/docs/server-sdk.friendlycaptchaoptions.sitekey.md +0 -11
- package/docs/server-sdk.friendlycaptchaoptions.siteverifyendpoint.md +0 -15
- package/docs/server-sdk.friendlycaptchaoptions.strict.md +0 -15
- package/docs/server-sdk.md +0 -41
- package/docs/server-sdk.request_failed_error_code.md +0 -13
- package/docs/server-sdk.request_failed_timeout_error_code.md +0 -13
- package/docs/server-sdk.siteverifyerrorresponse.error.md +0 -11
- package/docs/server-sdk.siteverifyerrorresponse.md +0 -20
- package/docs/server-sdk.siteverifyerrorresponse.success.md +0 -11
- package/docs/server-sdk.siteverifyerrorresponseerrordata.detail.md +0 -11
- package/docs/server-sdk.siteverifyerrorresponseerrordata.error_code.md +0 -11
- package/docs/server-sdk.siteverifyerrorresponseerrordata.md +0 -20
- package/docs/server-sdk.siteverifyresponse.md +0 -14
- package/docs/server-sdk.siteverifyresponsechallengedata.md +0 -20
- package/docs/server-sdk.siteverifyresponsechallengedata.origin.md +0 -13
- package/docs/server-sdk.siteverifyresponsechallengedata.timestamp.md +0 -13
- package/docs/server-sdk.siteverifyresponsedata.challenge.md +0 -11
- package/docs/server-sdk.siteverifyresponsedata.md +0 -19
- package/docs/server-sdk.siteverifysuccessresponse.data.md +0 -11
- package/docs/server-sdk.siteverifysuccessresponse.md +0 -20
- package/docs/server-sdk.siteverifysuccessresponse.success.md +0 -11
- package/docs/server-sdk.verifyclienterrorcode.md +0 -14
- package/docs/server-sdk.verifyresult._constructor_.md +0 -20
- package/docs/server-sdk.verifyresult.clienterrortype.md +0 -11
- package/docs/server-sdk.verifyresult.geterrorcode.md +0 -15
- package/docs/server-sdk.verifyresult.getresponse.md +0 -17
- package/docs/server-sdk.verifyresult.getresponseerror.md +0 -17
- package/docs/server-sdk.verifyresult.isclienterror.md +0 -19
- package/docs/server-sdk.verifyresult.isdecodeerror.md +0 -17
- package/docs/server-sdk.verifyresult.isencodeerror.md +0 -17
- package/docs/server-sdk.verifyresult.isrequestortimeouterror.md +0 -17
- package/docs/server-sdk.verifyresult.isstrict.md +0 -17
- package/docs/server-sdk.verifyresult.md +0 -44
- package/docs/server-sdk.verifyresult.response.md +0 -13
- package/docs/server-sdk.verifyresult.shouldaccept.md +0 -17
- package/docs/server-sdk.verifyresult.shouldreject.md +0 -17
- package/docs/server-sdk.verifyresult.status.md +0 -13
- package/docs/server-sdk.verifyresult.wasabletoverify.md +0 -17
- package/example/README.md +0 -29
- package/example/package-lock.json +0 -1404
- package/example/package.json +0 -24
- package/example/src/index.ts +0 -84
- package/example/tsconfig.json +0 -13
- package/example/views/index.ejs +0 -86
- package/src/api/errors.ts +0 -77
- package/src/api/index.ts +0 -1
- package/src/api/types.ts +0 -66
- package/src/client/client.ts +0 -157
- package/src/client/errors.ts +0 -42
- package/src/client/index.ts +0 -3
- package/src/client/result.ts +0 -152
- package/src/client/version.gen.ts +0 -3
- package/src/index.ts +0 -2
- package/test/client/client.test.ts +0 -47
- package/test/client/mock.test.ts +0 -44
- package/tsconfig.json +0 -20
package/example/package.json
DELETED
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "friendly-captcha-example",
|
|
3
|
-
"version": "1.0.0",
|
|
4
|
-
"description": "Friendly Captcha V2 Javascript SDK integration example",
|
|
5
|
-
"main": "index.js",
|
|
6
|
-
"type": "module",
|
|
7
|
-
"private": true,
|
|
8
|
-
"scripts": {
|
|
9
|
-
"start": "node --import tsx src/index.ts"
|
|
10
|
-
},
|
|
11
|
-
"author": "Friendly Captcha GmbH",
|
|
12
|
-
"license": "MIT",
|
|
13
|
-
"dependencies": {
|
|
14
|
-
"@friendlycaptcha/server-sdk": "^0.1.0",
|
|
15
|
-
"ejs": "^3.1.9",
|
|
16
|
-
"express": "^4.18.2"
|
|
17
|
-
},
|
|
18
|
-
"devDependencies": {
|
|
19
|
-
"@types/express": "^4.17.21",
|
|
20
|
-
"@types/node": "^20.11.5",
|
|
21
|
-
"tsx": "^4.7.0",
|
|
22
|
-
"typescript": "^5.3.3"
|
|
23
|
-
}
|
|
24
|
-
}
|
package/example/src/index.ts
DELETED
|
@@ -1,84 +0,0 @@
|
|
|
1
|
-
import express, { Request, Response } from "express";
|
|
2
|
-
import { FriendlyCaptchaClient } from "@friendlycaptcha/server-sdk";
|
|
3
|
-
|
|
4
|
-
type FormMessage = {
|
|
5
|
-
subject: string;
|
|
6
|
-
message: string;
|
|
7
|
-
};
|
|
8
|
-
|
|
9
|
-
const app = express();
|
|
10
|
-
const port = process.env.PORT || 3000;
|
|
11
|
-
|
|
12
|
-
const FRC_SITEKEY = process.env.FRC_SITEKEY;
|
|
13
|
-
const FRC_APIKEY = process.env.FRC_APIKEY;
|
|
14
|
-
|
|
15
|
-
// Optionally we can pass in custom endpoints to be used, such as "eu".
|
|
16
|
-
const FRC_SITEVERIFY_ENDPOINT = process.env.FRC_SITEVERIFY_ENDPOINT;
|
|
17
|
-
const FRC_WIDGET_ENDPOINT = process.env.FRC_WIDGET_ENDPOINT;
|
|
18
|
-
|
|
19
|
-
if (!FRC_SITEKEY || !FRC_APIKEY) {
|
|
20
|
-
console.error(
|
|
21
|
-
"Please set the FRC_SITEKEY and FRC_APIKEY environment values before running this example to your Friendly Captcha sitekey and API key respectively.",
|
|
22
|
-
);
|
|
23
|
-
process.exit(1);
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
const frcClient = new FriendlyCaptchaClient({
|
|
27
|
-
apiKey: FRC_APIKEY,
|
|
28
|
-
sitekey: FRC_SITEKEY,
|
|
29
|
-
siteverifyEndpoint: FRC_SITEVERIFY_ENDPOINT, // optional, defaults to "global"
|
|
30
|
-
});
|
|
31
|
-
|
|
32
|
-
app.set("view engine", "ejs");
|
|
33
|
-
app.use(express.urlencoded({ extended: true }));
|
|
34
|
-
|
|
35
|
-
app.get("/", (req: Request, res: Response) => {
|
|
36
|
-
res.render("index", {
|
|
37
|
-
message: "",
|
|
38
|
-
sitekey: FRC_SITEKEY,
|
|
39
|
-
widgetEndpoint: FRC_WIDGET_ENDPOINT,
|
|
40
|
-
});
|
|
41
|
-
});
|
|
42
|
-
|
|
43
|
-
app.post("/", async (req: Request, res: Response) => {
|
|
44
|
-
const formData = req.body;
|
|
45
|
-
const formMessage = formData as FormMessage;
|
|
46
|
-
|
|
47
|
-
const frcCaptchaResponse = formData["frc-captcha-response"];
|
|
48
|
-
const result = await frcClient.verifyCaptchaResponse(frcCaptchaResponse);
|
|
49
|
-
if (!result.wasAbleToVerify()) {
|
|
50
|
-
// In this case we were not actually able to verify the response embedded in the form, but we may still want to accept it.
|
|
51
|
-
// It could mean there is a network issue or that the service is down. In those cases you generally want to accept submissions anyhow.
|
|
52
|
-
// That's why we use `shouldAccept()` below to actually accept or reject the form submission. It will return true in these cases.
|
|
53
|
-
|
|
54
|
-
if (result.isClientError()) {
|
|
55
|
-
// Something is wrong with our configuration, check your API key!
|
|
56
|
-
// Send yourself an alert to fix this! Your site is unprotected until you fix this.
|
|
57
|
-
console.error("CAPTCHA CONFIG ERROR: ", result.getErrorCode(), result.getResponseError());
|
|
58
|
-
} else {
|
|
59
|
-
console.error("Failed to verify captcha response: ", result.getErrorCode(), result.getResponseError());
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
if (!result.shouldAccept()) {
|
|
64
|
-
res.render("index", {
|
|
65
|
-
message: "❌ Anti-robot check failed, please try again.",
|
|
66
|
-
sitekey: FRC_SITEKEY,
|
|
67
|
-
widgetEndpoint: FRC_WIDGET_ENDPOINT,
|
|
68
|
-
});
|
|
69
|
-
return;
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
// The captcha was OK, process the form.
|
|
73
|
-
formMessage; // Normally we would use the form data in `formMessage` here and submit it to our database.
|
|
74
|
-
|
|
75
|
-
res.render("index", {
|
|
76
|
-
message: "✅ Your message has been submitted successfully.",
|
|
77
|
-
sitekey: FRC_SITEKEY,
|
|
78
|
-
widgetEndpoint: FRC_WIDGET_ENDPOINT,
|
|
79
|
-
});
|
|
80
|
-
});
|
|
81
|
-
|
|
82
|
-
app.listen(port, () => {
|
|
83
|
-
console.log(`Server running at http://localhost:${port}`);
|
|
84
|
-
});
|
package/example/tsconfig.json
DELETED
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"compilerOptions": {
|
|
3
|
-
"target": "es6",
|
|
4
|
-
"module": "commonjs",
|
|
5
|
-
"outDir": "./dist",
|
|
6
|
-
"strict": true,
|
|
7
|
-
"esModuleInterop": true,
|
|
8
|
-
"skipLibCheck": true,
|
|
9
|
-
"forceConsistentCasingInFileNames": true
|
|
10
|
-
},
|
|
11
|
-
"include": ["src/**/*.ts"],
|
|
12
|
-
"exclude": ["node_modules"]
|
|
13
|
-
}
|
package/example/views/index.ejs
DELETED
|
@@ -1,86 +0,0 @@
|
|
|
1
|
-
<!doctype html>
|
|
2
|
-
<html lang="en">
|
|
3
|
-
|
|
4
|
-
<head>
|
|
5
|
-
<meta charset="utf-8" />
|
|
6
|
-
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
7
|
-
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
|
|
8
|
-
<title>Friendly Captcha Javascript SDK example</title>
|
|
9
|
-
<style>
|
|
10
|
-
* {
|
|
11
|
-
box-sizing: border-box;
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
body {
|
|
15
|
-
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, "Open Sans",
|
|
16
|
-
"Helvetica Neue", sans-serif;
|
|
17
|
-
display: flex;
|
|
18
|
-
align-items: center;
|
|
19
|
-
justify-content: center;
|
|
20
|
-
height: 100vh;
|
|
21
|
-
width: 100vw;
|
|
22
|
-
background-color: #f2f2f2;
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
h1 {
|
|
26
|
-
font-size: 1.4em;
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
main {
|
|
30
|
-
width: 100%;
|
|
31
|
-
max-width: 680px;
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
.message {
|
|
35
|
-
width: 100%;
|
|
36
|
-
padding: 0.5em 2em;
|
|
37
|
-
margin: 1.5em 0;
|
|
38
|
-
border-radius: 8px;
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
.message h2 {
|
|
42
|
-
margin-bottom: 0;
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
label {
|
|
46
|
-
display: block;
|
|
47
|
-
}
|
|
48
|
-
</style>
|
|
49
|
-
|
|
50
|
-
<script type="module" src="https://cdn.jsdelivr.net/npm/@friendlycaptcha/sdk@0.1.8/site.min.js" async defer></script>
|
|
51
|
-
<script nomodule src="https://cdn.jsdelivr.net/npm/@friendlycaptcha/sdk@0.1.8/site.compat.min.js" async
|
|
52
|
-
defer></script>
|
|
53
|
-
|
|
54
|
-
<!-- You can change the data-api-endpoint via this tag. More info here https://developer.friendlycaptcha.com/docs/sdk/configuration -->
|
|
55
|
-
<!-- <meta name="frc-api-endpoint" content="."> -->
|
|
56
|
-
</head>
|
|
57
|
-
|
|
58
|
-
<body>
|
|
59
|
-
<main>
|
|
60
|
-
<h1>Friendly Captcha JavaScript SDK form</h1>
|
|
61
|
-
<% if (message) { %>
|
|
62
|
-
<p>
|
|
63
|
-
<%= message %>
|
|
64
|
-
</p>
|
|
65
|
-
<% } %>
|
|
66
|
-
<form method="POST">
|
|
67
|
-
<div class="form-group">
|
|
68
|
-
<label>Subject:</label><br />
|
|
69
|
-
<input type="text" name="subject" /><br />
|
|
70
|
-
<label>Message:</label><br />
|
|
71
|
-
<textarea name="message"></textarea><br />
|
|
72
|
-
<div class="frc-captcha" data-sitekey="<%= sitekey %>" <% if (widgetEndpoint) { %> data-api-endpoint="<%=
|
|
73
|
-
widgetEndpoint %>" <% } %>></div>
|
|
74
|
-
<input style="margin-top: 1em" type="submit" value="Submit" />
|
|
75
|
-
</div>
|
|
76
|
-
</form>
|
|
77
|
-
</main>
|
|
78
|
-
|
|
79
|
-
<script>
|
|
80
|
-
if (window.history.replaceState) {
|
|
81
|
-
window.history.replaceState(null, null, window.location.href);
|
|
82
|
-
}
|
|
83
|
-
</script>
|
|
84
|
-
</body>
|
|
85
|
-
|
|
86
|
-
</html>
|
package/src/api/errors.ts
DELETED
|
@@ -1,77 +0,0 @@
|
|
|
1
|
-
export type SiteverifyErrorCode =
|
|
2
|
-
| typeof SITEKEY_INVALID
|
|
3
|
-
| typeof AUTH_INVALID
|
|
4
|
-
| typeof AUTH_REQUIRED
|
|
5
|
-
| typeof BAD_REQUEST
|
|
6
|
-
| typeof RESPONSE_TIMEOUT
|
|
7
|
-
| typeof RESPONSE_DUPLICATE
|
|
8
|
-
| typeof RESPONSE_INVALID
|
|
9
|
-
| typeof RESPONSE_MISSING
|
|
10
|
-
| typeof INTERNAL_SERVER_ERROR;
|
|
11
|
-
|
|
12
|
-
/**
|
|
13
|
-
* The API key you provided was invalid.
|
|
14
|
-
*
|
|
15
|
-
* HTTP status 401.
|
|
16
|
-
*/
|
|
17
|
-
export const AUTH_INVALID = "auth_invalid";
|
|
18
|
-
/**
|
|
19
|
-
* You forgot to set the `X-API-Key` header.
|
|
20
|
-
*
|
|
21
|
-
* HTTP status 401.
|
|
22
|
-
*/
|
|
23
|
-
export const AUTH_REQUIRED = "auth_required";
|
|
24
|
-
|
|
25
|
-
/**
|
|
26
|
-
* The sitekey in your request is invalid.
|
|
27
|
-
*
|
|
28
|
-
* HTTP status 400.
|
|
29
|
-
*/
|
|
30
|
-
export const SITEKEY_INVALID = "sitekey_invalid";
|
|
31
|
-
|
|
32
|
-
/**
|
|
33
|
-
* Something else is wrong with your request, e.g. your request body is empty.
|
|
34
|
-
*/
|
|
35
|
-
export const BAD_REQUEST = "bad_request";
|
|
36
|
-
/**
|
|
37
|
-
* The response has expired.
|
|
38
|
-
*
|
|
39
|
-
* HTTP status 200.
|
|
40
|
-
*/
|
|
41
|
-
export const RESPONSE_TIMEOUT = "response_timeout";
|
|
42
|
-
/**
|
|
43
|
-
* The response has already been used.
|
|
44
|
-
*
|
|
45
|
-
* HTTP status 200.
|
|
46
|
-
*/
|
|
47
|
-
export const RESPONSE_DUPLICATE = "response_duplicate";
|
|
48
|
-
/**
|
|
49
|
-
* The response you provided was invalid (perhaps the user tried to work around the captcha).
|
|
50
|
-
*
|
|
51
|
-
* HTTP status 200.
|
|
52
|
-
*/
|
|
53
|
-
export const RESPONSE_INVALID = "response_invalid";
|
|
54
|
-
/**
|
|
55
|
-
* You forgot to add the response parameter.
|
|
56
|
-
*
|
|
57
|
-
* HTTP status 400.
|
|
58
|
-
*/
|
|
59
|
-
export const RESPONSE_MISSING = "response_missing";
|
|
60
|
-
/**
|
|
61
|
-
* Something went wrong within the server. (Should never happen).
|
|
62
|
-
*
|
|
63
|
-
* HTTP status 500.
|
|
64
|
-
*/
|
|
65
|
-
export const INTERNAL_SERVER_ERROR = "internal_server_error";
|
|
66
|
-
|
|
67
|
-
export const ERROR_CODE_TO_STATUS: Record<SiteverifyErrorCode, number> = {
|
|
68
|
-
[SITEKEY_INVALID]: 400,
|
|
69
|
-
[AUTH_INVALID]: 401,
|
|
70
|
-
[AUTH_REQUIRED]: 401,
|
|
71
|
-
[BAD_REQUEST]: 400,
|
|
72
|
-
[RESPONSE_TIMEOUT]: 200,
|
|
73
|
-
[RESPONSE_DUPLICATE]: 200,
|
|
74
|
-
[RESPONSE_INVALID]: 200,
|
|
75
|
-
[RESPONSE_MISSING]: 400,
|
|
76
|
-
[INTERNAL_SERVER_ERROR]: 500,
|
|
77
|
-
};
|
package/src/api/index.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export * from "./types.js";
|
package/src/api/types.ts
DELETED
|
@@ -1,66 +0,0 @@
|
|
|
1
|
-
import { SiteverifyErrorCode } from "./errors";
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* The request we make to the Frienldy Captcha API.
|
|
5
|
-
* @internal
|
|
6
|
-
*/
|
|
7
|
-
export interface SiteverifyRequest {
|
|
8
|
-
/**
|
|
9
|
-
* The response value that the user submitted in the frc-captcha-response field
|
|
10
|
-
*/
|
|
11
|
-
response: string;
|
|
12
|
-
/**
|
|
13
|
-
* Optional: the sitekey that you want to make sure the puzzle was generated from.
|
|
14
|
-
*/
|
|
15
|
-
sitekey?: string;
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
/**
|
|
19
|
-
* @public
|
|
20
|
-
*/
|
|
21
|
-
export interface SiteverifyResponseData {
|
|
22
|
-
challenge: SiteverifyResponseChallengeData;
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
/**
|
|
26
|
-
* @public
|
|
27
|
-
*/
|
|
28
|
-
export interface SiteverifyResponseChallengeData {
|
|
29
|
-
/**
|
|
30
|
-
* Timestamp when the captcha challenge was completed (RFC3339).
|
|
31
|
-
*/
|
|
32
|
-
timestamp: string;
|
|
33
|
-
/**
|
|
34
|
-
* The origin of the site where the captcha was solved (if known, can be empty string if not known).
|
|
35
|
-
*/
|
|
36
|
-
origin: string;
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
/**
|
|
40
|
-
* @public
|
|
41
|
-
*/
|
|
42
|
-
export interface SiteverifySuccessResponse {
|
|
43
|
-
success: true;
|
|
44
|
-
data: SiteverifyResponseData;
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
/**
|
|
48
|
-
* @public
|
|
49
|
-
*/
|
|
50
|
-
export interface SiteverifyErrorResponseErrorData {
|
|
51
|
-
error_code: SiteverifyErrorCode;
|
|
52
|
-
detail: string;
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
/**
|
|
56
|
-
* @public
|
|
57
|
-
*/
|
|
58
|
-
export interface SiteverifyErrorResponse {
|
|
59
|
-
success: false;
|
|
60
|
-
error: SiteverifyErrorResponseErrorData;
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
/**
|
|
64
|
-
* @public
|
|
65
|
-
*/
|
|
66
|
-
export type SiteverifyResponse = SiteverifySuccessResponse | SiteverifyErrorResponse;
|
package/src/client/client.ts
DELETED
|
@@ -1,157 +0,0 @@
|
|
|
1
|
-
import type { SiteverifyRequest } from "../api/index.js";
|
|
2
|
-
import {
|
|
3
|
-
FAILED_DUE_TO_CLIENT_ERROR_CODE,
|
|
4
|
-
FAILED_TO_DECODE_RESPONSE_ERROR_CODE,
|
|
5
|
-
FAILED_TO_ENCODE_ERROR_CODE,
|
|
6
|
-
REQUEST_FAILED_ERROR_CODE,
|
|
7
|
-
REQUEST_FAILED_TIMEOUT_ERROR_CODE,
|
|
8
|
-
} from "./errors.js";
|
|
9
|
-
import { VerifyResult } from "./result.js";
|
|
10
|
-
import { SDK_VERSION } from "./version.gen.js";
|
|
11
|
-
|
|
12
|
-
/**
|
|
13
|
-
* Configuration options when creating a new `FriendlyCaptchaClient`.
|
|
14
|
-
* @public
|
|
15
|
-
*/
|
|
16
|
-
export interface FriendlyCaptchaOptions {
|
|
17
|
-
sitekey?: string;
|
|
18
|
-
/**
|
|
19
|
-
* Friendly Captcha API Key.
|
|
20
|
-
*/
|
|
21
|
-
apiKey: string;
|
|
22
|
-
|
|
23
|
-
/**
|
|
24
|
-
* The endpoint to use for the API. Can be "eu", "global", or a custom URL.
|
|
25
|
-
*
|
|
26
|
-
* Defaults to `"global"`.
|
|
27
|
-
*/
|
|
28
|
-
siteverifyEndpoint?: string;
|
|
29
|
-
|
|
30
|
-
/**
|
|
31
|
-
* Whether to use strict mode, which rejects all captcha responses which were not strictly verified.
|
|
32
|
-
*
|
|
33
|
-
* This is not recommended. Defaults to `false`.
|
|
34
|
-
*/
|
|
35
|
-
strict?: boolean;
|
|
36
|
-
|
|
37
|
-
/**
|
|
38
|
-
* The fetch implementation to use. Defaults to `globalThis.fetch`.
|
|
39
|
-
*/
|
|
40
|
-
fetch?: typeof globalThis.fetch;
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
const GLOBAL_SITEVERIFY_ENDPOINT = "https://global.frcapi.com/api/v2/captcha/siteverify";
|
|
44
|
-
const EU_SITEVERIFY_ENDPOINT = "https://eu.frcapi.com/api/v2/captcha/siteverify";
|
|
45
|
-
|
|
46
|
-
/**
|
|
47
|
-
* A client for the Friendly Captcha API.
|
|
48
|
-
* @public
|
|
49
|
-
*/
|
|
50
|
-
export class FriendlyCaptchaClient {
|
|
51
|
-
private sitekey?: string;
|
|
52
|
-
private apiKey: string;
|
|
53
|
-
private siteverifyEndpoint: string;
|
|
54
|
-
private strict: boolean;
|
|
55
|
-
|
|
56
|
-
private fetch: typeof globalThis.fetch;
|
|
57
|
-
|
|
58
|
-
constructor(opts: FriendlyCaptchaOptions) {
|
|
59
|
-
this.sitekey = opts.sitekey;
|
|
60
|
-
|
|
61
|
-
if (!opts.apiKey) {
|
|
62
|
-
throw new Error("api key is required");
|
|
63
|
-
}
|
|
64
|
-
this.apiKey = opts.apiKey;
|
|
65
|
-
|
|
66
|
-
let siteverifyEndpoint = opts.siteverifyEndpoint || "global";
|
|
67
|
-
if (siteverifyEndpoint === "global") {
|
|
68
|
-
siteverifyEndpoint = GLOBAL_SITEVERIFY_ENDPOINT;
|
|
69
|
-
} else if (siteverifyEndpoint === "eu") {
|
|
70
|
-
siteverifyEndpoint = EU_SITEVERIFY_ENDPOINT;
|
|
71
|
-
}
|
|
72
|
-
this.siteverifyEndpoint = siteverifyEndpoint;
|
|
73
|
-
|
|
74
|
-
this.strict = !!opts.strict;
|
|
75
|
-
this.fetch = opts.fetch || globalThis.fetch;
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
/**
|
|
79
|
-
* Verify a captcha response.
|
|
80
|
-
*
|
|
81
|
-
* @param response - The response token from the captcha.
|
|
82
|
-
* @param opts - Optional options object:
|
|
83
|
-
* * `timeout`: The timeout in milliseconds. Defaults to 20 seconds.
|
|
84
|
-
* * `sitekey`: The sitekey to use for this request. Defaults to the sitekey passed to the constructor (if any).
|
|
85
|
-
* @returns A promise that always resolves to a `VerifyResult` object, which contains the fields `shouldAccept()` and `wasAbleToVerify()`. This promise never rejects.
|
|
86
|
-
*/
|
|
87
|
-
public verifyCaptchaResponse(
|
|
88
|
-
response: string,
|
|
89
|
-
opts: { timeout?: number; sitekey?: string } = {},
|
|
90
|
-
): Promise<VerifyResult> {
|
|
91
|
-
const siteverifyRequest: SiteverifyRequest = {
|
|
92
|
-
response,
|
|
93
|
-
};
|
|
94
|
-
if (this.sitekey || opts.sitekey) {
|
|
95
|
-
siteverifyRequest.sitekey = this.sitekey || opts.sitekey;
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
const result = new VerifyResult(this.strict);
|
|
99
|
-
let body: string;
|
|
100
|
-
|
|
101
|
-
try {
|
|
102
|
-
body = JSON.stringify(siteverifyRequest);
|
|
103
|
-
} catch (e) {
|
|
104
|
-
result.clientErrorType = FAILED_TO_ENCODE_ERROR_CODE;
|
|
105
|
-
return Promise.resolve(result);
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
const headers = {
|
|
109
|
-
"Content-Type": "application/json",
|
|
110
|
-
Accept: "application/json",
|
|
111
|
-
"Frc-Sdk": "friendly-captcha-javascript-sdk@" + SDK_VERSION,
|
|
112
|
-
"X-Api-Key": this.apiKey,
|
|
113
|
-
};
|
|
114
|
-
|
|
115
|
-
const timeout = opts?.timeout || 20_000;
|
|
116
|
-
|
|
117
|
-
return new Promise((resolve) => {
|
|
118
|
-
const controller = new AbortController();
|
|
119
|
-
const signal = controller.signal;
|
|
120
|
-
setTimeout(() => {
|
|
121
|
-
controller.abort();
|
|
122
|
-
result.clientErrorType = REQUEST_FAILED_TIMEOUT_ERROR_CODE;
|
|
123
|
-
resolve(result);
|
|
124
|
-
}, timeout);
|
|
125
|
-
|
|
126
|
-
this.fetch(this.siteverifyEndpoint, {
|
|
127
|
-
method: "POST",
|
|
128
|
-
headers,
|
|
129
|
-
body,
|
|
130
|
-
signal,
|
|
131
|
-
})
|
|
132
|
-
.then((response) => {
|
|
133
|
-
result.status = response.status;
|
|
134
|
-
if (response.status >= 400 && response.status < 500) {
|
|
135
|
-
result.clientErrorType = FAILED_DUE_TO_CLIENT_ERROR_CODE;
|
|
136
|
-
}
|
|
137
|
-
return response.json().catch(() => {
|
|
138
|
-
result.clientErrorType = FAILED_TO_DECODE_RESPONSE_ERROR_CODE;
|
|
139
|
-
resolve(result);
|
|
140
|
-
});
|
|
141
|
-
})
|
|
142
|
-
.then((json) => {
|
|
143
|
-
if (typeof json !== "object" || json === null) {
|
|
144
|
-
result.clientErrorType = FAILED_TO_DECODE_RESPONSE_ERROR_CODE;
|
|
145
|
-
resolve(result);
|
|
146
|
-
return;
|
|
147
|
-
}
|
|
148
|
-
result.response = json;
|
|
149
|
-
resolve(result);
|
|
150
|
-
})
|
|
151
|
-
.catch((e) => {
|
|
152
|
-
result.clientErrorType = REQUEST_FAILED_ERROR_CODE;
|
|
153
|
-
resolve(result);
|
|
154
|
-
});
|
|
155
|
-
});
|
|
156
|
-
}
|
|
157
|
-
}
|
package/src/client/errors.ts
DELETED
|
@@ -1,42 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Failed to encode the captcha response. This means the captcha response was invalid and should never be accepted.
|
|
3
|
-
*
|
|
4
|
-
* @public
|
|
5
|
-
*/
|
|
6
|
-
export const FAILED_TO_ENCODE_ERROR_CODE = "failed_to_encode_request";
|
|
7
|
-
/**
|
|
8
|
-
*
|
|
9
|
-
* The request couldn't be made, perhaps there is a network outage, DNS issue, or the API is unreachable.
|
|
10
|
-
*
|
|
11
|
-
* @public
|
|
12
|
-
*/
|
|
13
|
-
export const REQUEST_FAILED_ERROR_CODE = "request_failed";
|
|
14
|
-
/**
|
|
15
|
-
*
|
|
16
|
-
* The request couldn't be made, perhaps there is a network outage, DNS issue, or the API is unreachable.
|
|
17
|
-
*
|
|
18
|
-
* @public
|
|
19
|
-
*/
|
|
20
|
-
export const REQUEST_FAILED_TIMEOUT_ERROR_CODE = "request_failed_due_to_timeout";
|
|
21
|
-
/**
|
|
22
|
-
* An error occured on the client side that could've been prevented. This generally means your configuration is wrong.
|
|
23
|
-
*
|
|
24
|
-
* Check your API key and sitekey.
|
|
25
|
-
* @public
|
|
26
|
-
*/
|
|
27
|
-
export const FAILED_DUE_TO_CLIENT_ERROR_CODE = "request_failed_due_to_client_error";
|
|
28
|
-
/**
|
|
29
|
-
* The response from the Friendly Captcha API could not be decoded.
|
|
30
|
-
*
|
|
31
|
-
* @public
|
|
32
|
-
*/
|
|
33
|
-
export const FAILED_TO_DECODE_RESPONSE_ERROR_CODE = "verification_response_could_not_be_decoded";
|
|
34
|
-
/**
|
|
35
|
-
* @public
|
|
36
|
-
*/
|
|
37
|
-
export type VerifyClientErrorCode =
|
|
38
|
-
| typeof FAILED_TO_ENCODE_ERROR_CODE
|
|
39
|
-
| typeof REQUEST_FAILED_ERROR_CODE
|
|
40
|
-
| typeof REQUEST_FAILED_TIMEOUT_ERROR_CODE
|
|
41
|
-
| typeof FAILED_DUE_TO_CLIENT_ERROR_CODE
|
|
42
|
-
| typeof FAILED_TO_DECODE_RESPONSE_ERROR_CODE;
|
package/src/client/index.ts
DELETED