UNPKG

dynamodb-ts-model

Version:

A DynamoDB model/client with full TypeScript typings

181 lines 9.97 kB
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