Skip to content

Commit

Permalink
feat: minor improvements to diffbot, predictleads, and proxycurl
Browse files Browse the repository at this point in the history
  • Loading branch information
transitive-bullshit committed Jun 10, 2024
1 parent 3f70516 commit f1db6dc
Show file tree
Hide file tree
Showing 5 changed files with 86 additions and 42 deletions.
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@
"scripts": {
"preinstall": "npx only-allow pnpm",
"build": "tsup",
"dev": "tsup --watch",
"clean": "del dist",
"prebuild": "run-s clean",
"predev": "run-s clean",
Expand Down
7 changes: 6 additions & 1 deletion src/services/diffbot-client.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import type { Simplify } from 'type-fest'
import defaultKy, { type KyInstance } from 'ky'
import pThrottle from 'p-throttle'
import { z } from 'zod'
Expand Down Expand Up @@ -657,6 +658,8 @@ export namespace diffbot {
'interests'
)
}

export type PrunedEntity = Simplify<ReturnType<typeof pruneEntity>>
}

/**
Expand Down Expand Up @@ -747,7 +750,9 @@ export class DiffbotClient extends AIFunctionsProvider {
threshold: true
})
})
async enhanceEntity(opts: diffbot.EnhanceEntityOptions) {
async enhanceEntity(
opts: diffbot.EnhanceEntityOptions
): Promise<diffbot.PrunedEntity[]> {
const res = await this.kyKnowledgeGraph
.get('kg/v3/enhance', {
searchParams: sanitizeSearchParams({
Expand Down
2 changes: 1 addition & 1 deletion src/services/predict-leads-client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -532,7 +532,7 @@ export class PredictLeadsClient extends AIFunctionsProvider {
'Returns basic information about a company given its `domain` like location, name, stock ticker, description, etc.',
inputSchema: predictleads.CompanyParamsSchema
})
async company(domainOrOpts: string | predictleads.CompanyParams) {
async getCompany(domainOrOpts: string | predictleads.CompanyParams) {
const opts =
typeof domainOrOpts === 'string' ? { domain: domainOrOpts } : domainOrOpts
const { domain } = opts
Expand Down
94 changes: 62 additions & 32 deletions src/services/proxycurl-client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import pThrottle from 'p-throttle'
import { z } from 'zod'

import { aiFunction, AIFunctionsProvider } from '../fns.js'
import { assert, getEnv, throttleKy } from '../utils.js'
import { assert, getEnv, sanitizeSearchParams, throttleKy } from '../utils.js'

// All proxycurl types are auto-generated from their openapi spec
export namespace proxycurl {
Expand All @@ -25,35 +25,48 @@ export namespace proxycurl {
])
export type CompanyType = z.infer<typeof CompanyTypeSchema>

export const OptionalFieldSchema = z.enum(['exclude', 'include']).optional()
export type OptionalField = z.infer<typeof OptionalFieldSchema>

export const OptionalEnrichFieldSchema = z.enum(['skip', 'enrich']).optional()
export type OptionalEnrichField = z.infer<typeof OptionalEnrichFieldSchema>

export const UseCacheSchema = z.enum(['if-present', 'if-recent']).optional()
export type UseCache = z.infer<typeof UseCacheSchema>

export const FallbackToCacheSchema = z.enum(['on-error', 'never']).optional()
export type FallbackToCache = z.infer<typeof FallbackToCacheSchema>

export const CompanyProfileEndpointParamsQueryClassSchema = z.object({
acquisitions: z.string().optional(),
categories: z.string().optional(),
exit_data: z.string().optional(),
extra: z.string().optional(),
fallback_to_cache: z.string().optional(),
funding_data: z.string().optional(),
resolve_numeric_id: z.string().optional(),
url: z.string(),
use_cache: z.string().optional()
acquisitions: OptionalFieldSchema,
categories: OptionalFieldSchema,
exit_data: OptionalFieldSchema,
extra: OptionalFieldSchema,
funding_data: OptionalFieldSchema,
resolve_numeric_id: z.boolean().optional(),
fallback_to_cache: FallbackToCacheSchema,
use_cache: UseCacheSchema
})
export type CompanyProfileEndpointParamsQueryClass = z.infer<
typeof CompanyProfileEndpointParamsQueryClassSchema
>

export const PersonProfileEndpointParamsQueryClassSchema = z.object({
extra: z.string().optional(),
facebook_profile_id: z.string().optional(),
// requires one of `facebook_profile_url`, `linkedin_profile_url`, or `twitter_profile_url`
facebook_profile_url: z.string().optional(),
fallback_to_cache: z.string().optional(),
github_profile_id: z.string().optional(),
inferred_salary: z.string().optional(),
linkedin_profile_url: z.string().optional(),
personal_contact_number: z.string().optional(),
personal_email: z.string().optional(),
skills: z.string().optional(),
twitter_profile_id: z.string().optional(),
twitter_profile_url: z.string().optional(),
use_cache: z.string().optional()
facebook_profile_id: OptionalFieldSchema,
twitter_profile_id: OptionalFieldSchema,
extra: OptionalFieldSchema,
github_profile_id: OptionalFieldSchema,
inferred_salary: OptionalFieldSchema,
personal_contact_number: OptionalFieldSchema,
personal_email: OptionalFieldSchema,
skills: OptionalFieldSchema,
fallback_to_cache: FallbackToCacheSchema,
use_cache: UseCacheSchema
})
export type PersonProfileEndpointParamsQueryClass = z.infer<
typeof PersonProfileEndpointParamsQueryClassSchema
Expand All @@ -63,12 +76,12 @@ export namespace proxycurl {
company_domain: z
.string()
.describe('The domain URL of the company the person works at'),
enrich_profile: z.string().optional(),
first_name: z.string(),
last_name: z.string().optional(),
location: z.string().optional(),
similarity_checks: z.string().optional(),
title: z.string().optional()
title: z.string().optional(),
enrich_profile: OptionalEnrichFieldSchema
})
export type PersonLookupEndpointParamsQueryClass = z.infer<
typeof PersonLookupEndpointParamsQueryClassSchema
Expand All @@ -77,7 +90,7 @@ export namespace proxycurl {
export const RoleLookupEndpointParamsQueryClassSchema = z.object({
company_name: z.string(),
role: z.string(),
enrich_profile: z.string().optional()
enrich_profile: OptionalEnrichFieldSchema
})
export type RoleLookupEndpointParamsQueryClass = z.infer<
typeof RoleLookupEndpointParamsQueryClassSchema
Expand All @@ -87,15 +100,15 @@ export namespace proxycurl {
company_domain: z.string().optional(),
company_location: z.string().optional(),
company_name: z.string().optional(),
enrich_profile: z.string().optional()
enrich_profile: OptionalEnrichFieldSchema
})
export type CompanyLookupEndpointParamsQueryClass = z.infer<
typeof CompanyLookupEndpointParamsQueryClassSchema
>

export const ReverseEmailLookupEndpointParamsQueryClassSchema = z.object({
email: z.string(),
enrich_profile: z.string().optional(),
enrich_profile: OptionalEnrichFieldSchema,
lookup_depth: z.string().optional()
})
export type ReverseEmailLookupEndpointParamsQueryClass = z.infer<
Expand Down Expand Up @@ -2068,7 +2081,12 @@ export class ProxycurlClient extends AIFunctionsProvider {
) {
return this.ky
.get('api/linkedin/company', {
searchParams: { ...opts }
searchParams: sanitizeSearchParams({
funding_data: 'include',
exit_data: 'include',
extra_data: 'include',
...opts
})
})
.json<proxycurl.ResultProfile>()
}
Expand All @@ -2084,7 +2102,7 @@ export class ProxycurlClient extends AIFunctionsProvider {
) {
return this.ky
.get('api/v2/linkedin', {
searchParams: { ...opts }
searchParams: sanitizeSearchParams(opts)
})
.json<proxycurl.PublicPerson>()
}
Expand All @@ -2100,7 +2118,10 @@ export class ProxycurlClient extends AIFunctionsProvider {
) {
return this.ky
.get('api/linkedin/profile/resolve', {
searchParams: { ...opts }
searchParams: sanitizeSearchParams({
enrich_profile: 'enrich',
...opts
})
})
.json<proxycurl.PublicPerson>()
}
Expand All @@ -2116,7 +2137,10 @@ export class ProxycurlClient extends AIFunctionsProvider {
) {
return this.ky
.get('api/linkedin/profile/resolve/email', {
searchParams: { ...opts }
searchParams: sanitizeSearchParams({
enrich_profile: 'enrich',
...opts
})
})
.json<proxycurl.ReverseEmailUrlEnrichResult>()
}
Expand All @@ -2132,7 +2156,10 @@ export class ProxycurlClient extends AIFunctionsProvider {
) {
return this.ky
.get('api/find/company/role/', {
searchParams: { ...opts }
searchParams: sanitizeSearchParams({
enrich_profile: 'enrich',
...opts
})
})
.json<proxycurl.PublicPerson>()
}
Expand All @@ -2148,7 +2175,10 @@ export class ProxycurlClient extends AIFunctionsProvider {
) {
return this.ky
.get('api/linkedin/company/resolve', {
searchParams: { ...opts }
searchParams: sanitizeSearchParams({
enrich_profile: 'enrich',
...opts
})
})
.json<proxycurl.ResultProfile>()
}
Expand All @@ -2162,7 +2192,7 @@ export class ProxycurlClient extends AIFunctionsProvider {
async searchCompanies(opts: proxycurl.CompanySearchEndpointParamsQueryClass) {
return this.ky
.get('api/v2/search/company', {
searchParams: { ...opts }
searchParams: sanitizeSearchParams(opts)
})
.json<proxycurl.CompanySearchResult>()
}
Expand All @@ -2176,7 +2206,7 @@ export class ProxycurlClient extends AIFunctionsProvider {
async searchPeople(opts: proxycurl.PersonSearchEndpointParamsQueryClass) {
return this.ky
.get('api/v2/search/person/', {
searchParams: { ...opts }
searchParams: sanitizeSearchParams(opts)
})
.json<proxycurl.PersonSearchResult>()
}
Expand Down
24 changes: 16 additions & 8 deletions src/url-utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import QuickLRU from 'quick-lru'
import { hashObject } from './utils.js'

const protocolAllowList = new Set(['https:', 'http:'])
const normalizedUrlCache = new QuickLRU<string, string | null>({
const normalizedUrlCache = new QuickLRU<string, string>({
maxSize: 4000
})

Expand Down Expand Up @@ -42,11 +42,11 @@ export function isRelativeUrl(url: string): boolean {
export function normalizeUrl(
url: string,
options?: NormalizeUrlOptions
): string | null {
let normalizedUrl: string | null | undefined
): string | undefined {
let normalizedUrl: string | undefined

if (!url || isRelativeUrl(url)) {
return null
return undefined
}

const opts = {
Expand All @@ -71,18 +71,26 @@ export function normalizeUrl(
normalizedUrl = normalizedUrlCache.get(cacheKey)

if (normalizedUrl !== undefined) {
return normalizedUrl
if (normalizedUrl) {
return normalizedUrl
} else {
return undefined
}
}

normalizedUrl = normalizeUrlImpl(url, opts)
if (!normalizeUrl) {
normalizedUrl = null
normalizedUrl = ''
}
} catch {
// ignore invalid urls
normalizedUrl = null
normalizedUrl = ''
}

normalizedUrlCache.set(cacheKey, normalizedUrl!)
return normalizedUrl
if (normalizedUrl) {
return normalizedUrl
} else {
return undefined
}
}

0 comments on commit f1db6dc

Please sign in to comment.