import * as Brand from "effect/Brand"; /** * Ordered names for the visible components of a stream's ordering key. Names * may repeat, and the sequence may be empty. They are aliases, not document * field paths; implicit ID positions have no visible label. * * @experimental */ export type QueryStreamKeyLabels< Names extends ReadonlyArray = ReadonlyArray, > = Readonly & Brand.Brand<"@confect/server/QueryStreamKeyLabels">; // Tuple operations must use the underlying names: spreading a branded tuple // directly can widen its fixed positions into an array of element unions. // Defer extraction and concatenation until both label types are known to avoid // expanding unresolved tuple types while checking generic stream operations. /** * @experimental */ export type Concat< LeftKeyLabels extends QueryStreamKeyLabels, RightKeyLabels extends QueryStreamKeyLabels, > = LeftKeyLabels extends QueryStreamKeyLabels ? RightKeyLabels extends QueryStreamKeyLabels ? QueryStreamKeyLabels : never : never; const LabelsBrand = Brand.nominal(); /** * Mark a tuple of names as labels without changing its runtime representation. * * @experimental */ export function make>( names: Names, ): QueryStreamKeyLabels; export function make(names: ReadonlyArray): QueryStreamKeyLabels { return LabelsBrand(names); } /** * Check whether the labels start with the given prefix, including order and * multiplicity. The empty prefix always matches. * * @experimental */ export const hasPrefix = ( self: QueryStreamKeyLabels, prefixKeyLabels: QueryStreamKeyLabels, ): boolean => prefixKeyLabels.length <= self.length && prefixKeyLabels.every((label, index) => label === self[index]);