GV

GeezerVison

The World Wide Web, restored to 800 pixels of glory.

Home|About|Gaming cabinet|Archives|How it works|Starter sites

On this site

  • Sign in
  • ActionsCI/CD and automation
  • CodespacesCloud development environments
  • All Features
  • Documentation
  • Training
  • Certifications
  • Build with Copilot
  • Customize Copilot
  • Integrations
  • Trending repos
  • GitHub Sponsors
  • Developer articles
  • Enterprises

This view

  • Original page
  • New address

GeezerVison is showing github.com — GitHub - entitykit/entitykit: ef-inspired typescript orm

BranchesTags
Open more actions menu

Latest commit

 

History

1,218 Commits
1,218 Commits

Folders and files

NameName
Last commit message
Last commit date
.changeset
.changeset
 
 
.github
.github
 
 
benchmarks
benchmarks
 
 
config
config
 
 
docs
docs
 
 
dogfood
dogfood
 
 
examples
examples
 
 
packages
packages
 
 
scripts
scripts
 
 
tests
tests
 
 
.gitignore
.gitignore
 
 
API.md
API.md
 
 
CONTRIBUTING.md
CONTRIBUTING.md
 
 
LICENSE
LICENSE
 
 
README.md
README.md
 
 
SECURITY.md
SECURITY.md
 
 
USAGE.md
USAGE.md
 
 
entitykit-logo.svg
entitykit-logo.svg
 
 
eslint.config.mjs
eslint.config.mjs
 
 
package-lock.json
package-lock.json
 
 
package.json
package.json
 
 
tsconfig.base.json
tsconfig.base.json
 
 
tsconfig.json
tsconfig.json
 
 

Repository files navigation

EntityKit

An Entity Framework-inspired ORM for TypeScript.

Model ordinary classes, write typed queries, track changes, and evolve schemas across SQLite, Postgres, and MySQL.

CI

Install · Quick start · Docs · Model · Packages · Migrations · Learn · Alpha


Important

EntityKit is prerelease software; APIs may change before 1.0. This branch is preparing the coordinated 0.1.0-alpha.3 family. The published alpha.2 includes @entitykit/nestjs and the source-backed DbContext constructor. Applications upgrading from alpha.1 must select a shared source explicitly with options.useDataSource(source) in configure() until they upgrade.

With a configured context, application code looks like this:

const user = db.users.create({
  id: "usr_1",
  email: "[email protected]",
  name: "Ada",
});

await db.saveChanges();

const users = await db.users
  .where(user => user.email.endsWith("@example.com"))
  .orderBy(user => user.name)
  .toArray();

The quick start below includes the complete model and context setup.

Install

Install the provider-neutral runtime, one database provider, and the CLI:

npm install @entitykit/core@alpha @entitykit/sqlite@alpha
npm install -D @entitykit/cli@alpha
Database Provider Driver
SQLite @entitykit/sqlite Built into Node
Postgres @entitykit/postgres pg
MySQL @entitykit/mysql mysql2
# Postgres
npm install @entitykit/core@alpha @entitykit/postgres@alpha pg

# MySQL
npm install @entitykit/core@alpha @entitykit/mysql@alpha mysql2

EntityKit requires Node 22.13 or newer. Importing @entitykit/core does not load a provider or database driver.

Enable typed predicate linting in your editor and CI before writing queries. It catches JavaScript && and || on EntityKit predicate objects.

Quick start

Define an ordinary class and map it in a DbContext:

import {
  DbContext,
  type ModelBuilder,
} from "@entitykit/core";
import { createSqliteDataSource } from "@entitykit/sqlite";

type NewUser = { id: string; email: string; name: string };

class User {
  id: string;
  email: string;
  name: string;

  constructor(input: NewUser) {
    this.id = input.id;
    this.email = input.email;
    this.name = input.name;
  }
}

class AppDbContext extends DbContext {
  readonly users = this.set(User);

  protected override model(model: ModelBuilder): void {
    model.entity(User, entity => {
      entity.toTable("users");
      entity.hasKey(user => user.id);
      entity.property(user => user.id).hasColumnType("text").isRequired();
      entity.property(user => user.email).hasColumnType("text").isRequired();
      entity.property(user => user.name).hasColumnType("text").isRequired();
      entity.materializeChecked(row => new User({
        id: row.required(user => user.id),
        email: row.required(user => user.email),
        name: row.required(user => user.name),
      }));
      entity.hasIndex(user => user.email).isUnique();
    });
  }
}

const dataSource = createSqliteDataSource("./app.db");

materializeChecked() lets the callback construct a fresh entity and check the scalar values it requests. Errors identify the entity and property.

EntityKit then assigns the captured mapped values, including configured read conversions. Constructor-only transformations can be overwritten; unrequested values receive no additional checks. See materialization for nullable fields, read conversions, and custom domain values.

Create a local schema, write a row, query it, and save a tracked change. users.create() constructs and tracks the entity; it executes no SQL. saveChanges() persists the pending work:

try {
  await using db = dataSource.createContext(AppDbContext);

  await db.database.ensureCreated();

  const user = db.users.create({
    id: "usr_1",
    email: "[email protected]",
    name: "Ada",
  });

  await db.saveChanges();

  const loaded = await db.users
    .where(candidate => candidate.email.eq("[email protected]"))
    .single();

  loaded.name = "Ada Lovelace";
  await db.saveChanges();
} finally {
  await dataSource.dispose();
}

