Skip to content
Open
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion dev/create-sequelize-instance.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@
return new Sequelize6(wrapOptions(options));
}

export function createSequelize7Instance(options?: Sequelize7Options): Sequelize7 {
export function createSequelize7Instance(options?: Sequelize7Options<AbstractDialect>): Sequelize7 {

Check failure on line 10 in dev/create-sequelize-instance.ts

View workflow job for this annotation

GitHub Actions / sqlite (Node 20)

Cannot find name 'AbstractDialect'.

Check failure on line 10 in dev/create-sequelize-instance.ts

View workflow job for this annotation

GitHub Actions / sqlite (Node 20)

Type 'Options' is not generic.

Check failure on line 10 in dev/create-sequelize-instance.ts

View workflow job for this annotation

GitHub Actions / sqlite (Node 18)

Cannot find name 'AbstractDialect'.

Check failure on line 10 in dev/create-sequelize-instance.ts

View workflow job for this annotation

GitHub Actions / sqlite (Node 18)

Type 'Options' is not generic.

Check failure on line 10 in dev/create-sequelize-instance.ts

View workflow job for this annotation

GitHub Actions / sqlite (Node 10)

Cannot find name 'AbstractDialect'.

Check failure on line 10 in dev/create-sequelize-instance.ts

View workflow job for this annotation

GitHub Actions / sqlite (Node 10)

Type 'Options' is not generic.
// not compatible with node 10
const { Sequelize: Sequelize7Constructor } = require('@sequelize/core');
// @ts-expect-error -- wrapOptions expect sequelize 6.

Check failure on line 13 in dev/create-sequelize-instance.ts

View workflow job for this annotation

GitHub Actions / sqlite (Node 20)

Unused '@ts-expect-error' directive.

Check failure on line 13 in dev/create-sequelize-instance.ts

View workflow job for this annotation

GitHub Actions / sqlite (Node 18)

Unused '@ts-expect-error' directive.

Check failure on line 13 in dev/create-sequelize-instance.ts

View workflow job for this annotation

GitHub Actions / sqlite (Node 10)

Unused '@ts-expect-error' directive.
return new Sequelize7Constructor(wrapOptions(options));
}
256 changes: 232 additions & 24 deletions src/sscce-sequelize-7.ts
Original file line number Diff line number Diff line change
@@ -1,43 +1,251 @@
import { CreationOptional, DataTypes, InferAttributes, InferCreationAttributes, Model } from '@sequelize/core';
import { Attribute, NotNull } from '@sequelize/core/decorators-legacy';
import { createSequelize7Instance } from '../dev/create-sequelize-instance';
import { expect } from 'chai';
import sinon from 'sinon';
import {
CreationOptional,
DataTypes,
InferAttributes,
InferCreationAttributes,
Model,
} from "@sequelize/core";
import { createSequelize7Instance } from "../dev/create-sequelize-instance";
import { expect } from "chai";

// if your issue is dialect specific, remove the dialects you don't need to test on.
export const testingOnDialects = new Set(['mssql', 'sqlite', 'mysql', 'mariadb', 'postgres', 'postgres-native']);
export const testingOnDialects = new Set(["postgres"]);

// You can delete this file if you don't want your SSCCE to be tested against Sequelize 7
class Location extends Model<
InferAttributes<Location>,
InferCreationAttributes<Location>
> {
declare id: CreationOptional<number>;
declare name: string;

declare customers?: Customer[];
declare systems?: System[];
}

class Customer extends Model<
InferAttributes<Customer>,
InferCreationAttributes<Customer>
> {
declare id: CreationOptional<number>;
declare name: string;

declare locations?: Location[];
}

class System extends Model<
InferAttributes<System>,
InferCreationAttributes<System>
> {
declare id: CreationOptional<number>;
declare name: string;
declare locationId: number;

declare location?: Location;
declare fuelDeliveries?: FuelDelivery[];
}

class FuelDelivery extends Model<
InferAttributes<FuelDelivery>,
InferCreationAttributes<FuelDelivery>
> {
declare id: CreationOptional<number>;
declare product: string;
declare systemId: number;

declare system?: System;
}

class LocationCustomer extends Model<
InferAttributes<LocationCustomer>,
InferCreationAttributes<LocationCustomer>
> {
declare locationId: number;
declare customerId: number;
}

// Your SSCCE goes inside this function.
export async function run() {
// This function should be used instead of `new Sequelize()`.
// It applies the config for your SSCCE to work on CI.
const sequelize = createSequelize7Instance({
logQueryParameters: true,
benchmark: true,
minifyAliases: true,
dialect: "postgres",
define: {
// For less clutter in the SSCCE
// Keep model definitions lean so the regression focus stays on include resolution.
timestamps: false,
},
});

class Foo extends Model<InferAttributes<Foo>, InferCreationAttributes<Foo>> {
declare id: CreationOptional<number>;
Location.init(
{
id: {
type: DataTypes.INTEGER,
autoIncrement: true,
primaryKey: true,
},
name: {
type: DataTypes.STRING,
allowNull: false,
},
},
{
sequelize,
tableName: "locations",
}
);

@Attribute(DataTypes.TEXT)
@NotNull
declare name: string;
}
Customer.init(
{
id: {
type: DataTypes.INTEGER,
autoIncrement: true,
primaryKey: true,
},
name: {
type: DataTypes.STRING,
allowNull: false,
},
},
{
sequelize,
tableName: "customers",
}
);

sequelize.addModels([Foo]);
System.init(
{
id: {
type: DataTypes.INTEGER,
autoIncrement: true,
primaryKey: true,
},
name: {
type: DataTypes.STRING,
allowNull: false,
},
locationId: {
type: DataTypes.INTEGER,
allowNull: false,
},
},
{
sequelize,
tableName: "systems",
}
);

FuelDelivery.init(
{
id: {
type: DataTypes.INTEGER,
autoIncrement: true,
primaryKey: true,
},
product: {
type: DataTypes.STRING,
allowNull: false,
},
systemId: {
type: DataTypes.INTEGER,
allowNull: false,
},
},
{
sequelize,
tableName: "fuel_deliveries",
}
);

LocationCustomer.init(
{
locationId: {
type: DataTypes.INTEGER,
allowNull: false,
primaryKey: true,
},
customerId: {
type: DataTypes.INTEGER,
allowNull: false,
primaryKey: true,
},
},
{
sequelize,
tableName: "location_customers",
}
);

FuelDelivery.belongsTo(System, { as: "system", foreignKey: "systemId" });
System.hasMany(FuelDelivery, {
as: "fuelDeliveries",
foreignKey: "systemId",
});

// You can use sinon and chai assertions directly in your SSCCE.
const spy = sinon.spy();
sequelize.afterBulkSync(() => spy());
await sequelize.sync({ force: true });
expect(spy).to.have.been.called;
System.belongsTo(Location, { as: "location", foreignKey: "locationId" });
Location.hasMany(System, { as: "systems", foreignKey: "locationId" });

console.log(await Foo.create({ name: 'TS foo' }));
expect(await Foo.count()).to.equal(1);
Location.belongsToMany(Customer, {
as: "customers",
through: LocationCustomer,
foreignKey: "locationId",
otherKey: "customerId",
});
Customer.belongsToMany(Location, {
as: "locations",
through: LocationCustomer,
foreignKey: "customerId",
otherKey: "locationId",
});

try {
await sequelize.sync({ force: true });

const customer = await Customer.create({ name: "Propane Co-op" });
const location = await Location.create({ name: "Rural Depot" });
await LocationCustomer.create({
customerId: customer.id,
locationId: location.id,
});

const system = await System.create({
name: "Delivery System Alpha",
locationId: location.id,
});
const delivery = await FuelDelivery.create({
product: "Propane",
systemId: system.id,
});

const result = await FuelDelivery.findByPk(delivery.id, {
logging: console.log,
include: [
{
association: "system",
required: true,
include: [
{
association: "location",
required: true,
include: [
{
association: "customers",
required: true,
},
],
},
],
},
],
});

expect(result).to.not.be.null;
expect(result!.system).to.not.be.undefined;
expect(result!.system!.location).to.not.be.undefined;
const customers = result!.system!.location!.customers;
expect(customers).to.not.be.undefined;
expect(customers).to.have.length(1);
expect(customers![0].id).to.equal(customer.id);
} finally {
await sequelize.close();
}
}
Loading