I use sequelize ORM. I have created a register route and controller to create new user. I created a new user with AVA test, but the auto-increment function isn't working properly. Despite being the fourth user created, this new user created with AVA test has an ID of 1 (The other three users were created using Sequelize seeders). I've checked the database schema and confirmed that the 'id' field is set to auto-increment. Any ideas on how to resolve this issue?
Terminal output :
npm test .../tests/register/registerTest.js
> test
> ava --require dotenv/...tests/register/registerTest.js
Executing (default): INSERT INTO "Users" ("uuid","username","email","password","createdAt","updatedAt") VALUES ($1,$2,$3,$4,$5,$6) RETURNING "uuid","username","email","password","createdAt","updatedAt";
✔ RegisterNewUser function should create a new user and return a token (127ms)
ℹ {
token: 'eyJhbGciOiJIUzI1N...Z_iVY8hjgsf9Ak',
user: {
createdAt: '2023-03-07T07:48:53.393Z',
email: 'testuser@example.com',
password: '$2b$10$kNeC1h7d0wX7WPQC3H.94OlpXveXVeaP7WaWEIGQN6VLypSVKoAE.',
updatedAt: '2023-03-07T07:48:53.393Z',
username: 'testuser',
uuid: 'e33c6803-1c18-4d25-906f-2d6de8726d27',
},
}
─
1 test passed
PSQL Terminal output :
database_test=# SELECT * FROM "Users";
id | uuid | username | email | password | createdAt | updatedAt
----+--------------------------------------+----------+----------------------+--------------------------------------------------------------+----------------------------+----------------------------
1 | 15bf1cb7-8346-4140-8b36-ced76facb4d7 | johndoe | johndoe@example.com | $2b$10$1r.N1fS6ea82w9WgMZmdsevl/awhaWjSfWgwHzMXSWDNPdZlfS.bS | 2023-03-07 07:45:28.403+00 | 2023-03-07 07:45:28.403+00
2 | af947f46-2991-43fd-aaec-dec95c40a729 | janedoe | janedoe@example.com | $2b$10$8H7ktluUZrr21SzE7Eo2MuegtmaCLMWjxHnQvg8LrlAD1uLI1BICm | 2023-03-07 07:45:28.412+00 | 2023-03-07 07:45:28.412+00
3 | d2658a11-b088-4e86-a351-ee628c3a7cad | billdoe | billdoe@example.com | $2b$10$CBWz3iUSVot3nLqgSP3z4.ma2tiCp8SaPTKPRC3Z8fjHNMDJs.oIO | 2023-03-07 07:45:28.405+00 | 2023-03-07 07:45:28.405+00
1 | e33c6803-1c18-4d25-906f-2d6de8726d27 | testuser | testuser@example.com | $2b$10$kNeC1h7d0wX7WPQC3H.94OlpXveXVeaP7WaWEIGQN6VLypSVKoAE. | 2023-03-07 07:48:53.393+00 | 2023-03-07 07:48:53.393+00
\d "Users"
database_test=# \d "Users"
Table "public.Users"
Column | Type | Collation | Nullable | Default
-----------+--------------------------+-----------+----------+-------------------------------------
id | integer | | not null | nextval('"Users_id_seq"'::regclass)
uuid | uuid | | not null |
username | character varying(255) | | not null |
email | character varying(255) | | not null |
password | character varying(255) | | not null |
createdAt | timestamp with time zone | | not null |
updatedAt | timestamp with time zone | | not null |
models/user.js
'use strict';
// Import the bcrypt library for password hashing
const {
Model
} = require('sequelize');
// Import the bcrypt library for password hashing
const bcrypt = require('bcrypt');
// Define a sequelize model for a User
module.exports = (sequelize, DataTypes) => {
class User extends Model {
/**
* Helper method for defining associations.
* This method is not a part of Sequelize lifecycle.
* The `models/index` file will call this method automatically.
*/
static associate(models) {
...
})
}
}
User.init({
id: {
type: DataTypes.INTEGER,
primaryKey: true,
autoIncrement: true,
allowNull: false
},
uuid: {
type: DataTypes.UUID,
defaultValue: DataTypes.UUIDV4,
allowNull: false,
unique: true,
primaryKey: true,
},
...
}, {
sequelize,
modelName: 'User',
// Add hooks to run code before or after certain events
hooks: {
// Hash the user's password before creating a new user
beforeCreate: (User) => {
const salt = bcrypt.genSaltSync(10);
User.password = bcrypt.hashSync(User.password, salt);
}
},
});
return User;
};
migrations/20230223064615-create-user.js
'use strict';
/** @type {import('sequelize-cli').Migration} */
module.exports = {
async up(queryInterface, Sequelize) {
await queryInterface.createTable('Users', {
id: {
allowNull: false,
autoIncrement: true,
type: Sequelize.INTEGER,
onDelete: 'CASCADE'
},
...
createdAt: {
allowNull: false,
type: Sequelize.DATE
},
updatedAt: {
allowNull: false,
type: Sequelize.DATE
}
});
},
async down(queryInterface, Sequelize) {
await queryInterface.dropTable('Users');
}
};
seeder :
module.exports = {
// The up function is responsible for defining the changes that should be applied to the database schema.
up: async (queryInterface, Sequelize) => {
// Define an array of user objects with plaintext passwords.
const users = [{
id: 1,
uuid: uuidv4(),
username: 'johndoe',
email: 'johndoe@example.com',
password: 'password123'
},
{
id: 2,
uuid: uuidv4(),
username: 'janedoe',
email: 'janedoe@example.com',
password: 'password456'
},
....
// The down function is responsible for undoing the changes made to the database schema by the up function.
down: async (queryInterface, Sequelize) => {
// Delete all users from the Users table using the bulkDelete function provided by Sequelize.
return queryInterface.bulkDelete('Users', null, {});
}
};