@captchafox/node 1.2.0 → 1.4.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/dist/index.d.mts CHANGED
@@ -1,3 +1,14 @@
1
+ type ParseErrorProps = {
2
+ code?: number;
3
+ message: string;
4
+ body: string;
5
+ };
6
+ declare class ParseError extends Error {
7
+ code: number | undefined;
8
+ body: string;
9
+ constructor({ code, message, body }: ParseErrorProps);
10
+ }
11
+
1
12
  /**
2
13
  * The response returned from the /siteverify
3
14
  * endpoint used for verifying the challenge token.
@@ -15,18 +26,17 @@ type VerifyResponse = {
15
26
  /** List of error codes. Only included if success is false */
16
27
  'error-codes'?: string[];
17
28
  };
18
- type VerifyPayload = NodeJS.Dict<string> & {
19
- /** The organization secret */
20
- secret: string;
21
- /** The response token from the widget */
22
- response: string;
29
+ type OptionalProps = {
23
30
  /** (Optional) The sitekey that was used to issue the token */
24
31
  sitekey?: string;
25
32
  /** (Optional) The IP address of the requesting user */
26
33
  remoteIp?: string;
34
+ retry?: {
35
+ attempts?: number;
36
+ };
27
37
  };
28
- declare function verify(secret: string, token: string, sitekey?: string, remoteIp?: string): Promise<VerifyResponse>;
38
+ declare function verify(secret: string, token: string, options?: OptionalProps): Promise<VerifyResponse>;
29
39
 
30
40
  declare const CAPTCHA_RESPONSE_KEY = "cf-captcha-response";
31
41
 
32
- export { CAPTCHA_RESPONSE_KEY, VerifyPayload, VerifyResponse, verify };
42
+ export { CAPTCHA_RESPONSE_KEY, ParseError, type VerifyResponse, verify };
package/dist/index.d.ts CHANGED
@@ -1,3 +1,14 @@
1
+ type ParseErrorProps = {
2
+ code?: number;
3
+ message: string;
4
+ body: string;
5
+ };
6
+ declare class ParseError extends Error {
7
+ code: number | undefined;
8
+ body: string;
9
+ constructor({ code, message, body }: ParseErrorProps);
10
+ }
11
+
1
12
  /**
2
13
  * The response returned from the /siteverify
3
14
  * endpoint used for verifying the challenge token.
@@ -15,18 +26,17 @@ type VerifyResponse = {
15
26
  /** List of error codes. Only included if success is false */
16
27
  'error-codes'?: string[];
17
28
  };
