Skip to content

Commit 9aab887

Browse files
2 parents f9e8ae0 + 81bd4b9 commit 9aab887

8 files changed

Lines changed: 258 additions & 1 deletion

File tree

src/core/operation.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,11 @@ export const OPERATION_NAME = {
2525
removeConnection: 'removeConnection',
2626
searchCompanies: 'searchCompanies',
2727
searchPeople: 'searchPeople',
28+
searchJobs: 'searchJobs',
2829
fetchPerson: 'fetchPerson',
2930
fetchCompany: 'fetchCompany',
3031
fetchPost: 'fetchPost',
32+
fetchJob: 'fetchJob',
3133
reactToPost: 'reactToPost',
3234
commentOnPost: 'commentOnPost',
3335
createPost: 'createPost',

src/index.ts

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import {
77
CreatePost,
88
CustomWorkflow,
99
FetchCompany,
10+
FetchJob,
1011
FetchPerson,
1112
FetchPost,
1213
NvFetchCompany,
@@ -22,6 +23,7 @@ import {
2223
RetrievePerformance,
2324
RetrieveSSI,
2425
SearchCompanies,
26+
SearchJobs,
2527
SearchPeople,
2628
SendConnectionRequest,
2729
SendMessage,
@@ -98,9 +100,11 @@ class LinkedApi {
98100
this.removeConnection = new RemoveConnection(this.httpClient);
99101
this.searchCompanies = new SearchCompanies(this.httpClient);
100102
this.searchPeople = new SearchPeople(this.httpClient);
103+
this.searchJobs = new SearchJobs(this.httpClient);
101104
this.fetchCompany = new FetchCompany(this.httpClient);
102105
this.fetchPerson = new FetchPerson(this.httpClient);
103106
this.fetchPost = new FetchPost(this.httpClient);
107+
this.fetchJob = new FetchJob(this.httpClient);
104108
this.reactToPost = new ReactToPost(this.httpClient);
105109
this.commentOnPost = new CommentOnPost(this.httpClient);
106110
this.createPost = new CreatePost(this.httpClient);
@@ -125,9 +129,11 @@ class LinkedApi {
125129
this.removeConnection,
126130
this.searchCompanies,
127131
this.searchPeople,
132+
this.searchJobs,
128133
this.fetchCompany,
129134
this.fetchPerson,
130135
this.fetchPost,
136+
this.fetchJob,
131137
this.reactToPost,
132138
this.commentOnPost,
133139
this.createPost,
@@ -579,6 +585,32 @@ class LinkedApi {
579585
*/
580586
public fetchPost: FetchPost;
581587

588+
/**
589+
* Retrieve detailed information about a LinkedIn job.
590+
*
591+
* This method fetches comprehensive data about a specific LinkedIn job,
592+
* including company, location, salary, description, and application details.
593+
*
594+
* @param params - Parameters specifying the job URL
595+
* @returns Promise resolving to an object containing the job data
596+
*
597+
* @see {@link https://linkedapi.io/docs/action-st-open-job/ st.openJob Action Documentation}
598+
*
599+
* @example
600+
* ```typescript
601+
* const workflow = await linkedapi.fetchJob.execute({
602+
* jobUrl: "https://www.linkedin.com/jobs/view/4416248954/"
603+
* });
604+
*
605+
* const result = await linkedapi.fetchJob.result(workflow.workflowId);
606+
* if (result.data) {
607+
* console.log("Job title:", result.data.title);
608+
* console.log("Company:", result.data.companyName);
609+
* }
610+
* ```
611+
*/
612+
public fetchJob: FetchJob;
613+
582614
/**
583615
* Search for companies on LinkedIn using standard search.
584616
*
@@ -676,6 +708,37 @@ class LinkedApi {
676708
*/
677709
public searchPeople: SearchPeople;
678710

711+
/**
712+
* Search for jobs on LinkedIn using standard search.
713+
*
714+
* This method performs a job search on LinkedIn using the standard search interface.
715+
* You can filter by location, date posted, experience level, employment type, workplace type, and more.
716+
*
717+
* @param params - Search parameters including keywords, filters, and pagination options
718+
* @returns Promise resolving to an object containing an array of job search results
719+
*
720+
* @see {@link https://linkedapi.io/docs/action-st-search-jobs/ st.searchJobs Action Documentation}
721+
*
722+
* @example
723+
* ```typescript
724+
* const workflow = await linkedapi.searchJobs.execute({
725+
* term: "product manager",
726+
* filter: {
727+
* location: "San Francisco, California, United States",
728+
* experienceLevels: ["midSeniorLevel", "director"],
729+
* workplaceTypes: ["remote", "hybrid"]
730+
* },
731+
* limit: 25
732+
* });
733+
*
734+
* const jobsResult = await linkedapi.searchJobs.result(workflow.workflowId);
735+
* if (jobsResult.data) {
736+
* console.log("Found jobs:", jobsResult.data.length);
737+
* }
738+
* ```
739+
*/
740+
public searchJobs: SearchJobs;
741+
679742
/**
680743
* Search for people on LinkedIn using Sales Navigator.
681744
*

src/operations/fetch-job.ts

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import { Operation, TOperationName } from '../core';
2+
import { TActionConfig, ThenWorkflowMapper, TResponseMappingConfig } from '../mappers';
3+
import { TBaseFetchJobParams, TFetchJobResult } from '../types';
4+
5+
export class FetchJob extends Operation<TBaseFetchJobParams, TFetchJobResult> {
6+
public override readonly operationName: TOperationName = 'fetchJob';
7+
protected override readonly mapper = new FetchJobMapper();
8+
}
9+
10+
const FETCH_JOB_ACTIONS: TActionConfig[] = [];
11+
12+
const RESPONSE_MAPPINGS: TResponseMappingConfig[] = [];
13+
14+
export class FetchJobMapper extends ThenWorkflowMapper<TBaseFetchJobParams, TFetchJobResult> {
15+
constructor() {
16+
super({
17+
actionConfigs: FETCH_JOB_ACTIONS,
18+
responseMappings: RESPONSE_MAPPINGS,
19+
baseActionType: 'st.openJob',
20+
defaultParams: {
21+
basicInfo: true,
22+
},
23+
});
24+
}
25+
}

src/operations/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,9 @@ export * from './nv-sync-conversation';
1010
export * from './nv-fetch-person';
1111
export * from './nv-search-companies';
1212
export * from './fetch-post';
13+
export * from './fetch-job';
1314
export * from './search-people';
15+
export * from './search-jobs';
1416
export * from './nv-search-people';
1517
export * from './send-connection-request';
1618
export * from './check-connection-status';

src/operations/search-jobs.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import { Operation, TOperationName } from '../core';
2+
import { ArrayWorkflowMapper } from '../mappers/array-workflow-mapper';
3+
import { TSearchJobResult, TSearchJobsParams } from '../types';
4+
5+
export class SearchJobs extends Operation<TSearchJobsParams, TSearchJobResult[]> {
6+
public override readonly operationName: TOperationName = 'searchJobs';
7+
protected override readonly mapper = new ArrayWorkflowMapper<TSearchJobsParams, TSearchJobResult>(
8+
'st.searchJobs',
9+
);
10+
}

src/types/actions/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
export * from './account';
22
export * from './company';
33
export * from './connection';
4+
export * from './job';
45
export * from './message';
56
export * from './person';
67
export * from './post';

src/types/actions/job.ts

Lines changed: 152 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,152 @@
1+
import { TBaseActionParams } from '../params';
2+
3+
export const JOB_DATE_POSTED = {
4+
anyTime: 'anyTime',
5+
past24Hours: 'past24Hours',
6+
pastWeek: 'pastWeek',
7+
pastMonth: 'pastMonth',
8+
} as const;
9+
export type TJobDatePosted = (typeof JOB_DATE_POSTED)[keyof typeof JOB_DATE_POSTED];
10+
11+
export const JOB_EXPERIENCE_LEVEL = {
12+
internship: 'internship',
13+
entryLevel: 'entryLevel',
14+
associate: 'associate',
15+
midSeniorLevel: 'midSeniorLevel',
16+
director: 'director',
17+
executive: 'executive',
18+
} as const;
19+
export type TJobExperienceLevel = (typeof JOB_EXPERIENCE_LEVEL)[keyof typeof JOB_EXPERIENCE_LEVEL];
20+
21+
export const JOB_EMPLOYMENT_TYPE = {
22+
fullTime: 'fullTime',
23+
partTime: 'partTime',
24+
contract: 'contract',
25+
temporary: 'temporary',
26+
volunteer: 'volunteer',
27+
internship: 'internship',
28+
other: 'other',
29+
} as const;
30+
export type TJobEmploymentType = (typeof JOB_EMPLOYMENT_TYPE)[keyof typeof JOB_EMPLOYMENT_TYPE];
31+
32+
export const JOB_WORKPLACE_TYPE = {
33+
onSite: 'onSite',
34+
remote: 'remote',
35+
hybrid: 'hybrid',
36+
} as const;
37+
export type TJobWorkplaceType = (typeof JOB_WORKPLACE_TYPE)[keyof typeof JOB_WORKPLACE_TYPE];
38+
39+
export const JOB_SALARY_PERIOD = {
40+
yearly: 'yearly',
41+
monthly: 'monthly',
42+
hourly: 'hourly',
43+
} as const;
44+
export type TJobSalaryPeriod = (typeof JOB_SALARY_PERIOD)[keyof typeof JOB_SALARY_PERIOD];
45+
46+
export const JOB_CURRENCY = {
47+
usd: 'usd',
48+
eur: 'eur',
49+
gbp: 'gbp',
50+
inr: 'inr',
51+
cad: 'cad',
52+
aud: 'aud',
53+
nzd: 'nzd',
54+
hkd: 'hkd',
55+
sgd: 'sgd',
56+
jpy: 'jpy',
57+
cny: 'cny',
58+
chf: 'chf',
59+
sek: 'sek',
60+
nok: 'nok',
61+
dkk: 'dkk',
62+
pln: 'pln',
63+
czk: 'czk',
64+
huf: 'huf',
65+
ron: 'ron',
66+
brl: 'brl',
67+
mxn: 'mxn',
68+
ars: 'ars',
69+
zar: 'zar',
70+
aed: 'aed',
71+
sar: 'sar',
72+
ils: 'ils',
73+
try: 'try',
74+
rub: 'rub',
75+
uah: 'uah',
76+
krw: 'krw',
77+
thb: 'thb',
78+
idr: 'idr',
79+
myr: 'myr',
80+
php: 'php',
81+
vnd: 'vnd',
82+
ngn: 'ngn',
83+
twd: 'twd',
84+
} as const;
85+
export type TJobCurrency = (typeof JOB_CURRENCY)[keyof typeof JOB_CURRENCY];
86+
87+
export interface TJobSalary {
88+
currency: TJobCurrency | null;
89+
minAmount: number | null;
90+
maxAmount: number | null;
91+
period: TJobSalaryPeriod | null;
92+
}
93+
94+
export interface TJobFilter {
95+
location?: string;
96+
datePosted?: TJobDatePosted;
97+
experienceLevels?: TJobExperienceLevel[];
98+
employmentTypes?: TJobEmploymentType[];
99+
workplaceTypes?: TJobWorkplaceType[];
100+
companies?: string[];
101+
industries?: string[];
102+
jobFunctions?: string[];
103+
easyApply?: boolean;
104+
hasVerifications?: boolean;
105+
under10Applicants?: boolean;
106+
inYourNetwork?: boolean;
107+
fairChanceEmployer?: boolean;
108+
}
109+
110+
export interface TSearchJobsParams extends TBaseActionParams {
111+
term?: string;
112+
limit?: number;
113+
filter?: TJobFilter;
114+
customSearchUrl?: string;
115+
}
116+
117+
export interface TSearchJobResult {
118+
jobId: string | null;
119+
jobUrl: string | null;
120+
title: string;
121+
companyName: string | null;
122+
location: string | null;
123+
workplaceType: string | null;
124+
salary: TJobSalary | null;
125+
easyApply: boolean;
126+
isPromoted: boolean;
127+
}
128+
129+
export interface TBaseFetchJobParams extends TBaseActionParams {
130+
jobUrl: string;
131+
}
132+
133+
export type TFetchJobParams = TBaseFetchJobParams;
134+
135+
export interface TJob {
136+
jobId: string;
137+
jobUrl: string;
138+
title: string;
139+
companyName: string | null;
140+
companyUrl: string | null;
141+
location: string | null;
142+
postedDate: string | null;
143+
applicantsCount: number | null;
144+
workplaceType: string | null;
145+
employmentType: string | null;
146+
salary: TJobSalary | null;
147+
description: string | null;
148+
applyUrl: string | null;
149+
easyApply: boolean;
150+
}
151+
152+
export type TFetchJobResult = TJob;

src/types/errors.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,10 @@ import { TOperationName } from '../core';
1717
* - notPending (withdrawConnectionRequest))
1818
* - retrievingNotAllowed (retrieveConnections, fetchCompany, nvFetchCompany)
1919
* - connectionNotFound (removeConnection)
20-
* - searchingNotAllowed (searchCompanies, searchPeople, nvSearchCompanies, nvSearchPeople)
20+
* - searchingNotAllowed (searchCompanies, searchPeople, searchJobs, nvSearchCompanies, nvSearchPeople)
2121
* - companyNotFound (fetchCompany, nvFetchCompany)
2222
* - postNotFound (fetchPost, reactToPost, commentOnPost)
23+
* - jobNotFound (fetchJob)
2324
* - commentingNotAllowed (commentOnPost)
2425
* - noPostingPermission (createPost, reactToPost, commentOnPost)
2526
* - noSalesNavigator (nvSendMessage, nvSyncConversation, nvSearchCompanies, nvSearchPeople, nvFetchCompany, nvFetchPerson)
@@ -41,6 +42,7 @@ export const LINKED_API_ACTION_ERROR = {
4142
searchingNotAllowed: 'searchingNotAllowed',
4243
companyNotFound: 'companyNotFound',
4344
postNotFound: 'postNotFound',
45+
jobNotFound: 'jobNotFound',
4446
commentingNotAllowed: 'commentingNotAllowed',
4547
noPostingPermission: 'noPostingPermission',
4648
noSalesNavigator: 'noSalesNavigator',

0 commit comments

Comments
 (0)