Skip to content

Roadmap ​

Egon ORM is under construction: nothing is published to npm yet.

Built ​

FeaturePages
Schemas, types, associations and embedsSchemas, Types, Associations, Embeds
Changesets, validation (built-in rules, Zod and any Standard Schema library), constraints, nested changesetsChangesets, Validation, Constraints, Nested changesets
The query builder: joins, subqueries, CTEs, set operations, window functions, fragments, named parametersQueries, Expressions, Advanced queries
The repo: reads, writes, upserts, bulk writes, preloads, streams, transactions, batches, the test sandboxRepo, Transactions, Batch, Testing
Postgres, SQLite and MySQL adaptersAdapters, Dialect support
Migrations, their runner and the egon commandMigrations, CLI

Before the first release ​

WorkNotes
PerformanceBenchmarks against the raw drivers. No numbers are published until then.
Release hardeningPublishing the packages, @egon-orm/cli included, versioning and the changelog.

Planned after the first release ​

FeatureNotes
Faster editor completions in large modelsAfter an edit, completions inside a query callback take about 40 ms plus 1.1–1.2 ms per schema reachable through associations, so they pass 200 ms at about 140–170 connected schemas on the machine measured, sooner on slower ones. The likely cause is that the association and preload types infer every static member of each reachable schema; the plan is to make them read the schema's association metadata and expand only where preload is used. Until then, declaring the return type of changeset methods lowers the cost (to about 114 ms at 200 schemas in one measurement); include in it the error keys the validations add, as in Changeset<typeof User, boolean, "passwordConfirmation">, or errorMessages() loses them.
Lateral joinsjoinLateral, leftJoinLateral.
VALUES lists as a query sourcefrom(values(...), "v").
Table-valued fragmentsSuch as generate_series as a source.
Index hintsMySQL.
Data-modifying CTEsUPDATE or DELETE inside a WITH.
Named server-side prepared statementsFor prepare.
Form helpers for nested changesetsSort and drop parameters, and index-keyed objects in place of arrays.
Other databases through a custom dialect
Built-in multi-tenancyTenants as a column of shared tables, with the tenant given explicitly on the repo or the call: a query or write on a tenant-scoped schema class without a tenant is refused, inserts fill in the tenant, and preloads stay within it. A database schema per tenant stays a recipe, using the repo's schema option.
Built-in soft deletesSupport for what the soft-deletes recipe does by hand: a schema option for the deleted-at field, soft delete and restore in the repo, and an explicit opt-in to leave deleted rows out of a query. No default scope applies by itself.
Postgres row-level securityOperations in migrations to enable row-level security on a table and to create and drop policies, each with the operation that undoes it, for down; settings such as the application's user id (app.user_id) given per transaction, always transaction-scoped and bound; a new row a policy refuses (SQLSTATE 42501, "new row violates row-level security policy") reported as an error of its own. Rows a policy hides are not errors: a read leaves them out and a write affects no rows. Postgres only.
Query observabilityBuilt on the query event of repo.on, which already reports each statement's SQL and timings: slow-query detection, OpenTelemetry tracing and warnings for N+1 query patterns.
A browser entry pointegon-orm/client, with cast and the validations, so a form can run the same casts and field validations in the browser, without bundling the query builder or the repo. Constraints and checks that ask the database stay on the server.
Test factoriesBeside the test sandbox: build valid rows for a schema, override single fields, create association graphs, and generate deterministic test data. For integration tests in large applications.

Not planned ​

These are deliberate choices, not gaps:

  • Active-record methods such as user.save(). Rows are data.
  • Lazy loading. Associations are loaded only when asked for.
  • An identity map or unit of work. Two queries for the same row return two objects.
  • Implicit transactions. Nothing joins a transaction you did not open: only calls on the transaction object are inside it. (A single call that writes several statements, a parent with its children or a chunked insertAll, is atomic on its own.)
  • Generating migrations from schema differences. Migrations are written by hand.
  • Non-SQL stores.