The lifecycle is deliberate: create one provider data source for the application, create a fresh context for every request, job, or other unit of work, dispose that context, then dispose the data source during application shutdown. DbContext accepts the source in its optional constructor, so a source-backed context needs no provider-specific configure() method.

ensureCreated() is convenient for a one-time prototype or disposable-database bootstrap; it is not a deployment or schema-evolution primitive. Once a schema must evolve without losing data, use source-controlled migrations.

Model

Domain model
Plain TypeScript classes, explicit fluent mapping, value converters, complex properties, keys, indexes, and relationships.
Typed queries
Filters, ordering, paging, projections, joins, aggregates, relationship predicates, streaming, and parameterized SQL.
Unit of work
Identity-map materialization, snapshot change tracking, transactional saveChanges(), savepoints, and optimistic concurrency.
Explicit relationships
Split-query includes, filtered collections, explicit loading, and opt-in awaitable lazy loading—never hidden property-access I/O.
Schema workflow
Model snapshots, generated migrations, dry runs, SQL scripts, guarded destructive changes, and database-first model generation.
Application controls
Tenant scopes, soft deletes, audit fields, outbox rows, cancellation, diagnostics, retries, and provider-neutral test doubles.

EntityKit does not require decorators, generated clients, function-source parsing, or hidden lazy loading. Query selectors build typed expression trees; values stay separate from generated SQL.

Packages

Package Role
@entitykit/core Contexts, mapping, queries, tracking, errors, and configuration
@entitykit/sqlite SQLite provider using Node's built-in node:sqlite
@entitykit/postgres Postgres provider using pg
@entitykit/mysql MySQL provider using mysql2
@entitykit/cli Migrations, database inspection, and scaffolding
@entitykit/testing Provider-neutral recording test doubles
@entitykit/nestjs Native-ESM NestJS 12 lifecycle integration; begins in alpha.2

Core also exposes focused /migrations, /tooling, and /adapter entry points. /experimental contains unstable compiler and builder internals.

Migrations

The CLI creates configuration and context files, compares the current model with its checked-in snapshot, and produces reviewable TypeScript migrations:

npx entitykit init
# add entities and mappings to src/db/app-db-context.ts
npx entitykit migration add InitialCreate
npx entitykit db migrate --dry-run
npx entitykit db migrate

Rename hints preserve data when a model name changes. Destructive forward operations are reported and require explicit --allow-data-loss approval. Generated migrations are source code: review them before applying them.

The migration guide covers renames, rollback planning, deployment scripts, database-first projects, and provider-specific DDL rules.

Learn

  • Documentation map — the shortest path for newcomers, framework users, contributors, and release maintainers.
  • Usage guide — build a real context, query, save, load relationships, run transactions, and manage migrations.
  • API reference — packages, entry points, public operations, errors, and extension surfaces.
  • Framework guide — NestJS 12 and the Node-runtime Next.js 16 integration pattern.
  • Next.js + Postgres demo — a production-shaped App Router example pinned to the exact alpha.3 workspace family.
  • Compatibility — Node support, provider parity, and current alpha boundaries.
  • Architecture — package ownership, provider seams, and the query/save pipelines.

Alpha

EntityKit is deliberately honest about its current boundary. The 0.1.0-alpha.1 release was the original six-package family; the coordinated 0.1.0-alpha.2 release added the NestJS package and the refined data-source lifecycle API. This branch prepares 0.1.0-alpha.3, with aggregate correctness, nested-savepoint cleanup, performance repairs and both published upgrade baselines.

  • Every package in a coordinated release moves on one exact prerelease version.
  • The public API may change before 1.0; /experimental has no compatibility promise during alpha.
  • Provider-neutral behavior is shared, but database DDL, isolation, locking, collation, and schema-introspection details still differ.
  • Migration generation is conservative. Renames and destructive changes need explicit review.
  • SQLite table rebuilds and MySQL's implicitly committed DDL require extra care.

The complete, provider-by-provider contract lives in Compatibility.

Development

npm ci
npm run verify

Read Contributing before changing package boundaries or a public API. Report suspected vulnerabilities through the private process in Security. Maintainers should follow the exact release runbook for the published alpha family.

License

MIT. See LICENSE.

Explicit compiled models

compileModel(configure, { provider: 'sqlite' }) creates an owned mapping handle. Select it with options.useCompiledModel(handle) to skip the per-context model() hook while retaining fresh request state. The initial flat, callback-free subset and ownership limits are documented in compiled models. Eligible buffered entity reads reuse field plans, and flat projections resolve their fields once per execution. Constructors, value readers, verified writes and persistence ownership remain live.

About

ef-inspired typescript orm

Topics

change-trackingdbcontextentity-frameworkmigrationsmysqlnodejsormpostgresqlsqlitetypescripttypescript-orm

Resources

Readme
MIT license

Contributing

Contributing

Security policy

Security policy
Activity
Custom properties

Stars

0 stars

Watchers

0 watching

Forks

0 forks
Report repository

Releases

Packages

Contributors

Languages

You are visitor 01402503 — GeezerVison does not store the pages you look up.
Best viewed with Netscape Navigator 4.7 or Internet Explorer 6 at 800×600. No cookies required.