sync() installs it, list what a database has and what a managed servicesrc/extensions is also a searchable catalogue of| Engine | Install | Inventory |
|---|---|---|
| PostgreSQL family (PostgreSQL, TimescaleDB, Citus, AlloyDB, ParadeDB, Greenplum, YugabyteDB, CockroachDB shims, RDS/Aurora, Azure, Cloud SQL, Cosmos DB for PostgreSQL, Neon, Supabase) | CREATE EXTENSION IF NOT EXISTS "name" [SCHEMA] [VERSION] [CASCADE] | pg_available_extensions |
| DuckDB, MotherDuck | INSTALL "name" then LOAD "name" | duckdb_extensions() |
| MySQL | INSTALL PLUGIN name SONAME 'lib.so', or INSTALL COMPONENT 'file://component_x' | information_schema.PLUGINS, mysql.component |
| MariaDB | INSTALL PLUGIN name SONAME 'lib.so' | information_schema.ALL_PLUGINS |
| SQLite | the driver's Database#loadExtension(path) (better-sqlite3) | pragma_module_list |
query_rewriterewriter plugin from rewriter.so); otherwise the library is<name>.so, or pass soname / --soname.import { Prorm } from 'ts-prorm-orm';
const prorm = new Prorm({
dialect: 'postgres',
url: process.env.DATABASE_URL,
extensions: ['pgvector', 'postgis', { name: 'pg_trgm', schema: 'ext', version: '1.6' }],
});
await prorm.sync(); // installs the extensions, then creates tables
await prorm.ensureExtensions(); // or just the extensions, without syncingextensions import --dry-runimport { Prorm } from 'ts-prorm-orm';
new Prorm({
dialect: 'postgres',
url: process.env.DATABASE_URL,
extensions: ['vector', 'postgis', { name: 'pg_trgm', schema: 'ext', version: '1.6' }],
});import { Prorm } from 'ts-prorm-orm';
new Prorm({ dialect: 'duckdb', storage: './warehouse.duckdb', extensions: ['spatial', 'httpfs'] });import { Prorm } from 'ts-prorm-orm';
// The catalogue maps query_rewrite to the rewriter plugin and its library.
new Prorm({ dialect: 'mysql', url: process.env.DATABASE_URL, extensions: ['query_rewrite'] });import { Prorm } from 'ts-prorm-orm';
// Loaded per connection, through better-sqlite3's loadExtension().
new Prorm({ dialect: 'sqlite', storage: 'app.db', extensions: [{ name: 'vec0', path: './ext/vec0.dylib' }] });sync() orensureExtensions().sync() installs declared extensions before it creates any table: aVECTOR(1536) or GEOMETRY column cannot be created until the extension that{ name, version?, schema?, cascade?, soname?, path? }; pgvector is acceptedvector and timescale for timescaledb. An extension that is alreadyversion is asked for, in whichALTER EXTENSION … UPDATE TO'd. If any extension fails, sync()path (assync() (orensureExtensions()) runs.$ prorm db up --dialect postgres --ext pgvector--ext picks an image that has pgvector and writes the credentials to a.env; seeimport { Prorm, DataTypes } from 'ts-prorm-orm';
const prorm = new Prorm({
dialect: 'postgres',
url: process.env.DATABASE_URL,
extensions: ['pgvector'], // accepted for "vector"
});
await prorm.connect();
const Doc = prorm.define('Doc', {
id: { type: DataTypes.INTEGER, primaryKey: true, autoIncrement: true },
body: { type: DataTypes.TEXT },
embedding: { type: DataTypes.VECTOR(1536) },
}, { tableName: 'docs' });
await prorm.sync(); // CREATE EXTENSION first, then CREATE TABLE docs$ prorm extensions list --url $DATABASE_URLvector is now installed, with its version.$ prorm extensions export --url $DATABASE_URL --key dev
✓ Wrote 1 extension(s) for dev to prorm.extensions.json. Replay with: prorm extensions import --from prorm.extensions.jsonprorm.extensions.json; CI and staging replay it withextensions import --from.planExtensions(prorm,
names, { dryRun }) returns the statements (and, without dryRun, runs them),readExtensionsManifest(file) reads a manifest:import { planExtensions, readExtensionsManifest } from 'ts-prorm-orm';
const { statements } = await planExtensions(prorm, ['vector'], { dryRun: true });
// ['CREATE EXTENSION IF NOT EXISTS "vector"']sync() uses, so a --dry-run$ prorm extensions import vector postgis --dialect postgres --database app --dry-run
CREATE EXTENSION IF NOT EXISTS "vector";
CREATE EXTENSION IF NOT EXISTS "postgis";
$ prorm extensions import postgis_topology --cascade --dialect postgres --database app --dry-run
CREATE EXTENSION IF NOT EXISTS "postgis_topology" CASCADE;
$ prorm extensions import pg_trgm --schema ext --version 1.6 --dialect postgres --database app --dry-run
CREATE EXTENSION IF NOT EXISTS "pg_trgm" SCHEMA "ext" VERSION '1.6';list reads pragma_module_list, which reports the modules$ prorm extensions list --dialect sqlite --database ./app.sqlite
name status installed default note
dbstat installed virtual-table module
fts3 installed virtual-table module
fts4 installed virtual-table module
fts5 installed virtual-table module
geopoly installed virtual-table module
rtree installed virtual-table module
…extensions list marks each extension:| Status | Meaning |
|---|---|
installed | In the database now (with its version). |
available | The server offers it (pg_available_extensions, duckdb_extensions(), MariaDB's plugin directory). |
not-allowed | The server has it, but the managed service's allow-list excludes it. |
unknown | Known to the catalogue (--catalog, and always on MySQL) but the server could not say whether the library is there. |
extensions import takes --schema, --version (one extension at a time),--cascade, --soname (MySQL/MariaDB) and --dry-run, which prints the--dry-run uses, without$ prorm extensions import foo --dialect mssql --database app --dry-run
✗ mssql has no extensions prorm can install. Extensions are a PostgreSQL, DuckDB, SQLite (loadable modules) and MySQL/MariaDB (plugins) feature. The closest equivalents on mssql are server features, not installable here: Full-Text Search, In-Memory OLTP, PolyBase, Machine Learning Services, CLR Integration.
$ echo $?
2extension create / extension drop commands still install andQueryInterface; extensions is the| Service | Allow-list | What the refusal tells you to run |
|---|---|---|
| RDS for PostgreSQL | rds.allowed_extensions (null/* = no restriction) | aws rds modify-db-parameter-group --db-parameter-group-name <group> --parameters "ParameterName=rds.allowed_extensions,ParameterValue='…,postgis',ApplyMethod=immediate" |
| Aurora PostgreSQL | same, cluster parameter group | aws rds modify-db-cluster-parameter-group --db-cluster-parameter-group-name <group> … |
| Azure Database for PostgreSQL | azure.extensions (empty = nothing allowed) | az postgres flexible-server parameter set --name azure.extensions --value "…,vector" --resource-group <rg> --server-name <server> |
| Cloud SQL for PostgreSQL | database flags for pg_cron, pgaudit, pglogical, pg_hint_plan, pg_squeeze, pg_bigm, pg_wait_sampling, anon | gcloud sql instances patch INSTANCE --database-flags=cloudsql.enable_pg_cron=on (the whole flag list is replaced; pass every flag) |
extensions list shows the allow-list and marks what it excludesnot-allowed; on Cloud SQL the flag an extension needs appears in the note$ prorm extensions import vector --dialect rdsmysql --database app --dry-run
✗ rdsmysql has no extensions prorm can install. RDS for MySQL enables plugins through option groups: aws rds add-option-to-option-group --option-group-name <group> --options OptionName=<PLUGIN> --apply-immediately[!WARNING] gcloud sql instances patch --database-flagsreplaces every flag
The command sets the instance's whole flag list. Pass the flags that are
already set along with the new one, or they are reset to their defaults,
and some flag changes restart the instance.
requireExtensionEngine(),extensionEngineFor() and managedAllowCommand() in src/extensions/manage.ts:POSTGRES_EXTENSION_DIALECTS inmanage.ts (PostgreSQL, TimescaleDB, Citus, AlloyDB and Omni, ParadeDB,$ prorm extensions export --url $PROD_URL --key prod
$ prorm extensions import --from prorm.extensions.json --source prod --url $STAGING_URLexport writes prorm.extensions.json unless --out names another file--out - prints the manifest to stdout).public schema, and a{
"version": 1,
"generatedAt": "2026-09-25T12:00:00.000Z",
"databases": {
"prod": {
"dialect": "rdspostgres",
"extensions": [
{ "name": "vector", "version": "0.7.4" },
{ "name": "postgis", "version": "3.4.2", "schema": "gis" }
]
}
}
}export merges into an existing file by key (default: the database name), soimport --from picks --source,--latest drops theplpgsql, MySQL's compiled-in plugins) are not^[A-Za-z_][A-Za-z0-9_-]{0,62}$ (DuckDB and MySQL"uuid-ossp", `audit_log`.x"; DROP TABLE users; -- is anInvalidExtensionNameError (a usage error, exit 2, on the CLI), not a$ prorm extensions import 'x"; DROP TABLE users; --' --dialect postgres --database app --dry-run
✗ Invalid extension name "x\"; DROP TABLE users; --": use letters, digits, underscores and hyphens, starting with a letter or underscore (max 63).
$ echo $?
2import { Prorm } from 'ts-prorm-orm';
const prorm = new Prorm({ dialect: 'postgres', url: process.env.DATABASE_URL });
await prorm.connect();
await prorm.createExtension('pg_trgm', { ifNotExists: true });
await prorm.hasExtension('pg_trgm');
await prorm.getExtensions();
await prorm.dropExtension('pg_trgm', { cascade: true });CREATE EXTENSION mechanism. EntriesisNativeSqlExtension: false.import {
findExtension, listExtensionsForDialect, listExtensionsByCategory,
listExtensionsForDialectAndCategory, searchExtensions,
listCategoriesForDialect, extensionCatalog,
} from 'ts-prorm-orm';
findExtension('pg_trgm');
listExtensionsForDialect('postgres'); // 51 entries
listExtensionsByCategory('vector-search');
listExtensionsForDialectAndCategory('mysql', 'full-text-search');
searchExtensions('vector'); // name + description search
listCategoriesForDialect('oracle');{
name: 'pg_trgm',
dialects: ['postgres', 'cockroachdb'],
category: 'full-text-search',
description: 'Trigram-based similarity matching and indexing for text ' +
'(similarity(), % operator, GiST/GIN opclasses). On CockroachDB, ' +
'`CREATE EXTENSION pg_trgm` is accepted as a no-op compatibility shim ' +
'only — no trigram functions or operators are actually provided.',
installCommand: 'CREATE EXTENSION IF NOT EXISTS pg_trgm',
isNativeSqlExtension: true,
docsUrl: 'https://www.postgresql.org/docs/current/pgtrgm.html',
}installCommand is omitted where there is no single statement, because thefull-text-search, data-types, json, spatial-gis, cryptography,uuid-generation, vector-search, indexing, foreign-data, scheduling,partitioning, monitoring-stats, utility, procedural-language,time-series, replication, security-audit, high-availability,connectivity, compression, in-memory, machine-learning.| Source file | Entries | Covers |
|---|---|---|
postgres-extensions.ts | 51 | Real CREATE EXTENSION extensions — pg_trgm, postgis, pgcrypto, hstore, uuid-ossp, pgvector, … |
mysql-mariadb-plugins.ts | 20 | MySQL/MariaDB plugins (INSTALL PLUGIN) and storage engines |
oracle-db2-features.ts | 21 | Oracle and IBM Db2 licensed options and built-in features |
mssql-features.ts | 13 | SQL Server features — In-Memory OLTP, Always Encrypted, PolyBase, … |
cloud-warehouse-features.ts | 19 | Snowflake / Redshift / ClickHouse / BigQuery-style capabilities |
const options = searchExtensions('vector')
.filter((e) => e.dialects.includes(prorm.getDialect() as any));
for (const e of options) {
console.log(e.name, '—', e.description);
if (e.installCommand) console.log(' install:', e.installCommand);
console.log(' docs:', e.docsUrl);
}vector (pgvector), whose install statement you canawait prorm.createExtension('vector', { ifNotExists: true });DataTypes.VECTOR(1536) maps to a real VECTOR(1536) column — seeextensions — the full entry shape and per-file breakdowncreateExtension and friendsprorm db up --ext pgvector,postgis picks an image that ships themextensions flag