Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
119 changes: 119 additions & 0 deletions components/xverify/actions/verify-address/verify-address.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
import app from "../../xverify.app.mjs";

export default {
key: "xverify-verify-address",
name: "Verify Address",
description: "Sends an address verification request. [See the documentation](https://apidocs.xverify.com/#address-verification-api-endpoint).",
version: "0.0.1",
type: "action",
props: {
app,
// eslint-disable-next-line pipedream/props-label, pipedream/props-description
info: {
type: "alert",
alertType: "info",
content: "**Note**: The `city`, `state`, and `zip` fields are optional. However, you must provide at least one of these fields to verify an address. If you provide all three fields, the API will use the city and state to verify the address.",
},
domain: {
propDefinition: [
app,
"domain",
],
},
address1: {
type: "string",
label: "Street Address 1",
description: "The street address to be verified.",
},
address2: {
type: "string",
label: "Street Address 2",
description: "The second line of the street address to be verified.",
optional: true,
},
city: {
type: "string",
label: "City",
description: "The city of the address to be verified.",
optional: true,
},
state: {
type: "string",
label: "State",
description: "The state of the address to be verified.",
optional: true,
},
zip: {
type: "string",
label: "Zip Code",
description: "The postal code of the address to be verified. **Required** if city and state are not provided.",
optional: true,
},
urbanization: {
type: "string",
label: "Urbanization",
description: "A component of certain addresses in Puerto Rico.",
optional: true,
},
parse: {
type: "boolean",
label: "Parse Address",
description: "Set to `true` if you want the street address to be parsed into individual elements in the response.",
optional: true,
},
aff: {
propDefinition: [
app,
"aff",
],
},
subaff: {
propDefinition: [
app,
"subaff",
],
},
},
methods: {
verifyAddress(args = {}) {
return this.app._makeRequest({
path: "/av",
...args,
});
},
},
async run({ $ }) {
const {
verifyAddress,
domain,
address1,
address2,
city,
state,
zip,
urbanization,
parse,
aff,
subaff,
} = this;

const response = await verifyAddress({
$,
params: {
domain,
address1,
address2,
city,
state,
zip,
urbanization,
parse,
aff,
subaff,
},
});

$.export("$summary", `Successfully sent address verification request with status \`${response.status}\`.`);
return response;
},
};
82 changes: 82 additions & 0 deletions components/xverify/actions/verify-email/verify-email.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
import app from "../../xverify.app.mjs";

export default {
key: "xverify-verify-email",
name: "Verify Email",
description: "Sends an email verification request. [See the documentation](https://apidocs.xverify.com/#email-verification-api-endpoint).",
version: "0.0.1",
type: "action",
props: {
app,
domain: {
propDefinition: [
app,
"domain",
],
},
email: {
propDefinition: [
app,
"email",
],
},
ip: {
type: "string",
label: "IP Address",
description: "IP address from which a user submitted an email address. Can be used to detect fraudulent or risky submissions.",
optional: true,
},
ua: {
type: "string",
label: "User Agent",
description: "User Agent of the browser that submitted the email address. Can be used to detect fraudlent or risky data.",
optional: true,
},
aff: {
propDefinition: [
app,
"aff",
],
},
subaff: {
propDefinition: [
app,
"subaff",
],
},
},
methods: {
verifyEmail(args = {}) {
return this.app._makeRequest({
path: "/ev",
...args,
});
},
Comment on lines +49 to +54
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Add response type validation in verifyEmail method.

The method should validate the response type from the API to ensure proper error handling.

 verifyEmail(args = {}) {
+  const responseSchema = {
+    status: 'string',
+    data: 'object',
+    error: 'string?'
+  };
   return this.app._makeRequest({
     path: "/ev",
     ...args,
+  }).then(response => {
+    // Validate response against schema
+    Object.entries(responseSchema).forEach(([key, type]) => {
+      const isOptional = type.endsWith('?');
+      const actualType = typeof response[key];
+      const expectedType = isOptional ? type.slice(0, -1) : type;
+      if (!isOptional && !response[key]) {
+        throw new Error(`Missing required field: ${key}`);
+      }
+      if (response[key] && actualType !== expectedType) {
+        throw new Error(`Invalid type for ${key}: expected ${expectedType}, got ${actualType}`);
+      }
+    });
+    return response;
   });
 },
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
verifyEmail(args = {}) {
return this.app._makeRequest({
path: "/ev",
...args,
});
},
verifyEmail(args = {}) {
const responseSchema = {
status: 'string',
data: 'object',
error: 'string?'
};
return this.app._makeRequest({
path: "/ev",
...args,
}).then(response => {
// Validate response against schema
Object.entries(responseSchema).forEach(([key, type]) => {
const isOptional = type.endsWith('?');
const actualType = typeof response[key];
const expectedType = isOptional ? type.slice(0, -1) : type;
if (!isOptional && !response[key]) {
throw new Error(`Missing required field: ${key}`);
}
if (response[key] && actualType !== expectedType) {
throw new Error(`Invalid type for ${key}: expected ${expectedType}, got ${actualType}`);
}
});
return response;
});
},

},
async run({ $ }) {
const {
verifyEmail,
domain,
email,
ip,
ua,
aff,
subaff,
} = this;

const response = await verifyEmail({
$,
params: {
domain,
email,
ip,
ua,
aff,
subaff,
},
});

$.export("$summary", `Successfully sent email verification with status \`${response.status}\`.`);
return response;
},
};
66 changes: 66 additions & 0 deletions components/xverify/actions/verify-phone/verify-phone.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
import app from "../../xverify.app.mjs";