18
- type VerifyPayload = NodeJS.Dict<string> & {
19
- /** The organization secret */
20
- secret: string;
21
- /** The response token from the widget */
22
- response: string;
29
+ type OptionalProps = {
23
30
  /** (Optional) The sitekey that was used to issue the token */
24
31
  sitekey?: string;
25
32
  /** (Optional) The IP address of the requesting user */
26
33
  remoteIp?: string;
34
+ retry?: {
35
+ attempts?: number;
36
+ };
27
37
  };
28
- declare function verify(secret: string, token: string, sitekey?: string, remoteIp?: string): Promise<VerifyResponse>;
38
+ declare function verify(secret: string, token: string, options?: OptionalProps): Promise<VerifyResponse>;
29
39
 
30
40
  declare const CAPTCHA_RESPONSE_KEY = "cf-captcha-response";
31
41
 
32
- export { CAPTCHA_RESPONSE_KEY, VerifyPayload, VerifyResponse, verify };
42
+ export { CAPTCHA_RESPONSE_KEY, ParseError, type VerifyResponse, verify };
package/dist/index.js CHANGED
@@ -21,16 +21,50 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
21
21
  var src_exports = {};
22
22
  __export(src_exports, {
23
23
  CAPTCHA_RESPONSE_KEY: () => CAPTCHA_RESPONSE_KEY,
24
+ ParseError: () => ParseError,
24
25
  verify: () => verify
25
26
  });
26
27
  module.exports = __toCommonJS(src_exports);
27
28
 
29
+ // src/errors/ParseError.ts
30
+ var ParseError = class extends Error {
31
+ code;
32
+ body;
33
+ constructor({ code, message, body }) {
34
+ super(message);
35
+ this.code = code;
36
+ this.body = body;
37
+ }
38
+ };
39
+
28
40
  // src/verify.ts
29
41
  var import_https = require("https");
30
42
  var import_querystring = require("querystring");
43
+
44
+ // src/withRetry.ts
45
+ var backoff = (retryCount) => Math.exp(retryCount) * 100;
46
+ var withRetry = async (callback, { attempts = 4 } = {}) => {
47
+ let res;
48
+ let error;
49
+ for (let i = 0; i < attempts; i++) {
50
+ try {
51
+ res = await callback();
52
+ break;
53
+ } catch (err) {
54
+ error = err;
55
+ await new Promise((r) => setTimeout(r, backoff(i)));
56
+ }
57
+ }
58
+ if (!res) {
59
+ throw error ?? new Error("Exhausted all retries");
60
+ }
61
+ return res;
62
+ };
63
+
64
+ // src/verify.ts
31
65
  var HOST = "api.captchafox.com";
32
66
  var API_PATH = "/siteverify";
33
- async function verify(secret, token, sitekey, remoteIp) {
67
+ async function verifyRequest(secret, token, sitekey, remoteIp) {
34
68
  return new Promise(function verifyPromise(resolve, reject) {
35
69
  const payload = { secret, response: token };
36
70
  if (sitekey) {
@@ -52,25 +86,44 @@ async function verify(secret, token, sitekey, remoteIp) {
52
86
  const apiRequest = (0, import_https.request)(options, (response) => {
53
87
  response.setEncoding("utf8");
54
88
  let responseBuffer = "";
55
- response.on("error", reject).on("data", (chunk) => responseBuffer += chunk).on("end", () => {
89
+ response.on("error", (error) => {
90
+ reject(error);
91
+ }).on("data", (chunk) => responseBuffer += chunk).on("end", () => {
56
92
  try {
57
93
  const json = JSON.parse(responseBuffer);
58
94
  resolve(json);
59
95
  } catch (error) {
96
+ if (error instanceof SyntaxError) {
97
+ const errorResponse = new ParseError({
98
+ code: response.statusCode,
99
+ message: error.message,
100
+ body: responseBuffer
101
+ });
102
+ reject(errorResponse);
103
+ return;
104
+ }
60
105
  reject(error);
61
106
  }
62
107
  });
63
108
  });
64
- apiRequest.on("error", reject);
109
+ apiRequest.on("error", (error) => {
110
+ reject(error);
111
+ });
65
112
  apiRequest.write(data);
66
113
  apiRequest.end();
67
114
  });
68
115
  }
116
+ async function verify(secret, token, options) {
117
+ return withRetry(() => {
118
+ return verifyRequest(secret, token, options == null ? void 0 : options.sitekey, options == null ? void 0 : options.remoteIp);
119
+ }, options == null ? void 0 : options.retry);
120
+ }
69
121
 
70
122
  // src/index.ts
71
123
  var CAPTCHA_RESPONSE_KEY = "cf-captcha-response";
72
124
  // Annotate the CommonJS export names for ESM import in node:
73
125
  0 && (module.exports = {
74
126
  CAPTCHA_RESPONSE_KEY,
127
+ ParseError,
75
128
  verify
76
129
  });
package/dist/index.mjs CHANGED
@@ -1,9 +1,42 @@
1
+ // src/errors/ParseError.ts
2
+ var ParseError = class extends Error {
3
+ code;
4
+ body;
5
+ constructor({ code, message, body }) {
6
+ super(message);
7
+ this.code = code;
8
+ this.body = body;
9
+ }
10
+ };
11
+
1
12
  // src/verify.ts
2
13
  import { request } from "https";
3
14
  import { stringify } from "querystring";
15
+
16
+ // src/withRetry.ts
17
+ var backoff = (retryCount) => Math.exp(retryCount) * 100;
18
+ var withRetry = async (callback, { attempts = 4 } = {}) => {
19
+ let res;
20
+ let error;
21
+ for (let i = 0; i < attempts; i++) {
22
+ try {
23
+ res = await callback();
24
+ break;
25
+ } catch (err) {
26
+ error = err;
27
+ await new Promise((r) => setTimeout(r, backoff(i)));
28
+ }
29
+ }
30
+ if (!res) {
31
+ throw error ?? new Error("Exhausted all retries");
32
+ }
33
+ return res;
34
+ };
35
+
36
+ // src/verify.ts
4
37
  var HOST = "api.captchafox.com";
5
38
  var API_PATH = "/siteverify";
6
- async function verify(secret, token, sitekey, remoteIp) {
39
+ async function verifyRequest(secret, token, sitekey, remoteIp) {
7
40
  return new Promise(function verifyPromise(resolve, reject) {
8
41
  const payload = { secret, response: token };
9
42
  if (sitekey) {
@@ -25,24 +58,43 @@ async function verify(secret, token, sitekey, remoteIp) {
25
58
  const apiRequest = request(options, (response) => {
26
59
  response.setEncoding("utf8");
27
60
  let responseBuffer = "";
28
- response.on("error", reject).on("data", (chunk) => responseBuffer += chunk).on("end", () => {
61
+ response.on("error", (error) => {
62
+ reject(error);
63
+ }).on("data", (chunk) => responseBuffer += chunk).on("end", () => {
29
64
  try {
30
65
  const json = JSON.parse(responseBuffer);
31
66
  resolve(json);
32
67
  } catch (error) {
68
+ if (error instanceof SyntaxError) {
69
+ const errorResponse = new ParseError({
70
+ code: response.statusCode,
71
+ message: error.message,
72
+ body: responseBuffer
73
+ });
74
+ reject(errorResponse);
75
+ return;
76
+ }
33
77
  reject(error);
34
78
  }
35
79
  });
36
80
  });
37
- apiRequest.on("error", reject);
81
+ apiRequest.on("error", (error) => {
82
+ reject(error);
83
+ });
38
84
  apiRequest.write(data);
39
85
  apiRequest.end();
40
86
  });
41
87
  }
88
+ async function verify(secret, token, options) {
89
+ return withRetry(() => {
90
+ return verifyRequest(secret, token, options == null ? void 0 : options.sitekey, options == null ? void 0 : options.remoteIp);
91
+ }, options == null ? void 0 : options.retry);
92
+ }
42
93
 
43
94
  // src/index.ts
44
95
  var CAPTCHA_RESPONSE_KEY = "cf-captcha-response";
45
96
  export {
46
97
  CAPTCHA_RESPONSE_KEY,
98
+ ParseError,
47
99
  verify
48
100
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@captchafox/node",
3
- "version": "1.2.0",
3
+ "version": "1.4.0",
4
4
  "main": "./dist/index.js",
5
5
  "module": "./dist/index.mjs",
6
6
  "types": "./dist/index.d.ts",
@@ -36,7 +36,7 @@
36
36
  "@types/node": "^18.13.0",
37
37
  "jest": "^29.7.0",
38
38
  "nock": "^13.3.3",
39
- "tsup": "^7.2.0",
39
+ "tsup": "^8.3.5",
40
40
  "ts-jest": "^29.1.1",
41
41
  "typescript": "^5.0.2"
42
42
  },