import { workosRequest } from './client.ts'
import { WORKOS_PORTAL_INTENTS } from './setup.ts'
import type { DryRunResult, JsonRecord, WorkosAuthInput, WorkosPortalIntent } from './types.ts'
import { compactRecord, optionalString, requireRecord, requireString, stringField } from './types.ts'
export type CreatePortalLinkInput = WorkosAuthInput & {
organization: string
intent: WorkosPortalIntent
returnUrl?: string
successUrl?: string
confirm?: boolean
dryRun?: boolean
}
export type CreatePortalLinkResult = {
link: string
intent: WorkosPortalIntent
organization: string
}
function requireIntent(value: unknown): WorkosPortalIntent {
const intent = requireString(value, 'intent')
if (!(WORKOS_PORTAL_INTENTS as ReadonlyArray<string>).includes(intent)) {
throw new Error(`intent must be one of: ${WORKOS_PORTAL_INTENTS.join(', ')}.`)
}
return intent as WorkosPortalIntent
}
/**
* Generate a WorkOS Admin Portal link. Requires `confirm: true`, or use
* `dryRun: true`.
* @example
* import createPortalLink from 'kody:@kody/workos/create-portal-link'
* const preview = await createPortalLink({
* organization: 'org_01EXAMPLE',
* intent: 'sso',
* dryRun: true,
* })
*/
export async function createPortalLink(
input: CreatePortalLinkInput,
): Promise<
CreatePortalLinkResult | DryRunResult<{ method: string; path: string; body: JsonRecord }>
> {
const organization = requireString(input.organization, 'organization')
const intent = requireIntent(input.intent)
const body = compactRecord({
organization,
intent,
return_url: optionalString(input.returnUrl, 'returnUrl'),
success_url: optionalString(input.successUrl, 'successUrl'),
})
if (input.dryRun) {
return { dryRun: true, wouldCall: { method: 'POST', path: '/portal/generate_link', body } }
}
if (input.confirm !== true) {
throw new Error(
'Creating a WorkOS Admin Portal link requires confirm: true after explicit user approval, or dryRun: true.',
)
}
const result = await workosRequest<unknown>({
...input,
operation: 'portal.write',
method: 'POST',
path: '/portal/generate_link',
body,
})
const record = result.data && typeof result.data === 'object' ? (result.data as JsonRecord) : {}
const link = stringField(record.link)
if (!link) {
throw new Error('WorkOS did not return a portal link.')
}
return { link, intent, organization }
}
/**
* Generate a WorkOS Admin Portal link. Requires `confirm: true`, or use
* `dryRun: true`.
* @example
* import createPortalLink from 'kody:@kody/workos/create-portal-link'
* const preview = await createPortalLink({
* organization: 'org_01EXAMPLE',
* intent: 'sso',
* dryRun: true,
* })
*/
export default async function createPortalLinkEntrypoint(
params: Partial<CreatePortalLinkInput> & Record<string, unknown> = {},
) {
const input = requireRecord(params, 'create-portal-link')
return createPortalLink({
organization: requireString(input.organization, 'organization'),
intent: requireIntent(input.intent),
returnUrl: optionalString(input.returnUrl, 'returnUrl'),
successUrl: optionalString(input.successUrl, 'successUrl'),
account: optionalString(input.account, 'account'),
secretName: optionalString(input.secretName, 'secretName'),
confirm: input.confirm === true,
dryRun: input.dryRun === true,
})
}