Repository navigation
Releases
ts-orm 2.0.0
ts-orm v2.0.0
ts-orm v2.0.0 rewrites the internal query engine to eliminate runtime execution overhead while preserving total compile-time type safety.
This release targets high-concurrency Node.js and Bun applications where query compilation speed and low memory usage directly affect request throughput.
Key Changes
1. Re-Engineered Query Engine
- Reduced query compilation overhead up to 4x compared to v1.x releases.
- Consolidated internal AST parsing to minimize heap allocations per query execution.
- Streamlined connection pool handling for lower latency under high concurrent load.
2. Strict Type Inference
- Full autocomplete across complex multi-table joins, subqueries, and dynamic filters.
- Payload shapes infer directly from schema definitions without requiring code generation steps or external CLI tools.
- Schema mismatches and invalid relation references fail at build time.
3. Updated API Surface
- Standardized initialization syntax for database drivers and custom dialects.
- Cleaner methods for conditional filtering, pagination, and bulk mutations.
- Uniform query semantics across supported SQL drivers.
Installation
npm install ts-orm@latest
1.5.0 Security-Focused Release
⏺ Release Notes: v1.5.0
Security-Focused Release
Version 1.5.0 is a major security update that addresses critical vulnerabilities and adds enterprise-grade
security features to ts-orm. This release focuses on preventing SQL injection attacks, enhancing input
validation, and protecting sensitive information through error sanitization.
Highlights
- SQL Injection Prevention: Hybrid validation and escaping for all database identifiers
- Enhanced Validation: Strict format checking for UUID, datetime, date, and boolean types
- Error Sanitization: Protected error messages prevent schema information leakage
- Security Test Suite: 9 new tests covering injection attempts and validation edge cases
Security Enhancements
SQL Injection Prevention
- ✅ All table names validated and escaped before query execution
- ✅ All column names validated and escaped (WHERE, SET, ORDER BY, JOIN clauses)
- ✅ Qualified identifiers (e.g., table.column) validated in JOIN operations
- ✅ Hybrid approach: Pattern validation [a-zA-Z0-9_] + mysql2 escapeId()
- ✅ Protection against common injection vectors:
- Malicious table names: users; DROP TABLE users--
- Malicious ORDER BY: id; DROP TABLE--
- Malicious WHERE conditions: id' OR '1'='1
Enhanced Input Validation
- ✅ UUID v4 format validation: Regex pattern
/^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i - ✅ Datetime format validation: YYYY-MM-DD HH:MM:SS with range checks (month 1-12, day 1-31, hour 0-23,
etc.) - ✅ Date format validation: YYYY-MM-DD with validity checks using Date object
- ✅ Boolean type validation: Accepts true, false, 0, 1, '0', '1'
- ✅ Enum null handling: Properly allows null/undefined for non-required enum fields
- ✅ Required field fix: Now allows falsy values like false and 0 but rejects undefined/null
Error Sanitization
- ✅ Database errors mapped to safe, generic messages
- ✅ Full error details logged server-side with console.error()
- ✅ Schema information never exposed to clients
- ✅ Error mappings:
- ER_DUP_ENTRY → "Record already exists"
- ER_NO_REFERENCED_ROW → "Related record not found"
- ER_ROW_IS_REFERENCED → "Cannot delete record - it is referenced by other records"
- All other errors → "Database operation failed"
v1.4.0 Release
This release introduces a powerful new command-line tool that allows you to generate ts-orm JSON structs directly from your MySQL tables. It's the fastest way to bootstrap your project with real schema definitions.
New: CLI Struct Generator
You can now generate a ts-orm compatible struct with a single command:
npx ts-orm struct usersThis will connect to your database using your .env settings and output a file called:
users.json
Features:
- Maps MySQL types to
ts-ormtypes (string,number,uuid,boolean,enum,date,datetime) - Detects
auto_incrementfields and marks them correctly - Extracts enum values as arrays
- Assigns proper length limits for fields like
varchar,date, anddatetime - Skips optional or null defaults appropriately
Examples
MySQL column:
id INT AUTO_INCREMENT PRIMARY KEYGenerates:
{
"name": "id",
"type": "number",
"required": true,
"length": 11,
"default": "auto_increment"
}MySQL enum:
status ENUM('draft', 'published') NOT NULL DEFAULT 'draft'Generates:
{
"name": "status",
"type": "enum",
"required": true,
"length": null,
"default": "draft",
"enum": ["draft", "published"]
}Getting Started
npm install @velkymx/ts-orm
npx ts-orm struct usersThis is especially useful when onboarding legacy tables or rapidly scaffolding new endpoints.
Thanks for using ts-orm. Feedback and feature suggestions welcome!
v1.3.0 – Auto-Increment Support & Validation
This release introduces support for traditional SQL-style AUTO_INCREMENT primary keys, with smarter insert handling, enhanced validation, and full test coverage.
🚀 New Features
✅ Auto-Increment ID Field Support
You can now define a struct field like this:
{
name: "id",
type: "number",
required: true,
length: 11,
default: "auto_increment"
}Behavior:
- On
create():- The
idis ignored automatically (not included in SQL). - If the user tries to pass
id, validation will fail.
- The
- On
update()/remove():- The
idis required and validated as a number.
- The
🔐 Validation Enhancements
The validatePayload() function now:
- Skips validation for
auto_incrementfields during insert - Rejects attempts to manually pass
idduring insert - Preserves strict type validation for updates/deletes
🧪 Tests Added
New tests verify:
- Successful creation without ID
- Proper update/delete using returned ID
- Failure if user tries to provide an
auto_incrementID on insert
✨ Example
await create('users', userStruct, {
title: 'Auto User'
});
// Returns: { success: true, data: { id: 1 } }await create('users', userStruct, {
id: 99,
title: 'Invalid'
});
// Fails: id should not be provided (auto_increment)✅ Summary
This update adds:
- Cleaner support for auto-incrementing numeric IDs
- Safer inserts with validation against misuse
- Consistent handling across all CRUD operations
v1.2.0 Release Notes
This release introduces powerful enhancements to the read and readWith methods by adding support for:
- Sorting (
orderBy,direction) - Pagination (
limit,offset)
These features allow you to build cleaner APIs, faster admin tools, and scalable data listings with minimal effort.
New Features
1. Sorting Support
You can now sort results using orderBy and direction.
Usage:
await read('users', {}, {
orderBy: 'created_at',
direction: 'DESC'
});2. Pagination Support
Limit the number of returned records and skip records using limit and offset.
Usage:
await read('posts', {}, {
orderBy: 'created_at',
direction: 'ASC',
limit: 10,
offset: 20 // Page 3, assuming 10 per page
});3. readWith() Enhanced
The readWith method now also supports sorting and pagination across joined tables.
Usage:
await readWith('orders', {}, [
{ table: 'users', on: ['orders.user_id', 'users.id'], type: 'left' }
], {
orderBy: 'orders.created_at',
direction: 'DESC',
limit: 5,
offset: 10
});Test Coverage
- Bulk record inserts added for pagination simulation
- New tests for:
read()withorderByandlimit/offsetreadWith()with joins and pagination
- Validated sorting direction and dataset correctness
Migration Notes
No breaking changes. Existing read() and readWith() calls will continue to work as before.
These new options are fully backward-compatible and optional.
What’s Next
- Optional field selection (
select) - Pagination metadata (
total,pages) - Default sort support in struct definitions
Thank you for using ts-orm. Feedback and contributions welcome.
v1.1.0 Release Notes
This document outlines the latest additions to ts-orm for improved querying and relational data handling.
readOne
Fetch a single record that matches the given conditions.
Usage
const result = await readOne('users', { id: 'abc-123' });
if (result.success) {
console.log('User:', result.data);
} else {
console.log('Not found:', result.message);
}Behavior
- Returns
{ success: true, data: {...} }if found - Returns
{ success: false, data: null }if not found
findOrFail
Fetch a record by key or throw an error if it doesn't exist.
Usage
try {
const user = await findOrFail('users', 'id', 'abc-123');
console.log('User:', user);
} catch (err) {
console.error(err.message); // Record not found in table 'users' with id = abc-123
}Behavior
- Returns the record directly if found
- Throws
Errorif not found
readWith
Perform a SELECT query with JOINs based on JSON-configured relationships.
Syntax
readWith(table, conditions = {}, joins = [])Usage
const result = await readWith('orders', { user_id: 42 }, [
{ table: 'users', on: ['orders.user_id', 'users.id'], type: 'inner' }
]);
if (result.success) {
console.log(result.data);
}Join Options
type(optional):'inner'(default),'left','right'table: the table to joinon: an array of two column paths:[leftColumn, rightColumn]
Example
[
{ table: 'users', on: ['orders.user_id', 'users.id'], type: 'left' },
{ table: 'products', on: ['orders.product_id', 'products.id'], type: 'right' }
]Behavior
- Builds a raw SQL query with joins
- Returns all joined results in
result.data
Example Scenario with readWith
Two tables:
CREATE TABLE orders (
id VARCHAR(36) PRIMARY KEY,
user_id VARCHAR(36),
product_id VARCHAR(36)
);
CREATE TABLE users (
id VARCHAR(36) PRIMARY KEY,
name VARCHAR(128)
);const result = await readWith('orders', { user_id: 'abc-123' }, [
{ table: 'users', on: ['orders.user_id', 'users.id'], type: 'inner' }
]);This performs:
SELECT * FROM orders
JOIN users ON orders.user_id = users.id
WHERE orders.user_id = 'abc-123'