forked from NangoHQ/nango
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
474a2d7
commit 2b24195
Showing
20 changed files
with
1,327 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
--- | ||
title: 'Lever API Integration Template' | ||
sidebarTitle: 'Lever' | ||
--- | ||
|
||
## Get started with the Lever template | ||
|
||
<Card title="How to use integration templates" | ||
href="/integration-templates/overview#how-to-use-integration-templates" | ||
icon="book-open"> | ||
Learn how to use integration templates in Nango | ||
</Card> | ||
|
||
<Card title="Get the Lever template" | ||
href="https://github.com/NangoHQ/nango/tree/master/integration-templates/lever" | ||
icon="github"> | ||
Get the latest version of the Lever integration template from GitHub | ||
</Card> | ||
|
||
## Need help with the template? | ||
Please reach out on the [Slack community](https://nango.dev/slack), we are very active there and happy to help! |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
import type { NangoAction, LeverOpportunityNote } from './models'; | ||
|
||
interface LeverCreateNoteInput { | ||
opportunityId: string; | ||
perform_as?: string; | ||
note_id?: string; | ||
value: string; | ||
secret?: boolean; | ||
score?: number; | ||
notifyFollowers?: boolean; | ||
createdAt?: number; | ||
} | ||
|
||
export default async function runAction(nango: NangoAction, input: LeverCreateNoteInput): Promise<LeverOpportunityNote> { | ||
if (!input.opportunityId) { | ||
throw new nango.ActionError({ | ||
message: 'opportunity id is a required field' | ||
}); | ||
} else if (!input.value) { | ||
throw new nango.ActionError({ | ||
message: 'value of the note is a required field' | ||
}); | ||
} | ||
|
||
const endpoint = `/v1/opportunities/${input.opportunityId}/notes`; | ||
|
||
try { | ||
const postData = { | ||
value: input.value, | ||
secret: input.secret, | ||
score: input.score, | ||
notifyFollowers: input.notifyFollowers, | ||
createdAt: input.createdAt | ||
}; | ||
|
||
const params = Object.entries({ | ||
...(input.perform_as ? { perform_as: input.perform_as } : {}), | ||
...(input.note_id ? { note_id: input.note_id } : {}) | ||
}) | ||
.map(([key, value]) => `${encodeURIComponent(key)}=${encodeURIComponent(value)}`) | ||
.join('&'); | ||
|
||
const urlWithParams = `${endpoint}${params ? `?${params}` : ''}`; | ||
|
||
const resp = await nango.post({ | ||
endpoint: urlWithParams, | ||
data: postData | ||
}); | ||
|
||
return { | ||
id: resp.data.data.id, | ||
text: resp.data.data.text, | ||
fields: resp.data.data.fields, | ||
user: resp.data.data.user, | ||
secret: resp.data.data.secret, | ||
completedAt: resp.data.data.completedAt, | ||
createdAt: resp.data.data.createdAt, | ||
deletedAt: resp.data.data.deletedAt | ||
}; | ||
} catch (error: any) { | ||
throw new Error(`Error in runAction: ${error.message}`); | ||
} | ||
} |
113 changes: 113 additions & 0 deletions
113
integration-templates/lever/lever-create-opportunity.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,113 @@ | ||
import type { NangoAction, LeverOpportunity } from './models'; | ||
|
||
interface PhoneEntry { | ||
value?: string; | ||
type?: string; | ||
} | ||
interface ArchievedEntry { | ||
archivedAt?: number; | ||
reason?: string; | ||
} | ||
interface LeverCreateNoteInput { | ||
perform_as: string; | ||
parse?: boolean; | ||
perform_as_posting_owner?: boolean; | ||
name?: string; | ||
headline?: string; | ||
stage?: string; | ||
location?: string; | ||
phones?: PhoneEntry[]; | ||
emails?: string; | ||
links?: string[]; | ||
tags?: string[]; | ||
sources?: string[]; | ||
origin?: string; | ||
owner?: string; | ||
followers?: string[]; | ||
postings?: string[]; | ||
createdAt?: number; | ||
archived?: ArchievedEntry; | ||
contact?: string[]; | ||
} | ||
|
||
export default async function runAction(nango: NangoAction, input: LeverCreateNoteInput): Promise<LeverOpportunity> { | ||
if (!input.perform_as) { | ||
throw new nango.ActionError({ | ||
message: 'perform_as is the only required field' | ||
}); | ||
} | ||
|
||
const endpoint = `/v1/opportunities?perform_as=${input.perform_as}`; | ||
|
||
try { | ||
const postData = { | ||
name: input.name, | ||
headline: input.headline, | ||
stage: input.stage, | ||
location: input.location, | ||
phones: input.phones, | ||
emails: input.emails, | ||
links: input.links, | ||
tags: input.tags, | ||
sources: input.sources, | ||
origin: input.origin, | ||
owner: input.owner, | ||
followers: input.followers, | ||
postings: input.postings, | ||
createdAt: input.createdAt, | ||
archived: input.archived, | ||
contact: input.contact | ||
}; | ||
|
||
const queryParams = Object.entries({ | ||
...(input.parse ? { parse: input.parse } : {}), | ||
...(input.perform_as_posting_owner ? { note_id: input.perform_as_posting_owner } : {}) | ||
}) | ||
.map(([key, value]) => `${encodeURIComponent(key)}=${encodeURIComponent(value)}`) | ||
.join('&'); | ||
|
||
const params = queryParams ? `&${queryParams}` : ''; | ||
const urlWithParams = `${endpoint}${params}`; | ||
|
||
const resp = await nango.post({ | ||
endpoint: urlWithParams, | ||
data: postData | ||
}); | ||
|
||
return { | ||
id: resp.data.data.id, | ||
name: resp.data.data.name, | ||
headline: resp.data.data.headline, | ||
contact: resp.data.data.contact, | ||
emails: resp.data.data.emails, | ||
phones: resp.data.data.phones, | ||
confidentiality: resp.data.data.confidentiality, | ||
location: resp.data.data.location, | ||
links: resp.data.data.links, | ||
archived: resp.data.data.archived, | ||
createdAt: resp.data.data.createdAt, | ||
updatedAt: resp.data.data.updatedAt, | ||
lastInteractionAt: resp.data.data.lastInteractionAt, | ||
lastAdvancedAt: resp.data.data.lastAdvancedAt, | ||
snoozedUntil: resp.data.data.snoozedUntil, | ||
archivedAt: resp.data.data.archivedAt, | ||
archiveReason: resp.data.data.archiveReason, | ||
stage: resp.data.data.stage, | ||
stageChanges: resp.data.data.stageChanges, | ||
owner: resp.data.data.owner, | ||
tags: resp.data.data.tags, | ||
sources: resp.data.data.sources, | ||
origin: resp.data.data.origin, | ||
sourcedBy: resp.data.data.sourcedBy, | ||
applications: resp.data.data.applications, | ||
resume: resp.data.data.resume, | ||
followers: resp.data.data.followers, | ||
urls: resp.data.data.urls, | ||
dataProtection: resp.data.data.dataProtection, | ||
isAnonymized: resp.data.data.isAnonymized, | ||
opportunityLocation: resp.data.data.opportunityLocation | ||
}; | ||
} catch (error: any) { | ||
throw new Error(`Error in runAction: ${error.message}`); | ||
} | ||
} |
82 changes: 82 additions & 0 deletions
82
integration-templates/lever/lever-opportunities-applications.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,82 @@ | ||
import type { LeverOpportunityApplication, NangoSync } from './models'; | ||
|
||
const LIMIT = 100; | ||
|
||
export default async function fetchData(nango: NangoSync) { | ||
let totalRecords = 0; | ||
|
||
try { | ||
const opportunities: any[] = await getAllOpportunities(nango); | ||
|
||
for (const opportunity of opportunities) { | ||
const endpoint = `/v1/opportunities/${opportunity.id}/applications`; | ||
|
||
const config = { | ||
paginate: { | ||
type: 'cursor', | ||
cursor_path_in_response: 'next', | ||
cursor_name_in_request: 'offset', | ||
limit_name_in_request: 'limit', | ||
response_path: 'data', | ||
limit: LIMIT | ||
} | ||
}; | ||
for await (const application of nango.paginate({ ...config, endpoint })) { | ||
const mappedApplication: LeverOpportunityApplication[] = application.map(mapApplication) || []; | ||
// Save applications | ||
const batchSize: number = mappedApplication.length; | ||
totalRecords += batchSize; | ||
await nango.log(`Saving batch of ${batchSize} application(s) for opportunity ${opportunity.id} (total application(s): ${totalRecords})`); | ||
await nango.batchSave(mappedApplication, 'LeverOpportunityApplication'); | ||
} | ||
} | ||
} catch (error: any) { | ||
throw new Error(`Error in fetchData: ${error.message}`); | ||
} | ||
} | ||
|
||
async function getAllOpportunities(nango: NangoSync) { | ||
const records: any[] = []; | ||
const config = { | ||
endpoint: '/v1/opportunities', | ||
paginate: { | ||
type: 'cursor', | ||
cursor_path_in_response: 'next', | ||
cursor_name_in_request: 'offset', | ||
limit_name_in_request: 'limit', | ||
response_path: 'data', | ||
limit: LIMIT | ||
} | ||
}; | ||
|
||
for await (const recordBatch of nango.paginate(config)) { | ||
records.push(...recordBatch); | ||
} | ||
|
||
return records; | ||
} | ||
|
||
function mapApplication(application: any): LeverOpportunityApplication { | ||
return { | ||
id: application.id, | ||
opportunityId: application.opportunityId, | ||
candidateId: application.candidateId, | ||
createdAt: application.createdAt, | ||
type: application.type, | ||
posting: application.posting, | ||
postingHiringManager: application.postingHiringManager, | ||
postingOwner: application.postingOwner, | ||
user: application.user, | ||
name: application.name, | ||
email: application.email, | ||
phone: application.phone, | ||
requisitionForHire: application.requisitionForHire, | ||
ownerId: application.ownerId, | ||
hiringManager: application.hiringManager, | ||
company: application.company, | ||
links: application.links, | ||
comments: application.comments, | ||
customQuestions: application.customQuestions, | ||
archived: application.archived | ||
}; | ||
} |
75 changes: 75 additions & 0 deletions
75
integration-templates/lever/lever-opportunities-feedbacks.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,75 @@ | ||
import type { LeverOpportunityFeedback, NangoSync } from './models'; | ||
|
||
const LIMIT = 100; | ||
|
||
export default async function fetchData(nango: NangoSync) { | ||
let totalRecords = 0; | ||
|
||
try { | ||
const opportunities: any[] = await getAllOpportunities(nango); | ||
|
||
for (const opportunity of opportunities) { | ||
const endpoint = `/v1/opportunities/${opportunity.id}/feedback`; | ||
|
||
const config = { | ||
paginate: { | ||
type: 'cursor', | ||
cursor_path_in_response: 'next', | ||
cursor_name_in_request: 'offset', | ||
limit_name_in_request: 'limit', | ||
response_path: 'data', | ||
limit: LIMIT | ||
} | ||
}; | ||
for await (const feedback of nango.paginate({ ...config, endpoint })) { | ||
const mappedFeedback: LeverOpportunityFeedback[] = feedback.map(mapFeedback) || []; | ||
// Save feedbacks | ||
const batchSize: number = mappedFeedback.length; | ||
totalRecords += batchSize; | ||
await nango.log(`Saving batch of ${batchSize} feedback(s) for opportunity ${opportunity.id} (total feedback(s): ${totalRecords})`); | ||
await nango.batchSave(mappedFeedback, 'LeverOpportunityFeedback'); | ||
} | ||
} | ||
} catch (error: any) { | ||
throw new Error(`Error in fetchData: ${error.message}`); | ||
} | ||
} | ||
|
||
async function getAllOpportunities(nango: NangoSync) { | ||
const records: any[] = []; | ||
const config = { | ||
endpoint: '/v1/opportunities', | ||
paginate: { | ||
type: 'cursor', | ||
cursor_path_in_response: 'next', | ||
cursor_name_in_request: 'offset', | ||
limit_name_in_request: 'limit', | ||
response_path: 'data', | ||
limit: LIMIT | ||
} | ||
}; | ||
|
||
for await (const recordBatch of nango.paginate(config)) { | ||
records.push(...recordBatch); | ||
} | ||
|
||
return records; | ||
} | ||
|
||
function mapFeedback(feedback: any): LeverOpportunityFeedback { | ||
return { | ||
id: feedback.id, | ||
type: feedback.type, | ||
text: feedback.text, | ||
instructions: feedback.instructions, | ||
fields: feedback.fields, | ||
baseTemplateId: feedback.baseTemplateId, | ||
interview: feedback.interview, | ||
panel: feedback.panel, | ||
user: feedback.user, | ||
createdAt: feedback.createdAt, | ||
completedAt: feedback.completedAt, | ||
updatedAt: feedback.updatedAt, | ||
deletedAt: feedback.deletedAt | ||
}; | ||
} |
Oops, something went wrong.