Skip to content

Commit e5b20b7

Browse files
prettier
1 parent 957c385 commit e5b20b7

File tree

13 files changed

+350
-239
lines changed

13 files changed

+350
-239
lines changed

packages/core/src/associations/base.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -319,7 +319,7 @@ export interface AssociationOptions<ForeignKey extends string = string> extends
319319
*/
320320
foreignKey?: ForeignKey | ForeignKeyOptions<ForeignKey>;
321321

322-
foreignKeys?: ForeignKey[] | Array<{ source: string, target: string }>;
322+
foreignKeys?: ForeignKey[] | Array<{ source: string; target: string }>;
323323

324324
/**
325325
* Should ON UPDATE, ON DELETE, and REFERENCES constraints be enabled on the foreign key.

packages/core/src/associations/belongs-to.ts

Lines changed: 57 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
1-
import isEqual from 'lodash/isEqual';
1+
import { MapView } from '@sequelize/utils';
22
import isEmpty from 'lodash/isEmpty.js';
3+
import isEqual from 'lodash/isEqual';
34
import isObject from 'lodash/isObject.js';
45
import upperFirst from 'lodash/upperFirst';
56
import assert from 'node:assert';
@@ -29,7 +30,6 @@ import { HasManyAssociation } from './has-many.js';
2930
import { HasOneAssociation } from './has-one.js';
3031
import type { NormalizeBaseAssociationOptions } from './helpers';
3132
import { defineAssociation, mixinMethods, normalizeBaseAssociationOptions } from './helpers';
32-
import { MapView } from '@sequelize/utils';
3333

3434
/**
3535
* One-to-one association
@@ -64,7 +64,7 @@ export class BelongsToAssociation<
6464

6565
foreignKey: SourceKey;
6666

67-
foreignKeys: Array<{ source: SourceKey, target: TargetKey }> = [];
67+
foreignKeys: Array<{ source: SourceKey; target: TargetKey }> = [];
6868

6969
/**
7070
* The column name of the foreign key
@@ -113,26 +113,29 @@ export class BelongsToAssociation<
113113
parent?: Association,
114114
) {
115115
const isForeignKeyEmpty = isEmpty(options.foreignKey);
116-
const isForeignKeysValid = Array.isArray(options.foreignKeys)
117-
&& options.foreignKeys.length > 0
118-
&& options.foreignKeys.every(fk => !isEmpty(fk));
116+
const isForeignKeysValid =
117+
Array.isArray(options.foreignKeys) &&
118+
options.foreignKeys.length > 0 &&
119+
options.foreignKeys.every(fk => !isEmpty(fk));
119120

120121
let targetKeys;
121122
if (isForeignKeyEmpty && isForeignKeysValid) {
122-
targetKeys = (options.foreignKeys as Array<{ source: SourceKey, target: TargetKey }>).map(fk => fk.target);
123+
targetKeys = (options.foreignKeys as Array<{ source: SourceKey; target: TargetKey }>).map(
124+
fk => fk.target,
125+
);
123126
} else {
124127
targetKeys = options?.targetKey
125-
? [options.targetKey]
126-
: target.modelDefinition.primaryKeysAttributeNames;
128+
? [options.targetKey]
129+
: target.modelDefinition.primaryKeysAttributeNames;
127130
}
128131

129132
const targetAttributes = target.modelDefinition.attributes;
130133

131134
for (const key of targetKeys) {
132135
if (!targetAttributes.has(key)) {
133136
throw new Error(
134-
`Unknown attribute "${key}" passed as targetKey, define this attribute on model "${target.name}" first`,
135-
);
137+
`Unknown attribute "${key}" passed as targetKey, define this attribute on model "${target.name}" first`,
138+
);
136139
}
137140
}
138141

@@ -148,15 +151,14 @@ export class BelongsToAssociation<
148151

149152
const shouldHashPrimaryKey = this.shouldHashPrimaryKey(targetAttributes);
150153

151-
if ((!isEmpty(options.foreignKeys) && isEmpty(options.foreignKey)) && !shouldHashPrimaryKey) {
152-
154+
if (!isEmpty(options.foreignKeys) && isEmpty(options.foreignKey) && !shouldHashPrimaryKey) {
153155
// Composite key flow
154156
// TODO: fix this
155157
this.targetKey = null as any;
156158
this.foreignKey = null as any;
157159
this.identifierField = null as any;
158160

159-
this.foreignKeys = options.foreignKeys as Array<{ source: SourceKey, target: TargetKey }>;
161+
this.foreignKeys = options.foreignKeys as Array<{ source: SourceKey; target: TargetKey }>;
160162

161163
for (const targetKey of this.targetKeys) {
162164
const targetColumn = targetAttributes.get(targetKey)!;
@@ -170,7 +172,6 @@ export class BelongsToAssociation<
170172
[targetColumn.columnName]: newForeignKeyAttribute,
171173
});
172174
}
173-
174175
} else {
175176
const [targetKey] = this.targetKeys;
176177
this.targetKey = targetKey;
@@ -179,9 +180,9 @@ export class BelongsToAssociation<
179180
// else, server throws SQL0573N error. Hence, setting it here explicitly
180181
// for non primary columns.
181182
if (
182-
target.sequelize.dialect.name === 'db2' &&
183-
targetAttributes.get(this.targetKey)!.primaryKey !== true
184-
) {
183+
target.sequelize.dialect.name === 'db2' &&
184+
targetAttributes.get(this.targetKey)!.primaryKey !== true
185+
) {
185186
// TODO: throw instead
186187
this.target.modelDefinition.rawAttributes[this.targetKey].unique = true;
187188
}
@@ -218,7 +219,7 @@ export class BelongsToAssociation<
218219
if (options.foreignKeyConstraints !== false) {
219220
const existingReference = existingForeignKey?.references
220221
? ((normalizeReference(existingForeignKey.references) ??
221-
existingForeignKey.references) as AttributeReferencesOptions)
222+
existingForeignKey.references) as AttributeReferencesOptions)
222223
: undefined;
223224

224225
const queryGenerator = this.source.sequelize.queryGenerator;
@@ -233,24 +234,27 @@ export class BelongsToAssociation<
233234
if (existingReferencedTable) {
234235
if (!isEqual(existingReferencedTable, newReferencedTable)) {
235236
throw new Error(
236-
`Foreign key ${this.foreignKey} on ${this.source.name} already references ${queryGenerator.quoteTable(existingReferencedTable)}, but this association needs to make it reference ${queryGenerator.quoteTable(newReferencedTable)} instead.`,
237-
);
237+
`Foreign key ${this.foreignKey} on ${this.source.name} already references ${queryGenerator.quoteTable(existingReferencedTable)}, but this association needs to make it reference ${queryGenerator.quoteTable(newReferencedTable)} instead.`,
238+
);
238239
}
239240
} else {
240241
newReference.table = newReferencedTable;
241242
}
242243

243-
if (existingReference?.key && existingReference.key !== this.targetKeyField(this.targetKey)) {
244-
throw new Error(
245-
`Foreign key ${this.foreignKey} on ${this.source.name} already references column ${existingReference.key}, but this association needs to make it reference ${this.targetKeyField} instead.`,
246-
);
247-
}
244+
if (
245+
existingReference?.key &&
246+
existingReference.key !== this.targetKeyField(this.targetKey)
247+
) {
248+
throw new Error(
249+
`Foreign key ${this.foreignKey} on ${this.source.name} already references column ${existingReference.key}, but this association needs to make it reference ${this.targetKeyField} instead.`,
250+
);
251+
}
248252

249253
newReference.key = this.targetKeyField(this.targetKey);
250254

251255
newForeignKeyAttribute.references = newReference;
252256
newForeignKeyAttribute.onDelete ??=
253-
newForeignKeyAttribute.allowNull !== false ? 'SET NULL' : 'CASCADE';
257+
newForeignKeyAttribute.allowNull !== false ? 'SET NULL' : 'CASCADE';
254258
newForeignKeyAttribute.onUpdate ??= newForeignKeyAttribute.onUpdate ?? 'CASCADE';
255259
}
256260

@@ -300,15 +304,21 @@ export class BelongsToAssociation<
300304
}
301305
}
302306

303-
private setupTargetKeys(options: NormalizedBelongsToOptions<SourceKey, TargetKey>, target: ModelStatic<T>) {
307+
private setupTargetKeys(
308+
options: NormalizedBelongsToOptions<SourceKey, TargetKey>,
309+
target: ModelStatic<T>,
310+
) {
304311
const isForeignKeyEmpty = isEmpty(options.foreignKey);
305-
const isForeignKeysValid = Array.isArray(options.foreignKeys)
306-
&& options.foreignKeys.length > 0
307-
&& options.foreignKeys.every(fk => !isEmpty(fk));
312+
const isForeignKeysValid =
313+
Array.isArray(options.foreignKeys) &&
314+
options.foreignKeys.length > 0 &&
315+
options.foreignKeys.every(fk => !isEmpty(fk));
308316

309317
let targetKeys;
310318
if (isForeignKeyEmpty && isForeignKeysValid) {
311-
targetKeys = (options.foreignKeys as Array<{ source: SourceKey, target: TargetKey }>).map(fk => fk.target);
319+
targetKeys = (options.foreignKeys as Array<{ source: SourceKey; target: TargetKey }>).map(
320+
fk => fk.target,
321+
);
312322
} else {
313323
targetKeys = options?.targetKey
314324
? [options.targetKey]
@@ -318,11 +328,15 @@ export class BelongsToAssociation<
318328
const targetAttributes = target.modelDefinition.attributes;
319329
for (const key of targetKeys) {
320330
if (!targetAttributes.has(key)) {
321-
throw new Error(`Unknown attribute "${key}" passed as targetKey, define this attribute on model "${target.name}" first`);
331+
throw new Error(
332+
`Unknown attribute "${key}" passed as targetKey, define this attribute on model "${target.name}" first`,
333+
);
322334
}
323335
}
324336

325-
this.targetKeys = Array.isArray(targetKeys) ? targetKeys : [...targetKeys].map(key => key as TargetKey);
337+
this.targetKeys = Array.isArray(targetKeys)
338+
? targetKeys
339+
: [...targetKeys].map(key => key as TargetKey);
326340
}
327341

328342
/**
@@ -334,15 +348,20 @@ export class BelongsToAssociation<
334348
* @param targetAttributes
335349
* @protected
336350
*/
337-
protected shouldHashPrimaryKey(targetAttributes: MapView<string, NormalizedAttributeOptions<Model<any, any>>>): Boolean {
351+
protected shouldHashPrimaryKey(
352+
targetAttributes: MapView<string, NormalizedAttributeOptions<Model<any, any>>>,
353+
): Boolean {
338354
const primaryKeyAttributes = [];
339355
for (const attributes of targetAttributes.values()) {
340356
if (attributes.primaryKey) {
341357
primaryKeyAttributes.push(attributes);
342358
}
343359
}
344360

345-
return primaryKeyAttributes.length === 2 && primaryKeyAttributes.some(attr => attr.type === 'BINARY(16)');
361+
return (
362+
primaryKeyAttributes.length === 2 &&
363+
primaryKeyAttributes.some(attr => attr.type === 'BINARY(16)')
364+
);
346365
}
347366

348367
static associate<
@@ -456,13 +475,13 @@ export class BelongsToAssociation<
456475
} else if (this.targetKeyIsPrimary(this.targetKey) && !options.where) {
457476
const foreignKeyValue = instances[0].get(this.foreignKey);
458477

459-
return Target.findByPk(foreignKeyValue as any, options);} else {
478+
return Target.findByPk(foreignKeyValue as any, options);
479+
} else {
460480
// TODO: combine once we can just have the foreignKey in the foreignKeys array all the time
461481
if (this.isCompositeKey) {
462482
for (const key of this.foreignKeys) {
463483
where[key.target] = instances[0].get(key.source);
464484
}
465-
466485
} else {
467486
where[this.targetKey] = instances[0].get(this.foreignKey);
468487
}

packages/core/src/associations/has-one.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,8 @@ export class HasOneAssociation<
122122
as: options.inverse?.as,
123123
scope: options.inverse?.scope,
124124
foreignKey: options.foreignKey,
125-
foreignKeys: options.foreignKeys,targetKey: options.sourceKey,
125+
foreignKeys: options.foreignKeys,
126+
targetKey: options.sourceKey,
126127
foreignKeyConstraints: options.foreignKeyConstraints,
127128
hooks: options.hooks,
128129
}),
@@ -248,7 +249,6 @@ If having two associations does not make sense (for instance a "spouse" associat
248249
for (const key of this.foreignKeys) {
249250
where[key.target] = instances[0].get(key.source);
250251
}
251-
252252
} else {
253253
where[this.foreignKey] = instances[0].get(this.sourceKey);
254254
}

