import {z} from 'zod' export type GetApiV1SignalsPresetsOptions = {baseUrl?: string | undefined, BearerApiKey?: string | undefined, fetch?: typeof fetch | undefined}; export const signalType = z.enum(["LINKEDIN_OWN_POST_ENGAGEMENT", "LINKEDIN_COMPETITOR_POST_ENGAGEMENT", "LINKEDIN_PERSON_POST_ENGAGEMENT", "LINKEDIN_KEYWORD_MENTION", "LINKEDIN_OWN_COMPANY_FOLLOWERS", "LINKEDIN_COMPETITOR_FOLLOWERS", "LINKEDIN_COMPANY_PAGE_FOLLOWERS", "HIRING_SIGNALS", "JOB_DESCRIPTION_KEYWORD", "FUNDING_EVENTS", "TECH_ADOPTION", "NEWS_EVENTS", "NEW_JOB", "CUSTOM_EVENT", "LINKEDIN_PARTNER_FOLLOWERS", "LINKEDIN_CUSTOMER_FOLLOWERS", "LINKEDIN_PARTNER_POST_ENGAGEMENT", "LINKEDIN_CUSTOMER_POST_ENGAGEMENT", "LINKEDIN_COMPANY_PAGE_POST_ENGAGEMENT", "LINKEDIN_OWN_PROFILE_POST_ENGAGEMENT", "LINKEDIN_OWN_EMPLOYEES_POST_ENGAGEMENT", "LINKEDIN_COMPETITOR_EMPLOYEES_POST_ENGAGEMENT", "LINKEDIN_PARTNER_EMPLOYEES_POST_ENGAGEMENT", "LINKEDIN_CUSTOMER_EMPLOYEES_POST_ENGAGEMENT", "LINKEDIN_OWN_BRAND_MENTION", "LINKEDIN_COMPETITOR_MENTION", "LINKEDIN_PARTNER_MENTION", "LINKEDIN_CUSTOMER_MENTION", "LINKEDIN_EVENT_MENTION", "COMPETITOR_TECH_ADOPTION", "INTEGRATION_TECH_ADOPTION", "LINKEDIN_EVENT_PAGE_FOLLOWERS", "CHAMPION_CHANGED_JOB", "CRM_LIST_ENTRY"]); export const signalScope = z.enum(["PEOPLE", "COMPANY"]); export const filterFieldKey = z.enum(["job_titles", "locations", "employee_count_ranges", "keywords", "employer_names", "exact_employer_names", "exclude_job_titles", "all_titles", "names", "exclude_names", "skills", "exclude_skills", "languages", "schools", "degrees", "field_of_study", "exclude_locations", "geographies", "exclude_keywords", "exclude_employer_names", "employer_domains", "exclude_employer_domains", "past_employer_names", "company_types", "hq_countries", "hq_states", "largest_headcount_countries", "markets", "acquisition_status", "linkedin_connections_min", "linkedin_connections_max", "linkedin_followers_min", "linkedin_followers_max", "company_revenue_min", "company_revenue_max", "year_founded_min", "year_founded_max", "open_to_work", "is_freelance", "is_public_company", "employee_start_date_after", "role_started_max_months_ago", "role_started_min_months_ago", "competitor_domains", "query", "company_technology_slug_or", "company_technology_slug_and", "company_technology_slug_not", "tech_min_confidence", "funding_stage_or", "industry_or", "industry_not", "company_country_code_or", "company_country_code_not", "company_name_or", "company_name_not", "company_name_partial_match_or", "company_domain_or", "company_domain_not", "company_description_pattern_or", "min_employee_count", "max_employee_count", "company_size", "min_funding_usd", "max_funding_usd", "last_funding_round_after", "last_funding_round_before", "funding_raised_max_age_days", "only_yc_companies", "company_type", "job_title_or", "job_title_not", "job_description_contains_or", "job_location_pattern_or", "posted_at_max_age_days", "tech_first_detected_after", "tech_first_detected_before", "tech_last_detected_before", "tech_last_detected_after", "tech_first_detected_max_age_days", "min_matching_jobs", "seniority", "job_functions", "departments", "exclude_seniority", "exclude_job_functions", "exclude_hq_countries", "past_job_titles", "posted_on_linkedin", "years_of_experience", "follows_your_company", "exact_job_titles", "exclude_exact_job_titles", "years_of_experience_min", "years_of_experience_max", "has_profile_picture", "naics_codes", "monthly_visitors_min", "monthly_visitors_max", "past_employer_titles", "company_keywords", "exclude_company_keywords", "headcount_range_sales", "headcount_range_engineering", "headcount_range_marketing", "headcount_range_operations", "headcount_range_finance", "headcount_range_human_resources", "headcount_range_support", "headcount_range_information_technology", "headcount_range_business_development", "headcount_growth_6m_min", "headcount_growth_6m_max", "headcount_growth_12m_min", "headcount_growth_12m_max", "followers_growth_6m_min", "followers_growth_6m_max", "followers_growth_12m_min", "followers_growth_12m_max", "web_traffic_growth_6m_min", "web_traffic_growth_6m_max", "web_traffic_growth_12m_min", "web_traffic_growth_12m_max", "job_openings_growth_6m_min", "job_openings_growth_6m_max", "job_openings_growth_12m_min", "job_openings_growth_12m_max", "contact_list_ids", "account_list_ids", "first_party_event_name", "news_query_or", "news_category_or", "news_published_max_age_days", "linkedin_company_url_or", "linkedin_person_url_or", "linkedin_post_max_age_days", "linkedin_watched_engagement", "linkedin_keyword_or", "linkedin_followed_company_url_or"]); export const signalPresetPublicOutput = z.object({signal_type: signalType, title: z.string(), description: z.string(), category_label: z.string(), scope: signalScope, scope_selectable_at_creation: z.boolean(), filter_keys: z.array(filterFieldKey), required_filter_keys: z.array(filterFieldKey), requires_event_subject: z.boolean(), preview_supported: z.boolean(), backfill_windows_days: z.array(z.number().int()).nullable()}); export const getApiV1SignalsPresetsResponse = z.array(signalPresetPublicOutput); export const validateResponse = async ( schema: { readonly '~standard': { readonly validate: (value: unknown) => ({ readonly value: Output; readonly issues?: undefined } | { readonly issues: ReadonlyArray<{ readonly message: string; readonly path?: ReadonlyArray | undefined }> }) | Promise<{ readonly value: Output; readonly issues?: undefined } | { readonly issues: ReadonlyArray<{ readonly message: string; readonly path?: ReadonlyArray | undefined }> }> } }, value: unknown ): Promise => { const result = await schema['~standard'].validate(value) if (result.issues !== undefined) { const detail = result.issues .map(({ message, path }) => path?.length ? `${path.map((segment) => String(typeof segment === 'object' ? segment.key : segment)).join('.')}: ${message}` : message ) .join('; ') throw new Error(`Response does not match the schema: ${detail}`, { cause: { issues: result.issues } }) } return result.value }; /** * List Signal Presets * * GET /v1/signals/presets */ export const getApiV1SignalsPresets = async (options?: GetApiV1SignalsPresetsOptions) => { const {baseUrl = "https://api.topo.io", fetch: fetchFn = fetch, BearerApiKey} = options ?? {} const query = new URLSearchParams() const headers = new Headers() headers.set('accept', "application/json") if (BearerApiKey !== undefined) headers.set('authorization', `Bearer ${BearerApiKey}`) const url = `${baseUrl.replace(/\/+$/, '')}/v1/signals/presets${query.size > 0 ? `?${query}` : ''}` const res = await fetchFn(url, {method: "GET", headers}) if (!res.ok) throw new Error(`Request failed with status ${res.status}`, {cause: {status: res.status, body: await res.text()}}) return validateResponse(getApiV1SignalsPresetsResponse, await res.json()) };