diff --git a/components/predictleads/actions/get-technologies/get-technologies.mjs b/components/predictleads/actions/get-technologies/get-technologies.mjs new file mode 100644 index 0000000000000..d1c93167d7636 --- /dev/null +++ b/components/predictleads/actions/get-technologies/get-technologies.mjs @@ -0,0 +1,22 @@ +import app from "../../predictleads.app.mjs"; + +export default { + key: "predictleads-get-technologies", + name: "Get Technologies", + description: "Retrieve a list of technologies that PredictLeads tracks. [See the documentation](https://docs.predictleads.com/v3/api_endpoints/technologies_dataset/retrieve_all_tracked_technologies)", + version: "0.0.1", + type: "action", + props: { + app, + }, + async run({ $ }) { + const response = await this.app.retrieveTechnologies({ + $, + params: { + limit: 1000, + }, + }); + $.export("$summary", "Successfully retrieved the first page of technologies."); + return response; + }, +}; diff --git a/components/predictleads/actions/lookup-company/lookup-company.mjs b/components/predictleads/actions/lookup-company/lookup-company.mjs new file mode 100644 index 0000000000000..95f9aa61ccebe --- /dev/null +++ b/components/predictleads/actions/lookup-company/lookup-company.mjs @@ -0,0 +1,36 @@ +import app from "../../predictleads.app.mjs"; + +export default { + key: "predictleads-lookup-company", + name: "Lookup Company By Domain", + description: "Lookup a company by their domain. [See the documentation](https://docs.predictleads.com/v3/api_endpoints/companies_dataset/retrieve_company)", + version: "0.0.1", + type: "action", + props: { + app, + domain: { + propDefinition: [ + app, + "domain", + ], + }, + }, + async run({ $ }) { + const { + app, + domain, + } = this; + + const response = await app.retrieveCompany({ + $, + domain, + }); + + if (response.data.length > 0) { + $.export("$summary", `Successfully found company for domain \`${domain}\`.`); + } else { + $.export("$summary", `No company found for domain \`${domain}\`.`); + } + return response; + }, +}; diff --git a/components/predictleads/actions/retrieve-companies-by-technology/retrieve-companies-by-technology.mjs b/components/predictleads/actions/retrieve-companies-by-technology/retrieve-companies-by-technology.mjs new file mode 100644 index 0000000000000..282687b3ca54d --- /dev/null +++ b/components/predictleads/actions/retrieve-companies-by-technology/retrieve-companies-by-technology.mjs @@ -0,0 +1,30 @@ +import app from "../../predictleads.app.mjs"; + +export default { + key: "predictleads-retrieve-companies-by-technology", + name: "Retrieve Companies By Technology", + description: "Retrieve companies that use a specific technology. [See the documentation](https://docs.predictleads.com/v3/api_endpoints/technologies_dataset/retrieve_a_single_technology_by_id)", + version: "0.0.1", + type: "action", + props: { + app, + technologyId: { + propDefinition: [ + app, + "technologyId", + ], + }, + }, + async run({ $ }) { + const { + app, + technologyId, + } = this; + const response = await app.retrieveCompaniesByTechnology({ + $, + technologyId, + }); + $.export("$summary", "Successfully retrieved the first page of companies."); + return response; + }, +}; diff --git a/components/predictleads/actions/retrieve-news-events-by-domain/retrieve-news-events-by-domain.mjs b/components/predictleads/actions/retrieve-news-events-by-domain/retrieve-news-events-by-domain.mjs new file mode 100644 index 0000000000000..97f5f1e937632 --- /dev/null +++ b/components/predictleads/actions/retrieve-news-events-by-domain/retrieve-news-events-by-domain.mjs @@ -0,0 +1,31 @@ +import app from "../../predictleads.app.mjs"; + +export default { + key: "predictleads-retrieve-news-events-by-domain", + name: "Retrieve News Events By Domain", + description: "Retrieve news events for a company by domain. [See the documentation](https://docs.predictleads.com/v3/api_endpoints/news_events_dataset/retrieve_company_s_news_events)", + version: "0.0.1", + type: "action", + props: { + app, + domain: { + description: "The domain of the company to retrieve news events for (e.g., `google.com`).", + propDefinition: [ + app, + "domain", + ], + }, + }, + async run({ $ }) { + const { + app, + domain, + } = this; + const response = await app.retrieveNewsEvents({ + $, + domain, + }); + $.export("$summary", "Successfully retrieved the first page of news events."); + return response; + }, +}; diff --git a/components/predictleads/package.json b/components/predictleads/package.json index e1636833be8ce..ed2f0f21a0f1b 100644 --- a/components/predictleads/package.json +++ b/components/predictleads/package.json @@ -1,6 +1,6 @@ { "name": "@pipedream/predictleads", - "version": "0.0.1", + "version": "0.1.0", "description": "Pipedream PredictLeads Components", "main": "predictleads.app.mjs", "keywords": [ @@ -11,5 +11,8 @@ "author": "Pipedream (https://pipedream.com/)", "publishConfig": { "access": "public" + }, + "dependencies": { + "@pipedream/platform": "^3.1.0" } -} \ No newline at end of file +} diff --git a/components/predictleads/predictleads.app.mjs b/components/predictleads/predictleads.app.mjs index 46b3bef6f030c..4d81e3ef24c65 100644 --- a/components/predictleads/predictleads.app.mjs +++ b/components/predictleads/predictleads.app.mjs @@ -1,11 +1,158 @@ +import { axios } from "@pipedream/platform"; + export default { type: "app", app: "predictleads", - propDefinitions: {}, + propDefinitions: { + domain: { + type: "string", + label: "Domain", + description: "The domain of the company to lookup (e.g., `google.com`).", + }, + technologyId: { + type: "string", + label: "Technology", + description: "Select a technology to search for.", + async options({ page }) { + const { data: technologies } = await this.retrieveTechnologies({ + params: { + page, + limit: 100, + }, + }); + return technologies.map(({ + id: value, + name: label, + }) => ({ + label, + value, + })); + }, + }, + }, methods: { - // this.$auth contains connected account data - authKeys() { - console.log(Object.keys(this.$auth)); + getUrl(path) { + return `https://predictleads.com/api/v3${path}`; + }, + getHeaders(headers) { + return { + "X-Api-Key": this.$auth.api_key, + "X-Api-Token": this.$auth.api_token, + ...headers, + }; + }, + _makeRequest({ + $ = this, path, headers, ...args + }) { + return axios($, { + url: this.getUrl(path), + headers: this.getHeaders(headers), + ...args, + }); + }, + retrieveCompany({ + domain, ...args + } = {}) { + return this._makeRequest({ + path: `/companies/${domain}`, + ...args, + }); + }, + retrieveTechnologies(args = {}) { + return this._makeRequest({ + path: "/technologies", + ...args, + }); + }, + retrieveCompaniesByTechnology({ + technologyId, ...args + } = {}) { + return this._makeRequest({ + path: `/discover/technologies/${technologyId}/technology_detections`, + ...args, + }); + }, + retrieveJobOpenings({ + domain, ...args + } = {}) { + return this._makeRequest({ + path: `/companies/${domain}/job_openings`, + ...args, + }); + }, + retrieveNewsEvents({ + domain, ...args + } = {}) { + return this._makeRequest({ + path: `/companies/${domain}/news_events`, + ...args, + }); + }, + retrieveTechnologyDetections({ + domain, ...args + } = {}) { + return this._makeRequest({ + path: `/companies/${domain}/technology_detections`, + ...args, + }); + }, + retrieveFinancingEvents({ + domain, ...args + } = {}) { + return this._makeRequest({ + path: `/companies/${domain}/financing_events`, + ...args, + }); + }, + async *getIterations({ + resourceFn, + resourceFnArgs, + max = 300, + }) { + let page = 1; + let resourcesCount = 0; + const limit = 100; + + while (true) { + const response = await resourceFn({ + ...resourceFnArgs, + params: { + ...resourceFnArgs?.params, + page, + limit, + }, + }); + + const resources = response.data; + + if (!resources?.length) { + console.log("No resources found"); + return; + } + + for (const resource of resources) { + yield resource; + resourcesCount += 1; + if (resourcesCount >= max) { + console.log("Max resources reached"); + return; + } + } + + if (page * limit > response.meta.count) { + console.log("Page limit reached"); + return; + } + + page += 1; + } + }, + async paginate(args) { + const resources = []; + for await (const resource of this.getIterations(args)) { + resources.push(resource); + } + return resources; }, }, }; diff --git a/components/predictleads/sources/common/polling.mjs b/components/predictleads/sources/common/polling.mjs new file mode 100644 index 0000000000000..777f4efbde6fb --- /dev/null +++ b/components/predictleads/sources/common/polling.mjs @@ -0,0 +1,114 @@ +import { + ConfigurationError, + DEFAULT_POLLING_SOURCE_TIMER_INTERVAL, +} from "@pipedream/platform"; +import app from "../../predictleads.app.mjs"; + +const IS_FIRST_RUN = "isFirstRun"; +const LAST_PROCESSED_DATE = "lastProcessedDate"; +const DEFAULT_DATE_FIELD = "first_seen_at"; + +export default { + props: { + app, + db: "$.service.db", + timer: { + type: "$.interface.timer", + default: { + intervalSeconds: DEFAULT_POLLING_SOURCE_TIMER_INTERVAL, + }, + }, + }, + hooks: { + async deploy() { + this.setIsFirstRun(true); + }, + }, + methods: { + getIsFirstRun() { + return this.db.get(IS_FIRST_RUN) ?? true; + }, + setIsFirstRun(value) { + this.db.set(IS_FIRST_RUN, value); + }, + getLastDate() { + return this.db.get(LAST_PROCESSED_DATE); + }, + setLastDate(value) { + this.db.set(LAST_PROCESSED_DATE, value); + }, + getDateField() { + return DEFAULT_DATE_FIELD; + }, + sortFn(a, b) { + const dateField = this.getDateField(); + return new Date(b.attributes[dateField]) - new Date(a.attributes[dateField]); + }, + generateMeta() { + throw new ConfigurationError("The 'generateMeta' method must be implemented."); + }, + getResourcesFn() { + throw new ConfigurationError("The 'getResourcesFn' method must be implemented."); + }, + getResourcesFnArgs() { + return {}; + }, + processResources(resources = []) { + resources.reverse().forEach((resource) => { + this.$emit(resource, this.generateMeta(resource)); + }); + }, + }, + async run() { + const { + app, + getResourcesFn, + getResourcesFnArgs, + getIsFirstRun, + setIsFirstRun, + processResources, + getLastDate, + setLastDate, + getDateField, + sortFn, + } = this; + + const isFirstRun = getIsFirstRun(); + const lastDate = getLastDate(); + const dateField = getDateField(); + const fnArgs = getResourcesFnArgs(); + + const resources = await app.paginate({ + resourceFn: getResourcesFn(), + resourceFnArgs: { + ...fnArgs, + params: { + ...fnArgs.params, + ...(!isFirstRun && + lastDate && { + [`${dateField}_from`]: lastDate, + }), + }, + }, + ...(isFirstRun && { + max: 100, + }), + }); + + if (resources?.length) { + const sortedResources = Array.from(resources).sort(sortFn.bind(this)); + const [ + newestResource, + ] = sortedResources; + + if (newestResource) { + setLastDate(newestResource.attributes[dateField]); + } + processResources(sortedResources); + } + + if (isFirstRun) { + setIsFirstRun(false); + } + }, +}; diff --git a/components/predictleads/sources/new-financing-event/new-financing-event.mjs b/components/predictleads/sources/new-financing-event/new-financing-event.mjs new file mode 100644 index 0000000000000..af4763d22767c --- /dev/null +++ b/components/predictleads/sources/new-financing-event/new-financing-event.mjs @@ -0,0 +1,44 @@ +import common from "../common/polling.mjs"; +import sampleEmit from "./test-event.mjs"; + +export default { + ...common, + key: "predictleads-new-financing-event", + name: "New Financing Event Added", + description: "Emit new event for each new financing event. [See the documentation](https://docs.predictleads.com/v3/api_endpoints/financing_events_dataset/retrieve_company_s_financing_events)", + version: "0.0.1", + type: "source", + dedupe: "unique", + props: { + ...common.props, + domain: { + description: "The domain of the company to retrieve financing events for (e.g., `google.com`).", + propDefinition: [ + common.props.app, + "domain", + ], + }, + }, + methods: { + ...common.methods, + getDateField() { + return "found_at"; + }, + getResourcesFn() { + return this.app.retrieveFinancingEvents; + }, + getResourcesFnArgs() { + return { + domain: this.domain, + }; + }, + generateMeta(resource) { + return { + id: resource.id, + summary: `New Financing Event ${resource.id}`, + ts: Date.now(), + }; + }, + }, + sampleEmit, +}; diff --git a/components/predictleads/sources/new-financing-event/test-event.mjs b/components/predictleads/sources/new-financing-event/test-event.mjs new file mode 100644 index 0000000000000..59758490c0250 --- /dev/null +++ b/components/predictleads/sources/new-financing-event/test-event.mjs @@ -0,0 +1,30 @@ +export default { + "id": "8d2cb2c1-8f39-47e9-b9b5-df22f25d2baa", + "type": "financing_event", + "attributes": { + "effective_date": null, + "found_at": "2024-10-23T02:00:00+02:00", + "categories": [ + "private_equity", + "venture" + ], + "financing_type": null, + "financing_type_normalized": null, + "amount": "$14 million", + "amount_normalized": 14000000, + "source_urls": [ + "https://digitalexperience.live/ex-spacex-engineers-secure-14m-3d-printing" + ] + }, + "relationships": { + "company": { + "data": { + "id": "b3b9bc14-b61b-50d3-956f-5ce0e25b7f65", + "type": "company" + } + }, + "investors": { + "data": [] + } + } +}; diff --git a/components/predictleads/sources/new-job-opening/new-job-opening.mjs b/components/predictleads/sources/new-job-opening/new-job-opening.mjs new file mode 100644 index 0000000000000..f3bf7caa8793f --- /dev/null +++ b/components/predictleads/sources/new-job-opening/new-job-opening.mjs @@ -0,0 +1,110 @@ +import common from "../common/polling.mjs"; +import sampleEmit from "./test-event.mjs"; + +export default { + ...common, + key: "predictleads-new-job-opening", + name: "New Job Opening Added", + description: "Emit new event for each new job opening for a specific company. [See the documentation](https://docs.predictleads.com/v3/api_endpoints/job_openings_dataset/retrieve_job_openings_from_specific_company)", + version: "0.0.1", + type: "source", + dedupe: "unique", + props: { + ...common.props, + domain: { + description: "The domain of the company to retrieve job openings for (e.g., `google.com`).", + propDefinition: [ + common.props.app, + "domain", + ], + }, + activeOnly: { + type: "boolean", + label: "Active Only", + description: "Set to `true` to receive Job Openings that are not closed", + optional: true, + }, + withDescriptionOnly: { + type: "boolean", + label: "With Description Only", + description: "Set to `true` to only return Job Openings that have a description.", + optional: true, + }, + withLocationOnly: { + type: "boolean", + label: "With Location Only", + description: "Set to `true` to only return Job Openings that have a location.", + optional: true, + }, + categories: { + type: "string[]", + label: "Categories", + description: "Filter job openings by specific categories.", + optional: true, + options: [ + "administration", + "consulting", + "data_analysis", + "design", + "directors", + "education", + "engineering", + "finance", + "healthcare_services", + "human_resources", + "information_technology", + "internship", + "legal", + "management", + "marketing", + "military_and_protective_services", + "operations", + "purchasing", + "product_management", + "quality_assurance", + "real_estate", + "research", + "sales", + "software_development", + "support", + "manual_work", + "food", + ], + }, + }, + methods: { + ...common.methods, + getDateField() { + return "last_seen_at"; + }, + getResourcesFn() { + return this.app.retrieveJobOpenings; + }, + getResourcesFnArgs() { + const { + domain, + activeOnly, + withDescriptionOnly, + withLocationOnly, + categories, + } = this; + return { + domain, + params: { + active_only: activeOnly, + with_description_only: withDescriptionOnly, + with_location_only: withLocationOnly, + categories: categories?.join(","), + }, + }; + }, + generateMeta(resource) { + return { + id: resource.id, + summary: `New Job Opening: ${resource.attributes.title}`, + ts: Date.parse(resource.attributes.first_seen_at), + }; + }, + }, + sampleEmit, +}; diff --git a/components/predictleads/sources/new-job-opening/test-event.mjs b/components/predictleads/sources/new-job-opening/test-event.mjs new file mode 100644 index 0000000000000..db32a1e9a227e --- /dev/null +++ b/components/predictleads/sources/new-job-opening/test-event.mjs @@ -0,0 +1,66 @@ +export default { + "id": "12345678-abcd-1234-efgh-123456789abc", + "type": "job_opening", + "attributes": { + "title": "Senior Software Engineer", + "description": "### **About TechCorp**\n\nTechCorp's mission is to build innovative software solutions that help businesses grow and succeed.\n\nOur team is collaborative, diverse, and focused on delivering high-quality products. This organization is for individuals who enjoy solving complex problems and working with cutting-edge technologies.\n\nWe operate with a collaborative organizational structure. All employees are expected to contribute meaningfully to our projects and company culture. Leadership opportunities are available for those who demonstrate initiative and consistently deliver results.\n\n## About the Role\n\nWe are seeking a talented Senior Software Engineer to join our development team. In this role, you will be responsible for designing, developing, and maintaining scalable web applications. You will work closely with product managers, designers, and other engineers to deliver exceptional user experiences.\n\n## Ideal Experience\n\n* Design and develop robust, scalable web applications\n* Write clean, maintainable, and well-tested code\n* Collaborate with cross-functional teams to define and implement new features\n* Participate in code reviews and provide constructive feedback\n* Mentor junior developers and contribute to team knowledge sharing\n* Stay up-to-date with emerging technologies and industry best practices\n* Troubleshoot and resolve technical issues in production environments\n\n## **Requirements**\n\n* Bachelor's degree in Computer Science, Engineering, or related field\n* 5+ years of experience in software development\n* Strong proficiency in JavaScript, Python, or similar programming languages\n* Experience with modern web frameworks (React, Vue.js, Angular)\n* Knowledge of database design and SQL\n* Familiarity with cloud platforms (AWS, GCP, Azure)\n* Strong problem-solving skills and attention to detail\n* Excellent communication and teamwork abilities\n\n## **Preferred Qualifications**\n\n* Experience with microservices architecture\n* Knowledge of containerization technologies (Docker, Kubernetes)\n* Familiarity with CI/CD pipelines\n* Experience with agile development methodologies\n\n## **Bonus Skills**\n\n* Contributions to open-source projects\n* Experience with machine learning or data science\n* Mobile development experience\n* DevOps experience\n\n## Annual Salary Range\n\n$120,000 - $180,000 USD\n\n*TechCorp is an equal opportunity employer committed to diversity and inclusion.*", + "url": "https://careers.techcorp.com/jobs/senior-software-engineer-123", + "first_seen_at": "2024-01-15T10:30:00Z", + "last_seen_at": "2024-01-20T14:45:30Z", + "last_processed_at": "2024-01-15T12:15:45Z", + "contract_types": [ + "full_time" + ], + "categories": [ + "engineering", + "software_development" + ], + "onet_data": { + "code": "15-1252.00", + "family": "Computer and Mathematical", + "occupation_name": "Software Developers, Applications" + }, + "posted_at": "2024-01-14T09:00:00Z", + "salary": "$120,000 - $180,000 USD", + "salary_data": { + "salary_low": 120000, + "salary_high": 180000, + "salary_currency": "USD", + "salary_low_usd": 120000, + "salary_high_usd": 180000, + "salary_time_unit": "year" + }, + "seniority": "senior", + "status": "active", + "language": "en", + "location": "San Francisco, California, United States", + "location_data": [ + { + "city": "San Francisco", + "state": "California", + "zip_code": "94102", + "country": "United States", + "region": "West Coast", + "continent": "North America", + "fuzzy_match": false + } + ], + "tags": [ + "JavaScript", + "Python", + "React", + "AWS", + "Docker", + "Remote Friendly", + "Full Stack" + ] + }, + "relationships": { + "company": { + "data": { + "id": "11111111-2222-3333-4444-555555555555", + "type": "company" + } + } + } +}; \ No newline at end of file diff --git a/components/predictleads/sources/new-news-event/new-news-event.mjs b/components/predictleads/sources/new-news-event/new-news-event.mjs new file mode 100644 index 0000000000000..602114d3e6f2c --- /dev/null +++ b/components/predictleads/sources/new-news-event/new-news-event.mjs @@ -0,0 +1,87 @@ +import common from "../common/polling.mjs"; +import sampleEmit from "./test-event.mjs"; + +export default { + ...common, + key: "predictleads-new-news-event", + name: "New News Event Added", + description: "Emit new event for each new news event for a specific company. [See the documentation](https://docs.predictleads.com/v3/api_endpoints/news_events_dataset/retrieve_company_s_news_events)", + version: "0.0.1", + type: "source", + dedupe: "unique", + props: { + ...common.props, + domain: { + description: "The domain of the company to retrieve news events for (e.g., `google.com`).", + propDefinition: [ + common.props.app, + "domain", + ], + }, + categories: { + type: "string[]", + label: "Categories", + description: "Filter news events by specific categories.", + optional: true, + options: [ + "acquires", + "merges_with", + "sells_assets_to", + "signs_new_client", + "files_suit_against", + "has_issues_with", + "closes_offices_in", + "decreases_headcount_by", + "attends_event", + "expands_facilities", + "expands_offices_in", + "expands_offices_to", + "increases_headcount_by", + "opens_new_location", + "goes_public", + "invests_into", + "invests_into_assets", + "receives_financing", + "hires", + "leaves", + "promotes", + "retires_from", + "integrates_with", + "is_developing", + "launches", + "partners_with", + "receives_award", + "recognized_as", + "identified_as_competitor_of", + ], + }, + }, + methods: { + ...common.methods, + getDateField() { + return "found_at"; + }, + getResourcesFn() { + return this.app.retrieveNewsEvents; + }, + getResourcesFnArgs() { + const { + domain, categories, + } = this; + return { + domain, + params: { + categories: categories?.join(","), + }, + }; + }, + generateMeta(resource) { + return { + id: resource.id, + summary: `New News Event: ${resource.id}`, + ts: Date.parse(resource.attributes.found_at), + }; + }, + }, + sampleEmit, +}; diff --git a/components/predictleads/sources/new-news-event/test-event.mjs b/components/predictleads/sources/new-news-event/test-event.mjs new file mode 100644 index 0000000000000..f1f9e98970736 --- /dev/null +++ b/components/predictleads/sources/new-news-event/test-event.mjs @@ -0,0 +1,55 @@ +export default { + id: "87f1cee7-e9e1-4ce9-aade-b080850b2686", + type: "news_event", + attributes: { + summary: "x.ai has issues with lawsuit over data center air pollution.", + category: "has_issues_with", + found_at: "2025-06-19T04:06:39Z", + confidence: 0.3819, + article_sentence: "Elon Musk's AI firm xAI faces lawsuit over data center air pollution.", + human_approved: false, + planning: false, + amount: null, + amount_normalized: null, + assets: null, + assets_tags: [], + award: null, + contact: null, + division: null, + effective_date: null, + event: null, + financing_type: null, + financing_type_normalized: null, + financing_type_tags: [], + headcount: null, + job_title: null, + job_title_tags: [], + location: null, + location_data: [], + product: null, + product_data: { + full_text: null, + name: null, + release_type: null, + release_version: null, + fuzzy_match: null, + }, + product_tags: [], + recognition: null, + vulnerability: "lawsuit over data center air pollution", + }, + relationships: { + company1: { + data: { + id: "b3b9bc14-b61b-50d3-956f-5ce0e25b7f65", + type: "company", + }, + }, + most_relevant_source: { + data: { + id: "cb963974-57e2-456f-a160-5dc95b5298e4", + type: "news_article", + }, + }, + }, +}; \ No newline at end of file diff --git a/components/predictleads/sources/new-technology-detected/new-technology-detected.mjs b/components/predictleads/sources/new-technology-detected/new-technology-detected.mjs new file mode 100644 index 0000000000000..61b614b7cbbd9 --- /dev/null +++ b/components/predictleads/sources/new-technology-detected/new-technology-detected.mjs @@ -0,0 +1,44 @@ +import common from "../common/polling.mjs"; +import sampleEmit from "./test-event.mjs"; + +export default { + ...common, + key: "predictleads-new-technology-detected", + name: "New Technology Detected", + description: "Emit new event for each new technology detected for a specific company. [See the documentation](https://docs.predictleads.com/v3/api_endpoints/technology_detections_dataset/retrieve_technologies_used_by_specific_company)", + version: "0.0.1", + type: "source", + dedupe: "unique", + props: { + ...common.props, + domain: { + description: "The domain of the company to retrieve technology detections for (e.g., `google.com`).", + propDefinition: [ + common.props.app, + "domain", + ], + }, + }, + methods: { + ...common.methods, + getDateField() { + return "first_seen_at"; + }, + getResourcesFn() { + return this.app.retrieveTechnologyDetections; + }, + getResourcesFnArgs() { + return { + domain: this.domain, + }; + }, + generateMeta(resource) { + return { + id: resource.id, + summary: `New Technology Detected: ${resource.id}`, + ts: Date.parse(resource.attributes.first_seen_at), + }; + }, + }, + sampleEmit, +}; diff --git a/components/predictleads/sources/new-technology-detected/test-event.mjs b/components/predictleads/sources/new-technology-detected/test-event.mjs new file mode 100644 index 0000000000000..6021c4a82c55e --- /dev/null +++ b/components/predictleads/sources/new-technology-detected/test-event.mjs @@ -0,0 +1,45 @@ +export default { + "id": "12345678-abcd-1234-efgh-123456789abc", + "type": "technology_detection", + "attributes": { + "first_seen_at": "2024-01-15T10:30:00Z", + "last_seen_at": "2024-01-20T14:45:30Z", + "behind_firewall": false, + "score": 0.85 + }, + "relationships": { + "company": { + "data": { + "id": "11111111-2222-3333-4444-555555555555", + "type": "company" + } + }, + "seen_on_job_openings": { + "data": [ + { + "id": "aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee", + "type": "job_opening" + }, + { + "id": "ffffffff-gggg-hhhh-iiii-jjjjjjjjjjjj", + "type": "job_opening" + } + ] + }, + "seen_on_subpages": { + "data": [] + }, + "seen_on_dns_records": { + "data": [] + }, + "seen_on_connection": { + "data": null + }, + "technology": { + "data": { + "id": "99999999-8888-7777-6666-555555555555", + "type": "technology" + } + } + } +}; \ No newline at end of file diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 3490cf60dc22f..81a649bec4f1d 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -1124,8 +1124,7 @@ importers: components/avochato: {} - components/avosms: - specifiers: {} + components/avosms: {} components/aweber: dependencies: @@ -2853,8 +2852,7 @@ importers: components/common_paper: {} - components/commonninja: - specifiers: {} + components/commonninja: {} components/commpeak: dependencies: @@ -4026,8 +4024,7 @@ importers: components/easy_projects: {} - components/easybroker: - specifiers: {} + components/easybroker: {} components/easycsv: {} @@ -6777,8 +6774,7 @@ importers: specifier: ^1.1.1 version: 1.6.6 - components/ipstack: - specifiers: {} + components/ipstack: {} components/iqair_airvisual: {} @@ -9316,8 +9312,7 @@ importers: specifier: ^17.0.45 version: 17.0.45 - components/openai_passthrough: - specifiers: {} + components/openai_passthrough: {} components/opencage: dependencies: @@ -9916,8 +9911,7 @@ importers: specifier: ^1.5.1 version: 1.6.6 - components/phonely: - specifiers: {} + components/phonely: {} components/php_point_of_sale: dependencies: @@ -10404,10 +10398,13 @@ importers: specifier: ^1.5.1 version: 1.6.6 - components/predictleads: {} + components/predictleads: + dependencies: + '@pipedream/platform': + specifier: ^3.1.0 + version: 3.1.0 - components/predis_ai: - specifiers: {} + components/predis_ai: {} components/prepr_graphql: {} @@ -10568,8 +10565,7 @@ importers: specifier: ^3.0.0 version: 3.0.3 - components/prompthub: - specifiers: {} + components/prompthub: {} components/promptmate_io: {} @@ -13436,8 +13432,7 @@ importers: components/test_apps_for_switching_appslug_009: {} - components/test_apps_for_switching_appslug_025: - specifiers: {} + components/test_apps_for_switching_appslug_025: {} components/testlocally: dependencies: @@ -36145,8 +36140,6 @@ snapshots: '@putout/operator-filesystem': 5.0.0(putout@36.13.1(eslint@8.57.1)(typescript@5.6.3)) '@putout/operator-json': 2.2.0 putout: 36.13.1(eslint@8.57.1)(typescript@5.6.3) - transitivePeerDependencies: - - supports-color '@putout/operator-regexp@1.0.0(putout@36.13.1(eslint@8.57.1)(typescript@5.6.3))': dependencies: