← Public packages
@danj/hey-email
HEY.com email for Kody: search threads, read messages, download PDF attachments, and write drafts. Sending is barred until you allow it.
src/search.js
61 lines · 2.3 KB · JavaScriptimport { heyFetch } from './client.js'
const PAGE_SIZE = 10
const OWN_KEYS = new Set(['q', 'query', 'from', 'date', 'in', 'limit', 'page'])
function searchParams(input, page) {
const params = new URLSearchParams()
const parts = []
const q = input.q ?? input.query
if (q) parts.push(String(q))
if (input.from) parts.push(`from:${String(input.from)}`)
if (parts.length) params.set('q', parts.join(' '))
if (input.date) params.set('date', String(input.date))
if (input.in) params.set('in', String(input.in))
for (const [k, v] of Object.entries(input)) {
if (OWN_KEYS.has(k)) continue
if (v == null || v === '') continue
params.set(k, String(v))
}
// Official hey-sdk AdvancedSearch: page is 1-based and omitted on page 1.
if (page > 1) params.set('page', String(page))
return params
}
function pageCount(input) {
const limit = input.limit == null || input.limit === '' ? null : Number(input.limit)
if (limit > PAGE_SIZE) return Math.ceil(limit / PAGE_SIZE)
return 1
}
/**
* Search HEY mail via advanced_search.
* Use when finding purchase/shipping/sale threads by keyword or sender.
* Sender filters should be passed as from: "example.com" (embedded in q as from:domain).
*
* `page` is the 1-based results page the official SDK sends. Zero and one both
* ask for the first page, which omits the query param. `limit` past 10 fetches
* further pages (`page=2`, …) until that many matches or a short page.
*
* @param {{ q?: string, query?: string, from?: string, date?: string, in?: string, page?: number|string, limit?: number|string }} [input]
* @returns {Promise<{ matches: unknown[], raw: unknown }>}
*
* @example
* import search from 'kody:@danj/hey-email/search'
* const { matches } = await search({ from: 'example.com', date: 'last_30_days', limit: 20 })
*/
export default async function search(input = {}) {
const startPage = Number(input.page) > 1 ? Number(input.page) : 1
const pages = pageCount(input)
const matches = []
let raw
for (let i = 0; i < pages; i++) {
const page = startPage + i
const qs = searchParams(input, page).toString()
raw = await heyFetch(`/advanced_search.json${qs ? `?${qs}` : ''}`)
const batch = raw?.matches || []
matches.push(...batch)
if (batch.length < PAGE_SIZE) break
}
return { matches, raw }
}