import { ok, type CommandContext, type Result } from "@tailor-platform/erp-kit/core"; import type { Transaction } from "../generated/kysely-tailordb"; import { createStateToken } from "../lib/slackState"; export interface BeginSlackWorkspaceInstallInput { redirectUri?: string; clientId: string; /** Shared secret used to HMAC-sign the state token; the same value must be supplied to completeSlackWorkspaceInstall. */ signingSecret: string; } type RunResult = Result<{ state: string; authorizeUrl: string }, never>; export async function run( db: Transaction, input: BeginSlackWorkspaceInstallInput, ctx: CommandContext, ): Promise { void db; const state = await createStateToken( { userId: ctx.actorId, redirectUri: input.redirectUri, }, input.signingSecret, ); const params = new URLSearchParams({ client_id: input.clientId, scope: "chat:write,channels:read", state, }); if (input.redirectUri) { params.set("redirect_uri", input.redirectUri); } const authorizeUrl = `https://slack.com/oauth/v2/authorize?${params.toString()}`; return ok({ state, authorizeUrl }); }