SlintORM
Docsnpm

CRUD

Every model returned by defineModel has a full set of create, read, update, and delete methods. All mutating methods auto-manage createdAt and updatedAt.

insert

// insert(data) — returns EntityWithUpdate<T>
const user = await User.insert({
  email: 'joe@example.com',
  name: 'Joe',
});
console.log(user.id);         // auto-assigned
console.log(user.createdAt);  // set automatically
console.log(user.updatedAt);  // set automatically

// Returned entity has .update(), .delete(), .refresh(), .toJSON()
const updated = await user.update({ name: 'Joseph' });

insertMany

// insertMany(data[]) — batch insert
// On SQLite, wrapped in a single transaction for speed
const users = await User.insertMany([
  { email: 'alice@example.com', name: 'Alice' },
  { email: 'bob@example.com', name: 'Bob' },
  { email: 'carol@example.com', name: 'Carol' },
]);
console.log(users.length); // 3

get

// get(filter) — returns EntityWithUpdate<T> | null
const user = await User.get({ email: 'joe@example.com' });
if (!user) {
  throw new Error('User not found');
}
console.log(user.name);

// Multiple filters (AND)
const admin = await User.get({ role: 'admin', active: true });

getAll

// getAll(filter?) — returns EntityWithUpdate<T>[]
const allUsers = await User.getAll();
const admins = await User.getAll({ role: 'admin' });

// All returned entities have .update(), .delete(), etc.
for (const user of admins) {
  await user.update({ notifiedAt: new Date().toISOString() });
}

update / updateMany

// update(filter, data) — auto-sets updatedAt
const count = await User.update(
  { role: 'user' },
  { role: 'member' }
);
console.log(count); // number of rows updated

// update returns number of affected rows for updateMany
const affected = await User.updateMany(
  { status: 'pending' },
  { status: 'active' }
);

delete / deleteMany

// delete(filter) — non-empty filter required
await User.delete({ id: 42 });

// deleteMany(filter) — returns number deleted
const count = await User.deleteMany({ role: 'guest' });
console.log(`Deleted ${count} guests`);

upsert

Inserts a row or updates it if the conflict column already exists. The implementation varies by driver: ON CONFLICT on Postgres,ON DUPLICATE KEY on MySQL, manual lookup on SQLite and MongoDB.

// upsert(data, conflictKey)
// Postgres: ON CONFLICT (email) DO UPDATE
// MySQL: ON DUPLICATE KEY UPDATE
// SQLite / MongoDB: manual get-then-insert-or-update

const user = await User.upsert(
  { email: 'joe@example.com', name: 'Joe', role: 'admin' },
  'email'   // conflict column
);

findOrCreate

// findOrCreate(filter, defaults?) — returns { record, created }
const { record, created } = await User.findOrCreate(
  { email: 'joe@example.com' },
  { name: 'Joe', role: 'user' }  // defaults if creating
);

if (created) {
  console.log('New user:', record.id);
} else {
  console.log('Existing user:', record.id);
}

exists

// exists(filter) — returns boolean
const taken = await User.exists({ email: 'joe@example.com' });
if (taken) {
  throw new Error('Email already registered');
}

count / sum / avg / min / max

// count(filter?) — count matching rows
const total = await User.count();
const admins = await User.count({ role: 'admin' });

// Scalar aggregates on a column
const totalSpend = await Order.sum('amount', { userId: 42 });
const avgRating  = await Review.avg('rating', { productId: 7 });
const earliest   = await Event.min('startDate');
const latest     = await Event.max('endDate');

truncate

// truncate() — deletes ALL rows. Use with care.
await TempData.truncate();

restore

Only applies to models with a @softDelete annotated field. Sets deletedAt back to NULL.

// restore(filter) — un-soft-delete rows
// Only available when the model has a @softDelete field

await User.delete({ id: 42 });          // soft-deletes
const user = await User.get({ id: 42 }); // null — filtered out

await User.restore({ id: 42 });
const back = await User.get({ id: 42 }); // found again
PreviousdefineModelNextUpsert & findOrCreate