Skip to content

Built for people who want to own their automations. Join the waitlist for an invite.

Package listing

@kody/planetscale

src/smoke-test.ts

110 lines · 3.1 KB · TypeScript
import { accounts } from './accounts.ts'
import { buildLoopDraft } from './draft-loop.ts'
import { listOrganizations } from './list-organizations.ts'
import { apiTokenSetupUrl, insightsUrl, webhookSecretSetupUrl } from './setup.ts'
import type { PlanetscaleAuthInput } from './types.ts'
import { requireRecord } from './types.ts'

function fixtureDraft() {
	return buildLoopDraft({
		target: {
			organization: 'acme',
			database: 'app',
			branch: 'main',
			githubOwner: 'acme',
			githubRepo: 'app',
			repositoryUrl: 'https://github.com/acme/app',
		},
		anomaly: {
			id: 'anom_smoke',
			active: true,
			periodStart: '2026-08-24T00:00:00.000Z',
			periodEnd: '2026-08-24T01:00:00.000Z',
			minutesInViolation: 12,
			duration: 720,
			correlations: [
				{
					id: 'corr_smoke',
					fingerprint: 'select-users-by-email',
					normalizedSql: 'SELECT * FROM users WHERE email = ?',
					keyspace: null,
					r: 0.92,
				},
			],
		},
	})
}

/**
 * Credential-optional smoke test. Without a service token this still returns
 * setup URLs and a fixture loop draft. With a token it lists organizations
 * (no billing emails) and does not open issues or agents.
 * @example
 * import smokeTest from 'kody:@kody/planetscale/smoke-test'
 * const result = await smokeTest()
 */
export async function smokeTest(input: PlanetscaleAuthInput = {}) {
	const accountInfo = await accounts(input)
	const draft = fixtureDraft()
	const setup = {
		serviceTokenUrl: apiTokenSetupUrl(accountInfo.secretName),
		webhookSecretUrl: webhookSecretSetupUrl(),
		secretName: accountInfo.secretName,
		apiTokenSaved: accountInfo.apiTokenSaved,
		insightsExample: insightsUrl('your-org', 'your-db', 'main'),
		communityUrl: 'https://kody.codes/@kody/planetscale',
	}

	if (!accountInfo.apiTokenSaved) {
		return {
			ok: true,
			live: false,
			setup,
			draft: {
				title: draft.title,
				insightsUrl: draft.insightsUrl,
				hasImplementerPrompt: draft.implementerPrompt.includes('ManagePullRequest'),
				hasReviewerPrompt: draft.reviewerPrompt.includes('fingerprint'),
			},
			message:
				'PlanetScale loop helpers are loaded. Save a service token, then call list-organizations or draft-loop. run-loop stays dry-run until confirm: true.',
		}
	}

	const organizations = await listOrganizations({
		account: input.account,
		secretName: input.secretName,
		perPage: 5,
	})
	return {
		ok: true,
		live: true,
		setup,
		organizations: organizations.items.map((item) => ({
			id: item.id,
			name: item.name,
		})),
		draft: {
			title: draft.title,
			insightsUrl: draft.insightsUrl,
		},
		message: 'Service token works. No issues or Cursor agents were created.',
	}
}

/**
 * Credential-optional smoke test.
 * @example
 * import smokeTest from 'kody:@kody/planetscale/smoke-test'
 * await smokeTest()
 */
export default async function smokeTestEntrypoint(
	params: PlanetscaleAuthInput & Record<string, unknown> = {},
) {
	const input = requireRecord(params, 'smoke-test')
	return smokeTest({
		account: typeof input.account === 'string' ? input.account : undefined,
		secretName: typeof input.secretName === 'string' ? input.secretName : undefined,
	})
}