Skip to content

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

Package listing

@kody/producthunt

src/index.ts

90 lines · 2.7 KB · TypeScript
import { accounts } from './accounts.ts'
import { parseAuthInput } from './auth.ts'
import { getSetupGuide } from './guide.ts'
import { smokeTest } from './smoke-test.ts'
import {
	DEFAULT_OAUTH_SCOPES,
	PRODUCTHUNT_CALLBACK_URL,
	PRODUCTHUNT_REQUIRED_HOST,
	PRODUCTHUNT_SCOPES,
} from './setup.ts'
import { optionalString, requireRecord } from './types.ts'

export {
	ProductHuntRequestError,
	request,
} from './request.ts'
export { clampPageSize } from './setup.ts'
export {
	getCollection,
	getPost,
	getTopic,
	getUser,
	getViewer,
	listCollections,
	listComments,
	listPosts,
	listTodayPosts,
	listTopics,
	unwrapConnection,
} from './domain.ts'
export { todayBounds } from './today.ts'
export { DEFAULT_KODY_ORIGIN, getConnectUrl, getSetupGuide } from './guide.ts'
export { accounts } from './accounts.ts'
export { smokeTest } from './smoke-test.ts'

/**
 * Describe the Product Hunt package, auth lanes, and export surface.
 * Pass `{ action: 'smoke-test' }` to run the smoke helper.
 * @example
 * import producthunt from 'kody:@kody/producthunt'
 * const overview = await producthunt()
 */
export default async function productHuntOverview(
	params: { action?: string } & Record<string, unknown> = {},
) {
	const input = requireRecord(params, 'producthunt')
	const action = optionalString(input.action, 'action')
	if (action === 'smoke-test') {
		return smokeTest({
			...parseAuthInput(input),
			setupOnly: input.setupOnly === true,
		})
	}

	const info = await accounts(parseAuthInput(input)).catch(() => null)
	return {
		package: '@kody/producthunt',
		publicUrl: 'https://kody.codes/@kody/producthunt',
		description:
			"Read today's Product Hunt posts, lookups, and comments through the saved Product Hunt OAuth integration.",
		auth: {
			oauth: {
				defaultIntegration: 'producthunt',
				connectUrl: info?.connectUrl ?? getSetupGuide().connectUrl,
				callbackUrl: PRODUCTHUNT_CALLBACK_URL,
				scopes: PRODUCTHUNT_SCOPES,
				defaultScopes: [...DEFAULT_OAUTH_SCOPES],
				requiredHost: PRODUCTHUNT_REQUIRED_HOST,
			},
			token: {
				defaultSecret: 'producthuntAccessToken',
				setupUrl: info?.accessTokenUrl ?? getSetupGuide().accessTokenUrl,
				requiredHost: PRODUCTHUNT_REQUIRED_HOST,
			},
		},
		comments: 'Read-only. The public Product Hunt GraphQL schema has no comment-create mutation.',
		safety: 'GraphQL mutations require confirm: true and support dryRun: true.',
		jobs: 'off',
		setup: info ?? getSetupGuide(),
		exports: {
			setup: ['accounts', 'smoke-test', 'guide'],
			today: ['list-today-posts'],
			posts: ['list-posts', 'get-post', 'list-comments'],
			hunters: ['get-user', 'get-viewer'],
			topics: ['list-topics', 'get-topic'],
			collections: ['list-collections', 'get-collection'],
			advanced: ['request', 'types'],
		},
	}
}