import { hubspotRequest, hubspotUrl, inferOperationFromPath, isMutatingMethod } from './client.ts' import { HUBSPOT_API_BASE_URL } from './setup.ts' import type { HubSpotAuthInput, JsonRecord } from './types.ts' import { optionalBoolean, optionalString, requireRecord, requireString, } from './types.ts' import { requireAuthMode } from './auth.ts' export type HubSpotRawRequestInput = HubSpotAuthInput & { path: string method?: string query?: JsonRecord body?: JsonRecord confirm?: boolean dryRun?: boolean } /** * Call the HubSpot REST API with a saved OAuth integration or private-app token. * Search POST `/crm/v3/objects/{type}/search` is treated as a read. Other * mutating methods require `confirm: true`; use `dryRun: true` to preview. * @example * import request from 'kody:@kody/hubspot/request' * const result = await request({ path: '/crm/v3/objects/contacts', query: { limit: 5 } }) */ export async function request(input: HubSpotRawRequestInput) { const path = requireString(input.path, 'path') const method = (input.method ?? 'GET').toUpperCase() const operation = inferOperationFromPath(method, path) const integrationName = optionalString(input.integrationName, 'integrationName') ?? optionalString(input.integration, 'integration') const secretName = optionalString(input.secretName, 'secretName') const account = optionalString(input.account, 'account') const isSearch = /\/search(?:\/|$)/.test(path) && method === 'POST' const mutating = isMutatingMethod(method) && !isSearch if (input.dryRun) { return { dryRun: true, url: hubspotUrl(path, input.query), apiBaseUrl: HUBSPOT_API_BASE_URL, method, operation, path, query: input.query ?? {}, body: input.body ?? null, integrationName: integrationName ?? null, secretName: secretName ?? null, account: account ?? null, readOnly: !mutating, } } if (mutating && input.confirm !== true) { throw new Error( 'This HubSpot request may mutate CRM data. Pass confirm: true only after explicit user approval, or use dryRun: true.', ) } return hubspotRequest({ path, method, query: input.query, body: input.body, operation, integrationName, integration: input.integration, account, secretName, auth: input.auth, }) } /** * Call the HubSpot REST API with a saved OAuth integration or private-app token. * @example * import request from 'kody:@kody/hubspot/request' * const result = await request({ path: '/account-info/v3/details' }) */ export default async function requestEntrypoint( params: Partial & Record = {}, ) { const input = requireRecord(params, 'request') return request({ path: requireString(input.path, 'path'), method: optionalString(input.method, 'method'), query: input.query as JsonRecord | undefined, body: input.body as JsonRecord | undefined, integrationName: optionalString(input.integrationName, 'integrationName'), integration: optionalString(input.integration, 'integration'), account: optionalString(input.account, 'account'), secretName: optionalString(input.secretName, 'secretName'), auth: requireAuthMode(input.auth), confirm: optionalBoolean(input.confirm, 'confirm'), dryRun: optionalBoolean(input.dryRun, 'dryRun'), }) }