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<string, unknown> = {},
) {
const input = requireRecord(params, 'smoke-test')
return smokeTest({
...pickAuthInput(input),
setupOnly: input.setupOnly === true,
})
}