import { integrationScope, type IntegrationAccountConnectionOption, type IntegrationAccountRequirement, type IntegrationScopeRequirement, type ScopeRequirementGroup, } from "@automate.ax/catalog/authoring" import { getAutomationPlanningContext } from "./runtime" export { integrationScope, type IntegrationAccountConnectionOption, type IntegrationAccountRequirement, type IntegrationScopeRequirement, type ScopeRequirementGroup, } export const actionAccountRequirementDefinition: unique symbol = Symbol( "automation.actionAccountRequirementDefinition", ) export const actionAccountServiceDefinition: unique symbol = Symbol( "automation.actionAccountServiceDefinition", ) export const DEFAULT_ACCOUNT_BINDING = "default" export const serializedIntegrationAccountDefinition = "$integrationAccount" /** Public connection-specific scope declaration for an action account. */ export interface ActionAccountConnectionRequirement { connectionMethodId: string requiredScope?: IntegrationScopeRequirement } /** Non-empty connection alternatives accepted for one integration service. */ export interface ActionAccountConnectionRequirements { connections: readonly [ ActionAccountConnectionRequirement, ...ActionAccountConnectionRequirement[], ] } /** Public shorthand accepted when declaring action account alternatives. */ export type ActionAccountOption = | TServiceId | ({ serviceId: TServiceId } & ( | { connections: ActionAccountConnectionRequirements["connections"] requiredScope?: never } | { connections?: never requiredScope?: IntegrationScopeRequirement } )) /** An action whose account requirement can contribute authorization scopes. */ export interface AccountAuthorizationAction { readonly [actionAccountRequirementDefinition]: Record< string, readonly IntegrationAccountConnectionOption[] > readonly [actionAccountServiceDefinition]: (serviceId: TServiceId) => void } export type AccountAuthorizationHint = | AccountAuthorizationAction | IntegrationScopeRequirement /** Reference to a stable project account binding. */ export interface IntegrationAccountReference< TServiceId extends string = string, > { readonly [serializedIntegrationAccountDefinition]: { binding: string serviceId: TServiceId } } export interface ResolvedIntegrationAccount< TServiceId extends string = string, > { accountId?: string connectionMethodId: string secret: Record serviceId: TServiceId } /** * Defines the account declaration function for one integration service. * * @param serviceId - Stable integration service identifier. */ export function defineAccount( serviceId: TServiceId, ) { return ( binding = DEFAULT_ACCOUNT_BINDING, authorizationHints?: AccountAuthorizationHint[], ): IntegrationAccountReference => { getAutomationPlanningContext()?.accountDeclarations.push({ binding, ...(authorizationHints?.length && { connectionOptionGroups: authorizationHints.map((hint) => typeof hint === "string" || "type" in hint ? [{ requiredScopes: [hint] }] : (hint[actionAccountRequirementDefinition][serviceId] ?? []), ), }), serviceId, }) return { [serializedIntegrationAccountDefinition]: { binding, serviceId }, } } } /** * Determines whether a runtime value is an integration account reference. * * @param value - Materialized action input value to inspect. */ export function isIntegrationAccountReference( value: unknown, ): value is IntegrationAccountReference { return ( typeof value === "object" && value !== null && serializedIntegrationAccountDefinition in value ) }