TypeORM column-level encryption with a single decorator, powered by crypto-lib.
Getting started
The Crypto Service ecosystem
Package reference
Operational
pnpm add @sebastienrousseau/crypto-typeorm
# or
npm install @sebastienrousseau/crypto-typeorm
# or
yarn add @sebastienrousseau/crypto-typeorm
^22.0.0 or >=24.0.0 (active and maintenance LTS releases)pnpm >=9 (recommended) or npm >=10>=5.0 (when compiling with TypeScript)import { Entity, PrimaryGeneratedColumn } from "typeorm";
import { EncryptedColumn } from "@sebastienrousseau/crypto-typeorm";
@Entity()
class User {
@PrimaryGeneratedColumn()
id!: number;
@EncryptedColumn({
encrypt: { key: process.env.COLUMN_ENCRYPTION_KEY! },
})
ssn!: string;
}
That is it. The ssn column is stored as an XChaCha20-Poly1305
sealed box (Base64) and decrypted transparently on every read.
Crypto Service provides a complete cryptography stack across 14 specialized packages:
| Package | Role | Description |
|---|---|---|
@sebastienrousseau/crypto-api |
API Schemas | Shared TypeScript types and utilities for the Crypto Service Suite, defining the canonical API surface. |
@sebastienrousseau/crypto-cli |
Terminal CLI | An interactive command-line interface for cryptographic operations, supporting both legacy OpenPGP and modern post-quantum algorithms. |
@sebastienrousseau/crypto-edge |
Edge Runtime | Edge-runtime cryptographic operations using the Web Crypto API, optimized for Cloudflare Workers, Vercel Edge, and Deno. |
@sebastienrousseau/crypto-kms |
Cloud KMS | Unified Key Management Service interface for AWS KMS, GCP Cloud KMS, Azure Key Vault, and HashiCorp Vault. |
@sebastienrousseau/crypto-lib |
Core Library | A modern cryptographic library for TypeScript, with post-quantum support, zero unsafe dependencies, and 100% test coverage. |
@sebastienrousseau/crypto-middleware |
Middleware | Framework-agnostic cryptographic middleware for Express, Fastify, and Koa applications. |
@sebastienrousseau/crypto-prisma |
ORM Adapter | Transparent field-level encryption extension for Prisma Client, powered by AES-256-GCM. |
@sebastienrousseau/crypto-react |
React Hooks | React hooks and context provider for client-side cryptographic operations with zero boilerplate. |
@sebastienrousseau/crypto-sdk |
Client SDK | A zero-dependency, typed HTTP client for the Crypto Service REST API, with full post-quantum support. |
@sebastienrousseau/crypto-server |
HTTP API | A hardened Fastify REST API for cryptographic operations, with rate limiting, OpenAPI schemas, and post-quantum endpoints. |
@sebastienrousseau/crypto-testing |
Test Support | Deterministic keys, fast mocks, and test fixtures for crypto-lib |
@sebastienrousseau/crypto-typeorm (this package) |
ORM Adapter | TypeORM column-level encryption with a single decorator, powered by crypto-lib. |
@sebastienrousseau/crypto-vue |
Vue Composables | Vue 3 composables for client-side cryptography |
@sebastienrousseau/crypto-wasm |
Acceleration | WebAssembly performance accelerator for crypto-lib |
crypto-typeorm provides column-level encryption for TypeORM
entities. Three integration styles are available: a @EncryptedColumn
decorator that combines TypeORM's @Column with automatic
encryption/decryption, an EncryptionSubscriber for centralised
field configuration, and an EncryptionTransformer for manual
ValueTransformer usage. All styles use XChaCha20-Poly1305 via
crypto-lib's secretbox, with fresh random nonces on every write.
All APIs accept an EncryptionConfig object:
| Property | Type | Default | Description |
|---|---|---|---|
key |
string |
required | 256-bit key as a 64-char hex string |
algorithm |
string |
"xchacha20-poly1305" |
Algorithm identifier |
fields |
Map<string, string[]> |
undefined |
Per-entity field list (used by EncryptionSubscriber) |
@EncryptedColumn reads process.env.TYPEORM_ENCRYPTION_KEY when
no key is provided in decorator options.
@EncryptedColumn(options?)A property decorator that combines TypeORM's @Column with an
EncryptionTransformer.
@EncryptedColumn() // uses TYPEORM_ENCRYPTION_KEY env var
@EncryptedColumn({ encrypt: { key: "..." } }) // explicit key
@EncryptedColumn({ type: "text", nullable: true, encrypt: { key: "..." } })
## Subscriber API
EncryptionSubscriberAn EntitySubscriberInterface that encrypts/decrypts fields based
on a centralised configuration.
import { DataSource } from "typeorm";
import { EncryptionSubscriber } from "@sebastienrousseau/crypto-typeorm";
const ds = new DataSource({
subscribers: [
new EncryptionSubscriber({
key: process.env.COLUMN_ENCRYPTION_KEY!,
fields: new Map([
["User", ["ssn", "email"]],
["Payment", ["cardNumber"]],
]),
}),
],
});
| Hook | Behaviour |
|---|---|
beforeInsert |
Encrypts configured fields in-place |
beforeUpdate |
Encrypts configured fields in-place |
afterLoad |
Decrypts configured fields in-place |
Decryption is wrapped in a try/catch so that legacy unencrypted rows are left as-is during a gradual migration.
## Transformer APIEncryptionTransformerA standard TypeORM ValueTransformer for manual use on any
@Column.
import { Column, Entity, PrimaryGeneratedColumn } from "typeorm";
import { EncryptionTransformer } from "@sebastienrousseau/crypto-typeorm";
const transformer = new EncryptionTransformer({
key: process.env.COLUMN_ENCRYPTION_KEY!,
});
@Entity()
class Secret {
@PrimaryGeneratedColumn()
id!: number;
@Column({ type: "text", transformer })
value!: string;
}
| Method | Input | Output |
|---|---|---|
to(value) |
plaintext or null |
Base64 sealed box or null |
from(value) |
Base64 sealed box or null |
plaintext string or null |
All examples are self-contained TypeScript files in the examples/
directory. Run any example with:
npx ts-node examples/<name>.ts
| Category | Example | Purpose |
|---|---|---|
| Decorator | decorator.ts | Using @EncryptedColumn on entity fields |
| Subscriber | subscriber.ts | Centralised encryption via EncryptionSubscriber |
| Transformer | transformer.ts | Manual ValueTransformer on @Column |
| Migration | migration.ts | Encrypting existing plaintext columns |
pnpm --filter @sebastienrousseau/crypto-typeorm run build
pnpm --filter @sebastienrousseau/crypto-typeorm run test
pnpm --filter @sebastienrousseau/crypto-typeorm run lint
pnpm --filter @sebastienrousseau/crypto-typeorm run format
All 14 packages in the Crypto Service workspace maintain a 100% coverage floor across statements, branches, functions, and lines.
Report vulnerabilities privately via GitHub Security Advisories or according to SECURITY.md. Never report security issues publicly.
All cryptographic operations leverage audited primitives, enforce constant-time execution where applicable, and zero sensitive key material upon disposal.
Versions advance strictly one step at a time on the 0.0.x line (v0.0.1 → v0.0.2 → v0.0.3 ... → v0.0.999 → v0.1.0). Work for every release iteration begins on a dedicated feat/v<version> branch.
All 14 packages in the workspace move in lockstep. Public API signatures, cipher output formats, and serialization schemas are strictly versioned. Breaking changes to serialized formats or algorithm defaults are considered major breaking changes. Minimum toolchain upgrades (e.g. Node.js LTS floor) are governed by POLICIES.md.
Dual-licensed under Apache 2.0 or MIT, at your option.
Copyright (c) 2022-2026 Sebastien Rousseau and The Crypto Service Suite contributors.