packages/core/src/associations/helpers.ts

Lines changed: 34 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
1-
import assert from 'node:assert';
2-
import NodeUtils from 'node:util';
31
import isArray from 'lodash/isArray';
42
import isEmpty from 'lodash/isEmpty';
53
import isEqual from 'lodash/isEqual';
64
import isPlainObject from 'lodash/isPlainObject.js';
75
import lowerFirst from 'lodash/lowerFirst';
86
import omit from 'lodash/omit';
97
import some from 'lodash/some';
8+
import assert from 'node:assert';
9+
import NodeUtils from 'node:util';
1010
import type { Class } from 'type-fest';
1111
import { AssociationError } from '../errors/index.js';
1212
import type { Model, ModelStatic } from '../model';
@@ -16,15 +16,20 @@ import { isModelStatic, isSameInitialModel } from '../utils/model-utils.js';
1616
import { removeUndefined } from '../utils/object.js';
1717
import { pluralize, singularize } from '../utils/string.js';
1818
import type { OmitConstructors } from '../utils/types.js';
19-
import type { Association, AssociationOptions, ForeignKeyOptions, NormalizedAssociationOptions } from './base';
19+
import type {
20+
Association,
21+
AssociationOptions,
22+
ForeignKeyOptions,
23+
NormalizedAssociationOptions,
24+
} from './base';
2025
import type { ThroughOptions } from './belongs-to-many.js';
2126

