export type AttributeKey = string;
export type AttributeValue = string | number | boolean | Date | null | undefined;
export interface Context {
    [key: AttributeKey]: AttributeValue;
}
export type AttributeType = "boolean" | "string" | "integer" | "double" | "date" | "semver";
export interface Attribute {
    archived?: boolean;
    key: AttributeKey;
    type: AttributeType;
    capture?: boolean;
    description?: string;
}
export type Operator = "equals" | "notEquals" | "greaterThan" | "greaterThanOrEquals" | "lessThan" | "lessThanOrEquals" | "contains" | "notContains" | "startsWith" | "endsWith" | "semverEquals" | "semverNotEquals" | "semverGreaterThan" | "semverGreaterThanOrEquals" | "semverLessThan" | "semverLessThanOrEquals" | "before" | "after" | "in" | "notIn";
export type ConditionValue = string | number | boolean | Date | null | undefined | string[];
export interface PlainCondition {
    attribute: AttributeKey;
    operator: Operator;
    value: ConditionValue;
}
export interface AndCondition {
    and: Condition[];
}
export interface OrCondition {
    or: Condition[];
}
export interface NotCondition {
    not: Condition[];
}
export type AndOrNotCondition = AndCondition | OrCondition | NotCondition;
export type Condition = PlainCondition | AndOrNotCondition;
export type SegmentKey = string;
export interface Segment {
    archived?: boolean;
    key: SegmentKey;
    conditions: Condition | Condition[] | string;
    description?: string;
}
export type PlainGroupSegment = SegmentKey;
export interface AndGroupSegment {
    and: GroupSegment[];
}
export interface OrGroupSegment {
    or: GroupSegment[];
}
export interface NotGroupSegment {
    not: GroupSegment[];
}
export type AndOrNotGroupSegment = AndGroupSegment | OrGroupSegment | NotGroupSegment;
export type GroupSegment = PlainGroupSegment | AndOrNotGroupSegment;
export type VariationValue = string;
export type VariableKey = string;
export type VariableType = "boolean" | "string" | "integer" | "double" | "array" | "object" | "json";
export interface VariableObjectValue {
    [key: string]: VariableValue;
}
export type VariableValue = boolean | string | number | string[] | VariableObjectValue | null | undefined;
export interface VariableOverrideSegments {
    segments: GroupSegment | GroupSegment[];
}
export interface VariableOverrideConditions {
    conditions: Condition | Condition[];
}
export interface VariableOverrideBase {
    value: VariableValue;
}
export type VariableOverrideSegmentsOrConditions = VariableOverrideSegments | VariableOverrideConditions;
export interface VariableOverride {
    value: VariableValue;
    conditions?: Condition | Condition[];
    segments?: GroupSegment | GroupSegment[];
}
export interface Variable {
    key: VariableKey;
    value: VariableValue;
    description?: string;
    overrides?: VariableOverride[];
}
export interface Variation {
    description?: string;
    value: VariationValue;
    weight?: Weight;
    variables?: Variable[];
}
export interface VariableSchema {
    deprecated?: boolean;
    key: VariableKey;
    type: VariableType;
    defaultValue: VariableValue;
    description?: string;
}
export type FeatureKey = string;
export interface Force {
    conditions?: Condition | Condition[];
    segments?: GroupSegment | GroupSegment[];
    enabled?: boolean;
    variation?: VariationValue;
    variables?: {
        [key: string]: VariableValue;
    };
}
export interface Slot {
    feature: FeatureKey | false;
    percentage: Weight;
}
export interface Group {
    key: string;
    description: string;
    slots: Slot[];
}
export type BucketKey = string;
export type BucketValue = number;
/**
 * Datafile-only types
 */
export type Percentage = number;
export type Range = [Percentage, Percentage];
export interface Allocation {
    variation: VariationValue;
    range: Range;
}
export interface Traffic {
    key: RuleKey;
    segments: GroupSegment | GroupSegment[] | "*";
    percentage: Percentage;
    enabled?: boolean;
    variation?: VariationValue;
    variables?: {
        [key: string]: VariableValue;
    };
    allocation: Allocation[];
}
export type PlainBucketBy = AttributeKey;
export type AndBucketBy = AttributeKey[];
export interface OrBucketBy {
    or: AttributeKey[];
}
export type BucketBy = PlainBucketBy | AndBucketBy | OrBucketBy;
export interface RequiredWithVariation {
    key: FeatureKey;
    variation: VariationValue;
}
export type Required = FeatureKey | RequiredWithVariation;
export interface Feature {
    key: FeatureKey;
    deprecated?: boolean;
    required?: Required[];
    variablesSchema?: VariableSchema[] | Record<VariableKey, VariableSchema>;
    variations?: Variation[];
    bucketBy: BucketBy;
    traffic: Traffic[];
    force?: Force[];
    ranges?: Range[];
}
export interface DatafileContentV1 {
    schemaVersion: string;
    revision: string;
    attributes: Attribute[];
    segments: Segment[];
    features: Feature[];
}
export interface DatafileContentV2 {
    schemaVersion: string;
    revision: string;
    attributes: {
        [key: AttributeKey]: Attribute;
    };
    segments: {
        [key: SegmentKey]: Segment;
    };
    features: {
        [key: FeatureKey]: Feature;
    };
}
export type DatafileContent = DatafileContentV1 | DatafileContentV2;
export interface OverrideFeature {
    enabled: boolean;
    variation?: VariationValue;
    variables?: {
        [key: VariableKey]: VariableValue;
    };
}
export interface StickyFeatures {
    [key: FeatureKey]: OverrideFeature;
}
export type InitialFeatures = StickyFeatures;
/**
 * YAML-only type
 */
