join

package
v0.16.2 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 24, 2026 License: MIT Imports: 14 Imported by: 0

Documentation

Overview

Package join provides a client for join.com's public candidate-facing job search and detail surfaces. See API.md for the reverse-engineered API notes this client is built from.

Index

Constants

View Source
const (
	MockJobIdParam = "16397229-senior-software-engineer-backend-llm-infrastructure"
	MockJobSlug    = "routinelabs"
)

MockJobIdParam / MockJobSlug identify the job & company slug mockJobDetailRsp was captured for.

View Source
const (
	MockRemoteJobIdParam = "16433808-freelancer-m-w-d-gesucht-inbound-home-office-in-der-eu"
	MockRemoteJobSlug    = "hey-contact-heroes"
)

MockRemoteJobIdParam / MockRemoteJobSlug identify a REMOTE/ANYWHERE job (mockJobDetailRemoteRsp): workplaceType REMOTE, remoteType ANYWHERE, but city/country still carry the employer's base location — see API.md's note on remoteType and internal/ats/join.go's joinLocation.

View Source
const GetCompanyJobs_Operation = `` /* 502-byte string literal not displayed */

The query executed by GetCompanyJobs.

View Source
const MockCompanyID = 172617

MockCompanyID is the companyId the mock server serves mockJobsRsp for (routinelabs' real id — the fixture is captured live traffic, not hand-written).

View Source
const MockEmptyCompanyID = 154838

MockEmptyCompanyID is a companyId the mock server serves an empty dump for, mirroring a real company with zero open jobs.

Variables

View Source
var Companies = mustLoadCompanies()

Companies holds every confirmed join.com company, sorted by company name.

View Source
var CompaniesBySlug = buildSlugIndex(Companies)

CompaniesBySlug looks up a confirmed company by slug. Keys are lowercased, so callers must lowercase their input before indexing.

View Source
var ErrNotFound = errors.New("join: not found")

ErrNotFound is returned by JobDetail for a nonexistent job or company slug (upstream 404) and by ResolveCompany for a nonexistent slug.

Functions

func NewMockServer

func NewMockServer() *httptest.Server

NewMockServer returns an httptest.Server that mimics join.com's GraphQL search endpoint and SSR job detail pages with canned fixture responses, so tests never hit the real site. The caller owns the server and must Close it.

Types

type Client

type Client struct {
	// contains filtered or unexported fields
}

Client talks to join.com's public candidate-facing surfaces: the unauthenticated GraphQL search endpoint and the SSR HTML pages scraped for job/company detail (see API.md).

func NewClient

func NewClient(baseURL string, httpClient *http.Client) *Client

NewClient builds a Client against baseURL (e.g. "https://join.com"). When httpClient is nil, http.DefaultClient is used.

func (*Client) JobDetail

func (c *Client) JobDetail(ctx context.Context, slug, idParam string) (*JobDetail, error)

JobDetail fetches the full posting at /companies/{slug}/{idParam}. slug and idParam must come from the same roster entry / Client.Jobs result pair Search used — see API.md's "Job identity" section for why idParam, not the job's numeric id, is the value to pass here.

func (*Client) Jobs

func (c *Client) Jobs(ctx context.Context, companyID int) ([]Job, error)

Jobs returns every job in companyID's board, looping pages until pageInfo.pageCount is exhausted. There is no server-side keyword search (see API.md); callers filter the returned dump themselves.

func (*Client) ResolveCompany

func (c *Client) ResolveCompany(ctx context.Context, slug string) (*Company, error)

ResolveCompany scrapes /companies/{slug} for the company's numeric id and canonical name. There is no GraphQL field for this lookup (see API.md); roster curation is the intended caller, not the request-time adapter path.

type Company

type Company struct {
	ID   int
	Name string
	Slug string
}

Company is a resolved company identity, scraped from the SSR /companies/{slug} page's embedded __NEXT_DATA__. There is no public GraphQL field to resolve a slug to its numeric id (see API.md), so this is the only way to learn a company's id from its slug.

type GetCompanyJobsPublicJobsPublicJobsResult

type GetCompanyJobsPublicJobsPublicJobsResult struct {
	Items    []GetCompanyJobsPublicJobsPublicJobsResultItemsPublicJob `json:"items"`
	PageInfo GetCompanyJobsPublicJobsPublicJobsResultPageInfo         `json:"pageInfo"`
}

GetCompanyJobsPublicJobsPublicJobsResult includes the requested fields of the GraphQL type PublicJobsResult.

func (*GetCompanyJobsPublicJobsPublicJobsResult) GetItems

GetItems returns GetCompanyJobsPublicJobsPublicJobsResult.Items, and is useful for accessing the field via an interface.

func (*GetCompanyJobsPublicJobsPublicJobsResult) GetPageInfo

GetPageInfo returns GetCompanyJobsPublicJobsPublicJobsResult.PageInfo, and is useful for accessing the field via an interface.

type GetCompanyJobsPublicJobsPublicJobsResultItemsPublicJob

type GetCompanyJobsPublicJobsPublicJobsResultItemsPublicJob struct {
	Id             int                                                                  `json:"id"`
	IdParam        string                                                               `json:"idParam"`
	Title          string                                                               `json:"title"`
	Status         string                                                               `json:"status"`
	WorkplaceType  string                                                               `json:"workplaceType"`
	RemoteType     string                                                               `json:"remoteType"`
	CreatedAt      string                                                               `json:"createdAt"`
	UpdatedAt      string                                                               `json:"updatedAt"`
	City           GetCompanyJobsPublicJobsPublicJobsResultItemsPublicJobCity           `json:"city"`
	Country        GetCompanyJobsPublicJobsPublicJobsResultItemsPublicJobCountry        `json:"country"`
	Category       GetCompanyJobsPublicJobsPublicJobsResultItemsPublicJobCategory       `json:"category"`
	EmploymentType GetCompanyJobsPublicJobsPublicJobsResultItemsPublicJobEmploymentType `json:"employmentType"`
}

GetCompanyJobsPublicJobsPublicJobsResultItemsPublicJob includes the requested fields of the GraphQL type PublicJob.

func (*GetCompanyJobsPublicJobsPublicJobsResultItemsPublicJob) GetCategory

GetCategory returns GetCompanyJobsPublicJobsPublicJobsResultItemsPublicJob.Category, and is useful for accessing the field via an interface.

func (*GetCompanyJobsPublicJobsPublicJobsResultItemsPublicJob) GetCity

GetCity returns GetCompanyJobsPublicJobsPublicJobsResultItemsPublicJob.City, and is useful for accessing the field via an interface.

func (*GetCompanyJobsPublicJobsPublicJobsResultItemsPublicJob) GetCountry

GetCountry returns GetCompanyJobsPublicJobsPublicJobsResultItemsPublicJob.Country, and is useful for accessing the field via an interface.

func (*GetCompanyJobsPublicJobsPublicJobsResultItemsPublicJob) GetCreatedAt

GetCreatedAt returns GetCompanyJobsPublicJobsPublicJobsResultItemsPublicJob.CreatedAt, and is useful for accessing the field via an interface.

func (*GetCompanyJobsPublicJobsPublicJobsResultItemsPublicJob) GetEmploymentType

GetEmploymentType returns GetCompanyJobsPublicJobsPublicJobsResultItemsPublicJob.EmploymentType, and is useful for accessing the field via an interface.

func (*GetCompanyJobsPublicJobsPublicJobsResultItemsPublicJob) GetId

GetId returns GetCompanyJobsPublicJobsPublicJobsResultItemsPublicJob.Id, and is useful for accessing the field via an interface.

func (*GetCompanyJobsPublicJobsPublicJobsResultItemsPublicJob) GetIdParam

GetIdParam returns GetCompanyJobsPublicJobsPublicJobsResultItemsPublicJob.IdParam, and is useful for accessing the field via an interface.

func (*GetCompanyJobsPublicJobsPublicJobsResultItemsPublicJob) GetRemoteType

GetRemoteType returns GetCompanyJobsPublicJobsPublicJobsResultItemsPublicJob.RemoteType, and is useful for accessing the field via an interface.

func (*GetCompanyJobsPublicJobsPublicJobsResultItemsPublicJob) GetStatus

GetStatus returns GetCompanyJobsPublicJobsPublicJobsResultItemsPublicJob.Status, and is useful for accessing the field via an interface.

func (*GetCompanyJobsPublicJobsPublicJobsResultItemsPublicJob) GetTitle

GetTitle returns GetCompanyJobsPublicJobsPublicJobsResultItemsPublicJob.Title, and is useful for accessing the field via an interface.

func (*GetCompanyJobsPublicJobsPublicJobsResultItemsPublicJob) GetUpdatedAt

GetUpdatedAt returns GetCompanyJobsPublicJobsPublicJobsResultItemsPublicJob.UpdatedAt, and is useful for accessing the field via an interface.

func (*GetCompanyJobsPublicJobsPublicJobsResultItemsPublicJob) GetWorkplaceType

GetWorkplaceType returns GetCompanyJobsPublicJobsPublicJobsResultItemsPublicJob.WorkplaceType, and is useful for accessing the field via an interface.

type GetCompanyJobsPublicJobsPublicJobsResultItemsPublicJobCategory

type GetCompanyJobsPublicJobsPublicJobsResultItemsPublicJobCategory struct {
	Id   int    `json:"id"`
	Name string `json:"name"`
}

GetCompanyJobsPublicJobsPublicJobsResultItemsPublicJobCategory includes the requested fields of the GraphQL type JobCategory.

func (*GetCompanyJobsPublicJobsPublicJobsResultItemsPublicJobCategory) GetId

GetId returns GetCompanyJobsPublicJobsPublicJobsResultItemsPublicJobCategory.Id, and is useful for accessing the field via an interface.

func (*GetCompanyJobsPublicJobsPublicJobsResultItemsPublicJobCategory) GetName

GetName returns GetCompanyJobsPublicJobsPublicJobsResultItemsPublicJobCategory.Name, and is useful for accessing the field via an interface.

type GetCompanyJobsPublicJobsPublicJobsResultItemsPublicJobCity

type GetCompanyJobsPublicJobsPublicJobsResultItemsPublicJobCity struct {
	CityName    string `json:"cityName"`
	CountryName string `json:"countryName"`
}

GetCompanyJobsPublicJobsPublicJobsResultItemsPublicJobCity includes the requested fields of the GraphQL type JobCity.

func (*GetCompanyJobsPublicJobsPublicJobsResultItemsPublicJobCity) GetCityName

GetCityName returns GetCompanyJobsPublicJobsPublicJobsResultItemsPublicJobCity.CityName, and is useful for accessing the field via an interface.

func (*GetCompanyJobsPublicJobsPublicJobsResultItemsPublicJobCity) GetCountryName

GetCountryName returns GetCompanyJobsPublicJobsPublicJobsResultItemsPublicJobCity.CountryName, and is useful for accessing the field via an interface.

type GetCompanyJobsPublicJobsPublicJobsResultItemsPublicJobCountry

type GetCompanyJobsPublicJobsPublicJobsResultItemsPublicJobCountry struct {
	Iso3166 string `json:"iso3166"`
	Name    string `json:"name"`
}

GetCompanyJobsPublicJobsPublicJobsResultItemsPublicJobCountry includes the requested fields of the GraphQL type JobCountry.

func (*GetCompanyJobsPublicJobsPublicJobsResultItemsPublicJobCountry) GetIso3166

GetIso3166 returns GetCompanyJobsPublicJobsPublicJobsResultItemsPublicJobCountry.Iso3166, and is useful for accessing the field via an interface.

func (*GetCompanyJobsPublicJobsPublicJobsResultItemsPublicJobCountry) GetName

GetName returns GetCompanyJobsPublicJobsPublicJobsResultItemsPublicJobCountry.Name, and is useful for accessing the field via an interface.

type GetCompanyJobsPublicJobsPublicJobsResultItemsPublicJobEmploymentType

type GetCompanyJobsPublicJobsPublicJobsResultItemsPublicJobEmploymentType struct {
	Id   int    `json:"id"`
	Name string `json:"name"`
}

GetCompanyJobsPublicJobsPublicJobsResultItemsPublicJobEmploymentType includes the requested fields of the GraphQL type JobEmploymentType.

func (*GetCompanyJobsPublicJobsPublicJobsResultItemsPublicJobEmploymentType) GetId

GetId returns GetCompanyJobsPublicJobsPublicJobsResultItemsPublicJobEmploymentType.Id, and is useful for accessing the field via an interface.

func (*GetCompanyJobsPublicJobsPublicJobsResultItemsPublicJobEmploymentType) GetName

GetName returns GetCompanyJobsPublicJobsPublicJobsResultItemsPublicJobEmploymentType.Name, and is useful for accessing the field via an interface.

type GetCompanyJobsPublicJobsPublicJobsResultPageInfo

type GetCompanyJobsPublicJobsPublicJobsResultPageInfo struct {
	Page      int `json:"page"`
	PageCount int `json:"pageCount"`
	PageSize  int `json:"pageSize"`
	RowCount  int `json:"rowCount"`
}

GetCompanyJobsPublicJobsPublicJobsResultPageInfo includes the requested fields of the GraphQL type PageInfo.

func (*GetCompanyJobsPublicJobsPublicJobsResultPageInfo) GetPage

GetPage returns GetCompanyJobsPublicJobsPublicJobsResultPageInfo.Page, and is useful for accessing the field via an interface.

func (*GetCompanyJobsPublicJobsPublicJobsResultPageInfo) GetPageCount

GetPageCount returns GetCompanyJobsPublicJobsPublicJobsResultPageInfo.PageCount, and is useful for accessing the field via an interface.

func (*GetCompanyJobsPublicJobsPublicJobsResultPageInfo) GetPageSize

GetPageSize returns GetCompanyJobsPublicJobsPublicJobsResultPageInfo.PageSize, and is useful for accessing the field via an interface.

func (*GetCompanyJobsPublicJobsPublicJobsResultPageInfo) GetRowCount

GetRowCount returns GetCompanyJobsPublicJobsPublicJobsResultPageInfo.RowCount, and is useful for accessing the field via an interface.

type GetCompanyJobsResponse

type GetCompanyJobsResponse struct {
	PublicJobs GetCompanyJobsPublicJobsPublicJobsResult `json:"publicJobs"`
}

GetCompanyJobsResponse is returned by GetCompanyJobs on success.

func GetCompanyJobs

func GetCompanyJobs(
	ctx_ context.Context,
	client_ graphql.Client,
	companyId int,
	page int,
	pageSize int,
) (data_ *GetCompanyJobsResponse, err_ error)

One page can hold every job a curated company has: JOIN's SMB-focused customers rarely exceed a few dozen open postings, and the client loops pages regardless (see client.go) rather than trusting a single call.

func (*GetCompanyJobsResponse) GetPublicJobs

GetPublicJobs returns GetCompanyJobsResponse.PublicJobs, and is useful for accessing the field via an interface.

type Job

type Job struct {
	// IdParam is the value [Client.JobDetail] takes to fetch this job's
	// full posting. Not the same as the job's numeric database id — see
	// API.md's "Job identity" section.
	IdParam        string
	Title          string
	Status         string
	WorkplaceType  string // e.g. ONSITE, HYBRID, REMOTE; empty when unset upstream.
	RemoteType     string
	CreatedAt      time.Time
	UpdatedAt      time.Time
	City           string
	Country        string
	Category       string
	EmploymentType string
}

Job is one row from a company's job dump (search). It carries no description: publicJobs never populates descriptionHtml regardless of requested fields (see API.md) — fetch Client.JobDetail with IdParam for the full posting.

type JobDetail

type JobDetail struct {
	ID             int
	IdParam        string
	Title          string
	CompanyID      int
	WorkplaceType  string
	RemoteType     string
	Status         string
	CreatedAt      time.Time
	UpdatedAt      time.Time
	City           string
	Country        string
	Category       string
	EmploymentType string
	// Description is the full posting body in Markdown, assembled from
	// intro/tasks/requirements/benefits/outro (legacy jobs) or the single
	// description field (unifiedDescription jobs) — see API.md.
	Description string
}

JobDetail is a full posting, scraped from the SSR job detail page's embedded __NEXT_DATA__ (see parse.go). Fields beyond Job mirror what the detail page alone carries.

type JobsResponse

type JobsResponse struct {
	Jobs      []Job
	Page      int
	PageCount int
	PageSize  int
	RowCount  int
}

JobsResponse is one page of a company's job dump.

type RosterCompany

type RosterCompany struct {
	Name      string `yaml:"company" json:"company"`
	Slug      string `yaml:"slug" json:"slug"`
	CompanyID int    `yaml:"company_id" json:"company_id"`
}

RosterCompany is a confirmed organization hosting a public join.com career page, drawn from a curated list (internal/provider/join/companies.yaml). Every entry was verified live: the GraphQL search endpoint returns HTTP 200 with at least one job for Slug/CompanyID, or — for a company that happens to have zero open jobs right now — the /companies/{slug} page resolves to the same CompanyID independently (see cmd/verify-companies). CompanyID is the numeric id the GraphQL API takes as PublicJobsQueryInput.companyId; there is no way to derive it from Slug at request time (see API.md), so it's resolved once here.

func (RosterCompany) CareersURL

func (c RosterCompany) CareersURL() string

CareersURL returns the company's human-facing career page, e.g. https://join.com/companies/routinelabs.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL