From 79094d7cb8b0fb91efa5a37cfe93d998917e4af7 Mon Sep 17 00:00:00 2001 From: Kiril Ivonchik Date: Fri, 8 Aug 2025 16:39:34 +0200 Subject: [PATCH 1/3] Fix then mapper --- examples/connections.ts | 16 +- examples/custom-workflow.ts | 53 ++- examples/fetch-company.ts | 58 +-- examples/fetch-person.ts | 59 +-- examples/fetch-post.ts | 43 +-- examples/messaging.ts | 16 +- examples/post-actions.ts | 16 +- examples/search-companies.ts | 54 +-- examples/search-people.ts | 51 +-- examples/statistics.ts | 18 +- src/core/then-workflow-mapper.abstract.ts | 2 +- src/data-api/data-api.ts | 418 ---------------------- src/data-api/fetch-company-mapper.ts | 47 --- src/data-api/fetch-person-mapper.ts | 88 ----- src/data-api/fetch-post-mapper.ts | 16 - src/data-api/search-companies-mapper.ts | 16 - src/data-api/search-people-mapper.ts | 16 - src/index.ts | 87 +---- src/types/config.ts | 5 +- 19 files changed, 89 insertions(+), 990 deletions(-) delete mode 100644 src/data-api/data-api.ts delete mode 100644 src/data-api/fetch-company-mapper.ts delete mode 100644 src/data-api/fetch-person-mapper.ts delete mode 100644 src/data-api/fetch-post-mapper.ts delete mode 100644 src/data-api/search-companies-mapper.ts delete mode 100644 src/data-api/search-people-mapper.ts diff --git a/examples/connections.ts b/examples/connections.ts index 91cc704..18ebcf1 100644 --- a/examples/connections.ts +++ b/examples/connections.ts @@ -3,9 +3,8 @@ import LinkedApi from 'linkedapi-node'; async function connectionsExample(): Promise { const linkedapi = new LinkedApi({ - accountApiToken: process.env.ACCOUNT_API_TOKEN, - identificationToken: process.env.IDENTIFICATION_TOKEN, - dataApiToken: process.env.DATA_API_TOKEN, + apiToken: process.env.API_TOKEN!, + identificationToken: process.env.IDENTIFICATION_TOKEN!, }); try { @@ -140,15 +139,6 @@ async function removeConnection(linkedapi: LinkedApi, personUrl: string): Promis console.log(' šŸ”— No longer connected with this person'); } -async function runExample(): Promise { - try { - await connectionsExample(); - } catch (error) { - console.error('šŸ’„ Example failed:', error); - process.exit(1); - } -} - if (require.main === module) { - runExample(); + connectionsExample(); } \ No newline at end of file diff --git a/examples/custom-workflow.ts b/examples/custom-workflow.ts index 99c76db..462251c 100644 --- a/examples/custom-workflow.ts +++ b/examples/custom-workflow.ts @@ -3,14 +3,34 @@ import LinkedApi from 'linkedapi-node'; async function customWorkflowExample(): Promise { const linkedapi = new LinkedApi({ - accountApiToken: process.env.ACCOUNT_API_TOKEN, - identificationToken: process.env.IDENTIFICATION_TOKEN, - dataApiToken: process.env.DATA_API_TOKEN, + apiToken: process.env.API_TOKEN!, + identificationToken: process.env.IDENTIFICATION_TOKEN!, }); try { console.log('šŸš€ Linked API custom workflow example starting...'); - await accountApiExample(linkedapi); + const customWorkflow = await linkedapi.account.executeCustomWorkflow({ + actionType: 'st.searchPeople', + limit: 5, + filter: { + locations: ["San Francisco"], + }, + then: { + actionType: 'st.doForPeople', + then: { + actionType: 'st.openPersonPage', + basicInfo: true, + then: { + actionType: 'st.retrievePersonSkills', + } + } + } + }); + console.log('šŸ” Workflow started: ', customWorkflow.workflowId); + const result = await customWorkflow.result(); + + console.log('āœ… Custom workflow executed successfully'); + console.log('šŸ” Result: ', result.completion); } catch (error) { if (error instanceof LinkedApi.LinkedApiError) { console.error('🚨 Linked API Error:', error.message); @@ -24,31 +44,6 @@ async function customWorkflowExample(): Promise { } } -async function accountApiExample(linkedapi: LinkedApi): Promise { - const customWorkflow = await linkedapi.account.executeCustomWorkflow({ - actionType: 'st.searchPeople', - limit: 5, - filter: { - locations: ["San Francisco"], - }, - then: { - actionType: 'st.doForPeople', - then: { - actionType: 'st.openPersonPage', - basicInfo: true, - then: { - actionType: 'st.retrievePersonSkills', - } - } - } - }); - console.log('šŸ” Workflow started: ', customWorkflow.workflowId); - const result = await customWorkflow.result(); - - console.log('āœ… Custom workflow executed successfully'); - console.log('šŸ” Result: ', result.completion); -} - if (require.main === module) { customWorkflowExample(); } \ No newline at end of file diff --git a/examples/fetch-company.ts b/examples/fetch-company.ts index 36954b2..2b19456 100644 --- a/examples/fetch-company.ts +++ b/examples/fetch-company.ts @@ -2,16 +2,14 @@ import LinkedApi from 'linkedapi-node'; async function fetchCompanyExample(): Promise { const linkedapi = new LinkedApi({ - accountApiToken: process.env.ACCOUNT_API_TOKEN, - identificationToken: process.env.IDENTIFICATION_TOKEN, - dataApiToken: process.env.DATA_API_TOKEN, + apiToken: process.env.API_TOKEN!, + identificationToken: process.env.IDENTIFICATION_TOKEN!, }); try { console.log('šŸš€ TypeScript Linked API example starting...'); - await accountApiExample(linkedapi); - await accountApiSalesNavigatorExample(linkedapi); - await dataApiExample(linkedapi); + await standardExample(linkedapi); + await salesNavigatorExample(linkedapi); } catch (error) { if (error instanceof LinkedApi.LinkedApiError) { @@ -26,7 +24,7 @@ async function fetchCompanyExample(): Promise { } } -async function accountApiExample(linkedapi: LinkedApi): Promise { +async function standardExample(linkedapi: LinkedApi): Promise { const fetchCompanyWorkflow = await linkedapi.account.fetchCompany({ companyUrl: 'https://www.linkedin.com/company/linkedin/', retrieveEmployees: true, @@ -62,7 +60,7 @@ async function accountApiExample(linkedapi: LinkedApi): Promise { console.log(`šŸ“ Posts Retrieved: ${company.posts?.length || 0}`); } -async function accountApiSalesNavigatorExample(linkedapi: LinkedApi): Promise { +async function salesNavigatorExample(linkedapi: LinkedApi): Promise { const nvCompanyResult = await linkedapi.account.salesNavigatorFetchCompany({ companyHashedUrl: 'https://www.linkedin.com/sales/company/1035', retrieveEmployees: true, @@ -93,48 +91,6 @@ async function accountApiSalesNavigatorExample(linkedapi: LinkedApi): Promise { - const dataCompanyResult = await linkedapi.data.fetchCompany({ - companyUrl: 'https://www.linkedin.com/sales/company/1337', - retrieveEmployees: true, - retrieveDms: true, - employeeRetrievalConfig: { - limit: 10, - filter: { - position: 'engineer', - locations: ['United States'], - industries: ['Technology', 'Software'], - schools: ['Stanford University', 'MIT'], - yearsOfExperiences: ['threeToFive', 'sixToTen'], - }, - }, - dmRetrievalConfig: { - limit: 2, - }, - }); - - console.log('šŸ” Data API company workflow started: ', dataCompanyResult.workflowId); - const dataCompany = await dataCompanyResult.result(); - - console.log('āœ… Data API company page opened successfully'); - console.log(`šŸ¢ Company: ${dataCompany.name}`); - console.log(`šŸ“– Description: ${dataCompany.description}`); - console.log(`šŸ“ Location: ${dataCompany.location}`); - console.log(`šŸ­ Industry: ${dataCompany.industry}`); - console.log(`šŸ‘„ Employee Count: ${dataCompany.employeeCount}`); - console.log(`šŸ“… Founded: ${dataCompany.yearFounded}`); - console.log(`šŸ‘Øā€šŸ’¼ Employees Retrieved: ${dataCompany.employees?.length || 0}`); -} - -async function runExample(): Promise { - try { - await fetchCompanyExample(); - } catch (error) { - console.error('šŸ’„ Example failed:', error); - process.exit(1); - } -} - if (require.main === module) { - runExample(); + fetchCompanyExample(); } \ No newline at end of file diff --git a/examples/fetch-person.ts b/examples/fetch-person.ts index e4cbc99..464e45b 100644 --- a/examples/fetch-person.ts +++ b/examples/fetch-person.ts @@ -3,17 +3,15 @@ import LinkedApi from 'linkedapi-node'; async function fetchPersonExample(): Promise { const linkedapi = new LinkedApi({ - accountApiToken: process.env.ACCOUNT_API_TOKEN, - identificationToken: process.env.IDENTIFICATION_TOKEN, - dataApiToken: process.env.DATA_API_TOKEN, + apiToken: process.env.API_TOKEN!, + identificationToken: process.env.IDENTIFICATION_TOKEN!, }); try { console.log('šŸš€ Linked API fetchPerson example starting...'); - await accountApiExample(linkedapi); - await salesNavigatorAccountApiExample(linkedapi); - await dataApiExample(linkedapi); + await standardExample(linkedapi); + await salesNavigatorExample(linkedapi); } catch (error) { if (error instanceof LinkedApi.LinkedApiError) { console.error('🚨 Linked API Error:', error.message); @@ -27,7 +25,7 @@ async function fetchPersonExample(): Promise { } } -async function accountApiExample(linkedapi: LinkedApi): Promise { +async function standardExample(linkedapi: LinkedApi): Promise { const personResult = await linkedapi.account.fetchPerson({ personUrl: 'https://www.linkedin.com/in/example-person/', retrieveExperience: true, @@ -59,7 +57,7 @@ async function accountApiExample(linkedapi: LinkedApi): Promise { console.log(`šŸ’¼ Experiences: ${person.experiences}`); } -async function salesNavigatorAccountApiExample(linkedapi: LinkedApi): Promise { +async function salesNavigatorExample(linkedapi: LinkedApi): Promise { const fetchParams = { personHashedUrl: 'https://www.linkedin.com/in/abc123', }; @@ -74,47 +72,6 @@ async function salesNavigatorAccountApiExample(linkedapi: LinkedApi): Promise { - const personResult = await linkedapi.data.fetchPerson({ - personUrl: 'https://www.linkedin.com/in/example-person/', - retrieveExperience: true, - retrieveEducation: true, - retrieveLanguages: true, - retrieveSkills: true, - retrievePosts: true, - retrieveComments: true, - retrieveReactions: true, - postsRetrievalConfig: { - limit: 5, - since: '2024-01-01', - }, - commentRetrievalConfig: { - limit: 5, - }, - reactionRetrievalConfig: { - limit: 5, - }, - }); - console.log('šŸ” Workflow started: ', personResult.workflowId); - const person = await personResult.result(); - - console.log('āœ… Person page opened successfully'); - console.log(`šŸ‘¤ Name: ${person.name}`); - console.log(`šŸ’¼ Position: ${person.position} at ${person.companyName}`); - console.log(`šŸ“ Location: ${person.location}`); - console.log(`🌐 Skills: ${person.skills}`); - console.log(`šŸ’¼ Experiences: ${person.experiences}`); -} - -async function runExample(): Promise { - try { - await fetchPersonExample(); - } catch (error) { - console.error('šŸ’„ Example failed:', error); - process.exit(1); - } -} - if (require.main === module) { - runExample(); -} \ No newline at end of file + fetchPersonExample(); +} diff --git a/examples/fetch-post.ts b/examples/fetch-post.ts index 1b7375e..f26691f 100644 --- a/examples/fetch-post.ts +++ b/examples/fetch-post.ts @@ -2,15 +2,13 @@ import LinkedApi from 'linkedapi-node'; async function fetchPostExample(): Promise { const linkedapi = new LinkedApi({ - accountApiToken: process.env.ACCOUNT_API_TOKEN, - identificationToken: process.env.IDENTIFICATION_TOKEN, - dataApiToken: process.env.DATA_API_TOKEN, + apiToken: process.env.API_TOKEN!, + identificationToken: process.env.IDENTIFICATION_TOKEN!, }); try { console.log('šŸš€ Linked API fetchPost example starting...'); - await accountApiExample(linkedapi); - await dataApiExample(linkedapi); + await standardExample(linkedapi); } catch (error) { if (error instanceof LinkedApi.LinkedApiError) { console.error('🚨 Linked API Error:', error.message); @@ -24,28 +22,7 @@ async function fetchPostExample(): Promise { } } -async function dataApiExample(linkedapi: LinkedApi): Promise { - console.log('\nšŸ“„ Fetching post with Data API...'); - const dataPostWorkflow = await linkedapi.data.fetchPost({ - postUrl: 'https://www.linkedin.com/posts/post-url' - }); - console.log('šŸ” Data API workflow started:', dataPostWorkflow.workflowId); - const dataPost = await dataPostWorkflow.result(); - - console.log('āœ… Data API post fetched successfully'); - console.log(`šŸ“„ Post URL: ${dataPost.url}`); - console.log(`ā° Post Time: ${dataPost.time}`); - console.log(`šŸ“ Post Type: ${dataPost.type}`); - console.log(`šŸ’¬ Text: ${dataPost.text || 'No text content'}`); - console.log(`šŸ”„ Repost Text: ${dataPost.repostText || 'Not a repost'}`); - console.log(`šŸ–¼ļø Images: ${dataPost.images?.length || 0} image(s)`); - console.log(`šŸŽ„ Has Video: ${dataPost.hasVideo}`); - console.log(`šŸ“Š Has Poll: ${dataPost.hasPoll}`); - console.log(`šŸ‘ Reactions: ${dataPost.reactionCount}`); - console.log(`šŸ’¬ Comments: ${dataPost.commentCount}`); -} - -async function accountApiExample(linkedapi: LinkedApi): Promise { +async function standardExample(linkedapi: LinkedApi): Promise { const accountPostWorkflow = await linkedapi.account.fetchPost({ postUrl: 'https://www.linkedin.com/posts/post-url' }); @@ -65,16 +42,6 @@ async function accountApiExample(linkedapi: LinkedApi): Promise { console.log(`šŸ’¬ Comments: ${accountPost.commentCount}`); } -async function runExample(): Promise { - try { - await fetchPostExample(); - console.log('✨ Fetch post example completed successfully'); - } catch (error) { - console.error('šŸ’„ Example failed:', error); - process.exit(1); - } -} - if (require.main === module) { - runExample(); + fetchPostExample(); } \ No newline at end of file diff --git a/examples/messaging.ts b/examples/messaging.ts index f98c96d..2b480cf 100644 --- a/examples/messaging.ts +++ b/examples/messaging.ts @@ -2,9 +2,8 @@ import LinkedApi from 'linkedapi-node'; async function messagingExample(): Promise { const linkedapi = new LinkedApi({ - accountApiToken: process.env.ACCOUNT_API_TOKEN, - identificationToken: process.env.IDENTIFICATION_TOKEN, - dataApiToken: process.env.DATA_API_TOKEN, + apiToken: process.env.API_TOKEN!, + identificationToken: process.env.IDENTIFICATION_TOKEN!, }); try { @@ -142,15 +141,6 @@ async function pollConversations(linkedapi: LinkedApi, standardPersonUrl: string }); } -async function runExample(): Promise { - try { - await messagingExample(); - } catch (error) { - console.error('šŸ’„ Example failed:', error); - process.exit(1); - } -} - if (require.main === module) { - runExample(); + messagingExample(); } \ No newline at end of file diff --git a/examples/post-actions.ts b/examples/post-actions.ts index 16bbbe9..33b0d5e 100644 --- a/examples/post-actions.ts +++ b/examples/post-actions.ts @@ -2,9 +2,8 @@ import LinkedApi from 'linkedapi-node'; async function postActionsExample(): Promise { const linkedapi = new LinkedApi({ - accountApiToken: process.env.ACCOUNT_API_TOKEN, - identificationToken: process.env.IDENTIFICATION_TOKEN, - dataApiToken: process.env.DATA_API_TOKEN, + apiToken: process.env.API_TOKEN!, + identificationToken: process.env.IDENTIFICATION_TOKEN!, }); try { @@ -55,15 +54,6 @@ async function commentOnPost(linkedapi: LinkedApi): Promise { console.log('āœ… Comment added successfully'); } -async function runExample(): Promise { - try { - await postActionsExample(); - } catch (error) { - console.error('šŸ’„ Example failed:', error); - process.exit(1); - } -} - if (require.main === module) { - runExample(); + postActionsExample(); } \ No newline at end of file diff --git a/examples/search-companies.ts b/examples/search-companies.ts index 452f9ce..61ff64f 100644 --- a/examples/search-companies.ts +++ b/examples/search-companies.ts @@ -2,17 +2,15 @@ import LinkedApi, { TSearchCompanySize } from 'linkedapi-node'; async function searchCompaniesExample(): Promise { const linkedapi = new LinkedApi({ - accountApiToken: process.env.ACCOUNT_API_TOKEN, - identificationToken: process.env.IDENTIFICATION_TOKEN, - dataApiToken: process.env.DATA_API_TOKEN, + apiToken: process.env.API_TOKEN!, + identificationToken: process.env.IDENTIFICATION_TOKEN!, }); try { console.log('šŸš€ Linked API searchCompanies example starting...'); - await accountApiExample(linkedapi); - await accountApiSalesNavigatorExample(linkedapi); - await dataApiExample(linkedapi); + await standardExample(linkedapi); + await salesNavigatorExample(linkedapi); } catch (error) { if (error instanceof LinkedApi.LinkedApiError) { @@ -27,7 +25,7 @@ async function searchCompaniesExample(): Promise { } } -async function accountApiExample(linkedapi: LinkedApi): Promise { +async function standardExample(linkedapi: LinkedApi): Promise { const searchParams = { term: 'technology startup', limit: 2, @@ -53,8 +51,7 @@ async function accountApiExample(linkedapi: LinkedApi): Promise { }); } -async function accountApiSalesNavigatorExample(linkedapi: LinkedApi): Promise { - // Example: Sales Navigator company search (Account API only) +async function salesNavigatorExample(linkedapi: LinkedApi): Promise { const nvSearchParams = { term: 'fintech', limit: 1, @@ -84,41 +81,6 @@ async function accountApiSalesNavigatorExample(linkedapi: LinkedApi): Promise { - const dataSearchParams = { - term: 'artificial intelligence', - limit: 5, - filter: { - locations: ['Seattle', 'Boston'], - industries: ['Technology', 'Artificial Intelligence'], - }, - }; - - console.log('\nšŸ” Searching companies with Data API...'); - const dataSearchWorkflow = await linkedapi.data.searchCompanies(dataSearchParams); - console.log('šŸ” Data API workflow started:', dataSearchWorkflow.workflowId); - const dataResults = await dataSearchWorkflow.result(); - - console.log('āœ… Data API company search completed'); - console.log(`šŸ“Š Found ${dataResults.length} companies`); - dataResults.forEach((company, index) => { - console.log(` ${index + 1}. ${company.name}`); - console.log(` Industry: ${company.industry}`); - console.log(` Employees: ${company.employeeCount}`); - console.log(` URL: ${company.hashedUrl}`); - }); -} - -async function runExample(): Promise { - try { - await searchCompaniesExample(); - console.log('✨ Search companies example completed successfully'); - } catch (error) { - console.error('šŸ’„ Example failed:', error); - process.exit(1); - } -} - if (require.main === module) { - runExample(); -} \ No newline at end of file + searchCompaniesExample(); +} diff --git a/examples/search-people.ts b/examples/search-people.ts index 5ade847..9bd2d15 100644 --- a/examples/search-people.ts +++ b/examples/search-people.ts @@ -2,16 +2,14 @@ import LinkedApi, { TYearsOfExperience } from 'linkedapi-node'; async function searchPeopleExample(): Promise { const linkedapi = new LinkedApi({ - accountApiToken: process.env.ACCOUNT_API_TOKEN, - identificationToken: process.env.IDENTIFICATION_TOKEN, - dataApiToken: process.env.DATA_API_TOKEN, + apiToken: process.env.API_TOKEN!, + identificationToken: process.env.IDENTIFICATION_TOKEN!, }); try { console.log('šŸš€ Linked API searchPeople example starting...'); - await accountApiExample(linkedapi); + await standardExample(linkedapi); await salesNavigatorExample(linkedapi); - await dataApiExample(linkedapi); } catch (error) { if (error instanceof LinkedApi.LinkedApiError) { @@ -26,7 +24,7 @@ async function searchPeopleExample(): Promise { } } -async function accountApiExample(linkedapi: LinkedApi): Promise { +async function standardExample(linkedapi: LinkedApi): Promise { const searchParams = { term: 'software engineer', limit: 10, @@ -83,45 +81,6 @@ async function salesNavigatorExample(linkedapi: LinkedApi): Promise { }); } -async function dataApiExample(linkedapi: LinkedApi): Promise { - const dataSearchParams = { - term: 'data scientist', - limit: 6, - filter: { - lastName: 'Johnson', - position: 'Senior Data Scientist', - locations: ['Seattle', 'Boston', 'California'], - currentCompanies: ['Tesla', 'SpaceX', 'Apple'], - schools: ['UC Berkeley', 'Carnegie Mellon', 'Harvard University'], - }, - }; - - console.log('\nšŸ” Searching people with Data API...'); - const dataSearchWorkflow = await linkedapi.data.searchPeople(dataSearchParams); - console.log('šŸ” Data API workflow started:', dataSearchWorkflow.workflowId); - const dataResults = await dataSearchWorkflow.result(); - - console.log('āœ… Data API people search completed'); - console.log(`šŸ“Š Found ${dataResults.length} people`); - dataResults.forEach((person, index) => { - console.log(` ${index + 1}. ${person.name}`); - console.log(` Position: ${person.position}`); - console.log(` Location: ${person.location}`); - console.log(` URL: ${person.hashedUrl}`); - }); - -} - -async function runExample(): Promise { - try { - await searchPeopleExample(); - console.log('✨ Search people example completed successfully'); - } catch (error) { - console.error('šŸ’„ Example failed:', error); - process.exit(1); - } -} - if (require.main === module) { - runExample(); + searchPeopleExample(); } \ No newline at end of file diff --git a/examples/statistics.ts b/examples/statistics.ts index 832a344..8e3c7c8 100644 --- a/examples/statistics.ts +++ b/examples/statistics.ts @@ -2,9 +2,8 @@ import LinkedApi from 'linkedapi-node'; async function statisticsExample(): Promise { const linkedapi = new LinkedApi({ - accountApiToken: process.env.ACCOUNT_API_TOKEN, - identificationToken: process.env.IDENTIFICATION_TOKEN, - dataApiToken: process.env.DATA_API_TOKEN, + apiToken: process.env.API_TOKEN!, + identificationToken: process.env.IDENTIFICATION_TOKEN!, }); try { @@ -92,15 +91,6 @@ async function getRecentUsageStats(linkedapi: LinkedApi): Promise { } } -async function runExample(): Promise { - try { - await statisticsExample(); - } catch (error) { - console.error('šŸ’„ Example failed:', error); - process.exit(1); - } -} - if (require.main === module) { - runExample(); -} \ No newline at end of file + statisticsExample(); +} diff --git a/src/core/then-workflow-mapper.abstract.ts b/src/core/then-workflow-mapper.abstract.ts index 331646b..c3dc122 100644 --- a/src/core/then-workflow-mapper.abstract.ts +++ b/src/core/then-workflow-mapper.abstract.ts @@ -126,7 +126,7 @@ export abstract class ThenWorkflowMapper< config: TActionConfig, ): boolean { const paramValue = params[config.paramName as keyof TParams]; - return paramValue !== undefined && paramValue !== null; + return paramValue === true; } private buildRequestAction( diff --git a/src/data-api/data-api.ts b/src/data-api/data-api.ts deleted file mode 100644 index d7a304c..0000000 --- a/src/data-api/data-api.ts +++ /dev/null @@ -1,418 +0,0 @@ -import type { - TWorkflowDefinition, - TWorkflowResponse, -} from "../types/workflows"; -import type { - TBaseFetchPersonParams, - TFetchPersonParams, - TFetchPersonResult, -} from "../types/actions/person"; -import type { - TDtBaseFetchCompanyParams, - TDtFetchCompanyParams, - TDtFetchCompanyResult, -} from "../types/actions/company.sales-navigator"; -import type { TFetchPostParams, TFetchPostResult } from "../types/actions/post"; -import type { - TNvSearchCompanyParams, - TNvSearchCompanyResult, -} from "../types/actions/search-company"; -import type { - TNvSearchPeopleParams, - TNvSearchPeopleResult, -} from "../types/actions/search-people"; -import { DtFetchPersonMapper } from "./fetch-person-mapper"; -import { DtFetchCompanyMapper } from "./fetch-company-mapper"; -import { DtFetchPostMapper } from "./fetch-post-mapper"; -import { DtSearchCompaniesMapper } from "./search-companies-mapper"; -import { DtSearchPeopleMapper } from "./search-people-mapper"; -import { WorkflowHandler } from "../core/workflow-handler"; -import type { WorkflowExecutor } from "../core/workflow-executor"; - -/** - * Linked API Data API client for retrieving LinkedIn data without account connection. - * - * The Data API allows you to retrieve real-time LinkedIn data without connecting your own LinkedIn account. - * It uses a credit-based system and is perfect for data enrichment, lead generation, and market research. - * All actions are executed through workflows and consume credits from your Data API balance. - * - * @see {@link https://linkedapi.io/docs/data-api/ Data API Documentation} - * @see {@link https://linkedapi.io/docs/data-api/making-requests-0/ Making Requests Documentation} - * - * @example - * ```typescript - * const linkedapi = new LinkedApi({ - * dataApiToken: "your-data-api-token" - * }); - * - * // Search for companies - * const companies = await linkedapi.data.searchCompanies({ - * term: "tech startup", - * limit: 10 - * }); - * - * // Fetch person data - * const person = await linkedapi.data.fetchPerson({ - * personUrl: "https://www.linkedin.com/in/john-doe" - * }); - * ``` - */ -export class DataApi { - /** - * Creates a new DataApi instance. - * - * @param workflowExecutor - The workflow executor configured with Data API settings and authentication - */ - constructor(private workflowExecutor: WorkflowExecutor) {} - - /** - * Retrieve comprehensive data about a LinkedIn person profile using Data API. - * - * This method fetches detailed information about a person from their LinkedIn profile without - * requiring your own LinkedIn account connection. It retrieves basic information and can include - * experience, education, skills, languages, posts, comments, and reactions based on parameters. - * This action consumes credits from your Data API balance. - * - * @param params - Parameters specifying the person URL and what data to retrieve - * @returns Promise resolving to a WorkflowHandler containing the person's profile data - * - * @see {@link https://linkedapi.io/docs/data-api/retrieving-person-data-0/ Retrieving Person Data Documentation} - * @see {@link https://linkedapi.io/docs/data-api/action-open-person-page/ openPersonPage Action Documentation} - * @see {@link https://linkedapi.io/docs/data-api/action-retrieve-person-experience/ retrievePersonExperience Child Action} - * @see {@link https://linkedapi.io/docs/data-api/action-retrieve-person-education/ retrievePersonEducation Child Action} - * @see {@link https://linkedapi.io/docs/data-api/action-retrieve-person-skills/ retrievePersonSkills Child Action} - * @see {@link https://linkedapi.io/docs/data-api/action-retrieve-person-languages/ retrievePersonLanguages Child Action} - * @see {@link https://linkedapi.io/docs/data-api/action-retrieve-person-posts/ retrievePersonPosts Child Action} - * @see {@link https://linkedapi.io/docs/data-api/action-retrieve-person-comments/ retrievePersonComments Child Action} - * @see {@link https://linkedapi.io/docs/data-api/action-retrieve-person-reactions/ retrievePersonReactions Child Action} - * - * @example - * ```typescript - * // Fetch comprehensive person data with type-safe parameters - * const personResult = await linkedapi.data.fetchPerson({ - * personUrl: 'https://www.linkedin.com/in/john-doe/', - * retrieveExperience: true, - * retrieveEducation: true, - * retrieveLanguages: true, - * retrieveSkills: true, - * retrievePosts: true, - * retrieveComments: true, - * retrieveReactions: true, - * postsRetrievalConfig: { - * limit: 5, - * since: '2024-01-01', - * }, - * commentRetrievalConfig: { - * limit: 5, - * }, - * reactionRetrievalConfig: { - * limit: 5, - * }, - * }); - * - * const personData = await personResult.result(); - * console.log("Person name:", personData.name); - * console.log("Experience:", personData.experiences); // TypeScript knows this exists - * console.log("Recent posts:", personData.posts); // TypeScript knows this exists - * ``` - * - * @example - * ```typescript - * // Simple fetch for basic profile data only - * const basicResult = await linkedapi.data.fetchPerson({ - * personUrl: 'https://www.linkedin.com/in/john-doe' - * }); - * - * const basicData = await basicResult.result(); - * console.log("CEO info:", basicData.name, basicData.companyName); - * // basicData.experiences is undefined (TypeScript enforces this) - * ``` - */ - public async fetchPerson( - params: TFetchPersonParams, - ): Promise>> { - const fetchPersonMapper = new DtFetchPersonMapper(); - const workflowDefinition = fetchPersonMapper.mapRequest(params); - const { workflowId } = - await this.workflowExecutor.startWorkflow(workflowDefinition); - return new WorkflowHandler>( - workflowId, - this.workflowExecutor, - fetchPersonMapper, - ); - } - - /** - * Retrieve comprehensive data about a LinkedIn company profile using Data API. - * - * This method fetches detailed information about a company from their LinkedIn page without - * requiring your own LinkedIn account connection. It retrieves basic company information and can - * include employee data and direct messages based on parameters. This action consumes credits - * from your Data API balance. - * - * @param params - Parameters specifying the company URL and what data to retrieve - * @returns Promise resolving to a WorkflowHandler containing the company's profile data - * - * @see {@link https://linkedapi.io/docs/data-api/retrieving-company-data-0/ Retrieving Company Data Documentation} - * @see {@link https://linkedapi.io/docs/data-api/action-open-company-page/ openCompanyPage Action Documentation} - * @see {@link https://linkedapi.io/docs/data-api/action-retrieve-company-employees/ retrieveCompanyEmployees Child Action} - * @see {@link https://linkedapi.io/docs/data-api/action-retrieve-company-dms/ retrieveCompanyDMs Child Action} - * - * @example - * ```typescript - * // Fetch company data with employees (new simplified syntax) - * const companyResult = await linkedapi.data.fetchCompany({ - * companyUrl: "https://www.linkedin.com/company/microsoft", - * retrieveEmployees: true, - * retrieveDms: true, - * employeeRetrievalConfig: { - * limit: 20, - * filter: { - * positions: ["Engineer", "Manager"], - * industries: ["Software Development"] - * } - * }, - * dmRetrievalConfig: { limit: 10 } - * }); - * - * const companyData = await companyResult.result(); - * console.log("Company name:", companyData.name); - * console.log("Employees:", companyData.employees); - * console.log("Decision makers:", companyData.dms); - * ``` - */ - public async fetchCompany( - params: TDtFetchCompanyParams, - ): Promise>> { - const fetchCompanyMapper = new DtFetchCompanyMapper(); - const workflowDefinition = fetchCompanyMapper.mapRequest(params); - const { workflowId } = - await this.workflowExecutor.startWorkflow(workflowDefinition); - return new WorkflowHandler>( - workflowId, - this.workflowExecutor, - fetchCompanyMapper, - ); - } - - /** - * Retrieve detailed information about a LinkedIn post using Data API. - * - * This method fetches comprehensive data about a specific LinkedIn post without requiring - * your own LinkedIn account connection. It retrieves post content, author information, - * engagement metrics, and metadata. This action consumes credits from your Data API balance. - * - * @param params - Parameters specifying the post URL - * @returns Promise resolving to a WorkflowHandler containing the post data - * - * @see {@link https://linkedapi.io/docs/data-api/retrieving-post-data-0/ Retrieving Post Data Documentation} - * @see {@link https://linkedapi.io/docs/data-api/action-open-post/ openPost Action Documentation} - * - * @example - * ```typescript - * // Fetch post data - * const postWorkflow = await linkedapi.data.fetchPost({ - * postUrl: "https://www.linkedin.com/posts/john-doe_activity-123456789" - * }); - * - * const postData = await postWorkflow.result(); - * console.log("Post content:", postData.text); - * console.log("Author:", postData.author); - * console.log("Reactions:", postData.reactions); - * console.log("Comments:", postData.commentsCount); - * ``` - */ - public async fetchPost( - params: TFetchPostParams, - ): Promise> { - const fetchPostMapper = new DtFetchPostMapper(); - const workflowDefinition = fetchPostMapper.mapRequest(params); - const { workflowId } = - await this.workflowExecutor.startWorkflow(workflowDefinition); - return new WorkflowHandler( - workflowId, - this.workflowExecutor, - fetchPostMapper, - ); - } - - /** - * Search for companies on LinkedIn using Data API with advanced filtering. - * - * This method performs a company search without requiring your own LinkedIn account connection. - * You can filter by company size, location, industry, annual revenue, and search terms. - * Results include company details with hashed URLs for further data retrieval. - * This action consumes credits from your Data API balance. - * - * @param params - Search parameters including keywords, filters, and pagination options - * @returns Promise resolving to a WorkflowHandler containing an array of company search results - * - * @see {@link https://linkedapi.io/docs/data-api/searching-for-companies-0/ Searching for Companies Documentation} - * @see {@link https://linkedapi.io/docs/data-api/action-search-companies/ searchCompanies Action Documentation} - * - * @example - * ```typescript - * // Search for tech companies with advanced filters - * const companySearchWorkflow = await linkedapi.data.searchCompanies({ - * term: "Tech Inc", - * limit: 50, - * filter: { - * sizes: ["51-200", "201-500"], - * locations: ["San Francisco", "New York"], - * industries: ["Software Development", "Robotics Engineering"], - * annualRevenue: { - * min: "0", - * max: "50" - * } - * } - * }); - * - * const companies = await companySearchWorkflow.result(); - * console.log("Found companies:", companies.length); - * companies.forEach(company => { - * console.log(`${company.name} - ${company.industry} (${company.employeeCount} employees)`); - * }); - * ``` - */ - public async searchCompanies( - params: TNvSearchCompanyParams, - ): Promise> { - const searchCompaniesMapper = new DtSearchCompaniesMapper(); - const workflowDefinition = searchCompaniesMapper.mapRequest(params); - const { workflowId } = - await this.workflowExecutor.startWorkflow(workflowDefinition); - return new WorkflowHandler( - workflowId, - this.workflowExecutor, - searchCompaniesMapper, - ); - } - - /** - * Search for people on LinkedIn using Data API with advanced filtering. - * - * This method performs a people search without requiring your own LinkedIn account connection. - * You can filter by location, current/previous companies, industries, schools, years of experience, - * and search terms. Results include person details with hashed URLs for further data retrieval. - * This action consumes credits from your Data API balance. - * - * @param params - Search parameters including keywords, filters, and pagination options - * @returns Promise resolving to a WorkflowHandler containing an array of people search results - * - * @see {@link https://linkedapi.io/docs/data-api/searching-for-people-0/ Searching for People Documentation} - * @see {@link https://linkedapi.io/docs/data-api/action-search-people/ searchPeople Action Documentation} - * - * @example - * ```typescript - * // Search for professionals with specific criteria - * const peopleSearchWorkflow = await linkedapi.data.searchPeople({ - * term: "software engineer React", - * limit: 25, - * filter: { - * locations: ["San Francisco Bay Area", "New York"], - * currentCompanies: ["Google", "Facebook", "Apple"], - * industries: ["Technology", "Software"], - * schools: ["Stanford University", "MIT"], - * yearsOfExperience: ["threeToFive", "sixToTen"] - * } - * }); - * - * const people = await peopleSearchWorkflow.result(); - * console.log("Found professionals:", people.length); - * people.forEach(person => { - * console.log(`${person.name} - ${person.headline} (${person.location})`); - * }); - * ``` - */ - public async searchPeople( - params: TNvSearchPeopleParams, - ): Promise> { - const searchPeopleMapper = new DtSearchPeopleMapper(); - const workflowDefinition = searchPeopleMapper.mapRequest(params); - const { workflowId } = - await this.workflowExecutor.startWorkflow(workflowDefinition); - return new WorkflowHandler( - workflowId, - this.workflowExecutor, - searchPeopleMapper, - ); - } - - /** - * Execute a custom workflow with raw workflow definition using Data API. - * - * This method allows you to execute any custom Data API workflow by providing a raw workflow definition. - * Use this for advanced use cases when you need to create custom action sequences or use actions - * not directly exposed as methods. This consumes credits from your Data API balance. - * - * @param params - The workflow definition containing action types and parameters - * @returns Promise resolving to a WorkflowHandler for managing the workflow execution - * - * @see {@link https://linkedapi.io/docs/data-api/building-workflows-0/ Building Workflows Documentation} - * @see {@link https://linkedapi.io/docs/data-api/executing-workflows-0/ Executing Workflows Documentation} - * @see {@link https://linkedapi.io/docs/data-api/actions-overview-0/ Actions Overview Documentation} - * - * @example - * ```typescript - * // Execute a custom company search with child actions - * const customWorkflow = await linkedapi.data.executeCustomWorkflow({ - * actionType: "searchCompanies", - * term: "AI startup", - * limit: 10, - * filter: { - * sizes: ["11-50", "51-200"], - * industries: ["Artificial Intelligence"] - * }, - * then: { - * actionType: "doForCompanies", - * then: { - * actionType: "openCompanyPage", - * basicInfo: true, - * retrieveEmployees: true - * } - * } - * }); - * - * const result = await customWorkflow.result(); - * console.log("Custom workflow completed:", result); - * ``` - */ - public async executeCustomWorkflow( - params: TWorkflowDefinition, - ): Promise { - const workflow = await this.workflowExecutor.startWorkflow(params); - return new WorkflowHandler(workflow.workflowId, this.workflowExecutor); - } - - /** - * Get the result of a Data API workflow by its ID. - * - * This method retrieves the result of a previously started Data API workflow using its workflow ID. - * Useful for checking workflow status and retrieving results asynchronously without waiting - * for the workflow to complete. - * - * @param workflowId - The unique identifier of the workflow - * @returns Promise resolving to the workflow response containing completion data or failure information - * - * @see {@link https://linkedapi.io/docs/data-api/executing-workflows-0/ Executing Workflows Documentation} - * - * @example - * ```typescript - * // Get workflow result by ID - * const workflowResponse = await linkedapi.data.getWorkflowResult("workflow-id-123"); - * - * if (workflowResponse.completion) { - * console.log("Data API workflow completed:", workflowResponse.completion.data); - * } else if (workflowResponse.failure) { - * console.error("Data API workflow failed:", workflowResponse.failure.message); - * } else { - * console.log("Workflow still in progress..."); - * } - * ``` - */ - public async getWorkflowResult( - workflowId: string, - ): Promise { - return this.workflowExecutor.getWorkflowResult(workflowId); - } -} diff --git a/src/data-api/fetch-company-mapper.ts b/src/data-api/fetch-company-mapper.ts deleted file mode 100644 index 6e23b3f..0000000 --- a/src/data-api/fetch-company-mapper.ts +++ /dev/null @@ -1,47 +0,0 @@ -import type { - TDtBaseFetchCompanyParams, - TDtFetchCompanyResult, -} from "../types/actions/company.sales-navigator"; -import { - ThenWorkflowMapper, - type TActionConfig, -} from "../core/then-workflow-mapper.abstract"; - -const FETCH_COMPANY_ACTIONS: TActionConfig[] = [ - { - paramName: "retrieveEmployees", - actionType: "retrieveCompanyEmployees", - configSource: "employeeRetrievalConfig", - }, - { - paramName: "retrieveDms", - actionType: "retrieveCompanyDMs", - configSource: "dmRetrievalConfig", - }, -]; - -const RESPONSE_MAPPINGS = [ - { - actionType: "retrieveCompanyEmployees", - targetProperty: "employees", - }, - { - actionType: "retrieveCompanyDMs", - targetProperty: "dms", - }, -]; - -export class DtFetchCompanyMapper< - TParams extends TDtBaseFetchCompanyParams, -> extends ThenWorkflowMapper> { - constructor() { - super({ - actionConfigs: FETCH_COMPANY_ACTIONS, - responseMappings: RESPONSE_MAPPINGS, - baseActionType: "openCompanyPage", - defaultParams: { - basicInfo: true, - }, - }); - } -} diff --git a/src/data-api/fetch-person-mapper.ts b/src/data-api/fetch-person-mapper.ts deleted file mode 100644 index 4aa82c3..0000000 --- a/src/data-api/fetch-person-mapper.ts +++ /dev/null @@ -1,88 +0,0 @@ -import type { - TBaseFetchPersonParams, - TFetchPersonResult, -} from "../types/actions/person"; -import { - ThenWorkflowMapper, - type TActionConfig, -} from "../core/then-workflow-mapper.abstract"; - -const FETCH_PERSON_ACTIONS: TActionConfig[] = [ - { - paramName: "retrieveExperience", - actionType: "retrievePersonExperience", - }, - { - paramName: "retrieveEducation", - actionType: "retrievePersonEducation", - }, - { - paramName: "retrieveSkills", - actionType: "retrievePersonSkills", - }, - { - paramName: "retrieveLanguages", - actionType: "retrievePersonLanguages", - }, - { - paramName: "retrievePosts", - actionType: "retrievePersonPosts", - configSource: "postsRetrievalConfig", - }, - { - paramName: "retrieveComments", - actionType: "retrievePersonComments", - configSource: "commentRetrievalConfig", - }, - { - paramName: "retrieveReactions", - actionType: "retrievePersonReactions", - configSource: "reactionRetrievalConfig", - }, -]; - -const RESPONSE_MAPPINGS = [ - { - actionType: "retrievePersonExperience", - targetProperty: "experiences", - }, - { - actionType: "retrievePersonEducation", - targetProperty: "education", - }, - { - actionType: "retrievePersonSkills", - targetProperty: "skills", - }, - { - actionType: "retrievePersonLanguages", - targetProperty: "languages", - }, - { - actionType: "retrievePersonPosts", - targetProperty: "posts", - }, - { - actionType: "retrievePersonComments", - targetProperty: "comments", - }, - { - actionType: "retrievePersonReactions", - targetProperty: "reactions", - }, -]; - -export class DtFetchPersonMapper< - TParams extends TBaseFetchPersonParams, -> extends ThenWorkflowMapper> { - constructor() { - super({ - actionConfigs: FETCH_PERSON_ACTIONS, - responseMappings: RESPONSE_MAPPINGS, - baseActionType: "openPersonPage", - defaultParams: { - basicInfo: true, - }, - }); - } -} diff --git a/src/data-api/fetch-post-mapper.ts b/src/data-api/fetch-post-mapper.ts deleted file mode 100644 index 9ffa1ed..0000000 --- a/src/data-api/fetch-post-mapper.ts +++ /dev/null @@ -1,16 +0,0 @@ -import type { TFetchPostParams, TFetchPostResult } from "../types/actions/post"; -import { SimpleWorkflowMapper } from "../core/simple-workflow-mapper"; - -export class DtFetchPostMapper extends SimpleWorkflowMapper< - TFetchPostParams, - TFetchPostResult -> { - constructor() { - super({ - actionType: "openPost", - defaultParams: { - basicInfo: true, - }, - }); - } -} diff --git a/src/data-api/search-companies-mapper.ts b/src/data-api/search-companies-mapper.ts deleted file mode 100644 index e0d5dab..0000000 --- a/src/data-api/search-companies-mapper.ts +++ /dev/null @@ -1,16 +0,0 @@ -import type { - TNvSearchCompanyParams, - TNvSearchCompanyResult, -} from "../types/actions/search-company"; -import { ArrayWorkflowMapper } from "../core/array-workflow-mapper.abstract"; - -export class DtSearchCompaniesMapper extends ArrayWorkflowMapper< - TNvSearchCompanyParams, - TNvSearchCompanyResult -> { - constructor() { - super({ - baseActionType: "searchCompanies", - }); - } -} diff --git a/src/data-api/search-people-mapper.ts b/src/data-api/search-people-mapper.ts deleted file mode 100644 index 76bb2b1..0000000 --- a/src/data-api/search-people-mapper.ts +++ /dev/null @@ -1,16 +0,0 @@ -import type { - TNvSearchPeopleParams, - TNvSearchPeopleResult, -} from "../types/actions/search-people"; -import { ArrayWorkflowMapper } from "../core/array-workflow-mapper.abstract"; - -export class DtSearchPeopleMapper extends ArrayWorkflowMapper< - TNvSearchPeopleParams, - TNvSearchPeopleResult -> { - constructor() { - super({ - baseActionType: "searchPeople", - }); - } -} diff --git a/src/index.ts b/src/index.ts index 4dc36ed..4589dd6 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,5 +1,4 @@ import { AccountApi } from "./account-api/account-api"; -import { DataApi } from "./data-api/data-api"; import type { TLinkedApiConfig } from "./types/config"; import { LinkedApiError, LinkedApiWorkflowError } from "./types/errors"; import type { TWorkflowDefinition, TWorkflowResponse } from "./types/workflows"; @@ -11,25 +10,22 @@ import { WorkflowHandler } from "./core/workflow-handler"; /** * LinkedApi - Official TypeScript SDK for Linked API * - * Provides access to both Account API and Data API functionality. - * The Account API enables LinkedIn automation and account control, while the Data API provides - * credit-based data retrieval without requiring LinkedIn account access. + * The Linked API enables LinkedIn automation and account control. * * @see {@link https://linkedapi.io Homepage} * @see {@link https://linkedapi.io/docs/account-api/ Account API Documentation} - * @see {@link https://linkedapi.io/docs/data-api/ Data API Documentation} * * @example * ```typescript * import LinkedApi from "linkedapi-node"; * - * // Initialize with Account API tokens for LinkedIn automation + * // Initialize with Linked API tokens for LinkedIn automation * const linkedapi = LinkedApi.init({ * accountApiToken: "your-account-api-token", * identificationToken: "your-identification-token" * }); * - * // Use Account API features with full type safety + * // Use Linked API features with full type safety * const personWorkflow = await linkedapi.account.fetchPerson({ * personUrl: "https://www.linkedin.com/in/john-doe", * retrieveExperience: true, @@ -41,25 +37,10 @@ import { WorkflowHandler } from "./core/workflow-handler"; * * @example * ```typescript - * // Initialize with Data API token for data enrichment (no account required) - * const linkedapi = LinkedApi.init({ - * dataApiToken: "your-data-api-token" - * }); - * - * // Use Data API features - * const companies = await linkedapi.data.searchCompanies({ - * term: "tech startup", - * limit: 10 - * }); - * ``` - * - * @example - * ```typescript * // Initialize with both APIs for full functionality * const linkedapi = LinkedApi.init({ * accountApiToken: "your-account-api-token", * identificationToken: "your-identification-token", - * dataApiToken: "your-data-api-token" * }); * ``` * @@ -82,58 +63,23 @@ class LinkedApi { * @param config - Configuration object containing API tokens and optional settings * @returns LinkedApi instance with access to account and data APIs */ - private accountApi?: AccountApi; - private dataApi?: DataApi; + public readonly account: AccountApi; constructor(config: TLinkedApiConfig) { const workflowTimeout = config.workflowTimeout ?? 24 * 60 * 60 * 1000; - if (config.accountApiToken && config.identificationToken) { - const accountApiClient = new HttpClient({ - headers: { - "account-api-token": config.accountApiToken, - "identification-token": config.identificationToken, - }, - }); - const accountApiExecutor = new WorkflowExecutor({ - httpClient: accountApiClient, - apiPath: "/account/workflows", - workflowTimeout: workflowTimeout, - }); - this.accountApi = new AccountApi(accountApiExecutor, accountApiClient); - } - - if (config.dataApiToken) { - const dataApiClient = new HttpClient({ - headers: { - "data-api-token": config.dataApiToken, - }, - }); - const dataApiExecutor = new WorkflowExecutor({ - httpClient: dataApiClient, - apiPath: "/data/workflows", - workflowTimeout: workflowTimeout, - }); - this.dataApi = new DataApi(dataApiExecutor); - } - } - - get account(): AccountApi { - if (!this.accountApi) { - throw new Error( - "Account API is not initialized. Please provide 'accountApiToken' and 'identificationToken' in the configuration.", - ); - } - return this.accountApi; - } - - get data(): DataApi { - if (!this.dataApi) { - throw new Error( - "Data API is not initialized. Please provide 'dataApiToken' in the configuration.", - ); - } - return this.dataApi; + const accountApiClient = new HttpClient({ + headers: { + "account-api-token": config.apiToken, + "identification-token": config.identificationToken, + }, + }); + const accountApiExecutor = new WorkflowExecutor({ + httpClient: accountApiClient, + apiPath: "/account/workflows", + workflowTimeout: workflowTimeout, + }); + this.account = new AccountApi(accountApiExecutor, accountApiClient); } // Error classes @@ -146,7 +92,6 @@ export default LinkedApi; export { LinkedApi, AccountApi, - DataApi, LinkedApiError, LinkedApiWorkflowError, WorkflowHandler, diff --git a/src/types/config.ts b/src/types/config.ts index 8248ca8..2962a8e 100644 --- a/src/types/config.ts +++ b/src/types/config.ts @@ -1,6 +1,5 @@ export interface TLinkedApiConfig { - dataApiToken?: string; - accountApiToken?: string; - identificationToken?: string; + apiToken: string; + identificationToken: string; workflowTimeout?: number; } From 9dc0117be81c26bdb58319c932626529e79e8618 Mon Sep 17 00:00:00 2001 From: Kiril Ivonchik Date: Fri, 8 Aug 2025 17:31:06 +0200 Subject: [PATCH 2/3] Simplify architecture --- README.md | 370 +---- examples/connections.ts | 18 +- examples/custom-workflow.ts | 8 +- examples/fetch-company.ts | 10 +- examples/fetch-person.ts | 10 +- examples/fetch-post.ts | 8 +- examples/messaging.ts | 16 +- examples/post-actions.ts | 12 +- examples/search-companies.ts | 10 +- examples/search-people.ts | 10 +- examples/statistics.ts | 12 +- src/account-api/account-api.ts | 1299 ----------------- src/core/workflow-handler.ts | 2 +- src/index.ts | 1299 ++++++++++++++++- .../array-workflow-mapper.abstract.ts | 0 src/{core => mappers}/base-mapper.abstract.ts | 0 .../fetch-company-mapper.ts | 2 +- .../fetch-nv-company-mapper.ts | 2 +- .../fetch-person-mapper.ts | 2 +- src/mappers/index.ts | 12 + .../nv-open-person-page-mapper.ts | 2 +- .../retrieve-connections-mapper.ts | 2 +- .../retrieve-pending-requests-mapper.ts | 4 +- ...sales-navigator-search-companies-mapper.ts | 2 +- .../sales-navigator-search-people-mapper.ts | 2 +- .../search-companies-mapper.ts | 2 +- .../search-people-mapper.ts | 2 +- .../simple-workflow-mapper.ts | 0 .../then-workflow-mapper.abstract.ts | 0 src/{core => mappers}/void-workflow-mapper.ts | 0 30 files changed, 1417 insertions(+), 1701 deletions(-) delete mode 100644 src/account-api/account-api.ts rename src/{core => mappers}/array-workflow-mapper.abstract.ts (100%) rename src/{core => mappers}/base-mapper.abstract.ts (100%) rename src/{account-api => mappers}/fetch-company-mapper.ts (96%) rename src/{account-api => mappers}/fetch-nv-company-mapper.ts (95%) rename src/{account-api => mappers}/fetch-person-mapper.ts (97%) create mode 100644 src/mappers/index.ts rename src/{account-api => mappers}/nv-open-person-page-mapper.ts (84%) rename src/{account-api => mappers}/retrieve-connections-mapper.ts (81%) rename src/{account-api => mappers}/retrieve-pending-requests-mapper.ts (70%) rename src/{account-api => mappers}/sales-navigator-search-companies-mapper.ts (80%) rename src/{account-api => mappers}/sales-navigator-search-people-mapper.ts (80%) rename src/{account-api => mappers}/search-companies-mapper.ts (79%) rename src/{account-api => mappers}/search-people-mapper.ts (79%) rename src/{core => mappers}/simple-workflow-mapper.ts (100%) rename src/{core => mappers}/then-workflow-mapper.abstract.ts (100%) rename src/{core => mappers}/void-workflow-mapper.ts (100%) diff --git a/README.md b/README.md index 778ec7e..e4b6180 100644 --- a/README.md +++ b/README.md @@ -2,8 +2,7 @@ - [Installation](#-installation) - [Quick Start](#-quick-start) -- [Account API](#-account-api) -- [Data API](#-data-api) +- [Linked API](#-linked-api) - [Best Practices](#-best-practices) - [Workflow Consistency & State Management](#-workflow-consistency--state-management) - [Error Handling](#-error-handling) @@ -27,36 +26,35 @@ import LinkedApi from "linkedapi-node"; // Initialize with your API tokens const linkedapi = new LinkedApi({ - accountApiToken: "your-account-api-token", + apiToken: "your-api-token", identificationToken: "your-identification-token", - dataApiToken: "your-data-api-token", }); -// Use Account API for LinkedIn automation -const connectionWorkflow = await linkedapi.account.sendConnectionRequest({ +// Use Linked API for your LinkedIn account automation +const connectionWorkflow = await linkedapi.sendConnectionRequest({ personUrl: "https://www.linkedin.com/in/person1", message: "It would be great to add you to my network!", }); -await conntectionWorkwflow.result(); +await connectionWorkflow.result(); -const commentWorkflow = await linkedapi.account.commentOnPost({ +const commentWorkflow = await linkedapi.commentOnPost({ postUrl: "https://www.linkedin.com/posts/post1", text: "Great post! Thanks for sharing.", }); await commentWorkflow.result(); // Search companies -const searchCompaniesWorkflow = await linkedapi.data.searchCompanies({ +const searchCompaniesWorkflow = await linkedapi.searchCompanies({ filter: { sizes: ["11-50", "51-200", "201-500", "501-1000"], locations: ["California", "Wyoming", "Texas"], - indusctries: ["Software Development", "Robotics Engineering"], + industries: ["Software Development", "Robotics Engineering"], }, }); const companies = await searchCompaniesWorkflow.result(); // Retrieving company basic info, employees -const companyWorflow = await linkedapi.data.fetchCompany({ +const companyWorkflow = await linkedapi.fetchCompany({ companyUrl: "https://www.linkedin.com/company/company1", retrieveEmployees: true, employeeRetrievalConfig: { @@ -70,26 +68,26 @@ const company = await companyWorkflow.result(); --- -## šŸ”§ Account API +## šŸ”§ Linked API -Account API lets you manage LinkedIn accounts programmatically through an API interface. +Linked API lets you manage LinkedIn accounts programmatically through an API interface. -To use Acoount API you must initialize Linked API with: +To use Linked API you must initialize with: -- `accountApiToken` – your main token that enables overall Account API access. +- `apiToken` – your main token that enables overall Linked API access. - `identificationToken` – unique token specific to each managed LinkedIn account. ```typescript const linkedapi = new LinkedApi({ - accountApiToken: "your-account-api-token", + apiToken: "your-api-token", identificationToken: "your-identification-token", }); ``` You can obtain these tokens through [Linked API Platform](https://app.linkedapi.io/account-api?ref=linkedapi-node), as demonstrated below: -![Account API Tokens](https://linkedapi.io/content/images/size/w1600/2025/07/tokens-1.webp) +![API Tokens](https://linkedapi.io/content/images/size/w1600/2025/07/tokens-1.webp) -**šŸ“– Documentation:** [Account API Documentation](https://linkedapi.io/docs/account-api/) +**šŸ“– Documentation:** [Documentation](https://linkedapi.io/docs/account-api/) --- @@ -102,7 +100,7 @@ Execute custom LinkedIn automation workflows with raw workflow definitions. - **Documentation:** [Building Workflows](https://linkedapi.io/docs/account-api/building-workflows/) | [Executing Workflows](https://linkedapi.io/docs/account-api/executing-workflows/) | [Actions Overview](https://linkedapi.io/docs/account-api/actions-overview/) ```typescript -const workflow = await linkedapi.account.executeCustomWorkflow({ +const workflow = await linkedapi.executeCustomWorkflow({ actionType: "st.searchCompanies", term: "Tech Inc", then: { actionType: "st.doForCompanies", ... } @@ -120,7 +118,7 @@ Retrieve the result of a previously started workflow by its ID. - **Documentation:** [Executing Workflows](https://linkedapi.io/docs/account-api/executing-workflows/) ```typescript -const result = await linkedapi.account.getWorkflowResult("workflow-id-123"); +const result = await linkedapi.getWorkflowResult("workflow-id-123"); ``` --- @@ -133,26 +131,26 @@ Retrieve comprehensive LinkedIn person profile data including experience, educat - **Returns:** `Promise>` - Person profile data ```typescript -const personWorkflow = await linkedapi.account.fetchPerson({ +const personWorkflow = await linkedapi.fetchPerson({ personUrl: "https://www.linkedin.com/in/john-doe", - retrieveExperience: true, // Get work experience and job history - retrieveEducation: true, // Get educational background and degrees - retrieveSkills: true, // Get skills and endorsements - retrieveLanguages: true, // Get languages and proficiency levels - retrievePosts: true, // Get recent posts and articles - retrieveComments: true, // Get comments made by the person - retrieveReactions: true, // Get reactions/likes given by the person + retrieveExperience: true, // Get work experience and job history + retrieveEducation: true, // Get educational background and degrees + retrieveSkills: true, // Get skills and endorsements + retrieveLanguages: true, // Get languages and proficiency levels + retrievePosts: true, // Get recent posts and articles + retrieveComments: true, // Get comments made by the person + retrieveReactions: true, // Get reactions/likes given by the person postsRetrievalConfig: { - limit: 20, // Maximum number of posts to retrieve (1-20) - since: "2024-01-01", // Retrieve posts since this date (YYYY-MM-DD) + limit: 20, // Maximum number of posts to retrieve (1-20) + since: "2024-01-01", // Retrieve posts since this date (YYYY-MM-DD) }, commentRetrievalConfig: { - limit: 10, // Maximum number of comments to retrieve (1-20) - since: "2024-01-01", // Retrieve comments since this date + limit: 10, // Maximum number of comments to retrieve (1-20) + since: "2024-01-01", // Retrieve comments since this date }, reactionRetrievalConfig: { - limit: 15, // Maximum number of reactions to retrieve (1-20) - since: "2024-01-01", // Retrieve reactions since this date + limit: 15, // Maximum number of reactions to retrieve (1-20) + since: "2024-01-01", // Retrieve reactions since this date }, }); const personData = await personWorkflow.result(); @@ -168,7 +166,7 @@ Retrieve person data through Sales Navigator for enhanced prospecting capabiliti - **Returns:** `Promise>` - Enhanced person data ```typescript -const nvPersonWorkflow = await linkedapi.account.salesNavigatorFetchPerson({ +const nvPersonWorkflow = await linkedapi.salesNavigatorFetchPerson({ personHashedUrl: "https://www.linkedin.com/in/ABC123", }); ``` @@ -183,30 +181,30 @@ Retrieve detailed LinkedIn company profile data including employees, posts, and - **Returns:** `Promise>` - Company profile data ```typescript -const companyWorkflow = await linkedapi.account.fetchCompany({ +const companyWorkflow = await linkedapi.fetchCompany({ companyUrl: "https://www.linkedin.com/company/microsoft", - retrieveEmployees: true, // Get company employees with their profiles - retrievePosts: true, // Get recent company posts and updates - retrieveDms: true, // Get decision makers and key personnel + retrieveEmployees: true, // Get company employees with their profiles + retrievePosts: true, // Get recent company posts and updates + retrieveDms: true, // Get decision makers and key personnel employeeRetrievalConfig: { - limit: 25, // Maximum number of employees to retrieve (1-500) + limit: 25, // Maximum number of employees to retrieve (1-500) filter: { - firstName: "John", // Filter by employee first name - lastName: "Smith", // Filter by employee last name - position: "engineer", // Filter by job position/title - locations: ["United States", "Canada"], // Filter by employee locations - industries: ["Software Development"], // Filter by industries + firstName: "John", // Filter by employee first name + lastName: "Smith", // Filter by employee last name + position: "engineer", // Filter by job position/title + locations: ["United States", "Canada"], // Filter by employee locations + industries: ["Software Development"], // Filter by industries currentCompanies: ["Microsoft", "Google"], // Filter by current companies - previousCompanies: ["Apple", "Amazon"], // Filter by previous companies - schools: ["Stanford University", "MIT"], // Filter by educational background + previousCompanies: ["Apple", "Amazon"], // Filter by previous companies + schools: ["Stanford University", "MIT"], // Filter by educational background }, }, postRetrievalConfig: { - limit: 10, // Maximum number of posts to retrieve (1-20) + limit: 10, // Maximum number of posts to retrieve (1-20) since: "2024-01-01", // Retrieve posts since this date (YYYY-MM-DD) }, dmRetrievalConfig: { - limit: 5, // Maximum number of decision makers to retrieve + limit: 5, // Maximum number of decision makers to retrieve }, }); const companyData = await companyWorkflow.result(); @@ -222,12 +220,12 @@ Retrieve company data through Sales Navigator with advanced filtering and prospe - **Returns:** `Promise>` - Enhanced company data ```typescript -const nvCompanyWorkflow = await linkedapi.account.salesNavigatorFetchCompany({ +const nvCompanyWorkflow = await linkedapi.salesNavigatorFetchCompany({ companyHashedUrl: "https://www.linkedin.com/sales/company/1035", retrieveEmployees: true, // Get company employees with Sales Navigator data - retrieveDms: true, // Get decision makers and key personnel + retrieveDms: true, // Get decision makers and key personnel employeeRetrievalConfig: { - limit: 25, // Maximum number of employees to retrieve (1-500) + limit: 25, // Maximum number of employees to retrieve (1-500) filter: { firstName: "John", lastName: "Doe", @@ -255,7 +253,7 @@ Retrieve detailed information about a LinkedIn post including content, engagemen - **Returns:** `Promise>` - Post data and metrics ```typescript -const postWorkflow = await linkedapi.account.fetchPost({ +const postWorkflow = await linkedapi.fetchPost({ postUrl: "https://www.linkedin.com/posts/john-doe_activity-123456789", }); ``` @@ -270,7 +268,7 @@ Search for companies on LinkedIn using standard search with advanced filtering o - **Returns:** `Promise>` - Array of company search results ```typescript -const companySearchWorkflow = await linkedapi.account.searchCompanies({ +const companySearchWorkflow = await linkedapi.searchCompanies({ term: "software development", // Search term/keywords for company name or description filter: { locations: ["San Francisco", "New York", "Seattle"], @@ -291,14 +289,14 @@ Search for companies using Sales Navigator with advanced prospecting filters. - **Returns:** `Promise>` - Enhanced company search results ```typescript -const nvCompanySearch = await linkedapi.account.salesNavigatorSearchCompanies({ +const nvCompanySearch = await linkedapi.salesNavigatorSearchCompanies({ term: "enterprise software", // Search term for company name, description, or keywords filter: { locations: ["San Francisco", "New York", "London"], industries: ["Software Development", "Enterprise Software", "SaaS"], sizes: ["201-500", "501-1000", "1001-5000"], annualRevenue: { - min: "10", // Minimum annual revenue in millions USD + min: "10", // Minimum annual revenue in millions USD max: "500", // Maximum annual revenue in millions USD }, }, @@ -316,7 +314,7 @@ Search for people on LinkedIn using standard search with location, experience, a - **Returns:** `Promise>` - Array of people search results ```typescript -const peopleSearchWorkflow = await linkedapi.account.searchPeople({ +const peopleSearchWorkflow = await linkedapi.searchPeople({ term: "product manager", // Search term filter: { firstName: "John", @@ -342,7 +340,7 @@ Search for people using Sales Navigator with advanced prospecting and lead gener - **Returns:** `Promise>` - Enhanced people search results ```typescript -const nvPeopleSearch = await linkedapi.account.salesNavigatorSearchPeople({ +const nvPeopleSearch = await linkedapi.salesNavigatorSearchPeople({ term: "VP Engineering", limit: 20, // Maximum number of results to return (1-100, default: 10) filter: { @@ -369,7 +367,7 @@ Send connection requests to LinkedIn users with optional personalized messages. - **Returns:** `Promise>` - Workflow handler (no result data) ```typescript -await linkedapi.account.sendConnectionRequest({ +await linkedapi.sendConnectionRequest({ personUrl: "https://www.linkedin.com/in/john-doe", note: "Hello! I'd love to connect and discuss opportunities.", }); @@ -385,7 +383,7 @@ Check the current connection status with a LinkedIn user. - **Returns:** `Promise>` - Connection status information ```typescript -const statusWorkflow = await linkedapi.account.checkConnectionStatus({ +const statusWorkflow = await linkedapi.checkConnectionStatus({ personUrl: "https://www.linkedin.com/in/john-doe", }); const status = await statusWorkflow.result(); @@ -402,7 +400,7 @@ Withdraw previously sent connection requests. - **Returns:** `Promise>` - Workflow handler (no result data) ```typescript -await linkedapi.account.withdrawConnectionRequest({ +await linkedapi.withdrawConnectionRequest({ personUrl: "https://www.linkedin.com/in/john-doe", }); ``` @@ -417,7 +415,7 @@ Retrieve all pending connection requests sent by your account. - **Returns:** `Promise>` - List of pending requests ```typescript -const pendingWorkflow = await linkedapi.account.retrievePendingRequests(); +const pendingWorkflow = await linkedapi.retrievePendingRequests(); const pending = await pendingWorkflow.result(); console.log("Pending requests:", pending.requests); ``` @@ -432,7 +430,7 @@ Retrieve existing connections with advanced filtering options. - **Returns:** `Promise>` - List of connections ```typescript -const connectionsWorkflow = await linkedapi.account.retrieveConnections({ +const connectionsWorkflow = await linkedapi.retrieveConnections({ filter: { firstName: "John", positions: ["Engineer", "Manager"], @@ -452,7 +450,7 @@ Remove existing connections from your LinkedIn network. - **Returns:** `Promise>` - Workflow handler (no result data) ```typescript -await linkedapi.account.removeConnection({ +await linkedapi.removeConnection({ personUrl: "https://www.linkedin.com/in/former-colleague", }); ``` @@ -467,7 +465,7 @@ React to LinkedIn posts with various reaction types (like, love, support, etc.). - **Returns:** `Promise>` - Workflow handler (no result data) ```typescript -await linkedapi.account.reactToPost({ +await linkedapi.reactToPost({ postUrl: "https://www.linkedin.com/posts/john-doe_activity-123456789", reactionType: "like", }); @@ -483,7 +481,7 @@ Comment on LinkedIn posts to engage with your network. - **Returns:** `Promise>` - Workflow handler (no result data) ```typescript -await linkedapi.account.commentOnPost({ +await linkedapi.commentOnPost({ postUrl: "https://www.linkedin.com/posts/john-doe_activity-123456789", text: "Great insight! Thanks for sharing.", }); @@ -499,7 +497,7 @@ Retrieve your LinkedIn Social Selling Index (SSI) score and rankings. - **Returns:** `Promise>` - SSI score and industry/network rankings ```typescript -const ssiWorkflow = await linkedapi.account.retrieveSSI(); +const ssiWorkflow = await linkedapi.retrieveSSI(); const ssi = await ssiWorkflow.result(); console.log("SSI Score:", ssi.ssi, "Industry Top:", ssi.industryTop); ``` @@ -514,7 +512,7 @@ Retrieve LinkedIn account performance metrics including profile views and post e - **Returns:** `Promise>` - Performance metrics ```typescript -const performanceWorkflow = await linkedapi.account.retrievePerformance(); +const performanceWorkflow = await linkedapi.retrievePerformance(); const metrics = await performanceWorkflow.result(); console.log("Profile views:", metrics.profileViewsLast90Days); console.log("Post views:", metrics.postViewsLast7Days); @@ -534,7 +532,7 @@ Retrieve Account API usage statistics for monitoring and optimization. const endDate = new Date(); const startDate = new Date(endDate.getTime() - 7 * 24 * 60 * 60 * 1000); -const statsResponse = await linkedapi.account.getApiUsageStats({ +const statsResponse = await linkedapi.getApiUsageStats({ start: startDate.toISOString(), end: endDate.toISOString(), }); @@ -559,7 +557,7 @@ Send messages to LinkedIn users through standard LinkedIn messaging. - **Returns:** `Promise>` - Workflow handler (no result data) ```typescript -await linkedapi.account.sendMessage({ +await linkedapi.sendMessage({ personUrl: "https://www.linkedin.com/in/john-doe", text: "Hello! I saw your post about AI and wanted to connect.", }); @@ -576,7 +574,7 @@ Sync conversation history with a LinkedIn user for message polling. - **Related Methods:** Use with `pollConversations()` to retrieve message history ```typescript -await linkedapi.account.syncConversation({ +await linkedapi.syncConversation({ personUrl: "https://www.linkedin.com/in/john-doe", }); ``` @@ -591,7 +589,7 @@ Send messages through Sales Navigator with enhanced messaging capabilities. - **Returns:** `Promise>` - Workflow handler (no result data) ```typescript -await linkedapi.account.salesNavigatorSendMessage({ +await linkedapi.salesNavigatorSendMessage({ personUrl: "https://www.linkedin.com/sales/people/ABC123", subject: "Partnership Opportunity", text: "Hi! I'd love to discuss potential collaboration opportunities.", @@ -608,7 +606,7 @@ Sync Sales Navigator conversation for message polling. - **Returns:** `Promise>` - Workflow handler (no result data) ```typescript -await linkedapi.account.salesNavigatorSyncConversation({ +await linkedapi.salesNavigatorSyncConversation({ personUrl: "https://www.linkedin.com/sales/people/ABC123", }); ``` @@ -624,7 +622,7 @@ Poll multiple conversations to retrieve message history and new messages. - **Prerequisites:** Must call `syncConversation()` or `salesNavigatorSyncConversation()` for each person before polling ```typescript -const response = await linkedapi.account.pollConversations([ +const response = await linkedapi.pollConversations([ { personUrl: "https://www.linkedin.com/in/john-doe", type: "st" }, { personUrl: "https://www.linkedin.com/sales/people/ABC123", @@ -645,203 +643,6 @@ if (response.success) { --- -## šŸ” Data API - -Data API lets you retrieve real-time LinkedIn data through an API interface, even if you don't have or don't want to connect your own LinkedIn account. - -**šŸ“– Documentation:** [Data API Documentation](https://linkedapi.io/docs/data-api/) - -Your requests must include the authorization header: - -- `dataApiToken` – your main token that enables overall Data API access. - -```typescript -const linkedapi = new LinkedApi({ - dataApiToken: "your-data-api-token", -}); -``` - -You can obtain this token through Linked API Platform, as demonstrated below: -![Data API Token](https://linkedapi.io/content/images/2025/07/data-token.webp) - ---- - -### `executeCustomWorkflow(params)` - -Execute custom Data API workflows with raw workflow definitions. - -- **Parameters:** `TWorkflowDefinition` - Custom workflow definition -- **Returns:** `Promise` - Workflow handler for result management -- **Documentation:** [Building Workflows](https://linkedapi.io/docs/data-api/building-workflows-0/) | [Executing Workflows](https://linkedapi.io/docs/data-api/executing-workflows-0/) | [Actions Overview](https://linkedapi.io/docs/data-api/actions-overview-0/) - -```typescript -const customWorkflow = await linkedapi.data.executeCustomWorkflow({ - actionType: "searchCompanies", - term: "AI startup", - limit: 10, - then: { - actionType: "doForCompanies", - then: { actionType: "openCompanyPage", basicInfo: true }, - }, -}); -``` - ---- - -### `getWorkflowResult(workflowId)` - -Retrieve Data API workflow results by workflow ID. - -- **Parameters:** `string` - Workflow ID -- **Returns:** `Promise` - Workflow response with completion data -- **Documentation:** [Executing Workflows](https://linkedapi.io/docs/data-api/executing-workflows-0/) - -```typescript -const workflowResponse = - await linkedapi.data.getWorkflowResult("workflow-id-123"); -if (workflowResponse.completion) { - console.log("Data API workflow completed:", workflowResponse.completion.data); -} -``` - ---- - -### `fetchPerson(params)` - -Retrieve comprehensive person profile data using Data API credits. - -- **Parameters:** `TBaseFetchPersonParams` - Person URL and data retrieval options -- **Returns:** `Promise>` - Person profile data - -```typescript -const personWorkflow = await linkedapi.data.fetchPerson({ - personUrl: "https://www.linkedin.com/in/john-doe", // LinkedIn person profile URL - retrieveExperience: true, // Get work experience and job history - retrieveEducation: true, // Get educational background and degrees - retrieveSkills: true, // Get skills and endorsements - retrieveLanguages: true, // Get languages and proficiency levels - retrievePosts: true, // Get recent posts and articles - retrieveComments: true, // Get comments made by the person - retrieveReactions: true, // Get reactions/likes given by the person - postsRetrievalConfig: { - limit: 15, // Maximum number of posts to retrieve (1-20) - since: "2024-01-01", // Retrieve posts since this date (YYYY-MM-DD) - }, - commentRetrievalConfig: { - limit: 15, // Maximum number of comments to retrieve (1-20) - since: "2024-01-01", // Retrieve comments since this date - }, - reactionRetrievalConfig: { - limit: 10, // Maximum number of reactions to retrieve (1-20) - since: "2024-01-01", // Retrieve reactions since this date - }, -}); -const personData = await personWorkflow.result(); -``` - ---- - -### `fetchCompany(params)` - -Retrieve detailed company profile data using Data API credits. - -- **Parameters:** `TDtBaseFetchCompanyParams` - Company URL and data retrieval options -- **Returns:** `Promise>` - Company profile data - -```typescript -const companyWorkflow = await linkedapi.data.fetchCompany({ - companyUrl: "https://www.linkedin.com/company/microsoft", // LinkedIn company page URL - retrieveEmployees: true, // Get company employees with their profiles - retrieveDms: true, // Get decision makers and key personnel - employeeRetrievalConfig: { - limit: 30, // Maximum number of employees to retrieve (1-500) - filter: { - position: "engineer", - locations: ["United States", "Canada"], - industries: ["Software Development", "Technology"], - currentCompanies: ["Microsoft", "Google"], - previousCompanies: ["Apple", "Amazon"], - schools: ["Stanford University", "MIT"], - }, - }, - dmRetrievalConfig: { - limit: 10, // Maximum number of decision makers to retrieve (1-20) - }, -}); -const companyData = await companyWorkflow.result(); -``` - ---- - -### `fetchPost(params)` - -Retrieve LinkedIn post data and engagement metrics using Data API. - -- **Parameters:** `TFetchPostParams` - Post URL -- **Returns:** `Promise>` - Post data and engagement metrics - -```typescript -const postWorkflow = await linkedapi.data.fetchPost({ - postUrl: - "https://www.linkedin.com/posts/john-doe_activity-123456789", -}); -``` - ---- - -### `searchCompanies(params)` - -Search for companies with advanced filtering using Data API credits. - -- **Parameters:** `TNvSearchCompanyParams` - Search term, filters, and pagination -- **Returns:** `Promise>` - Array of company search results - -```typescript -const companySearchWorkflow = await linkedapi.data.searchCompanies({ - term: "Tech Inc", // Search term for company name, description, or keywords - limit: 100, // Maximum number of results to return (1-100, default: 10) - filter: { - sizes: ["11-50", "51-200", "201-500"], // Employee count ranges - locations: ["New York", "Austin"], // Company headquarters locations - industries: ["Software Development", "Robotics Engineering", "AI", "SaaS"], - annualRevenue: { - min: "1", // Minimum annual revenue in millions USD - max: "100", // Maximum annual revenue in millions USD - }, - }, - since: "2024-01-01", // Filter companies updated since this date (YYYY-MM-DD) -}); -``` - ---- - -### `searchPeople(params)` - -Search for professionals with advanced filtering using Data API credits. - -- **Parameters:** `TNvSearchPeopleParams` - Search term, filters, and pagination -- **Returns:** `Promise>` - Array of people search results - -```typescript -const peopleSearchWorkflow = await linkedapi.data.searchPeople({ - term: "software engineer React", // Search term for name, headline, or job title - limit: 50, // Maximum number of results to return (1-100, default: 10) - filter: { - firstName: "John", - lastName: "Doe", - position: "CEO", - locations: ["New York", "San Francisco", "London"], - industries: ["Software Development", "Professional Services"], - currentCompanies: ["Tech Solutions", "Innovatech"], - previousCompanies: ["FutureCorp"], - schools: ["Harvard University", "MIT"], - yearsOfExperience: ["lessThanOne", "oneToTwo", "threeToFive"], - }, -}); -``` - ---- - ## šŸ’” Best Practices ### Custom Workflows for Complex Scenarios @@ -856,7 +657,7 @@ For complex multi-step workflows involving multiple actions, it's recommended to ```typescript // āœ… Recommended: Custom workflow for complex operations -const customWorkflow = await linkedapi.account.executeCustomWorkflow({ +const customWorkflow = await linkedapi.executeCustomWorkflow({ actionType: "st.searchCompanies", term: "AI startup", filter: { locations: ["San Francisco"], sizes: ["11-50", "51-200"] }, @@ -887,7 +688,7 @@ const customWorkflow = await linkedapi.account.executeCustomWorkflow({ // vs. āŒ Less efficient: Multiple separate API calls // (Multiple network requests, no atomicity, complex error handling) try { - const searchCompaniesWorkflow = await linkedapi.account.searchCompanies({ + const searchCompaniesWorkflow = await linkedapi.searchCompanies({ term: "AI startup", filter: { locations: ["San Francisco"], sizes: ["11-50", "51-200"] }, limit: 10, @@ -895,7 +696,7 @@ try { const companies = await searchCompaniesWorkflow.result(); for (company of companies) { try { - const companyEmployeesWorkflow = await linkedapi.account.fetchCompany({ + const companyEmployeesWorkflow = await linkedapi.fetchCompany({ retrieveEmployees: true, employeeRetrievalConfig: { limit: 5, @@ -907,7 +708,7 @@ try { const employees = await companyEmployeesWorkflow.result(); for (employee of employees) { try { - const sendConnectionWorkflow = await linkedapi.account.sendConnectionRequest({ + const sendConnectionWorkflow = await linkedapi.sendConnectionRequest({ personUrl: employee.publicUrl, note: "Hi! I'd love to connect.", email: "example@example.com" @@ -938,7 +739,7 @@ When you start a workflow, you can access its ID immediately and store it for la ```typescript // Start a workflow and save the ID -const personWorkflow = await linkedapi.account.fetchPerson({ +const personWorkflow = await linkedapi.fetchPerson({ personUrl: "https://www.linkedin.com/in/john-doe", retrieveExperience: true, }); @@ -965,7 +766,7 @@ If your application restarts or you need to check workflow status later, use `ge const savedWorkflows = await getWorkflowsFromDatabase(); for (workflowId of runningWorkflows) { try { - const result = await linkedapi.account.getWorkflowResult(workflowId); + const result = await linkedapi.getWorkflowResult(workflowId); if (result.completion) { console.log("Workflow completed:", result.completion.data); @@ -994,7 +795,7 @@ Linked API provides structured error handling for different failure scenarios. import LinkedApi from "linkedapi-node"; try { - const result = await linkedapi.account.fetchPerson({ + const result = await linkedapi.fetchPerson({ personUrl: "https://www.linkedin.com/in/invalid-profile", }); const data = await result.result(); @@ -1014,22 +815,13 @@ try { ### Common Error Types -#### Account API - -- **`accountApiTokenRequired`** - Missing Account API token -- **`invalidAccountApiToken`** - Invalid Account API token +- **`accountApiTokenRequired`** - Missing API token +- **`invalidAccountApiToken`** - Invalid API token - **`identificationTokenRequired`** - Missing Indentification token - **`invalidIdentificationToken`** - Invalid Identification Token - **`subscriptionRequired`** - No purchased subscription seats available for this LinkedIn account. - **`invalidRequestPayload`** - Invalid request body/parameters: {validation_message}. -#### Data API - -- **`dataApiTokenRequired`** - Missing Data API token -- **`invalidDataApiToken`** - Invalid Data API token -- **`insufficientCredits`** - Not enough Data API credits -- **`invalidRequestPayload`** - Invalid request body/parameters: {validation_message}. - --- ## šŸ“„ License diff --git a/examples/connections.ts b/examples/connections.ts index 18ebcf1..3c1c6e4 100644 --- a/examples/connections.ts +++ b/examples/connections.ts @@ -1,4 +1,4 @@ -import LinkedApi from 'linkedapi-node'; +import LinkedApi, { LinkedApiError, LinkedApiWorkflowError } from 'linkedapi-node'; async function connectionsExample(): Promise { @@ -21,10 +21,10 @@ async function connectionsExample(): Promise { await removeConnection(linkedapi, targetPersonUrl2); } catch (error) { - if (error instanceof LinkedApi.LinkedApiError) { + if (error instanceof LinkedApiError) { console.error('🚨 Linked API Error:', error.message); console.error('šŸ“ Details:', error.details); - } else if (error instanceof LinkedApi.LinkedApiWorkflowError) { + } else if (error instanceof LinkedApiWorkflowError) { console.error('🚨 Linked API Workflow Error:', error.message); console.error('šŸ” Reason:', error.reason); } else { @@ -40,7 +40,7 @@ async function checkConnectionStatus(linkedapi: LinkedApi, personUrl: string): P personUrl: personUrl, }; - const statusWorkflow = await linkedapi.account.checkConnectionStatus(statusParams); + const statusWorkflow = await linkedapi.checkConnectionStatus(statusParams); console.log('šŸ” Connection status workflow started:', statusWorkflow.workflowId); const statusResult = await statusWorkflow.result(); @@ -57,7 +57,7 @@ async function sendConnectionRequest(linkedapi: LinkedApi, personUrl: string): P email: 'example@gmail.com', }; - const requestWorkflow = await linkedapi.account.sendConnectionRequest(requestParams); + const requestWorkflow = await linkedapi.sendConnectionRequest(requestParams); console.log('šŸ“¤ Send connection request workflow started:', requestWorkflow.workflowId); await requestWorkflow.result(); @@ -68,7 +68,7 @@ async function sendConnectionRequest(linkedapi: LinkedApi, personUrl: string): P async function retrievePendingRequests(linkedapi: LinkedApi): Promise { console.log('\nšŸ“‹ Retrieving pending connection requests...'); - const pendingWorkflow = await linkedapi.account.retrievePendingRequests(); + const pendingWorkflow = await linkedapi.retrievePendingRequests(); console.log('šŸ“‹ Retrieve pending requests workflow started:', pendingWorkflow.workflowId); const pendingResults = await pendingWorkflow.result(); @@ -90,7 +90,7 @@ async function withdrawConnectionRequest(linkedapi: LinkedApi, personUrl: string unfollow: true, }; - const withdrawWorkflow = await linkedapi.account.withdrawConnectionRequest(withdrawParams); + const withdrawWorkflow = await linkedapi.withdrawConnectionRequest(withdrawParams); console.log('šŸ”™ Withdraw connection request workflow started:', withdrawWorkflow.workflowId); await withdrawWorkflow.result(); @@ -109,7 +109,7 @@ async function retrieveConnections(linkedapi: LinkedApi): Promise { }, }; - const connectionsWorkflow = await linkedapi.account.retrieveConnections(connectionsParams); + const connectionsWorkflow = await linkedapi.retrieveConnections(connectionsParams); console.log('šŸ‘„ Retrieve connections workflow started:', connectionsWorkflow.workflowId); const connectionsResults = await connectionsWorkflow.result(); @@ -131,7 +131,7 @@ async function removeConnection(linkedapi: LinkedApi, personUrl: string): Promis personUrl: personUrl, }; - const removeWorkflow = await linkedapi.account.removeConnection(removeParams); + const removeWorkflow = await linkedapi.removeConnection(removeParams); console.log('āŒ Remove connection workflow started:', removeWorkflow.workflowId); await removeWorkflow.result(); diff --git a/examples/custom-workflow.ts b/examples/custom-workflow.ts index 462251c..13602e3 100644 --- a/examples/custom-workflow.ts +++ b/examples/custom-workflow.ts @@ -1,4 +1,4 @@ -import LinkedApi from 'linkedapi-node'; +import LinkedApi, { LinkedApiError, LinkedApiWorkflowError } from 'linkedapi-node'; async function customWorkflowExample(): Promise { @@ -9,7 +9,7 @@ async function customWorkflowExample(): Promise { try { console.log('šŸš€ Linked API custom workflow example starting...'); - const customWorkflow = await linkedapi.account.executeCustomWorkflow({ + const customWorkflow = await linkedapi.executeCustomWorkflow({ actionType: 'st.searchPeople', limit: 5, filter: { @@ -32,10 +32,10 @@ async function customWorkflowExample(): Promise { console.log('āœ… Custom workflow executed successfully'); console.log('šŸ” Result: ', result.completion); } catch (error) { - if (error instanceof LinkedApi.LinkedApiError) { + if (error instanceof LinkedApiError) { console.error('🚨 Linked API Error:', error.message); console.error('šŸ“ Details:', error.details); - } else if (error instanceof LinkedApi.LinkedApiWorkflowError) { + } else if (error instanceof LinkedApiWorkflowError) { console.error('🚨 Linked API Workflow Error:', error.message); console.error('šŸ” Reason:', error.reason); } else { diff --git a/examples/fetch-company.ts b/examples/fetch-company.ts index 2b19456..7772482 100644 --- a/examples/fetch-company.ts +++ b/examples/fetch-company.ts @@ -1,4 +1,4 @@ -import LinkedApi from 'linkedapi-node'; +import LinkedApi, { LinkedApiError, LinkedApiWorkflowError } from 'linkedapi-node'; async function fetchCompanyExample(): Promise { const linkedapi = new LinkedApi({ @@ -12,10 +12,10 @@ async function fetchCompanyExample(): Promise { await salesNavigatorExample(linkedapi); } catch (error) { - if (error instanceof LinkedApi.LinkedApiError) { + if (error instanceof LinkedApiError) { console.error('🚨 Linked API Error:', error.message); console.error('šŸ“ Details:', error.details); - } else if (error instanceof LinkedApi.LinkedApiWorkflowError) { + } else if (error instanceof LinkedApiWorkflowError) { console.error('🚨 Linked API Workflow Error:', error.message); console.error('šŸ” Reason:', error.reason); } else { @@ -25,7 +25,7 @@ async function fetchCompanyExample(): Promise { } async function standardExample(linkedapi: LinkedApi): Promise { - const fetchCompanyWorkflow = await linkedapi.account.fetchCompany({ + const fetchCompanyWorkflow = await linkedapi.fetchCompany({ companyUrl: 'https://www.linkedin.com/company/linkedin/', retrieveEmployees: true, retrieveDms: true, @@ -61,7 +61,7 @@ async function standardExample(linkedapi: LinkedApi): Promise { } async function salesNavigatorExample(linkedapi: LinkedApi): Promise { - const nvCompanyResult = await linkedapi.account.salesNavigatorFetchCompany({ + const nvCompanyResult = await linkedapi.salesNavigatorFetchCompany({ companyHashedUrl: 'https://www.linkedin.com/sales/company/1035', retrieveEmployees: true, retrieveDms: true, diff --git a/examples/fetch-person.ts b/examples/fetch-person.ts index 464e45b..acb4b29 100644 --- a/examples/fetch-person.ts +++ b/examples/fetch-person.ts @@ -1,4 +1,4 @@ -import LinkedApi from 'linkedapi-node'; +import LinkedApi, { LinkedApiError, LinkedApiWorkflowError } from 'linkedapi-node'; async function fetchPersonExample(): Promise { @@ -13,10 +13,10 @@ async function fetchPersonExample(): Promise { await standardExample(linkedapi); await salesNavigatorExample(linkedapi); } catch (error) { - if (error instanceof LinkedApi.LinkedApiError) { + if (error instanceof LinkedApiError) { console.error('🚨 Linked API Error:', error.message); console.error('šŸ“ Details:', error.details); - } else if (error instanceof LinkedApi.LinkedApiWorkflowError) { + } else if (error instanceof LinkedApiWorkflowError) { console.error('🚨 Linked API Workflow Error:', error.message); console.error('šŸ” Reason:', error.reason); } else { @@ -26,7 +26,7 @@ async function fetchPersonExample(): Promise { } async function standardExample(linkedapi: LinkedApi): Promise { - const personResult = await linkedapi.account.fetchPerson({ + const personResult = await linkedapi.fetchPerson({ personUrl: 'https://www.linkedin.com/in/example-person/', retrieveExperience: true, retrieveEducation: true, @@ -62,7 +62,7 @@ async function salesNavigatorExample(linkedapi: LinkedApi): Promise { personHashedUrl: 'https://www.linkedin.com/in/abc123', }; - const personResult = await linkedapi.account.salesNavigatorFetchPerson(fetchParams); + const personResult = await linkedapi.salesNavigatorFetchPerson(fetchParams); console.log('šŸ” Workflow started: ', personResult.workflowId); const person = await personResult.result(); diff --git a/examples/fetch-post.ts b/examples/fetch-post.ts index f26691f..ccd65de 100644 --- a/examples/fetch-post.ts +++ b/examples/fetch-post.ts @@ -1,4 +1,4 @@ -import LinkedApi from 'linkedapi-node'; +import LinkedApi, { LinkedApiError, LinkedApiWorkflowError } from 'linkedapi-node'; async function fetchPostExample(): Promise { const linkedapi = new LinkedApi({ @@ -10,10 +10,10 @@ async function fetchPostExample(): Promise { console.log('šŸš€ Linked API fetchPost example starting...'); await standardExample(linkedapi); } catch (error) { - if (error instanceof LinkedApi.LinkedApiError) { + if (error instanceof LinkedApiError) { console.error('🚨 Linked API Error:', error.message); console.error('šŸ“ Details:', error.details); - } else if (error instanceof LinkedApi.LinkedApiWorkflowError) { + } else if (error instanceof LinkedApiWorkflowError) { console.error('🚨 Linked API Workflow Error:', error.message); console.error('šŸ” Reason:', error.reason); } else { @@ -23,7 +23,7 @@ async function fetchPostExample(): Promise { } async function standardExample(linkedapi: LinkedApi): Promise { - const accountPostWorkflow = await linkedapi.account.fetchPost({ + const accountPostWorkflow = await linkedapi.fetchPost({ postUrl: 'https://www.linkedin.com/posts/post-url' }); console.log('šŸ” Account API workflow started:', accountPostWorkflow.workflowId); diff --git a/examples/messaging.ts b/examples/messaging.ts index 2b480cf..1e9a28b 100644 --- a/examples/messaging.ts +++ b/examples/messaging.ts @@ -1,4 +1,4 @@ -import LinkedApi from 'linkedapi-node'; +import LinkedApi, { LinkedApiError, LinkedApiWorkflowError } from 'linkedapi-node'; async function messagingExample(): Promise { const linkedapi = new LinkedApi({ @@ -21,10 +21,10 @@ async function messagingExample(): Promise { await pollConversations(linkedapi, targetPersonUrl, targetPersonUrl2); } catch (error) { - if (error instanceof LinkedApi.LinkedApiError) { + if (error instanceof LinkedApiError) { console.error('🚨 Linked API Error:', error.message); console.error('šŸ“ Details:', error.details); - } else if (error instanceof LinkedApi.LinkedApiWorkflowError) { + } else if (error instanceof LinkedApiWorkflowError) { console.error('🚨 Linked API Workflow Error:', error.message); console.error('šŸ” Reason:', error.reason); } else { @@ -41,7 +41,7 @@ async function sendMessage(linkedapi: LinkedApi, personUrl: string): Promise { console.log('\nšŸ“„ Polling conversations...'); - const pollResponse = await linkedapi.account.pollConversations([ + const pollResponse = await linkedapi.pollConversations([ { personUrl: standardPersonUrl, type: 'st', diff --git a/examples/post-actions.ts b/examples/post-actions.ts index 33b0d5e..c4a75df 100644 --- a/examples/post-actions.ts +++ b/examples/post-actions.ts @@ -1,4 +1,4 @@ -import LinkedApi from 'linkedapi-node'; +import LinkedApi, { LinkedApiError, LinkedApiWorkflowError } from 'linkedapi-node'; async function postActionsExample(): Promise { const linkedapi = new LinkedApi({ @@ -12,14 +12,14 @@ async function postActionsExample(): Promise { await commentOnPost(linkedapi); } catch (error) { - if (error instanceof LinkedApi.LinkedApiError) { + if (error instanceof LinkedApiError) { console.error('🚨 Linked API Error:', error.message); console.error('šŸ“ Details:', error.details); - } else if (error instanceof LinkedApi.LinkedApiWorkflowError) { + } else if (error instanceof LinkedApiWorkflowError) { console.error('🚨 Linked API Workflow Error:', error.message); console.error('šŸ” Reason:', error.reason); } else { - console.error('šŸ’„ Unknown error:', error); + console.error('šŸ’„ Unknown error:', error); } } } @@ -32,7 +32,7 @@ async function reactToPost(linkedapi: LinkedApi): Promise { type: 'like' as const, }; - const reactionWorkflow = await linkedapi.account.reactToPost(reactionParams); + const reactionWorkflow = await linkedapi.reactToPost(reactionParams); console.log('šŸ‘ React to post workflow started:', reactionWorkflow.workflowId); await reactionWorkflow.result(); @@ -47,7 +47,7 @@ async function commentOnPost(linkedapi: LinkedApi): Promise { text: 'Great post! Thanks for sharing this valuable insight. Looking forward to more content like this.', }; - const commentWorkflow = await linkedapi.account.commentOnPost(commentParams); + const commentWorkflow = await linkedapi.commentOnPost(commentParams); console.log('šŸ’¬ Comment on post workflow started:', commentWorkflow.workflowId); await commentWorkflow.result(); diff --git a/examples/search-companies.ts b/examples/search-companies.ts index 61ff64f..cf09478 100644 --- a/examples/search-companies.ts +++ b/examples/search-companies.ts @@ -1,4 +1,4 @@ -import LinkedApi, { TSearchCompanySize } from 'linkedapi-node'; +import LinkedApi, { LinkedApiError, LinkedApiWorkflowError, TSearchCompanySize } from 'linkedapi-node'; async function searchCompaniesExample(): Promise { const linkedapi = new LinkedApi({ @@ -13,10 +13,10 @@ async function searchCompaniesExample(): Promise { await salesNavigatorExample(linkedapi); } catch (error) { - if (error instanceof LinkedApi.LinkedApiError) { + if (error instanceof LinkedApiError) { console.error('🚨 Linked API Error:', error.message); console.error('šŸ“ Details:', error.details); - } else if (error instanceof LinkedApi.LinkedApiWorkflowError) { + } else if (error instanceof LinkedApiWorkflowError) { console.error('🚨 Linked API Workflow Error:', error.message); console.error('šŸ” Reason:', error.reason); } else { @@ -37,7 +37,7 @@ async function standardExample(linkedapi: LinkedApi): Promise { }; console.log('šŸ” Searching companies with Account API...'); - const accountSearchWorkflow = await linkedapi.account.searchCompanies(searchParams); + const accountSearchWorkflow = await linkedapi.searchCompanies(searchParams); console.log('šŸ” Account API workflow started:', accountSearchWorkflow.workflowId); const accountResults = await accountSearchWorkflow.result(); @@ -67,7 +67,7 @@ async function salesNavigatorExample(linkedapi: LinkedApi): Promise { }; console.log('\nšŸŽÆ Searching companies with Sales Navigator (Account API)...'); - const nvSearchWorkflow = await linkedapi.account.salesNavigatorSearchCompanies(nvSearchParams); + const nvSearchWorkflow = await linkedapi.salesNavigatorSearchCompanies(nvSearchParams); console.log('šŸ” Sales Navigator workflow started:', nvSearchWorkflow.workflowId); const nvResults = await nvSearchWorkflow.result(); diff --git a/examples/search-people.ts b/examples/search-people.ts index 9bd2d15..4e25f13 100644 --- a/examples/search-people.ts +++ b/examples/search-people.ts @@ -1,4 +1,4 @@ -import LinkedApi, { TYearsOfExperience } from 'linkedapi-node'; +import LinkedApi, { LinkedApiError, LinkedApiWorkflowError, TYearsOfExperience } from 'linkedapi-node'; async function searchPeopleExample(): Promise { const linkedapi = new LinkedApi({ @@ -12,10 +12,10 @@ async function searchPeopleExample(): Promise { await salesNavigatorExample(linkedapi); } catch (error) { - if (error instanceof LinkedApi.LinkedApiError) { + if (error instanceof LinkedApiError) { console.error('🚨 Linked API Error:', error.message); console.error('šŸ“ Details:', error.details); - } else if (error instanceof LinkedApi.LinkedApiWorkflowError) { + } else if (error instanceof LinkedApiWorkflowError) { console.error('🚨 Linked API Workflow Error:', error.message); console.error('šŸ” Reason:', error.reason); } else { @@ -39,7 +39,7 @@ async function standardExample(linkedapi: LinkedApi): Promise { }; console.log('šŸ” Searching people with Account API...'); - const accountSearchWorkflow = await linkedapi.account.searchPeople(searchParams); + const accountSearchWorkflow = await linkedapi.searchPeople(searchParams); console.log('šŸ” Account API workflow started:', accountSearchWorkflow.workflowId); const accountResults = await accountSearchWorkflow.result(); @@ -67,7 +67,7 @@ async function salesNavigatorExample(linkedapi: LinkedApi): Promise { }; console.log('\nšŸŽÆ Searching people with Sales Navigator (Account API)...'); - const nvSearchWorkflow = await linkedapi.account.salesNavigatorSearchPeople(nvSearchParams); + const nvSearchWorkflow = await linkedapi.salesNavigatorSearchPeople(nvSearchParams); console.log('šŸ” Sales Navigator workflow started:', nvSearchWorkflow.workflowId); const nvResults = await nvSearchWorkflow.result(); diff --git a/examples/statistics.ts b/examples/statistics.ts index 8e3c7c8..bb03f43 100644 --- a/examples/statistics.ts +++ b/examples/statistics.ts @@ -1,4 +1,4 @@ -import LinkedApi from 'linkedapi-node'; +import LinkedApi, { LinkedApiError, LinkedApiWorkflowError } from 'linkedapi-node'; async function statisticsExample(): Promise { const linkedapi = new LinkedApi({ @@ -14,10 +14,10 @@ async function statisticsExample(): Promise { await getRecentUsageStats(linkedapi); } catch (error) { - if (error instanceof LinkedApi.LinkedApiError) { + if (error instanceof LinkedApiError) { console.error('🚨 Linked API Error:', error.message); console.error('šŸ“ Details:', error.details); - } else if (error instanceof LinkedApi.LinkedApiWorkflowError) { + } else if (error instanceof LinkedApiWorkflowError) { console.error('🚨 Linked API Workflow Error:', error.message); console.error('šŸ” Reason:', error.reason); } else { @@ -29,7 +29,7 @@ async function statisticsExample(): Promise { async function retrieveSSI(linkedapi: LinkedApi): Promise { console.log('\nšŸ“Š Retrieving SSI (Social Selling Index)...'); - const ssiWorkflow = await linkedapi.account.retrieveSSI(); + const ssiWorkflow = await linkedapi.retrieveSSI(); console.log('šŸ“Š Retrieve SSI workflow started:', ssiWorkflow.workflowId); const ssiResult = await ssiWorkflow.result(); @@ -49,7 +49,7 @@ async function retrieveSSI(linkedapi: LinkedApi): Promise { async function retrievePerformance(linkedapi: LinkedApi): Promise { console.log('\nšŸ“ˆ Retrieving Performance Statistics...'); - const performanceWorkflow = await linkedapi.account.retrievePerformance(); + const performanceWorkflow = await linkedapi.retrievePerformance(); console.log('šŸ“ˆ Retrieve performance workflow started:', performanceWorkflow.workflowId); const performanceResult = await performanceWorkflow.result(); @@ -67,7 +67,7 @@ async function getRecentUsageStats(linkedapi: LinkedApi): Promise { const endDate = new Date(); const startDate = new Date(endDate.getTime() - 7 * 24 * 60 * 60 * 1000); - const statsResponse = await linkedapi.account.getApiUsageStats({ + const statsResponse = await linkedapi.getApiUsageStats({ start: startDate.toISOString(), end: endDate.toISOString() }); diff --git a/src/account-api/account-api.ts b/src/account-api/account-api.ts deleted file mode 100644 index 686cbdc..0000000 --- a/src/account-api/account-api.ts +++ /dev/null @@ -1,1299 +0,0 @@ -import type { - TWorkflowDefinition, - TWorkflowResponse, -} from "../types/workflows"; -import type { - TBaseFetchPersonParams, - TFetchPersonParams, - TFetchPersonResult, -} from "../types/actions/person"; -import type { - TBaseFetchCompanyParams, - TFetchCompanyParams, - TFetchCompanyResult, -} from "../types/actions/company"; -import type { - TNvBaseFetchCompanyParams, - TNvFetchCompanyParams, - TNvFetchCompanyResult, -} from "../types/actions/company.sales-navigator"; -import type { - TFetchPostParams, - TFetchPostResult, - TReactToPostParams, - TCommentOnPostParams, -} from "../types/actions/post"; -import type { - TRetrieveSSIResult, - TRetrievePerformanceResult, - TApiUsageStatsParams, - TApiUsageStatsResponse, - TApiUsageAction, -} from "../types/actions/statistics"; -import type { - TSearchCompanyParams, - TSearchCompanyResult, - TNvSearchCompanyParams, - TNvSearchCompanyResult, -} from "../types/actions/search-company"; -import type { - TSearchPeopleParams, - TSearchPeopleResult, - TNvSearchPeopleParams, - TNvSearchPeopleResult, -} from "../types/actions/search-people"; -import type { - TSendConnectionRequestParams, - TCheckConnectionStatusParams, - TCheckConnectionStatusResult, - TWithdrawConnectionRequestParams, - TRetrievePendingRequestsResult, - TRetrieveConnectionsParams, - TRetrieveConnectionsResult, - TRemoveConnectionParams, - TNvOpenPersonPageParams, - TNvOpenPersonPageResult, -} from "../types/actions/connection"; -import { AcFetchPersonMapper } from "./fetch-person-mapper"; -import { AcFetchCompanyMapper } from "./fetch-company-mapper"; -import { AcFetchNvCompanyMapper } from "./fetch-nv-company-mapper"; -import { AcSearchCompaniesMapper } from "./search-companies-mapper"; -import { AcSalesNavigatorSearchCompaniesMapper } from "./sales-navigator-search-companies-mapper"; -import { AcSearchPeopleMapper } from "./search-people-mapper"; -import { AcSalesNavigatorSearchPeopleMapper } from "./sales-navigator-search-people-mapper"; -import { AcRetrievePendingRequestsMapper } from "./retrieve-pending-requests-mapper"; -import { AcRetrieveConnectionsMapper } from "./retrieve-connections-mapper"; -import { AcNvOpenPersonPageMapper } from "./nv-open-person-page-mapper"; -import { VoidWorkflowMapper } from "../core/void-workflow-mapper"; -import { SimpleWorkflowMapper } from "../core/simple-workflow-mapper"; -import { WorkflowHandler } from "../core/workflow-handler"; -import type { WorkflowExecutor } from "../core/workflow-executor"; -import type { TBaseActionParams } from "../types/params"; -import { HttpClient } from "../core/http-client"; -import { - TConversationPollRequest, - TConversationPollResponse, - TConversationPollResult, - TNvSendMessageParams, - TNvSyncConversationParams, - TSendMessageParams, - TSyncConversationParams, -} from "../types"; - -/** - * Linked API Account API client for LinkedIn automation and data retrieval. - * - * The Account API allows you to control LinkedIn accounts and execute various actions - * like messaging, networking, searching, and data retrieval through workflow-based automation. - * - * @see {@link https://linkedapi.io/docs/account-api/ Account API Documentation} - * - * @example - * ```typescript - * const linkedapi = new LinkedApi({ - * accountApiToken: "your-account-api-token", - * identificationToken: "your-identification-token" - * }); - * - * // Use various API methods - * const personData = await linkedapi.account.fetchPerson({ personUrl: "..." }); - * const searchResults = await linkedapi.account.searchPeople({ term: "developer" }); - * ``` - */ -export class AccountApi { - /** - * Creates a new AccountApi instance. - * - * @param workflowExecutor - The workflow executor for managing LinkedIn automation workflows - * @param httpClient - HTTP client configured with authentication headers - */ - constructor( - private workflowExecutor: WorkflowExecutor, - private readonly httpClient: HttpClient, - ) {} - - /** - * Execute a custom workflow with raw workflow definition. - * - * This method allows you to execute any custom workflow by providing a raw workflow definition. - * Use this for advanced use cases when you need to create custom action sequences. - * - * @param params - The workflow definition containing action types and parameters - * @returns Promise resolving to a WorkflowHandler for managing the workflow execution - * - * @see {@link https://linkedapi.io/docs/account-api/ Account API Documentation} - * @see {@link https://linkedapi.io/docs/account-api/executing-workflows/ Executing Workflows Documentation} - * @see {@link https://linkedapi.io/docs/account-api/building-workflows/ Building Workflows Documentation} - * @see {@link https://linkedapi.io/docs/account-api/actions-overview/ Actions Overview Documentation} - * - * @example - * ```typescript - * const workflow = await linkedapi.account.executeCustomWorkflow({ - * actionType: "st.searchCompanies", - * term: "Tech Inc", - * filter: { - * sizes: ["51-200", "2001-500"], - * locations: ["San Francisco", "New York"], - * industries: ["Software Development", "Robotics Engineering"], - * annualRevenue: { - * min: "0", - * max: "2.5" - * } - * }, - * then: { - * actionType: "st.doForCompanies", - * then: { - * actionType: "st.openCompanyPage", - * basicInfo: true - * } - * } - * }); - * - * const result = await workflow.result(); - * ``` - */ - public async executeCustomWorkflow( - params: TWorkflowDefinition, - ): Promise { - const workflow = await this.workflowExecutor.startWorkflow(params); - return new WorkflowHandler(workflow.workflowId, this.workflowExecutor); - } - - /** - * Get the result of a workflow by its ID. - * - * This method retrieves the result of a previously started workflow using its workflow ID. - * Useful for checking workflow status and retrieving results asynchronously. - * - * @param workflowId - The unique identifier of the workflow - * @returns Promise resolving to the workflow response containing completion data or failure information - * - * @see {@link https://linkedapi.io/docs/account-api/ Account API Documentation} - * - * @example - * ```typescript - * const workflowResponse = await linkedapi.account.getWorkflowResult("workflow-id-123"); - * - * if (workflowResponse.completion) { - * console.log("Workflow completed:", workflowResponse.completion.data); - * } else if (workflowResponse.failure) { - * console.error("Workflow failed:", workflowResponse.failure.message); - * } - * ``` - */ - public async getWorkflowResult( - workflowId: string, - ): Promise { - return this.workflowExecutor.getWorkflowResult(workflowId); - } - - /** - * Send a message to a LinkedIn user via standard LinkedIn messaging. - * - * This method sends a direct message to a person on LinkedIn. The recipient must be a connection - * or allow messages from anyone. This uses the standard LinkedIn messaging interface. - * - * @param params - Parameters including the person's URL and message text - * @returns Promise resolving to a WorkflowHandler for the message sending action - * - * @see {@link https://linkedapi.io/docs/account-api/sending-message/ Sending Messages Documentation} - * @see {@link https://linkedapi.io/docs/account-api/action-st-send-message/ st.sendMessage Action Documentation} - * - * @example - * ```typescript - * const messageWorkflow = await linkedapi.account.sendMessage({ - * personUrl: "https://www.linkedin.com/in/john-doe", - * text: "Hi John! I saw your recent post about AI and would love to discuss further." - * }); - * - * await messageWorkflow.result(); - * console.log("Message sent successfully"); - * ``` - */ - public async sendMessage( - params: TSendMessageParams, - ): Promise> { - const sendMessageMapper = new VoidWorkflowMapper( - "st.sendMessage", - ); - const workflowDefinition = sendMessageMapper.mapRequest(params); - const { workflowId } = - await this.workflowExecutor.startWorkflow(workflowDefinition); - return new WorkflowHandler( - workflowId, - this.workflowExecutor, - sendMessageMapper, - ); - } - - /** - * Sync a conversation with a LinkedIn user for standard LinkedIn messaging. - * - * This method synchronizes a conversation with a person, preparing it for future message polling. - * Each conversation must be synced once before you can poll it for messages. This is a time-consuming - * process that retrieves the conversation history and prepares it for future updates. - * - * @param params - Parameters including the person's URL - * @returns Promise resolving to a WorkflowHandler for the sync action - * - * @see {@link https://linkedapi.io/docs/account-api/working-with-conversations/ Working with Conversations Documentation} - * @see {@link https://linkedapi.io/docs/account-api/action-st-sync-conversation/ st.syncConversation Action Documentation} - * - * @example - * ```typescript - * const syncWorkflow = await linkedapi.account.syncConversation({ - * personUrl: "https://www.linkedin.com/in/john-doe" - * }); - * - * await syncWorkflow.result(); - * console.log("Conversation synced and ready for polling"); - * ``` - */ - public async syncConversation( - params: TSyncConversationParams, - ): Promise> { - const syncConversationMapper = - new VoidWorkflowMapper("st.syncConversation"); - const workflowDefinition = syncConversationMapper.mapRequest(params); - const { workflowId } = - await this.workflowExecutor.startWorkflow(workflowDefinition); - return new WorkflowHandler( - workflowId, - this.workflowExecutor, - syncConversationMapper, - ); - } - - /** - * Send a message to a LinkedIn user via Sales Navigator. - * - * This method sends a direct message to a person using Sales Navigator's messaging capabilities. - * Sales Navigator allows messaging people who are not connections and provides enhanced messaging features. - * - * @param params - Parameters including the person's URL, message text, and subject line - * @returns Promise resolving to a WorkflowHandler for the message sending action - * - * @see {@link https://linkedapi.io/docs/account-api/sending-message/ Sending Messages Documentation} - * @see {@link https://linkedapi.io/docs/account-api/action-nv-send-message/ nv.sendMessage Action Documentation} - * - * @example - * ```typescript - * const nvMessageWorkflow = await linkedapi.account.salesNavigatorSendMessage({ - * personUrl: "https://www.linkedin.com/in/john-doe", - * text: "Hi John! I'm reaching out regarding potential collaboration opportunities.", - * subject: "Partnership Opportunity" - * }); - * - * await nvMessageWorkflow.result(); - * console.log("Sales Navigator message sent successfully"); - * ``` - */ - public async salesNavigatorSendMessage( - params: TNvSendMessageParams, - ): Promise> { - const nvSendMessageMapper = new VoidWorkflowMapper( - "nv.sendMessage", - ); - const workflowDefinition = nvSendMessageMapper.mapRequest(params); - const { workflowId } = - await this.workflowExecutor.startWorkflow(workflowDefinition); - return new WorkflowHandler( - workflowId, - this.workflowExecutor, - nvSendMessageMapper, - ); - } - - /** - * Sync a conversation with a LinkedIn user for Sales Navigator messaging. - * - * This method synchronizes a Sales Navigator conversation with a person, preparing it for future message polling. - * Each conversation must be synced once before you can poll it for messages. This retrieves the conversation - * history from Sales Navigator and prepares it for future updates. - * - * @param params - Parameters including the person's URL - * @returns Promise resolving to a WorkflowHandler for the sync action - * - * @see {@link https://linkedapi.io/docs/account-api/working-with-conversations/ Working with Conversations Documentation} - * @see {@link https://linkedapi.io/docs/account-api/action-nv-sync-conversation/ nv.syncConversation Action Documentation} - * - * @example - * ```typescript - * const nvSyncWorkflow = await linkedapi.account.salesNavigatorSyncConversation({ - * personUrl: "https://www.linkedin.com/in/john-doe" - * }); - * - * await nvSyncWorkflow.result(); - * console.log("Sales Navigator conversation synced and ready for polling"); - * ``` - */ - public async salesNavigatorSyncConversation( - params: TNvSyncConversationParams, - ): Promise> { - const nvSyncConversationMapper = - new VoidWorkflowMapper("nv.syncConversation"); - const workflowDefinition = nvSyncConversationMapper.mapRequest(params); - const { workflowId } = - await this.workflowExecutor.startWorkflow(workflowDefinition); - return new WorkflowHandler( - workflowId, - this.workflowExecutor, - nvSyncConversationMapper, - ); - } - - /** - * Poll multiple conversations to retrieve message history and new messages. - * - * This method retrieves messages from one or more previously synced conversations using direct HTTP requests. - * Unlike syncing, polling is fast and can be done continuously to get real-time message updates. - * You can specify a timestamp to get only messages since that time. - * - * @param conversations - Array of conversation requests specifying person URLs, types, and optional timestamps - * @returns Promise resolving to a response containing conversation data and messages - * - * @see {@link https://linkedapi.io/docs/account-api/working-with-conversations/ Working with Conversations Documentation} - * - * @example - * ```typescript - * // Poll multiple conversations - * const pollResponse = await linkedapi.account.pollConversations([ - * { - * personUrl: "https://www.linkedin.com/in/john-doe", - * type: "st", - * since: "2023-01-01T00:00:00Z" - * }, - * { - * personUrl: "https://www.linkedin.com/in/jane-smith", - * type: "nv" - * } - * ]); - * - * if (pollResponse.success) { - * pollResponse.result?.forEach(conversation => { - * console.log(`Conversation with ${conversation.personUrl}:`); - * console.log(`Messages: ${conversation.messages.length}`); - * - * conversation.messages.forEach(message => { - * console.log(`${message.sender}: ${message.text}`); - * }); - * }); - * } else { - * console.error("Polling failed:", pollResponse.error?.message); - * } - * ``` - */ - public async pollConversations( - conversations: TConversationPollRequest[], - ): Promise { - const response = await this.httpClient.post( - "/account/conversations/poll", - conversations, - ); - - return { - success: response.success, - result: response.result, - error: response.error, - }; - } - - /** - * Retrieve detailed information about a LinkedIn person profile. - * - * This method fetches comprehensive data about a person from their LinkedIn profile, - * including basic information, experience, education, skills, and more based on the specified parameters. - * - * @param params - Parameters specifying the person URL and what data to retrieve - * @returns Promise resolving to a WorkflowHandler containing the person's profile data - * - * @see {@link https://linkedapi.io/docs/account-api/visiting-person-page/ Visiting Person Page Documentation} - * @see {@link https://linkedapi.io/docs/account-api/action-st-open-person-page/ st.openPersonPage Action Documentation} - * @see {@link https://linkedapi.io/docs/account-api/action-st-retrieve-person-experience/ st.retrievePersonExperience Child Action} - * @see {@link https://linkedapi.io/docs/account-api/action-st-retrieve-person-education/ st.retrievePersonEducation Child Action} - * @see {@link https://linkedapi.io/docs/account-api/action-st-retrieve-person-skills/ st.retrievePersonSkills Child Action} - * @see {@link https://linkedapi.io/docs/account-api/action-st-retrieve-person-languages/ st.retrievePersonLanguages Child Action} - * @see {@link https://linkedapi.io/docs/account-api/action-st-retrieve-person-posts/ st.retrievePersonPosts Child Action} - * @see {@link https://linkedapi.io/docs/account-api/action-st-retrieve-person-comments/ st.retrievePersonComments Child Action} - * @see {@link https://linkedapi.io/docs/account-api/action-st-retrieve-person-reactions/ st.retrievePersonReactions Child Action} - * - * @example - * ```typescript - * // Fetch comprehensive person information with type-safe parameters - * const personWorkflow = await linkedapi.account.fetchPerson({ - * personUrl: "https://www.linkedin.com/in/john-doe", - * retrieveExperience: true, - * retrieveEducation: true, - * retrieveSkills: true, - * retrieveLanguages: true, - * retrievePosts: true, - * retrieveComments: true, - * retrieveReactions: true, - * postsRetrievalConfig: { - * limit: 10, - * since: "2024-01-01" - * }, - * commentRetrievalConfig: { - * limit: 5, - * since: "2024-01-01" - * }, - * reactionRetrievalConfig: { - * limit: 3, - * since: "2024-01-01" - * } - * }); - * - * const personData = await personWorkflow.result(); - * console.log("Person name:", personData.name); - * console.log("Headline:", personData.headline); - * console.log("Experience:", personData.experiences); // TypeScript knows this exists - * console.log("Posts:", personData.posts); // TypeScript knows this exists - * ``` - * - * @example - * ```typescript - * // Simple fetch without additional data - no config objects needed - * const basicPersonWorkflow = await linkedapi.account.fetchPerson({ - * personUrl: "https://www.linkedin.com/in/john-doe" - * }); - * - * const basicData = await basicPersonWorkflow.result(); - * console.log("Basic info:", basicData.name, basicData.headline); - * // personData.experiences is undefined (and TypeScript knows this) - * ``` - */ - public async fetchPerson( - params: TFetchPersonParams, - ): Promise>> { - const fetchPersonMapper = new AcFetchPersonMapper(); - const workflowDefinition = fetchPersonMapper.mapRequest(params); - const { workflowId } = - await this.workflowExecutor.startWorkflow(workflowDefinition); - return new WorkflowHandler>( - workflowId, - this.workflowExecutor, - fetchPersonMapper, - ); - } - - /** - * Retrieve person information via Sales Navigator. - * - * This method opens a person's profile page in Sales Navigator and retrieves their information. - * Sales Navigator provides enhanced data and is useful for sales prospecting activities. - * - * @param params - Parameters including the person's hashed URL and data options - * @returns Promise resolving to a WorkflowHandler containing Sales Navigator person data - * - * @see {@link https://linkedapi.io/docs/account-api/visiting-person-page/ Visiting Person Page Documentation} - * @see {@link https://linkedapi.io/docs/account-api/action-nv-open-person-page/ nv.openPersonPage Action Documentation} - * - * @example - * ```typescript - * const nvPersonWorkflow = await linkedapi.account.salesNavigatorFetchPerson({ - * personHashedUrl: "https://www.linkedin.com/in/ABC123", - * }); - * - * const personData = await nvPersonWorkflow.result(); - * console.log("Sales Navigator data:", personData); - * ``` - */ - public async salesNavigatorFetchPerson( - params: TNvOpenPersonPageParams, - ): Promise> { - const nvOpenPersonPageMapper = new AcNvOpenPersonPageMapper(); - const workflowDefinition = nvOpenPersonPageMapper.mapRequest(params); - const { workflowId } = - await this.workflowExecutor.startWorkflow(workflowDefinition); - return new WorkflowHandler( - workflowId, - this.workflowExecutor, - nvOpenPersonPageMapper, - ); - } - - /** - * Retrieve detailed information about a LinkedIn company profile. - * - * This method fetches comprehensive data about a company from their LinkedIn page, - * including basic information, employee data, posts, and more based on the specified parameters. - * - * @param params - Parameters specifying the company URL and what data to retrieve - * @returns Promise resolving to a WorkflowHandler containing the company's profile data - * - * @see {@link https://linkedapi.io/docs/account-api/ Account API Documentation} - * @see {@link https://linkedapi.io/docs/account-api/action-st-open-company-page/ st.openCompanyPage Action Documentation} - * @see {@link https://linkedapi.io/docs/account-api/action-st-retrieve-company-employees/ st.retrieveCompanyEmployees Child Action} - * @see {@link https://linkedapi.io/docs/account-api/action-st-retrieve-company-dms/ st.retrieveCompanyDMs Child Action} - * @see {@link https://linkedapi.io/docs/account-api/action-st-retrieve-company-posts/ st.retrieveCompanyPosts Child Action} - * - * @example - * ```typescript - * // Fetch company information with employees and posts (new simplified syntax) - * const companyWorkflow = await linkedapi.account.fetchCompany({ - * companyUrl: "https://www.linkedin.com/company/microsoft", - * retrieveEmployees: true, - * retrievePosts: true, - * retrieveDms: true, - * employeeRetrievalConfig: { - * limit: 5, - * filter: { - * firstName: 'John', - * lastName: 'Doe', - * position: 'engineer', - * locations: ['United States'], - * industries: ['Software Development', 'Robotics Engineering'], - * schools: ['Stanford University', 'Harvard University'], - * }, - * }, - * postRetrievalConfig: { limit: 10, since: "2024-01-01" }, - * dmRetrievalConfig: { limit: 3 } - * }); - * - * const companyData = await companyWorkflow.result(); - * console.log("Company name:", companyData.name); - * console.log("Employee count:", companyData.employees?.length); - * console.log("Posts:", companyData.posts?.length); - * ``` - */ - public async fetchCompany( - params: TFetchCompanyParams, - ): Promise>> { - const fetchCompanyMapper = new AcFetchCompanyMapper(); - const workflowDefinition = fetchCompanyMapper.mapRequest(params); - const { workflowId } = - await this.workflowExecutor.startWorkflow(workflowDefinition); - return new WorkflowHandler>( - workflowId, - this.workflowExecutor, - fetchCompanyMapper, - ); - } - - /** - * Retrieve company information via Sales Navigator. - * - * This method opens a company's profile page in Sales Navigator and retrieves their information. - * Sales Navigator provides enhanced company data and is useful for B2B sales prospecting. - * - * @param params - Parameters including the company's hashed URL and data options - * @returns Promise resolving to a WorkflowHandler containing Sales Navigator company data - * - * @see {@link https://linkedapi.io/docs/account-api/ Account API Documentation} - * @see {@link https://linkedapi.io/docs/account-api/action-nv-open-company-page/ nv.openCompanyPage Action Documentation} - * @see {@link https://linkedapi.io/docs/account-api/action-nv-retrieve-company-employees/ nv.retrieveCompanyEmployees Child Action} - * @see {@link https://linkedapi.io/docs/account-api/action-nv-retrieve-company-dms/ nv.retrieveCompanyDMs Child Action} - * - * @example - * ```typescript - * // Sales Navigator company fetch (new simplified syntax) - * const nvCompanyWorkflow = await linkedapi.account.salesNavigatorFetchCompany({ - * companyHashedUrl: 'https://www.linkedin.com/sales/company/1035', - * retrieveEmployees: true, - * retrieveDms: true, - * employeeRetrievalConfig: { - * limit: 1, - * filter: { - * positions: ['Manager', 'Engineer'], - * yearsOfExperiences: ['threeToFive', 'sixToTen'], - * industries: ['Software Development', 'Robotics Engineering'], - * schools: ['Stanford University', 'Harvard University'], - * }, - * }, - * dmRetrievalConfig: { - * limit: 2, - * }, - * }); - * - * const companyData = await nvCompanyWorkflow.result(); - * console.log("Company name:", companyData.name); - * console.log("Employees:", companyData.employees?.length); - * console.log("Decision makers:", companyData.dms?.length); - * ``` - */ - public async salesNavigatorFetchCompany< - TParams extends TNvBaseFetchCompanyParams, - >( - params: TNvFetchCompanyParams, - ): Promise>> { - const fetchNvCompanyMapper = new AcFetchNvCompanyMapper(); - const workflowDefinition = fetchNvCompanyMapper.mapRequest(params); - const { workflowId } = - await this.workflowExecutor.startWorkflow(workflowDefinition); - return new WorkflowHandler>( - workflowId, - this.workflowExecutor, - fetchNvCompanyMapper, - ); - } - - /** - * Retrieve detailed information about a LinkedIn post. - * - * This method fetches comprehensive data about a specific LinkedIn post, - * including content, author information, engagement metrics, and comments. - * - * @param params - Parameters specifying the post URL - * @returns Promise resolving to a WorkflowHandler containing the post data - * - * @see {@link https://linkedapi.io/docs/account-api/ Account API Documentation} - * @see {@link https://linkedapi.io/docs/account-api/action-st-open-post/ st.openPost Action Documentation} - * - * @example - * ```typescript - * const postWorkflow = await linkedapi.account.fetchPost({ - * postUrl: "https://www.linkedin.com/posts/john-doe_activity-123456789" - * }); - * - * const postData = await postWorkflow.result(); - * console.log("Post content:", postData.text); - * console.log("Author:", postData.author); - * console.log("Reactions:", postData.reactions); - * ``` - */ - public async fetchPost( - params: TFetchPostParams, - ): Promise> { - const fetchPostMapper = new SimpleWorkflowMapper< - TFetchPostParams, - TFetchPostResult - >({ - actionType: "st.openPost", - defaultParams: { - basicInfo: true, - }, - }); - const workflowDefinition = fetchPostMapper.mapRequest(params); - const { workflowId } = - await this.workflowExecutor.startWorkflow(workflowDefinition); - return new WorkflowHandler( - workflowId, - this.workflowExecutor, - fetchPostMapper, - ); - } - - /** - * Search for companies on LinkedIn using standard search. - * - * This method performs a company search on LinkedIn using the standard search interface. - * You can filter by various criteria like location, industry, company size, and more. - * - * @param params - Search parameters including keywords, filters, and pagination options - * @returns Promise resolving to a WorkflowHandler containing an array of company search results - * - * @see {@link https://linkedapi.io/docs/account-api/ Account API Documentation} - * @see {@link https://linkedapi.io/docs/account-api/action-st-search-companies/ st.searchCompanies Action Documentation} - * - * @example - * ```typescript - * const companySearchWorkflow = await linkedapi.account.searchCompanies({ - * term: "software development", - * filter: { - * locations: ["San Francisco", "New York"], - * industries: ["Technology", "Software"], - * sizes: ["51-200", "201-500"] - * }, - * limit: 25 - * }); - * - * const companies = await companySearchWorkflow.result(); - * console.log("Found companies:", companies.length); - * ``` - */ - public async searchCompanies( - params: TSearchCompanyParams, - ): Promise> { - const searchCompaniesMapper = new AcSearchCompaniesMapper(); - const workflowDefinition = searchCompaniesMapper.mapRequest(params); - const { workflowId } = - await this.workflowExecutor.startWorkflow(workflowDefinition); - return new WorkflowHandler( - workflowId, - this.workflowExecutor, - searchCompaniesMapper, - ); - } - - /** - * Search for companies on LinkedIn using Sales Navigator. - * - * This method performs a company search using Sales Navigator's advanced search capabilities. - * Sales Navigator provides more detailed filtering options and enhanced company data. - * - * @param params - Sales Navigator search parameters with advanced filtering options - * @returns Promise resolving to a WorkflowHandler containing an array of Sales Navigator company results - * - * @see {@link https://linkedapi.io/docs/account-api/ Account API Documentation} - * @see {@link https://linkedapi.io/docs/account-api/action-nv-search-companies/ nv.searchCompanies Action Documentation} - * - * @example - * ```typescript - * const nvCompanySearchWorkflow = await linkedapi.account.salesNavigatorSearchCompanies({ - * term: "fintech startup", - * filter: { - * locations: ["United States"], - * industries: ["Financial Services"], - * sizes: ["11-50"], - * annualRevenue: { - * min: "0", - * max: "2.5" - * } - * }, - * limit: 50 - * }); - * - * const companies = await nvCompanySearchWorkflow.result(); - * console.log("Sales Navigator companies:", companies.length); - * ``` - */ - public async salesNavigatorSearchCompanies( - params: TNvSearchCompanyParams, - ): Promise> { - const salesNavigatorSearchCompaniesMapper = - new AcSalesNavigatorSearchCompaniesMapper(); - const workflowDefinition = - salesNavigatorSearchCompaniesMapper.mapRequest(params); - const { workflowId } = - await this.workflowExecutor.startWorkflow(workflowDefinition); - return new WorkflowHandler( - workflowId, - this.workflowExecutor, - salesNavigatorSearchCompaniesMapper, - ); - } - - /** - * Search for people on LinkedIn using standard search. - * - * This method performs a people search on LinkedIn using the standard search interface. - * You can filter by keywords, location, current company, past company, industry, and more. - * - * @param params - Search parameters including keywords, filters, and pagination options - * @returns Promise resolving to a WorkflowHandler containing an array of people search results - * - * @see {@link https://linkedapi.io/docs/account-api/ Account API Documentation} - * @see {@link https://linkedapi.io/docs/account-api/action-st-search-people/ st.searchPeople Action Documentation} - * - * @example - * ```typescript - * const peopleSearchWorkflow = await linkedapi.account.searchPeople({ - * term: "software engineer React", - * filter: { - * locations: ["San Francisco Bay Area"], - * currentCompanies: ["Google", "Facebook", "Apple"], - * industries: ["Technology"] - * }, - * limit: 50 - * }); - * - * const people = await peopleSearchWorkflow.result(); - * console.log("Found professionals:", people.length); - * ``` - */ - public async searchPeople( - params: TSearchPeopleParams, - ): Promise> { - const searchPeopleMapper = new AcSearchPeopleMapper(); - const workflowDefinition = searchPeopleMapper.mapRequest(params); - const { workflowId } = - await this.workflowExecutor.startWorkflow(workflowDefinition); - return new WorkflowHandler( - workflowId, - this.workflowExecutor, - searchPeopleMapper, - ); - } - - /** - * Search for people on LinkedIn using Sales Navigator. - * - * This method performs a people search using Sales Navigator's advanced search capabilities. - * Sales Navigator provides more sophisticated filtering options and enhanced prospect data. - * - * @param params - Sales Navigator search parameters with advanced filtering options - * @returns Promise resolving to a WorkflowHandler containing an array of Sales Navigator people results - * - * @see {@link https://linkedapi.io/docs/account-api/ Account API Documentation} - * @see {@link https://linkedapi.io/docs/account-api/action-nv-search-people/ nv.searchPeople Action Documentation} - * - * @example - * ```typescript - * const nvPeopleSearchWorkflow = await linkedapi.account.salesNavigatorSearchPeople({ - * term: "VP Marketing B2B SaaS", - * filter: { - * locations: ["United States"], - * currentCompanies: ["Salesforce", "HubSpot"], - * position: "VP" - * }, - * limit: 25 - * }); - * - * const prospects = await nvPeopleSearchWorkflow.result(); - * console.log("Sales Navigator prospects:", prospects.length); - * ``` - */ - public async salesNavigatorSearchPeople( - params: TNvSearchPeopleParams, - ): Promise> { - const salesNavigatorSearchPeopleMapper = - new AcSalesNavigatorSearchPeopleMapper(); - const workflowDefinition = - salesNavigatorSearchPeopleMapper.mapRequest(params); - const { workflowId } = - await this.workflowExecutor.startWorkflow(workflowDefinition); - return new WorkflowHandler( - workflowId, - this.workflowExecutor, - salesNavigatorSearchPeopleMapper, - ); - } - - /** - * Send a connection request to a LinkedIn user. - * - * This method sends a connection request to the specified person with an optional personalized message. - * The request will appear in the recipient's connection requests section. - * - * @param params - Parameters including the person's URL and optional connection message - * @returns Promise resolving to a WorkflowHandler for the connection request action - * - * @see {@link https://linkedapi.io/docs/account-api/working-with-connection-requests/ Working with Connection Requests Documentation} - * @see {@link https://linkedapi.io/docs/account-api/action-st-send-connection-request/ st.sendConnectionRequest Action Documentation} - * - * @example - * ```typescript - * const connectionWorkflow = await linkedapi.account.sendConnectionRequest({ - * personUrl: "https://www.linkedin.com/in/john-doe", - * note: "Hi John, I'd love to connect and discuss opportunities in tech!" - * }); - * - * await connectionWorkflow.result(); - * console.log("Connection request sent successfully"); - * ``` - */ - public async sendConnectionRequest( - params: TSendConnectionRequestParams, - ): Promise> { - const sendConnectionRequestMapper = - new VoidWorkflowMapper( - "st.sendConnectionRequest", - ); - const workflowDefinition = sendConnectionRequestMapper.mapRequest(params); - const { workflowId } = - await this.workflowExecutor.startWorkflow(workflowDefinition); - return new WorkflowHandler( - workflowId, - this.workflowExecutor, - sendConnectionRequestMapper, - ); - } - - /** - * Check the connection status with a specific LinkedIn user. - * - * This method checks whether you are connected with a person, have a pending request, - * or have no connection with them. - * - * @param params - Parameters including the person's URL - * @returns Promise resolving to a WorkflowHandler containing the connection status result - * - * @see {@link https://linkedapi.io/docs/account-api/checking-connection-status/ Checking Connection Status Documentation} - * @see {@link https://linkedapi.io/docs/account-api/action-st-check-connection-status/ st.checkConnectionStatus Action Documentation} - * - * @example - * ```typescript - * const statusWorkflow = await linkedapi.account.checkConnectionStatus({ - * personUrl: "https://www.linkedin.com/in/john-doe" - * }); - * - * const status = await statusWorkflow.result(); - * console.log("Connection status:", status.connectionStatus); - * ``` - */ - public async checkConnectionStatus( - params: TCheckConnectionStatusParams, - ): Promise> { - const checkConnectionStatusMapper = new SimpleWorkflowMapper< - TCheckConnectionStatusParams, - TCheckConnectionStatusResult - >({ - actionType: "st.checkConnectionStatus", - }); - const workflowDefinition = checkConnectionStatusMapper.mapRequest(params); - const { workflowId } = - await this.workflowExecutor.startWorkflow(workflowDefinition); - return new WorkflowHandler( - workflowId, - this.workflowExecutor, - checkConnectionStatusMapper, - ); - } - - /** - * Withdraw a previously sent connection request. - * - * This method withdraws a connection request that was previously sent to a person. - * The request will be removed from their pending connection requests. - * - * @param params - Parameters including the person's URL - * @returns Promise resolving to a WorkflowHandler for the withdrawal action - * - * @see {@link https://linkedapi.io/docs/account-api/working-with-connection-requests/ Working with Connection Requests Documentation} - * @see {@link https://linkedapi.io/docs/account-api/action-st-withdraw-connection-request/ st.withdrawConnectionRequest Action Documentation} - * - * @example - * ```typescript - * const withdrawWorkflow = await linkedapi.account.withdrawConnectionRequest({ - * personUrl: "https://www.linkedin.com/in/john-doe" - * }); - * - * await withdrawWorkflow.result(); - * console.log("Connection request withdrawn successfully"); - * ``` - */ - public async withdrawConnectionRequest( - params: TWithdrawConnectionRequestParams, - ): Promise> { - const withdrawConnectionRequestMapper = - new VoidWorkflowMapper( - "st.withdrawConnectionRequest", - ); - const workflowDefinition = - withdrawConnectionRequestMapper.mapRequest(params); - const { workflowId } = - await this.workflowExecutor.startWorkflow(workflowDefinition); - return new WorkflowHandler( - workflowId, - this.workflowExecutor, - withdrawConnectionRequestMapper, - ); - } - - /** - * Retrieve all pending connection requests you have received. - * - * This method fetches a list of all pending connection requests that others have sent to you. - * You can optionally filter the results by label. - * - * @returns Promise resolving to a WorkflowHandler containing an array of pending requests - * - * @see {@link https://linkedapi.io/docs/account-api/working-with-connection-requests/ Working with Connection Requests Documentation} - * @see {@link https://linkedapi.io/docs/account-api/action-st-retrieve-pending-requests/ st.retrievePendingRequests Action Documentation} - * - * @example - * ```typescript - * const pendingWorkflow = await linkedapi.account.retrievePendingRequests(); - * - * const pendingRequests = await pendingWorkflow.result(); - * console.log("Pending requests:", pendingRequests.length); - * - * pendingRequests.forEach(request => { - * console.log(`${request.name}: ${request.headline}`); - * console.log(`Profile: ${request.publicUrl}`); - * }); - * ``` - */ - public async retrievePendingRequests(): Promise< - WorkflowHandler - > { - const retrievePendingRequestsMapper = new AcRetrievePendingRequestsMapper(); - const workflowDefinition = retrievePendingRequestsMapper.mapRequest({}); - const { workflowId } = - await this.workflowExecutor.startWorkflow(workflowDefinition); - return new WorkflowHandler( - workflowId, - this.workflowExecutor, - retrievePendingRequestsMapper, - ); - } - - /** - * Retrieve your LinkedIn connections with optional filtering. - * - * This method fetches a list of your LinkedIn connections. You can filter by various criteria - * like name, position, location, industry, company, and school. - * - * @param params - Parameters including optional filters and pagination options - * @returns Promise resolving to a WorkflowHandler containing an array of connections - * - * @see {@link https://linkedapi.io/docs/account-api/managing-existing-connections/ Managing Existing Connections Documentation} - * @see {@link https://linkedapi.io/docs/account-api/action-st-retrieve-connections/ st.retrieveConnections Action Documentation} - * - * @example - * ```typescript - * const connectionsWorkflow = await linkedapi.account.retrieveConnections({ - * filter: { - * firstName: "John", - * industries: ["Technology", "Software"], - * locations: ["San Francisco Bay Area"], - * currentCompanies: ["Google", "Microsoft"] - * }, - * limit: 50 - * }); - * - * const connections = await connectionsWorkflow.result(); - * console.log("Filtered connections:", connections.length); - * ``` - */ - public async retrieveConnections( - params: TRetrieveConnectionsParams = {}, - ): Promise> { - const retrieveConnectionsMapper = new AcRetrieveConnectionsMapper(); - const workflowDefinition = retrieveConnectionsMapper.mapRequest(params); - const { workflowId } = - await this.workflowExecutor.startWorkflow(workflowDefinition); - return new WorkflowHandler( - workflowId, - this.workflowExecutor, - retrieveConnectionsMapper, - ); - } - - /** - * Remove an existing connection from your LinkedIn network. - * - * This method removes a connection from your LinkedIn network. The person will no longer - * be in your connections list and you will lose the connection relationship. - * - * @param params - Parameters including the person's URL - * @returns Promise resolving to a WorkflowHandler for the removal action - * - * @see {@link https://linkedapi.io/docs/account-api/managing-existing-connections/ Managing Existing Connections Documentation} - * @see {@link https://linkedapi.io/docs/account-api/action-st-remove-connection/ st.removeConnection Action Documentation} - * - * @example - * ```typescript - * const removeWorkflow = await linkedapi.account.removeConnection({ - * personUrl: "https://www.linkedin.com/in/john-doe" - * }); - * - * await removeWorkflow.result(); - * console.log("Connection removed successfully"); - * ``` - */ - public async removeConnection( - params: TRemoveConnectionParams, - ): Promise> { - const removeConnectionMapper = - new VoidWorkflowMapper("st.removeConnection"); - const workflowDefinition = removeConnectionMapper.mapRequest(params); - const { workflowId } = - await this.workflowExecutor.startWorkflow(workflowDefinition); - return new WorkflowHandler( - workflowId, - this.workflowExecutor, - removeConnectionMapper, - ); - } - - /** - * React to a LinkedIn post with an emoji reaction. - * - * This method adds a reaction (like, love, celebrate, support, funny, insightful) to a LinkedIn post. - * You can only have one reaction per post, and adding a new reaction will replace any existing one. - * - * @param params - Parameters including the post URL and reaction type - * @returns Promise resolving to a WorkflowHandler for the reaction action - * - * @see {@link https://linkedapi.io/docs/account-api/reacting-and-commenting/ Reacting and Commenting Documentation} - * @see {@link https://linkedapi.io/docs/account-api/action-st-react-to-post/ st.reactToPost Action Documentation} - * - * @example - * ```typescript - * const reactionWorkflow = await linkedapi.account.reactToPost({ - * postUrl: "https://www.linkedin.com/posts/john-doe_activity-123456789", - * type: "like" - * }); - * - * await reactionWorkflow.result(); - * console.log("Post reaction added successfully"); - * ``` - */ - public async reactToPost( - params: TReactToPostParams, - ): Promise> { - const reactToPostMapper = new VoidWorkflowMapper( - "st.reactToPost", - ); - const workflowDefinition = reactToPostMapper.mapRequest(params); - const { workflowId } = - await this.workflowExecutor.startWorkflow(workflowDefinition); - return new WorkflowHandler( - workflowId, - this.workflowExecutor, - reactToPostMapper, - ); - } - - /** - * Comment on a LinkedIn post. - * - * This method adds a text comment to a LinkedIn post. The comment will be visible to other users - * and can help increase engagement with the post. - * - * @param params - Parameters including the post URL and comment text - * @returns Promise resolving to a WorkflowHandler for the comment action - * - * @see {@link https://linkedapi.io/docs/account-api/reacting-and-commenting/ Reacting and Commenting Documentation} - * @see {@link https://linkedapi.io/docs/account-api/action-st-comment-on-post/ st.commentOnPost Action Documentation} - * - * @example - * ```typescript - * const commentWorkflow = await linkedapi.account.commentOnPost({ - * postUrl: "https://www.linkedin.com/posts/john-doe_activity-123456789", - * text: "Great insights! Thanks for sharing this valuable information." - * }); - * - * await commentWorkflow.result(); - * console.log("Comment posted successfully"); - * ``` - */ - public async commentOnPost( - params: TCommentOnPostParams, - ): Promise> { - const commentOnPostMapper = new VoidWorkflowMapper( - "st.commentOnPost", - ); - const workflowDefinition = commentOnPostMapper.mapRequest(params); - const { workflowId } = - await this.workflowExecutor.startWorkflow(workflowDefinition); - return new WorkflowHandler( - workflowId, - this.workflowExecutor, - commentOnPostMapper, - ); - } - - /** - * Retrieve your LinkedIn Social Selling Index (SSI) score. - * - * This method fetches your current SSI score and rankings. The SSI score measures your social selling - * performance across four key areas: establishing professional brand, finding right people, - * engaging with insights, and building strong relationships. - * - * @returns Promise resolving to a WorkflowHandler containing SSI data - * - * @see {@link https://linkedapi.io/docs/account-api/retrieving-ssi-and-performance/ Retrieving SSI and Performance Documentation} - * @see {@link https://linkedapi.io/docs/account-api/action-st-retrieve-ssi/ st.retrieveSSI Action Documentation} - * - * @example - * ```typescript - * const ssiWorkflow = await linkedapi.account.retrieveSSI(); - * - * const ssiData = await ssiWorkflow.result(); - * console.log("SSI Score:", ssiData.ssi); - * console.log("Industry Ranking:", ssiData.industryTop); - * console.log("Network Ranking:", ssiData.networkTop); - * ``` - */ - public async retrieveSSI(): Promise> { - const retrieveSSIMapper = new SimpleWorkflowMapper< - TBaseActionParams, - TRetrieveSSIResult - >({ - actionType: "st.retrieveSSI", - }); - const workflowDefinition = retrieveSSIMapper.mapRequest({}); - const { workflowId } = - await this.workflowExecutor.startWorkflow(workflowDefinition); - return new WorkflowHandler( - workflowId, - this.workflowExecutor, - retrieveSSIMapper, - ); - } - - /** - * Retrieve your LinkedIn performance and analytics data. - * - * This method fetches your LinkedIn performance metrics including profile views, - * search appearances, post impressions, and other engagement statistics. - * - * @returns Promise resolving to a WorkflowHandler containing performance data - * - * @see {@link https://linkedapi.io/docs/account-api/retrieving-ssi-and-performance/ Retrieving SSI and Performance Documentation} - * @see {@link https://linkedapi.io/docs/account-api/action-st-retrieve-performance/ st.retrievePerformance Action Documentation} - * - * @example - * ```typescript - * const performanceWorkflow = await linkedapi.account.retrievePerformance(); - * - * const performanceData = await performanceWorkflow.result(); - * console.log("Profile views:", performanceData.profileViews); - * console.log("Search appearances:", performanceData.searchAppearances); - * console.log("Post impressions:", performanceData.postImpressions); - * ``` - */ - public async retrievePerformance(): Promise< - WorkflowHandler - > { - const retrievePerformanceMapper = new SimpleWorkflowMapper< - TBaseActionParams, - TRetrievePerformanceResult - >({ - actionType: "st.retrievePerformance", - }); - const workflowDefinition = retrievePerformanceMapper.mapRequest({}); - const { workflowId } = - await this.workflowExecutor.startWorkflow(workflowDefinition); - return new WorkflowHandler( - workflowId, - this.workflowExecutor, - retrievePerformanceMapper, - ); - } - - /** - * Retrieve Account API usage statistics for a specific time period. - * - * This method fetches statistics about all actions executed during the specified period. - * Use this information to monitor your LinkedIn automation usage and stay within limits. - * The difference between start and end timestamps must not exceed 30 days. - * - * @param params - Parameters including start and end timestamps (ISO format) - * @returns Promise resolving to API usage statistics response - * - * @see {@link https://linkedapi.io/docs/account-api/api-usage-statistics/ API Usage Statistics Documentation} - * - * @example - * ```typescript - * // Get usage statistics for the last 7 days - * const endDate = new Date(); - * const startDate = new Date(endDate.getTime() - 7 * 24 * 60 * 60 * 1000); - * - * const statsResponse = await linkedapi.account.getApiUsageStats({ - * start: startDate.toISOString(), - * end: endDate.toISOString() - * }); - * - * if (statsResponse.success) { - * console.log("Total actions executed:", statsResponse.result?.length); - * - * statsResponse.result?.forEach(action => { - * console.log(`${action.actionType}: ${action.success ? 'SUCCESS' : 'FAILED'} at ${action.time}`); - * }); - * } else { - * console.error("Failed to retrieve stats:", statsResponse.error?.message); - * } - * ``` - */ - public async getApiUsageStats( - params: TApiUsageStatsParams, - ): Promise { - const queryParams = new URLSearchParams({ - start: params.start, - end: params.end, - }); - - const response = await this.httpClient.get( - `/account/stats/actions?${queryParams.toString()}`, - ); - - return { - success: response.success, - result: response.result, - error: response.error, - }; - } -} diff --git a/src/core/workflow-handler.ts b/src/core/workflow-handler.ts index 268887c..b38c639 100644 --- a/src/core/workflow-handler.ts +++ b/src/core/workflow-handler.ts @@ -1,5 +1,5 @@ import type { TBaseActionParams } from "../types/params"; -import type { BaseMapper } from "./base-mapper.abstract"; +import type { BaseMapper } from "../mappers/base-mapper.abstract"; import type { TWorkflowResponse } from "../types/workflows"; import type { WaitForCompletionOptions, diff --git a/src/index.ts b/src/index.ts index 4589dd6..894c649 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,4 +1,3 @@ -import { AccountApi } from "./account-api/account-api"; import type { TLinkedApiConfig } from "./types/config"; import { LinkedApiError, LinkedApiWorkflowError } from "./types/errors"; import type { TWorkflowDefinition, TWorkflowResponse } from "./types/workflows"; @@ -6,6 +5,66 @@ import type { TLinkedApiResponse } from "./types/responses"; import { HttpClient } from "./core/http-client"; import { WorkflowExecutor } from "./core/workflow-executor"; import { WorkflowHandler } from "./core/workflow-handler"; +import { + AcFetchCompanyMapper, + AcFetchNvCompanyMapper, + AcFetchPersonMapper, + AcNvOpenPersonPageMapper, + AcRetrieveConnectionsMapper, + AcRetrievePendingRequestsMapper, + AcSalesNavigatorSearchCompaniesMapper, + AcSalesNavigatorSearchPeopleMapper, + AcSearchCompaniesMapper, + AcSearchPeopleMapper, + SimpleWorkflowMapper, + VoidWorkflowMapper, +} from "./mappers"; +import { + TSendMessageParams, + TSyncConversationParams, + TNvSendMessageParams, + TNvSyncConversationParams, + TConversationPollRequest, + TConversationPollResponse, + TConversationPollResult, + TBaseFetchPersonParams, + TFetchPersonParams, + TFetchPersonResult, + TNvOpenPersonPageParams, + TNvOpenPersonPageResult, + TBaseFetchCompanyParams, + TFetchCompanyParams, + TFetchCompanyResult, + TNvBaseFetchCompanyParams, + TNvFetchCompanyParams, + TNvFetchCompanyResult, + TFetchPostParams, + TFetchPostResult, + TSearchCompanyParams, + TSearchCompanyResult, + TNvSearchCompanyParams, + TNvSearchCompanyResult, + TSearchPeopleParams, + TSearchPeopleResult, + TNvSearchPeopleParams, + TNvSearchPeopleResult, + TSendConnectionRequestParams, + TCheckConnectionStatusParams, + TCheckConnectionStatusResult, + TWithdrawConnectionRequestParams, + TRetrievePendingRequestsResult, + TRetrieveConnectionsParams, + TRetrieveConnectionsResult, + TRemoveConnectionParams, + TReactToPostParams, + TCommentOnPostParams, + TRetrieveSSIResult, + TBaseActionParams, + TRetrievePerformanceResult, + TApiUsageStatsParams, + TApiUsageStatsResponse, + TApiUsageAction, +} from "./types"; /** * LinkedApi - Official TypeScript SDK for Linked API @@ -20,13 +79,13 @@ import { WorkflowHandler } from "./core/workflow-handler"; * import LinkedApi from "linkedapi-node"; * * // Initialize with Linked API tokens for LinkedIn automation - * const linkedapi = LinkedApi.init({ - * accountApiToken: "your-account-api-token", + * const linkedapi = new LinkedApi({ + * apiToken: "your-api-token", * identificationToken: "your-identification-token" * }); * * // Use Linked API features with full type safety - * const personWorkflow = await linkedapi.account.fetchPerson({ + * const personWorkflow = await linkedapi.fetchPerson({ * personUrl: "https://www.linkedin.com/in/john-doe", * retrieveExperience: true, * retrievePosts: true, @@ -34,68 +93,1220 @@ import { WorkflowHandler } from "./core/workflow-handler"; * }); * const personData = await personWorkflow.result(); * ``` - * - * @example - * ```typescript - * // Initialize with both APIs for full functionality - * const linkedapi = LinkedApi.init({ - * accountApiToken: "your-account-api-token", - * identificationToken: "your-identification-token", - * }); - * ``` - * - * @example - * ```typescript - * // Error handling - * try { - * const result = await linkedapi.account.fetchPerson({ personUrl: "..." }); - * } catch (error) { - * if (error instanceof LinkedApi.LinkedApiError) { - * console.error("API Error:", error.message); - * } - * } - * ``` */ class LinkedApi { + private readonly httpClient: HttpClient; + private readonly workflowExecutor: WorkflowExecutor; /** * Initialize LinkedApi client with your API tokens. * * @param config - Configuration object containing API tokens and optional settings - * @returns LinkedApi instance with access to account and data APIs + * @returns LinkedApi instance with access to LinkedIn automation features */ - public readonly account: AccountApi; constructor(config: TLinkedApiConfig) { - const workflowTimeout = config.workflowTimeout ?? 24 * 60 * 60 * 1000; - - const accountApiClient = new HttpClient({ + this.httpClient = new HttpClient({ headers: { "account-api-token": config.apiToken, "identification-token": config.identificationToken, }, }); - const accountApiExecutor = new WorkflowExecutor({ - httpClient: accountApiClient, + this.workflowExecutor = new WorkflowExecutor({ + httpClient: this.httpClient, apiPath: "/account/workflows", - workflowTimeout: workflowTimeout, + workflowTimeout: config.workflowTimeout ?? 24 * 60 * 60 * 1000, + }); + } + + /** + * Execute a custom workflow with raw workflow definition. + * + * This method allows you to execute any custom workflow by providing a raw workflow definition. + * Use this for advanced use cases when you need to create custom action sequences. + * + * @param params - The workflow definition containing action types and parameters + * @returns Promise resolving to a WorkflowHandler for managing the workflow execution + * + * @see {@link https://linkedapi.io/docs/account-api/ Account API Documentation} + * @see {@link https://linkedapi.io/docs/account-api/executing-workflows/ Executing Workflows Documentation} + * @see {@link https://linkedapi.io/docs/account-api/building-workflows/ Building Workflows Documentation} + * @see {@link https://linkedapi.io/docs/account-api/actions-overview/ Actions Overview Documentation} + * + * @example + * ```typescript + * const workflow = await linkedapi.executeCustomWorkflow({ + * actionType: "st.searchCompanies", + * term: "Tech Inc", + * filter: { + * sizes: ["51-200", "2001-500"], + * locations: ["San Francisco", "New York"], + * industries: ["Software Development", "Robotics Engineering"], + * annualRevenue: { + * min: "0", + * max: "2.5" + * } + * }, + * then: { + * actionType: "st.doForCompanies", + * then: { + * actionType: "st.openCompanyPage", + * basicInfo: true + * } + * } + * }); + * + * const result = await workflow.result(); + * ``` + */ + public async executeCustomWorkflow( + params: TWorkflowDefinition, + ): Promise { + const workflow = await this.workflowExecutor.startWorkflow(params); + return new WorkflowHandler(workflow.workflowId, this.workflowExecutor); + } + + /** + * Get the result of a workflow by its ID. + * + * This method retrieves the result of a previously started workflow using its workflow ID. + * Useful for checking workflow status and retrieving results asynchronously. + * + * @param workflowId - The unique identifier of the workflow + * @returns Promise resolving to the workflow response containing completion data or failure information + * + * @see {@link https://linkedapi.io/docs/account-api/ Account API Documentation} + * + * @example + * ```typescript + * const workflowResponse = await linkedapi.getWorkflowResult("workflow-id-123"); + * + * if (workflowResponse.completion) { + * console.log("Workflow completed:", workflowResponse.completion.data); + * } else if (workflowResponse.failure) { + * console.error("Workflow failed:", workflowResponse.failure.message); + * } + * ``` + */ + public async getWorkflowResult( + workflowId: string, + ): Promise { + return this.workflowExecutor.getWorkflowResult(workflowId); + } + + /** + * Send a message to a LinkedIn user via standard LinkedIn messaging. + * + * This method sends a direct message to a person on LinkedIn. The recipient must be a connection + * or allow messages from anyone. This uses the standard LinkedIn messaging interface. + * + * @param params - Parameters including the person's URL and message text + * @returns Promise resolving to a WorkflowHandler for the message sending action + * + * @see {@link https://linkedapi.io/docs/account-api/sending-message/ Sending Messages Documentation} + * @see {@link https://linkedapi.io/docs/account-api/action-st-send-message/ st.sendMessage Action Documentation} + * + * @example + * ```typescript + * const messageWorkflow = await linkedapi.sendMessage({ + * personUrl: "https://www.linkedin.com/in/john-doe", + * text: "Hi John! I saw your recent post about AI and would love to discuss further." + * }); + * + * await messageWorkflow.result(); + * console.log("Message sent successfully"); + * ``` + */ + public async sendMessage( + params: TSendMessageParams, + ): Promise> { + const sendMessageMapper = new VoidWorkflowMapper( + "st.sendMessage", + ); + const workflowDefinition = sendMessageMapper.mapRequest(params); + const { workflowId } = + await this.workflowExecutor.startWorkflow(workflowDefinition); + return new WorkflowHandler( + workflowId, + this.workflowExecutor, + sendMessageMapper, + ); + } + + /** + * Sync a conversation with a LinkedIn user for standard LinkedIn messaging. + * + * This method synchronizes a conversation with a person, preparing it for future message polling. + * Each conversation must be synced once before you can poll it for messages. This is a time-consuming + * process that retrieves the conversation history and prepares it for future updates. + * + * @param params - Parameters including the person's URL + * @returns Promise resolving to a WorkflowHandler for the sync action + * + * @see {@link https://linkedapi.io/docs/account-api/working-with-conversations/ Working with Conversations Documentation} + * @see {@link https://linkedapi.io/docs/account-api/action-st-sync-conversation/ st.syncConversation Action Documentation} + * + * @example + * ```typescript + * const syncWorkflow = await linkedapi.syncConversation({ + * personUrl: "https://www.linkedin.com/in/john-doe" + * }); + * + * await syncWorkflow.result(); + * console.log("Conversation synced and ready for polling"); + * ``` + */ + public async syncConversation( + params: TSyncConversationParams, + ): Promise> { + const syncConversationMapper = + new VoidWorkflowMapper("st.syncConversation"); + const workflowDefinition = syncConversationMapper.mapRequest(params); + const { workflowId } = + await this.workflowExecutor.startWorkflow(workflowDefinition); + return new WorkflowHandler( + workflowId, + this.workflowExecutor, + syncConversationMapper, + ); + } + + /** + * Send a message to a LinkedIn user via Sales Navigator. + * + * This method sends a direct message to a person using Sales Navigator's messaging capabilities. + * Sales Navigator allows messaging people who are not connections and provides enhanced messaging features. + * + * @param params - Parameters including the person's URL, message text, and subject line + * @returns Promise resolving to a WorkflowHandler for the message sending action + * + * @see {@link https://linkedapi.io/docs/account-api/sending-message/ Sending Messages Documentation} + * @see {@link https://linkedapi.io/docs/account-api/action-nv-send-message/ nv.sendMessage Action Documentation} + * + * @example + * ```typescript + * const nvMessageWorkflow = await linkedapi.salesNavigatorSendMessage({ + * personUrl: "https://www.linkedin.com/in/john-doe", + * text: "Hi John! I'm reaching out regarding potential collaboration opportunities.", + * subject: "Partnership Opportunity" + * }); + * + * await nvMessageWorkflow.result(); + * console.log("Sales Navigator message sent successfully"); + * ``` + */ + public async salesNavigatorSendMessage( + params: TNvSendMessageParams, + ): Promise> { + const nvSendMessageMapper = new VoidWorkflowMapper( + "nv.sendMessage", + ); + const workflowDefinition = nvSendMessageMapper.mapRequest(params); + const { workflowId } = + await this.workflowExecutor.startWorkflow(workflowDefinition); + return new WorkflowHandler( + workflowId, + this.workflowExecutor, + nvSendMessageMapper, + ); + } + + /** + * Sync a conversation with a LinkedIn user for Sales Navigator messaging. + * + * This method synchronizes a Sales Navigator conversation with a person, preparing it for future message polling. + * Each conversation must be synced once before you can poll it for messages. This retrieves the conversation + * history from Sales Navigator and prepares it for future updates. + * + * @param params - Parameters including the person's URL + * @returns Promise resolving to a WorkflowHandler for the sync action + * + * @see {@link https://linkedapi.io/docs/account-api/working-with-conversations/ Working with Conversations Documentation} + * @see {@link https://linkedapi.io/docs/account-api/action-nv-sync-conversation/ nv.syncConversation Action Documentation} + * + * @example + * ```typescript + * const nvSyncWorkflow = await linkedapi.salesNavigatorSyncConversation({ + * personUrl: "https://www.linkedin.com/in/john-doe" + * }); + * + * await nvSyncWorkflow.result(); + * console.log("Sales Navigator conversation synced and ready for polling"); + * ``` + */ + public async salesNavigatorSyncConversation( + params: TNvSyncConversationParams, + ): Promise> { + const nvSyncConversationMapper = + new VoidWorkflowMapper("nv.syncConversation"); + const workflowDefinition = nvSyncConversationMapper.mapRequest(params); + const { workflowId } = + await this.workflowExecutor.startWorkflow(workflowDefinition); + return new WorkflowHandler( + workflowId, + this.workflowExecutor, + nvSyncConversationMapper, + ); + } + + /** + * Poll multiple conversations to retrieve message history and new messages. + * + * This method retrieves messages from one or more previously synced conversations using direct HTTP requests. + * Unlike syncing, polling is fast and can be done continuously to get real-time message updates. + * You can specify a timestamp to get only messages since that time. + * + * @param conversations - Array of conversation requests specifying person URLs, types, and optional timestamps + * @returns Promise resolving to a response containing conversation data and messages + * + * @see {@link https://linkedapi.io/docs/account-api/working-with-conversations/ Working with Conversations Documentation} + * + * @example + * ```typescript + * // Poll multiple conversations + * const pollResponse = await linkedapi.pollConversations([ + * { + * personUrl: "https://www.linkedin.com/in/john-doe", + * type: "st", + * since: "2023-01-01T00:00:00Z" + * }, + * { + * personUrl: "https://www.linkedin.com/in/jane-smith", + * type: "nv" + * } + * ]); + * + * if (pollResponse.success) { + * pollResponse.result?.forEach(conversation => { + * console.log(`Conversation with ${conversation.personUrl}:`); + * console.log(`Messages: ${conversation.messages.length}`); + * + * conversation.messages.forEach(message => { + * console.log(`${message.sender}: ${message.text}`); + * }); + * }); + * } else { + * console.error("Polling failed:", pollResponse.error?.message); + * } + * ``` + */ + public async pollConversations( + conversations: TConversationPollRequest[], + ): Promise { + const response = await this.httpClient.post( + "/account/conversations/poll", + conversations, + ); + + return { + success: response.success, + result: response.result, + error: response.error, + }; + } + + /** + * Retrieve detailed information about a LinkedIn person profile. + * + * This method fetches comprehensive data about a person from their LinkedIn profile, + * including basic information, experience, education, skills, and more based on the specified parameters. + * + * @param params - Parameters specifying the person URL and what data to retrieve + * @returns Promise resolving to a WorkflowHandler containing the person's profile data + * + * @see {@link https://linkedapi.io/docs/account-api/visiting-person-page/ Visiting Person Page Documentation} + * @see {@link https://linkedapi.io/docs/account-api/action-st-open-person-page/ st.openPersonPage Action Documentation} + * @see {@link https://linkedapi.io/docs/account-api/action-st-retrieve-person-experience/ st.retrievePersonExperience Child Action} + * @see {@link https://linkedapi.io/docs/account-api/action-st-retrieve-person-education/ st.retrievePersonEducation Child Action} + * @see {@link https://linkedapi.io/docs/account-api/action-st-retrieve-person-skills/ st.retrievePersonSkills Child Action} + * @see {@link https://linkedapi.io/docs/account-api/action-st-retrieve-person-languages/ st.retrievePersonLanguages Child Action} + * @see {@link https://linkedapi.io/docs/account-api/action-st-retrieve-person-posts/ st.retrievePersonPosts Child Action} + * @see {@link https://linkedapi.io/docs/account-api/action-st-retrieve-person-comments/ st.retrievePersonComments Child Action} + * @see {@link https://linkedapi.io/docs/account-api/action-st-retrieve-person-reactions/ st.retrievePersonReactions Child Action} + * + * @example + * ```typescript + * // Fetch comprehensive person information with type-safe parameters + * const personWorkflow = await linkedapi.fetchPerson({ + * personUrl: "https://www.linkedin.com/in/john-doe", + * retrieveExperience: true, + * retrieveEducation: true, + * retrieveSkills: true, + * retrieveLanguages: true, + * retrievePosts: true, + * retrieveComments: true, + * retrieveReactions: true, + * postsRetrievalConfig: { + * limit: 10, + * since: "2024-01-01" + * }, + * commentRetrievalConfig: { + * limit: 5, + * since: "2024-01-01" + * }, + * reactionRetrievalConfig: { + * limit: 3, + * since: "2024-01-01" + * } + * }); + * + * const personData = await personWorkflow.result(); + * console.log("Person name:", personData.name); + * console.log("Headline:", personData.headline); + * console.log("Experience:", personData.experiences); // TypeScript knows this exists + * console.log("Posts:", personData.posts); // TypeScript knows this exists + * ``` + * + * @example + * ```typescript + * // Simple fetch without additional data - no config objects needed + * const basicPersonWorkflow = await linkedapi.fetchPerson({ + * personUrl: "https://www.linkedin.com/in/john-doe" + * }); + * + * const basicData = await basicPersonWorkflow.result(); + * console.log("Basic info:", basicData.name, basicData.headline); + * // personData.experiences is undefined (and TypeScript knows this) + * ``` + */ + public async fetchPerson( + params: TFetchPersonParams, + ): Promise>> { + const fetchPersonMapper = new AcFetchPersonMapper(); + const workflowDefinition = fetchPersonMapper.mapRequest(params); + const { workflowId } = + await this.workflowExecutor.startWorkflow(workflowDefinition); + return new WorkflowHandler>( + workflowId, + this.workflowExecutor, + fetchPersonMapper, + ); + } + + /** + * Retrieve person information via Sales Navigator. + * + * This method opens a person's profile page in Sales Navigator and retrieves their information. + * Sales Navigator provides enhanced data and is useful for sales prospecting activities. + * + * @param params - Parameters including the person's hashed URL and data options + * @returns Promise resolving to a WorkflowHandler containing Sales Navigator person data + * + * @see {@link https://linkedapi.io/docs/account-api/visiting-person-page/ Visiting Person Page Documentation} + * @see {@link https://linkedapi.io/docs/account-api/action-nv-open-person-page/ nv.openPersonPage Action Documentation} + * + * @example + * ```typescript + * const nvPersonWorkflow = await linkedapi.salesNavigatorFetchPerson({ + * personHashedUrl: "https://www.linkedin.com/in/ABC123", + * }); + * + * const personData = await nvPersonWorkflow.result(); + * console.log("Sales Navigator data:", personData); + * ``` + */ + public async salesNavigatorFetchPerson( + params: TNvOpenPersonPageParams, + ): Promise> { + const nvOpenPersonPageMapper = new AcNvOpenPersonPageMapper(); + const workflowDefinition = nvOpenPersonPageMapper.mapRequest(params); + const { workflowId } = + await this.workflowExecutor.startWorkflow(workflowDefinition); + return new WorkflowHandler( + workflowId, + this.workflowExecutor, + nvOpenPersonPageMapper, + ); + } + + /** + * Retrieve detailed information about a LinkedIn company profile. + * + * This method fetches comprehensive data about a company from their LinkedIn page, + * including basic information, employee data, posts, and more based on the specified parameters. + * + * @param params - Parameters specifying the company URL and what data to retrieve + * @returns Promise resolving to a WorkflowHandler containing the company's profile data + * + * @see {@link https://linkedapi.io/docs/account-api/ Account API Documentation} + * @see {@link https://linkedapi.io/docs/account-api/action-st-open-company-page/ st.openCompanyPage Action Documentation} + * @see {@link https://linkedapi.io/docs/account-api/action-st-retrieve-company-employees/ st.retrieveCompanyEmployees Child Action} + * @see {@link https://linkedapi.io/docs/account-api/action-st-retrieve-company-dms/ st.retrieveCompanyDMs Child Action} + * @see {@link https://linkedapi.io/docs/account-api/action-st-retrieve-company-posts/ st.retrieveCompanyPosts Child Action} + * + * @example + * ```typescript + * // Fetch company information with employees and posts (new simplified syntax) + * const companyWorkflow = await linkedapi.fetchCompany({ + * companyUrl: "https://www.linkedin.com/company/microsoft", + * retrieveEmployees: true, + * retrievePosts: true, + * retrieveDms: true, + * employeeRetrievalConfig: { + * limit: 5, + * filter: { + * firstName: 'John', + * lastName: 'Doe', + * position: 'engineer', + * locations: ['United States'], + * industries: ['Software Development', 'Robotics Engineering'], + * schools: ['Stanford University', 'Harvard University'], + * }, + * }, + * postRetrievalConfig: { limit: 10, since: "2024-01-01" }, + * dmRetrievalConfig: { limit: 3 } + * }); + * + * const companyData = await companyWorkflow.result(); + * console.log("Company name:", companyData.name); + * console.log("Employee count:", companyData.employees?.length); + * console.log("Posts:", companyData.posts?.length); + * ``` + */ + public async fetchCompany( + params: TFetchCompanyParams, + ): Promise>> { + const fetchCompanyMapper = new AcFetchCompanyMapper(); + const workflowDefinition = fetchCompanyMapper.mapRequest(params); + const { workflowId } = + await this.workflowExecutor.startWorkflow(workflowDefinition); + return new WorkflowHandler>( + workflowId, + this.workflowExecutor, + fetchCompanyMapper, + ); + } + + /** + * Retrieve company information via Sales Navigator. + * + * This method opens a company's profile page in Sales Navigator and retrieves their information. + * Sales Navigator provides enhanced company data and is useful for B2B sales prospecting. + * + * @param params - Parameters including the company's hashed URL and data options + * @returns Promise resolving to a WorkflowHandler containing Sales Navigator company data + * + * @see {@link https://linkedapi.io/docs/account-api/ Account API Documentation} + * @see {@link https://linkedapi.io/docs/account-api/action-nv-open-company-page/ nv.openCompanyPage Action Documentation} + * @see {@link https://linkedapi.io/docs/account-api/action-nv-retrieve-company-employees/ nv.retrieveCompanyEmployees Child Action} + * @see {@link https://linkedapi.io/docs/account-api/action-nv-retrieve-company-dms/ nv.retrieveCompanyDMs Child Action} + * + * @example + * ```typescript + * // Sales Navigator company fetch (new simplified syntax) + * const nvCompanyWorkflow = await linkedapi.salesNavigatorFetchCompany({ + * companyHashedUrl: 'https://www.linkedin.com/sales/company/1035', + * retrieveEmployees: true, + * retrieveDms: true, + * employeeRetrievalConfig: { + * limit: 1, + * filter: { + * positions: ['Manager', 'Engineer'], + * yearsOfExperiences: ['threeToFive', 'sixToTen'], + * industries: ['Software Development', 'Robotics Engineering'], + * schools: ['Stanford University', 'Harvard University'], + * }, + * }, + * dmRetrievalConfig: { + * limit: 2, + * }, + * }); + * + * const companyData = await nvCompanyWorkflow.result(); + * console.log("Company name:", companyData.name); + * console.log("Employees:", companyData.employees?.length); + * console.log("Decision makers:", companyData.dms?.length); + * ``` + */ + public async salesNavigatorFetchCompany< + TParams extends TNvBaseFetchCompanyParams, + >( + params: TNvFetchCompanyParams, + ): Promise>> { + const fetchNvCompanyMapper = new AcFetchNvCompanyMapper(); + const workflowDefinition = fetchNvCompanyMapper.mapRequest(params); + const { workflowId } = + await this.workflowExecutor.startWorkflow(workflowDefinition); + return new WorkflowHandler>( + workflowId, + this.workflowExecutor, + fetchNvCompanyMapper, + ); + } + + /** + * Retrieve detailed information about a LinkedIn post. + * + * This method fetches comprehensive data about a specific LinkedIn post, + * including content, author information, engagement metrics, and comments. + * + * @param params - Parameters specifying the post URL + * @returns Promise resolving to a WorkflowHandler containing the post data + * + * @see {@link https://linkedapi.io/docs/account-api/ Account API Documentation} + * @see {@link https://linkedapi.io/docs/account-api/action-st-open-post/ st.openPost Action Documentation} + * + * @example + * ```typescript + * const postWorkflow = await linkedapi.fetchPost({ + * postUrl: "https://www.linkedin.com/posts/john-doe_activity-123456789" + * }); + * + * const postData = await postWorkflow.result(); + * console.log("Post content:", postData.text); + * console.log("Author:", postData.author); + * console.log("Reactions:", postData.reactions); + * ``` + */ + public async fetchPost( + params: TFetchPostParams, + ): Promise> { + const fetchPostMapper = new SimpleWorkflowMapper< + TFetchPostParams, + TFetchPostResult + >({ + actionType: "st.openPost", + defaultParams: { + basicInfo: true, + }, + }); + const workflowDefinition = fetchPostMapper.mapRequest(params); + const { workflowId } = + await this.workflowExecutor.startWorkflow(workflowDefinition); + return new WorkflowHandler( + workflowId, + this.workflowExecutor, + fetchPostMapper, + ); + } + + /** + * Search for companies on LinkedIn using standard search. + * + * This method performs a company search on LinkedIn using the standard search interface. + * You can filter by various criteria like location, industry, company size, and more. + * + * @param params - Search parameters including keywords, filters, and pagination options + * @returns Promise resolving to a WorkflowHandler containing an array of company search results + * + * @see {@link https://linkedapi.io/docs/account-api/ Account API Documentation} + * @see {@link https://linkedapi.io/docs/account-api/action-st-search-companies/ st.searchCompanies Action Documentation} + * + * @example + * ```typescript + * const companySearchWorkflow = await linkedapi.searchCompanies({ + * term: "software development", + * filter: { + * locations: ["San Francisco", "New York"], + * industries: ["Technology", "Software"], + * sizes: ["51-200", "201-500"] + * }, + * limit: 25 + * }); + * + * const companies = await companySearchWorkflow.result(); + * console.log("Found companies:", companies.length); + * ``` + */ + public async searchCompanies( + params: TSearchCompanyParams, + ): Promise> { + const searchCompaniesMapper = new AcSearchCompaniesMapper(); + const workflowDefinition = searchCompaniesMapper.mapRequest(params); + const { workflowId } = + await this.workflowExecutor.startWorkflow(workflowDefinition); + return new WorkflowHandler( + workflowId, + this.workflowExecutor, + searchCompaniesMapper, + ); + } + + /** + * Search for companies on LinkedIn using Sales Navigator. + * + * This method performs a company search using Sales Navigator's advanced search capabilities. + * Sales Navigator provides more detailed filtering options and enhanced company data. + * + * @param params - Sales Navigator search parameters with advanced filtering options + * @returns Promise resolving to a WorkflowHandler containing an array of Sales Navigator company results + * + * @see {@link https://linkedapi.io/docs/account-api/ Account API Documentation} + * @see {@link https://linkedapi.io/docs/account-api/action-nv-search-companies/ nv.searchCompanies Action Documentation} + * + * @example + * ```typescript + * const nvCompanySearchWorkflow = await linkedapi.salesNavigatorSearchCompanies({ + * term: "fintech startup", + * filter: { + * locations: ["United States"], + * industries: ["Financial Services"], + * sizes: ["11-50"], + * annualRevenue: { + * min: "0", + * max: "2.5" + * } + * }, + * limit: 50 + * }); + * + * const companies = await nvCompanySearchWorkflow.result(); + * console.log("Sales Navigator companies:", companies.length); + * ``` + */ + public async salesNavigatorSearchCompanies( + params: TNvSearchCompanyParams, + ): Promise> { + const salesNavigatorSearchCompaniesMapper = + new AcSalesNavigatorSearchCompaniesMapper(); + const workflowDefinition = + salesNavigatorSearchCompaniesMapper.mapRequest(params); + const { workflowId } = + await this.workflowExecutor.startWorkflow(workflowDefinition); + return new WorkflowHandler( + workflowId, + this.workflowExecutor, + salesNavigatorSearchCompaniesMapper, + ); + } + + /** + * Search for people on LinkedIn using standard search. + * + * This method performs a people search on LinkedIn using the standard search interface. + * You can filter by keywords, location, current company, past company, industry, and more. + * + * @param params - Search parameters including keywords, filters, and pagination options + * @returns Promise resolving to a WorkflowHandler containing an array of people search results + * + * @see {@link https://linkedapi.io/docs/account-api/ Account API Documentation} + * @see {@link https://linkedapi.io/docs/account-api/action-st-search-people/ st.searchPeople Action Documentation} + * + * @example + * ```typescript + * const peopleSearchWorkflow = await linkedapi.searchPeople({ + * term: "software engineer React", + * filter: { + * locations: ["San Francisco Bay Area"], + * currentCompanies: ["Google", "Facebook", "Apple"], + * industries: ["Technology"] + * }, + * limit: 50 + * }); + * + * const people = await peopleSearchWorkflow.result(); + * console.log("Found professionals:", people.length); + * ``` + */ + public async searchPeople( + params: TSearchPeopleParams, + ): Promise> { + const searchPeopleMapper = new AcSearchPeopleMapper(); + const workflowDefinition = searchPeopleMapper.mapRequest(params); + const { workflowId } = + await this.workflowExecutor.startWorkflow(workflowDefinition); + return new WorkflowHandler( + workflowId, + this.workflowExecutor, + searchPeopleMapper, + ); + } + + /** + * Search for people on LinkedIn using Sales Navigator. + * + * This method performs a people search using Sales Navigator's advanced search capabilities. + * Sales Navigator provides more sophisticated filtering options and enhanced prospect data. + * + * @param params - Sales Navigator search parameters with advanced filtering options + * @returns Promise resolving to a WorkflowHandler containing an array of Sales Navigator people results + * + * @see {@link https://linkedapi.io/docs/account-api/ Account API Documentation} + * @see {@link https://linkedapi.io/docs/account-api/action-nv-search-people/ nv.searchPeople Action Documentation} + * + * @example + * ```typescript + * const nvPeopleSearchWorkflow = await linkedapi.salesNavigatorSearchPeople({ + * term: "VP Marketing B2B SaaS", + * filter: { + * locations: ["United States"], + * currentCompanies: ["Salesforce", "HubSpot"], + * position: "VP" + * }, + * limit: 25 + * }); + * + * const prospects = await nvPeopleSearchWorkflow.result(); + * console.log("Sales Navigator prospects:", prospects.length); + * ``` + */ + public async salesNavigatorSearchPeople( + params: TNvSearchPeopleParams, + ): Promise> { + const salesNavigatorSearchPeopleMapper = + new AcSalesNavigatorSearchPeopleMapper(); + const workflowDefinition = + salesNavigatorSearchPeopleMapper.mapRequest(params); + const { workflowId } = + await this.workflowExecutor.startWorkflow(workflowDefinition); + return new WorkflowHandler( + workflowId, + this.workflowExecutor, + salesNavigatorSearchPeopleMapper, + ); + } + + /** + * Send a connection request to a LinkedIn user. + * + * This method sends a connection request to the specified person with an optional personalized message. + * The request will appear in the recipient's connection requests section. + * + * @param params - Parameters including the person's URL and optional connection message + * @returns Promise resolving to a WorkflowHandler for the connection request action + * + * @see {@link https://linkedapi.io/docs/account-api/working-with-connection-requests/ Working with Connection Requests Documentation} + * @see {@link https://linkedapi.io/docs/account-api/action-st-send-connection-request/ st.sendConnectionRequest Action Documentation} + * + * @example + * ```typescript + * const connectionWorkflow = await linkedapi.sendConnectionRequest({ + * personUrl: "https://www.linkedin.com/in/john-doe", + * note: "Hi John, I'd love to connect and discuss opportunities in tech!" + * }); + * + * await connectionWorkflow.result(); + * console.log("Connection request sent successfully"); + * ``` + */ + public async sendConnectionRequest( + params: TSendConnectionRequestParams, + ): Promise> { + const sendConnectionRequestMapper = + new VoidWorkflowMapper( + "st.sendConnectionRequest", + ); + const workflowDefinition = sendConnectionRequestMapper.mapRequest(params); + const { workflowId } = + await this.workflowExecutor.startWorkflow(workflowDefinition); + return new WorkflowHandler( + workflowId, + this.workflowExecutor, + sendConnectionRequestMapper, + ); + } + + /** + * Check the connection status with a specific LinkedIn user. + * + * This method checks whether you are connected with a person, have a pending request, + * or have no connection with them. + * + * @param params - Parameters including the person's URL + * @returns Promise resolving to a WorkflowHandler containing the connection status result + * + * @see {@link https://linkedapi.io/docs/account-api/checking-connection-status/ Checking Connection Status Documentation} + * @see {@link https://linkedapi.io/docs/account-api/action-st-check-connection-status/ st.checkConnectionStatus Action Documentation} + * + * @example + * ```typescript + * const statusWorkflow = await linkedapi.checkConnectionStatus({ + * personUrl: "https://www.linkedin.com/in/john-doe" + * }); + * + * const status = await statusWorkflow.result(); + * console.log("Connection status:", status.connectionStatus); + * ``` + */ + public async checkConnectionStatus( + params: TCheckConnectionStatusParams, + ): Promise> { + const checkConnectionStatusMapper = new SimpleWorkflowMapper< + TCheckConnectionStatusParams, + TCheckConnectionStatusResult + >({ + actionType: "st.checkConnectionStatus", + }); + const workflowDefinition = checkConnectionStatusMapper.mapRequest(params); + const { workflowId } = + await this.workflowExecutor.startWorkflow(workflowDefinition); + return new WorkflowHandler( + workflowId, + this.workflowExecutor, + checkConnectionStatusMapper, + ); + } + + /** + * Withdraw a previously sent connection request. + * + * This method withdraws a connection request that was previously sent to a person. + * The request will be removed from their pending connection requests. + * + * @param params - Parameters including the person's URL + * @returns Promise resolving to a WorkflowHandler for the withdrawal action + * + * @see {@link https://linkedapi.io/docs/account-api/working-with-connection-requests/ Working with Connection Requests Documentation} + * @see {@link https://linkedapi.io/docs/account-api/action-st-withdraw-connection-request/ st.withdrawConnectionRequest Action Documentation} + * + * @example + * ```typescript + * const withdrawWorkflow = await linkedapi.withdrawConnectionRequest({ + * personUrl: "https://www.linkedin.com/in/john-doe" + * }); + * + * await withdrawWorkflow.result(); + * console.log("Connection request withdrawn successfully"); + * ``` + */ + public async withdrawConnectionRequest( + params: TWithdrawConnectionRequestParams, + ): Promise> { + const withdrawConnectionRequestMapper = + new VoidWorkflowMapper( + "st.withdrawConnectionRequest", + ); + const workflowDefinition = + withdrawConnectionRequestMapper.mapRequest(params); + const { workflowId } = + await this.workflowExecutor.startWorkflow(workflowDefinition); + return new WorkflowHandler( + workflowId, + this.workflowExecutor, + withdrawConnectionRequestMapper, + ); + } + + /** + * Retrieve all pending connection requests you have received. + * + * This method fetches a list of all pending connection requests that others have sent to you. + * You can optionally filter the results by label. + * + * @returns Promise resolving to a WorkflowHandler containing an array of pending requests + * + * @see {@link https://linkedapi.io/docs/account-api/working-with-connection-requests/ Working with Connection Requests Documentation} + * @see {@link https://linkedapi.io/docs/account-api/action-st-retrieve-pending-requests/ st.retrievePendingRequests Action Documentation} + * + * @example + * ```typescript + * const pendingWorkflow = await linkedapi.retrievePendingRequests(); + * + * const pendingRequests = await pendingWorkflow.result(); + * console.log("Pending requests:", pendingRequests.length); + * + * pendingRequests.forEach(request => { + * console.log(`${request.name}: ${request.headline}`); + * console.log(`Profile: ${request.publicUrl}`); + * }); + * ``` + */ + public async retrievePendingRequests(): Promise< + WorkflowHandler + > { + const retrievePendingRequestsMapper = new AcRetrievePendingRequestsMapper(); + const workflowDefinition = retrievePendingRequestsMapper.mapRequest({}); + const { workflowId } = + await this.workflowExecutor.startWorkflow(workflowDefinition); + return new WorkflowHandler( + workflowId, + this.workflowExecutor, + retrievePendingRequestsMapper, + ); + } + + /** + * Retrieve your LinkedIn connections with optional filtering. + * + * This method fetches a list of your LinkedIn connections. You can filter by various criteria + * like name, position, location, industry, company, and school. + * + * @param params - Parameters including optional filters and pagination options + * @returns Promise resolving to a WorkflowHandler containing an array of connections + * + * @see {@link https://linkedapi.io/docs/account-api/managing-existing-connections/ Managing Existing Connections Documentation} + * @see {@link https://linkedapi.io/docs/account-api/action-st-retrieve-connections/ st.retrieveConnections Action Documentation} + * + * @example + * ```typescript + * const connectionsWorkflow = await linkedapi.retrieveConnections({ + * filter: { + * firstName: "John", + * industries: ["Technology", "Software"], + * locations: ["San Francisco Bay Area"], + * currentCompanies: ["Google", "Microsoft"] + * }, + * limit: 50 + * }); + * + * const connections = await connectionsWorkflow.result(); + * console.log("Filtered connections:", connections.length); + * ``` + */ + public async retrieveConnections( + params: TRetrieveConnectionsParams = {}, + ): Promise> { + const retrieveConnectionsMapper = new AcRetrieveConnectionsMapper(); + const workflowDefinition = retrieveConnectionsMapper.mapRequest(params); + const { workflowId } = + await this.workflowExecutor.startWorkflow(workflowDefinition); + return new WorkflowHandler( + workflowId, + this.workflowExecutor, + retrieveConnectionsMapper, + ); + } + + /** + * Remove an existing connection from your LinkedIn network. + * + * This method removes a connection from your LinkedIn network. The person will no longer + * be in your connections list and you will lose the connection relationship. + * + * @param params - Parameters including the person's URL + * @returns Promise resolving to a WorkflowHandler for the removal action + * + * @see {@link https://linkedapi.io/docs/account-api/managing-existing-connections/ Managing Existing Connections Documentation} + * @see {@link https://linkedapi.io/docs/account-api/action-st-remove-connection/ st.removeConnection Action Documentation} + * + * @example + * ```typescript + * const removeWorkflow = await linkedapi.removeConnection({ + * personUrl: "https://www.linkedin.com/in/john-doe" + * }); + * + * await removeWorkflow.result(); + * console.log("Connection removed successfully"); + * ``` + */ + public async removeConnection( + params: TRemoveConnectionParams, + ): Promise> { + const removeConnectionMapper = + new VoidWorkflowMapper("st.removeConnection"); + const workflowDefinition = removeConnectionMapper.mapRequest(params); + const { workflowId } = + await this.workflowExecutor.startWorkflow(workflowDefinition); + return new WorkflowHandler( + workflowId, + this.workflowExecutor, + removeConnectionMapper, + ); + } + + /** + * React to a LinkedIn post with an emoji reaction. + * + * This method adds a reaction (like, love, celebrate, support, funny, insightful) to a LinkedIn post. + * You can only have one reaction per post, and adding a new reaction will replace any existing one. + * + * @param params - Parameters including the post URL and reaction type + * @returns Promise resolving to a WorkflowHandler for the reaction action + * + * @see {@link https://linkedapi.io/docs/account-api/reacting-and-commenting/ Reacting and Commenting Documentation} + * @see {@link https://linkedapi.io/docs/account-api/action-st-react-to-post/ st.reactToPost Action Documentation} + * + * @example + * ```typescript + * const reactionWorkflow = await linkedapi.reactToPost({ + * postUrl: "https://www.linkedin.com/posts/john-doe_activity-123456789", + * type: "like" + * }); + * + * await reactionWorkflow.result(); + * console.log("Post reaction added successfully"); + * ``` + */ + public async reactToPost( + params: TReactToPostParams, + ): Promise> { + const reactToPostMapper = new VoidWorkflowMapper( + "st.reactToPost", + ); + const workflowDefinition = reactToPostMapper.mapRequest(params); + const { workflowId } = + await this.workflowExecutor.startWorkflow(workflowDefinition); + return new WorkflowHandler( + workflowId, + this.workflowExecutor, + reactToPostMapper, + ); + } + + /** + * Comment on a LinkedIn post. + * + * This method adds a text comment to a LinkedIn post. The comment will be visible to other users + * and can help increase engagement with the post. + * + * @param params - Parameters including the post URL and comment text + * @returns Promise resolving to a WorkflowHandler for the comment action + * + * @see {@link https://linkedapi.io/docs/account-api/reacting-and-commenting/ Reacting and Commenting Documentation} + * @see {@link https://linkedapi.io/docs/account-api/action-st-comment-on-post/ st.commentOnPost Action Documentation} + * + * @example + * ```typescript + * const commentWorkflow = await linkedapi.commentOnPost({ + * postUrl: "https://www.linkedin.com/posts/john-doe_activity-123456789", + * text: "Great insights! Thanks for sharing this valuable information." + * }); + * + * await commentWorkflow.result(); + * console.log("Comment posted successfully"); + * ``` + */ + public async commentOnPost( + params: TCommentOnPostParams, + ): Promise> { + const commentOnPostMapper = new VoidWorkflowMapper( + "st.commentOnPost", + ); + const workflowDefinition = commentOnPostMapper.mapRequest(params); + const { workflowId } = + await this.workflowExecutor.startWorkflow(workflowDefinition); + return new WorkflowHandler( + workflowId, + this.workflowExecutor, + commentOnPostMapper, + ); + } + + /** + * Retrieve your LinkedIn Social Selling Index (SSI) score. + * + * This method fetches your current SSI score and rankings. The SSI score measures your social selling + * performance across four key areas: establishing professional brand, finding right people, + * engaging with insights, and building strong relationships. + * + * @returns Promise resolving to a WorkflowHandler containing SSI data + * + * @see {@link https://linkedapi.io/docs/account-api/retrieving-ssi-and-performance/ Retrieving SSI and Performance Documentation} + * @see {@link https://linkedapi.io/docs/account-api/action-st-retrieve-ssi/ st.retrieveSSI Action Documentation} + * + * @example + * ```typescript + * const ssiWorkflow = await linkedapi.retrieveSSI(); + * + * const ssiData = await ssiWorkflow.result(); + * console.log("SSI Score:", ssiData.ssi); + * console.log("Industry Ranking:", ssiData.industryTop); + * console.log("Network Ranking:", ssiData.networkTop); + * ``` + */ + public async retrieveSSI(): Promise> { + const retrieveSSIMapper = new SimpleWorkflowMapper< + TBaseActionParams, + TRetrieveSSIResult + >({ + actionType: "st.retrieveSSI", }); - this.account = new AccountApi(accountApiExecutor, accountApiClient); + const workflowDefinition = retrieveSSIMapper.mapRequest({}); + const { workflowId } = + await this.workflowExecutor.startWorkflow(workflowDefinition); + return new WorkflowHandler( + workflowId, + this.workflowExecutor, + retrieveSSIMapper, + ); } - // Error classes - static LinkedApiError = LinkedApiError; - static LinkedApiWorkflowError = LinkedApiWorkflowError; + /** + * Retrieve your LinkedIn performance and analytics data. + * + * This method fetches your LinkedIn performance metrics including profile views, + * search appearances, post impressions, and other engagement statistics. + * + * @returns Promise resolving to a WorkflowHandler containing performance data + * + * @see {@link https://linkedapi.io/docs/account-api/retrieving-ssi-and-performance/ Retrieving SSI and Performance Documentation} + * @see {@link https://linkedapi.io/docs/account-api/action-st-retrieve-performance/ st.retrievePerformance Action Documentation} + * + * @example + * ```typescript + * const performanceWorkflow = await linkedapi.retrievePerformance(); + * + * const performanceData = await performanceWorkflow.result(); + * console.log("Profile views:", performanceData.profileViews); + * console.log("Search appearances:", performanceData.searchAppearances); + * console.log("Post impressions:", performanceData.postImpressions); + * ``` + */ + public async retrievePerformance(): Promise< + WorkflowHandler + > { + const retrievePerformanceMapper = new SimpleWorkflowMapper< + TBaseActionParams, + TRetrievePerformanceResult + >({ + actionType: "st.retrievePerformance", + }); + const workflowDefinition = retrievePerformanceMapper.mapRequest({}); + const { workflowId } = + await this.workflowExecutor.startWorkflow(workflowDefinition); + return new WorkflowHandler( + workflowId, + this.workflowExecutor, + retrievePerformanceMapper, + ); + } + + /** + * Retrieve Account API usage statistics for a specific time period. + * + * This method fetches statistics about all actions executed during the specified period. + * Use this information to monitor your LinkedIn automation usage and stay within limits. + * The difference between start and end timestamps must not exceed 30 days. + * + * @param params - Parameters including start and end timestamps (ISO format) + * @returns Promise resolving to API usage statistics response + * + * @see {@link https://linkedapi.io/docs/account-api/api-usage-statistics/ API Usage Statistics Documentation} + * + * @example + * ```typescript + * // Get usage statistics for the last 7 days + * const endDate = new Date(); + * const startDate = new Date(endDate.getTime() - 7 * 24 * 60 * 60 * 1000); + * + * const statsResponse = await linkedapi.getApiUsageStats({ + * start: startDate.toISOString(), + * end: endDate.toISOString() + * }); + * + * if (statsResponse.success) { + * console.log("Total actions executed:", statsResponse.result?.length); + * + * statsResponse.result?.forEach(action => { + * console.log(`${action.actionType}: ${action.success ? 'SUCCESS' : 'FAILED'} at ${action.time}`); + * }); + * } else { + * console.error("Failed to retrieve stats:", statsResponse.error?.message); + * } + * ``` + */ + public async getApiUsageStats( + params: TApiUsageStatsParams, + ): Promise { + const queryParams = new URLSearchParams({ + start: params.start, + end: params.end, + }); + + const response = await this.httpClient.get( + `/account/stats/actions?${queryParams.toString()}`, + ); + + return { + success: response.success, + result: response.result, + error: response.error, + }; + } } export default LinkedApi; -export { - LinkedApi, - AccountApi, - LinkedApiError, - LinkedApiWorkflowError, - WorkflowHandler, -}; +export { LinkedApi, LinkedApiError, LinkedApiWorkflowError, WorkflowHandler }; export type { TLinkedApiConfig, diff --git a/src/core/array-workflow-mapper.abstract.ts b/src/mappers/array-workflow-mapper.abstract.ts similarity index 100% rename from src/core/array-workflow-mapper.abstract.ts rename to src/mappers/array-workflow-mapper.abstract.ts diff --git a/src/core/base-mapper.abstract.ts b/src/mappers/base-mapper.abstract.ts similarity index 100% rename from src/core/base-mapper.abstract.ts rename to src/mappers/base-mapper.abstract.ts diff --git a/src/account-api/fetch-company-mapper.ts b/src/mappers/fetch-company-mapper.ts similarity index 96% rename from src/account-api/fetch-company-mapper.ts rename to src/mappers/fetch-company-mapper.ts index 674db7b..5fda53b 100644 --- a/src/account-api/fetch-company-mapper.ts +++ b/src/mappers/fetch-company-mapper.ts @@ -5,7 +5,7 @@ import type { import { ThenWorkflowMapper, type TActionConfig, -} from "../core/then-workflow-mapper.abstract"; +} from "./then-workflow-mapper.abstract"; const FETCH_COMPANY_ACTIONS: TActionConfig[] = [ { diff --git a/src/account-api/fetch-nv-company-mapper.ts b/src/mappers/fetch-nv-company-mapper.ts similarity index 95% rename from src/account-api/fetch-nv-company-mapper.ts rename to src/mappers/fetch-nv-company-mapper.ts index 7016081..0e13532 100644 --- a/src/account-api/fetch-nv-company-mapper.ts +++ b/src/mappers/fetch-nv-company-mapper.ts @@ -5,7 +5,7 @@ import type { import { ThenWorkflowMapper, type TActionConfig, -} from "../core/then-workflow-mapper.abstract"; +} from "./then-workflow-mapper.abstract"; const FETCH_NV_COMPANY_ACTIONS: TActionConfig[] = [ { diff --git a/src/account-api/fetch-person-mapper.ts b/src/mappers/fetch-person-mapper.ts similarity index 97% rename from src/account-api/fetch-person-mapper.ts rename to src/mappers/fetch-person-mapper.ts index 3816ba2..0d5eff1 100644 --- a/src/account-api/fetch-person-mapper.ts +++ b/src/mappers/fetch-person-mapper.ts @@ -5,7 +5,7 @@ import type { import { ThenWorkflowMapper, type TActionConfig, -} from "../core/then-workflow-mapper.abstract"; +} from "./then-workflow-mapper.abstract"; const FETCH_PERSON_ACTIONS: TActionConfig[] = [ { diff --git a/src/mappers/index.ts b/src/mappers/index.ts new file mode 100644 index 0000000..f223039 --- /dev/null +++ b/src/mappers/index.ts @@ -0,0 +1,12 @@ +export * from "./fetch-company-mapper"; +export * from "./fetch-nv-company-mapper"; +export * from "./fetch-person-mapper"; +export * from "./nv-open-person-page-mapper"; +export * from "./retrieve-connections-mapper"; +export * from "./retrieve-pending-requests-mapper"; +export * from "./sales-navigator-search-companies-mapper"; +export * from "./sales-navigator-search-people-mapper"; +export * from "./search-companies-mapper"; +export * from "./search-people-mapper"; +export * from "./simple-workflow-mapper"; +export * from "./void-workflow-mapper"; diff --git a/src/account-api/nv-open-person-page-mapper.ts b/src/mappers/nv-open-person-page-mapper.ts similarity index 84% rename from src/account-api/nv-open-person-page-mapper.ts rename to src/mappers/nv-open-person-page-mapper.ts index 17a3e17..af77752 100644 --- a/src/account-api/nv-open-person-page-mapper.ts +++ b/src/mappers/nv-open-person-page-mapper.ts @@ -2,7 +2,7 @@ import type { TNvOpenPersonPageParams, TNvOpenPersonPageResult, } from "../types/actions/connection"; -import { ThenWorkflowMapper } from "../core/then-workflow-mapper.abstract"; +import { ThenWorkflowMapper } from "./then-workflow-mapper.abstract"; export class AcNvOpenPersonPageMapper extends ThenWorkflowMapper< TNvOpenPersonPageParams, diff --git a/src/account-api/retrieve-connections-mapper.ts b/src/mappers/retrieve-connections-mapper.ts similarity index 81% rename from src/account-api/retrieve-connections-mapper.ts rename to src/mappers/retrieve-connections-mapper.ts index 5443959..d72fc2c 100644 --- a/src/account-api/retrieve-connections-mapper.ts +++ b/src/mappers/retrieve-connections-mapper.ts @@ -2,7 +2,7 @@ import type { TRetrieveConnectionsParams, TRetrieveConnectionsResult, } from "../types/actions/connection"; -import { ArrayWorkflowMapper } from "../core/array-workflow-mapper.abstract"; +import { ArrayWorkflowMapper } from "./array-workflow-mapper.abstract"; export class AcRetrieveConnectionsMapper extends ArrayWorkflowMapper< TRetrieveConnectionsParams, diff --git a/src/account-api/retrieve-pending-requests-mapper.ts b/src/mappers/retrieve-pending-requests-mapper.ts similarity index 70% rename from src/account-api/retrieve-pending-requests-mapper.ts rename to src/mappers/retrieve-pending-requests-mapper.ts index 8a78b6b..3d157ba 100644 --- a/src/account-api/retrieve-pending-requests-mapper.ts +++ b/src/mappers/retrieve-pending-requests-mapper.ts @@ -1,6 +1,6 @@ import type { TRetrievePendingRequestsResult } from "../types/actions/connection"; -import { ArrayWorkflowMapper } from "../core/array-workflow-mapper.abstract"; -import { TBaseActionParams } from "src/types/params"; +import { ArrayWorkflowMapper } from "./array-workflow-mapper.abstract"; +import { TBaseActionParams } from "../types/params"; export class AcRetrievePendingRequestsMapper extends ArrayWorkflowMapper< TBaseActionParams, diff --git a/src/account-api/sales-navigator-search-companies-mapper.ts b/src/mappers/sales-navigator-search-companies-mapper.ts similarity index 80% rename from src/account-api/sales-navigator-search-companies-mapper.ts rename to src/mappers/sales-navigator-search-companies-mapper.ts index 27b6b09..b05c72d 100644 --- a/src/account-api/sales-navigator-search-companies-mapper.ts +++ b/src/mappers/sales-navigator-search-companies-mapper.ts @@ -2,7 +2,7 @@ import type { TNvSearchCompanyParams, TNvSearchCompanyResult, } from "../types/actions/search-company"; -import { ArrayWorkflowMapper } from "../core/array-workflow-mapper.abstract"; +import { ArrayWorkflowMapper } from "./array-workflow-mapper.abstract"; export class AcSalesNavigatorSearchCompaniesMapper extends ArrayWorkflowMapper< TNvSearchCompanyParams, diff --git a/src/account-api/sales-navigator-search-people-mapper.ts b/src/mappers/sales-navigator-search-people-mapper.ts similarity index 80% rename from src/account-api/sales-navigator-search-people-mapper.ts rename to src/mappers/sales-navigator-search-people-mapper.ts index 83787bf..072bf1f 100644 --- a/src/account-api/sales-navigator-search-people-mapper.ts +++ b/src/mappers/sales-navigator-search-people-mapper.ts @@ -2,7 +2,7 @@ import type { TNvSearchPeopleParams, TNvSearchPeopleResult, } from "../types/actions/search-people"; -import { ArrayWorkflowMapper } from "../core/array-workflow-mapper.abstract"; +import { ArrayWorkflowMapper } from "./array-workflow-mapper.abstract"; export class AcSalesNavigatorSearchPeopleMapper extends ArrayWorkflowMapper< TNvSearchPeopleParams, diff --git a/src/account-api/search-companies-mapper.ts b/src/mappers/search-companies-mapper.ts similarity index 79% rename from src/account-api/search-companies-mapper.ts rename to src/mappers/search-companies-mapper.ts index ad87a70..5b4918d 100644 --- a/src/account-api/search-companies-mapper.ts +++ b/src/mappers/search-companies-mapper.ts @@ -2,7 +2,7 @@ import type { TSearchCompanyParams, TSearchCompanyResult, } from "../types/actions/search-company"; -import { ArrayWorkflowMapper } from "../core/array-workflow-mapper.abstract"; +import { ArrayWorkflowMapper } from "./array-workflow-mapper.abstract"; export class AcSearchCompaniesMapper extends ArrayWorkflowMapper< TSearchCompanyParams, diff --git a/src/account-api/search-people-mapper.ts b/src/mappers/search-people-mapper.ts similarity index 79% rename from src/account-api/search-people-mapper.ts rename to src/mappers/search-people-mapper.ts index 324171b..8f5d12d 100644 --- a/src/account-api/search-people-mapper.ts +++ b/src/mappers/search-people-mapper.ts @@ -2,7 +2,7 @@ import type { TSearchPeopleParams, TSearchPeopleResult, } from "../types/actions/search-people"; -import { ArrayWorkflowMapper } from "../core/array-workflow-mapper.abstract"; +import { ArrayWorkflowMapper } from "./array-workflow-mapper.abstract"; export class AcSearchPeopleMapper extends ArrayWorkflowMapper< TSearchPeopleParams, diff --git a/src/core/simple-workflow-mapper.ts b/src/mappers/simple-workflow-mapper.ts similarity index 100% rename from src/core/simple-workflow-mapper.ts rename to src/mappers/simple-workflow-mapper.ts diff --git a/src/core/then-workflow-mapper.abstract.ts b/src/mappers/then-workflow-mapper.abstract.ts similarity index 100% rename from src/core/then-workflow-mapper.abstract.ts rename to src/mappers/then-workflow-mapper.abstract.ts diff --git a/src/core/void-workflow-mapper.ts b/src/mappers/void-workflow-mapper.ts similarity index 100% rename from src/core/void-workflow-mapper.ts rename to src/mappers/void-workflow-mapper.ts From d72f12842579fbb72dad398197b830f2e7645ae7 Mon Sep 17 00:00:00 2001 From: Kiril Ivonchik Date: Fri, 8 Aug 2025 17:36:44 +0200 Subject: [PATCH 3/3] 1.0.2 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 2a66fbd..fe62e09 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "linkedapi-node", - "version": "1.0.1", + "version": "1.0.2", "description": "Official TypeScript SDK for Linked API", "main": "dist/index.js", "types": "dist/index.d.ts",