import Dream from '../Dream.js'; import { OnStatementForSpecificColumns } from '../types/associations/shared.js'; import { AllDefaultScopeNames, AssociationNameToDream, DreamAssociationNames, DreamAssociationNamesWithoutRequiredOnClauses, DreamAssociationNamesWithPassthroughOnClauses, DreamAssociationNamesWithRequiredOnClauses, DreamBelongsToAssociationNames, DreamHasManyAssociationNames, DreamHasOneAssociationNames, DreamSerializerKey, JoinAndStatements, PassthroughOnClauseKeys, RequiredOnClauseKeys, UpdateableAssociationProperties, UpdateableProperties } from '../types/dream.js'; import { DefaultQueryTypeOptions, LoadForModifierFn, QueryWithJoinedAssociationsType } from '../types/query.js'; import { JoinedAssociation, JoinedAssociationsTypeFromAssociations, VariadicJoinsArgs, VariadicLeftJoinLoadArgs, VariadicLoadArgs } from '../types/variadic.js'; import DreamTransaction from './DreamTransaction.js'; import type { InstanceDestroyOptions, InstanceUpdateOptions } from './internal/instanceMutationOptions.js'; import LeftJoinLoadBuilder from './LeftJoinLoadBuilder.js'; import LoadBuilder from './LoadBuilder.js'; import Query from './Query.js'; export default class DreamInstanceTransactionBuilder { private dreamInstance; private dreamTransaction; /** * Constructs a new DreamInstanceTransactionBuilder. * * @param dreamInstance - The Dream instance to build the transaction for * @param txn - The DreamTransaction instance */ constructor(dreamInstance: DreamInstance, dreamTransaction: DreamTransaction | null); /** * Loads the requested associations upon execution * * **IMPORTANT:** `load().execute()` returns a **new clone** of the model with the * associations loaded. It does NOT modify the original instance. * * NOTE: {@link Dream#preload} is often a preferrable way of achieving the * same goal. * * ```ts * await ApplicationModel.transaction(async txn => { * const loadedUser = await user * .txn(txn) * .load('posts', { and: { body: ops.ilike('%hello world%') } }, 'comments', 'replies') * .load('images') * .execute() * * loadedUser.posts[0].comments[0].replies[0] * // Reply{} * * loadedUser.images[0] * // Image{} * }) * ``` * * @param args - A chain of association names and and/andNot/andAny clauses * @returns A chainable LoadBuilder instance */ load, DB extends DreamInstance['DB'], TableName extends DreamInstance['table'], Schema extends DreamInstance['schema'], const Arr extends readonly unknown[]>(this: I, ...args: [...Arr, VariadicLoadArgs]): LoadBuilder; /** * Recursively loads all Dream associations referenced by `rendersOne` and `rendersMany` * in a DreamSerializer. This traverses the entire content tree of serializers to automatically * load all necessary associations, eliminating N+1 query problems and removing the need to * manually remember which associations to preload for serialization. * * This method decouples data loading code from data rendering code by having the serializer * (rendering code) inform the query (loading code) about which associations are needed. * As serializers evolve over time - adding new `rendersOne` and `rendersMany` calls or * modifying existing ones - the loading code automatically adapts without requiring * corresponding modifications to preload statements. * * This method analyzes the serializer (specified by `serializerKey` or 'default') and * automatically preloads all associations that will be needed during serialization. * * ```ts * await ApplicationModel.transaction(async txn => { * // Instead of manually specifying all associations: * await User.txn(txn).preload('posts', 'comments', 'replies').all() * * // Automatically preload everything needed for serialization: * await user.txn(txn).loadFor('summary').execute() * * // Add where conditions to specific associations during preloading: * await user.txn(txn).loadFor('detailed', (associationName, dreamClass) => { * if (dreamClass.typeof(Post) && associationName === 'comments') { * return { and: { published: true } } * } * }).execute() * * // Skip preloading specific associations to handle them manually: * await user * .txn(txn) * .loadFor('summary', (associationName, dreamClass) => { * if (dreamClass.typeof(User) && associationName === 'posts') { * return 'omit' // Handle posts preloading separately with custom logic * } * }) * .load('posts', { and: { featured: true } }) // Custom preloading * .execute() * }) * ``` * * @param serializerKey - The serializer key to use for determining which associations to preload. * @param modifierFn - Optional callback function to modify or omit specific associations during preloading. Called for each association with the Dream class and association name. Return an object with `and`, `andAny`, or `andNot` properties to add where conditions, return 'omit' to skip preloading that association (useful when you want to handle it manually), or return undefined to use default preloading * @returns A Query with all serialization associations preloaded */ loadFor, SerializerKey extends DreamSerializerKey>(this: I, serializerKey: SerializerKey, modifierFn?: LoadForModifierFn): LoadBuilder; /** * Load each specified association using a single SQL query. * See {@link #load} for loading in separate queries. * * **IMPORTANT:** Like `load()`, `leftJoinLoad().execute()` returns a **new clone** of the * model with associations loaded. It does NOT modify the original instance. * * Note: since leftJoinLoad loads via single query, it has * some downsides that may be avoided using {@link #load}: * 1. `limit` and `offset` will be automatically removed * 2. `through` associations will bring additional namespaces into the query that can conflict with through associations from other associations, creating an invalid query * 3. each nested association will result in an additional record which duplicates data from the outer record. E.g., given `.leftJoinLoad('a', 'b', 'c')`, if each `a` has 10 `b` and each `b` has 10 `c`, then for one `a`, 100 records will be returned, each of which has all of the columns of `a`. `.load('a', 'b', 'c')` would perform three separate SQL queries, but the data for a single `a` would only be returned once. * 4. the individual query becomes more complex the more associations are included * 5. associations loading associations loading associations could result in exponential amounts of data; in those cases, `.load(...).findEach(...)` avoids instantiating massive amounts of data at once * * ```ts * await ApplicationModel.transaction(async txn => { * const loadedUser = await user * .txn(txn) * .leftJoinLoad('posts', { and: { body: ops.ilike('%hello world%') } }, 'comments', 'replies') * .leftJoinLoad('images') * .execute() * * loadedUser.posts[0].comments[0].replies[0] * // Reply{} * * loadedUser.images[0] * // Image{} * }) * ``` * * @param args - A chain of association names and and/andNot/andAny clauses * @returns A chainable LeftJoinLoadBuilder instance */ leftJoinLoad, DB extends DreamInstance['DB'], TableName extends DreamInstance['table'], Schema extends DreamInstance['schema'], const Arr extends readonly unknown[]>(this: I, ...args: [...Arr, VariadicLeftJoinLoadArgs]): LeftJoinLoadBuilder; /** * Returns a new Query instance with the provided * inner join statement attached * * ```ts * await ApplicationModel.transaction(async txn => { * await user.txn(txn).innerJoin('posts').first() * }) * ``` * * @param args - A chain of association names and and/andNot/andAny clauses * @returns A Query for this model with the inner join clause applied */ innerJoin, DB extends DreamInstance['DB'], TableName extends DreamInstance['table'], Schema extends DreamInstance['schema'], const Arr extends readonly unknown[], const LastArg extends VariadicJoinsArgs, const JoinedAssociationsCandidate = JoinedAssociationsTypeFromAssociations, const JoinedAssociations extends readonly JoinedAssociation[] = JoinedAssociationsCandidate extends readonly JoinedAssociation[] ? JoinedAssociationsCandidate : never, RetQuery = QueryWithJoinedAssociationsType, JoinedAssociations>>(this: I, ...args: [...Arr, LastArg]): RetQuery; /** * Returns a new Query instance with the provided * left join statement attached * * ```ts * await ApplicationModel.transaction(async txn => { * await user.txn(txn).leftJoin('posts').first() * }) * ``` * * @param args - A chain of association names and and/andNot/andAny clauses * @returns A Query for this model with the left join clause applied */ leftJoin, DB extends DreamInstance['DB'], TableName extends DreamInstance['table'], Schema extends DreamInstance['schema'], const Arr extends readonly unknown[], const LastArg extends VariadicJoinsArgs, const JoinedAssociationsCandidate = JoinedAssociationsTypeFromAssociations, const JoinedAssociations extends readonly JoinedAssociation[] = JoinedAssociationsCandidate extends readonly JoinedAssociation[] ? JoinedAssociationsCandidate : never, RetQuery = QueryWithJoinedAssociationsType, JoinedAssociations>>(this: I, ...args: [...Arr, LastArg]): RetQuery; /** * Deletes the record represented by this instance * from the database, calling any destroy * hooks on this model. * * ```ts * const user = await User.last() * await ApplicationModel.transaction(async txn => { * await user.txn(txn).destroy() * }) * ``` * * @param options - Options for destroying the instance * @param options.skipHooks - If true, skips applying model hooks during the destroy operation. Defaults to false * @param options.cascade - If false, skips destroying associations marked `dependent: 'destroy'`. Defaults to true * @param options.bypassAllDefaultScopes - If true, bypasses user-removable default scopes when cascade destroying; an STI child's reserved discriminator remains enforced, including when associations are loaded. Defaults to false * @param options.defaultScopesToBypass - An array of default scope names to bypass when cascade destroying. Defaults to an empty array * @returns The instance that was destroyed */ destroy>(this: I, options?: InstanceDestroyOptions): Promise; /** * Deletes the record represented by this instance * from the database, calling any destroy * hooks on this model. * * ```ts * const user = await User.last() * await ApplicationModel.transaction(async txn => { * await user.txn(txn).reallyDestroy() * }) * ``` * * @param options - Options for destroying the instance * @param options.skipHooks - If true, skips applying model hooks during the destroy operation. Defaults to false * @param options.cascade - If false, skips destroying associations marked `dependent: 'destroy'`. Defaults to true * @param options.bypassAllDefaultScopes - If true, bypasses user-removable default scopes when cascade destroying; an STI child's reserved discriminator remains enforced, including when associations are loaded. Defaults to false * @param options.defaultScopesToBypass - An array of default scope names to bypass when cascade destroying. Defaults to an empty array * @returns The instance that was destroyed */ reallyDestroy>(this: I, options?: InstanceDestroyOptions): Promise; /** * Undestroys a SoftDelete model, unsetting * the `deletedAt` field in the database. * * If the model is not a SoftDelete model, * this will raise an exception. * * ```ts * const user = await User.removeDefaultScope('dream:SoftDelete').last() * await user.txn(txn).undestroy() * ``` * * @param options - Options for undestroying the instance * @param options.skipHooks - If true, skips applying model hooks during the undestroy operation. Defaults to false * @param options.cascade - If false, skips undestroying associations marked `dependent: 'destroy'`. Defaults to true * @param options.bypassAllDefaultScopes - If true, bypasses user-removable default scopes when cascade undestroying; an STI child's reserved discriminator remains enforced, including when associations are loaded. Defaults to false * @param options.defaultScopesToBypass - An array of default scope names to bypass when cascade undestroying (soft delete is always bypassed). Defaults to an empty array * @returns The undestroyed instance */ undestroy>(this: I, options?: InstanceDestroyOptions): Promise; /** * Applies all attribute changes passed to the Dream * instance, leveraging any custom-defined setters, * and then saves the Dream instance. Can be called * on an unpersisted Dream instance. * * See {@link Dream.save | save} for details on * the side effects of saving. * * A column whose value is still `undefined` after setters run is * skipped, not written (see {@link Dream.save | save}), with two * `@Encrypted` exceptions: `undefined` for an encrypted property (e.g. * `secret`) is encrypted to `null`, so it clears the column, and * `undefined` for its backing column (e.g. `encryptedSecret`) throws. * * NOTE: * To bypass custom-defined setters, use {@link Dream.updateAttributes | updateAttributes} instead. * * ```ts * const user = await User.create({ email: 'saly@gmail.com' }) * await ApplicationModel.transaction(async txn => { * await user.txn(txn).update({ email: 'sally@gmail.com' }) * }) * ``` * * @param attributes - the attributes to set on the model * @param opts.skipHooks - if true, will skip applying model hooks. Defaults to false * @returns void */ update>(this: I, attributes: UpdateableProperties, { skipHooks }?: InstanceUpdateOptions): Promise; /** * Applies all attribute changes passed to the dream, * bypassing any custom-defined setters, * and then saves the dream instance. Does not bypass * model hooks. * * See {@link Dream.save | save} for details on * the side effects of saving. * * An encrypted property (e.g. `secret`) is still encrypted. Its * `@Encrypted` backing column (e.g. `encryptedSecret`) accepts only * ciphertext that decrypts with this app's column encryption keys, or * `null`; anything else throws before anything is saved (see * {@link Dream.setAttribute | setAttribute}). * * A column whose value is still `undefined` after setters run is * skipped, not written (see {@link Dream.save | save}), with two * `@Encrypted` exceptions: `undefined` for an encrypted property (e.g. * `secret`) is encrypted to `null`, so it clears the column, and * `undefined` for its backing column (e.g. `encryptedSecret`) throws. * * NOTE: * To update the values without bypassing any custom-defined * setters, use {@link Dream.update | update} instead. * * ```ts * const user = await User.create({ email: 'saly@gmail.com' }) * await ApplicationModel.transaction(async txn => { * await user.txn(txn).updateAttributes({ email: 'sally@gmail.com' }) * }) * ``` * * @param attributes - The attributes to update on this instance * @param opts.skipHooks - if true, will skip applying model hooks. Defaults to false * @returns - void */ updateAttributes>(this: I, attributes: UpdateableProperties, { skipHooks }?: InstanceUpdateOptions): Promise; /** * Reloads an instance, refreshing all it's attribute values * to those in the database. * * NOTE: this does not refresh associations * * ```ts * await ApplicationModel.transaction(async txn => { * await user.txn(txn).reload() * }) * ``` * * @returns void */ reload>(this: I): Promise; /** * Saves the state of the current instance to the * database. For new instances (that have not been * persisted), `save` and `create` model hooks will be called. * For instances that have already been persisted, * the `save` and `update` model hooks will be called. * * Upon saving a new instance, the primary key, timestamp * fields (if defined), and `type` (if STI) will be set on * the model. * * Upon updating an instance, the update timestamp (if defined) * will be updated on the model. * * A column whose value is `undefined` is skipped, not written: a new * record gets the column's database default, and a persisted record * keeps the value stored for it. Set a column to `null` to clear it. * * ```ts * const user = User.new({ email: 'how@yadoin' }) * * await ApplicationModel.transaction(async txn => { * user.name = 'fred' * await user.txn(txn).save() * }) * * user.email // 'how@yadoin' * user.name // 'fred' * user.id // 1 * user.createdAt // A DateTime object * user.updatedAt // A DateTime object * * // If User were STI: * user.type // 'User' * ``` * * @param opts.skipHooks - if true, will skip applying model hooks. Defaults to false * @returns void */ save>(this: I, { skipHooks }?: { skipHooks?: boolean; }): Promise; /** * If the association is already loaded on the instance, it returns the loaded value * immediately without making a database query. If the association is not loaded, * it performs a database query to fetch the association. * * If a query is performed, the association is set on the model so that future calls to * access this association can access the already loaded value. * * For HasMany associations, returns an array (empty if no records). For BelongsTo/HasOne * associations, returns the associated model or null if not found. * * ```ts * // Basic association loading within a transaction * await ApplicationModel.transaction(async txn => { * const user = await post.txn(txn).association('user') * const comments = await post.txn(txn).association('comments') * }) * * // With required clause (for associations with DreamConst.required `and` clauses) * const pets = await user.txn(txn).association('petsWithRequiredName', { * required: { name: 'Woodstock' } * }) * * // With passthrough clause (for associations with DreamConst.passthrough `and` clauses) * const pets = await user.txn(txn).association('petsWithPassthroughName', { * passthrough: { name: 'Woodstock' } * }) * * // With both required and passthrough clauses (for associations with DreamConst.required and DreamConst.passthrough `and` clauses) * const text = await composition.txn(txn).association('passthroughAndRequiredCurrentLocalizedText', { * passthrough: { name: 'My Composition' }, * required: { locale: 'de-DE' } * }) * ``` * * @param associationName - The name of the BelongsTo, HasOne, or HasMany association * @param options - Optional configuration for required and passthrough clauses * @param options.required - for associations with DreamConst.required `and` clauses * @param options.passthrough - for associations with DreamConst.passthrough `and` clauses * @returns The associated model instance(s) or null/empty array if not found */ association, MaybeAssociationName extends DreamBelongsToAssociationNames | DreamHasOneAssociationNames | DreamHasManyAssociationNames, AssociationName extends MaybeAssociationName extends DreamAssociationNamesWithPassthroughOnClauses | DreamAssociationNamesWithRequiredOnClauses ? MaybeAssociationName : never, AssociationDream extends AssociationNameToDream, AssociationTableName extends AssociationDream['table'], DB extends DreamInstance['DB'], TableName extends DreamInstance['table'], Schema extends DreamInstance['schema'], PassthroughOnStatement extends Required & string[]>>, RequiredOnStatement extends Required & string[]>>, Opts extends AssociationName extends DreamAssociationNamesWithPassthroughOnClauses & DreamAssociationNamesWithRequiredOnClauses ? { passthrough: PassthroughOnStatement; required: RequiredOnStatement; } : AssociationName extends DreamAssociationNamesWithPassthroughOnClauses ? { passthrough: PassthroughOnStatement; } : AssociationName extends DreamAssociationNamesWithRequiredOnClauses ? { required: RequiredOnStatement; } : never, ReturnType extends AssociationName extends DreamHasManyAssociationNames ? AssociationNameToDream[] : AssociationNameToDream | null>(this: I, associationName: AssociationName, options: Opts): Promise; association, MaybeAssociationName extends DreamBelongsToAssociationNames | DreamHasOneAssociationNames | DreamHasManyAssociationNames, AssociationName extends MaybeAssociationName extends DreamAssociationNamesWithPassthroughOnClauses | DreamAssociationNamesWithRequiredOnClauses ? never : MaybeAssociationName, ReturnType extends AssociationName extends DreamHasManyAssociationNames ? AssociationNameToDream[] : AssociationNameToDream | null>(this: I, associationName: AssociationName): Promise; /** * If the association is already loaded on the instance, it returns the loaded value * immediately without making a database query. If the association is not loaded, * it performs a database query to fetch the association. * * Unlike `association`, this method throws an exception if no associated * record is found for BelongsTo/HasOne associations, guaranteeing a non-null result. * For HasMany associations, returns an empty array instead of throwing when no records exist. * * If a query is performed, the association is set on the model so that future calls to * access this association can access the already loaded value. * * For HasMany associations, returns an array (empty if no records). For BelongsTo/HasOne * associations, returns the associated model or throws RecordNotFound if not found. * * ```ts * // Basic association loading within a transaction - throws RecordNotFound if user doesn't exist * await ApplicationModel.transaction(async txn => { * const user = await post.txn(txn).associationOrFail('user') * const comments = await post.txn(txn).associationOrFail('comments') // returns empty array if no comments * }) * * // With required clause (for associations with DreamConst.required `and` clauses) * const pets = await user.txn(txn).associationOrFail('petsWithRequiredName', { * required: { name: 'Woodstock' } * }) * * // With passthrough clause (for associations with DreamConst.passthrough `and` clauses) * const pets = await user.txn(txn).associationOrFail('petsWithPassthroughName', { * passthrough: { name: 'Woodstock' } * }) * * // With both required and passthrough clauses (for associations with DreamConst.required and DreamConst.passthrough `and` clauses) * const text = await composition.txn(txn).associationOrFail('passthroughAndRequiredCurrentLocalizedText', { * passthrough: { name: 'My Composition' }, * required: { locale: 'de-DE' } * }) * ``` * * @param associationName - The name of the BelongsTo, HasOne, or HasMany association * @param options - Optional configuration for required and passthrough clauses * @param options.required - for associations with DreamConst.required `and` clauses * @param options.passthrough - for associations with DreamConst.passthrough `and` clauses * @returns The associated model instance(s) (never null for BelongsTo/HasOne) * @throws RecordNotFound if no associated record exists (BelongsTo/HasOne only) */ associationOrFail, MaybeAssociationName extends DreamBelongsToAssociationNames | DreamHasOneAssociationNames | DreamHasManyAssociationNames, AssociationName extends MaybeAssociationName extends DreamAssociationNamesWithPassthroughOnClauses | DreamAssociationNamesWithRequiredOnClauses ? MaybeAssociationName : never, AssociationDream extends AssociationNameToDream, AssociationTableName extends AssociationDream['table'], DB extends DreamInstance['DB'], TableName extends DreamInstance['table'], Schema extends DreamInstance['schema'], PassthroughOnStatement extends Required & string[]>>, RequiredOnStatement extends Required & string[]>>, Opts extends AssociationName extends DreamAssociationNamesWithPassthroughOnClauses & DreamAssociationNamesWithRequiredOnClauses ? { passthrough: PassthroughOnStatement; required: RequiredOnStatement; } : AssociationName extends DreamAssociationNamesWithPassthroughOnClauses ? { passthrough: PassthroughOnStatement; } : AssociationName extends DreamAssociationNamesWithRequiredOnClauses ? { required: RequiredOnStatement; } : never, ReturnType extends AssociationName extends DreamHasManyAssociationNames ? AssociationNameToDream[] : AssociationNameToDream>(this: I, associationName: AssociationName, options: Opts): Promise; associationOrFail, MaybeAssociationName extends DreamBelongsToAssociationNames | DreamHasOneAssociationNames | DreamHasManyAssociationNames, AssociationName extends MaybeAssociationName extends DreamAssociationNamesWithPassthroughOnClauses | DreamAssociationNamesWithRequiredOnClauses ? never : MaybeAssociationName, ReturnType extends AssociationName extends DreamHasManyAssociationNames ? AssociationNameToDream[] : AssociationNameToDream>(this: I, associationName: AssociationName): Promise; associationQuery, DB extends DreamInstance['DB'], TableName extends DreamInstance['table'], Schema extends DreamInstance['schema'], AssociationName extends DreamAssociationNamesWithRequiredOnClauses, RequiredOnClauseKeysForThisAssociation extends RequiredOnClauseKeys, AssociationDream extends AssociationNameToDream, AssociationTableName extends AssociationDream['table']>(this: I, associationName: AssociationName, joinAndStatements: JoinAndStatements): Query>; associationQuery, DB extends DreamInstance['DB'], Schema extends DreamInstance['schema'], AssociationName extends DreamAssociationNamesWithoutRequiredOnClauses, AssociationDream extends AssociationNameToDream, AssociationTableName extends AssociationDream['table']>(this: I, associationName: AssociationName, joinAndStatements?: JoinAndStatements): Query>; updateAssociation, DB extends DreamInstance['DB'], TableName extends DreamInstance['table'], Schema extends DreamInstance['schema'], AssociationName extends DreamAssociationNamesWithRequiredOnClauses, RequiredOnClauseKeysForThisAssociation extends RequiredOnClauseKeys, AssociationDream extends AssociationNameToDream, AssociationTableName extends AssociationDream['table'], PossibleArrayAssociationType = DreamInstance[AssociationName & keyof DreamInstance], AssociationType = PossibleArrayAssociationType extends (infer ElementType)[] ? ElementType : PossibleArrayAssociationType, RestrictedAssociationType extends AssociationType extends Dream ? AssociationType : never = AssociationType extends Dream ? AssociationType : never>(this: I, associationName: AssociationName, attributes: UpdateableAssociationProperties, updateAssociationOptions: InstanceUpdateOptions & { bypassAllDefaultScopes?: boolean; defaultScopesToBypass?: AllDefaultScopeNames[]; } & JoinAndStatements): Promise; updateAssociation, DB extends DreamInstance['DB'], Schema extends DreamInstance['schema'], AssociationName extends DreamAssociationNamesWithoutRequiredOnClauses, AssociationDream extends AssociationNameToDream, AssociationTableName extends AssociationDream['table'], PossibleArrayAssociationType = DreamInstance[AssociationName & keyof DreamInstance], AssociationType = PossibleArrayAssociationType extends (infer ElementType)[] ? ElementType : PossibleArrayAssociationType, RestrictedAssociationType extends AssociationType extends Dream ? AssociationType : never = AssociationType extends Dream ? AssociationType : never>(this: I, associationName: AssociationName, attributes: UpdateableAssociationProperties, updateAssociationOptions?: InstanceUpdateOptions & { bypassAllDefaultScopes?: boolean; defaultScopesToBypass?: AllDefaultScopeNames[]; } & JoinAndStatements): Promise; /** * Creates an association for an instance. Automatically * handles setting foreign key and, in the case of polymorphism, * foreign key type. * * ```ts * await ApplicationModel.transaction(async txn => { * await user.txn(txn).createAssociation('posts', { body: 'hello world' }) * }) * ``` * * @param associationName - The name of the association to create * @param attributes - The attributes with which to create the associated model * @returns The created association */ createAssociation, AssociationName extends DreamAssociationNames, PossibleArrayAssociationType = DreamInstance[AssociationName & keyof DreamInstance], AssociationType = PossibleArrayAssociationType extends (infer ElementType)[] ? ElementType : PossibleArrayAssociationType, RestrictedAssociationType extends AssociationType extends Dream ? AssociationType : never = AssociationType extends Dream ? AssociationType : never>(this: I, associationName: AssociationName, opts?: UpdateableAssociationProperties): Promise>; destroyAssociation, DB extends DreamInstance['DB'], TableName extends DreamInstance['table'], Schema extends DreamInstance['schema'], AssociationName extends DreamAssociationNamesWithRequiredOnClauses, RequiredOnClauseKeysForThisAssociation extends RequiredOnClauseKeys, AssociationDream extends AssociationNameToDream, AssociationTableName extends AssociationDream['table']>(this: I, associationName: AssociationName, options: InstanceDestroyOptions & JoinAndStatements): Promise; destroyAssociation, DB extends DreamInstance['DB'], Schema extends DreamInstance['schema'], AssociationName extends DreamAssociationNamesWithoutRequiredOnClauses, AssociationDream extends AssociationNameToDream, AssociationTableName extends AssociationDream['table']>(this: I, associationName: AssociationName, options?: InstanceDestroyOptions & JoinAndStatements): Promise; reallyDestroyAssociation, DB extends DreamInstance['DB'], TableName extends DreamInstance['table'], Schema extends DreamInstance['schema'], AssociationName extends DreamAssociationNamesWithRequiredOnClauses, RequiredOnClauseKeysForThisAssociation extends RequiredOnClauseKeys, AssociationDream extends AssociationNameToDream, AssociationTableName extends AssociationDream['table']>(this: I, associationName: AssociationName, options: InstanceDestroyOptions & JoinAndStatements): Promise; reallyDestroyAssociation, DB extends DreamInstance['DB'], Schema extends DreamInstance['schema'], AssociationName extends DreamAssociationNamesWithoutRequiredOnClauses, AssociationDream extends AssociationNameToDream, AssociationTableName extends AssociationDream['table']>(this: I, associationName: AssociationName, options?: InstanceDestroyOptions & JoinAndStatements): Promise; undestroyAssociation, DB extends DreamInstance['DB'], TableName extends DreamInstance['table'], Schema extends DreamInstance['schema'], AssociationName extends DreamAssociationNamesWithRequiredOnClauses, RequiredOnClauseKeysForThisAssociation extends RequiredOnClauseKeys, AssociationDream extends AssociationNameToDream, AssociationTableName extends AssociationDream['table']>(this: I, associationName: AssociationName, options: InstanceDestroyOptions & JoinAndStatements): Promise; undestroyAssociation, DB extends DreamInstance['DB'], Schema extends DreamInstance['schema'], AssociationName extends DreamAssociationNamesWithoutRequiredOnClauses, AssociationDream extends AssociationNameToDream, AssociationTableName extends AssociationDream['table']>(this: I, associationName: AssociationName, options?: InstanceDestroyOptions & JoinAndStatements): Promise; /** * @internal * * returns a query instance, scoped to the current * dream instance with primary key where statement * automatically applied. */ private queryInstance; }