import { parseAuth } from './auth.ts'
import { accounts } from './accounts.ts'
import { getMe } from './me.ts'
import {
inferOperationFromPath,
normalizeSubdomain,
normalizeZendeskPath,
oauthConnectUrl,
permissionForOperation,
zendeskHost,
} from './setup.ts'
import type { ZendeskAuthInput } from './types.ts'
import { requireRecord } from './types.ts'
export type SmokeTestInput = ZendeskAuthInput & {
/** When true, skip the live `/users/me` query even if credentials exist. */
setupOnly?: boolean
}
/**
* Verify Zendesk helpers without returning email. Without credentials this
* still returns setup URLs so the package is forkable before anyone connects.
* @example
* import smokeTest from 'kody:@kody/zendesk/smoke-test'
* const result = await smokeTest()
*/
export async function smokeTest(params: SmokeTestInput = {}) {
const connectUrl = oauthConnectUrl('zendesk', 'your-subdomain')
const selfCheck = {
ok: true as const,
subdomainNormalizesHost: normalizeSubdomain('Acme.zendesk.com') === 'acme',
ticketPath: normalizeZendeskPath('/tickets') === '/tickets',
searchIsRead: inferOperationFromPath('GET', '/search') === 'tickets.read',
ticketWrite: inferOperationFromPath('POST', '/tickets') === 'tickets.write',
userSearchIsRead: inferOperationFromPath('GET', '/users/search') === 'users.read',
userWrite: inferOperationFromPath('POST', '/users') === 'users.write',
articleWrite: inferOperationFromPath('POST', '/help_center/sections/1/articles') === 'articles.write',
articleRead: inferOperationFromPath('GET', '/help_center/articles') === 'articles.read',
meRead: inferOperationFromPath('GET', '/users/me') === 'me.read',
ticketWritePermission: permissionForOperation('tickets.write') === 'tickets:write',
connectUrlUsesPlaceholderHost: connectUrl.includes(encodeURIComponent('your-subdomain.zendesk.com')),
connectUrlUsesAuthorizations: connectUrl.includes('oauth%2Fauthorizations%2Fnew'),
hostIsGeneric: zendeskHost('acme') === 'acme.zendesk.com',
}
const info = await accounts(params)
const canLive = Boolean(info.preferredAuth) && Boolean(info.subdomain) && params.setupOnly !== true
if (!canLive) {
return {
ok: true,
live: false,
selfCheck,
authMode: info.preferredAuth,
integrationName: info.integrationName,
secretName: info.secretName,
usernameSecretName: info.usernameSecretName,
oauthConnected: info.oauthConnected,
apiTokenSaved: info.apiTokenSaved,
apiUsernameSaved: info.apiUsernameSaved,
hasSubdomain: Boolean(info.subdomain),
hasUserId: false,
setup: {
connectUrl: info.connectUrl,
apiTokenUrl: info.apiTokenUrl,
apiUsernameUrl: info.apiUsernameUrl,
callbackUrl: info.callbackUrl,
requiredHosts: info.requiredHosts,
},
}
}
const me = await getMe(params)
return {
ok: true,
live: true,
selfCheck,
authMode: info.preferredAuth,
integrationName: info.integrationName,
secretName: info.secretName,
usernameSecretName: info.usernameSecretName,
oauthConnected: info.oauthConnected,
apiTokenSaved: info.apiTokenSaved,
apiUsernameSaved: info.apiUsernameSaved,
hasSubdomain: Boolean(info.subdomain),
hasUserId: Boolean(me.id),
role: me.role,
setup: {
connectUrl: info.connectUrl,
apiTokenUrl: info.apiTokenUrl,
apiUsernameUrl: info.apiUsernameUrl,
callbackUrl: info.callbackUrl,
requiredHosts: info.requiredHosts,
},
}
}
/**
* Verify Zendesk helpers without returning email.
* @example
* import smokeTest from 'kody:@kody/zendesk/smoke-test'
* const result = await smokeTest({ setupOnly: true, subdomain: 'acme' })
*/
export default async function smokeTestEntrypoint(
params: SmokeTestInput & Record<string, unknown> = {},
) {
const input = requireRecord(params, 'smoke-test')
return smokeTest({
...parseAuth(input),
setupOnly: input.setupOnly === true,
})
}