Skip to content

Commit

Permalink
Merge branch 'main' into WikiRik/node-16
Browse files Browse the repository at this point in the history
  • Loading branch information
WikiRik committed Jun 18, 2023
2 parents b3eb6de + 1301c97 commit a93d830
Show file tree
Hide file tree
Showing 87 changed files with 2,917 additions and 1,390 deletions.
26 changes: 13 additions & 13 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -76,23 +76,23 @@ jobs:
- name: ESM / CJS export equivalence
run: yarn test-unit-esm
- name: Unit tests (validator.js)
run: yarn workspace @sequelize/validator.js test-unit
run: yarn lerna run test-unit --scope=@sequelize/validator.js
- name: Unit tests (mariadb)
run: yarn workspace @sequelize/core test-unit-mariadb
run: yarn lerna run test-unit-mariadb --scope=@sequelize/core
- name: Unit tests (mysql)
run: yarn workspace @sequelize/core test-unit-mysql
run: yarn lerna run test-unit-mysql --scope=@sequelize/core
- name: Unit tests (postgres)
run: yarn workspace @sequelize/core test-unit-postgres
run: yarn lerna run test-unit-postgres --scope=@sequelize/core
- name: Unit tests (sqlite)
run: yarn workspace @sequelize/core test-unit-sqlite
run: yarn lerna run test-unit-sqlite --scope=@sequelize/core
- name: Unit tests (mssql)
run: yarn workspace @sequelize/core test-unit-mssql
run: yarn lerna run test-unit-mssql --scope=@sequelize/core
- name: Unit tests (db2)
run: yarn workspace @sequelize/core test-unit-db2
run: yarn lerna run test-unit-db2 --scope=@sequelize/core
- name: Unit tests (ibmi)
run: yarn workspace @sequelize/core test-unit-ibmi
run: yarn lerna run test-unit-ibmi --scope=@sequelize/core
- name: Unit tests (snowflake)
run: yarn workspace @sequelize/core test-unit-snowflake
run: yarn lerna run test-unit-snowflake --scope=@sequelize/core
docs:
name: Generate TypeDoc
runs-on: ubuntu-latest
Expand Down Expand Up @@ -131,7 +131,7 @@ jobs:
- name: Install TypeScript
run: yarn add typescript@~${{ matrix.ts-version }}
- name: Typing Tests
run: yarn workspace @sequelize/core test-typings
run: yarn lerna run test-typings --scope=@sequelize/core
test-sqlite:
strategy:
fail-fast: false
Expand All @@ -154,7 +154,7 @@ jobs:
- name: Extract artifact
run: tar -xf install-build-node-${{ matrix.node-version }}.tar
- name: Integration Tests
run: yarn workspace @sequelize/core test-integration
run: yarn lerna run test-integration --scope=@sequelize/core
test-postgres:
strategy:
fail-fast: false
Expand Down Expand Up @@ -185,7 +185,7 @@ jobs:
if: matrix.native
- run: yarn start-postgres-${{ matrix.postgres-version }}
- name: Integration Tests
run: yarn workspace @sequelize/core test-integration
run: yarn lerna run test-integration --scope=@sequelize/core
test-oldest-latest:
strategy:
fail-fast: false
Expand All @@ -211,7 +211,7 @@ jobs:
run: tar -xf install-build-node-${{ matrix.node-version }}.tar
- run: yarn start-${{ matrix.dialect }}-${{ matrix.database-version }}
- name: Integration Tests
run: yarn workspace @sequelize/core test-integration
run: yarn lerna run test-integration --scope=@sequelize/core
release:
name: Release
runs-on: ubuntu-latest
Expand Down
30 changes: 22 additions & 8 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -153,27 +153,41 @@ You will have to manually install and configure each of database engines you wan

### 4. Running tests

Sequelize is a monorepo and uses `lerna` to run scripts in each of the packages. The syntax for the commands is: `yarn lerna run` followed by the script name. For example:

```
yarn lerna run test-unit
```

By default, the `yarn lerna run` command will run the script in all packages which have a matching script. By appending `--scope=package_name` to the command (where `package_name` is the name of the package you want to run the script on) you can select a specific package to run the script on. For example:

```
yarn lerna run test-unit --scope=@sequelize/core
```

