@dymo-api/better-auth 1.2.21 → 1.2.24

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
@@ -1,7 +1,31 @@
1
- # Official Dymo API Library for Better-Auth.
1
+ <div align="center">
2
+ <h1>Dymo API for Better-Auth</h1>
3
+ <h3>Official Dymo API Library for Better-Auth</h3>
4
+ <img src="https://img.shields.io/badge/TypeScript-purple?style=for-the-badge&logo=typescript&logoColor=white"/>
5
+ <a href="https://github.com/TPEOficial"> <img alt="GitHub" src="https://img.shields.io/badge/GitHub-purple?style=for-the-badge&logo=github&logoColor=white"/></a>
6
+ <a href="https://ko-fi.com/fjrg2007"> <img alt="Kofi" src="https://img.shields.io/badge/Ko--fi-purple?style=for-the-badge&logo=ko-fi&logoColor=white"></a>
7
+ <br />
8
+ <br />
9
+ <a href="https://docs.tpeoficial.com/docs/dymo-api/integrations/better-auth/email-validation?ch-pg=gh-dmapi-better-auth-rd-step">Quickstart</a>
10
+ <span>&nbsp;&nbsp;•&nbsp;&nbsp;</span>
11
+ <a href="https://tpe.li/dsc">Discord</a>
12
+ <span>&nbsp;&nbsp;•&nbsp;&nbsp;</span>
13
+ <a href="https://docs.tpeoficial.com/docs/dymo-api/integrations/better-auth/getting-started?ch-pg=gh-dmapi-better-auth-rd-step">All Features</a>
14
+ <span>&nbsp;&nbsp;•&nbsp;&nbsp;</span>
15
+ <a href="https://docs.tpeoficial.com/docs/dymo-api/getting-started/authentication?ch-pg=gh-dmapi-better-auth-rd-step">Node SDK</a>
16
+ <span>&nbsp;&nbsp;•&nbsp;&nbsp;</span>
17
+ <a href="https://docs.tpeoficial.com/docs/dymo-api/getting-started/faq?ch-pg=gh-dmapi-better-auth-rd-step">FAQ</a>
18
+ <br />
19
+ <hr />
20
+ </div>
2
21
 
3
22
  You can see the library documentation by clicking [here](https://docs.tpeoficial.com/docs/dymo-api/getting-started/libraries?ch-pg=r-dm-better-auth).
4
23
 
24
+ - ✅ World's largest fraud validation database | `fakeuser@temp.com` -> **Blocked**.
25
+ - ✅ Fraud validation for personal emails and OAuth (the only one on the market today) | `fakeuser@gmail.com` -> **Blocked**.
26
+ - ✅ Multi-data validation at no additional cost | Validate email addresses, phone numbers, and more at no additional cost, all in one place.
27
+ - ✅ Data normalization | `fo.o+tem.p@gmail.com` -> `foo@gmail.com`.
28
+
5
29
  #### Installation
6
30
 
7
31
  Use one of the following commands to install **Dymo API** in your `TS`/`JS` project.
@@ -1,5 +1,9 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.dymoEmailPlugin = void 0;
3
+ exports.dymoPhonePlugin = exports.dymoIPPlugin = exports.dymoEmailPlugin = void 0;
4
4
  var emailValidation_1 = require("./plugins/emailValidation/index.cjs");
5
5
  Object.defineProperty(exports, "dymoEmailPlugin", { enumerable: true, get: function () { return emailValidation_1.dymoEmailPlugin; } });
6
+ var ipValidation_1 = require("./plugins/ipValidation/index.cjs");
7
+ Object.defineProperty(exports, "dymoIPPlugin", { enumerable: true, get: function () { return ipValidation_1.dymoIPPlugin; } });
8
+ var phoneValidation_1 = require("./plugins/phoneValidation/index.cjs");
9
+ Object.defineProperty(exports, "dymoPhonePlugin", { enumerable: true, get: function () { return phoneValidation_1.dymoPhonePlugin; } });
@@ -18,7 +18,20 @@ const dymoEmailPlugin = ({ apiKey, applyToLogin = false, applyToOAuth = true, em
18
18
  }
19
19
  }
20
20
  });