export type Weight = number;
export type EnvironmentKey = string;
export type RuleKey = string;
export interface Rule {
    key: RuleKey;
    description?: string;
    segments: GroupSegment | GroupSegment[];
    percentage: Weight;
    enabled?: boolean;
    variation?: VariationValue;
    variables?: {
        [key: string]: VariableValue;
    };
}
export type Tag = string;
export type Expose = boolean | Tag[];
export interface Environment {
    expose?: Expose;
    rules: Rule[];
    force?: Force[];
}
export interface ParsedFeature {
    key: FeatureKey;
    archived?: boolean;
    deprecated?: boolean;
    description: string;
    tags: Tag[];
    required?: Required[];
    bucketBy: BucketBy;
    variablesSchema?: VariableSchema[];
    variations?: Variation[];
    environments?: {
        [key: EnvironmentKey]: Environment;
    };
    expose?: Expose;
    rules?: Rule[];
    force?: Force[];
}
/**
 * For maintaining old allocations info,
 * allowing for gradual rollout of new allocations
 * with consistent bucketing
 */
export interface ExistingFeature {
    variations?: {
        value: VariationValue;
        weight: Weight;
    }[];
    traffic: {
        key: RuleKey;
        percentage: Percentage;
        allocation: Allocation[];
    }[];
    ranges?: Range[];
}
export interface ExistingFeatures {
    [key: FeatureKey]: ExistingFeature;
}
export interface ExistingState {
    features: ExistingFeatures;
}
/**
 * Tests
 */
export interface AssertionMatrix {
    [key: string]: AttributeValue[];
}
export interface FeatureAssertion {
    matrix?: AssertionMatrix;
    description?: string;
    environment: EnvironmentKey;
    at: Weight;
    context: Context;
    expectedToBeEnabled: boolean;
    expectedVariation?: VariationValue;
    expectedVariables?: {
        [key: VariableKey]: VariableValue;
    };
}
export interface TestFeature {
    feature: FeatureKey;
    assertions: FeatureAssertion[];
}
export interface SegmentAssertion {
    matrix?: AssertionMatrix;
    description?: string;
    context: Context;
    expectedToMatch: boolean;
}
export interface TestSegment {
    segment: SegmentKey;
    assertions: SegmentAssertion[];
}
export type Test = TestSegment | TestFeature;
export interface TestResultAssertionError {
    type: "flag" | "variation" | "variable" | "segment";
    expected: string | number | boolean | Date | null | undefined;
    actual: string | number | boolean | Date | null | undefined;
    message?: string;
    details?: object;
}
export interface TestResultAssertion {
    description: string;
    duration: number;
    passed: boolean;
    errors?: TestResultAssertionError[];
}
export interface TestResult {
    type: "feature" | "segment";
    key: string;
    notFound?: boolean;
    passed: boolean;
    duration: number;
    assertions: TestResultAssertion[];
}
/**
 * Site index and history
 */
export type EntityType = "attribute" | "segment" | "feature" | "group" | "test";
export type CommitHash = string;
export interface HistoryEntity {
    type: EntityType;
    key: string;
}
export interface HistoryEntry {
    commit: CommitHash;
    author: string;
    timestamp: string;
    entities: HistoryEntity[];
}
export interface LastModified {
    commit: CommitHash;
    timestamp: string;
    author: string;
}
export interface SearchIndex {
    links?: {
        feature: string;
        segment: string;
        attribute: string;
        commit: CommitHash;
    };
    projectConfig: {
        tags: Tag[];
        environments: EnvironmentKey[] | false;
    };
    entities: {
        attributes: (Attribute & {
            lastModified?: LastModified;
            usedInSegments: SegmentKey[];
            usedInFeatures: FeatureKey[];
        })[];
        segments: (Segment & {
            lastModified?: LastModified;
            usedInFeatures: FeatureKey[];
        })[];
        features: (ParsedFeature & {
            lastModified?: LastModified;
        })[];
    };
}
export interface EntityDiff {
    type: EntityType;
    key: string;
    created?: boolean;
    deleted?: boolean;
    updated?: boolean;
    content?: string;
}
export interface Commit {
    hash: CommitHash;
    author: string;
    timestamp: string;
    entities: EntityDiff[];
}
