import { accounts } from './accounts.ts' import { pickAuthInput } from './auth.ts' import { inferOperationFromPath, normalizeAirtablePath, oauthConnectUrl, recordsPath, scopeForOperation, } from './setup.ts' import type { AirtableAuthInput } from './types.ts' import { requireRecord } from './types.ts' import { getViewer } from './viewer.ts' export type SmokeTestInput = AirtableAuthInput & { /** When true, skip the live whoami query even if credentials exist. */ setupOnly?: boolean } /** * Verify Airtable auth without returning account PII. Without credentials this * still returns setup URLs so the package is forkable before anyone connects. * @example * import smokeTest from 'kody:@kody/airtable/smoke-test' * const result = await smokeTest() */ export async function smokeTest(params: SmokeTestInput = {}) { const connectUrl = oauthConnectUrl('airtable') const selfCheck = { ok: true as const, pathNormalizesApiPrefix: normalizeAirtablePath('/meta/whoami') === '/v0/meta/whoami', commentWriteScope: scopeForOperation('comments.write') === 'data.recordComments:write', recordWriteFromPath: inferOperationFromPath('POST', '/v0/appExample/tblExample') === 'records.write', recordsPathEncodesTable: recordsPath('appExample', 'Table 1') === '/v0/appExample/Table%201', connectUrlUsesAuthorizeHost: connectUrl.includes('airtable.com'), connectUrlHasRecordsRead: connectUrl.includes('data.records%3Aread'), } const info = await accounts(params) const canLive = Boolean(info.preferredAuth) && params.setupOnly !== true if (!canLive) { return { ok: true, live: false, selfCheck, authMode: info.preferredAuth, integrationName: info.integrationName, secretName: info.secretName, oauthConnected: info.oauthConnected, patSaved: info.patSaved, hasViewerId: false, setup: { connectUrl: info.connectUrl, patUrl: info.patUrl, callbackUrl: info.callbackUrl, requiredHost: info.requiredHost, }, } } const viewer = await getViewer(params) return { ok: true, live: true, selfCheck, authMode: info.preferredAuth, integrationName: info.integrationName, secretName: info.secretName, oauthConnected: info.oauthConnected, patSaved: info.patSaved, hasViewerId: viewer.id.length > 0, setup: { connectUrl: info.connectUrl, patUrl: info.patUrl, callbackUrl: info.callbackUrl, requiredHost: info.requiredHost, }, } } /** * Verify Airtable auth without returning account PII. * @example * import smokeTest from 'kody:@kody/airtable/smoke-test' * const result = await smokeTest({ setupOnly: true }) */ export default async function smokeTestEntrypoint( params: SmokeTestInput & Record = {}, ) { const input = requireRecord(params, 'smoke-test') return smokeTest({ ...pickAuthInput(input), setupOnly: input.setupOnly === true, }) }