21
- const activePaths = ["/sign-up/email"];
21
+ const activePaths = [
22
+ "/sign-up/email",
23
+ "/email-otp/verify-email",
24
+ "/sign-in/email-otp",
25
+ "/sign-in/magic-link",
26
+ "/forget-password/email-otp",
27
+ "/email-otp/reset-password",
28
+ "/email-otp/create-verification-otp",
29
+ "/email-otp/get-verification-otp",
30
+ "/email-otp/send-verification-otp",
31
+ "/forget-password",
32
+ "/send-verification-email",
33
+ "/change-email"
34
+ ];
22
35
  if (applyToLogin)
23
36
  activePaths.push("/sign-in/email");
24
37
  if (applyToOAuth) {
@@ -0,0 +1,76 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.dymoIPPlugin = void 0;
7
+ const api_1 = require("better-auth/api");
8
+ const dymo_api_1 = __importDefault(require("dymo-api"));
9
+ const ipHeaders = ["x-forwarded-for", "cf-connecting-ip", "x-vercel-forwarded-for", "x-real-ip"];
10
+ const dymoIPPlugin = ({ apiKey, applyToLogin = false, applyToOAuth = true, ipRules }) => {
11
+ const defaultRules = {
12
+ deny: ["FRAUD", "INVALID", "TOR_NETWORK"]
13
+ };
14
+ const dymoClient = new dymo_api_1.default({
15
+ apiKey,
16
+ rules: {
17
+ ip: {
18
+ deny: ipRules?.deny ?? defaultRules.deny
19
+ }
20
+ }
21
+ });
22
+ const activePaths = [
23
+ "/sign-up/email",
24
+ "/email-otp/verify-email",
25
+ "/sign-in/email-otp",
26
+ "/sign-in/magic-link",
27
+ "/forget-password/email-otp",
28
+ "/email-otp/reset-password",
29
+ "/email-otp/create-verification-otp",
30
+ "/email-otp/get-verification-otp",
31
+ "/email-otp/send-verification-otp",
32
+ "/forget-password",
33
+ "/send-verification-email",
34
+ "/change-email"
35
+ ];
36
+ if (applyToLogin)
37
+ activePaths.push("/sign-in/email");
38
+ if (applyToOAuth) {
39
+ activePaths.push("/sign-up/oauth");
40
+ activePaths.push("/sign-in/oauth");
41
+ }
42
+ return {
43
+ id: "dymoIPPlugin",
44
+ hooks: {
45
+ before: [
46
+ {
47
+ matcher: (context) => activePaths.some(path => context.path.startsWith(path)),
48
+ handler: (0, api_1.createAuthMiddleware)(async (ctx) => {
49
+ let ip = null;
50
+ for (const header of ipHeaders) {
51
+ const value = ctx.request.headers.get(header);
52
+ if (value) {
53
+ ip = value.split(",")[0].trim();
54
+ break;
55
+ }
56
+ }
57
+ if (typeof ip !== "string")
58
+ throw new api_1.APIError("BAD_REQUEST", { message: "IP must be a string." });
59
+ const decision = await dymoClient.isValidIP(ip);
60
+ if (!decision.allow) {
61
+ throw new api_1.APIError("BAD_REQUEST", {
62
+ message: "IP is invalid or blocked.",
63
+ reasons: decision.reasons
64
+ });
65
+ }
66
+ ctx.body.ip = decision.ip;
67
+ ctx.request.headers.set("x-dymo-client-ip", decision.ip);
68
+ ctx.dymoIP = decision.response;
69
+ return { context: ctx };
70
+ })
71
+ }
72
+ ]
73
+ }
74
+ };
75
+ };
76
+ exports.dymoIPPlugin = dymoIPPlugin;
@@ -0,0 +1,60 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.dymoPhonePlugin = void 0;
7
+ const api_1 = require("better-auth/api");
8
+ const dymo_api_1 = __importDefault(require("dymo-api"));
9
+ const dymoPhonePlugin = ({ apiKey, applyToLogin = false, applyToOAuth = true, phoneRules }) => {
10
+ const defaultRules = {
11
+ deny: ["FRAUD", "INVALID"]
12
+ };
13
+ const dymoClient = new dymo_api_1.default({
14
+ apiKey,
15
+ rules: {
16
+ phone: {
17
+ deny: phoneRules?.deny ?? defaultRules.deny
18
+ }
19
+ }
20
+ });
21
+ const activePaths = [
22
+ "/sign-in/phone-number",
23
+ "/phone-number/forget-password",
24
+ "/phone-number/reset-password",
25
+ "/phone-number/send-otp",
26
+ "/phone-number/verify"
27
+ ];
28
+ if (applyToLogin)
29
+ activePaths.push("/sign-in/email");
30
+ if (applyToOAuth) {
31
+ activePaths.push("/sign-up/oauth");
32
+ activePaths.push("/sign-in/oauth");
33
+ }
34
+ return {
35
+ id: "dymoPhonePlugin",
36
+ hooks: {
37
+ before: [
38
+ {
39
+ matcher: (context) => activePaths.some(path => context.path.startsWith(path)),
40
+ handler: (0, api_1.createAuthMiddleware)(async (ctx) => {
41
+ const phoneNumber = ctx.body?.phoneNumber || ctx.body?.profile?.phoneNumber;
42
+ if (typeof phoneNumber !== "string")
43
+ throw new api_1.APIError("BAD_REQUEST", { message: "Phone number must be a string." });
44
+ const decision = await dymoClient.isValidPhone(phoneNumber);
45
+ if (!decision.allow) {
46
+ throw new api_1.APIError("BAD_REQUEST", {
47
+ message: "Phone number is invalid or blocked.",
48
+ reasons: decision.reasons
49
+ });
50
+ }
51
+ ctx.body.phoneNumber = decision.phone;
52
+ ctx.dymoEmail = decision.response;
53
+ return { context: ctx };
54
+ })
55
+ }
56
+ ]
57
+ }
58
+ };
59
+ };
60
+ exports.dymoPhonePlugin = dymoPhonePlugin;
package/dist/esm/index.js CHANGED
@@ -1 +1,3 @@
1
1
  export { dymoEmailPlugin } from "./plugins/emailValidation";
2
+ export { dymoIPPlugin } from "./plugins/ipValidation";
3
+ export { dymoPhonePlugin } from "./plugins/phoneValidation";
@@ -12,7 +12,20 @@ export const dymoEmailPlugin = ({ apiKey, applyToLogin = false, applyToOAuth = t
12
12
  }
13
13
  }
14
14
  });
