import { accounts } from './accounts.ts' import { getViewer } from './viewer.ts' import { buildIssueFilter, buildWorkflowStateFilter } from './filters.ts' import { oauthConnectUrl, scopeForOperation } from './setup.ts' import type { LinearAuthInput } from './types.ts' import { optionalString, requireRecord } from './types.ts' import { requireAuthMode } from './auth.ts' export type SmokeTestInput = LinearAuthInput & { /** When true, skip the live viewer query even if credentials exist. */ setupOnly?: boolean } /** * Verify Linear 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/linear/smoke-test' * const result = await smokeTest() */ export async function smokeTest(params: SmokeTestInput = {}) { const selfCheck = { ok: true as const, issueFilterUsesTeamKey: JSON.stringify(buildIssueFilter({ teamKey: 'ENG' })) === JSON.stringify({ team: { key: { eq: 'ENG' } } }), workflowFilterUsesType: JSON.stringify(buildWorkflowStateFilter({ type: 'started' })) === JSON.stringify({ type: { eq: 'started' } }), issueCreateScope: scopeForOperation('issueCreate') === 'issues:create', commentCreateScope: scopeForOperation('commentCreate') === 'comments:create', connectUrlHasCommaScopes: oauthConnectUrl('linear').includes('scopes=read%2Cwrite'), } 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, apiKeySaved: info.apiKeySaved, hasViewerId: false, hasOrganizationId: false, setup: { connectUrl: info.connectUrl, apiKeyUrl: info.apiKeyUrl, 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, apiKeySaved: info.apiKeySaved, hasViewerId: viewer.id.length > 0, hasOrganizationId: Boolean(viewer.organizationId), setup: { connectUrl: info.connectUrl, apiKeyUrl: info.apiKeyUrl, callbackUrl: info.callbackUrl, requiredHost: info.requiredHost, }, } } /** * Verify Linear auth without returning account PII. * @example * import smokeTest from 'kody:@kody/linear/smoke-test' * const result = await smokeTest({ setupOnly: true }) */ export default async function smokeTestEntrypoint( params: SmokeTestInput & Record = {}, ) { const input = requireRecord(params, 'smoke-test') return smokeTest({ integrationName: optionalString(input.integrationName, 'integrationName'), integration: optionalString(input.integration, 'integration'), account: optionalString(input.account, 'account'), secretName: optionalString(input.secretName, 'secretName'), auth: requireAuthMode(input.auth), setupOnly: input.setupOnly === true, }) }