/** * The subscriber filter model. * * Substack's own dashboard encodes a filter by gluing an operator suffix onto * the column name: `num_comments_gt`, `user_email_address_similar_to`, * `subscription_created_at_gte`. That is fine for a UI that knows the mapping * and hostile to anything constructing it blind, because the suffix depends on * the column's type and several suffixes read nothing like the operator they * implement. * * So callers name a column and an intent (`is_not`, `is_before`, `contains`) * and the suffix is derived here from the column's type. A wrong operator for a * column is refused with the valid list rather than sent upstream to become an * opaque 400. */ export type ColumnType = "Int" | "String" | "DateTime" | "Array" | "subscription_type" | "group_membership"; export type Operator = "is" | "is_not" | "gt" | "gte" | "lt" | "lte" | "is_any_of" | "contains" | "starts_with" | "ends_with" | "is_on" | "is_after" | "is_on_or_after" | "is_before" | "is_on_or_before" | "includes_any" | "includes_all" | "includes_none"; /** Column type to the operators it accepts, and the suffix each one sends. */ export declare const OPERATORS_BY_TYPE: Record>>; /** Operators whose value must be a list. Anything else must be a scalar. */ export declare const LIST_OPERATORS: Set; export declare const SUBSCRIPTION_TYPES: readonly ["paid", "free", "founding", "comp", "gift", "free_trial", "iap"]; export declare const GROUP_MEMBERSHIPS: readonly ["none", "member", "admin"]; export type ColumnSpec = { type: ColumnType; /** What the Substack dashboard calls it, which is how a caller will refer to it. */ label: string; values?: readonly string[]; /** Filterable but not exportable. Substack drops these from a CSV silently. */ exportable?: boolean; }; export declare const SUBSCRIBER_COLUMNS: Record; export declare const COLUMN_NAMES: string[]; /** Columns Substack will actually put in a CSV export. */ export declare const EXPORTABLE_COLUMNS: string[]; export type Filter = { column: string; operator: Operator; value: unknown; }; /** * Build the request body Substack expects. * * Conditions combine with AND. There is no OR and no nesting, which is a limit * of the endpoint rather than of this code: anything needing OR has to be * issued as separate calls and merged by the caller. */ export declare function buildQuery(options: { filters?: Filter[]; search?: string; sortBy?: string; sortDirection?: "asc" | "desc"; limit?: number; offset?: number; }): Record; /** A compact reference for the tool description, so a model does not guess names. */ export declare function columnReference(): string;