Skip to content

Commit

Permalink
Merge branch 'main' into v7
Browse files Browse the repository at this point in the history
  • Loading branch information
ephys committed Mar 12, 2023
2 parents 6d97203 + 50898ca commit 59543d9
Show file tree
Hide file tree
Showing 152 changed files with 6,687 additions and 7,830 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/authors.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ jobs:
fetch-depth: "0" # This is required to actually get all the authors
persist-credentials: false
- run: "dev/update-authors.js" # Run the AUTHORS tool
- uses: gr2m/create-or-update-pull-request-action@77596e3166f328b24613f7082ab30bf2d93079d5 # v1 # Create a PR or update the Action's existing PR
- uses: gr2m/create-or-update-pull-request-action@df20b2c073090271599a08c55ae26e0c3522b329 # v1.9.2 # Create a PR or update the Action's existing PR
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
Expand Down
8 changes: 4 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -47,21 +47,21 @@
"@ephys/eslint-config-typescript": "18.0.1",
"@rushstack/eslint-patch": "1.2.0",
"chai": "4.3.7",
"esbuild": "0.17.10",
"eslint": "8.35.0",
"esbuild": "0.17.11",
"eslint": "8.36.0",
"eslint-plugin-jsdoc": "40.0.1",
"eslint-plugin-mocha": "10.1.0",
"fast-glob": "3.2.12",
"lerna": "6.5.1",
"lint-staged": "13.1.2",
"lint-staged": "13.2.0",
"markdownlint-cli": "0.32.2",
"mocha": "10.2.0",
"node-hook": "1.0.0",
"source-map-support": "0.5.21",
"ts-node": "10.9.1",
"typedoc": "0.23.26",
"typedoc-plugin-carbon-ads": "1.1.6",
"typedoc-plugin-mdn-links": "2.0.2",
"typedoc-plugin-mdn-links": "3.0.3",
"typedoc-plugin-missing-exports": "1.0.0",
"typescript": "4.9.5"
},
Expand Down
7 changes: 4 additions & 3 deletions packages/core/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@
"dependencies": {
"@types/debug": "^4.1.7",
"@types/validator": "^13.7.5",
"bnf-parser": "^3.1.1",
"dayjs": "^1.11.5",
"debug": "^4.3.4",
"dottie": "^2.0.2",
Expand All @@ -71,7 +72,7 @@
"@types/ibm_db": "2.0.12",
"@types/lodash": "4.14.191",
"@types/mocha": "10.0.1",
"@types/node": "18.14.6",
"@types/node": "18.15.0",
"@types/pg": "8.6.6",
"@types/semver": "7.3.13",
"@types/sinon": "10.0.13",
Expand Down Expand Up @@ -100,9 +101,9 @@
"p-props": "4.0.0",
"p-settle": "4.1.1",
"p-timeout": "4.1.0",
"pg": "8.9.0",
"pg": "8.10.0",
"pg-hstore": "2.3.4",
"rimraf": "4.1.3",
"rimraf": "4.4.0",
"sinon": "15.0.1",
"sinon-chai": "3.7.0",
"snowflake-sdk": "1.6.19",
Expand Down
31 changes: 18 additions & 13 deletions packages/core/src/associations/belongs-to-many.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,10 @@ import each from 'lodash/each';
import isEqual from 'lodash/isEqual';
import omit from 'lodash/omit';
import upperFirst from 'lodash/upperFirst';
import type { WhereOptions } from '../dialects/abstract/where-sql-builder-types.js';
import { AssociationError } from '../errors';
import { col } from '../expression-builders/col.js';
import { fn } from '../expression-builders/fn.js';
import type {
AttributeNames,
Attributes,
Expand All @@ -21,11 +24,9 @@ import type {
ModelStatic,
Transactionable,
UpdateOptions,
WhereOptions,
} from '../model';
import { Op } from '../operators';
import type { Sequelize } from '../sequelize';
import { col, fn } from '../sequelize';
import { isModelStatic, isSameInitialModel } from '../utils/model-utils.js';
import { removeUndefined } from '../utils/object.js';
import { camelize } from '../utils/string.js';
Expand Down Expand Up @@ -586,7 +587,7 @@ Add your own primary key to the through model, on different attributes than the

const newInstances = newInstancesOrPrimaryKeys === null ? [] : this.toInstanceArray(newInstancesOrPrimaryKeys);

const where = {
const where: WhereOptions = {
[foreignKey]: sourceInstance.get(sourceKey),
...this.through.scope,
};
Expand Down Expand Up @@ -651,16 +652,18 @@ Add your own primary key to the through model, on different attributes than the

const newInstances = this.toInstanceArray(newInstancesOrPrimaryKeys);

const where: WhereOptions = {
[this.foreignKey]: sourceInstance.get(this.sourceKey),
[this.otherKey]: newInstances.map(newInstance => newInstance.get(this.targetKey)),
...this.through.scope,
};

let currentRows: any[] = [];
if (this.through?.unique ?? true) {
currentRows = await this.through.model.findAll({
...options,
raw: true,
where: {
[this.foreignKey]: sourceInstance.get(this.sourceKey),
[this.otherKey]: newInstances.map(newInstance => newInstance.get(this.targetKey)),
...this.through.scope,
},
where,
// force this option to be false, in case the user enabled
rejectOnEmpty: false,
});
Expand Down Expand Up @@ -749,12 +752,14 @@ Add your own primary key to the through model, on different attributes than the
throughAttributes = {};
}

const where: WhereOptions = {
[foreignKey]: sourceInstance.get(sourceKey),
[otherKey]: changedTarget.get(targetKey),
};

promises.push(this.through.model.update(attributes, {
...options,
where: {
[foreignKey]: sourceInstance.get(sourceKey),
[otherKey]: changedTarget.get(targetKey),
},
where,
}));
}

Expand All @@ -775,7 +780,7 @@ Add your own primary key to the through model, on different attributes than the
): Promise<void> {
const targetInstance = this.toInstanceArray(targetInstanceOrPks);

const where = {
const where: WhereOptions = {
[this.foreignKey]: sourceInstance.get(this.sourceKey),
[this.otherKey]: targetInstance.map(newInstance => newInstance.get(this.targetKey)),
...this.through.scope,
Expand Down
8 changes: 5 additions & 3 deletions packages/core/src/associations/belongs-to.ts
Original file line number Diff line number Diff line change
Expand Up @@ -221,11 +221,11 @@ export class BelongsTo<

switch (options.inverse.type) {
case 'hasMany':
HasMany.associate(secret, target, source, passDown, this);
HasMany.associate(secret, target, source, passDown, this, this);
break;

case 'hasOne':
HasOne.associate(secret, target, source, passDown, this);
HasOne.associate(secret, target, source, passDown, this, this);
break;

default:
Expand Down Expand Up @@ -316,7 +316,9 @@ export class BelongsTo<

if (instances.length > 1) {
where[this.targetKey] = {
[Op.in]: instances.map(_instance => _instance.get(this.foreignKey)),
[Op.in]: instances.map(instance => instance.get(this.foreignKey))
// only fetch entities that actually have a foreign key set
.filter(foreignKey => foreignKey != null),
};
} else {
const foreignKeyValue = instances[0].get(this.foreignKey);
Expand Down
28 changes: 17 additions & 11 deletions packages/core/src/associations/has-many.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
import upperFirst from 'lodash/upperFirst';
import type { WhereOptions } from '../dialects/abstract/where-sql-builder-types.js';
import { AssociationError } from '../errors/index.js';
import { col } from '../expression-builders/col.js';
import { fn } from '../expression-builders/fn.js';
import type {
Model,
CreateOptions,
Expand All @@ -12,7 +15,6 @@ import type {
AttributeNames, UpdateValues, Attributes,
} from '../model';
import { Op } from '../operators';
import { col, fn } from '../sequelize';
import { isPlainObject } from '../utils/check.js';
import { isSameInitialModel } from '../utils/model-utils.js';
import { removeUndefined } from '../utils/object.js';
Expand Down Expand Up @@ -87,6 +89,7 @@ export class HasMany<
target: ModelStatic<T>,
options: NormalizedHasManyOptions<SourceKey, TargetKey>,
parent?: Association,
inverse?: BelongsTo<T, S, TargetKey, SourceKey>,
) {
if (
options.sourceKey
Expand All @@ -105,7 +108,7 @@ export class HasMany<

super(secret, source, target, options, parent);

this.inverse = BelongsTo.associate(secret, target, source, removeUndefined({
this.inverse = inverse ?? BelongsTo.associate(secret, target, source, removeUndefined({
as: options.inverse?.as,
scope: options.inverse?.scope,
foreignKey: options.foreignKey,
Expand Down Expand Up @@ -140,12 +143,13 @@ export class HasMany<
T extends Model,
SourceKey extends AttributeNames<S>,
TargetKey extends AttributeNames<T>,
>(
>(
secret: symbol,
source: ModelStatic<S>,
target: ModelStatic<T>,
options: HasManyOptions<SourceKey, TargetKey> = {},
parent?: Association<any>,
inverse?: BelongsTo<T, S, TargetKey, SourceKey>,
): HasMany<S, T, SourceKey, TargetKey> {

return defineAssociation<
Expand All @@ -160,7 +164,7 @@ export class HasMany<
throw new AssociationError('Both options "as" and "inverse.as" must be defined for hasMany self-associations, and their value must be different.');
}

return new HasMany(secret, source, target, normalizedOptions, parent);
return new HasMany(secret, source, target, normalizedOptions, parent, inverse);
});
}

Expand Down Expand Up @@ -464,7 +468,7 @@ export class HasMany<
[this.foreignKey]: null,
} as UpdateValues<T>;

const where = {
const where: WhereOptions = {
[this.foreignKey]: sourceInstance.get(this.sourceKey),
// @ts-expect-error -- TODO: what if the target has no primary key?
[this.target.primaryKeyAttribute]: targetInstances.map(targetInstance => {
Expand Down Expand Up @@ -696,13 +700,12 @@ export interface HasManyCreateAssociationMixinOptions<T extends Model>
* @see Model.hasMany
*/
export type HasManyCreateAssociationMixin<
TModel extends Model,
TForeignKey extends keyof CreationAttributes<TModel> = never,
TScope extends keyof CreationAttributes<TModel> = never,
Target extends Model,
ExcludedAttributes extends keyof CreationAttributes<Target> = never,
> = (
values?: Omit<CreationAttributes<TModel>, TForeignKey | TScope>,
options?: HasManyCreateAssociationMixinOptions<TModel>
) => Promise<TModel>;
values?: Omit<CreationAttributes<Target>, ExcludedAttributes>,
options?: HasManyCreateAssociationMixinOptions<Target>
) => Promise<Target>;

/**
* The options for the removeAssociation mixin of the hasMany association.
Expand Down Expand Up @@ -807,6 +810,9 @@ export interface HasManyHasAssociationsMixinOptions<T extends Model>
*
* @see Model.hasMany
*/
// TODO: this should be renamed to "HasManyHasAllAssociationsMixin",
// we should also add a "HasManyHasAnyAssociationsMixin"
// and "HasManyHasAssociationsMixin" should instead return a Map of id -> boolean or WeakMap of instance -> boolean
export type HasManyHasAssociationsMixin<TModel extends Model, TModelPrimaryKey> = (
targets: Array<TModel | TModelPrimaryKey>,
options?: HasManyHasAssociationsMixinOptions<TModel>
Expand Down
24 changes: 13 additions & 11 deletions packages/core/src/associations/has-one.ts
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ export class HasOne<
target: ModelStatic<T>,
options: NormalizedHasOneOptions<SourceKey, TargetKey>,
parent?: Association,
inverse?: BelongsTo<T, S, TargetKey, SourceKey>,
) {
if (
options?.sourceKey
Expand All @@ -97,14 +98,12 @@ export class HasOne<
}

if ('keyType' in options) {
throw new TypeError('Option "keyType" has been removed from the BelongsTo\'s options. Set "foreignKey.type" instead.');
throw new TypeError(`Option "keyType" has been removed from the BelongsTo's options. Set "foreignKey.type" instead.`);
}

// TODO: throw is source model has a composite primary key.

super(secret, source, target, options, parent);

this.inverse = BelongsTo.associate(secret, target, source, removeUndefined({
this.inverse = inverse ?? BelongsTo.associate(secret, target, source, removeUndefined({
as: options.inverse?.as,
scope: options.inverse?.scope,
foreignKey: options.foreignKey,
Expand Down Expand Up @@ -134,12 +133,13 @@ export class HasOne<
T extends Model,
SourceKey extends AttributeNames<S>,
TargetKey extends AttributeNames<T>,
>(
>(
secret: symbol,
source: ModelStatic<S>,
target: ModelStatic<T>,
options: HasOneOptions<SourceKey, TargetKey> = {},
parent?: Association<any>,
inverse?: BelongsTo<T, S, TargetKey, SourceKey>,
): HasOne<S, T, SourceKey, TargetKey> {
return defineAssociation<
HasOne<S, T, SourceKey, TargetKey>,
Expand All @@ -156,7 +156,7 @@ This is because hasOne associations automatically create the corresponding belon
If having two associations does not make sense (for instance a "spouse" association from user to user), consider using belongsTo instead of hasOne.`);
}

return new HasOne(secret, source, target, normalizedOptions, parent);
return new HasOne(secret, source, target, normalizedOptions, parent, inverse);
});
}

Expand Down Expand Up @@ -457,8 +457,10 @@ export interface HasOneCreateAssociationMixinOptions<T extends Model>
*
* @see Model.hasOne
*/
export type HasOneCreateAssociationMixin<T extends Model> = (
// TODO: omit the foreign key from CreationAttributes once we have a way to determine which key is the foreign key in typings
values?: CreationAttributes<T>,
options?: HasOneCreateAssociationMixinOptions<T>
) => Promise<T>;
export type HasOneCreateAssociationMixin<
Target extends Model,
ExcludedAttributes extends keyof CreationAttributes<Target> = never,
> = (
values?: Omit<CreationAttributes<Target>, ExcludedAttributes>,
options?: HasOneCreateAssociationMixinOptions<Target>
) => Promise<Target>;
2 changes: 1 addition & 1 deletion packages/core/src/decorators/legacy/associations.ts
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ export function BelongsTo<SourceKey extends string, Target extends Model>(
return (
// This type is a hack to make sure the source model declares a property named [SourceKey].
// The error message is going to be horrendous, but at least it's enforced.
source: Model<{ [key in SourceKey]: unknown }>,
source: Model<{ [key in SourceKey]: any }>,
associationName: string,
) => {
const options = isString(optionsOrForeignKey) ? { foreignKey: optionsOrForeignKey } : optionsOrForeignKey;
Expand Down
4 changes: 2 additions & 2 deletions packages/core/src/decorators/shared/model.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { BaseError } from '../../errors/base-error.js';
import { mergeModelOptions } from '../../model-definition.js';
import { initModel } from '../../model-typescript.js';
import type { AttributeOptions, ModelAttributes, ModelOptions, ModelStatic } from '../../model.js';
Expand Down Expand Up @@ -35,8 +36,7 @@ export function registerModelOptions(
try {
mergeModelOptions(existingModelOptions, options, false);
} catch (error) {
// TODO [TS 4.8]: remove this "as Error" cast once support for TS < 4.8 is dropped, as the typing of "cause" has been fixed in TS 4.8
throw new Error(`Multiple decorators are trying to register conflicting options on model ${model.name}`, { cause: error as Error });
throw new BaseError(`Multiple decorators are trying to register conflicting options on model ${model.name}`, { cause: error });
}
}

Expand Down
Loading

0 comments on commit 59543d9

Please sign in to comment.