From b4a4b4ebc07ec88431f98ab6f6d6f0f4e954a478 Mon Sep 17 00:00:00 2001 From: Kiril Ivonchik Date: Thu, 14 Aug 2025 18:44:55 +0200 Subject: [PATCH] Types update according to documentation --- README.md | 130 ++++---- examples/connections.ts | 2 +- examples/custom-workflow.ts | 2 +- examples/fetch-company.ts | 16 +- examples/fetch-person.ts | 6 +- examples/fetch-post.ts | 30 +- examples/messaging.ts | 2 +- examples/post-actions.ts | 5 +- examples/restore-workflow.ts | 49 +++ examples/search-companies.ts | 18 +- examples/search-people.ts | 18 +- examples/statistics.ts | 2 +- package.json | 2 +- src/core/workflow-handler.ts | 29 +- src/core/workflow-restoration.ts | 248 +++++++++++++++ src/index.ts | 292 +++++++++++------- src/mappers/array-workflow-mapper.abstract.ts | 8 +- src/mappers/fetch-company-mapper.ts | 10 +- src/mappers/fetch-person-mapper.ts | 6 +- src/mappers/index.ts | 8 +- ...y-mapper.ts => nv-fetch-company-mapper.ts} | 8 +- ...ge-mapper.ts => nv-fetch-person-mapper.ts} | 2 +- ...apper.ts => nv-search-companies-mapper.ts} | 2 +- ...e-mapper.ts => nv-search-people-mapper.ts} | 2 +- src/mappers/retrieve-connections-mapper.ts | 2 +- .../retrieve-pending-requests-mapper.ts | 2 +- src/mappers/search-companies-mapper.ts | 2 +- src/mappers/search-people-mapper.ts | 2 +- src/mappers/simple-workflow-mapper.ts | 14 +- src/mappers/then-workflow-mapper.abstract.ts | 32 +- src/types/actions/company.sales-navigator.ts | 43 +-- src/types/actions/company.ts | 26 +- src/types/actions/person.ts | 38 ++- src/types/config.ts | 2 +- src/types/errors.ts | 22 +- src/types/workflows.ts | 38 ++- 36 files changed, 810 insertions(+), 310 deletions(-) create mode 100644 examples/restore-workflow.ts create mode 100644 src/core/workflow-restoration.ts rename src/mappers/{fetch-nv-company-mapper.ts => nv-fetch-company-mapper.ts} (86%) rename src/mappers/{nv-open-person-page-mapper.ts => nv-fetch-person-mapper.ts} (86%) rename src/mappers/{sales-navigator-search-companies-mapper.ts => nv-search-companies-mapper.ts} (80%) rename src/mappers/{sales-navigator-search-people-mapper.ts => nv-search-people-mapper.ts} (80%) diff --git a/README.md b/README.md index e4b6180..70ec3a5 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,6 @@ - [Quick Start](#-quick-start) - [Linked API](#-linked-api) - [Best Practices](#-best-practices) -- [Workflow Consistency & State Management](#-workflow-consistency--state-management) - [Error Handling](#-error-handling) - [TypeScript Support](#-typescript-support) - [License](#-license) @@ -26,7 +25,7 @@ import LinkedApi from "linkedapi-node"; // Initialize with your API tokens const linkedapi = new LinkedApi({ - apiToken: "your-api-token", + linkedApiToken: "your-linked-api-token", identificationToken: "your-identification-token", }); @@ -57,7 +56,7 @@ const companies = await searchCompaniesWorkflow.result(); const companyWorkflow = await linkedapi.fetchCompany({ companyUrl: "https://www.linkedin.com/company/company1", retrieveEmployees: true, - employeeRetrievalConfig: { + employeesRetrievalConfig: { filter: { schools: ["Harvard University", "Stanford University"], }, @@ -74,20 +73,20 @@ Linked API lets you manage LinkedIn accounts programmatically through an API int To use Linked API you must initialize with: -- `apiToken` – your main token that enables overall Linked API access. +- `linkedApiToken` – your main token that enables overall Linked API access. - `identificationToken` – unique token specific to each managed LinkedIn account. ```typescript const linkedapi = new LinkedApi({ - apiToken: "your-api-token", + linkedApiToken: "your-linked-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: +You can obtain these tokens through [Linked API Platform](https://app.linkedapi.io?ref=linkedapi-node), as demonstrated below: ![API Tokens](https://linkedapi.io/content/images/size/w1600/2025/07/tokens-1.webp) -**šŸ“– Documentation:** [Documentation](https://linkedapi.io/docs/account-api/) +**šŸ“– Documentation:** [Documentation](https://linkedapi.io/docs) --- @@ -97,7 +96,7 @@ Execute custom LinkedIn automation workflows with raw workflow definitions. - **Parameters:** `TWorkflowDefinition` - Custom workflow definition - **Returns:** `Promise` - Workflow handler for result management -- **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/) +- **Documentation:** [Building Workflows](https://linkedapi.io/docs/building-workflows/) | [Executing Workflows](https://linkedapi.io/docs/executing-workflows/) | [Actions Overview](https://linkedapi.io/docs/actions-overview/) ```typescript const workflow = await linkedapi.executeCustomWorkflow({ @@ -115,7 +114,7 @@ Retrieve the result of a previously started workflow by its ID. - **Parameters:** `string` - Workflow ID - **Returns:** `Promise` - Workflow response with completion data -- **Documentation:** [Executing Workflows](https://linkedapi.io/docs/account-api/executing-workflows/) +- **Documentation:** [Executing Workflows](https://linkedapi.io/docs/executing-workflows/) ```typescript const result = await linkedapi.getWorkflowResult("workflow-id-123"); @@ -123,6 +122,35 @@ const result = await linkedapi.getWorkflowResult("workflow-id-123"); --- +### `restoreWorkflow(workflowId, functionName)` + +Restore a WorkflowHandler for a previously started workflow using its ID and function name with type safety. + +- **Parameters:** + - `workflowId: string` - The unique identifier of the workflow to restore + - `functionName: TSupportedFunctionName` - The name of the function that was used to create the workflow +- **Returns:** `Promise>>` - WorkflowHandler with exact result type based on the function name +- **Type Safety:** Full TypeScript inference for exact return types based on the function name +- **Documentation:** [Executing Workflows](https://linkedapi.io/docs/executing-workflows/) + +```typescript +// Restore a person fetching workflow with full type safety +const personHandler = await linkedapi.restoreWorkflow( + "workflow-id-123", + "fetchPerson" +); +const personData = await personHandler.result(); + +// Restore a company fetching workflow +const companyHandler = await linkedapi.restoreWorkflow( + "workflow-id-456", + "fetchCompany" +); +const companyData = await companyHandler.result(); +``` + +--- + ### `fetchPerson(params)` Retrieve comprehensive LinkedIn person profile data including experience, education, skills, and posts. @@ -144,11 +172,11 @@ const personWorkflow = await linkedapi.fetchPerson({ limit: 20, // Maximum number of posts to retrieve (1-20) since: "2024-01-01", // Retrieve posts since this date (YYYY-MM-DD) }, - commentRetrievalConfig: { + commentsRetrievalConfig: { limit: 10, // Maximum number of comments to retrieve (1-20) since: "2024-01-01", // Retrieve comments since this date }, - reactionRetrievalConfig: { + reactionsRetrievalConfig: { limit: 15, // Maximum number of reactions to retrieve (1-20) since: "2024-01-01", // Retrieve reactions since this date }, @@ -185,8 +213,8 @@ 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 - employeeRetrievalConfig: { + retrieveDMs: true, // Get decision makers and key personnel + employeesRetrievalConfig: { limit: 25, // Maximum number of employees to retrieve (1-500) filter: { firstName: "John", // Filter by employee first name @@ -199,11 +227,11 @@ const companyWorkflow = await linkedapi.fetchCompany({ schools: ["Stanford University", "MIT"], // Filter by educational background }, }, - postRetrievalConfig: { + postsRetrievalConfig: { limit: 10, // Maximum number of posts to retrieve (1-20) since: "2024-01-01", // Retrieve posts since this date (YYYY-MM-DD) }, - dmRetrievalConfig: { + dmsRetrievalConfig: { limit: 5, // Maximum number of decision makers to retrieve }, }); @@ -222,9 +250,9 @@ Retrieve company data through Sales Navigator with advanced filtering and prospe ```typescript 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 - employeeRetrievalConfig: { + retrieveEmployees: true, // Get company employees with Sales Navigator + retrieveDMs: true, // Get decision makers + employeesRetrievalConfig: { limit: 25, // Maximum number of employees to retrieve (1-500) filter: { firstName: "John", @@ -236,7 +264,7 @@ const nvCompanyWorkflow = await linkedapi.salesNavigatorFetchCompany({ yearsOfExperiences: ["threeToFive", "sixToTen"], }, }, - dmRetrievalConfig: { + dmsRetrievalConfig: { limit: 10, // Maximum number of decision makers to retrieve (1-20) }, }); @@ -364,7 +392,7 @@ const nvPeopleSearch = await linkedapi.salesNavigatorSearchPeople({ Send connection requests to LinkedIn users with optional personalized messages. - **Parameters:** `TSendConnectionRequestParams` - Person URL and optional message -- **Returns:** `Promise>` - Workflow handler (no result data) +- **Returns:** `Promise>` - Workflow handler (void) ```typescript await linkedapi.sendConnectionRequest({ @@ -397,7 +425,7 @@ console.log("Connection status:", status.connectionStatus); // 'connected', 'pen Withdraw previously sent connection requests. - **Parameters:** `TWithdrawConnectionRequestParams` - Person URL -- **Returns:** `Promise>` - Workflow handler (no result data) +- **Returns:** `Promise>` - Workflow handler (void) ```typescript await linkedapi.withdrawConnectionRequest({ @@ -447,7 +475,7 @@ const connectionsWorkflow = await linkedapi.retrieveConnections({ Remove existing connections from your LinkedIn network. - **Parameters:** `TRemoveConnectionParams` - Person URL -- **Returns:** `Promise>` - Workflow handler (no result data) +- **Returns:** `Promise>` - Workflow handler (void) ```typescript await linkedapi.removeConnection({ @@ -462,7 +490,7 @@ await linkedapi.removeConnection({ React to LinkedIn posts with various reaction types (like, love, support, etc.). - **Parameters:** `TReactToPostParams` - Post URL and reaction type -- **Returns:** `Promise>` - Workflow handler (no result data) +- **Returns:** `Promise>` - Workflow handler (void) ```typescript await linkedapi.reactToPost({ @@ -478,7 +506,7 @@ await linkedapi.reactToPost({ Comment on LinkedIn posts to engage with your network. - **Parameters:** `TCommentOnPostParams` - Post URL and comment text -- **Returns:** `Promise>` - Workflow handler (no result data) +- **Returns:** `Promise>` - Workflow handler (void) ```typescript await linkedapi.commentOnPost({ @@ -522,7 +550,7 @@ console.log("Post views:", metrics.postViewsLast7Days); ### `getApiUsageStats(params)` -Retrieve Account API usage statistics for monitoring and optimization. +Retrieve Linked API usage statistics for monitoring and optimization. - **Parameters:** `TApiUsageStatsParams` - Start and end timestamps (max 30 days apart) - **Returns:** `Promise` - Array of executed actions with success/failure data @@ -554,7 +582,7 @@ if (statsResponse.success) { Send messages to LinkedIn users through standard LinkedIn messaging. - **Parameters:** `TSendMessageParams` - Person URL and message text -- **Returns:** `Promise>` - Workflow handler (no result data) +- **Returns:** `Promise>` - Workflow handler (void) ```typescript await linkedapi.sendMessage({ @@ -570,7 +598,7 @@ await linkedapi.sendMessage({ Sync conversation history with a LinkedIn user for message polling. - **Parameters:** `TSyncConversationParams` - Person URL -- **Returns:** `Promise>` - Workflow handler (no result data) +- **Returns:** `Promise>` - Workflow handler (void) - **Related Methods:** Use with `pollConversations()` to retrieve message history ```typescript @@ -586,7 +614,7 @@ await linkedapi.syncConversation({ Send messages through Sales Navigator with enhanced messaging capabilities. - **Parameters:** `TNvSendMessageParams` - Person URL, message text, and optional subject -- **Returns:** `Promise>` - Workflow handler (no result data) +- **Returns:** `Promise>` - Workflow handler (void) ```typescript await linkedapi.salesNavigatorSendMessage({ @@ -603,7 +631,7 @@ await linkedapi.salesNavigatorSendMessage({ Sync Sales Navigator conversation for message polling. - **Parameters:** `TNvSyncConversationParams` - Person URL -- **Returns:** `Promise>` - Workflow handler (no result data) +- **Returns:** `Promise>` - Workflow handler (void) ```typescript await linkedapi.salesNavigatorSyncConversation({ @@ -698,7 +726,7 @@ try { try { const companyEmployeesWorkflow = await linkedapi.fetchCompany({ retrieveEmployees: true, - employeeRetrievalConfig: { + employeesRetrievalConfig: { limit: 5, filter: { position: "manager" @@ -727,7 +755,7 @@ try { } ``` -**šŸ“– Learn more:** [Building Custom Workflows](https://linkedapi.io/docs/account-api/building-workflows/) | [Actions Overview](https://linkedapi.io/docs/account-api/actions-overview/) +**šŸ“– Learn more:** [Building Custom Workflows](https://linkedapi.io/docs/building-workflows/) | [Actions Overview](https://linkedapi.io/docs/actions-overview/) ### Workflow Consistency & State Management @@ -749,7 +777,7 @@ const workflowId = personWorkflow.workflowId; console.log("Workflow started with ID:", workflowId); // Store in database/file/memory for later retrieval -await saveWorkflowToDatabase(workflowId); +await saveWorkflowToDatabase(workflowId, "fetchPerson"); try { const person = await personWorkflow.result(); } finally { @@ -759,37 +787,31 @@ try { #### Retrieving Results After App Restart -If your application restarts or you need to check workflow status later, use `getWorkflowResult(workflowId)`: +If your application restarts or you need to check workflow status later, you can: +- Restore a `WorkflowHandler` using `restoreWorkflow(workflowId, functionName)` with full type safety ```typescript -// Account API - retrieve workflow result by ID -const savedWorkflows = await getWorkflowsFromDatabase(); -for (workflowId of runningWorkflows) { - try { - const result = await linkedapi.getWorkflowResult(workflowId); +// 1) Raw handler +const rawHandler = await linkedapi.restoreWorkflow(savedWorkflowId); - if (result.completion) { - console.log("Workflow completed:", result.completion.data); - await deleteWorkflowFromDatabase(workflowId); - } else { - console.log("Workflow still running..."); - // Continue polling or set up periodic checks - } - } catch (error) { - console.error("Workflow failed:", error); - await deleteWorkflowFromDatabase(workflowId); - } -} +// 2) Streamlined restoration with function name (wide result type with full type safety) +const handler = await linkedapi.restoreWorkflow(savedWorkflowId, "fetchPerson"); +const result = await handler.result(); +console.log("Person name:", result.name); +console.log("Experience count:", result.experiences?.length); ``` +See `examples/restore-workflow.ts` for a full example. + --- ## 🚨 Error Handling Linked API provides structured error handling for different failure scenarios. -- **`LinkedApiError`** - throws if a [common error](https://linkedapi.io/docs/account-api/making-requests/#common-errors) occurs -- **`LinkedApiWorkflowError`** - throws in case of the [workflow execution](https://linkedapi.io/docs/account-api/actions-overview/#result-options) error (like invalid URL or messaging not allowed) +- **`LinkedApiError`** - throws if a [common error](https://linkedapi.io/docs/making-requests/#common-errors) occurs +- **`LinkedApiWorkflowError`** - throws in case of the [workflow execution](https://linkedapi.io/docs/actions-overview/#result-options) error (like invalid URL or messaging not allowed) +- **`LinkedApiWorkflowTimeoutError`** - throws in case of timeout. Contains `workflowId` and `functionName` for future restoration ```typescript import LinkedApi from "linkedapi-node"; @@ -815,8 +837,8 @@ try { ### Common Error Types -- **`accountApiTokenRequired`** - Missing API token -- **`invalidAccountApiToken`** - Invalid API token +- **`linkedApiTokenRequired`** - Missing API token +- **`invalidLinkedApiToken`** - Invalid API token - **`identificationTokenRequired`** - Missing Indentification token - **`invalidIdentificationToken`** - Invalid Identification Token - **`subscriptionRequired`** - No purchased subscription seats available for this LinkedIn account. diff --git a/examples/connections.ts b/examples/connections.ts index 3c1c6e4..0adc227 100644 --- a/examples/connections.ts +++ b/examples/connections.ts @@ -3,7 +3,7 @@ import LinkedApi, { LinkedApiError, LinkedApiWorkflowError } from 'linkedapi-nod async function connectionsExample(): Promise { const linkedapi = new LinkedApi({ - apiToken: process.env.API_TOKEN!, + linkedApiToken: process.env.LINKED_API_TOKEN!, identificationToken: process.env.IDENTIFICATION_TOKEN!, }); diff --git a/examples/custom-workflow.ts b/examples/custom-workflow.ts index 13602e3..b5f1f2c 100644 --- a/examples/custom-workflow.ts +++ b/examples/custom-workflow.ts @@ -3,7 +3,7 @@ import LinkedApi, { LinkedApiError, LinkedApiWorkflowError } from 'linkedapi-nod async function customWorkflowExample(): Promise { const linkedapi = new LinkedApi({ - apiToken: process.env.API_TOKEN!, + linkedApiToken: process.env.LINKED_API_TOKEN!, identificationToken: process.env.IDENTIFICATION_TOKEN!, }); diff --git a/examples/fetch-company.ts b/examples/fetch-company.ts index 7772482..0a70ce2 100644 --- a/examples/fetch-company.ts +++ b/examples/fetch-company.ts @@ -2,7 +2,7 @@ import LinkedApi, { LinkedApiError, LinkedApiWorkflowError } from 'linkedapi-nod async function fetchCompanyExample(): Promise { const linkedapi = new LinkedApi({ - apiToken: process.env.API_TOKEN!, + linkedApiToken: process.env.LINKED_API_TOKEN!, identificationToken: process.env.IDENTIFICATION_TOKEN!, }); @@ -28,19 +28,19 @@ async function standardExample(linkedapi: LinkedApi): Promise { const fetchCompanyWorkflow = await linkedapi.fetchCompany({ companyUrl: 'https://www.linkedin.com/company/linkedin/', retrieveEmployees: true, - retrieveDms: true, + retrieveDMs: true, retrievePosts: true, - employeeRetrievalConfig: { + employeesRetrievalConfig: { limit: 2, filter: { position: 'engineer', locations: ['United States'], }, }, - dmRetrievalConfig: { + dmsRetrievalConfig: { limit: 2, }, - postRetrievalConfig: { + postsRetrievalConfig: { limit: 10, since: '2024-01-01', }, @@ -64,14 +64,14 @@ async function salesNavigatorExample(linkedapi: LinkedApi): Promise { const nvCompanyResult = await linkedapi.salesNavigatorFetchCompany({ companyHashedUrl: 'https://www.linkedin.com/sales/company/1035', retrieveEmployees: true, - retrieveDms: true, - employeeRetrievalConfig: { + retrieveDMs: true, + employeesRetrievalConfig: { limit: 1, filter: { positions: ['Manager', 'Engineer'], }, }, - dmRetrievalConfig: { + dmsRetrievalConfig: { limit: 2, }, }); diff --git a/examples/fetch-person.ts b/examples/fetch-person.ts index acb4b29..60acbff 100644 --- a/examples/fetch-person.ts +++ b/examples/fetch-person.ts @@ -3,7 +3,7 @@ import LinkedApi, { LinkedApiError, LinkedApiWorkflowError } from 'linkedapi-nod async function fetchPersonExample(): Promise { const linkedapi = new LinkedApi({ - apiToken: process.env.API_TOKEN!, + linkedApiToken: process.env.LINKED_API_TOKEN!, identificationToken: process.env.IDENTIFICATION_TOKEN!, }); @@ -39,10 +39,10 @@ async function standardExample(linkedapi: LinkedApi): Promise { limit: 5, since: '2024-01-01', }, - commentRetrievalConfig: { + commentsRetrievalConfig: { limit: 5, }, - reactionRetrievalConfig: { + reactionsRetrievalConfig: { limit: 5, }, }); diff --git a/examples/fetch-post.ts b/examples/fetch-post.ts index ccd65de..5ef1286 100644 --- a/examples/fetch-post.ts +++ b/examples/fetch-post.ts @@ -2,7 +2,7 @@ import LinkedApi, { LinkedApiError, LinkedApiWorkflowError } from 'linkedapi-nod async function fetchPostExample(): Promise { const linkedapi = new LinkedApi({ - apiToken: process.env.API_TOKEN!, + linkedApiToken: process.env.LINKED_API_TOKEN!, identificationToken: process.env.IDENTIFICATION_TOKEN!, }); @@ -23,23 +23,23 @@ async function fetchPostExample(): Promise { } async function standardExample(linkedapi: LinkedApi): Promise { - const accountPostWorkflow = await linkedapi.fetchPost({ + const postWorkflow = await linkedapi.fetchPost({ postUrl: 'https://www.linkedin.com/posts/post-url' }); - console.log('šŸ” Account API workflow started:', accountPostWorkflow.workflowId); - const accountPost = await accountPostWorkflow.result(); + console.log('šŸ” Workflow started:', postWorkflow.workflowId); + const post = await postWorkflow.result(); - console.log('āœ… Account API post fetched successfully'); - console.log(`šŸ“„ Post URL: ${accountPost.url}`); - console.log(`ā° Post Time: ${accountPost.time}`); - console.log(`šŸ“ Post Type: ${accountPost.type}`); - console.log(`šŸ’¬ Text: ${accountPost.text || 'No text content'}`); - console.log(`šŸ”„ Repost Text: ${accountPost.repostText || 'Not a repost'}`); - console.log(`šŸ–¼ļø Images: ${accountPost.images?.length || 0} image(s)`); - console.log(`šŸŽ„ Has Video: ${accountPost.hasVideo}`); - console.log(`šŸ“Š Has Poll: ${accountPost.hasPoll}`); - console.log(`šŸ‘ Reactions: ${accountPost.reactionCount}`); - console.log(`šŸ’¬ Comments: ${accountPost.commentCount}`); + console.log('āœ… Post fetched successfully'); + console.log(`šŸ“„ Post URL: ${post.url}`); + console.log(`ā° Post Time: ${post.time}`); + console.log(`šŸ“ Post Type: ${post.type}`); + console.log(`šŸ’¬ Text: ${post.text || 'No text content'}`); + console.log(`šŸ”„ Repost Text: ${post.repostText || 'Not a repost'}`); + console.log(`šŸ–¼ļø Images: ${post.images?.length || 0} image(s)`); + console.log(`šŸŽ„ Has Video: ${post.hasVideo}`); + console.log(`šŸ“Š Has Poll: ${post.hasPoll}`); + console.log(`šŸ‘ Reactions: ${post.reactionCount}`); + console.log(`šŸ’¬ Comments: ${post.commentCount}`); } if (require.main === module) { diff --git a/examples/messaging.ts b/examples/messaging.ts index 1e9a28b..3b99b16 100644 --- a/examples/messaging.ts +++ b/examples/messaging.ts @@ -2,7 +2,7 @@ import LinkedApi, { LinkedApiError, LinkedApiWorkflowError } from 'linkedapi-nod async function messagingExample(): Promise { const linkedapi = new LinkedApi({ - apiToken: process.env.API_TOKEN!, + linkedApiToken: process.env.LINKED_API_TOKEN!, identificationToken: process.env.IDENTIFICATION_TOKEN!, }); diff --git a/examples/post-actions.ts b/examples/post-actions.ts index c4a75df..f7baef2 100644 --- a/examples/post-actions.ts +++ b/examples/post-actions.ts @@ -2,7 +2,7 @@ import LinkedApi, { LinkedApiError, LinkedApiWorkflowError } from 'linkedapi-nod async function postActionsExample(): Promise { const linkedapi = new LinkedApi({ - apiToken: process.env.API_TOKEN!, + linkedApiToken: process.env.LINKED_API_TOKEN!, identificationToken: process.env.IDENTIFICATION_TOKEN!, }); @@ -10,7 +10,6 @@ async function postActionsExample(): Promise { console.log('šŸš€ Linked API Post Actions example starting...'); await reactToPost(linkedapi); await commentOnPost(linkedapi); - } catch (error) { if (error instanceof LinkedApiError) { console.error('🚨 Linked API Error:', error.message); @@ -56,4 +55,4 @@ async function commentOnPost(linkedapi: LinkedApi): Promise { if (require.main === module) { postActionsExample(); -} \ No newline at end of file +} diff --git a/examples/restore-workflow.ts b/examples/restore-workflow.ts new file mode 100644 index 0000000..b19e7e9 --- /dev/null +++ b/examples/restore-workflow.ts @@ -0,0 +1,49 @@ +import LinkedApi from '../src'; + +async function example(): Promise { + // First run + const linkedapi = new LinkedApi({ + linkedApiToken: process.env.LINKED_API_TOKEN!, + identificationToken: process.env.IDENTIFICATION_TOKEN!, + }); + + const startHandler = await linkedapi.fetchPerson({ + personUrl: 'https://www.linkedin.com/in/example-person/', + retrieveExperience: true, + retrieveEducation: true, + }); + + const savedWorkflowId = startHandler.workflowId; + + // ... App stops here + + // App restart: rebuild LinkedApi client + const linkedapiAfterRestart = new LinkedApi({ + linkedApiToken: process.env.LINKED_API_TOKEN!, + identificationToken: process.env.IDENTIFICATION_TOKEN!, + }); + + const restoredHandler = await linkedapiAfterRestart.restoreWorkflow( + savedWorkflowId, + "fetchPerson", + ); + + // Or if you want to restore a raw workflow (for executeCustomWorkflow) + const rawHandler = await linkedapiAfterRestart.restoreWorkflow( + savedWorkflowId, + ); + + console.log("Restoration started: ", restoredHandler.workflowId); + + const result = await restoredHandler.result(); + console.log("šŸ‘¤ Restored name:", result.name); + console.log("šŸ’¼ Restored experience:", result.experiences?.length); + console.log("Restored result:", JSON.stringify(result, null, 2)); + + const rawResult = await rawHandler.result(); + console.log("Raw result:", JSON.stringify(rawResult, null, 2)); +} + +if (require.main === module) { + example(); +} diff --git a/examples/search-companies.ts b/examples/search-companies.ts index cf09478..85af097 100644 --- a/examples/search-companies.ts +++ b/examples/search-companies.ts @@ -2,7 +2,7 @@ import LinkedApi, { LinkedApiError, LinkedApiWorkflowError, TSearchCompanySize } async function searchCompaniesExample(): Promise { const linkedapi = new LinkedApi({ - apiToken: process.env.API_TOKEN!, + linkedApiToken: process.env.LINKED_API_TOKEN!, identificationToken: process.env.IDENTIFICATION_TOKEN!, }); @@ -36,14 +36,14 @@ async function standardExample(linkedapi: LinkedApi): Promise { }, }; - console.log('šŸ” Searching companies with Account API...'); - const accountSearchWorkflow = await linkedapi.searchCompanies(searchParams); - console.log('šŸ” Account API workflow started:', accountSearchWorkflow.workflowId); - const accountResults = await accountSearchWorkflow.result(); + console.log('šŸ” Searching companies with Linked API...'); + const searchWorkflow = await linkedapi.searchCompanies(searchParams); + console.log('šŸ” Workflow started:', searchWorkflow.workflowId); + const results = await searchWorkflow.result(); - console.log('āœ… Account API company search completed'); - console.log(`šŸ“Š Found ${accountResults.length} companies`); - accountResults.forEach((company, index) => { + console.log('āœ… Company search completed'); + console.log(`šŸ“Š Found ${results.length} companies`); + results.forEach((company, index) => { console.log(` ${index + 1}. ${company.name}`); console.log(` Industry: ${company.industry}`); console.log(` Location: ${company.location}`); @@ -66,7 +66,7 @@ async function salesNavigatorExample(linkedapi: LinkedApi): Promise { }, }; - console.log('\nšŸŽÆ Searching companies with Sales Navigator (Account API)...'); + console.log('\nšŸŽÆ Searching companies with Sales Navigator...'); 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 4e25f13..8d5b267 100644 --- a/examples/search-people.ts +++ b/examples/search-people.ts @@ -2,7 +2,7 @@ import LinkedApi, { LinkedApiError, LinkedApiWorkflowError, TYearsOfExperience } async function searchPeopleExample(): Promise { const linkedapi = new LinkedApi({ - apiToken: process.env.API_TOKEN!, + linkedApiToken: process.env.LINKED_API_TOKEN!, identificationToken: process.env.IDENTIFICATION_TOKEN!, }); @@ -38,14 +38,14 @@ async function standardExample(linkedapi: LinkedApi): Promise { }, }; - console.log('šŸ” Searching people with Account API...'); - const accountSearchWorkflow = await linkedapi.searchPeople(searchParams); - console.log('šŸ” Account API workflow started:', accountSearchWorkflow.workflowId); - const accountResults = await accountSearchWorkflow.result(); + console.log('šŸ” Searching people with Linked API...'); + const searchWorkflow = await linkedapi.searchPeople(searchParams); + console.log('šŸ” Workflow started:', searchWorkflow.workflowId); + const results = await searchWorkflow.result(); - console.log('āœ… Account API people search completed'); - console.log(`šŸ“Š Found ${accountResults.length} people`); - accountResults.forEach((person, index) => { + console.log('āœ… People search completed'); + console.log(`šŸ“Š Found ${results.length} people`); + results.forEach((person, index) => { console.log(` ${index + 1}. ${person.name}`); console.log(` Headline: ${person.headline}`); console.log(` Location: ${person.location}`); @@ -66,7 +66,7 @@ async function salesNavigatorExample(linkedapi: LinkedApi): Promise { }, }; - console.log('\nšŸŽÆ Searching people with Sales Navigator (Account API)...'); + console.log('\nšŸŽÆ Searching people with Sales Navigator...'); 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 bb03f43..45d5cc2 100644 --- a/examples/statistics.ts +++ b/examples/statistics.ts @@ -2,7 +2,7 @@ import LinkedApi, { LinkedApiError, LinkedApiWorkflowError } from 'linkedapi-nod async function statisticsExample(): Promise { const linkedapi = new LinkedApi({ - apiToken: process.env.API_TOKEN!, + linkedApiToken: process.env.LINKED_API_TOKEN!, identificationToken: process.env.IDENTIFICATION_TOKEN!, }); diff --git a/package.json b/package.json index fe62e09..ded065e 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "linkedapi-node", - "version": "1.0.2", + "version": "1.1.0", "description": "Official TypeScript SDK for Linked API", "main": "dist/index.js", "types": "dist/index.d.ts", diff --git a/src/core/workflow-handler.ts b/src/core/workflow-handler.ts index b38c639..5eebdfc 100644 --- a/src/core/workflow-handler.ts +++ b/src/core/workflow-handler.ts @@ -5,10 +5,13 @@ import type { WaitForCompletionOptions, WorkflowExecutor, } from "./workflow-executor"; +import { TSupportedFunctionName } from "../core/workflow-restoration"; +import { LinkedApiError, LinkedApiWorkflowTimeoutError } from "../types"; export class WorkflowHandler { constructor( public readonly workflowId: string, + public readonly functionName: TSupportedFunctionName, private readonly workflowExecutor: WorkflowExecutor, private readonly mapper?: BaseMapper, ) {} @@ -16,15 +19,25 @@ export class WorkflowHandler { public async result( options: WaitForCompletionOptions = {}, ): Promise { - const rawResult = await this.workflowExecutor.result( - this.workflowId, - options, - ); + try { + const rawResult = await this.workflowExecutor.result( + this.workflowId, + options, + ); - if (!this.mapper) { - return rawResult as TResult; - } + if (!this.mapper) { + return rawResult as TResult; + } - return this.mapper.mapResponse(rawResult); + return this.mapper.mapResponse(rawResult); + } catch (error) { + if (error instanceof LinkedApiError && error.type === "timeout") { + throw new LinkedApiWorkflowTimeoutError( + this.workflowId, + this.functionName, + ); + } + throw error; + } } } diff --git a/src/core/workflow-restoration.ts b/src/core/workflow-restoration.ts new file mode 100644 index 0000000..a443a9f --- /dev/null +++ b/src/core/workflow-restoration.ts @@ -0,0 +1,248 @@ +import type { TBaseFetchPersonParamsWide } from "../types/actions/person"; +import type { TBaseFetchCompanyParamsWide } from "../types/actions/company"; +import type { TNvBaseFetchCompanyParamsWide } from "../types/actions/company.sales-navigator"; +import type { TWorkflowResponse } from "../types/workflows"; +import type { BaseMapper } from "../mappers/base-mapper.abstract"; + +export type TRestoreResultType = + T extends "executeCustomWorkflow" + ? TWorkflowResponse + : TRestoreMapperReturnType extends BaseMapper + ? R + : never; + +import { + FetchPersonMapper, + FetchCompanyMapper, + NvFetchCompanyMapper, + NvFetchPersonMapper, + SearchCompaniesMapper, + NvSearchCompaniesMapper, + SearchPeopleMapper, + NvSearchPeopleMapper, + RetrieveConnectionsMapper, + RetrievePendingRequestsMapper, + SimpleWorkflowMapper, + VoidWorkflowMapper, +} from "../mappers"; +import { + TFetchPostParams, + TFetchPostResult, + TSendMessageParams, + TSyncConversationParams, + TNvSendMessageParams, + TNvSyncConversationParams, + TSendConnectionRequestParams, + TCheckConnectionStatusParams, + TCheckConnectionStatusResult, + TWithdrawConnectionRequestParams, + TRemoveConnectionParams, + TReactToPostParams, + TCommentOnPostParams, + TRetrieveSSIResult, + TRetrievePerformanceResult, + TBaseActionParams, +} from "../types"; + +export type TRestoreMapperReturnType = T extends "fetchPerson" + ? FetchPersonMapper + : T extends "fetchCompany" + ? FetchCompanyMapper + : T extends "salesNavigatorFetchCompany" + ? NvFetchCompanyMapper + : T extends "salesNavigatorFetchPerson" + ? NvFetchPersonMapper + : T extends "fetchPost" + ? SimpleWorkflowMapper + : T extends "searchCompanies" + ? SearchCompaniesMapper + : T extends "salesNavigatorSearchCompanies" + ? NvSearchCompaniesMapper + : T extends "searchPeople" + ? SearchPeopleMapper + : T extends "salesNavigatorSearchPeople" + ? NvSearchPeopleMapper + : T extends "sendMessage" + ? VoidWorkflowMapper + : T extends "syncConversation" + ? VoidWorkflowMapper + : T extends "salesNavigatorSendMessage" + ? VoidWorkflowMapper + : T extends "salesNavigatorSyncConversation" + ? VoidWorkflowMapper + : T extends "sendConnectionRequest" + ? VoidWorkflowMapper + : T extends "checkConnectionStatus" + ? SimpleWorkflowMapper< + TCheckConnectionStatusParams, + TCheckConnectionStatusResult + > + : T extends "withdrawConnectionRequest" + ? VoidWorkflowMapper + : T extends "retrievePendingRequests" + ? RetrievePendingRequestsMapper + : T extends "retrieveConnections" + ? RetrieveConnectionsMapper + : T extends "removeConnection" + ? VoidWorkflowMapper + : T extends "reactToPost" + ? VoidWorkflowMapper + : T extends "commentOnPost" + ? VoidWorkflowMapper + : T extends "retrieveSSI" + ? SimpleWorkflowMapper< + TBaseActionParams, + TRetrieveSSIResult + > + : T extends "retrievePerformance" + ? SimpleWorkflowMapper< + TBaseActionParams, + TRetrievePerformanceResult + > + : T extends "executeCustomWorkflow" + ? null // Special case: no mapper needed, will return raw TWorkflowResponse + : never; + +export type TSupportedFunctionName = + | "fetchPerson" + | "fetchCompany" + | "salesNavigatorFetchCompany" + | "salesNavigatorFetchPerson" + | "fetchPost" + | "searchCompanies" + | "salesNavigatorSearchCompanies" + | "searchPeople" + | "salesNavigatorSearchPeople" + | "sendMessage" + | "syncConversation" + | "salesNavigatorSendMessage" + | "salesNavigatorSyncConversation" + | "sendConnectionRequest" + | "checkConnectionStatus" + | "withdrawConnectionRequest" + | "retrievePendingRequests" + | "retrieveConnections" + | "removeConnection" + | "reactToPost" + | "commentOnPost" + | "retrieveSSI" + | "retrievePerformance" + | "executeCustomWorkflow"; // Special case: no mapper needed, will return raw TWorkflowResponse + +/** + * Internal function to restore a mapper from a function name. + * This provides type-safe mapper creation for workflow restoration. + */ +export function createMapperFromFunctionName( + functionName: T, +): TRestoreMapperReturnType { + switch (functionName) { + case "fetchPerson": { + return new FetchPersonMapper() as TRestoreMapperReturnType; + } + case "fetchCompany": { + return new FetchCompanyMapper() as TRestoreMapperReturnType; + } + case "salesNavigatorFetchCompany": { + return new NvFetchCompanyMapper() as TRestoreMapperReturnType; + } + case "salesNavigatorFetchPerson": { + return new NvFetchPersonMapper() as TRestoreMapperReturnType; + } + case "fetchPost": { + return new SimpleWorkflowMapper({ + actionType: "st.openPost", + defaultParams: { basicInfo: true }, + }) as TRestoreMapperReturnType; + } + case "searchCompanies": { + return new SearchCompaniesMapper() as TRestoreMapperReturnType; + } + case "salesNavigatorSearchCompanies": { + return new NvSearchCompaniesMapper() as TRestoreMapperReturnType; + } + case "searchPeople": { + return new SearchPeopleMapper() as TRestoreMapperReturnType; + } + case "salesNavigatorSearchPeople": { + return new NvSearchPeopleMapper() as TRestoreMapperReturnType; + } + case "sendMessage": { + return new VoidWorkflowMapper( + "st.sendMessage", + ) as TRestoreMapperReturnType; + } + case "syncConversation": { + return new VoidWorkflowMapper( + "st.syncConversation", + ) as TRestoreMapperReturnType; + } + case "salesNavigatorSendMessage": { + return new VoidWorkflowMapper( + "nv.sendMessage", + ) as TRestoreMapperReturnType; + } + case "salesNavigatorSyncConversation": { + return new VoidWorkflowMapper( + "nv.syncConversation", + ) as TRestoreMapperReturnType; + } + case "sendConnectionRequest": { + return new VoidWorkflowMapper( + "st.sendConnectionRequest", + ) as TRestoreMapperReturnType; + } + case "checkConnectionStatus": { + return new SimpleWorkflowMapper< + TCheckConnectionStatusParams, + TCheckConnectionStatusResult + >({ + actionType: "st.checkConnectionStatus", + }) as TRestoreMapperReturnType; + } + case "withdrawConnectionRequest": { + return new VoidWorkflowMapper( + "st.withdrawConnectionRequest", + ) as TRestoreMapperReturnType; + } + case "retrievePendingRequests": { + return new RetrievePendingRequestsMapper() as TRestoreMapperReturnType; + } + case "retrieveConnections": { + return new RetrieveConnectionsMapper() as TRestoreMapperReturnType; + } + case "removeConnection": { + return new VoidWorkflowMapper( + "st.removeConnection", + ) as TRestoreMapperReturnType; + } + case "reactToPost": { + return new VoidWorkflowMapper( + "st.reactToPost", + ) as TRestoreMapperReturnType; + } + case "commentOnPost": { + return new VoidWorkflowMapper( + "st.commentOnPost", + ) as TRestoreMapperReturnType; + } + case "retrieveSSI": { + return new SimpleWorkflowMapper({ + actionType: "st.retrieveSSI", + }) as TRestoreMapperReturnType; + } + case "retrievePerformance": { + return new SimpleWorkflowMapper< + TBaseActionParams, + TRetrievePerformanceResult + >({ + actionType: "st.retrievePerformance", + }) as TRestoreMapperReturnType; + } + case "executeCustomWorkflow": { + return null as TRestoreMapperReturnType; + } + default: + throw new Error(`Unsupported functionName: ${functionName}`); + } +} diff --git a/src/index.ts b/src/index.ts index 894c649..613fec8 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,21 +1,27 @@ import type { TLinkedApiConfig } from "./types/config"; -import { LinkedApiError, LinkedApiWorkflowError } from "./types/errors"; +import { + LinkedApiError, + LinkedApiWorkflowError, + LinkedApiWorkflowTimeoutError, +} from "./types/errors"; import type { TWorkflowDefinition, TWorkflowResponse } from "./types/workflows"; 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 type { BaseMapper } from "./mappers/base-mapper.abstract"; + import { - AcFetchCompanyMapper, - AcFetchNvCompanyMapper, - AcFetchPersonMapper, - AcNvOpenPersonPageMapper, - AcRetrieveConnectionsMapper, - AcRetrievePendingRequestsMapper, - AcSalesNavigatorSearchCompaniesMapper, - AcSalesNavigatorSearchPeopleMapper, - AcSearchCompaniesMapper, - AcSearchPeopleMapper, + FetchCompanyMapper, + NvFetchCompanyMapper, + FetchPersonMapper, + NvFetchPersonMapper, + RetrieveConnectionsMapper, + RetrievePendingRequestsMapper, + NvSearchCompaniesMapper, + NvSearchPeopleMapper, + SearchCompaniesMapper, + SearchPeopleMapper, SimpleWorkflowMapper, VoidWorkflowMapper, } from "./mappers"; @@ -65,6 +71,11 @@ import { TApiUsageStatsResponse, TApiUsageAction, } from "./types"; +import { + TRestoreResultType, + TSupportedFunctionName, + createMapperFromFunctionName, +} from "./core/workflow-restoration"; /** * LinkedApi - Official TypeScript SDK for Linked API @@ -72,7 +83,7 @@ import { * 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/ Linked API Documentation} * * @example * ```typescript @@ -80,7 +91,7 @@ import { * * // Initialize with Linked API tokens for LinkedIn automation * const linkedapi = new LinkedApi({ - * apiToken: "your-api-token", + * linkedApiToken: "your-linked-api-token", * identificationToken: "your-identification-token" * }); * @@ -107,13 +118,13 @@ class LinkedApi { constructor(config: TLinkedApiConfig) { this.httpClient = new HttpClient({ headers: { - "account-api-token": config.apiToken, + "linked-api-token": config.linkedApiToken, "identification-token": config.identificationToken, }, }); this.workflowExecutor = new WorkflowExecutor({ httpClient: this.httpClient, - apiPath: "/account/workflows", + apiPath: "/workflows", workflowTimeout: config.workflowTimeout ?? 24 * 60 * 60 * 1000, }); } @@ -127,10 +138,10 @@ class LinkedApi { * @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} + * @see {@link https://linkedapi.io/docs/ Linked API Documentation} + * @see {@link https://linkedapi.io/docs/executing-workflows/ Executing Workflows Documentation} + * @see {@link https://linkedapi.io/docs/building-workflows/ Building Workflows Documentation} + * @see {@link https://linkedapi.io/docs/actions-overview/ Actions Overview Documentation} * * @example * ```typescript @@ -162,7 +173,11 @@ class LinkedApi { params: TWorkflowDefinition, ): Promise { const workflow = await this.workflowExecutor.startWorkflow(params); - return new WorkflowHandler(workflow.workflowId, this.workflowExecutor); + return new WorkflowHandler( + workflow.workflowId, + "executeCustomWorkflow", + this.workflowExecutor, + ); } /** @@ -174,7 +189,7 @@ class LinkedApi { * @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} + * @see {@link https://linkedapi.io/docs/executing-workflows/ Executing Workflows Documentation} * * @example * ```typescript @@ -193,6 +208,51 @@ class LinkedApi { return this.workflowExecutor.getWorkflowResult(workflowId); } + /** + * Restore a WorkflowHandler for a previously started workflow using its ID and function name. + * This provides full type safety and exact result types based on the function name. + * + * @param workflowId - The unique identifier of the workflow to restore + * @param functionName - The name of the function that was used to create the workflow + * @returns Promise resolving to a WorkflowHandler with exact result type based on the function name + * + * @see {@link https://linkedapi.io/docs/executing-workflows/ Executing Workflows Documentation} + * + * @example + * ```typescript + * // Restore a person fetching workflow with full type safety + * const personHandler = await linkedapi.restoreWorkflow("workflow-id-123", "fetchPerson"); + * const personData = await personHandler.result(); + * + * const statusHandler = await linkedapi.restoreWorkflow("workflow-id-456", "checkConnectionStatus"); + * const statusResult = await statusHandler.result(); + * // TypeScript knows exact type: TCheckConnectionStatusResult + * ``` + */ + public async restoreWorkflow( + workflowId: string, + functionName = "executeCustomWorkflow" as TFunctionName, + ): Promise>> { + const mapper = createMapperFromFunctionName(functionName); + + if (mapper === null) { + return new WorkflowHandler( + workflowId, + functionName, + this.workflowExecutor, + ) as WorkflowHandler>; + } + + return new WorkflowHandler( + workflowId, + functionName, + this.workflowExecutor, + mapper as BaseMapper, + ) as WorkflowHandler>; + } + + // Mapper descriptor based restoration was removed in favor of restoreMapper(functionName, parameters) + /** * Send a message to a LinkedIn user via standard LinkedIn messaging. * @@ -202,8 +262,8 @@ class LinkedApi { * @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} + * @see {@link https://linkedapi.io/docs/sending-message/ Sending Messages Documentation} + * @see {@link https://linkedapi.io/docs/action-st-send-message/ st.sendMessage Action Documentation} * * @example * ```typescript @@ -227,6 +287,7 @@ class LinkedApi { await this.workflowExecutor.startWorkflow(workflowDefinition); return new WorkflowHandler( workflowId, + "sendMessage" as const, this.workflowExecutor, sendMessageMapper, ); @@ -242,8 +303,8 @@ class LinkedApi { * @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} + * @see {@link https://linkedapi.io/docs/working-with-conversations/ Working with Conversations Documentation} + * @see {@link https://linkedapi.io/docs/action-st-sync-conversation/ st.syncConversation Action Documentation} * * @example * ```typescript @@ -265,6 +326,7 @@ class LinkedApi { await this.workflowExecutor.startWorkflow(workflowDefinition); return new WorkflowHandler( workflowId, + "syncConversation" as const, this.workflowExecutor, syncConversationMapper, ); @@ -279,8 +341,8 @@ class LinkedApi { * @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} + * @see {@link https://linkedapi.io/docs/sending-message/ Sending Messages Documentation} + * @see {@link https://linkedapi.io/docs/action-nv-send-message/ nv.sendMessage Action Documentation} * * @example * ```typescript @@ -305,6 +367,7 @@ class LinkedApi { await this.workflowExecutor.startWorkflow(workflowDefinition); return new WorkflowHandler( workflowId, + "salesNavigatorSendMessage" as const, this.workflowExecutor, nvSendMessageMapper, ); @@ -320,8 +383,8 @@ class LinkedApi { * @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} + * @see {@link https://linkedapi.io/docs/working-with-conversations/ Working with Conversations Documentation} + * @see {@link https://linkedapi.io/docs/action-nv-sync-conversation/ nv.syncConversation Action Documentation} * * @example * ```typescript @@ -343,6 +406,7 @@ class LinkedApi { await this.workflowExecutor.startWorkflow(workflowDefinition); return new WorkflowHandler( workflowId, + "salesNavigatorSyncConversation" as const, this.workflowExecutor, nvSyncConversationMapper, ); @@ -358,7 +422,7 @@ class LinkedApi { * @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} + * @see {@link https://linkedapi.io/docs/working-with-conversations/ Working with Conversations Documentation} * * @example * ```typescript @@ -393,7 +457,7 @@ class LinkedApi { conversations: TConversationPollRequest[], ): Promise { const response = await this.httpClient.post( - "/account/conversations/poll", + "/conversations/poll", conversations, ); @@ -413,15 +477,15 @@ class LinkedApi { * @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} + * @see {@link https://linkedapi.io/docs/visiting-person-page/ Visiting Person Page Documentation} + * @see {@link https://linkedapi.io/docs/action-st-open-person-page/ st.openPersonPage Action Documentation} + * @see {@link https://linkedapi.io/docs/action-st-retrieve-person-experience/ st.retrievePersonExperience Child Action} + * @see {@link https://linkedapi.io/docs/action-st-retrieve-person-education/ st.retrievePersonEducation Child Action} + * @see {@link https://linkedapi.io/docs/action-st-retrieve-person-skills/ st.retrievePersonSkills Child Action} + * @see {@link https://linkedapi.io/docs/action-st-retrieve-person-languages/ st.retrievePersonLanguages Child Action} + * @see {@link https://linkedapi.io/docs/action-st-retrieve-person-posts/ st.retrievePersonPosts Child Action} + * @see {@link https://linkedapi.io/docs/action-st-retrieve-person-comments/ st.retrievePersonComments Child Action} + * @see {@link https://linkedapi.io/docs/action-st-retrieve-person-reactions/ st.retrievePersonReactions Child Action} * * @example * ```typescript @@ -439,11 +503,11 @@ class LinkedApi { * limit: 10, * since: "2024-01-01" * }, - * commentRetrievalConfig: { + * commentsRetrievalConfig: { * limit: 5, * since: "2024-01-01" * }, - * reactionRetrievalConfig: { + * reactionsRetrievalConfig: { * limit: 3, * since: "2024-01-01" * } @@ -471,12 +535,13 @@ class LinkedApi { public async fetchPerson( params: TFetchPersonParams, ): Promise>> { - const fetchPersonMapper = new AcFetchPersonMapper(); + const fetchPersonMapper = new FetchPersonMapper(); const workflowDefinition = fetchPersonMapper.mapRequest(params); const { workflowId } = await this.workflowExecutor.startWorkflow(workflowDefinition); return new WorkflowHandler>( workflowId, + "fetchPerson", this.workflowExecutor, fetchPersonMapper, ); @@ -491,8 +556,8 @@ class LinkedApi { * @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} + * @see {@link https://linkedapi.io/docs/visiting-person-page/ Visiting Person Page Documentation} + * @see {@link https://linkedapi.io/docs/action-nv-open-person-page/ nv.openPersonPage Action Documentation} * * @example * ```typescript @@ -507,12 +572,13 @@ class LinkedApi { public async salesNavigatorFetchPerson( params: TNvOpenPersonPageParams, ): Promise> { - const nvOpenPersonPageMapper = new AcNvOpenPersonPageMapper(); + const nvOpenPersonPageMapper = new NvFetchPersonMapper(); const workflowDefinition = nvOpenPersonPageMapper.mapRequest(params); const { workflowId } = await this.workflowExecutor.startWorkflow(workflowDefinition); return new WorkflowHandler( workflowId, + "salesNavigatorFetchPerson", this.workflowExecutor, nvOpenPersonPageMapper, ); @@ -527,11 +593,10 @@ class LinkedApi { * @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} + * @see {@link https://linkedapi.io/docs/action-st-open-company-page/ st.openCompanyPage Action Documentation} + * @see {@link https://linkedapi.io/docs/action-st-retrieve-company-employees/ st.retrieveCompanyEmployees Child Action} + * @see {@link https://linkedapi.io/docs/action-st-retrieve-company-dms/ st.retrieveCompanyDMs Child Action} + * @see {@link https://linkedapi.io/docs/action-st-retrieve-company-posts/ st.retrieveCompanyPosts Child Action} * * @example * ```typescript @@ -540,8 +605,8 @@ class LinkedApi { * companyUrl: "https://www.linkedin.com/company/microsoft", * retrieveEmployees: true, * retrievePosts: true, - * retrieveDms: true, - * employeeRetrievalConfig: { + * retrieveDMs: true, + * employeesRetrievalConfig: { * limit: 5, * filter: { * firstName: 'John', @@ -552,8 +617,8 @@ class LinkedApi { * schools: ['Stanford University', 'Harvard University'], * }, * }, - * postRetrievalConfig: { limit: 10, since: "2024-01-01" }, - * dmRetrievalConfig: { limit: 3 } + * postsRetrievalConfig: { limit: 10, since: "2024-01-01" }, + * dmsRetrievalConfig: { limit: 3 } * }); * * const companyData = await companyWorkflow.result(); @@ -565,12 +630,13 @@ class LinkedApi { public async fetchCompany( params: TFetchCompanyParams, ): Promise>> { - const fetchCompanyMapper = new AcFetchCompanyMapper(); + const fetchCompanyMapper = new FetchCompanyMapper(); const workflowDefinition = fetchCompanyMapper.mapRequest(params); const { workflowId } = await this.workflowExecutor.startWorkflow(workflowDefinition); return new WorkflowHandler>( workflowId, + "fetchCompany" as const, this.workflowExecutor, fetchCompanyMapper, ); @@ -585,10 +651,9 @@ class LinkedApi { * @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} + * @see {@link https://linkedapi.io/docs/action-nv-open-company-page/ nv.openCompanyPage Action Documentation} + * @see {@link https://linkedapi.io/docs/action-nv-retrieve-company-employees/ nv.retrieveCompanyEmployees Child Action} + * @see {@link https://linkedapi.io/docs/action-nv-retrieve-company-dms/ nv.retrieveCompanyDMs Child Action} * * @example * ```typescript @@ -596,8 +661,8 @@ class LinkedApi { * const nvCompanyWorkflow = await linkedapi.salesNavigatorFetchCompany({ * companyHashedUrl: 'https://www.linkedin.com/sales/company/1035', * retrieveEmployees: true, - * retrieveDms: true, - * employeeRetrievalConfig: { + * retrieveDMs: true, + * employeesRetrievalConfig: { * limit: 1, * filter: { * positions: ['Manager', 'Engineer'], @@ -606,7 +671,7 @@ class LinkedApi { * schools: ['Stanford University', 'Harvard University'], * }, * }, - * dmRetrievalConfig: { + * dmsRetrievalConfig: { * limit: 2, * }, * }); @@ -622,12 +687,13 @@ class LinkedApi { >( params: TNvFetchCompanyParams, ): Promise>> { - const fetchNvCompanyMapper = new AcFetchNvCompanyMapper(); + const fetchNvCompanyMapper = new NvFetchCompanyMapper(); const workflowDefinition = fetchNvCompanyMapper.mapRequest(params); const { workflowId } = await this.workflowExecutor.startWorkflow(workflowDefinition); return new WorkflowHandler>( workflowId, + "salesNavigatorFetchCompany" as const, this.workflowExecutor, fetchNvCompanyMapper, ); @@ -642,8 +708,7 @@ class LinkedApi { * @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} + * @see {@link https://linkedapi.io/docs/action-st-open-post/ st.openPost Action Documentation} * * @example * ```typescript @@ -674,6 +739,7 @@ class LinkedApi { await this.workflowExecutor.startWorkflow(workflowDefinition); return new WorkflowHandler( workflowId, + "fetchPost" as const, this.workflowExecutor, fetchPostMapper, ); @@ -688,8 +754,7 @@ class LinkedApi { * @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} + * @see {@link https://linkedapi.io/docs/action-st-search-companies/ st.searchCompanies Action Documentation} * * @example * ```typescript @@ -710,12 +775,13 @@ class LinkedApi { public async searchCompanies( params: TSearchCompanyParams, ): Promise> { - const searchCompaniesMapper = new AcSearchCompaniesMapper(); + const searchCompaniesMapper = new SearchCompaniesMapper(); const workflowDefinition = searchCompaniesMapper.mapRequest(params); const { workflowId } = await this.workflowExecutor.startWorkflow(workflowDefinition); return new WorkflowHandler( workflowId, + "searchCompanies" as const, this.workflowExecutor, searchCompaniesMapper, ); @@ -730,8 +796,7 @@ class LinkedApi { * @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} + * @see {@link https://linkedapi.io/docs/action-nv-search-companies/ nv.searchCompanies Action Documentation} * * @example * ```typescript @@ -756,14 +821,14 @@ class LinkedApi { public async salesNavigatorSearchCompanies( params: TNvSearchCompanyParams, ): Promise> { - const salesNavigatorSearchCompaniesMapper = - new AcSalesNavigatorSearchCompaniesMapper(); + const salesNavigatorSearchCompaniesMapper = new NvSearchCompaniesMapper(); const workflowDefinition = salesNavigatorSearchCompaniesMapper.mapRequest(params); const { workflowId } = await this.workflowExecutor.startWorkflow(workflowDefinition); return new WorkflowHandler( workflowId, + "salesNavigatorSearchCompanies" as const, this.workflowExecutor, salesNavigatorSearchCompaniesMapper, ); @@ -778,8 +843,7 @@ class LinkedApi { * @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} + * @see {@link https://linkedapi.io/docs/action-st-search-people/ st.searchPeople Action Documentation} * * @example * ```typescript @@ -800,12 +864,13 @@ class LinkedApi { public async searchPeople( params: TSearchPeopleParams, ): Promise> { - const searchPeopleMapper = new AcSearchPeopleMapper(); + const searchPeopleMapper = new SearchPeopleMapper(); const workflowDefinition = searchPeopleMapper.mapRequest(params); const { workflowId } = await this.workflowExecutor.startWorkflow(workflowDefinition); return new WorkflowHandler( workflowId, + "searchPeople" as const, this.workflowExecutor, searchPeopleMapper, ); @@ -820,8 +885,7 @@ class LinkedApi { * @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} + * @see {@link https://linkedapi.io/docs/action-nv-search-people/ nv.searchPeople Action Documentation} * * @example * ```typescript @@ -842,14 +906,14 @@ class LinkedApi { public async salesNavigatorSearchPeople( params: TNvSearchPeopleParams, ): Promise> { - const salesNavigatorSearchPeopleMapper = - new AcSalesNavigatorSearchPeopleMapper(); + const salesNavigatorSearchPeopleMapper = new NvSearchPeopleMapper(); const workflowDefinition = salesNavigatorSearchPeopleMapper.mapRequest(params); const { workflowId } = await this.workflowExecutor.startWorkflow(workflowDefinition); return new WorkflowHandler( workflowId, + "salesNavigatorSearchPeople" as const, this.workflowExecutor, salesNavigatorSearchPeopleMapper, ); @@ -864,8 +928,8 @@ class LinkedApi { * @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} + * @see {@link https://linkedapi.io/docs/working-with-connection-requests/ Working with Connection Requests Documentation} + * @see {@link https://linkedapi.io/docs/action-st-send-connection-request/ st.sendConnectionRequest Action Documentation} * * @example * ```typescript @@ -890,6 +954,7 @@ class LinkedApi { await this.workflowExecutor.startWorkflow(workflowDefinition); return new WorkflowHandler( workflowId, + "sendConnectionRequest" as const, this.workflowExecutor, sendConnectionRequestMapper, ); @@ -904,8 +969,8 @@ class LinkedApi { * @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} + * @see {@link https://linkedapi.io/docs/checking-connection-status/ Checking Connection Status Documentation} + * @see {@link https://linkedapi.io/docs/action-st-check-connection-status/ st.checkConnectionStatus Action Documentation} * * @example * ```typescript @@ -931,6 +996,7 @@ class LinkedApi { await this.workflowExecutor.startWorkflow(workflowDefinition); return new WorkflowHandler( workflowId, + "checkConnectionStatus" as const, this.workflowExecutor, checkConnectionStatusMapper, ); @@ -945,8 +1011,8 @@ class LinkedApi { * @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} + * @see {@link https://linkedapi.io/docs/working-with-connection-requests/ Working with Connection Requests Documentation} + * @see {@link https://linkedapi.io/docs/action-st-withdraw-connection-request/ st.withdrawConnectionRequest Action Documentation} * * @example * ```typescript @@ -971,6 +1037,7 @@ class LinkedApi { await this.workflowExecutor.startWorkflow(workflowDefinition); return new WorkflowHandler( workflowId, + "withdrawConnectionRequest" as const, this.workflowExecutor, withdrawConnectionRequestMapper, ); @@ -984,8 +1051,8 @@ class LinkedApi { * * @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} + * @see {@link https://linkedapi.io/docs/working-with-connection-requests/ Working with Connection Requests Documentation} + * @see {@link https://linkedapi.io/docs/action-st-retrieve-pending-requests/ st.retrievePendingRequests Action Documentation} * * @example * ```typescript @@ -1003,12 +1070,13 @@ class LinkedApi { public async retrievePendingRequests(): Promise< WorkflowHandler > { - const retrievePendingRequestsMapper = new AcRetrievePendingRequestsMapper(); + const retrievePendingRequestsMapper = new RetrievePendingRequestsMapper(); const workflowDefinition = retrievePendingRequestsMapper.mapRequest({}); const { workflowId } = await this.workflowExecutor.startWorkflow(workflowDefinition); return new WorkflowHandler( workflowId, + "retrievePendingRequests" as const, this.workflowExecutor, retrievePendingRequestsMapper, ); @@ -1023,8 +1091,8 @@ class LinkedApi { * @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} + * @see {@link https://linkedapi.io/docs/managing-existing-connections/ Managing Existing Connections Documentation} + * @see {@link https://linkedapi.io/docs/action-st-retrieve-connections/ st.retrieveConnections Action Documentation} * * @example * ```typescript @@ -1045,12 +1113,13 @@ class LinkedApi { public async retrieveConnections( params: TRetrieveConnectionsParams = {}, ): Promise> { - const retrieveConnectionsMapper = new AcRetrieveConnectionsMapper(); + const retrieveConnectionsMapper = new RetrieveConnectionsMapper(); const workflowDefinition = retrieveConnectionsMapper.mapRequest(params); const { workflowId } = await this.workflowExecutor.startWorkflow(workflowDefinition); return new WorkflowHandler( workflowId, + "retrieveConnections" as const, this.workflowExecutor, retrieveConnectionsMapper, ); @@ -1065,8 +1134,8 @@ class LinkedApi { * @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} + * @see {@link https://linkedapi.io/docs/managing-existing-connections/ Managing Existing Connections Documentation} + * @see {@link https://linkedapi.io/docs/action-st-remove-connection/ st.removeConnection Action Documentation} * * @example * ```typescript @@ -1088,6 +1157,7 @@ class LinkedApi { await this.workflowExecutor.startWorkflow(workflowDefinition); return new WorkflowHandler( workflowId, + "removeConnection" as const, this.workflowExecutor, removeConnectionMapper, ); @@ -1102,8 +1172,8 @@ class LinkedApi { * @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} + * @see {@link https://linkedapi.io/docs/reacting-and-commenting/ Reacting and Commenting Documentation} + * @see {@link https://linkedapi.io/docs/action-st-react-to-post/ st.reactToPost Action Documentation} * * @example * ```typescript @@ -1127,6 +1197,7 @@ class LinkedApi { await this.workflowExecutor.startWorkflow(workflowDefinition); return new WorkflowHandler( workflowId, + "reactToPost" as const, this.workflowExecutor, reactToPostMapper, ); @@ -1141,8 +1212,8 @@ class LinkedApi { * @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} + * @see {@link https://linkedapi.io/docs/reacting-and-commenting/ Reacting and Commenting Documentation} + * @see {@link https://linkedapi.io/docs/action-st-comment-on-post/ st.commentOnPost Action Documentation} * * @example * ```typescript @@ -1166,6 +1237,7 @@ class LinkedApi { await this.workflowExecutor.startWorkflow(workflowDefinition); return new WorkflowHandler( workflowId, + "commentOnPost" as const, this.workflowExecutor, commentOnPostMapper, ); @@ -1180,8 +1252,8 @@ class LinkedApi { * * @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} + * @see {@link https://linkedapi.io/docs/retrieving-ssi-and-performance/ Retrieving SSI and Performance Documentation} + * @see {@link https://linkedapi.io/docs/action-st-retrieve-ssi/ st.retrieveSSI Action Documentation} * * @example * ```typescript @@ -1205,6 +1277,7 @@ class LinkedApi { await this.workflowExecutor.startWorkflow(workflowDefinition); return new WorkflowHandler( workflowId, + "retrieveSSI" as const, this.workflowExecutor, retrieveSSIMapper, ); @@ -1218,8 +1291,8 @@ class LinkedApi { * * @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} + * @see {@link https://linkedapi.io/docs/retrieving-ssi-and-performance/ Retrieving SSI and Performance Documentation} + * @see {@link https://linkedapi.io/docs/action-st-retrieve-performance/ st.retrievePerformance Action Documentation} * * @example * ```typescript @@ -1245,13 +1318,14 @@ class LinkedApi { await this.workflowExecutor.startWorkflow(workflowDefinition); return new WorkflowHandler( workflowId, + "retrievePerformance" as const, this.workflowExecutor, retrievePerformanceMapper, ); } /** - * Retrieve Account API usage statistics for a specific time period. + * Retrieve Linked 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. @@ -1260,7 +1334,7 @@ class LinkedApi { * @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} + * @see {@link https://linkedapi.io/docs/api-usage-statistics/ API Usage Statistics Documentation} * * @example * ```typescript @@ -1293,7 +1367,7 @@ class LinkedApi { }); const response = await this.httpClient.get( - `/account/stats/actions?${queryParams.toString()}`, + `/stats/actions?${queryParams.toString()}`, ); return { @@ -1306,7 +1380,13 @@ class LinkedApi { export default LinkedApi; -export { LinkedApi, LinkedApiError, LinkedApiWorkflowError, WorkflowHandler }; +export { + LinkedApi, + LinkedApiError, + LinkedApiWorkflowError, + LinkedApiWorkflowTimeoutError, + WorkflowHandler, +}; export type { TLinkedApiConfig, diff --git a/src/mappers/array-workflow-mapper.abstract.ts b/src/mappers/array-workflow-mapper.abstract.ts index 9449296..09f66e2 100644 --- a/src/mappers/array-workflow-mapper.abstract.ts +++ b/src/mappers/array-workflow-mapper.abstract.ts @@ -37,7 +37,13 @@ export abstract class ArrayWorkflowMapper< throw LinkedApiWorkflowError.unknownError(); } - const data = response.completion.data; + const completion = response.completion; + + if (Array.isArray(completion)) { + return completion.map((item) => item.data) as TResult[]; + } + + const data = completion.data; if (Array.isArray(data)) { return data as TResult[]; diff --git a/src/mappers/fetch-company-mapper.ts b/src/mappers/fetch-company-mapper.ts index 5fda53b..17a5b11 100644 --- a/src/mappers/fetch-company-mapper.ts +++ b/src/mappers/fetch-company-mapper.ts @@ -11,17 +11,17 @@ const FETCH_COMPANY_ACTIONS: TActionConfig[] = [ { paramName: "retrieveEmployees", actionType: "st.retrieveCompanyEmployees", - configSource: "employeeRetrievalConfig", + configSource: "employeesRetrievalConfig", }, { - paramName: "retrieveDms", + paramName: "retrieveDMs", actionType: "st.retrieveCompanyDMs", - configSource: "dmRetrievalConfig", + configSource: "dmsRetrievalConfig", }, { paramName: "retrievePosts", actionType: "st.retrieveCompanyPosts", - configSource: "postRetrievalConfig", + configSource: "postsRetrievalConfig", }, ]; @@ -40,7 +40,7 @@ const RESPONSE_MAPPINGS = [ }, ]; -export class AcFetchCompanyMapper< +export class FetchCompanyMapper< TParams extends TBaseFetchCompanyParams, > extends ThenWorkflowMapper> { constructor() { diff --git a/src/mappers/fetch-person-mapper.ts b/src/mappers/fetch-person-mapper.ts index 0d5eff1..fe97700 100644 --- a/src/mappers/fetch-person-mapper.ts +++ b/src/mappers/fetch-person-mapper.ts @@ -32,12 +32,12 @@ const FETCH_PERSON_ACTIONS: TActionConfig[] = [ { paramName: "retrieveComments", actionType: "st.retrievePersonComments", - configSource: "commentRetrievalConfig", + configSource: "commentsRetrievalConfig", }, { paramName: "retrieveReactions", actionType: "st.retrievePersonReactions", - configSource: "reactionRetrievalConfig", + configSource: "reactionsRetrievalConfig", }, ]; @@ -72,7 +72,7 @@ const RESPONSE_MAPPINGS = [ }, ]; -export class AcFetchPersonMapper< +export class FetchPersonMapper< TParams extends TBaseFetchPersonParams, > extends ThenWorkflowMapper> { constructor() { diff --git a/src/mappers/index.ts b/src/mappers/index.ts index f223039..eafb4e8 100644 --- a/src/mappers/index.ts +++ b/src/mappers/index.ts @@ -1,11 +1,11 @@ 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 "./nv-fetch-company-mapper"; +export * from "./nv-fetch-person-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 "./nv-search-companies-mapper"; +export * from "./nv-search-people-mapper"; export * from "./search-companies-mapper"; export * from "./search-people-mapper"; export * from "./simple-workflow-mapper"; diff --git a/src/mappers/fetch-nv-company-mapper.ts b/src/mappers/nv-fetch-company-mapper.ts similarity index 86% rename from src/mappers/fetch-nv-company-mapper.ts rename to src/mappers/nv-fetch-company-mapper.ts index 0e13532..cea3d25 100644 --- a/src/mappers/fetch-nv-company-mapper.ts +++ b/src/mappers/nv-fetch-company-mapper.ts @@ -11,12 +11,12 @@ const FETCH_NV_COMPANY_ACTIONS: TActionConfig[] = [ { paramName: "retrieveEmployees", actionType: "nv.retrieveCompanyEmployees", - configSource: "employeeRetrievalConfig", + configSource: "employeesRetrievalConfig", }, { - paramName: "retrieveDms", + paramName: "retrieveDMs", actionType: "nv.retrieveCompanyDMs", - configSource: "dmRetrievalConfig", + configSource: "dmsRetrievalConfig", }, ]; @@ -31,7 +31,7 @@ const RESPONSE_MAPPINGS = [ }, ]; -export class AcFetchNvCompanyMapper< +export class NvFetchCompanyMapper< TParams extends TNvBaseFetchCompanyParams, > extends ThenWorkflowMapper> { constructor() { diff --git a/src/mappers/nv-open-person-page-mapper.ts b/src/mappers/nv-fetch-person-mapper.ts similarity index 86% rename from src/mappers/nv-open-person-page-mapper.ts rename to src/mappers/nv-fetch-person-mapper.ts index af77752..c0ddda1 100644 --- a/src/mappers/nv-open-person-page-mapper.ts +++ b/src/mappers/nv-fetch-person-mapper.ts @@ -4,7 +4,7 @@ import type { } from "../types/actions/connection"; import { ThenWorkflowMapper } from "./then-workflow-mapper.abstract"; -export class AcNvOpenPersonPageMapper extends ThenWorkflowMapper< +export class NvFetchPersonMapper extends ThenWorkflowMapper< TNvOpenPersonPageParams, TNvOpenPersonPageResult > { diff --git a/src/mappers/sales-navigator-search-companies-mapper.ts b/src/mappers/nv-search-companies-mapper.ts similarity index 80% rename from src/mappers/sales-navigator-search-companies-mapper.ts rename to src/mappers/nv-search-companies-mapper.ts index b05c72d..275d459 100644 --- a/src/mappers/sales-navigator-search-companies-mapper.ts +++ b/src/mappers/nv-search-companies-mapper.ts @@ -4,7 +4,7 @@ import type { } from "../types/actions/search-company"; import { ArrayWorkflowMapper } from "./array-workflow-mapper.abstract"; -export class AcSalesNavigatorSearchCompaniesMapper extends ArrayWorkflowMapper< +export class NvSearchCompaniesMapper extends ArrayWorkflowMapper< TNvSearchCompanyParams, TNvSearchCompanyResult > { diff --git a/src/mappers/sales-navigator-search-people-mapper.ts b/src/mappers/nv-search-people-mapper.ts similarity index 80% rename from src/mappers/sales-navigator-search-people-mapper.ts rename to src/mappers/nv-search-people-mapper.ts index 072bf1f..2ef6336 100644 --- a/src/mappers/sales-navigator-search-people-mapper.ts +++ b/src/mappers/nv-search-people-mapper.ts @@ -4,7 +4,7 @@ import type { } from "../types/actions/search-people"; import { ArrayWorkflowMapper } from "./array-workflow-mapper.abstract"; -export class AcSalesNavigatorSearchPeopleMapper extends ArrayWorkflowMapper< +export class NvSearchPeopleMapper extends ArrayWorkflowMapper< TNvSearchPeopleParams, TNvSearchPeopleResult > { diff --git a/src/mappers/retrieve-connections-mapper.ts b/src/mappers/retrieve-connections-mapper.ts index d72fc2c..fe58c8c 100644 --- a/src/mappers/retrieve-connections-mapper.ts +++ b/src/mappers/retrieve-connections-mapper.ts @@ -4,7 +4,7 @@ import type { } from "../types/actions/connection"; import { ArrayWorkflowMapper } from "./array-workflow-mapper.abstract"; -export class AcRetrieveConnectionsMapper extends ArrayWorkflowMapper< +export class RetrieveConnectionsMapper extends ArrayWorkflowMapper< TRetrieveConnectionsParams, TRetrieveConnectionsResult > { diff --git a/src/mappers/retrieve-pending-requests-mapper.ts b/src/mappers/retrieve-pending-requests-mapper.ts index 3d157ba..e38da9a 100644 --- a/src/mappers/retrieve-pending-requests-mapper.ts +++ b/src/mappers/retrieve-pending-requests-mapper.ts @@ -2,7 +2,7 @@ import type { TRetrievePendingRequestsResult } from "../types/actions/connection import { ArrayWorkflowMapper } from "./array-workflow-mapper.abstract"; import { TBaseActionParams } from "../types/params"; -export class AcRetrievePendingRequestsMapper extends ArrayWorkflowMapper< +export class RetrievePendingRequestsMapper extends ArrayWorkflowMapper< TBaseActionParams, TRetrievePendingRequestsResult > { diff --git a/src/mappers/search-companies-mapper.ts b/src/mappers/search-companies-mapper.ts index 5b4918d..f0f4756 100644 --- a/src/mappers/search-companies-mapper.ts +++ b/src/mappers/search-companies-mapper.ts @@ -4,7 +4,7 @@ import type { } from "../types/actions/search-company"; import { ArrayWorkflowMapper } from "./array-workflow-mapper.abstract"; -export class AcSearchCompaniesMapper extends ArrayWorkflowMapper< +export class SearchCompaniesMapper extends ArrayWorkflowMapper< TSearchCompanyParams, TSearchCompanyResult > { diff --git a/src/mappers/search-people-mapper.ts b/src/mappers/search-people-mapper.ts index 8f5d12d..13ae03f 100644 --- a/src/mappers/search-people-mapper.ts +++ b/src/mappers/search-people-mapper.ts @@ -4,7 +4,7 @@ import type { } from "../types/actions/search-people"; import { ArrayWorkflowMapper } from "./array-workflow-mapper.abstract"; -export class AcSearchPeopleMapper extends ArrayWorkflowMapper< +export class SearchPeopleMapper extends ArrayWorkflowMapper< TSearchPeopleParams, TSearchPeopleResult > { diff --git a/src/mappers/simple-workflow-mapper.ts b/src/mappers/simple-workflow-mapper.ts index 9d8e89b..9efde72 100644 --- a/src/mappers/simple-workflow-mapper.ts +++ b/src/mappers/simple-workflow-mapper.ts @@ -41,6 +41,18 @@ export class SimpleWorkflowMapper throw LinkedApiWorkflowError.unknownError(); } - return response.completion.data as TResult; + const completion = response.completion; + if (Array.isArray(completion)) { + return completion as TResult; + } + + if (completion.error) { + throw new LinkedApiWorkflowError( + completion.error.message, + completion.error.type, + ); + } + + return completion.data as TResult; } } diff --git a/src/mappers/then-workflow-mapper.abstract.ts b/src/mappers/then-workflow-mapper.abstract.ts index c3dc122..421b5d9 100644 --- a/src/mappers/then-workflow-mapper.abstract.ts +++ b/src/mappers/then-workflow-mapper.abstract.ts @@ -1,8 +1,8 @@ import { LinkedApiWorkflowError } from "../types/errors"; import type { TBaseActionParams } from "../types/params"; import type { - TThenAction, - TWorkflowData, + TActionResponse, + TWorkflowSingleData, TWorkflowDefinition, TWorkflowResponse, } from "../types/workflows"; @@ -67,18 +67,25 @@ export abstract class ThenWorkflowMapper< throw LinkedApiWorkflowError.unknownError(); } - const { data, error } = response.completion; - if (error) { - throw new LinkedApiWorkflowError(error.message, error.type); + const completion = response.completion; + if (Array.isArray(completion)) { + return completion as TResult; } - if (data) { - return this.mapThenFromResponse(data); + + if (completion.error) { + throw new LinkedApiWorkflowError( + completion.error.message, + completion.error.type, + ); + } + if (completion.data) { + return this.mapThenFromResponse(completion.data as TWorkflowSingleData); } throw LinkedApiWorkflowError.unknownError(); } - private mapThenFromResponse(data: TWorkflowData): TResult { + private mapThenFromResponse(data: TWorkflowSingleData): TResult { const result = { ...data }; const thenActions = data.then; @@ -89,12 +96,19 @@ export abstract class ThenWorkflowMapper< for (const mapping of this.responseMappings) { if (Array.isArray(thenActions) && thenActions.length > 0) { const thenAction = thenActions.find( - (action: TThenAction) => action.actionType === mapping.actionType, + (action: TActionResponse) => action.actionType === mapping.actionType, ); if (thenAction) { (result as Record)[mapping.targetProperty] = thenAction.data; } + continue; + } + + if ((thenActions as TActionResponse).actionType === mapping.actionType) { + (result as Record)[mapping.targetProperty] = ( + thenActions as TActionResponse + ).data; } } delete (result as Record)["then"]; diff --git a/src/types/actions/company.sales-navigator.ts b/src/types/actions/company.sales-navigator.ts index 5ebc05a..115c85c 100644 --- a/src/types/actions/company.sales-navigator.ts +++ b/src/types/actions/company.sales-navigator.ts @@ -33,33 +33,22 @@ export interface TNvCompanyDm { export interface TNvBaseFetchCompanyParams extends TBaseActionParams { companyHashedUrl: string; retrieveEmployees?: boolean; - retrieveDms?: boolean; + retrieveDMs?: boolean; } -export interface TDtBaseFetchCompanyParams extends TBaseActionParams { - companyUrl: string; - retrieveEmployees?: boolean; - retrieveDms?: boolean; +export interface TNvBaseFetchCompanyParamsWide + extends TNvBaseFetchCompanyParams { + retrieveEmployees: true; + retrieveDMs: true; } export type TNvFetchCompanyParams< T extends TNvBaseFetchCompanyParams = TNvBaseFetchCompanyParams, > = T & { - employeeRetrievalConfig?: T["retrieveEmployees"] extends true - ? TNvCompanyEmployeeRetrievalConfig | undefined - : never; - dmRetrievalConfig?: T["retrieveDms"] extends true - ? TLimitParams | undefined - : never; -}; - -export type TDtFetchCompanyParams< - T extends TDtBaseFetchCompanyParams = TDtBaseFetchCompanyParams, -> = T & { - employeeRetrievalConfig?: T["retrieveEmployees"] extends true + employeesRetrievalConfig?: T["retrieveEmployees"] extends true ? TNvCompanyEmployeeRetrievalConfig | undefined : never; - dmRetrievalConfig?: T["retrieveDms"] extends true + dmsRetrievalConfig?: T["retrieveDMs"] extends true ? TLimitParams | undefined : never; }; @@ -80,20 +69,16 @@ type TNvBaseCompany = Pick< export type TNvFetchCompanyResult = TNvBaseCompany & (TParams["retrieveEmployees"] extends true - ? { employees: ReadonlyArray } + ? { employees: ReadonlyArray | undefined } : Record) & - (TParams["retrieveDms"] extends true - ? { dms: ReadonlyArray } + (TParams["retrieveDMs"] extends true + ? { dms: ReadonlyArray | undefined } : Record); -export type TDtFetchCompanyResult = - TNvBaseCompany & - (TParams["retrieveEmployees"] extends true - ? { employees: ReadonlyArray } - : Record) & - (TParams["retrieveDms"] extends true - ? { dms: ReadonlyArray } - : Record); +export type TNvFetchCompanyResultWide = TNvBaseCompany & { + employees?: ReadonlyArray; + dms?: ReadonlyArray; +}; export interface TNvCompanyEmployeeRetrievalConfig extends TLimitParams { filter?: { diff --git a/src/types/actions/company.ts b/src/types/actions/company.ts index b02f565..6f30c8b 100644 --- a/src/types/actions/company.ts +++ b/src/types/actions/company.ts @@ -22,20 +22,26 @@ export interface TCompany { export interface TBaseFetchCompanyParams extends TBaseActionParams { companyUrl: string; retrieveEmployees?: boolean; - retrieveDms?: boolean; + retrieveDMs?: boolean; retrievePosts?: boolean; } +export interface TBaseFetchCompanyParamsWide extends TBaseFetchCompanyParams { + retrieveEmployees: true; + retrieveDMs: true; + retrievePosts: true; +} + export type TFetchCompanyParams< T extends TBaseFetchCompanyParams = TBaseFetchCompanyParams, > = T & { - employeeRetrievalConfig?: T["retrieveEmployees"] extends true - ? TStCompanyEmployeeRetrievalConfig | undefined + employeesRetrievalConfig?: T["retrieveEmployees"] extends true + ? TStCompanyEmployeesRetrievalConfig | undefined : never; - dmRetrievalConfig?: T["retrieveDms"] extends true + dmsRetrievalConfig?: T["retrieveDMs"] extends true ? TLimitParams | undefined : never; - postRetrievalConfig?: T["retrievePosts"] extends true + postsRetrievalConfig?: T["retrievePosts"] extends true ? TLimitSinceParams | undefined : never; }; @@ -61,13 +67,19 @@ export type TFetchCompanyResult = (TParams["retrieveEmployees"] extends true ? { employees: ReadonlyArray } : Record) & - (TParams["retrieveDms"] extends true + (TParams["retrieveDMs"] extends true ? { dms: ReadonlyArray } : Record) & (TParams["retrievePosts"] extends true ? { posts: ReadonlyArray } : Record); +export type TFetchCompanyResultWide = TBaseCompany & { + employees?: ReadonlyArray; + dms?: ReadonlyArray; + posts?: ReadonlyArray; +}; + export interface TStCompanyEmployee { name: string; publicUrl: string; @@ -83,7 +95,7 @@ export interface TStCompanyDm { countryCode: string; } -export interface TStCompanyEmployeeRetrievalConfig extends TLimitParams { +export interface TStCompanyEmployeesRetrievalConfig extends TLimitParams { filter?: { firstName?: string; lastName?: string; diff --git a/src/types/actions/person.ts b/src/types/actions/person.ts index 55175fb..e62b6c8 100644 --- a/src/types/actions/person.ts +++ b/src/types/actions/person.ts @@ -31,16 +31,26 @@ export interface TBaseFetchPersonParams extends TBaseActionParams { retrieveReactions?: boolean; } +export interface TBaseFetchPersonParamsWide extends TBaseFetchPersonParams { + retrieveExperience: true; + retrieveEducation: true; + retrieveSkills: true; + retrieveLanguages: true; + retrievePosts: true; + retrieveComments: true; + retrieveReactions: true; +} + export type TFetchPersonParams< T extends TBaseFetchPersonParams = TBaseFetchPersonParams, > = T & { postsRetrievalConfig?: T["retrievePosts"] extends true ? TLimitSinceParams | undefined : never; - commentRetrievalConfig?: T["retrieveComments"] extends true + commentsRetrievalConfig?: T["retrieveComments"] extends true ? TLimitSinceParams | undefined : never; - reactionRetrievalConfig?: T["retrieveReactions"] extends true + reactionsRetrievalConfig?: T["retrieveReactions"] extends true ? TLimitSinceParams | undefined : never; }; @@ -61,27 +71,37 @@ type TBasePerson = Pick< export type TFetchPersonResult = TBasePerson & (TParams["retrieveExperience"] extends true - ? { experiences: ReadonlyArray } + ? { experiences: ReadonlyArray | undefined } : Record) & (TParams["retrieveEducation"] extends true - ? { education: ReadonlyArray } + ? { education: ReadonlyArray | undefined } : Record) & (TParams["retrieveSkills"] extends true - ? { skills: ReadonlyArray } + ? { skills: ReadonlyArray | undefined } : Record) & (TParams["retrieveLanguages"] extends true - ? { languages: ReadonlyArray } + ? { languages: ReadonlyArray | undefined } : Record) & (TParams["retrievePosts"] extends true - ? { posts: ReadonlyArray } + ? { posts: ReadonlyArray | undefined } : Record) & (TParams["retrieveComments"] extends true - ? { comments: ReadonlyArray } + ? { comments: ReadonlyArray | undefined } : Record) & (TParams["retrieveReactions"] extends true - ? { reactions: ReadonlyArray } + ? { reactions: ReadonlyArray | undefined } : Record); +export type TFetchPersonResultWide = TBasePerson & { + experiences?: ReadonlyArray; + education?: ReadonlyArray; + skills?: ReadonlyArray; + languages?: ReadonlyArray; + posts?: ReadonlyArray; + comments?: ReadonlyArray; + reactions?: ReadonlyArray; +}; + export interface TPersonExperience { position: string; companyName: string; diff --git a/src/types/config.ts b/src/types/config.ts index 2962a8e..64109a7 100644 --- a/src/types/config.ts +++ b/src/types/config.ts @@ -1,5 +1,5 @@ export interface TLinkedApiConfig { - apiToken: string; + linkedApiToken: string; identificationToken: string; workflowTimeout?: number; } diff --git a/src/types/errors.ts b/src/types/errors.ts index 3ee7c63..679a498 100644 --- a/src/types/errors.ts +++ b/src/types/errors.ts @@ -1,6 +1,8 @@ +import { TSupportedFunctionName } from "../core/workflow-restoration"; + /** * This error is thrown when a workflow fails to complete. - * @see {@link https://linkedapi.io/docs/account-api/actions-overview/#result-options} + * @see {@link https://linkedapi.io/docs/actions-overview/#result-options} */ export class LinkedApiWorkflowError extends Error { public reason: string; @@ -19,7 +21,7 @@ export class LinkedApiWorkflowError extends Error { /** * This error is thrown when a request fails. - * @see {@link https://linkedapi.io/docs/account-api/making-requests/#common-errors} + * @see {@link https://linkedapi.io/docs/making-requests/#common-errors} */ export class LinkedApiError extends Error { public type: string; @@ -33,3 +35,19 @@ export class LinkedApiError extends Error { this.details = details; } } + +/** + * This error is thrown when a workflow times out. + */ +export class LinkedApiWorkflowTimeoutError extends Error { + public readonly workflowId: string; + public readonly functionName: TSupportedFunctionName; + + constructor(workflowId: string, functionName: TSupportedFunctionName) { + super( + `Workflow ${workflowId} timed out. Use restoreWorkflow(${workflowId}, ${functionName}) to restore the workflow.`, + ); + this.workflowId = workflowId; + this.functionName = functionName; + } +} diff --git a/src/types/workflows.ts b/src/types/workflows.ts index 70bb780..b40c358 100644 --- a/src/types/workflows.ts +++ b/src/types/workflows.ts @@ -1,17 +1,27 @@ -export interface TWorkflowDefinition { +export interface TSingleActionWorkflowDefinition { actionType: string; [key: string]: unknown; } +export type TWorkflowDefinition = + | TSingleActionWorkflowDefinition + | TSingleActionWorkflowDefinition[]; + export type TWorkflowStatus = "running" | "completed" | "failed"; -export interface TWorkflowCompletion< +export type TWorkflowCompletion = + + | TWorkflowCompletionSingleAction + | TWorkflowCompletionSingleAction[]; + +export interface TWorkflowCompletionSingleAction< TResult extends TWorkflowData = TWorkflowData, > { data?: TResult; error?: TWorkflowActionError; actionType: string; - success?: boolean; + success: boolean; + label?: string; } export interface TWorkflowActionError { @@ -32,14 +42,26 @@ export interface TWorkflowResponse< failure?: TWorkflowFailure; } -export interface TWorkflowData { +export interface TWorkflowSingleData { [key: string]: unknown; - then?: TThenAction[]; + then?: TThen; } -export interface TThenAction { - actionType: string; +export type TWorkflowData = TWorkflowSingleData | TWorkflowSingleData[]; + +export interface TSingleActionResponse< + TResult extends TWorkflowData = TWorkflowData, +> { + data?: TResult; error?: TWorkflowActionError; - data: TWorkflowData; + actionType: string; success: boolean; + label?: string; } + +export type TActionResponse = + TSingleActionResponse; + +export type TThen = + | TActionResponse + | TActionResponse[];