import type { ShellArray } from './array.ts';
/** What a shell variable can hold. */
export type ShellValue = string | ShellArray | Record<string, string>;
export type Coercer = (text: string) => string;
/**
 * One bash variable attribute, spelled as its `declare` letter.
 *
 * Declaration order is the order `declare -p` prints a cluster in,
 * pinned exhaustively against bash 5.2.37 over all 72 ordered pairs of
 * `a A i l n r t u x`: `a`/`A` first, then `i n r t x`, then `l`/`u`. It
 * is bash's own internal order, not the order the letters were typed in
 * (`declare -xri` prints `-irx`), and not alphabetical.
 *
 * `-a` and `-A` are deliberately absent: whether a variable is an
 * indexed array, an associative array or a scalar is what its value
 * *is*, so storing it a second time as an attribute would let the two
 * contradict each other. `attrLetters` derives them from the value.
 */
export declare enum VarAttr {
    Integer = "i",
    Nameref = "n",
    Readonly = "r",
    Trace = "t",
    Export = "x",
    Lower = "l",
    Upper = "u"
}
/** What a variable's value is, derived from the value itself. */
export declare enum VarKind {
    Scalar = "scalar",
    Indexed = "indexed",
    Assoc = "assoc"
}
/**
 * Where a managed variable's value comes from.
 *
 * A managed variable is an ordinary `ShellVar` carrying one of these:
 * the pointer is host configuration (a YAML/in-app env entry), never
 * something an agent line can spell, and it is what serializes -- the
 * fetched value never does. All fill-step state rides here so a
 * session can carry managed entries the workspace never declared.
 *
 * `source` is the registered source name (`env`, `dotenv`, `aws-sm`,
 * or a user-registered one); `ref` the source's address for one secret
 * (a secret id, a dotenv path; `''` where the source has no
 * sub-address); `key` which field of the fetched secret this variable
 * reads (the variable's own name at declaration by default); `eager`
 * joins every line's fetch set instead of waiting for a line that
 * references the name.
 */
export interface ManagedRef {
    readonly source: string;
    readonly ref: string;
    readonly key: string;
    readonly eager: boolean;
}
/**
 * One shell variable: a value plus the attributes set on it.
 *
 * Readonly on purpose. Every writer already computes its result on a
 * copy and hands the finished value to the session view (`[...arr]`
 * before an element write, and so on), precisely so a refused write
 * leaves nothing half-applied. Making the record immutable turns that
 * convention into something the type enforces: the only way to change a
 * variable is to hand the session view a new record, so a policy gate cannot be
 * walked around by reaching into storage.
 *
 * `value` is null in bash's third state: declared with attributes but
 * *unset*, which `readonly NAME` and `export NAME` on a fresh name both
 * produce. It is not the empty string -- GNU prints `declare -r ONLY`
 * for one and `declare -r EMPTY=""` for the other, `${ONLY-d}` expands
 * to `d` while `${EMPTY-d}` does not, and `env` carries the empty one
 * but not the unset one.
 */
export interface ShellVar {
    readonly value: ShellValue | null;
    readonly attrs: ReadonlySet<VarAttr>;
    /**
     * Set when the value comes from a secrets source. Unfetched is
     * exactly the third state above: value null with attributes, so
     * `envSnapshot`'s existing value check already omits it. `withValue`
     * deliberately carries this field (the fill step writes through it)
     * and `detach` is the agent-write arm.
     */
    readonly managed?: ManagedRef;
}
/**
 * The records a prefix assignment shadowed for one function call.
 *
 * bash runs `x=1 f` with `x` in a scope of its own around the function,
 * its temporary environment: the caller's value comes back when the call
 * returns, `unset x` inside reveals it, and an `export` or `readonly` of
 * the name lets the value outlive the call. A frame of this type on the
 * call path is that scope; a plain frame holds a function's `local`
 * shadows.
 */
