Skip to content

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

Package listing

@kody/workos

src/update-organization.ts

110 lines · 3.5 KB · TypeScript
import { workosRequest } from './client.ts'
import { mapOrganization } from './models.ts'
import type {
	DryRunResult,
	JsonRecord,
	WorkosAuthInput,
	WorkosOrganizationSummary,
} from './types.ts'
import { compactRecord, optionalString, requireRecord, requireString } from './types.ts'

export type DomainDataInput = {
	domain: string
	state?: 'pending' | 'verified' | 'failed'
}

export type UpdateOrganizationInput = WorkosAuthInput & {
	organization: string
	name?: string
	domainData?: Array<DomainDataInput>
	externalId?: string
	metadata?: JsonRecord
	confirm?: boolean
	dryRun?: boolean
}

function mapDomainData(value: unknown): Array<DomainDataInput> | undefined {
	if (value === undefined || value === null) return undefined
	if (!Array.isArray(value)) throw new Error('domainData must be an array.')
	return value.map((item, index) => {
		const record = requireRecord(item, `domainData[${index}]`)
		const state = optionalString(record.state, `domainData[${index}].state`)
		if (state !== undefined && state !== 'pending' && state !== 'verified' && state !== 'failed') {
			throw new Error(`domainData[${index}].state must be pending, verified, or failed.`)
		}
		return {
			domain: requireString(record.domain, `domainData[${index}].domain`),
			state,
		}
	})
}

/**
 * Update a WorkOS organization. Requires `confirm: true`, or use `dryRun: true`.
 * @example
 * import updateOrganization from 'kody:@kody/workos/update-organization'
 * const preview = await updateOrganization({
 *   organization: 'org_01EXAMPLE',
 *   name: 'Acme',
 *   dryRun: true,
 * })
 */
export async function updateOrganization(
	input: UpdateOrganizationInput,
): Promise<
	WorkosOrganizationSummary | DryRunResult<{ method: string; path: string; body: JsonRecord }>
> {
	const organization = requireString(input.organization, 'organization')
	const path = `/organizations/${encodeURIComponent(organization)}`
	const body = compactRecord({
		name: optionalString(input.name, 'name'),
		domain_data: mapDomainData(input.domainData)?.map((item) =>
			compactRecord({ domain: item.domain, state: item.state }),
		),
		external_id: optionalString(input.externalId, 'externalId'),
		metadata: input.metadata,
	})
	if (input.dryRun) {
		return { dryRun: true, wouldCall: { method: 'PUT', path, body } }
	}
	if (input.confirm !== true) {
		throw new Error(
			'Updating a WorkOS organization requires confirm: true after explicit user approval, or dryRun: true.',
		)
	}
	const result = await workosRequest<unknown>({
		...input,
		operation: 'organizations.write',
		method: 'PUT',
		path,
		body,
	})
	return mapOrganization(result.data)
}

/**
 * Update a WorkOS organization. Requires `confirm: true`, or use `dryRun: true`.
 * @example
 * import updateOrganization from 'kody:@kody/workos/update-organization'
 * const preview = await updateOrganization({
 *   organization: 'org_01EXAMPLE',
 *   name: 'Acme',
 *   dryRun: true,
 * })
 */
export default async function updateOrganizationEntrypoint(
	params: Partial<UpdateOrganizationInput> & Record<string, unknown> = {},
) {
	const input = requireRecord(params, 'update-organization')
	return updateOrganization({
		organization: requireString(input.organization, 'organization'),
		name: optionalString(input.name, 'name'),
		domainData: mapDomainData(input.domainData),
		externalId: optionalString(input.externalId, 'externalId'),
		metadata: input.metadata as JsonRecord | undefined,
		account: optionalString(input.account, 'account'),
		secretName: optionalString(input.secretName, 'secretName'),
		confirm: input.confirm === true,
		dryRun: input.dryRun === true,
	})
}