Skip to content

Commit dd447d2

Browse files
1.2.1 (#5)
1 parent 786bdd4 commit dd447d2

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

42 files changed

+278
-281
lines changed

examples/custom-workflow.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ async function customWorkflowExample(): Promise<void> {
1111
console.log('🚀 Linked API custom workflow example starting...');
1212
const workflowId = await linkedapi.customWorkflow.execute({
1313
actionType: 'st.searchPeople',
14-
term: "John",
1514
limit: 3,
1615
filter: {
1716
locations: ["San Francisco"],
@@ -31,7 +30,7 @@ async function customWorkflowExample(): Promise<void> {
3130
const result = await linkedapi.customWorkflow.result(workflowId);
3231

3332
console.log('✅ Custom workflow executed successfully');
34-
console.log('🔍 Result: ', JSON.stringify(result, null, 2));
33+
console.log('🔍 Result: ', JSON.stringify(result.data, null, 2));
3534
} catch (error) {
3635
if (error instanceof LinkedApiError) {
3736
console.error('🚨 Linked API Error:', error.message);

examples/fetch-company.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ async function standardExample(linkedapi: LinkedApi): Promise<void> {
6363
}
6464

6565
async function salesNavigatorExample(linkedapi: LinkedApi): Promise<void> {
66-
const workflowId = await linkedapi.salesNavigatorFetchCompany.execute({
66+
const workflowId = await linkedapi.nvFetchCompany.execute({
6767
companyHashedUrl: 'https://www.linkedin.com/sales/company/1035',
6868
retrieveEmployees: true,
6969
retrieveDMs: true,
@@ -79,7 +79,7 @@ async function salesNavigatorExample(linkedapi: LinkedApi): Promise<void> {
7979
});
8080

8181
console.log('🔍 Sales Navigator workflow started: ', workflowId);
82-
const nvCompanyData = await linkedapi.salesNavigatorFetchCompany.result(workflowId);
82+
const nvCompanyData = await linkedapi.nvFetchCompany.result(workflowId);
8383
if (nvCompanyData.data) {
8484
const nvCompany = nvCompanyData.data;
8585
console.log('✅ Sales Navigator company page opened successfully');

examples/fetch-person.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -64,9 +64,9 @@ async function salesNavigatorExample(linkedapi: LinkedApi): Promise<void> {
6464
personHashedUrl: 'https://www.linkedin.com/in/abc123',
6565
};
6666

67-
const workflowId = await linkedapi.salesNavigatorFetchPerson.execute(fetchParams);
67+
const workflowId = await linkedapi.nvFetchPerson.execute(fetchParams);
6868
console.log('🔍 Workflow started: ', workflowId);
69-
const personResult = await linkedapi.salesNavigatorFetchPerson.result(workflowId);
69+
const personResult = await linkedapi.nvFetchPerson.result(workflowId);
7070
if (personResult.data) {
7171
const person = personResult.data;
7272
console.log('✅ Person page opened successfully');

examples/messaging.ts

Lines changed: 11 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -80,10 +80,10 @@ async function salesNavigatorSendMessage(linkedapi: LinkedApi, personUrl: string
8080
subject: 'Let\'s connect!',
8181
};
8282

83-
const workflowId = await linkedapi.salesNavigatorSendMessage.execute(nvMessageParams);
83+
const workflowId = await linkedapi.nvSendMessage.execute(nvMessageParams);
8484
console.log('🎯 Sales Navigator send message workflow started:', workflowId);
8585

86-
const nvMessageResult = await linkedapi.salesNavigatorSendMessage.result(workflowId);
86+
const nvMessageResult = await linkedapi.nvSendMessage.result(workflowId);
8787
if (nvMessageResult.errors.length > 0) {
8888
console.error('🚨 Errors:', JSON.stringify(nvMessageResult.errors, null, 2));
8989
} else {
@@ -100,10 +100,10 @@ async function salesNavigatorSyncConversation(linkedapi: LinkedApi, personUrl: s
100100
personUrl: personUrl,
101101
};
102102

103-
const workflowId = await linkedapi.salesNavigatorSyncConversation.execute(nvSyncParams);
103+
const workflowId = await linkedapi.nvSyncConversation.execute(nvSyncParams);
104104
console.log('🎯 Sales Navigator sync conversation workflow started:', workflowId);
105105

106-
const nvSyncResult = await linkedapi.salesNavigatorSyncConversation.result(workflowId);
106+
const nvSyncResult = await linkedapi.nvSyncConversation.result(workflowId);
107107
if (nvSyncResult.errors.length > 0) {
108108
console.error('🚨 Errors:', JSON.stringify(nvSyncResult.errors, null, 2));
109109
} else {
@@ -129,23 +129,20 @@ async function pollConversations(linkedapi: LinkedApi, standardPersonUrl: string
129129
},
130130
]);
131131

132-
if (!pollResponse.success) {
133-
console.error('❌ Failed to poll conversations:', pollResponse.error?.message);
134-
return;
135-
}
136-
137132
console.log('✅ Conversations polled successfully');
138-
console.log(`📊 Found ${pollResponse.result?.length || 0} conversations`);
133+
console.log(`📊 Found ${pollResponse.data?.length || 0} conversations`);
139134

140-
pollResponse.result?.forEach((conversation, index) => {
141-
console.log(`\n💬 Conversation ${index + 1}:`);
142-
console.log(` 👤 Person: ${conversation.personUrl}`);
135+
if (pollResponse.errors.length > 0) {
136+
console.error('🚨 Errors:', JSON.stringify(pollResponse.errors, null, 2));
137+
}
138+
pollResponse.data?.forEach((conversation) => {
139+
console.log(`\n💬 Conversation with ${conversation.personUrl}:`);
143140
console.log(` 🔗 Type: ${conversation.type === 'st' ? 'Standard' : 'Sales Navigator'}`);
144141
console.log(` 📬 Messages: ${conversation.messages.length}`);
145142

146143
if (conversation.messages.length > 0) {
147144
console.log(' 📝 Recent messages:');
148-
conversation.messages.slice(-3).forEach((message) => {
145+
conversation.messages.slice(0, 5).forEach((message) => {
149146
const senderIcon = message.sender === 'us' ? '👤' : '👋';
150147
console.log(` ${senderIcon} ${message.sender.toUpperCase()}: "${message.text}"`);
151148
console.log(` 🕐 ${message.time}`);

examples/search-companies.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -70,9 +70,9 @@ async function salesNavigatorExample(linkedapi: LinkedApi): Promise<void> {
7070
};
7171

7272
console.log('\n🎯 Searching companies with Sales Navigator...');
73-
const workflowId = await linkedapi.salesNavigatorSearchCompanies.execute(nvSearchParams);
73+
const workflowId = await linkedapi.nvSearchCompanies.execute(nvSearchParams);
7474
console.log('🔍 Sales Navigator workflow started:', workflowId);
75-
const nvResults = await linkedapi.salesNavigatorSearchCompanies.result(workflowId);
75+
const nvResults = await linkedapi.nvSearchCompanies.result(workflowId);
7676

7777
if (nvResults.data) {
7878
const results = nvResults.data;

examples/search-people.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -70,9 +70,9 @@ async function salesNavigatorExample(linkedapi: LinkedApi): Promise<void> {
7070
};
7171

7272
console.log('\n🎯 Searching people with Sales Navigator...');
73-
const workflowId = await linkedapi.salesNavigatorSearchPeople.execute(nvSearchParams);
73+
const workflowId = await linkedapi.nvSearchPeople.execute(nvSearchParams);
7474
console.log('🔍 Sales Navigator workflow started:', workflowId);
75-
const nvResults = await linkedapi.salesNavigatorSearchPeople.result(workflowId);
75+
const nvResults = await linkedapi.nvSearchPeople.result(workflowId);
7676

7777
if (nvResults.data) {
7878
const results = nvResults.data;

examples/statistics.ts

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -64,22 +64,18 @@ async function getRecentUsageStats(linkedapi: LinkedApi): Promise<void> {
6464
const endDate = new Date();
6565
const startDate = new Date(endDate.getTime() - 7 * 24 * 60 * 60 * 1000);
6666

67-
const statsResponse = await linkedapi.getApiUsageStats({
67+
const { data } = await linkedapi.getApiUsage({
6868
start: startDate.toISOString(),
6969
end: endDate.toISOString()
7070
});
7171

72-
if (!statsResponse.success) {
73-
console.error('❌ Failed to retrieve stats:', statsResponse.error?.message);
74-
return;
75-
}
72+
console.log('✅ API Usage retrieved successfully');
73+
console.log(`📈 Total actions executed: ${data?.length || 0}`);
7674

77-
console.log('✅ Usage statistics retrieved successfully');
78-
console.log(`📈 Total actions executed: ${statsResponse.result?.length || 0}`);
7975

80-
if (statsResponse.result && statsResponse.result.length > 0) {
76+
if (data && data.length > 0) {
8177
console.log('\n📋 Recent actions:');
82-
statsResponse.result.slice(-5).forEach((action) => {
78+
data.slice(0, 10).forEach((action) => {
8379
const status = action.success ? '✅' : '❌';
8480
const date = new Date(action.time).toLocaleDateString();
8581
const time = new Date(action.time).toLocaleTimeString();

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "linkedapi-node",
3-
"version": "1.2.0",
3+
"version": "1.2.1",
44
"description": "Official TypeScript SDK for Linked API",
55
"main": "dist/index.js",
66
"types": "dist/index.d.ts",

src/core/linked-api-http-client.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,21 +6,22 @@ import {
66
TLinkedApiResponse,
77
} from '../types';
88

9-
export function buildLinkedApiHttpClient(config: TLinkedApiConfig): HttpClient {
10-
return new LinkedApiHttpClient(config);
9+
export function buildLinkedApiHttpClient(config: TLinkedApiConfig, client: string): HttpClient {
10+
return new LinkedApiHttpClient(config, client);
1111
}
1212

1313
class LinkedApiHttpClient extends HttpClient {
1414
private readonly baseUrl: string;
1515
private readonly headers: Record<string, string>;
1616

17-
constructor(config: TLinkedApiConfig) {
17+
constructor(config: TLinkedApiConfig, client: string) {
1818
super();
1919
this.baseUrl = 'https://api.linkedapi.io';
2020
this.headers = {
2121
'Content-Type': 'application/json',
2222
'linked-api-token': config.linkedApiToken,
2323
'identification-token': config.identificationToken,
24+
client: client,
2425
};
2526
}
2627

src/core/operation.ts

Lines changed: 24 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -5,38 +5,37 @@ import {
55
LinkedApiWorkflowTimeoutError,
66
TLinkedApiErrorType,
77
TWorkflowCompletion,
8-
TWorkflowDefinition,
98
TWorkflowResponse,
109
TWorkflowRunningStatus,
1110
} from '../types';
1211

1312
import { pollWorkflowResult } from './poll-results';
1413

1514
export const OPERATION_NAME = {
16-
fetchPerson: 'fetchPerson',
17-
fetchCompany: 'fetchCompany',
18-
salesNavigatorFetchCompany: 'salesNavigatorFetchCompany',
19-
salesNavigatorFetchPerson: 'salesNavigatorFetchPerson',
20-
fetchPost: 'fetchPost',
21-
searchCompanies: 'searchCompanies',
22-
salesNavigatorSearchCompanies: 'salesNavigatorSearchCompanies',
23-
searchPeople: 'searchPeople',
24-
salesNavigatorSearchPeople: 'salesNavigatorSearchPeople',
15+
customWorkflow: 'customWorkflow',
2516
sendMessage: 'sendMessage',
2617
syncConversation: 'syncConversation',
27-
salesNavigatorSendMessage: 'salesNavigatorSendMessage',
28-
salesNavigatorSyncConversation: 'salesNavigatorSyncConversation',
29-
sendConnectionRequest: 'sendConnectionRequest',
3018
checkConnectionStatus: 'checkConnectionStatus',
19+
sendConnectionRequest: 'sendConnectionRequest',
3120
withdrawConnectionRequest: 'withdrawConnectionRequest',
3221
retrievePendingRequests: 'retrievePendingRequests',
3322
retrieveConnections: 'retrieveConnections',
3423
removeConnection: 'removeConnection',
24+
searchCompanies: 'searchCompanies',
25+
searchPeople: 'searchPeople',
26+
fetchPerson: 'fetchPerson',
27+
fetchCompany: 'fetchCompany',
28+
fetchPost: 'fetchPost',
3529
reactToPost: 'reactToPost',
3630
commentOnPost: 'commentOnPost',
3731
retrieveSSI: 'retrieveSSI',
3832
retrievePerformance: 'retrievePerformance',
39-
customWorkflow: 'customWorkflow',
33+
nvSendMessage: 'nvSendMessage',
34+
nvSyncConversation: 'nvSyncConversation',
35+
nvSearchCompanies: 'nvSearchCompanies',
36+
nvSearchPeople: 'nvSearchPeople',
37+
nvFetchCompany: 'nvFetchCompany',
38+
nvFetchPerson: 'nvFetchPerson',
4039
} as const;
4140
export type TOperationName = (typeof OPERATION_NAME)[keyof typeof OPERATION_NAME];
4241

@@ -45,52 +44,15 @@ export interface WaitForCompletionOptions {
4544
timeout?: number;
4645
}
4746

48-
export abstract class PredefinedOperation<TParams, TResult> {
47+
export abstract class Operation<TParams, TResult> {
4948
protected abstract readonly operationName: TOperationName;
5049
protected abstract readonly mapper: BaseMapper<TParams, TResult>;
5150

52-
private readonly operation: CustomWorkflowOperation;
53-
54-
constructor(httpClient: HttpClient) {
55-
this.operation = new CustomWorkflowOperation(httpClient);
56-
}
51+
constructor(private readonly httpClient: HttpClient) {}
5752

5853
public async execute(params: TParams): Promise<string> {
5954
const request = this.mapper.mapRequest(params);
60-
return this.operation.execute(request);
61-
}
62-
63-
public async result(
64-
workflowId: string,
65-
options: WaitForCompletionOptions = {},
66-
): Promise<TMappedResponse<TResult>> {
67-
try {
68-
const rawResult = await this.operation.result(workflowId, options);
69-
return this.mapper.mapResponse(rawResult);
70-
} catch (error) {
71-
if (error instanceof LinkedApiError && error.type === 'workflowTimeout') {
72-
throw new LinkedApiWorkflowTimeoutError(workflowId, this.operationName);
73-
}
74-
throw error;
75-
}
76-
}
77-
78-
public async status(
79-
workflowId: string,
80-
): Promise<TWorkflowRunningStatus | TMappedResponse<TResult>> {
81-
const result = await this.operation.status(workflowId);
82-
if (result === 'running') {
83-
return result;
84-
}
85-
return this.mapper.mapResponse(result);
86-
}
87-
}
88-
89-
export class CustomWorkflowOperation {
90-
constructor(private readonly httpClient: HttpClient) {}
91-
92-
public async execute(params: TWorkflowDefinition): Promise<string> {
93-
const response = await this.httpClient.post<TWorkflowResponse>(`/workflows`, params);
55+
const response = await this.httpClient.post<TWorkflowResponse>(`/workflows`, request);
9456
if (response.error) {
9557
throw new LinkedApiError(response.error.type as TLinkedApiErrorType, response.error.message);
9658
}
@@ -103,23 +65,26 @@ export class CustomWorkflowOperation {
10365
public async result(
10466
workflowId: string,
10567
options: WaitForCompletionOptions = {},
106-
): Promise<TWorkflowCompletion> {
68+
): Promise<TMappedResponse<TResult>> {
10769
try {
108-
return pollWorkflowResult(() => this.status(workflowId), options);
70+
return pollWorkflowResult<TMappedResponse<TResult>>(() => this.status(workflowId), options);
10971
} catch (error) {
11072
if (error instanceof LinkedApiError && error.type === 'workflowTimeout') {
111-
throw new LinkedApiWorkflowTimeoutError(workflowId, 'customWorkflow');
73+
throw new LinkedApiWorkflowTimeoutError(workflowId, this.operationName);
11274
}
11375
throw error;
11476
}
11577
}
11678

117-
public async status(workflowId: string): Promise<TWorkflowRunningStatus | TWorkflowCompletion> {
79+
public async status(
80+
workflowId: string,
81+
): Promise<TWorkflowRunningStatus | TMappedResponse<TResult>> {
11882
const workflowResult = await this.getWorkflowResult(workflowId);
11983
if (workflowResult.workflowStatus === 'running') {
12084
return workflowResult.workflowStatus;
12185
}
122-
return this.getCompletion(workflowResult);
86+
const result = this.getCompletion(workflowResult);
87+
return this.mapper.mapResponse(result);
12388
}
12489

12590
private async getWorkflowResult(workflowId: string): Promise<TWorkflowResponse> {

0 commit comments

Comments
 (0)