nukak
Version:
flexible and efficient ORM, with declarative JSON syntax and smart type-safety
457 lines (456 loc) • 11.7 kB
TypeScript
import type { FieldKey, IdValue, Key, RelationKey } from './entity.js';
import type { BooleanLike, ExpandScalar, Scalar, Type, Unpacked } from './utility.js';
export type QueryOptions = {
/**
* use or omit `softDelete` attribute.
*/
softDelete?: boolean;
/**
* prefix the query with this.
*/
prefix?: string;
/**
* automatically infer the prefix for the query.
*/
autoPrefix?: boolean;
};
export type QuerySelectOptions = {
/**
* prefix the query with this.
*/
prefix?: string;
/**
* automatically add the prefix for the alias.
*/
autoPrefixAlias?: boolean;
};
/**
* query selection as an array.
*/
export type QuerySelectArray<E> = (Key<E> | QueryRaw)[];
/**
* query selection as a map.
*/
export type QuerySelectMap<E> = QuerySelectFieldMap<E> | QuerySelectRelationMap<E>;
/**
* query selection.
*/
export type QuerySelect<E> = QuerySelectArray<E> | QuerySelectMap<E>;
/**
* query selection of fields as a map.
*/
export type QuerySelectFieldMap<E> = {
[K in FieldKey<E>]?: BooleanLike;
};
/**
* query conflict paths map.
*/
export type QueryConflictPathsMap<E> = {
[K in FieldKey<E>]?: true;
};
/**
* query conflict paths.
*/
export type QueryConflictPaths<E> = QueryConflictPathsMap<E>;
/**
* query selection of relations as a map.
*/
export type QuerySelectRelationMap<E> = {
[K in RelationKey<E>]?: BooleanLike | Key<Unpacked<E[K]>>[] | QuerySelectRelationOptions<E[K]>;
};
/**
* options to select a relation.
*/
export type QuerySelectRelationOptions<E> = (E extends unknown[] ? Query<Unpacked<E>> : QueryUnique<Unpacked<E>>) & {
$required?: boolean;
};
/**
* options for full-text-search operator.
*/
export type QueryTextSearchOptions<E> = {
/**
* text to search for.
*/
$value: string;
/**
* list of fields to search on.
*/
$fields?: FieldKey<E>[];
};
/**
* comparison by fields.
*/
export type QueryWhereFieldMap<E> = {
[K in FieldKey<E>]?: QueryWhereFieldValue<E[K]>;
};
/**
* complex operators.
*/
export type QueryWhereMap<E> = QueryWhereFieldMap<E> & QueryWhereRootOperator<E>;
export type QueryWhereRootOperator<E> = {
/**
* joins query clauses with a logical `AND`, returns records that match all the clauses.
*/
$and?: QueryWhereArray<E>;
/**
* joins query clauses with a logical `OR`, returns records that match any of the clauses.
*/
$or?: QueryWhereArray<E>;
/**
* joins query clauses with a logical `AND`, returns records that do not match all the clauses.
*/
$not?: QueryWhereArray<E>;
/**
* joins query clauses with a logical `OR`, returns records that do not match any of the clauses.
*/
$nor?: QueryWhereArray<E>;
/**
* whether the specified fields match against a full-text search of the given string.
*/
$text?: QueryTextSearchOptions<E>;
/**
* whether the record exists in the given sub-query.
*/
$exists?: QueryRaw;
/**
* whether the record does not exists in the given sub-query.
*/
$nexists?: QueryRaw;
};
export type QueryWhereFieldOperatorMap<T> = {
/**
* whether a value is equal to the given value.
*/
$eq?: ExpandScalar<T>;
/**
* whether a value is not equal to the given value.
*/
$ne?: ExpandScalar<T>;
/**
* negates the given comparison.
*/
$not?: QueryWhereFieldValue<T>;
/**
* whether a value is less than the given value.
*/
$lt?: ExpandScalar<T>;
/**
* whether a value is less than or equal to the given value.
*/
$lte?: ExpandScalar<T>;
/**
* whether a value is greater than the given value.
*/
$gt?: ExpandScalar<T>;
/**
* whether a value is greater than or equal to the given value.
*/
$gte?: ExpandScalar<T>;
/**
* whether a string begins with the given string (case sensitive).
*/
$startsWith?: string;
/**
* whether a string begins with the given string (case insensitive).
*/
$istartsWith?: string;
/**
* whether a string ends with the given string (case sensitive).
*/
$endsWith?: string;
/**
* whether a string ends with the given string (case insensitive).
*/
$iendsWith?: string;
/**
* whether a string is contained within the given string (case sensitive).
*/
$includes?: string;
/**
* whether a string is contained within the given string (case insensitive).
*/
$iincludes?: string;
/**
* whether a string fulfills the given pattern (case sensitive).
*/
$like?: string;
/**
* whether a string fulfills the given pattern (case insensitive).
*/
$ilike?: string;
/**
* whether a string matches the given regular expression.
*/
$regex?: string;
/**
* whether a value matches any of the given values.
*/
$in?: ExpandScalar<T>[];
/**
* whether a value does not match any of the given values.
*/
$nin?: ExpandScalar<T>[];
};
/**
* Value for a field comparison.
*/
export type QueryWhereFieldValue<T> = T | T[] | QueryWhereFieldOperatorMap<T> | QueryRaw;
/**
* query single filter.
*/
export type QueryWhereSingle<E> = IdValue<E> | IdValue<E>[] | QueryWhereMap<E> | QueryRaw;
/**
* query filter array.
*/
export type QueryWhereArray<E> = QueryWhereSingle<E>[];
/**
* query filter.
*/
export type QueryWhere<E> = QueryWhereSingle<E> | QueryWhereArray<E>;
/**
* direction for the sort.
*/
export type QuerySortDirection = -1 | 1 | 'asc' | 'desc';
/**
* sort by tuples
*/
export type QuerySortTuples<E> = [FieldKey<E>, QuerySortDirection][];
/**
* sort by objects.
*/
export type QuerySortObjects<E> = {
field: FieldKey<E>;
sort: QuerySortDirection;
}[];
/**
* sort by fields.
*/
export type QuerySortFieldMap<E> = {
[K in FieldKey<E>]?: QuerySortDirection;
};
/**
* sort by relations fields.
*/
export type QuerySortRelationMap<E> = {
[K in RelationKey<E>]?: QuerySortMap<Unpacked<E[K]>>;
};
/**
* sort by map.
*/
export type QuerySortMap<E> = QuerySortFieldMap<E> | QuerySortRelationMap<E>;
/**
* sort options.
*/
export type QuerySort<E> = QuerySortMap<E> | QuerySortTuples<E> | QuerySortObjects<E>;
/**
* pager options.
*/
export type QueryPager = {
/**
* Index from where start the search
*/
$skip?: number;
/**
* Max number of records to retrieve
*/
$limit?: number;
};
/**
* search options.
*/
export type QuerySearch<E> = {
/**
* filtering options.
*/
$where?: QueryWhere<E>;
/**
* sorting options.
*/
$sort?: QuerySort<E>;
} & QueryPager;
/**
* criteria one options.
*/
export type QuerySearchOne<E> = Omit<QuerySearch<E>, '$limit'>;
/**
* query options.
*/
export type Query<E> = {
/**
* selection options.
*/
$select?: QuerySelect<E>;
} & QuerySearch<E>;
/**
* options to get a single record.
*/
export type QueryOne<E> = Omit<Query<E>, '$limit'>;
/**
* options to get an unique record.
*/
export type QueryUnique<E> = Pick<QueryOne<E>, '$select' | '$where'>;
/**
* stringified query.
*/
export type QueryStringified = {
[K in keyof Query<unknown>]?: string;
};
/**
* result of an update operation.
*/
export type QueryUpdateResult = {
/**
* number of affected records.
*/
changes?: number;
/**
* the inserted IDs.
*/
ids?: number[] | string[];
/**
* first inserted ID.
*/
firstId?: number | string;
};
/**
* options for the `raw` function.
*/
export type QueryRawFnOptions = {
/**
* the current dialect.
*/
dialect?: QueryDialect;
/**
* the prefix.
*/
prefix?: string;
/**
* the escaped prefix.
*/
escapedPrefix?: string;
/**
* the query context.
*/
ctx?: QueryContext;
};
/**
* a `raw` function
*/
export type QueryRawFn = (opts?: QueryRawFnOptions) => void | Scalar;
export declare class QueryRaw {
readonly value: Scalar | QueryRawFn;
readonly alias?: string;
constructor(value: Scalar | QueryRawFn, alias?: string);
}
/**
* comparison options.
*/
export type QueryComparisonOptions = QueryOptions & {
/**
* use precedence for the comparison or not.
*/
usePrecedence?: boolean;
};
/**
* query filter options.
*/
export type QueryWhereOptions = QueryComparisonOptions & {
/**
* clause to be used in the filter.
*/
clause?: 'WHERE' | false;
};
export interface QueryContext {
append(sql: string): this;
addValue(value: unknown): this;
pushValue(value: unknown): this;
readonly sql: string;
readonly values: unknown[];
}
export interface QueryDialect {
/**
* obtains the records matching the given search parameters.
* @param ctx the query context
* @param entity the target entity
* @param q the criteria options
* @param opts the query options
*/
find<E>(ctx: QueryContext, entity: Type<E>, q: Query<E>, opts?: QueryOptions): void;
/**
* counts the number of records matching the given search parameters.
* @param ctx the query context
* @param entity the target entity
* @param q the criteria options
* @param opts the query options
*/
count<E>(ctx: QueryContext, entity: Type<E>, q: QuerySearch<E>, opts?: QueryOptions): void;
/**
* insert records.
* @param ctx the query context
* @param entity the target entity
* @param payload the payload
* @param opts the query options
*/
insert<E>(ctx: QueryContext, entity: Type<E>, payload: E | E[], opts?: QueryOptions): void;
/**
* update records.
* @param ctx the query context
* @param entity the target entity
* @param q the criteria options
* @param payload
* @param opts the query options
*/
update<E>(ctx: QueryContext, entity: Type<E>, q: QuerySearch<E>, payload: E, opts?: QueryOptions): void;
/**
* upsert records.
* @param ctx the query context
* @param entity the target entity
* @param conflictPaths the conflict paths
* @param payload
*/
upsert<E>(ctx: QueryContext, entity: Type<E>, conflictPaths: QueryConflictPaths<E>, payload: E): void;
/**
* delete records.
* @param ctx the query context
* @param entity the target entity
* @param q the criteria options
* @param opts the query options
*/
delete<E>(ctx: QueryContext, entity: Type<E>, q: QuerySearch<E>, opts?: QueryOptions): void;
/**
* escape an identifier.
* @param val the value to be escaped
* @param forbidQualified don't escape dots
* @param addDot use a dot as suffix
*/
escapeId(val: string, forbidQualified?: boolean, addDot?: boolean): string;
/**
* escape a value.
* @param val the value to escape
*/
escape(val: unknown): string;
/**
* add a value to the query.
* @param values the values array
* @param value the value to add
*/
addValue(values: unknown[], value: unknown): string;
/**
* create a new query context.
*/
createContext(): QueryContext;
}
/**
* Minimal dialect interface exposing escapeIdChar for SQL operations
*/
export interface SqlQueryDialect extends QueryDialect {
/**
* the escape character for identifiers.
*/
readonly escapeIdChar: '"' | '`';
/**
* Get the placeholder for a parameter at the given index (1-based).
* Default: '?' for MySQL/MariaDB/SQLite, '$n' for PostgreSQL.
*/
placeholder(index: number): string;
}