import type { IConstruct } from "constructs";
import { Construct } from "constructs";
import type { Project } from "./project";
/**
 * Represents a project component.
 * @param project
 * @param id Unique id of the component. If not provided, an unstable AutoId is generated.
 */
export declare class Component extends Construct {
    /**
     * Test whether the given construct is a component.
     */
    static isComponent(x: any): x is Component;
    readonly project: Project;
    constructor(scope: IConstruct, id?: string);
    /**
     * Called before synthesis.
     */
    preSynthesize(): void;
    /**
     * Synthesizes files to the project output directory.
     */
    synthesize(): void;
    /**
     * Called after synthesis. Order is *not* guaranteed.
     */
    postSynthesize(): void;
}
/**
 * A {@link Component} that is created *detached* from any project and attached
 * to one later via {@link FutureComponent.attach}.
 *
 * Like a regular component, but constructed without a project. It improves on a
 * naive deferred component in three ways:
 *
 * - Use-before-attach is an error, not a silent footgun. The constructor hands
 *   the caller a guard proxy; touching `project`, `node`, `synthesize()` or any
 *   subclass feature before `attach()` throws.
 * - No global shadow-tree leak. Each instance gets its own throwaway shadow
 *   root, so detached components never share an id counter and the root becomes
 *   garbage once the component is reparented on attach.
 * - `attach()` returns the unwrapped component, so callers can opt out of the
 *   proxy entirely.
 *
 * The constructor takes no arguments (`super()`). A subclass that needs options
 * captures them itself, reading the local parameter inside its constructor - NOT
 * `this.options`, which the guard blocks until attach.
 *
 * ```ts
 * class Worker extends FutureComponent {
 *   private readonly options: WorkerOptions;
 *   constructor(options: WorkerOptions = {}) {
 *     super();
 *     this.options = options; // set: allowed
 *   }
 *   protected init() {
 *     // this.project is available here
 *   }
 * }
 *
 * const w = new Worker({ retries: 3 });
 * // w.project;                  // throws: not attached yet
 * const real = w.attach(project); // reparents, runs init(), returns the bare instance
 * ```
 */
export declare abstract class FutureComponent extends Component {
    private readonly newTargetName;
    private attachedState;
    constructor();
    /**
     * Whether `attach()` has been called. A convenience for tests/introspection;
     * prefer `tryAttach()` over reading this and branching.
     */
    get attached(): boolean;
    /**
     * Project-dependent setup. Runs once, from `attach()`, when `this.project` is
     * finally available.
     */
    protected init(): void;
    /**
     * Attach the component to a scope. Only now does it become usable.
     *
     * Returns the real, unwrapped component (not the proxy). A component may be
     * attached exactly once; attaching an already-attached component throws (copy
     * it first to attach a variant elsewhere). Use `tryAttach()` if you don't care
     * whether it has already been attached.
     */
    attach(scope: IConstruct, id?: string): this;
    /**
     * Attach the component if it isn't already, without caring *where*.
     *
     * Unlike `attach()`, never throws on an already-attached component: if attached
     * anywhere at all, the existing instance is returned and `scope` is ignored.
     * Use `attach()` when attaching to a specific scope is part of your contract
     * and a pre-existing attachment elsewhere would be a bug.
     */
    tryAttach(scope: IConstruct, id?: string): this;
}
