Sequelize 6 associations and transactions on SQLite: working versions (tested 2026-10-15)
Define Sequelize models with hasMany and belongsTo, run CRUD inside a managed transaction, and query with includes on a file-backed SQLite database.
passed2 passed · 0 failed2026-10-15 16:04 UTC- Status
- passed
- Last passed
- 2026-10-15 16:04 UTC
- Tests
- 2 / 2
- Language
- TypeScript
- Runtime
- node v22.23.3
pinned versions4
sequelize@6.37.8sqlite3@6.0.1@types/node@26.6.5tsx@4.23.15
run it
npm install --no-audit --no-fund --ignore-scripts=false npm test
test environment
node v22.23.3 linux 6.17.0-1022-azure x64 runner: github-actions 38764699834
The code
Exactly the files that passed. Your agent can pull them with get_recipe("sequelize-sqlite-associations") (install), or see them on GitHub.
package.json
{
"name": "sequelize-sqlite-associations",
"private": true,
"type": "module",
"scripts": {
"test": "node --import tsx --test test/*.test.ts"
},
"dependencies": {
"sequelize": "6.37.8",
"sqlite3": "6.0.1"
},
"devDependencies": {
"@types/node": "26.6.5",
"tsx": "4.23.15"
}
}
src/db.ts
import { Sequelize, DataTypes, Model, type InferAttributes, type InferCreationAttributes, type CreationOptional } from "sequelize";
export class User extends Model<InferAttributes<User>, InferCreationAttributes<User>> {
declare id: CreationOptional<number>;
declare email: string;
}
export class Post extends Model<InferAttributes<Post>, InferCreationAttributes<Post>> {
declare id: CreationOptional<number>;
declare title: string;
declare userId: number;
}
export async function createDb(storage = ":memory:") {
const sequelize = new Sequelize({ dialect: "sqlite", storage, logging: false });
User.init(
{ id: { type: DataTypes.INTEGER, autoIncrement: true, primaryKey: true }, email: { type: DataTypes.STRING, allowNull: false, unique: true } },
{ sequelize, tableName: "users" },
);
Post.init(
{ id: { type: DataTypes.INTEGER, autoIncrement: true, primaryKey: true }, title: { type: DataTypes.STRING, allowNull: false }, userId: { type: DataTypes.INTEGER, allowNull: false } },
{ sequelize, tableName: "posts" },
);
User.hasMany(Post, { foreignKey: "userId", as: "posts" });
Post.belongsTo(User, { foreignKey: "userId", as: "author" });
await sequelize.sync({ force: true });
return sequelize;
}
export async function createAuthorWithPosts(email: string, titles: string[]) {
return User.sequelize!.transaction(async (t) => {
const user = await User.create({ email }, { transaction: t });
await Post.bulkCreate(titles.map((title) => ({ title, userId: user.id })), { transaction: t });
return user;
});
}
export async function postsForEmail(email: string) {
const user = await User.findOne({
where: { email },
include: [{ model: Post, as: "posts" }],
});
return user;
}
test/db.test.ts
import { test } from "node:test";
import assert from "node:assert/strict";
import { createAuthorWithPosts, createDb, postsForEmail, Post } from "../src/db.ts";
test("transaction creates user and posts with include", async () => {
const db = await createDb();
await createAuthorWithPosts("[email protected]", ["First", "Second"]);
const user = await postsForEmail("[email protected]");
assert.ok(user);
assert.equal(user!.email, "[email protected]");
const posts = (user as any).posts as Post[];
assert.deepEqual(posts.map((p) => p.title).sort(), ["First", "Second"]);
await db.close();
});
test("rollback leaves no rows when nested create fails", async () => {
const db = await createDb();
await createAuthorWithPosts("[email protected]", ["Ok"]);
await assert.rejects(async () => {
await Post.sequelize!.transaction(async (t) => {
await Post.create({ title: "x", userId: 999 }, { transaction: t });
});
});
assert.equal(await Post.count(), 1);
await db.close();
});
Connect to ProvenPin
Add the free MCP server so your agent can pull this recipe and others like it. Same setup as the docs.
terminal
claude mcp add --transport http provenpin https://mcp.provenpin.com/mcp
~/.cursor/mcp.json
{ "mcpServers": { "provenpin": { "url": "https://mcp.provenpin.com/mcp" } } }.vscode/mcp.json
{ "servers": { "provenpin": { "type": "http", "url": "https://mcp.provenpin.com/mcp" } } }~/.codeium/windsurf/mcp_config.json
{ "mcpServers": { "provenpin": { "serverUrl": "https://mcp.provenpin.com/mcp" } } }MCP settings
{ "mcpServers": { "provenpin": { "type": "streamableHttp", "url": "https://mcp.provenpin.com/mcp" } } }Any other MCP client: Streamable HTTP at https://mcp.provenpin.com/mcp. No API key, no signup.