export default {
key: "xverify-verify-phone",
name: "Verify Phone",
description: "Sends a phone verification request. [See the documentation](https://apidocs.xverify.com/#phone-verification-api-endpoint).",
version: "0.0.1",
type: "action",
props: {
app,
domain: {
propDefinition: [
app,
"domain",
],
},
phone: {
propDefinition: [
app,
"phone",
],
},
aff: {
propDefinition: [
app,
"aff",
],
},
subaff: {
propDefinition: [
app,
"subaff",
],
},
},
methods: {
verifyPhone(args = {}) {
return this.app._makeRequest({
path: "/pv",
...args,
});
},
},
async run({ $ }) {
const {
verifyPhone,
domain,
phone,
aff,
subaff,
} = this;

const response = await verifyPhone({
$,
params: {
domain,
phone,
aff,
subaff,
},
});

$.export("$summary", `Successfully sent verification with status \`${response.status}\`.`);
return response;
},
};
7 changes: 5 additions & 2 deletions components/xverify/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@pipedream/xverify",
"version": "0.0.1",
"version": "0.1.0",
"description": "Pipedream Xverify Components",
"main": "xverify.app.mjs",
"keywords": [
Expand All @@ -11,5 +11,8 @@
"author": "Pipedream <[email protected]> (https://pipedream.com/)",
"publishConfig": {
"access": "public"
},
"dependencies": {
"@pipedream/platform": "^3.0.3"
}
}
}
57 changes: 53 additions & 4 deletions components/xverify/xverify.app.mjs
Original file line number Diff line number Diff line change
@@ -1,11 +1,60 @@
import { axios } from "@pipedream/platform";

export default {
type: "app",
app: "xverify",
propDefinitions: {},
propDefinitions: {
domain: {
type: "string",
label: "Domain",
description: "The domain you have configured in your Xverify settings under which this query should be processed. See below.",
options() {
return [
this.$auth.domain,
];
},
},
email: {
type: "string",
label: "Email Address",
description: "The email address to be validated (and optionally corrected).",
},
aff: {
type: "string",
label: "Affiliate ID",
description: "The ID you define to identify the affiliate or source of the email for reporting or potential blocking.",
optional: true,
},
subaff: {
type: "string",
label: "Sub-Affiliate ID",
description: "The sub-identifier you define for the affiliate or source of the email for reporting or potential blocking.",
optional: true,
},
phone: {
type: "string",
label: "Phone Number",
description: "The phone number to be verified.",
},
Comment on lines +7 to +38
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Add validation for domain and email properties.

The propDefinitions should include validation for critical fields:

  1. Domain should be validated for proper format
  2. Email should be validated for proper format
 domain: {
   type: "string",
   label: "Domain",
   description: "The domain you have configured in your Xverify settings under which this query should be processed. See below.",
+  validate: (domain) => {
+    const domainRegex = /^[a-zA-Z0-9][a-zA-Z0-9-]{1,61}[a-zA-Z0-9]\.[a-zA-Z]{2,}$/;
+    if (!domainRegex.test(domain)) {
+      throw new Error('Invalid domain format');
+    }
+  },
   options() {
     return [
       this.$auth.domain,
     ];
   },
 },
 email: {
   type: "string",
   label: "Email Address",
   description: "The email address to be validated (and optionally corrected).",
+  validate: (email) => {
+    const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
+    if (!emailRegex.test(email)) {
+      throw new Error('Invalid email format');
+    }
+  },
 },
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
domain: {
type: "string",
label: "Domain",
description: "The domain you have configured in your Xverify settings under which this query should be processed. See below.",
options() {
return [
this.$auth.domain,
];
},
},
email: {
type: "string",
label: "Email Address",
description: "The email address to be validated (and optionally corrected).",
},
aff: {
type: "string",
label: "Affiliate ID",
description: "The ID you define to identify the affiliate or source of the email for reporting or potential blocking.",
optional: true,
},
subaff: {
type: "string",
label: "Sub-Affiliate ID",
description: "The sub-identifier you define for the affiliate or source of the email for reporting or potential blocking.",
optional: true,
},
phone: {
type: "string",
label: "Phone Number",
description: "The phone number to be verified.",
},
domain: {
type: "string",
label: "Domain",
description: "The domain you have configured in your Xverify settings under which this query should be processed. See below.",
validate: (domain) => {
const domainRegex = /^[a-zA-Z0-9][a-zA-Z0-9-]{1,61}[a-zA-Z0-9]\.[a-zA-Z]{2,}$/;
if (!domainRegex.test(domain)) {
throw new Error('Invalid domain format');
}
},
options() {
return [
this.$auth.domain,
];
},
},
email: {
type: "string",
label: "Email Address",
description: "The email address to be validated (and optionally corrected).",
validate: (email) => {
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
if (!emailRegex.test(email)) {
throw new Error('Invalid email format');
}
},
},
aff: {
type: "string",
label: "Affiliate ID",
description: "The ID you define to identify the affiliate or source of the email for reporting or potential blocking.",
optional: true,
},
subaff: {
type: "string",
label: "Sub-Affiliate ID",
description: "The sub-identifier you define for the affiliate or source of the email for reporting or potential blocking.",
optional: true,
},
phone: {
type: "string",
label: "Phone Number",
description: "The phone number to be verified.",
},

},
methods: {
// this.$auth contains connected account data
authKeys() {
console.log(Object.keys(this.$auth));
getUrl(path) {
return `https://api.xverify.com/v2${path}`;
},
getParams(params) {
return {
...params,
api_key: this.$auth.api_key,
};
},
_makeRequest({
$ = this, path, params, ...args
} = {}) {
return axios($, {
...args,
url: this.getUrl(path),
params: this.getParams(params),
});
},
},
};
8 changes: 5 additions & 3 deletions pnpm-lock.yaml

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

Loading