2227
export function checkNamingCollision(source: ModelStatic<any>, associationName: string): void {
2328
if (Object.hasOwn(source.getAttributes(), associationName)) {
2429
throw new Error(
25-
`Naming collision between attribute '${associationName}'`
26-
+ ` and association '${associationName}' on model ${source.name}`
27-
+ '. To remedy this, change the "as" options in your association definition',
30+
`Naming collision between attribute '${associationName}'` +
31+
` and association '${associationName}' on model ${source.name}` +
32+
'. To remedy this, change the "as" options in your association definition',
2833
);
2934
}
3035
}
@@ -127,7 +132,7 @@ ${NodeUtils.inspect(omit(options, 'inverse'), { sorted: true })}
127132
Options of the existing association:
128133
${NodeUtils.inspect(omit(existingAssociation.options as any, 'inverse'), { sorted: true })}
129134
`
130-
}`.trim(),
135+
}`.trim(),
131136
);
132137
}
133138

@@ -172,7 +177,7 @@ export function assertAssociationModelIsDefined(model: ModelStatic<any>): void {
172177
}
173178

174179
export type AssociationStatic<T extends Association> = {
175-
new (...arguments_: any[]): T,
180+
new (...arguments_: any[]): T;
176181
} & OmitConstructors<typeof Association>;
177182

178183
export function defineAssociation<
@@ -247,10 +252,10 @@ export function defineAssociation<
247252
}
248253

249254
export type NormalizeBaseAssociationOptions<T> = Omit<T, 'as' | 'hooks' | 'foreignKey'> & {
250-
as: string,
251-
name: { singular: string, plural: string },
252-
hooks: boolean,
253-
foreignKey: ForeignKeyOptions<any>,
255+
as: string;
256+
name: { singular: string; plural: string };
257+
hooks: boolean;
258+
foreignKey: ForeignKeyOptions<any>;
254259
// foreignKeys: Array<{ source: string, target: string }>,
255260
};
256261

@@ -288,14 +293,12 @@ export function normalizeBaseAssociationOptions<T extends AssociationOptions<any
288293

289294
// make sure both are not used at the same time
290295
if (some(options.foreignKey, isEmpty) && some(options.foreignKeys, isEmpty)) {
291-
throw new Error(
292-
'Only one of "foreignKey" and "foreignKeys" can be defined',
293-
);
296+
throw new Error('Only one of "foreignKey" and "foreignKeys" can be defined');
294297
}
295298

296299
const isMultiAssociation = associationType.isMultiAssociation;
297300

298-
let name: { singular: string, plural: string };
301+
let name: { singular: string; plural: string };
299302
let as: string;
300303
if (options?.as) {
301304
if (isPlainObject(options.as)) {
@@ -334,16 +337,18 @@ export function normalizeForeignKeyOptions<T extends string>(
334337
return typeof foreignKey === 'string'
335338
? { name: foreignKey }
336339
: removeUndefined({
337-
...foreignKey,
338-
name: foreignKey?.name ?? foreignKey?.columnName,
339-
fieldName: undefined,
340-
});
340+
...foreignKey,
341+
name: foreignKey?.name ?? foreignKey?.columnName,
342+
fieldName: undefined,
343+
});
341344
}
342345

343346
// Update the option normalization logic to turn `foreignKey` and `targetKey` into `foreignKeys`,
344-
export function normalizeCompositeForeignKeyOptions<T extends string>(options: AssociationOptions<T>): Array<{
345-
source: string,
346-
target: string,
347+
export function normalizeCompositeForeignKeyOptions<T extends string>(
348+
options: AssociationOptions<T>,
349+
): Array<{
350+
source: string;
351+
target: string;
347352
}> {
348353
if (isArray(options.foreignKeys) && !some(options.foreignKeys, isEmpty)) {
349354
return options.foreignKeys.map(fk => {
@@ -361,7 +366,12 @@ export function normalizeCompositeForeignKeyOptions<T extends string>(options: A
361366
// belongsTo has a targetKey option, which is the name of the column in the target table that the foreign key should reference.
362367
// hasOne and hasMany have a sourceKey option, which is the name of the column in the source table that the foreign key should reference.
363368
// belongsToMany has both sourceKey and targetKey, which are the names of the columns in the source and target tables that the foreign key should reference, respectively.
364-
return [{ source: sourceKey ?? normalizedForeignKey.name, target: targetKey ?? normalizedForeignKey.name }];
369+
return [
370+
{
371+
source: sourceKey ?? normalizedForeignKey.name,
372+
target: targetKey ?? normalizedForeignKey.name,
373+
},
374+
];
365375
}
366376

367377
export type MaybeForwardedModelStatic<M extends Model = Model> =

0 commit comments

Comments
 (0)