dynamodb-toolbox
Version:
A simple set of tools for working with Amazon DynamoDB and the DocumentClient.
326 lines (325 loc) • 20.1 kB
TypeScript
import type { A, B, O, F } from 'ts-toolbelt';
import { NativeAttributeValue } from '@aws-sdk/util-dynamodb';
import { ReturnConsumedCapacity, ReturnItemCollectionMetrics } from '@aws-sdk/client-dynamodb';
import type { Compute, FirstDefined, If } from '../../lib/utils.js';
import type { DynamoDBKeyTypes, DynamoDBTypes, $QueryOptions, TableDef } from '../Table/types.js';
import Entity from './Entity.js';
import { UpdateCommandInput } from '@aws-sdk/lib-dynamodb';
export interface EntityConstructor<EntityTable extends TableDef | undefined = undefined, Name extends string = string, AutoExecute extends boolean = true, AutoParse extends boolean = true, Timestamps extends boolean = true, CreatedAlias extends string = 'created', ModifiedAlias extends string = 'modified', TypeAlias extends string = 'entity', TypeHidden extends boolean = false, ReadonlyAttributeDefinitions extends Readonly<AttributeDefinitions> = Readonly<AttributeDefinitions>> {
table?: EntityTable;
name: Name;
timestamps?: Timestamps;
created?: string;
modified?: string;
createdAlias?: CreatedAlias;
modifiedAlias?: ModifiedAlias;
typeAlias?: TypeAlias;
typeHidden?: TypeHidden;
attributes: ReadonlyAttributeDefinitions;
autoExecute?: AutoExecute;
autoParse?: AutoParse;
}
export declare type KeyAttributeDefinition = {
type: 'string' | 'number' | 'bigint' | 'binary';
default: any;
hidden: boolean;
delimiter: string;
prefix: string;
suffix: string;
onUpdate: boolean;
dependsOn: string | string[];
transform: (value: any, data: any) => any;
format: (value: any, data: any) => any;
coerce: boolean;
save: never;
required: never;
alias: never;
map: never;
setType: never;
};
export declare type PartitionKeyDefinition = Partial<KeyAttributeDefinition> & {
partitionKey: true;
sortKey?: false;
};
export declare type GSIPartitionKeyDefinition = Partial<KeyAttributeDefinition> & {
partitionKey: string;
sortKey?: false;
};
export declare type SortKeyDefinition = Partial<KeyAttributeDefinition> & {
sortKey: true;
partitionKey?: false;
};
export declare type GSISortKeyDefinition = Partial<KeyAttributeDefinition> & {
partitionKey?: false;
sortKey: string;
};
export declare type PureAttributeDefinition = Partial<{
partitionKey: false;
sortKey: false;
type: DynamoDBTypes;
default: any | ((data: object) => any);
dependsOn: string | string[];
transform: (value: any, data: {}) => any;
format: (value: any, data: {}) => any;
coerce: boolean;
save: boolean;
onUpdate: boolean;
hidden: boolean;
required: boolean | 'always';
alias: string;
map: string;
setType: DynamoDBKeyTypes;
delimiter: string;
prefix: string;
suffix: string;
}>;
export declare type CompositeAttributeDefinition = [string, number] | [string, number, DynamoDBTypes] | [string, number, PureAttributeDefinition];
export declare type AttributeDefinition = DynamoDBTypes | PartitionKeyDefinition | SortKeyDefinition | GSIPartitionKeyDefinition | GSISortKeyDefinition | PureAttributeDefinition | CompositeAttributeDefinition;
export declare type AttributeDefinitions = Record<A.Key, AttributeDefinition>;
export declare type InferKeyAttribute<Definitions extends AttributeDefinitions, KeyType extends 'partitionKey' | 'sortKey'> = O.SelectKeys<Definitions, Record<KeyType, true>>;
export declare type InferMappedAttributes<Definitions extends AttributeDefinitions, AttributeName extends A.Key> = O.SelectKeys<Definitions, [AttributeName, any, any?]>;
export interface ParsedAttributes<Attributes extends A.Key = A.Key> {
aliases: Attributes;
all: Attributes;
default: Attributes;
key: {
partitionKey: {
pure: Attributes;
dependsOn: Attributes;
mapped: Attributes;
all: Attributes;
};
sortKey: {
pure: Attributes;
dependsOn: Attributes;
mapped: Attributes;
all: Attributes;
};
all: Attributes;
};
always: {
all: Attributes;
default: Attributes;
input: Attributes;
};
required: {
all: Attributes;
default: Attributes;
input: Attributes;
};
optional: Attributes;
shown: Attributes;
}
export declare type GetDependsOnAttributes<A extends AttributeDefinition> = A extends {
dependsOn: A.Key;
} ? A['dependsOn'] : A extends {
dependsOn: A.Key[];
} ? A['dependsOn'][number] : never;
export declare type ParseAttributes<Definitions extends AttributeDefinitions, Timestamps extends boolean, CreatedAlias extends string, ModifiedAlias extends string, TypeAlias extends string, TypeHidden extends boolean, Aliases extends string = (Timestamps extends true ? CreatedAlias | ModifiedAlias : never) | TypeAlias, Default extends A.Key = O.SelectKeys<Definitions, {
default: any;
} | [any, any, {
default: any;
}]> | Aliases, PK extends A.Key = InferKeyAttribute<Definitions, 'partitionKey'>, PKDependsOn extends A.Key = GetDependsOnAttributes<Definitions[PK]>, PKMappedAttribute extends A.Key = InferMappedAttributes<Definitions, PK>, SK extends A.Key = InferKeyAttribute<Definitions, 'sortKey'>, SKDependsOn extends A.Key = GetDependsOnAttributes<Definitions[SK]>, SKMappedAttribute extends A.Key = InferMappedAttributes<Definitions, SK>, KeyAttributes extends A.Key = PK | PKMappedAttribute | SK | SKMappedAttribute, AlwaysAttributes extends A.Key = Exclude<O.SelectKeys<Definitions, {
required: 'always';
} | [any, any, {
required: 'always';
}]> | (Timestamps extends true ? ModifiedAlias : never), KeyAttributes>, RequiredAttributes extends A.Key = Exclude<O.SelectKeys<Definitions, {
required: true;
} | [any, any, {
required: true;
}]> | (Timestamps extends true ? CreatedAlias : never) | TypeAlias, KeyAttributes>, Attribute extends A.Key = keyof Definitions | Aliases, Hidden extends A.Key = O.SelectKeys<Definitions, {
hidden: true;
} | [any, any, {
hidden: true;
}]>> = {
aliases: Aliases;
all: Attribute;
default: Default;
key: {
partitionKey: {
pure: PK;
mapped: PKMappedAttribute;
dependsOn: PKDependsOn;
all: PK | PKDependsOn | PKMappedAttribute;
};
sortKey: {
pure: SK;
mapped: SKMappedAttribute;
dependsOn: SKDependsOn;
all: SK | SKDependsOn | SKMappedAttribute;
};
all: KeyAttributes;
};
always: {
all: AlwaysAttributes;
default: Extract<AlwaysAttributes, Default>;
input: Exclude<AlwaysAttributes, Default>;
};
required: {
all: RequiredAttributes;
default: Extract<RequiredAttributes, Default>;
input: Exclude<RequiredAttributes, Default>;
};
optional: Exclude<Attribute, KeyAttributes | AlwaysAttributes | RequiredAttributes>;
shown: Exclude<Attribute, Hidden>;
};
export declare type FromDynamoData<T extends DynamoDBTypes> = {
string: string;
boolean: boolean;
number: number;
bigint: bigint;
list: any[];
map: any;
binary: any;
set: any[];
}[T];
export declare type InferItemAttributeValue<Definitions extends AttributeDefinitions, AttributeName extends keyof Definitions, Definition = Definitions[AttributeName]> = {
dynamoDbType: Definition extends DynamoDBTypes ? FromDynamoData<Definition> : never;
pure: Definition extends PartitionKeyDefinition | GSIPartitionKeyDefinition | SortKeyDefinition | GSISortKeyDefinition | PureAttributeDefinition ? Definition['type'] extends DynamoDBTypes ? Definition['setType'] extends DynamoDBKeyTypes ? FromDynamoData<NonNullable<Definition['setType']>>[] : FromDynamoData<A.Cast<Definition['type'], DynamoDBTypes>> : any : never;
composite: Definition extends CompositeAttributeDefinition ? Definition[0] extends Exclude<keyof Definitions, AttributeName> ? InferItemAttributeValue<Definitions, Definition[0]> : any : never;
}[Definition extends DynamoDBTypes ? 'dynamoDbType' : Definition extends PartitionKeyDefinition | GSIPartitionKeyDefinition | SortKeyDefinition | GSISortKeyDefinition | PureAttributeDefinition ? 'pure' : Definition extends CompositeAttributeDefinition ? 'composite' : never];
export declare type InferItem<Definitions extends AttributeDefinitions, Attributes extends ParsedAttributes> = O.Optional<{
[K in Attributes['all']]: K extends keyof Definitions ? InferItemAttributeValue<Definitions, K> : K extends Attributes['aliases'] ? string : never;
}, Attributes['optional']>;
export declare type CompositePrimaryKeyPart<Item extends O.Object, Attributes extends ParsedAttributes, KeyType extends 'partitionKey' | 'sortKey', KeyPureAttribute extends A.Key = Attributes['key'][KeyType]['pure'], KeyDependsOnAttributes extends A.Key = Attributes['key'][KeyType]['dependsOn'], KeyCompositeAttributes extends A.Key = Attributes['key'][KeyType]['mapped']> = If<A.Equals<KeyPureAttribute, never>, Record<never, unknown>, O.Optional<Pick<Item, KeyPureAttribute> | If<A.Equals<KeyDependsOnAttributes, never>, never, Pick<Item, KeyDependsOnAttributes>> | If<A.Equals<KeyCompositeAttributes, never>, never, Pick<Item, KeyCompositeAttributes>>, If<A.Equals<KeyDependsOnAttributes, never>, Attributes['default'], Exclude<Attributes['default'], KeyPureAttribute>>>>;
export declare type InferCompositePrimaryKey<Item extends O.Object, Attributes extends ParsedAttributes> = Compute<CompositePrimaryKeyPart<Item, Attributes, 'partitionKey'> & CompositePrimaryKeyPart<Item, Attributes, 'sortKey'>>;
export declare type Overlay = undefined | O.Object;
export declare type ConditionOrFilter<Attributes extends A.Key = A.Key> = ({
attr: Attributes;
} | {
size: string;
}) & Partial<{
contains: string;
exists: boolean;
type: 'S' | 'SS' | 'N' | 'NS' | 'B' | 'BS' | 'BOOL' | 'NULL' | 'L' | 'M';
or: boolean;
negate: boolean;
entity: string;
eq: string | number | bigint | boolean | null;
ne: string | number | bigint | boolean | null;
lt: string | number;
lte: string | bigint | number;
gt: string | bigint | number;
gte: string | bigint | number;
between: [string, string] | [number, number] | [bigint, bigint];
beginsWith: string;
in: any[];
}>;
export declare type ConditionsOrFilters<Attributes extends A.Key = A.Key> = ConditionOrFilter<Attributes> | ConditionsOrFilters<Attributes>[];
export declare type BaseOptions<Execute extends boolean | undefined = undefined, Parse extends boolean | undefined = undefined> = {
capacity: ReturnConsumedCapacity | `${ReturnConsumedCapacity}` | Lowercase<ReturnConsumedCapacity>;
execute: Execute;
parse: Parse;
};
export declare type $ReadOptions<Execute extends boolean | undefined = undefined, Parse extends boolean | undefined = undefined> = BaseOptions<Execute, Parse> & {
consistent: boolean;
};
export declare type $GetOptions<Attributes extends A.Key = A.Key, Execute extends boolean | undefined = undefined, Parse extends boolean | undefined = undefined> = Partial<$ReadOptions<Execute, Parse> & {
attributes: Attributes[];
include: string[];
}>;
export declare type EntityQueryOptions<Attributes extends A.Key = A.Key, FiltersAttributes extends A.Key = Attributes, Execute extends boolean | undefined = undefined, Parse extends boolean | undefined = undefined> = Partial<$QueryOptions<Execute, Parse> & {
attributes: Attributes[];
filters: ConditionsOrFilters<FiltersAttributes>;
}>;
export declare type $WriteOptions<Attributes extends A.Key = A.Key, Execute extends boolean | undefined = undefined, Parse extends boolean | undefined = undefined> = BaseOptions<Execute, Parse> & {
conditions: ConditionsOrFilters<Attributes>;
metrics: ReturnItemCollectionMetrics | `${ReturnItemCollectionMetrics}` | Lowercase<ReturnItemCollectionMetrics>;
include: string[];
};
export declare type PutOptionsReturnValues = 'NONE' | 'ALL_OLD';
export declare type $PutOptions<Attributes extends A.Key = A.Key, ReturnValues extends PutOptionsReturnValues = PutOptionsReturnValues, Execute extends boolean | undefined = undefined, Parse extends boolean | undefined = undefined, StrictSchemaCheck extends boolean | undefined = true> = Partial<$WriteOptions<Attributes, Execute, Parse> & {
returnValues: ReturnValues;
strictSchemaCheck?: StrictSchemaCheck;
}>;
export declare type $PutBatchOptions<Execute extends boolean | undefined = undefined, Parse extends boolean | undefined = undefined, StrictSchemaCheck extends boolean | undefined = true> = Partial<Pick<BaseOptions<Execute, Parse>, 'execute' | 'parse'> & {
strictSchemaCheck?: StrictSchemaCheck;
}>;
export declare type PutItem<MethodItemOverlay extends Overlay, EntityItemOverlay extends Overlay, CompositePrimaryKey extends O.Object, Item extends O.Object, Attributes extends ParsedAttributes, StrictSchemaCheck extends boolean | undefined = true> = FirstDefined<[
MethodItemOverlay,
EntityItemOverlay,
Compute<CompositePrimaryKey & Pick<Item, Attributes['always']['input'] | Attributes['required']['input']> & Partial<Pick<Item, Attributes['always']['default'] | Attributes['required']['default']> & O.Update<Item, Attributes['optional'], A.x | null>>>
] | If<A.Equals<StrictSchemaCheck, true>, never, any>>;
export declare type UpdateOptionsReturnValues = 'NONE' | 'UPDATED_OLD' | 'UPDATED_NEW' | 'ALL_OLD' | 'ALL_NEW';
export declare type $UpdateOptions<Attributes extends A.Key = A.Key, ReturnValues extends UpdateOptionsReturnValues = UpdateOptionsReturnValues, Execute extends boolean | undefined = undefined, Parse extends boolean | undefined = undefined, StrictSchemaCheck extends boolean | undefined = true> = Partial<$WriteOptions<Attributes, Execute, Parse> & {
returnValues: ReturnValues;
strictSchemaCheck?: StrictSchemaCheck;
}>;
export interface UpdateCustomParameters {
SET: string[];
REMOVE: string[];
ADD: string[];
DELETE: string[];
}
export declare type UpdateCustomParams = Partial<UpdateCustomParameters & UpdateCommandInput>;
export declare type UpdateItem<MethodItemOverlay extends Overlay, EntityItemOverlay extends Overlay, CompositePrimaryKey extends O.Object, Item extends O.Object, Attributes extends ParsedAttributes, StrictSchemaCheck extends boolean | undefined = true> = FirstDefined<[
MethodItemOverlay,
EntityItemOverlay,
Compute<CompositePrimaryKey & {
[inputAttr in Attributes['always']['input'] & keyof Item]: AttributeUpdateInput<Item[inputAttr]>;
} & {
[inputRequiredOrWithDefaultAttribute in (Attributes['required']['all'] | Attributes['always']['default']) & keyof Item]?: AttributeUpdateInput<Item[inputRequiredOrWithDefaultAttribute]>;
} & {
[inputOptionalAttribute in Attributes['optional'] & keyof Item]?: AttributeUpdateInput<Item[inputOptionalAttribute]> | null;
} & {
$remove?: Attributes['optional'] | Attributes['optional'][];
}>
] | If<A.Equals<StrictSchemaCheck, true>, never, any>>;
export declare type AttributeUpdateInput<AttributeType> = If<B.Or<A.Equals<AttributeType, FromDynamoData<'list' | 'set'>>, A.Equals<AttributeType, FromDynamoData<'list' | 'set'> | undefined>>, {
$delete?: string[];
$add?: any;
$prepend?: AttributeType;
$append?: AttributeType;
$remove?: number[];
} | AttributeType, AttributeType> | If<B.Or<A.Equals<AttributeType, number[]>, A.Equals<AttributeType, number[] | undefined>>, {
$delete?: number[];
$add?: number[];
$prepend?: AttributeType;
$append?: number[];
} | string[]> | If<B.Or<A.Equals<AttributeType, bigint[]>, A.Equals<AttributeType, bigint[] | undefined>>, {
$delete?: bigint[];
$add?: bigint[];
$prepend?: AttributeType;
$append?: bigint[];
} | string[]> | If<B.Or<A.Equals<AttributeType, string[]>, A.Equals<AttributeType, string[] | undefined>>, {
$delete?: string[];
$add?: string[];
$prepend?: AttributeType;
$append?: string[];
} | number[]> | If<B.Or<A.Equals<AttributeType, boolean[]>, A.Equals<AttributeType, boolean[] | undefined>>, {
$delete?: boolean[];
$add?: boolean[];
$prepend?: AttributeType;
$append?: boolean[];
} | boolean[]> | If<B.Or<A.Equals<AttributeType, FromDynamoData<'number'>>, A.Equals<AttributeType, FromDynamoData<'number'> | undefined>>, {
$add?: number;
}> | If<B.Or<A.Equals<AttributeType, FromDynamoData<'bigint'>>, A.Equals<AttributeType, FromDynamoData<'bigint'> | undefined>>, {
$add?: bigint;
}>;
export declare type DeleteOptionsReturnValues = 'NONE' | 'ALL_OLD';
export declare type RawDeleteOptions<Attributes extends A.Key = A.Key, ReturnValues extends DeleteOptionsReturnValues = DeleteOptionsReturnValues, Execute extends boolean | undefined = undefined, Parse extends boolean | undefined = undefined> = Partial<$WriteOptions<Attributes, Execute, Parse> & {
returnValues: ReturnValues;
}>;
export declare type TransactionOptionsReturnValues = 'NONE' | 'ALL_OLD';
export interface TransactionOptions<Attributes extends A.Key = A.Key, StrictSchemaCheck extends boolean | undefined = true> {
conditions?: ConditionsOrFilters<Attributes>;
returnValues?: TransactionOptionsReturnValues;
strictSchemaCheck?: StrictSchemaCheck;
}
export declare type ShouldExecute<Execute extends boolean | undefined, AutoExecute extends boolean> = B.Or<A.Equals<Execute, true>, B.And<A.Equals<Execute, undefined>, A.Equals<AutoExecute, true>>>;
export declare type ShouldParse<Parse extends boolean | undefined, AutoParse extends boolean> = B.Or<A.Equals<Parse, true>, B.And<A.Equals<Parse, undefined>, A.Equals<AutoParse, true>>>;
export declare type Readonly<T> = T extends F.Function | undefined ? T : T extends O.Object ? {
readonly [P in keyof T]: Readonly<T[P]>;
} : T;
export declare type Writable<T> = T extends F.Function | undefined ? T : T extends O.Object ? {
-readonly [P in keyof T]: Writable<T[P]>;
} : T;
export declare type InferEntityItem<E extends Entity, WritableAttributeDefinitions extends AttributeDefinitions = A.Cast<O.Writable<E['attributes'], A.Key, 'deep'>, AttributeDefinitions>, Attributes extends ParsedAttributes = ParseAttributes<WritableAttributeDefinitions, E['timestamps'], E['createdAlias'], E['modifiedAlias'], E['typeAlias'], E['typeHidden']>, Item = InferItem<WritableAttributeDefinitions, Attributes>> = Pick<Item, Extract<Attributes['shown'], keyof Item>>;
export declare type EntityItem<E extends Entity> = E['_typesOnly']['_entityItemOverlay'] extends Record<A.Key, any> ? E['_typesOnly']['_entityItemOverlay'] : InferEntityItem<E>;
export declare type ExtractAttributes<E extends Entity> = E['_typesOnly']['_entityItemOverlay'] extends Record<A.Key, any> ? ParsedAttributes<keyof E['_typesOnly']['_entityItemOverlay']> : ParseAttributes<A.Cast<O.Writable<E['attributes'], A.Key, 'deep'>, AttributeDefinitions>, E['timestamps'], E['createdAlias'], E['modifiedAlias'], E['typeAlias'], E['typeHidden']>;
export declare type GetOptions<E extends Entity, A extends ParsedAttributes = ExtractAttributes<E>> = $GetOptions<A['shown'], boolean | undefined, boolean | undefined>;
export declare type QueryOptions<E extends Entity, A extends ParsedAttributes = ExtractAttributes<E>> = EntityQueryOptions<A['shown'], A['all'], boolean | undefined, boolean | undefined>;
export declare type PutOptions<E extends Entity, A extends ParsedAttributes = ExtractAttributes<E>> = $PutOptions<A['all'], PutOptionsReturnValues, boolean | undefined, boolean | undefined, boolean | undefined>;
export declare type DeleteOptions<E extends Entity, A extends ParsedAttributes = ExtractAttributes<E>> = RawDeleteOptions<A['all'], DeleteOptionsReturnValues, boolean | undefined, boolean | undefined>;
export declare type UpdateOptions<E extends Entity, A extends ParsedAttributes = ExtractAttributes<E>> = $UpdateOptions<A['all'], UpdateOptionsReturnValues, boolean | undefined, boolean | undefined, boolean | undefined>;
export declare type AttributeMap = Record<string, NativeAttributeValue>;