import {
PRODUCTHUNT_ACCESS_TOKEN_SECRET,
PRODUCTHUNT_APPLICATIONS_URL,
PRODUCTHUNT_AUTHORIZE_URL,
PRODUCTHUNT_CLIENT_SECRET_SECRET,
PRODUCTHUNT_GRAPHQL_URL,
PRODUCTHUNT_INTEGRATION,
PRODUCTHUNT_TOKEN_URL,
} from './request.ts'
/** Default Kody deployment origin used when none is provided. */
export const DEFAULT_KODY_ORIGIN = 'https://kody.codes'
/**
* Builds the hosted Kody OAuth connect URL for the saved `producthunt` integration.
*
* Pass your own deployment origin when this package runs somewhere other than
* the default deployment.
*/
export function getConnectUrl(origin = DEFAULT_KODY_ORIGIN) {
const params = new URLSearchParams({
provider: PRODUCTHUNT_INTEGRATION,
authorizeUrl: PRODUCTHUNT_AUTHORIZE_URL,
tokenUrl: PRODUCTHUNT_TOKEN_URL,
apiBaseUrl: PRODUCTHUNT_GRAPHQL_URL,
allowedHosts: 'api.producthunt.com',
flow: 'confidential',
scopes: 'public private',
dashboardUrl: PRODUCTHUNT_APPLICATIONS_URL,
providerSetupInstructions:
'Create a Confidential Product Hunt OAuth app. Register the exact redirect URI shown in the connect wizard (https://kody.codes/connect/oauth on the default deployment). Paste the client ID and client secret into the Kody form. Public clients cannot store the secret Kody needs.',
})
return `${origin}/connect/oauth?${params.toString()}`
}
/**
* Returns setup guidance for agents and humans.
*/
export function getSetupGuide(origin = DEFAULT_KODY_ORIGIN) {
return {
integration: PRODUCTHUNT_INTEGRATION,
connectUrl: getConnectUrl(origin),
redirectUri: `${origin}/connect/oauth`,
applicationUrl: PRODUCTHUNT_APPLICATIONS_URL,
clientType: 'confidential',
scopes: ['public', 'private'],
requiredSecrets: [PRODUCTHUNT_ACCESS_TOKEN_SECRET, PRODUCTHUNT_CLIENT_SECRET_SECRET],
recommendedApprovedHosts: ['api.producthunt.com'],
notes: [
'Choose Confidential when creating the Product Hunt app. Kody stores the client secret server-side.',
'Register the redirect URI exactly as shown. A truncated URI will fail the callback.',
'Private scope is required for viewer.user. Public is enough for featured posts.',
`Reconnect any time with ${origin}/connect/oauth?provider=producthunt after the integration is saved.`,
'Use request() for uncommon GraphQL queries or mutations. Write mutations need Product Hunt approval plus the write scope.',
],
}
}
/**
* Return Product Hunt OAuth setup guidance and connect URL for this deployment.
* @returns Integration metadata, redirect URI, required secrets, and setup notes.
* @example
* import guide from 'kody:@kentcdodds/producthunt/guide'
* const info = await guide({ origin: 'https://kody.codes' })
* // => { integration: 'producthunt', connectUrl: 'https://.../connect/oauth?...', requiredSecrets: ['producthuntAccessToken', 'producthuntClientSecret'] }
*/
export default async function guideEntrypoint(params: { origin?: string } = {}) {
return getSetupGuide(params.origin ?? DEFAULT_KODY_ORIGIN)
}