/** * Project Resolution * * The single owner of "which project does this directory target, and does it * exist on the control plane?". One request carries the project directory, the * resolved config, where the project reference came from, and a client seam; * it settles into one typed outcome (existing, created, or planned-create). * Callers are presentation adapters: they own their own message wording and * spinners, this module owns the decision and the one persisted link format * (`.veryfront/project.json`). * * @module cli/shared/project-resolution */ import type { ProjectReferenceSource, ResolvedConfig } from "./config.js"; /** A project as the control plane identifies it. */ export interface ProjectTargetRef { id: string; slug: string; } /** * The one seam between resolution and the control plane. Adapters wire this * over whichever transport they already hold (deploy control plane, CLI API * client, demo token); tests wire an in-memory fake. */ export interface ProjectResolutionClient { getProject(reference: string): Promise; reserveSlug(slug: string, options: { allowAlternativeSlug: boolean; }): Promise<{ slug: string; projectId: string; }>; } export interface ProjectResolutionRequest { projectDir: string; config: ResolvedConfig; source: ProjectReferenceSource; client: ProjectResolutionClient; /** Plan only: never reserve a slug, never write a project link. */ dryRun?: boolean; /** * What to do when a named (non-inferred) reference is not found remotely: * create the project (push) or report it (deploy). Defaults to reporting. */ createMissingReference?: boolean; /** Defaults to true only for inferred references. */ allowAlternativeSlug?: boolean; } export type ProjectResolutionOutcome = { kind: "existing"; config: ResolvedConfig; project: ProjectTargetRef; persisted: boolean; } | { kind: "created"; config: ResolvedConfig; project: ProjectTargetRef; requestedSlug: string; persisted: boolean; } | { kind: "planned-create"; config: ResolvedConfig; plannedSlug: string; }; /** * A named project reference did not resolve remotely. Adapters translate this * into their own wording; the module never phrases user-facing guidance. */ export declare class ProjectReferenceNotFoundError extends Error { readonly reference: string; readonly source: ProjectReferenceSource; readonly byId: boolean; constructor(reference: string, source: ProjectReferenceSource, byId: boolean); } /** The reference to look a project up by: its id when known, else its slug. */ export declare function projectApiReference(config: ResolvedConfig): string; /** Only directory-owned references earn a persisted local project link. */ export declare function shouldPersistProjectLink(source: ProjectReferenceSource): boolean; /** Only an inferred slug may be silently replaced by an available alternative. */ export declare function canPersistAlternativeSlug(source: ProjectReferenceSource): boolean; export declare function getErrorStatus(error: unknown): number | undefined; /** Write `.veryfront/project.json` and fold the resolved identity into config. */ export declare function persistProjectLink(projectDir: string, config: T, project: ProjectTargetRef): Promise; /** The slug a directory suggests: its package name, else its own name. */ export declare function inferProjectSlugFromDirectory(projectDir: string): Promise; /** * What a user can do about a slug that is already taken, phrased against the * place the slug came from. */ export declare function slugConflictAction(source: ProjectReferenceSource): string; /** * Resolve the project this directory targets, creating it when the reference * is the directory's own inference (or when the caller opts in for a named * reference that no longer exists). */ export declare function resolveOrCreateProject(request: ProjectResolutionRequest): Promise; //# sourceMappingURL=project-resolution.d.ts.map