15
- const activePaths = ["/sign-up/email"];
15
+ const activePaths = [
16
+ "/sign-up/email",
17
+ "/email-otp/verify-email",
18
+ "/sign-in/email-otp",
19
+ "/sign-in/magic-link",
20
+ "/forget-password/email-otp",
21
+ "/email-otp/reset-password",
22
+ "/email-otp/create-verification-otp",
23
+ "/email-otp/get-verification-otp",
24
+ "/email-otp/send-verification-otp",
25
+ "/forget-password",
26
+ "/send-verification-email",
27
+ "/change-email"
28
+ ];
16
29
  if (applyToLogin)
17
30
  activePaths.push("/sign-in/email");
18
31
  if (applyToOAuth) {
@@ -0,0 +1,69 @@
1
+ import { APIError, createAuthMiddleware } from "better-auth/api";
2
+ import DymoAPI from "dymo-api";
3
+ const ipHeaders = ["x-forwarded-for", "cf-connecting-ip", "x-vercel-forwarded-for", "x-real-ip"];
4
+ export const dymoIPPlugin = ({ apiKey, applyToLogin = false, applyToOAuth = true, ipRules }) => {
5
+ const defaultRules = {
6
+ deny: ["FRAUD", "INVALID", "TOR_NETWORK"]
7
+ };
8
+ const dymoClient = new DymoAPI({
9
+ apiKey,
10
+ rules: {
11
+ ip: {
12
+ deny: ipRules?.deny ?? defaultRules.deny
13
+ }
14
+ }
15
+ });
16
+ const activePaths = [
17
+ "/sign-up/email",
18
+ "/email-otp/verify-email",
19
+ "/sign-in/email-otp",
20
+ "/sign-in/magic-link",
21
+ "/forget-password/email-otp",
22
+ "/email-otp/reset-password",
23
+ "/email-otp/create-verification-otp",
24
+ "/email-otp/get-verification-otp",
25
+ "/email-otp/send-verification-otp",
26
+ "/forget-password",
27
+ "/send-verification-email",
28
+ "/change-email"
29
+ ];
30
+ if (applyToLogin)
31
+ activePaths.push("/sign-in/email");
32
+ if (applyToOAuth) {
33
+ activePaths.push("/sign-up/oauth");
34
+ activePaths.push("/sign-in/oauth");
35
+ }
36
+ return {
37
+ id: "dymoIPPlugin",
38
+ hooks: {
39
+ before: [
40
+ {
41
+ matcher: (context) => activePaths.some(path => context.path.startsWith(path)),
42
+ handler: createAuthMiddleware(async (ctx) => {
43
+ let ip = null;
44
+ for (const header of ipHeaders) {
45
+ const value = ctx.request.headers.get(header);
46
+ if (value) {
47
+ ip = value.split(",")[0].trim();
48
+ break;
49
+ }
50
+ }
51
+ if (typeof ip !== "string")
52
+ throw new APIError("BAD_REQUEST", { message: "IP must be a string." });
53
+ const decision = await dymoClient.isValidIP(ip);
54
+ if (!decision.allow) {
55
+ throw new APIError("BAD_REQUEST", {
56
+ message: "IP is invalid or blocked.",
57
+ reasons: decision.reasons
58
+ });
59
+ }
60
+ ctx.body.ip = decision.ip;
61
+ ctx.request.headers.set("x-dymo-client-ip", decision.ip);
62
+ ctx.dymoIP = decision.response;
63
+ return { context: ctx };
64
+ })
65
+ }
66
+ ]
67
+ }
68
+ };
69
+ };
@@ -0,0 +1,53 @@
1
+ import { APIError, createAuthMiddleware } from "better-auth/api";
2
+ import DymoAPI from "dymo-api";
3
+ export const dymoPhonePlugin = ({ apiKey, applyToLogin = false, applyToOAuth = true, phoneRules }) => {
4
+ const defaultRules = {
5
+ deny: ["FRAUD", "INVALID"]
6
+ };
7
+ const dymoClient = new DymoAPI({
8
+ apiKey,
9
+ rules: {
10
+ phone: {
11
+ deny: phoneRules?.deny ?? defaultRules.deny
12
+ }
13
+ }
14
+ });
15
+ const activePaths = [
16
+ "/sign-in/phone-number",
17
+ "/phone-number/forget-password",
18
+ "/phone-number/reset-password",
19
+ "/phone-number/send-otp",
20
+ "/phone-number/verify"
21
+ ];
22
+ if (applyToLogin)
23
+ activePaths.push("/sign-in/email");
24
+ if (applyToOAuth) {
25
+ activePaths.push("/sign-up/oauth");
26
+ activePaths.push("/sign-in/oauth");
27
+ }
28
+ return {
29
+ id: "dymoPhonePlugin",
30
+ hooks: {
31
+ before: [
32
+ {
33
+ matcher: (context) => activePaths.some(path => context.path.startsWith(path)),
34
+ handler: createAuthMiddleware(async (ctx) => {
35
+ const phoneNumber = ctx.body?.phoneNumber || ctx.body?.profile?.phoneNumber;
36
+ if (typeof phoneNumber !== "string")
37
+ throw new APIError("BAD_REQUEST", { message: "Phone number must be a string." });
38
+ const decision = await dymoClient.isValidPhone(phoneNumber);
39
+ if (!decision.allow) {
40
+ throw new APIError("BAD_REQUEST", {
41
+ message: "Phone number is invalid or blocked.",
42
+ reasons: decision.reasons
43
+ });
44
+ }
45
+ ctx.body.phoneNumber = decision.phone;
46
+ ctx.dymoEmail = decision.response;
47
+ return { context: ctx };
48
+ })
49
+ }
50
+ ]
51
+ }
52
+ };
53
+ };
@@ -1 +1,3 @@
1
1
  export { dymoEmailPlugin } from "./plugins/emailValidation";
2
+ export { dymoIPPlugin } from "./plugins/ipValidation";
3
+ export { dymoPhonePlugin } from "./plugins/phoneValidation";
@@ -0,0 +1,19 @@
1
+ import { IPValidatorRules } from "dymo-api";
2
+ interface dymoIPPluginOptions {
3
+ apiKey: string;
4
+ applyToLogin?: boolean;
5
+ applyToOAuth?: boolean;
6
+ ipRules?: Partial<IPValidatorRules>;
7
+ }
8
+ export declare const dymoIPPlugin: ({ apiKey, applyToLogin, applyToOAuth, ipRules }: dymoIPPluginOptions) => {
9
+ id: "dymoIPPlugin";
10
+ hooks: {
11
+ before: {
12
+ matcher: (context: any) => boolean;
13
+ handler: (inputContext: import("better-auth").MiddlewareInputContext<import("better-auth").MiddlewareOptions>) => Promise<{
14
+ context: any;
15
+ }>;
16
+ }[];
17
+ };
18
+ };
19
+ export {};
@@ -0,0 +1,19 @@
1
+ import { PhoneValidatorRules } from "dymo-api";
2
+ interface DymoPhonePluginOptions {
3
+ apiKey: string;
4
+ applyToLogin?: boolean;
5
+ applyToOAuth?: boolean;
6
+ phoneRules?: Partial<PhoneValidatorRules>;
7
+ }
8
+ export declare const dymoPhonePlugin: ({ apiKey, applyToLogin, applyToOAuth, phoneRules }: DymoPhonePluginOptions) => {
9
+ id: "dymoPhonePlugin";
10
+ hooks: {
11
+ before: {
12
+ matcher: (context: any) => boolean;
13
+ handler: (inputContext: import("better-auth").MiddlewareInputContext<import("better-auth").MiddlewareOptions>) => Promise<{
14
+ context: any;
15
+ }>;
16
+ }[];
17
+ };
18
+ };
19
+ export {};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dymo-api/better-auth",
3
- "version": "1.2.21",
3
+ "version": "1.2.24",
4
4
  "description": "Flow system for Dymo API.",
5
5
  "main": "dist/cjs/index.js",
6
6
  "module": "dist/esm/index.js",
@@ -38,7 +38,18 @@
38
38
  "Dymo",
39
39
  "Dymo API",
40
40
  "TPEOficial",
41
- "Ciphera"
41
+ "Ciphera",
42
+ "email verification",
43
+ "email validation",
44
+ "disposable email detector",
45
+ "disposable checker",
46
+ "fraud detection",
47
+ "anti fraud",
48
+ "multiaccount detection",
49
+ "fake user prevention",
50
+ "bot detection",
51
+ "spam protection",
52
+ "user validation"
42
53
  ],
43
54
  "author": "TPEOficial LLC",
44
55
  "license": "Apache-2.0",
@@ -48,7 +59,7 @@
48
59
  "homepage": "https://dymo.tpeoficial.com",
49
60
  "dependencies": {
50
61
  "better-auth": "^1.3.23",
51
- "dymo-api": "^1.2.17",
62
+ "dymo-api": "^1.2.29",
52
63
  "path": "^0.12.7"
53
64
  },
54
65
  "contributors": [