/** * Sort order for ORDER BY clauses. */ export type SortOrder = 'ASC' | 'DESC'; /** * Comparison operators supported in WHERE clauses. */ export type ComparisonOperator = '=' | '!=' | '<' | '<=' | '>' | '>=' | 'LIKE'; /** * Logical operators for combining WHERE conditions. */ export type LogicalOperator = 'AND' | 'OR'; /** * Null handling options for ORDER BY clauses. */ export type NullsOrder = 'NULLS FIRST' | 'NULLS LAST'; /** * Interface for the fluent SOQL query builder. * * Enables dependency injection and testing by decoupling consumers * from the concrete CuneiformQueryBuilder implementation. */ export interface ICuneiformQueryBuilder { select(fields: string[]): this; count(): this; from(objectName: string): this; where(field: string, operator: ComparisonOperator, value: string | number | boolean): this; andWhere(field: string, operator: ComparisonOperator, value: string | number | boolean): this; orWhere(field: string, operator: ComparisonOperator, value: string | number | boolean): this; andWhereIn(field: string, values: Array): this; andWhereNotIn(field: string, values: Array): this; orWhereIn(field: string, values: Array): this; andWhereNull(field: string, isNull?: boolean): this; andWhereDatetime(field: string, operator: ComparisonOperator, datetimeValue: string): this; whereDatetime(field: string, operator: ComparisonOperator, datetimeValue: string): this; orderBy(field: string, order?: SortOrder, nullsOrder?: NullsOrder): this; limit(count: number): this; offset(count: number | undefined): this; groupBy(fields: string[]): this; having(field: string, operator: ComparisonOperator, value: string | number): this; toSOQL(): string; } /** * Fluent query builder for constructing type-safe SOQL queries. * * This class wraps @jetstreamapp/soql-parser-js to provide a fluent API * for building SOQL queries programmatically, replacing ad-hoc string * concatenation patterns throughout the codebase. * * @example Simple query * ```typescript * const soql = new CuneiformQueryBuilder() * .select(['Id', 'Name', 'CreatedDate']) * .from('Account') * .where('Industry', '=', 'Technology') * .orderBy('Name', 'ASC') * .limit(50) * .toSOQL(); * ``` * * @example Aggregate query * ```typescript * const soql = new CuneiformQueryBuilder() * .count() * .from('Account') * .toSOQL(); * // Result: SELECT COUNT() FROM Account * ``` * * @example Complex WHERE with IN clause * ```typescript * const soql = new CuneiformQueryBuilder() * .select(['Id', 'Name']) * .from('PermissionSetAssignment') * .where('AssigneeId', '=', userId) * .andWhereIn('PermissionSet.Name', ['CuneiformUser', 'CuneiformAdmin']) * .toSOQL(); * ``` */ export declare class CuneiformQueryBuilder implements ICuneiformQueryBuilder { private fields; private sObject; private conditions; private firstCondition; private orderByFields; private limitValue; private offsetValue; private groupByFields; private havingCondition; private isCountQuery; /** * Returns a new builder instance (for reuse patterns). * * @returns A new CuneiformQueryBuilder instance */ static create(): CuneiformQueryBuilder; /** * Escapes special characters in SOQL string values. * * @param value - The string value to escape * @returns The escaped string */ private static escapeString; /** * Creates a simple comparison condition. */ private static createCondition; /** * Creates an IN or NOT IN condition. */ private static createInCondition; /** * Specifies the fields to select in the query. * * @param fields - Array of field API names (supports relationship notation like 'Account.Name') * @returns this for method chaining * * @example * ```typescript * builder.select(['Id', 'Name', 'Account.Name', 'CreatedDate']) * ``` */ select(fields: string[]): this; /** * Creates a COUNT() aggregate query. * * When using count(), do not call select() as COUNT() replaces field selection. * * @returns this for method chaining * * @example * ```typescript * const soql = builder.count().from('Account').toSOQL(); * // Result: SELECT COUNT() FROM Account * ``` */ count(): this; /** * Specifies the sObject to query. * * @param objectName - The API name of the Salesforce object * @returns this for method chaining * * @example * ```typescript * builder.from('Account') * builder.from('Profiling_Definition__c') * ``` */ from(objectName: string): this; /** * Adds a WHERE condition to the query. * * This is the initial WHERE condition. Use andWhere() or orWhere() to add additional conditions. * * @param field - The field API name * @param operator - The comparison operator * @param value - The value to compare against (automatically escaped for strings) * @returns this for method chaining * * @example * ```typescript * builder.where('Industry', '=', 'Technology') * builder.where('Amount', '>', 1000) * builder.where('Name', 'LIKE', 'Acme%') * ``` */ where(field: string, operator: ComparisonOperator, value: string | number | boolean): this; /** * Adds an AND condition to the WHERE clause. * * @param field - The field API name * @param operator - The comparison operator * @param value - The value to compare against * @returns this for method chaining * * @example * ```typescript * builder * .where('Industry', '=', 'Technology') * .andWhere('IsActive', '=', true) * .andWhere('Revenue', '>', 1000000) * ``` */ andWhere(field: string, operator: ComparisonOperator, value: string | number | boolean): this; /** * Adds an OR condition to the WHERE clause. * * @param field - The field API name * @param operator - The comparison operator * @param value - The value to compare against * @returns this for method chaining * * @example * ```typescript * builder * .where('Status', '=', 'Active') * .orWhere('Status', '=', 'Pending') * ``` */ orWhere(field: string, operator: ComparisonOperator, value: string | number | boolean): this; /** * Adds an IN clause condition to the WHERE clause with AND logic. * * @param field - The field API name * @param values - Array of values for the IN clause * @returns this for method chaining * * @example * ```typescript * builder.andWhereIn('PermissionSet.Name', ['CuneiformUser', 'CuneiformAdmin']) * // Generates: ... AND PermissionSet.Name IN ('CuneiformUser', 'CuneiformAdmin') * ``` */ andWhereIn(field: string, values: Array): this; /** * Adds a NOT IN clause condition to the WHERE clause with AND logic. * * @param field - The field API name * @param values - Array of values for the NOT IN clause * @returns this for method chaining * * @example * ```typescript * builder.andWhereNotIn('Status', ['Complete', 'Failed', 'Cancelled']) * // Generates: ... AND Status NOT IN ('Complete', 'Failed', 'Cancelled') * ``` */ andWhereNotIn(field: string, values: Array): this; /** * Adds an IN clause condition to the WHERE clause with OR logic. * * @param field - The field API name * @param values - Array of values for the IN clause * @returns this for method chaining */ orWhereIn(field: string, values: Array): this; /** * Adds a NULL check condition with AND logic. * * @param field - The field API name * @param isNull - true for IS NULL, false for IS NOT NULL * @returns this for method chaining * * @example * ```typescript * builder.andWhereNull('ParentId', true) // ParentId = null * builder.andWhereNull('Email', false) // Email != null * ``` */ andWhereNull(field: string, isNull?: boolean): this; /** * Adds a DATETIME literal condition with AND logic. * * DATETIME literals in SOQL are not quoted and follow the format: * YYYY-MM-DDTHH:MM:SSZ (e.g., 2024-01-01T00:00:00Z) * * @param field - The field API name (typically CreatedDate, LastModifiedDate, etc.) * @param operator - The comparison operator * @param datetimeValue - ISO 8601 datetime string (e.g., '2024-01-01T00:00:00Z') * @returns this for method chaining * * @example * ```typescript * builder * .select(['Id']) * .from('Account') * .andWhereDatetime('CreatedDate', '>=', '2024-01-01T00:00:00Z') * .andWhereDatetime('CreatedDate', '<', '2025-01-01T00:00:00Z') * ``` */ andWhereDatetime(field: string, operator: ComparisonOperator, datetimeValue: string): this; /** * Adds a DATETIME literal as the initial WHERE condition. * * @param field - The field API name * @param operator - The comparison operator * @param datetimeValue - ISO 8601 datetime string * @returns this for method chaining */ whereDatetime(field: string, operator: ComparisonOperator, datetimeValue: string): this; /** * Adds an ORDER BY clause. * * @param field - The field API name to sort by * @param order - Sort direction ('ASC' or 'DESC') * @param nullsOrder - Optional null handling ('NULLS FIRST' or 'NULLS LAST') * @returns this for method chaining * * @example * ```typescript * builder.orderBy('Name', 'ASC') * builder.orderBy('CreatedDate', 'DESC', 'NULLS LAST') * ``` */ orderBy(field: string, order?: SortOrder, nullsOrder?: NullsOrder): this; /** * Adds a LIMIT clause to the query. * * @param count - Maximum number of records to return * @returns this for method chaining * * @example * ```typescript * builder.limit(50) * ``` */ limit(count: number): this; /** * Adds an OFFSET clause for pagination. * * @param count - Number of records to skip * @returns this for method chaining * * @example * ```typescript * builder.limit(50).offset(100) // Skip first 100, return next 50 * ``` */ offset(count: number | undefined): this; /** * Adds a GROUP BY clause for aggregate queries. * * @param fields - Array of field API names to group by * @returns this for method chaining * * @example * ```typescript * const soql = builder * .select(['SobjectType']) * .from('RecordType') * .where('IsActive', '=', true) * .groupBy(['SobjectType']) * .toSOQL(); * ``` */ groupBy(fields: string[]): this; /** * Adds a HAVING clause for filtering grouped results. * * @param field - The aggregate function or field to filter on * @param operator - The comparison operator * @param value - The value to compare against * @returns this for method chaining * * @example * ```typescript * builder * .select(['Industry', 'COUNT(Id)']) * .from('Account') * .groupBy(['Industry']) * .having('COUNT(Id)', '>', 5) * ``` */ having(field: string, operator: ComparisonOperator, value: string | number): this; /** * Generates the SOQL query string. * * @returns The complete SOQL query string * @throws Error if required components (fields or sObject) are missing * * @example * ```typescript * const soql = builder * .select(['Id', 'Name']) * .from('Account') * .where('Industry', '=', 'Technology') * .toSOQL(); * // Returns: "SELECT Id, Name FROM Account WHERE Industry = 'Technology'" * ``` */ toSOQL(): string; /** * Validates the query has required components. */ private validate; /** * Adds a condition to the internal list. */ private addCondition; /** * Builds the WHERE clause from accumulated conditions. * * The soql-parser-js library expects WHERE clauses in this format: * A AND B AND C becomes: * { left: A, operator: AND, right: { left: B, operator: AND, right: { left: C } } } * * We build from right to left to create the proper nesting structure. */ private buildWhereClause; }