dynamodb-ts-model
Version:
A DynamoDB model/client with full TypeScript typings
181 lines • 9.97 kB
TypeScript
import { ConditionalCheckFailedException } from '@aws-sdk/client-dynamodb';
import { ConditionAttributes, UpdateAttributes } from 'dynamodb-expressions';
import { DynamoClient } from './DynamoClient';
import { DynamoWrapper } from './DynamoWrapper';
import { DeleteParams, Extend, FullProjection, GetParams, GetResult, Item, ItemConverter, ItemResult, Key, KeyAttributes, KeyIndices, KeyValue, ModelParams, Projection, ProjectionKeys, PutParams, QueryParams, ScanParams, ScanResult, Trigger, UpdateParams } from './types';
import { StringKeyOf } from './utils';
export declare class ModelOptions {
client?: DynamoClient;
name?: string;
tableName?: string;
}
export interface AtomicActionParams<T extends Item, K extends KeyAttributes<T>, C extends keyof T> {
key: KeyValue<T, K>;
conditionAttribute: C;
maxAttempts?: number;
}
export interface AtomicActionFuncParams<T extends Item, K extends KeyAttributes<T>> {
key: KeyValue<T, K>;
item?: T;
conditions: ConditionAttributes<T>;
}
/**
* A model representing a DynamoDB table.
* Type params:
* * T represents the data stored in the table.
* * K represents the table key definition, which is either a single or a tuple key
* * I represents a dictionary of index names to index key definitions
* * B represents data being automatically created by one or more creator functions, e.g. automatic timestamp generators.
* This type may contain parts of T, meaning that added items only need to contain attributes of T
* which aren't in type B.
*/
export declare class DynamoModel<T extends Item, K extends KeyAttributes<T> = any, I extends KeyIndices<T> = any, B extends Item = any> extends DynamoWrapper {
readonly name: string;
readonly tableName: string;
readonly params: ModelParams<T, K, I, B>;
/**
* Check if an error returned by a DynamoModel is a conditional check failed error
* @param err
*/
static isConditionalCheckFailed(err: any): err is ConditionalCheckFailedException;
constructor(client: DynamoClient, name: string, tableName: string, params: ModelParams<T, K, I, B>);
private convertItem;
private convertItems;
/**
* Get a single item
* @param params
*/
get<P extends ProjectionKeys<T2> = FullProjection, T2 extends T = T>(params: GetParams<T2, K, P>): Promise<GetResult<T2, P>>;
/**
* Perform a scan operation, i.e., a query without any key condition, and return a page of items.
* @param params
*/
scan<P extends ProjectionKeys<T2> = null, N extends StringKeyOf<I> | undefined = undefined, T2 extends T = T>(params?: ScanParams<T2, P, N>): Promise<ScanResult<T2, P>>;
/**
* Perform a scan operation, i.e., a query without any key condition, and return an item iterator.
* @param params
*/
scanIterator<P extends ProjectionKeys<T2> = null, N extends StringKeyOf<I> | undefined = undefined, T2 extends T = T>(params?: ScanParams<T2, P, N>): AsyncGenerator<Projection<T2, P>>;
/**
* Perform a query operation with a key condition, and return a page of items.
* @param params
*/
query<P extends ProjectionKeys<T2> = null, N extends StringKeyOf<I> | undefined = undefined, T2 extends T = T>(params: QueryParams<T2, P, N, Key<T, N extends keyof I ? I[N] : K>>): Promise<ScanResult<T2, P>>;
/**
* Perform a query operation with a key condition, and return an item iterator.
* @param params
*/
queryIterator<P extends ProjectionKeys<T2> = null, N extends StringKeyOf<I> | undefined = undefined, T2 extends T = T>(params: QueryParams<T2, P, N, Key<T, N extends keyof I ? I[N] : K>>): AsyncGenerator<Projection<T2, P>>;
/**
* Put (upsert) an item. If no item with the same key exists, a new item is created; otherwise the existing item is
* replaced.
* Note that if the model has any creator functions, attributes of T which are also in B do not need to be provided,
* such as generated timestamps, auto-generated IDs etc.
* @param params
*/
put<T2 extends T = T>(params: PutParams<T2, B>): Promise<ItemResult<T2>>;
update<T2 extends T = T>(params: UpdateParams<T2, K, B>): Promise<ItemResult<T2>>;
/**
* Delete an item
* @param params
*/
delete(params: DeleteParams<T, K>): Promise<void>;
/**
* Perform an atomic read-modify-write action which fetches an item and calls the supplied function with a key,
* the existing item if it exists, and a set of conditions used to verify that the item hasn't been changed
* concurrently between the get and the performed action.
* The function should update the model using those arguments, using e.g. put() or update().
*
* If the action fails due to a conditional check failed error, after a delay the item will be fetched again and
* the function called again, up to a certain number of attempts.
*
* This enables putting or updating an item without overwriting data in case of concurrent modifications.
* It relies on the conditionAttribute having a unique value after each update, such as a random version assigned
* on each modification or a timestamp of sufficient accuracy being refreshed on each modification.
* @param params
* @param params.key Key of the item to perform the action on
* @param params.conditionAttribute Name of attribute to condition the action on
* @param [params.maxAttempts] Max number of attempts
* @param action Function called to perform the action on the item
*/
atomicAction<C extends keyof T, R>(params: AtomicActionParams<T, K, C>, action: (params: AtomicActionFuncParams<T, K>) => Promise<R>): Promise<R>;
}
/**
* A model builder
*/
export declare class DynamoModelBuilder<T extends Item, K extends KeyAttributes<T> = never, I extends KeyIndices<T> = {}, B extends Item = {}> {
readonly client?: DynamoClient | undefined;
readonly name?: string | undefined;
readonly tableName?: string | undefined;
private readonly params;
constructor(client?: DynamoClient | undefined, name?: string | undefined, tableName?: string | undefined);
/**
* Define the key attribute(s) of this model
* @param keyAttributes One or two attribute names identifying the HASH and RANGE keys of the table
*/
withKey<_K extends KeyAttributes<T>>(...keyAttributes: _K): DynamoModelBuilder<T, _K>;
/**
* Add an index to this model
* @param name Name of the index
* @param indexAttributes One or two attribute names identifying the HASH and RANGE keys of the index
*/
withIndex<N extends string, IK extends KeyAttributes<T>>(name: N, ...indexAttributes: IK): DynamoModelBuilder<T, K, I & Record<N, IK>, B>;
/**
* Add an item creator function that adds or modifies item attributes prior to calling put.
* This can for example be used to automatically create timestamps or auto-generated IDs when creating items.
* @param creator A function that may modify items being put.
*/
withCreator<_B>(creator: (item: T) => _B): DynamoModelBuilder<Extend<T, _B>, K, I, Extend<B, _B>>;
/**
* Add an item updater function that adds or modifies item attributes prior to calling update.
* This can for example be used to automatically update timestamps when updating items.
* @param updater A function that may modify items being updated.
*/
withUpdater(updater: (item: Partial<T>) => UpdateAttributes<T>): this;
/**
* Set a converter function to convert items read from the database to the proper type, e.g. to convert legacy items
* missing some attributes added later. This will be called for every item returned by a model operation.
* Note that the function should modify the passed item.
* @param converter
*/
withConverter(converter: ItemConverter<T>): this;
/**
* Define default values for stored legacy items
* @param values An object containing default values to assign to returned model items missing these properties.
*/
withDefaultValues(values: Partial<T>): this;
/**
* Add a trigger to be called after each successful table write operation.
* @param trigger
*/
withTrigger(trigger: Trigger<T, K>): this;
/**
* Build an instance of the model
* If the builder was created via the static method `DynamoClient.model()`, the options `client`, `name` and `tableName`
* must be supplied now.
* If the builder was created via the instance method `client.model(name, tableName)`, the arguments may be omitted,
* but if present they will override any options supplied when the builder was created.
*/
build(options?: ModelOptions): DynamoModel<T, K, I, B>;
/**
* Create a class for the model. This is convenient as it also creates a type that can be easily referred to instead
* of complex generic types such as DynamoModel<MyItem, 'id', {modifiedTime: string}> etc.
*
* If the builder was created via the static method `DynamoClient.model()`, the options `client`, `name` and `tableName`
* must be supplied either as arguments to this method or as arguments to the returned constructor function on each instance
* creation.
* If the builder was created via the instance method `client.model(name, tableName)`, the arguments may be omitted both
* from this method and the returned constructor function, but if present they will override any options supplied to
* this method or when the builder was created.
*
* Usage:
* class PersonModel extends DynamoClient.model<Person>()
* .withKey('id')
* .withIndex('name-age-index', 'name', 'age')
* .class() {}
*
* const persons = new PersonModel({client, name: 'foo'});
*/
class(options?: ModelOptions): abstract new (options?: ModelOptions) => DynamoModel<T, K, I, B>;
}
//# sourceMappingURL=DynamoModel.d.ts.map