UNPKG

dynamodb-toolbox

Version:

Lightweight and type-safe query builder for DynamoDB and TypeScript.

61 lines (60 loc) 4.31 kB
import type { ResolvedBinarySchema, ResolvedNumberSchema, ResolvedStringSchema } from '../../../schema/index.js'; import type { IndexNames, IndexSchema } from '../../../table/actions/indexes.js'; import type { Table } from '../../../table/index.js'; import type { GlobalIndex as GlobalSecondaryIndex, Key, KeyType, KeyTypeValue, KeyValue, LocalIndex as LocalSecondaryIndex } from '../../../table/types/index.js'; export type Query<TABLE extends Table = Table> = PrimaryIndexQuery<TABLE> | SecondaryIndexQueries<TABLE>; export type PrimaryIndexQuery<TABLE extends Table = Table> = { index?: undefined; partition: KeyValue<TABLE['partitionKey']>; range?: QueryRange<NonNullable<TABLE['sortKey']>>; }; /** * @debt refactor "Factorize with Condition types" */ type BeginsWithOperator = 'beginsWith'; type BetweenOperator = 'between'; type RangeOperator = 'gt' | 'gte' | 'lt' | 'lte'; type EqualityOperator = 'eq'; export type QueryOperator = EqualityOperator | RangeOperator | BeginsWithOperator | BetweenOperator; type KeyRange<KEY_VALUE extends ResolvedNumberSchema | ResolvedStringSchema | ResolvedBinarySchema> = (RangeOperator extends infer COMPARISON_OPERATOR ? COMPARISON_OPERATOR extends RangeOperator ? { [KEY in COMPARISON_OPERATOR]: KEY_VALUE; } : never : never) | { [KEY in BetweenOperator]: [KEY_VALUE, KEY_VALUE]; } | { [KEY in EqualityOperator]: KEY_VALUE; }; type QueryTypeRange<KEY_TYPE extends KeyType> = (KEY_TYPE extends 'string' ? { [OPERATOR in BeginsWithOperator]: KeyTypeValue<KEY_TYPE>; } | KeyRange<KeyTypeValue<KEY_TYPE>> : never) | (KEY_TYPE extends 'number' ? KeyRange<KeyTypeValue<KEY_TYPE>> : never) | (KEY_TYPE extends 'binary' ? KeyRange<KeyTypeValue<KEY_TYPE>> : never); export type QueryRange<KEY extends Key = Key> = QueryTypeRange<KEY['type']>; export type SecondaryIndexQueries<TABLE extends Table = Table> = { [INDEX_NAME in IndexNames<TABLE>]: SecondaryIndexQuery<TABLE, INDEX_NAME>; }[IndexNames<TABLE>]; export type SecondaryIndexQuery<TABLE extends Table = Table, INDEX_NAME extends IndexNames<TABLE> = IndexNames<TABLE>, INDEX_SCHEMA extends IndexSchema<TABLE, INDEX_NAME> = IndexSchema<TABLE, INDEX_NAME>> = (INDEX_SCHEMA extends LocalSecondaryIndex ? LocalSecondaryIndexQuery<TABLE, INDEX_NAME, INDEX_SCHEMA> : never) | (INDEX_SCHEMA extends GlobalSecondaryIndex ? GlobalSecondaryIndexQuery<INDEX_NAME, INDEX_SCHEMA> : never); export type LocalSecondaryIndexQuery<TABLE extends Table = Table, INDEX_NAME extends string = string, INDEX_SCHEMA extends LocalSecondaryIndex = LocalSecondaryIndex> = { index: INDEX_NAME; partition: KeyValue<TABLE['partitionKey']>; range?: QueryRange<INDEX_SCHEMA['sortKey']>; }; export type GlobalSecondaryIndexQuery<INDEX_NAME extends string = string, INDEX_SCHEMA extends GlobalSecondaryIndex = GlobalSecondaryIndex> = { index: INDEX_NAME; partition: (INDEX_SCHEMA extends { readonly partitionKey: Key; } ? KeyValue<INDEX_SCHEMA['partitionKey']> : never) | (INDEX_SCHEMA extends { readonly partitionKeys: readonly Key[]; } ? KeyValueRec<INDEX_SCHEMA['partitionKeys']> : never); range?: (INDEX_SCHEMA extends { readonly sortKey?: Key; } ? QueryRange<NonNullable<INDEX_SCHEMA['sortKey']>> : never) | (INDEX_SCHEMA extends { readonly sortKeys?: readonly Key[]; } ? QueryRangeRec<NonNullable<INDEX_SCHEMA['sortKeys']>> : never); }; type KeyValueRec<KEYS extends readonly Key[], KEY_VALUES extends KeyValue[] = []> = KEYS extends [ infer KEYS_HEAD, ...infer KEYS_TAIL ] ? KEYS_TAIL extends readonly Key[] ? KEYS_HEAD extends Key ? KeyValueRec<KEYS_TAIL, [...KEY_VALUES, KeyValue<KEYS_HEAD>]> : never : never : number extends KEYS['length'] ? KeyValue<KEYS[number]>[] : KEY_VALUES; type QueryRangeRec<KEYS extends readonly Key[], PREV_KEY_VALUES extends KeyValue[] = [], QUERY_RANGES extends (KeyValue | QueryRange)[] = []> = KEYS extends [infer KEYS_HEAD, ...infer KEYS_TAIL] ? KEYS_TAIL extends readonly Key[] ? KEYS_HEAD extends Key ? QueryRangeRec<KEYS_TAIL, [ ...PREV_KEY_VALUES, KeyValue<KEYS_HEAD> ], QUERY_RANGES | [...PREV_KEY_VALUES, KeyValue<KEYS_HEAD> | QueryRange<KEYS_HEAD>]> : never : never : number extends KEYS['length'] ? (KeyValue<KEYS[number]> | QueryRange<KEYS[number]>)[] : QUERY_RANGES; export {};