For more information about using `lerna` commands, use the [Lerna Documentation](https://lerna.js.org/docs/api-reference/commands).

Before starting any work, try to run the tests locally in order to be sure your setup is fine. Start by running the SQLite tests:

```
yarn test-sqlite
yarn lerna run test-sqlite
```

Then, if you want to run tests for another dialect, assuming you've set it up as written on section 3, run the corresponding command:

- `yarn test-mysql`
- `yarn test-mariadb`
- `yarn test-postgres`
- `yarn test-mssql`
- `yarn test-db2`
- `yarn lerna run test-mysql`
- `yarn lerna run test-mariadb`
- `yarn lerna run test-postgres`
- `yarn lerna run test-mssql`
- `yarn lerna run test-db2`

There are also the `test-unit-*` and `test-integration-*` sets of scripts (for example, `test-integration-postgres`).

#### 4.1. Running only some tests

While you're developing, you may want to execute only a single test (or a few), instead of executing everything (which takes some time). You can easily achieve this by modifying the `.mocharc.jsonc` file (but don't commit those changes!) to use `spec` (and maybe `grep`) from Mocha to specify the desired tests. Then, simply call `DIALECT=some-dialect yarn mocha` from your terminal (example: `DIALECT=postgres yarn mocha`).
While you're developing, you may want to execute only a single test (or a few), instead of executing everything (which takes some time). You can easily achieve this by modifying the `.mocharc.jsonc` file inside the package's root directory (but don't commit those changes!) to use `spec` (and maybe `grep`) from Mocha to specify the desired tests. Then, from your terminal, navigate to the package's root directory and simply call `DIALECT=some-dialect yarn mocha` (example: `DIALECT=postgres yarn mocha`). The package root directory is where the package.json file for the package is located. For example with the @sequelize/core package, the package root directory is [packages/core](https://github.com/sequelize/sequelize/tree/main/packages/core).

Hint: if you're creating a new test, you can execute only that test locally against all dialects by adapting the `spec` and `grep` options on `.mocharc.jsonc` and running the following from your terminal (assuming you already set up the database instances via the corresponding `yarn setup-*` calls, as explained on [Section 3a](https://github.com/sequelize/sequelize/blob/main/CONTRIBUTING.md#3a-with-docker-recommended)):
Hint: if you're creating a new test, you can execute only that test locally against all dialects by adapting the `spec` and `grep` options on `.mocharc.jsonc` and running the following from your terminal (assuming you already set up the database instances via the corresponding `yarn setup-*` calls, as explained on [Section 3a](https://github.com/sequelize/sequelize/blob/main/CONTRIBUTING.md#3a-with-docker-recommended) and you are in the package's root directory):

```
DIALECT=mariadb yarn mocha && DIALECT=mysql yarn mocha && DIALECT=postgres yarn mocha && DIALECT=sqlite yarn mocha && DIALECT=mssql yarn mocha && DIALECT=db2 yarn mocha
Expand Down
3 changes: 1 addition & 2 deletions lerna.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
{
"$schema": "node_modules/lerna/schemas/lerna-schema.json",
"useWorkspaces": true,
"version": "7.0.0-alpha.20"
"version": "0.0.0-development"
}
3 changes: 3 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -48,11 +48,14 @@
"@ephys/eslint-config-typescript": "19.0.2",
"@rushstack/eslint-patch": "1.3.2",
"chai": "4.3.7",
"concurrently": "8.2.0",
"cross-env": "7.0.3",
"esbuild": "0.17.19",
"eslint": "8.43.0",
"eslint-plugin-jsdoc": "41.1.2",
"eslint-plugin-mocha": "10.1.0",
"fast-glob": "3.2.12",
"husky": "8.0.3",
"lerna": "7.0.2",
"lint-staged": "13.2.2",
"markdownlint-cli": "0.35.0",
Expand Down
7 changes: 2 additions & 5 deletions packages/core/package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "@sequelize/core",
"description": "Sequelize is a promise-based Node.js ORM tool for Postgres, MySQL, MariaDB, SQLite, Microsoft SQL Server, Amazon Redshift, Snowflake’s Data Cloud, Db2, and IBM i. It features solid transaction support, relations, eager and lazy loading, read replication and more.",
"version": "7.0.0-alpha.20",
"version": "0.0.0-development",
"funding": [
{
"type": "opencollective",
Expand Down Expand Up @@ -74,7 +74,7 @@
"@types/lodash": "4.14.195",
"@types/mocha": "10.0.1",
"@types/node": "18.16.18",
"@types/pg": "8.6.6",
"@types/pg": "8.10.2",
"@types/semver": "7.5.0",
"@types/sinon": "10.0.15",
"@types/sinon-chai": "3.2.9",
Expand All @@ -84,12 +84,9 @@
"chai": "4.3.7",
"chai-as-promised": "7.1.1",
"chai-datetime": "1.8.0",
"concurrently": "8.2.0",
"cross-env": "7.0.3",
"delay": "5.0.0",
"expect-type": "0.13.0",
"fs-jetpack": "5.1.0",
"husky": "8.0.3",
"ibm_db": "3.2.1",
"lcov-result-merger": "4.1.0",
"mariadb": "2.5.6",
Expand Down
2 changes: 1 addition & 1 deletion packages/core/src/associations/base.ts
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,7 @@ export abstract class Association<

this.isAliased = Boolean(options?.as);

this.options = cloneDeep(options);
this.options = cloneDeep(options) ?? {};

source.associations[this.as] = this;
}
Expand Down
8 changes: 4 additions & 4 deletions packages/core/src/associations/belongs-to.ts
Original file line number Diff line number Diff line change
Expand Up @@ -281,13 +281,13 @@ export class BelongsTo<
* @param instances source instances
* @param options find options
*/
async get(instances: S, options: BelongsToGetAssociationMixinOptions<T>): Promise<T | null>;
async get(instances: S[], options: BelongsToGetAssociationMixinOptions<T>): Promise<Map<any, T | null>>;
async get(instances: S, options?: BelongsToGetAssociationMixinOptions<T>): Promise<T | null>;
async get(instances: S[], options?: BelongsToGetAssociationMixinOptions<T>): Promise<Map<any, T | null>>;
async get(
instances: S | S[],
options: BelongsToGetAssociationMixinOptions<T>,
options?: BelongsToGetAssociationMixinOptions<T>,
): Promise<Map<any, T | null> | T | null> {
options = cloneDeep(options);
options = cloneDeep(options) ?? {};

let Target = this.target;
if (options.scope != null) {
Expand Down
40 changes: 36 additions & 4 deletions packages/core/src/decorators/legacy/associations.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { inspect } from 'node:util';
import type { MaybeForwardedModelStatic } from '../../associations/helpers.js';
import { AssociationSecret, getForwardedModel } from '../../associations/helpers.js';
import type {
Expand All @@ -17,6 +18,7 @@ import type { AttributeNames, Model, ModelStatic } from '../../model.js';
import type { Sequelize } from '../../sequelize.js';
import { isString } from '../../utils/check.js';
import { isModelStatic } from '../../utils/model-utils.js';
import { EMPTY_ARRAY } from '../../utils/object.js';
import { throwMustBeInstanceProperty, throwMustBeModel } from './decorator-utils.js';

export type AssociationType = 'BelongsTo' | 'HasOne' | 'HasMany' | 'BelongsToMany';
Expand Down Expand Up @@ -107,15 +109,15 @@ export function BelongsToMany(
};
}

export function initDecoratedAssociations(model: ModelStatic, sequelize: Sequelize): void {
const associations = registeredAssociations.get(model);
export function initDecoratedAssociations(source: ModelStatic, sequelize: Sequelize): void {
const associations = getDeclaredAssociations(source);

if (!associations) {
if (!associations.length) {
return;
}

for (const association of associations) {
const { type, source, target: targetGetter, associationName } = association;
const { type, target: targetGetter, associationName } = association;
const options: AssociationOptions = { ...association.options, as: associationName };

const target = getForwardedModel(targetGetter, sequelize);
Expand All @@ -139,3 +141,33 @@ export function initDecoratedAssociations(model: ModelStatic, sequelize: Sequeli
}
}

function getDeclaredAssociations(model: ModelStatic): readonly RegisteredAssociation[] {
const associations: readonly RegisteredAssociation[] = registeredAssociations.get(model) ?? EMPTY_ARRAY;

const parentModel = Object.getPrototypeOf(model);
if (isModelStatic(parentModel)) {
const parentAssociations = getDeclaredAssociations(parentModel);

for (const parentAssociation of parentAssociations) {
if (parentAssociation.type !== 'BelongsTo') {
throw new Error(
`Models that use @HasOne, @HasMany, or @BelongsToMany associations cannot be inherited from, as they would add conflicting foreign keys on the target model.
Only @BelongsTo associations can be inherited, as it will add the foreign key on the source model.
Remove the ${parentAssociation.type} association ${inspect(parentAssociation.associationName)} from model ${inspect(parentModel.name)} to fix this error.`,
);
}

if ('inverse' in parentAssociation.options) {
throw new Error(
`Models that use @BelongsTo associations with the "inverse" option cannot be inherited from, as they would add conflicting associations on the target model.
Only @BelongsTo associations without the "inverse" option can be inherited, as they do not declare an association on the target model.
Remove the "inverse" option from association ${inspect(parentAssociation.associationName)} on model ${inspect(parentModel.name)} to fix this error.`,
);
}
}

return [...parentAssociations, ...associations];
}

return associations;
}
28 changes: 27 additions & 1 deletion packages/core/src/decorators/legacy/table.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import type { Model, ModelOptions, ModelStatic } from '../../model.js';
import type { RegisteredModelOptions } from '../shared/model.js';
import { registerModelOptions } from '../shared/model.js';

/**
Expand Down Expand Up @@ -27,9 +28,34 @@ export function Table(arg: any): undefined | ClassDecorator {

const options: ModelOptions = { ...arg };

// @ts-expect-error -- making sure the option is not provided.
if (options.abstract) {
throw new Error('`abstract` is not a valid option for @Table. Did you mean to use @Table.Abstract?');
}

return (target: any) => annotate(target, options);
}

function AbstractTable<M extends Model = Model>(options: Omit<ModelOptions<M>, 'tableName' | 'name'>): ClassDecorator;
function AbstractTable(target: ModelStatic): void;
function AbstractTable(arg: any): undefined | ClassDecorator {
if (typeof arg === 'function') {
annotate(arg, { abstract: true });

return undefined;
}

const options: ModelOptions = { ...arg, abstract: true };

if (options.tableName || options.name) {
throw new Error('Options "tableName" and "name" cannot be set on abstract models.');
}

return (target: any) => annotate(target, options);
}

function annotate(target: ModelStatic, options: ModelOptions = {}): void {
Table.Abstract = AbstractTable;

function annotate(target: ModelStatic, options: RegisteredModelOptions = {}): void {
registerModelOptions(target, options);
}
Loading

0 comments on commit a93d830

Please sign in to comment.