import { type AxiosInstance } from 'axios'; import type { GitInformation } from '../services/util.js'; import { SharedFile } from '../constructs/index.js'; export interface Project { name: string; logicalId: string; repoUrl?: string; } type ProjectResponse = Project & { id: string; created_at: string; }; export interface Change { logicalId: string; physicalId?: string | number; type: string; action: string; } export interface ResourceSync { logicalId: string; physicalId?: string | number; type: string; member: boolean; payload: any; } export interface AlertChannelFriendResource { type: 'alert-channel'; logicalId: string; physicalId: number; } export interface CheckGroupFriendResource { type: 'check-group'; logicalId: string; physicalId: number; } export interface PrivateLocationFriendResource { type: 'private-location'; logicalId: string; physicalId: string; } export interface StatusPageServiceFriendResource { type: 'status-page-service'; logicalId: string; physicalId: string; } export type FriendResourceSync = AlertChannelFriendResource | CheckGroupFriendResource | PrivateLocationFriendResource | StatusPageServiceFriendResource; export interface AuxiliaryResourceSync { physicalId?: string | number; type: string; payload: any; } export interface ProjectSync { project: Project; sharedFiles?: SharedFile[]; resources: Array; repoInfo: GitInformation | null; } export interface DeployedProject extends Project { id: string; createdAt: string; updatedAt: string | null; } export interface ProjectDeployResponse { project: DeployedProject; diff: Array; } export type ProjectDeploymentStatus = 'PENDING' | 'RUNNING' | 'SUCCEEDED' | 'FAILED' | 'CANCELLED'; export interface ProjectDeployment { id: string; logicalId: string; status: ProjectDeploymentStatus; dryRun: boolean; /** Opaque progress percentage (0-100). */ progress: number; error: { code: string; message: string; } | null; /** The applied { project, diff }; present once the deployment has succeeded. */ result: ProjectDeployResponse | null; createdAt: string; startedAt: string | null; endedAt: string | null; /** When cancellation was requested for this deployment, or null if it was not. */ cancelRequestedAt: string | null; } export declare class ProjectDeployFailedError extends Error { constructor(message: string, options?: ErrorOptions); } /** The deployment was cancelled before it finished (e.g. superseded by a newer deploy). */ export declare class ProjectDeployCancelledError extends Error { constructor(message: string, options?: ErrorOptions); } export interface ImportPlanFilter { type: 'include' | 'exclude'; resource?: { type: string; physicalId?: string | number; }; } export interface ImportPlanFriend { type: string; logicalId: string; } export interface ImportPlanOptions { preview?: boolean; filters?: ImportPlanFilter[]; friends?: ImportPlanFriend[]; } export interface ImportPlanChanges { resources: ResourceSync[]; friends?: FriendResourceSync[]; auxiliary?: AuxiliaryResourceSync[]; } export interface ImportPlan { id: string; createdAt: string; appliedAt?: string; committedAt?: string; changes?: ImportPlanChanges; } export declare class ProjectNotFoundError extends Error { logicalId: string; constructor(logicalId: string, options?: ErrorOptions); } export declare class ProjectAlreadyExistsError extends Error { logicalId: string; constructor(logicalId: string, options?: ErrorOptions); } export declare class NoImportableResourcesFoundError extends Error { constructor(options?: ErrorOptions); } export declare class ImportPlanNotFoundError extends Error { constructor(options?: ErrorOptions); } export declare class InvalidImportPlanStateError extends Error { constructor(options?: ErrorOptions); } declare class Projects { api: AxiosInstance; constructor(api: AxiosInstance); getAll(): Promise>; /** * @throws {ProjectNotFoundError} If the project does not exist. */ get(logicalId: string): Promise>; /** * @throws {ProjectAlreadyExistsError} If the project already exists. */ create(project: Project): Promise>; /** * Delete a project. The deletion runs asynchronously on the backend: this * submits it, then follows its progress stream to completion, so large projects * are no longer bound by the API gateway request timeout. A project that does * not exist is treated as already deleted (the endpoint is idempotent). * * @throws {ProjectDeployFailedError} If the deletion finishes unsuccessfully. */ deleteProject(logicalId: string, { preserveResources, cancelInProgress, onProgress, onStatus }?: { preserveResources?: boolean; /** * On a 409 (a deploy or delete is already in progress), cancel that * operation instead of waiting for it to finish, then retry. */ cancelInProgress?: boolean; onProgress?: (progress: number) => void; /** Human-readable status updates (e.g. while waiting on a predecessor). */ onStatus?: (message: string) => void; }): Promise; /** * Submit the async delete and follow it to completion. The endpoint responds * either with a deployment to follow (202), or — when there is nothing to delete * (the project does not exist) — a plain result with no deployment to follow. */ private submitDeletion; /** * Deploy a project. The deployment runs asynchronously on the backend: this * submits it, then follows its progress stream to completion, so large projects * are no longer bound by the API gateway request timeout. A dry run returns the * preview diff synchronously without starting a deployment. * * @throws {ProjectDeployFailedError} If the deployment finishes unsuccessfully. */ deploy(resources: ProjectSync, { dryRun, scheduleOnDeploy, preserveResources, cancelInProgress, onProgress, onStatus, }?: { dryRun?: boolean; scheduleOnDeploy?: boolean; /** * Keep resources removed from code (and their run history) in the account * instead of deleting them. */ preserveResources?: boolean; /** * On a 409 (another deployment is already in progress), cancel that * deployment instead of waiting for it to finish, then retry. */ cancelInProgress?: boolean; onProgress?: (progress: number) => void; /** Human-readable status updates (e.g. while waiting on a predecessor). */ onStatus?: (message: string) => void; }): Promise<{ data: ProjectDeployResponse; }>; private submitDeployment; /** * Resolve a collision with an in-progress deployment so the caller can retry: * optionally cancel it, then wait until it reaches a final state (or is gone) * before returning — so the caller re-POSTs only when the slot is actually * free, never re-uploading the payload while the predecessor is still running. * Returns early if the overall `deadlineAt` passes (the caller then re-POSTs * once and surfaces the conflict). */ private resolveInProgressDeployment; getDeployment(logicalId: string, deploymentId: string): Promise>; /** Request cancellation of an in-flight deployment (idempotent on the server). */ cancelDeployment(logicalId: string, deploymentId: string): Promise>; /** * Long-poll the completion endpoint once: the server blocks up to * `maxWaitSeconds` and returns the deployment when it reaches a final state, or * 408 (`RequestTimeoutError`) if it is still running when that window elapses. * The retry cadence lives in the caller, not here. */ awaitDeploymentCompletion(logicalId: string, deploymentId: string, { maxWaitSeconds }?: { maxWaitSeconds?: number; }): Promise; /** * Follow a deployment to completion over its Server-Sent Events stream, * invoking `onProgress` as progress frames arrive and resolving with the final * deployment on the terminal `complete` frame. If the stream drops before a * terminal frame (a transient network blip), it reconnects up to `maxReconnects` * times — the server is stateless and re-reads current state, so resuming needs * no cursor. */ streamDeploymentEvents(logicalId: string, deploymentId: string, { onProgress, maxReconnects }?: { onProgress?: (progress: number) => void; maxReconnects?: number; }): Promise; private openEventStream; private consumeEventStream; /** * @throws {ProjectNotFoundError} If the project does not exist. * @throws {NoImportableResourcesFoundError} If no importable resources were found. */ createImportPlan(logicalId: string, options?: ImportPlanOptions): Promise>; /** * @throws {ProjectNotFoundError} If the project does not exist. */ findImportPlans(logicalId: string, { onlyUnapplied, onlyUncommitted }?: { onlyUnapplied?: boolean | undefined; onlyUncommitted?: boolean | undefined; }): Promise>; listImportPlans({ onlyUnapplied, onlyUncommitted }?: { onlyUnapplied?: boolean | undefined; onlyUncommitted?: boolean | undefined; }): Promise>; /** * @throws {ImportPlanNotFoundError} If the import plan does not exist. * @throws {InvalidImportPlanStateError} If the operation is performed out of order. */ cancelImportPlan(importPlanId: string): Promise>; /** * @throws {ImportPlanNotFoundError} If the import plan does not exist. * @throws {InvalidImportPlanStateError} If the operation is performed out of order. */ applyImportPlan(importPlanId: string): Promise>; /** * @throws {ImportPlanNotFoundError} If the import plan does not exist. * @throws {InvalidImportPlanStateError} If the operation is performed out of order. */ commitImportPlan(importPlanId: string): Promise>; } export default Projects;