export declare class TempEnv extends Map<string, ShellVar | null> {
}
/** Build a variable record. */
export declare function makeVar(value?: ShellValue | null, attrs?: ReadonlySet<VarAttr>): ShellVar;
/**
 * What kind of variable this is, read off its value.
 *
 * An unset variable reads as a scalar: bash renders `declare -i n` with
 * no `-a`, so nothing but an actual array value earns the letter.
 */
export declare function varKind(v: ShellVar): VarKind;
/** Copy a variable and its mutable array value for a child shell. */
export declare function copyVar(v: ShellVar): ShellVar;
/**
 * The variable with a new value and the same attributes, but a reference's
 * under an array: bash's reference cannot hold one, so `declare -n r;
 * r=(x)` leaves `declare -a r`.
 */
export declare function withValue(v: ShellVar, value: ShellValue | null): ShellVar;
/**
 * The variable with its managed pointer dropped, value kept.
 *
 * An agent write to a managed name shadows session-locally: the record
 * becomes a plain variable for this session only, so the fill step
 * never clobbers it and the declaration (new sessions fetch fresh) and
 * the remote store are untouched by construction.
 */
export declare function detach(v: ShellVar): ShellVar;
/**
 * The variable with one attribute turned on or off. `+attr` is the off
 * direction, which is why this takes a flag rather than being two
 * functions.
 */
export declare function withAttr(v: ShellVar, attr: VarAttr, on?: boolean): ShellVar;
/**
 * The stored attribute letters, in `declare -p` print order.
 *
 * The tail of `attrLetters` without the `a`/`A` kind lead, which is
 * derived rather than stored. Split out because two callers want the
 * stored half alone: the serializer, which must not write a letter it
 * would then read back as an attribute the value already implies, and
 * `attrLetters` itself.
 */
/**
 * Apply the value-shaping attributes to one scalar being stored.
 *
 * bash applies these at assignment, not at read: `declare -l s; s=ABC`
 * stores `abc`, and `declare -i n; n=2+2` stores `4`, so `declare -p`
 * and `$s` agree with no per-read work. Order is integer first, then
 * case, which only matters for hex digits and is what GNU does
 * (`declare -il n=0xA` stores `10`). `-l` and `-u` cannot both hold; a
 * declaration that sets one clears the other, so at most one applies.
 */
export declare function coerceScalar(text: string, attrs: ReadonlySet<VarAttr>, integer: Coercer | null): string;
/**
 * `coerceScalar` lifted over every value shape. An array applies the
 * attribute per element, which is GNU's `declare -ai a=(1+1 2*3)` giving
 * `([0]="2" [1]="6")`. A write that assigns some elements only (`a[1]=x`,
 * `a=x`) names them in `assigned`, and the others are carried over as
 * stored: bash shapes a value when it is assigned, so `declare -i a;
 * a[0]=9` never re-evaluates a stored `a[1]`.
 */
export declare function coerceValue(value: ShellValue, attrs: ReadonlySet<VarAttr>, integer: Coercer | null, assigned?: ReadonlySet<number | string> | null): ShellValue;
export declare function storedAttrs(v: ShellVar): string;
/**
 * The attribute set a stored letter cluster spells, the inverse of
 * `storedAttrs`, used when a persisted session is read back. A letter
 * that names no attribute is ignored rather than throwing: the store is
 * shared with the other language and with future versions, and refusing
 * to load a session because one letter is unknown loses far more than
 * the letter.
 */
export declare function attrsFromLetters(letters: string): ReadonlySet<VarAttr>;
/**
 * The attribute cluster `declare -p` prints for this variable.
 *
 * `-a`/`-A` come from the value's kind and lead, then the stored
 * attributes in print order. bash prints `--` for a plain scalar with
 * nothing set, which is the caller's to render since only it knows it is
 * writing a `declare` line.
 */
export declare function attrLetters(v: ShellVar): string;
//# sourceMappingURL=variable.d.ts.map