UNPKG

dyngoose

Version:

Elegant DynamoDB object modeling for Typescript

354 lines (353 loc) 15.1 kB
import { type AttributeValue, type PutItemOutput, type UpdateItemOutput, type TableDescription, type DeleteItemCommandOutput } from '@aws-sdk/client-dynamodb'; import { type Attribute } from './attribute'; import { DocumentClient } from './document-client'; import type * as Events from './events'; import { type AttributeMap, type SetPropParams, type UpdateOperator } from './interfaces'; import { type Filters } from './query/filters'; import { MagicSearch, type MagicSearchInput } from './query/search'; import { type TablePropertyValue, type TableProperties, type TableProperty } from './tables/properties'; import { Schema } from './tables/schema'; import { type IRequestOptions } from './connections'; type StaticThis<T> = new () => T; export declare class Table { static get schema(): Schema; static set schema(schema: Schema); static get documentClient(): DocumentClient<Table>; static set documentClient(documentClient: DocumentClient<Table>); private static __schema; private static __documentClient; /** * Creates a new record for this table. * * This method is strongly typed and it is recommended you use over `new Table(…)` */ static new<T extends Table>(this: StaticThis<T>, values?: TableProperties<T>): T; /** * Creates a new instance of Table with values from a given `AttributeMap`. * * This assumes the record exists in DynamoDB and saving this record will * default to using an `UpdateItem` operation rather than a `PutItem` operation * upon being saved. */ static fromDynamo<T extends Table>(this: StaticThis<T>, attributes: AttributeMap, entireDocument?: boolean): T; /** * Creates an instance of Table from raw user input. Designs to be used for creating * records from requests, like: * * express.js: * ```app.post('/api/create', (req, res) => { * const card = Card.fromJSON(req.body) * })``` * * Each attribute can optionally define additional validation logic or sanitization * of the user input, @see {@link https://github.com/benhutchins/dyngoose/blob/master/docs/Attributes}. */ static fromJSON<T extends Table>(this: StaticThis<T>, json: Record<string, any>): T; /** * Query DynamoDB for what you need. * * This is a powerful all-around querying method. It will detect the best index available for use, * but it ignores indexes that are not set to Projection of `ALL`. To please use the index-specific * querying when necessary. * * This will avoid performing a scan at all cost, but it will fall back to using a scan if necessary. * * By default, this returns you one "page" of results (allows DynamoDB) to process and return the * maximum of items DynamoDB allows. If you want it to internally page for you to return all possible * results (be cautious as that can easily cause timeouts for Lambda), specify `{ all: true }` as an * input argument for the second argument. */ static search<T extends Table>(this: StaticThis<T>, filters?: Filters<T>, input?: MagicSearchInput<T>): MagicSearch<T>; /** * Creates the table in DynamoDB. * * You can also use {@link Table.migrateTable} to create and automatically * migrate and indexes that need changes. */ static createTable(waitForReady?: boolean): Promise<TableDescription>; /** * Migrates the table to match updated specifications. * * This will create new indexes and delete legacy indexes. */ static migrateTable(): Promise<TableDescription>; /** * Deletes the table from DynamoDB. * * Be a bit careful with this in production. */ static deleteTable(): Promise<TableDescription | undefined>; static describeTable(requestOptions?: IRequestOptions): Promise<TableDescription>; protected get table(): typeof Table; private __attributes; private __original; private __updatedAttributes; private __removedAttributes; private __updateOperators; private __putRequired; private __entireDocumentIsKnown; /** * Create a new Table record by attribute names, not property names. * * @see {@link Table.new} To create a strongly-typed record by property names. */ constructor(values?: Record<string, any>); /** * Apply any default values for attributes. */ applyDefaults(): this; /** * Load values from an a AttributeMap into this Table record. * * This assumes the values are loaded directly from DynamoDB, and after * setting the attributes it resets the attributes pending update and * deletion. */ fromDynamo(values: AttributeMap, entireDocument?: boolean): this; /** * Converts the current attribute values into a AttributeMap which * can be sent directly to DynamoDB within a PutItem, UpdateItem, or similar * request. * * @param {boolean} updateOnSaveAttributes If true, update all attributes that have logic to update with every save. */ toDynamo(updateOnSaveAttributes?: boolean): AttributeMap; /** * Get the DynamoDB.Key for this record. */ getDynamoKey(): AttributeMap; /** * Get the list of attributes pending update. * * The result includes attributes that have also been deleted. To get just * the list of attributes pending removal, use {@link Table.getRemovedAttributes}. * * If you want to easily know if this record has updates pending, use {@link Table.hasChanges}. */ getUpdatedAttributes(): string[]; /** * Get the list of attributes pending removal. * * To get all the attributes that have been updated, use {@link Table.getUpdatedAttributes}. * * If you want to easily know if this record has updates pending, use {@link Table.hasChanges}. */ getRemovedAttributes(): string[]; /** * Use getRemovedAttributes. * * @deprecated */ getDeletedAttributes(): string[]; /** * While similar to setAttributes, this method runs the attribute's defined fromJSON * methods to help standardize the attribute values as much as possible. * * @param {any} json A JSON object * @param {boolean} [ignoreArbitrary] Whether arbitrary attributes should be ignored. * When false, unknown attributes will result in an error being thrown. * When true, any non-recognized attribute will be ignored. Useful if you're * passing in raw request body objects or dealing with user input. * Defaults to false. */ fromJSON(json: Record<string, any>, ignoreArbitrary?: boolean): this; /** * Returns the AttributeValue value for an attribute. * * To get the transformed value, use {@link Table.getAttribute} */ getAttributeDynamoValue(attributeName: string): AttributeValue; /** * Gets the JavaScript transformed value for an attribute. * * While you can read values directly on the Table record by its property name, * sometimes you need to get attribute. * * Unlike {@link Table.get}, this excepts the attribute name, not the property name. */ getAttribute(attributeName: string): any; /** * Get the update operator for an attribute. */ getUpdateOperator<P extends TableProperty<this>>(propertyName: P | string): UpdateOperator; getAttributeUpdateOperator(attributeName: string): UpdateOperator; /** * Set the update operator for a property. */ setUpdateOperator<P extends TableProperty<this>>(propertyName: P | string, operator: UpdateOperator): this; /** * Set the update operator for an attribute. */ setAttributeUpdateOperator(attributeName: string, operator: UpdateOperator): this; /** * Sets the AttributeValue for an attribute. * * To set the value from a JavaScript object, use {@link Table.setAttribute} */ setAttributeDynamoValue(attributeName: string, attributeValue: AttributeValue): this; /** * Sets the value of an attribute by attribute name from a JavaScript object. * * - To set an attribute value by property name, use {@link Table.set}. */ setAttribute(attributeName: string, value: any, params?: SetPropParams): this; /** * Sets several attribute values on this record by attribute names. * * - To set several values by property names, use {@link Table.setValues}. * - To set a single attribute value by attribute name, use {@link Table.setAttribute}. * - To set a single attribute value by property name, use {@link Table.set}. * * @param {object} values An object, where the keys are the attribute names, * and the values are the values you'd like to set. */ setAttributes(values: Record<string, any>): this; /** * Remove a single attribute by its attribute name. * * @see {@link Table.remove} Remove an attribute by its property name. * @see {@link Table.removeAttributes} Remove several attributes by their property names. */ removeAttribute(...attributeNames: string[]): this; /** * Remove several attributes by their property names. * * @see {@link Table.remove} Remove an attribute by its property name. * @see {@link Table.removeAttribute} Remove a single attribute by its attribute name. * * @deprecated You can now pass multiple attributes to removeAttribute. */ removeAttributes(attributes: string[]): this; /** * Sets a value of an attribute by its property name. * * @see {@link Table.setValues} To set several attribute values by property names. * @see {@link Table.setAttribute} To set an attribute value by an attribute name. * @see {@link Table.setAttributes} To set several attribute values by attribute names. */ set<P extends TableProperty<this>>(propertyName: P | string, value: TablePropertyValue<this[P]>, params?: SetPropParams): this; /** * Gets a value of an attribute by its property name. * * @see {@link Table.getAttribute} To get a value by an attribute name. * @see {@link Table.toJSON} To get the entire record. */ get<P extends TableProperty<this>>(propertyName: P | string): this[P]; /** * Remove an attribute by its property name. * * @see {@link Table.removeAttribute} Remove a single attribute by its attribute name. */ remove<P extends TableProperty<this>>(...propertyNames: Array<P | string>): this; /** * Update several attribute values on this record by property names. * * @see {@link Table.set} To set an attribute value by property name. * @see {@link Table.setAttribute} To set an attribute value by an attribute names. * @see {@link Table.setAttributes} To set several attribute values by attribute names. */ setValues(values: TableProperties<this>): this; /** * Determines if this record has any attributes pending an update or deletion. */ hasChanges(): boolean; /** * Return the original values for the record, if it was loaded from DynamoDB. */ getOriginalValues(): AttributeMap; /** * Save this record to DynamoDB. * * Will check to see if there are changes to the record, if there are none the save request is ignored. * To skip this check, use {@link Table.forceSave} instead. * * Calls the {@link Table.beforeSave} before saving the record. * If {@link Table.beforeSave} returns false, the save request is ignored. * * Automatically determines if the the save should use a PutItem or UpdateItem request. */ save(event?: undefined | { returnOutput?: false; } & Events.SaveEvent<this>): Promise<void>; save(event: { returnOutput: true; operator?: undefined; } & Events.SaveEvent<this>): Promise<PutItemOutput | UpdateItemOutput>; save(event: { returnOutput: true; operator: 'put'; } & Events.SaveEvent<this>): Promise<PutItemOutput>; save(event: { returnOutput: true; operator: 'update'; } & Events.SaveEvent<this>): Promise<UpdateItemOutput>; /** * Returns whether this is a newly created record that hasn't been saved * It is not a guarantee that the hash key is not already in use */ isNew(): boolean; /** * Determine the best save operation method to use based upon the item's current state */ getSaveOperation(): 'put' | 'update'; /** * Deletes this record from DynamoDB. * * Before deleting, it will call {@link Table.beforeDelete}. If {@link Table.beforeDelete} * returns false then this record will not be deleted. * * After deleting, {@link Table.afterDelete} will be called. */ delete(event?: { returnOutput?: false; } & Events.DeleteEvent<this>): Promise<void>; delete(event: { returnOutput: true; } & Events.DeleteEvent<this>): Promise<DeleteItemCommandOutput>; /** * Convert this record to a JSON-exportable object. * * Has no consideration for "views" or "permissions", so all attributes * will be exported. * * Export object uses the property names as the object keys. To convert * a JSON object back into a Table record, use {@link Table.fromJSON}. * * Each attribute type can define a custom toJSON and fromJSON method, * @see {@link https://github.com/benhutchins/dyngoose/blog/master/docs/Attributes.md#custom-attribute-types}. */ toJSON(): Record<string, any>; protected beforeSave(event: Events.BeforeSaveEvent<this>): Promise<boolean | undefined>; /** * After a record is deleted, this handler is called. */ protected afterSave(event: Events.AfterSaveEvent<this>): Promise<void>; /** * Before a record is deleted, this handler is called and if the promise * resolves as false, the delete request will be ignored. */ protected beforeDelete(event: Events.BeforeDeleteEvent<this>): Promise<boolean>; /** * After a record is deleted, this handler is called. */ protected afterDelete(event: Events.AfterDeleteEvent<this>): Promise<void>; /** * Ensures Date attributes with nowOnUpdate are updated whenever the record is * being saved. */ protected updateOnSaveAttributes(): void; protected setByAttribute(attribute: Attribute<any>, value: any, params?: SetPropParams): this; protected getByAttribute(attribute: Attribute<any>): any; protected saveOriginalValue(attributeName: string): void; /** * Returns a list of attributes that should not be allowed when Table.fromJSON is used. */ protected static getBlacklist(): string[]; } export interface ITable<T extends Table> { schema: Schema; documentClient: DocumentClient<T>; new (): T; fromDynamo: (attributes: AttributeMap, entireDocument?: boolean) => T; } export {};