Skip to content

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

Package listing

@kody/supabase

src/smoke-test.ts

107 lines · 3.2 KB · TypeScript
import { accounts } from './accounts.ts'
import { insertRows } from './insert-rows.ts'
import { managementRequest } from './management-request.ts'
import { setupUrls } from './setup.ts'
import { optionalBoolean, optionalString, type SupabaseAuthInput } from './types.ts'
import { listProjects } from './list-projects.ts'
import { listBuckets } from './list-buckets.ts'

export type SmokeTestInput = SupabaseAuthInput & {
	setupOnly?: boolean
	dryRun?: boolean
}

/**
 * Verify package wiring. Without credentials this still returns setup URLs.
 * With a PAT it lists project refs/names only. With a service role and
 * projectRef it lists bucket names only. Never writes.
 *
 * This no-argument default is also the disabled `smoke` job wrapper.
 * @example
 * import smokeTest from 'kody:@kody/supabase/smoke-test'
 * const result = await smokeTest()
 */
export async function smokeTest(params: SmokeTestInput = {}) {
	const setup = setupUrls(params)
	const account = await accounts(params)
	const dryRunInsert = await insertRows({
		projectRef: params.projectRef ?? 'exampleprojectref1',
		table: 'items',
		rows: [{ name: 'kody-supabase-dry-run' }],
		dryRun: true,
	})
	const dryRunManagement = await managementRequest({
		path: '/v1/projects',
		method: 'POST',
		body: { name: 'kody-supabase-dry-run' },
		dryRun: true,
	})

	const local = {
		ok: true as const,
		live: false as const,
		hasPatSecret: account.hasPatSecret,
		hasServiceRoleSecret: account.hasServiceRoleSecret,
		patSecretName: account.patSecretName,
		serviceRoleSecretName: account.serviceRoleSecretName,
		setup,
		dryRunInsert,
		dryRunManagement,
	}

	if (params.setupOnly || params.dryRun || (!account.hasPatSecret && !account.hasServiceRoleSecret)) {
		return local
	}

	const live: {
		projects?: { count: number; refs: Array<string> }
		buckets?: { count: number; names: Array<string> }
	} = {}

	if (account.hasPatSecret) {
		const projects = await listProjects(params)
		live.projects = {
			count: projects.count,
			refs: projects.items.map((item) => item.ref),
		}
	}

	if (account.hasServiceRoleSecret && (params.projectRef || params.projectUrl)) {
		const buckets = await listBuckets(params)
		live.buckets = {
			count: buckets.count,
			names: buckets.items.map((item) => item.name),
		}
	}

	return {
		...local,
		ok: true as const,
		live: true as const,
		...live,
	}
}

/**
 * Verify package wiring without mutating Supabase.
 * @example
 * import smokeTest from 'kody:@kody/supabase/smoke-test'
 * const result = await smokeTest({ setupOnly: true })
 */
export default async function smokeTestEntrypoint(
	params: SmokeTestInput & Record<string, unknown> = {},
) {
	return await smokeTest({
		account: optionalString(params.account, 'account'),
		secretName: optionalString(params.secretName, 'secretName'),
		patSecretName: optionalString(params.patSecretName, 'patSecretName'),
		serviceRoleSecretName: optionalString(
			params.serviceRoleSecretName,
			'serviceRoleSecretName',
		),
		projectRef: optionalString(params.projectRef, 'projectRef'),
		projectUrl: optionalString(params.projectUrl, 'projectUrl'),
		setupOnly: optionalBoolean(params.setupOnly, 'setupOnly'),
		dryRun: optionalBoolean(params.dryRun, 'dryRun'),
	})
}