@ghuts/liteorm
v1.2.0
Published
Zero-dependency native SQLite ORM for Node.js with query builder, migrations, relations, schema builder, FTS5, encryption, audit logs, and CLI.
Maintainers
Readme
Lite ORM
Zero-dependency native SQLite ORM for Node.js.
Lite ORM is a lightweight SQLite-first ORM built around a C++ N-API addon and a small JavaScript ORM layer. It gives you a query builder, schema builder, migrations, typed models, relationships, validation, transactions, caching, hooks, soft deletes, JSON fields, FTS5, encryption casts, audit logs, CLI utilities, and TypeScript declarations without adding runtime npm dependencies.
Current version: 1.2.0
Package name: @ghuts/liteorm
Repository: https://github.com/yeweroooo/lite-orm
NPM: https://www.npmjs.com/package/@ghuts/liteorm
Highlights
- Native SQLite bridge using C++ N-API.
- Zero runtime npm dependencies.
- SQLite-first design: WAL, foreign keys, JSON1, FTS5, PRAGMA tuning, backup via
VACUUM INTO. - Native prepared statements, statement cache stats, JavaScript UDFs, and custom collations.
- Query Builder: filters, grouped conditions, joins, ordering, grouping, pagination, JSON operators, update/delete/restore.
- Schema Builder: create/drop/rename tables, columns, indexes, unique indexes, JSON expression indexes.
- Models: field definitions, structured validators, defaults, JSON casts, encrypted casts with key rotation, hidden/computed fields.
- Relationships:
hasOne,hasMany,belongsTo,belongsToMany. - Migrations: run once, status, preview, seed, rollback, generate model/migration scaffolds.
- TypeScript-first declarations with generic model/create/update helpers.
- Transactions with nested savepoints, retries, caching, abortable lifecycle hooks, paranoid soft delete, restore, dirty tracking.
- CDC/sync helpers, query profiling, RBAC policies, plugin hooks.
- FTS5 search helper with rank, highlight, snippets, sync triggers.
- Introspection and explain query plan.
- Audit log helper.
- Factory, deterministic seeder, export/import JSON/CSV, repository helper.
- CLI: init, inspect, model/migration generator, migrate/status/seed/rollback/preview, SQL studio exec, JSON export, doctor.
Requirements
- Node.js >= 18
- npm
- C++ compiler
- Python available to node-gyp
- node-gyp available through npm lifecycle
- SQLite is vendored in
deps/sqlite/for portable builds
On Debian/Ubuntu-like systems:
sudo apt-get install -y build-essential python3Installation
From npm after publish:
npm install @ghuts/liteormFrom local tarball:
npm install ./ghuts-liteorm-1.2.0.tgzFrom local project folder:
cd lite-orm
npm install
npm run build
npm testThe package runs node-gyp rebuild during npm install.
Quick start
const { Database, defineModel, field } = require('@ghuts/liteorm');
const db = new Database('app.sqlite');
db.schema.createTable('users', t => {
t.increments('id');
t.text('name').notNull();
t.text('email').notNull().unique();
t.text('role').default('user');
t.json('meta');
t.timestamps();
t.softDeletes();
});
const User = defineModel(db, 'users', {
fields: {
id: field.integer().primary().autoIncrement(),
name: field.text().required().min(2),
email: field.text().required().email(),
role: field.text().default('user'),
password: field.text().hidden(),
meta: field.json().default({})
},
softDelete: true,
timestamps: true,
json: ['meta'],
hidden: ['password'],
scopes: {
admins: q => q.where('role', '=', 'admin')
},
computed: {
label: user => `${user.name}<${user.email}>`
}
});
User.create({
name: 'Adit',
email: '[email protected]',
role: 'admin',
password: 'hidden-value',
meta: { tier: 'pro' }
});
const rows = User.query()
.where('role', '=', 'admin')
.whereJson('meta.tier', '=', 'pro')
.orderBy('id', 'desc')
.get();
console.log(rows.map(row => row.toJSON()));Imports
CommonJS:
const {
Database,
defineModel,
Model,
QueryBuilder,
field,
sql,
errors,
sqliteVersion
} = require('@ghuts/liteorm');TypeScript:
import { Database, defineModel, field, errors } from '@ghuts/liteorm';Database API
Create/open database
const db = new Database('app.sqlite');
const memory = new Database(':memory:');With options:
const db = new Database('app.sqlite', {
cache: { ttl: 1000, max: 500 },
busyTimeout: 5000,
retry: { attempts: 3, delay: 10 },
encryptionKey: Buffer.from('01234567890123456789012345678901')
});Raw query and exec
db.exec('CREATE TABLE users(id INTEGER PRIMARY KEY, email TEXT)');
db.exec('INSERT INTO users(email) VALUES(?)', ['[email protected]']);
const rows = db.query('SELECT * FROM users WHERE email = ?', ['[email protected]']);
console.log(rows);SQL tagged template
const { sql } = require('@ghuts/liteorm');
const rows = db.query(sql`SELECT * FROM users WHERE email = ${'[email protected]'}`);The tag returns { text, params }.
Transactions
db.transaction(tx => {
tx.exec('INSERT INTO users(email) VALUES(?)', ['[email protected]']);
tx.exec('INSERT INTO users(email) VALUES(?)', ['[email protected]']);
});If the callback throws, the transaction rolls back.
Async wrapper
const rows = await db.async.query('SELECT * FROM users');
await db.async.exec('INSERT INTO users(email) VALUES(?)', ['[email protected]']);Current async API is a Promise-compatible wrapper around the sync native calls, so the API is ready for a future worker-thread backend without breaking user code.
Prepared statement facade
const stmt = db.prepare('SELECT * FROM users WHERE email = ?');
const one = stmt.get(['[email protected]']);
const all = stmt.all(['[email protected]']);
stmt.finalize();stmt.run(params) is available for write statements.
PRAGMA tuning
db.tune({
journalMode: 'WAL',
synchronous: 'NORMAL',
busyTimeout: 5000,
cacheSize: -64000,
tempStore: 'MEMORY',
mmapSize: 268435456
});Supported option names:
journalMode->PRAGMA journal_modesynchronous->PRAGMA synchronousbusyTimeout->PRAGMA busy_timeoutcacheSize->PRAGMA cache_sizetempStore->PRAGMA temp_storemmapSize->PRAGMA mmap_size
Backup and restore
db.backup('backup.sqlite');
db.restore('backup.sqlite');Backup uses SQLite VACUUM INTO.
Explain query plan
const plan = db.explain(User.query().where('email', '=', '[email protected]'));
console.log(plan);Plugins
db.use((database, opts) => {
database.hello = () => `hello ${opts.name}`;
}, { name: 'orm' });
console.log(db.hello());Schema Builder
Create table
db.schema.createTable('users', t => {
t.increments('id');
t.text('name').notNull();
t.text('email').notNull().unique();
t.integer('age').default(0);
t.real('score').default(0);
t.boolean('active').default(1);
t.json('meta');
t.timestamps();
t.softDeletes();
t.index(['email']);
t.unique(['email']);
});Column helpers
t.increments(name)t.integer(name)t.text(name)t.real(name)t.boolean(name)t.json(name)t.timestamps()createscreated_atandupdated_att.softDeletes()createsdeleted_at
Column modifiers
.primary().autoIncrement().required()/.notNull().nullable().unique().default(value).references(table, column = 'id')
Example:
db.schema.createTable('posts', t => {
t.increments('id');
t.integer('user_id').notNull().references('users', 'id');
t.text('title').notNull();
t.text('body');
t.timestamps();
});Schema maintenance
db.schema.dropTable('old_table');
db.schema.renameTable('old_name', 'new_name');
db.schema.addColumn('users', 'phone', field.text().nullable());
db.schema.table('users', t => {
t.index(['email']);
});Schema diff and generated migration
const statements = db.schema.diff('users', {
phone: field.text().nullable(),
nickname: field.text().nullable()
});
const file = db.schema.generateMigration('add_user_contact_fields', statements, './migrations');
console.log(file);diff() currently detects missing columns and produces ALTER TABLE ... ADD COLUMN ... statements.
Field definitions
Field definitions describe model behavior and validation.
const User = defineModel(db, 'users', {
fields: {
id: field.integer().primary().autoIncrement(),
name: field.text().required().min(2).max(80),
email: field.text().required().email().unique(),
role: field.text().enum(['user', 'admin']).default('user'),
token: field.text().encrypted(),
meta: field.json().default({}),
password: field.text().hidden(),
version: field.integer().default(0)
}
});Available field types:
field.integer()field.text()field.real()field.boolean()field.json()field.blob()
Available field validators/modifiers:
.required().notNull().nullable().unique().default(value).hidden().references(table, column).min(n).max(n).email().regex(regexp).enum(values).encrypted()
Models
Define a model
const User = defineModel(db, 'users', {
fields: {
name: field.text().required(),
email: field.text().required().email()
},
timestamps: true,
softDelete: true,
json: ['meta'],
hidden: ['password'],
computed: {
displayName: user => `${user.name} <${user.email}>`
},
validate: {
email: v => String(v).includes('@') || 'email invalid'
},
scopes: {
active: q => q.where('active', '=', 1)
}
});Create/find/update/delete
const user = User.create({ name: 'Adit', email: '[email protected]' });
const same = User.find(user.id);
User.query()
.where('id', '=', user.id)
.update({ name: 'Adit Baru' });
User.delete(user.id); // soft delete if enabled
User.restore(user.id); // restore soft-deleted row
User.delete(user.id, true); // force deleteBulk insert
const users = User.insertMany([
{ name: 'A', email: '[email protected]' },
{ name: 'B', email: '[email protected]' }
]);Upsert
User.upsert(
{ email: '[email protected]', name: 'A Updated' },
['email'],
['name']
);Query-builder form:
User.query()
.insert({ email: '[email protected]', name: 'A' })
.onConflict('email')
.merge(['name']);
User.query()
.insert({ email: '[email protected]', name: 'A' })
.onConflict('email')
.ignore();Model instances and dirty tracking
Rows returned from models include non-enumerable helpers.
const user = User.find(1);
user.name = 'Adit Baru';
console.log(user.getChanges());
// { name: 'Adit Baru' }
user.save();
user.reload();
user.delete();
user.restore();
console.log(user.toJSON());Optimistic locking
Use a version column and enable optimisticLock.
const User = defineModel(db, 'users', {
fields: {
name: field.text(),
version: field.integer().default(0)
},
optimisticLock: true
});
const user = User.find(1);
user.name = 'New Name';
user.save();If another writer changes the version before save(), errors.ConflictError is thrown.
Hidden and computed fields
const User = defineModel(db, 'users', {
hidden: ['password', 'token'],
computed: {
label: u => `${u.name}<${u.email}>`
}
});
const user = User.find(1);
console.log(user.toJSON());Hidden fields are excluded from toJSON().
Query Builder
Basic select
const rows = User.query()
.select(['users.id', 'users.email'])
.where('users.email', 'LIKE', '%@test.local')
.orderBy('users.id', 'desc')
.limit(20)
.offset(0)
.get();First row
const user = User.query()
.where('email', '=', '[email protected]')
.first();Count
const total = User.query().where('role', '=', 'admin').count();Grouped conditions
const rows = User.query()
.where(q => q
.where('role', '=', 'admin')
.orWhere('email', 'LIKE', '%@company.local')
)
.whereBetween('age', 18, 60)
.get();Supported filters
where(column, op, value)orWhere(column, op, value)where(q => ...)orWhere(q => ...)whereNot(column, op, value)whereIn(column, values)whereNull(column)whereBetween(column, a, b)whereExists(subquery, params)whereJson(path, op, value)
JSON query
User.query()
.whereJson('meta.tier', '=', 'pro')
.get();With table-qualified column:
User.query()
.whereJson('users.meta.tier', '=', 'pro')
.get();Joins
const rows = User.query()
.select(['users.id', 'users.name', 'profiles.avatar'])
.leftJoin('profiles', 'profiles.user_id', '=', 'users.id')
.where('users.id', '>', 0)
.get();Group and having
const rows = User.query()
.select(['role', 'COUNT(*) AS total'])
.groupBy('role')
.having('COUNT(*) > ?', [1])
.get();Distinct
const roles = User.query()
.distinct()
.select(['role'])
.get();Update/delete from query
User.query()
.where('role', '=', 'guest')
.update({ role: 'user' });
User.query()
.where('deleted_at', 'IS NOT', null)
.delete(true);Soft delete helpers
User.query().get(); // excludes soft-deleted rows
User.query().withDeleted().get();
User.query().onlyDeleted().get();Scopes
const User = defineModel(db, 'users', {
scopes: {
admins: q => q.where('role', '=', 'admin'),
adults: q => q.where('age', '>=', 18)
}
});
const rows = User.query()
.scope('admins')
.scope('adults')
.get();Cursor pagination
const page = User.query()
.orderBy('id', 'asc')
.cursorPaginate({ limit: 20, column: 'id' });
console.log(page.data);
console.log(page.nextCursor);
console.log(page.hasMore);
const next = User.query()
.orderBy('id', 'asc')
.cursorPaginate({ after: page.nextCursor, limit: 20, column: 'id' });Query cache
const rows = User.query()
.where('role', '=', 'admin')
.cache(5000)
.get();
db.clearCache();Relationships
Register related models with the same Database instance.
hasMany
const User = defineModel(db, 'users', {
relations: {
posts: { type: 'hasMany', model: 'posts', foreignKey: 'user_id' }
}
});
const Post = defineModel(db, 'posts', {
relations: {
user: { type: 'belongsTo', model: 'users', foreignKey: 'user_id' }
}
});
const users = User.query().with('posts').get();hasOne
const User = defineModel(db, 'users', {
relations: {
profile: { type: 'hasOne', model: 'profiles', foreignKey: 'user_id' }
}
});
const users = User.query().with('profile').get();belongsTo
const Post = defineModel(db, 'posts', {
relations: {
user: { type: 'belongsTo', model: 'users', foreignKey: 'user_id' }
}
});
const post = Post.query().with('user').first();belongsToMany
db.schema.createTable('role_user', t => {
t.integer('user_id').notNull().references('users', 'id');
t.integer('role_id').notNull().references('roles', 'id');
t.unique(['user_id', 'role_id']);
});
const User = defineModel(db, 'users', {
relations: {
roles: {
type: 'belongsToMany',
model: 'roles',
pivot: 'role_user',
foreignPivotKey: 'user_id',
relatedPivotKey: 'role_id'
}
}
});
const Role = defineModel(db, 'roles', {
relations: {
users: {
type: 'belongsToMany',
model: 'users',
pivot: 'role_user',
foreignPivotKey: 'role_id',
relatedPivotKey: 'user_id'
}
}
});
const user = User.query().with('roles').first();Constrained eager loading
const user = User.query()
.with('posts', q => q.where('published', '=', 1).limit(5))
.first();Relation counts
const users = User.query()
.withCount('posts')
.get();
console.log(users[0].posts_count);Migrations
Inline migrations
const migrations = [
{
id: '001_create_users',
up(db) {
db.schema.createTable('users', t => {
t.increments('id');
t.text('email').notNull().unique();
});
},
down(db) {
db.schema.dropTable('users');
}
}
];
db.migrate(migrations);
db.rollbackMigrations(1);Migrations are tracked in _migrations and only run once.
Generate migration file
const diff = db.schema.diff('users', {
phone: field.text().nullable()
});
const migrationPath = db.schema.generateMigration('add_phone_to_users', diff, './migrations');
console.log(migrationPath);Validation
Field validation
const User = defineModel(db, 'users', {
fields: {
email: field.text().required().email(),
username: field.text().required().min(3).max(20).regex(/^[a-z0-9_]+$/),
role: field.text().enum(['user', 'admin']).default('user')
}
});Custom validation
const User = defineModel(db, 'users', {
validate: {
email: value => String(value).includes('@') || 'email invalid',
age: value => Number(value) >= 18 || 'age must be >= 18'
}
});Validation errors throw errors.ValidationError.
try {
User.create({ email: 'broken' });
} catch (err) {
if (err instanceof errors.ValidationError) {
console.error(err.message);
}
}Hooks
User.hook('beforeCreate', row => {
row.email = row.email.toLowerCase();
});
User.hook('afterCreate', row => {
console.log('created', row.id);
});
User.hook('beforeUpdate', row => {
row.updated_by = 'system';
});Built-in hook names used by the model layer:
beforeCreateafterCreatebeforeUpdate
Custom hook names can also be registered for plugins or userland conventions.
JSON fields
Schema:
db.schema.createTable('users', t => {
t.increments('id');
t.json('meta');
});Model:
const User = defineModel(db, 'users', {
fields: {
meta: field.json().default({})
},
json: ['meta']
});Usage:
User.create({ meta: { tier: 'pro', flags: ['a', 'b'] } });
const rows = User.query()
.whereJson('meta.tier', '=', 'pro')
.get();
console.log(rows[0].meta.tier);Encrypted fields
Encrypted fields use Node built-in crypto with AES-256-GCM.
const db = new Database('app.sqlite', {
encryptionKey: Buffer.from('01234567890123456789012345678901')
});
const User = defineModel(db, 'users', {
fields: {
token: field.text().encrypted()
}
});
const user = User.create({ token: 'secret-token' });
console.log(User.find(user.id).token); // secret-tokenThe raw SQLite value is stored with an enc: prefix and decrypted during hydration.
Audit logs
Enable audit logging:
db.audit.enable({
actor: () => currentUserId
});This creates audit_logs by default:
CREATE TABLE audit_logs (
id INTEGER PRIMARY KEY AUTOINCREMENT,
table_name TEXT,
row_id TEXT,
action TEXT,
old_values TEXT,
new_values TEXT,
actor_id TEXT,
created_at TEXT DEFAULT CURRENT_TIMESTAMP
)Tracked actions:
createupsertdeleteforceDeleterestore
Custom table name:
db.audit.enable({
table: 'my_audit_logs',
actor: () => 'system'
});Full Text Search / FTS5
db.fts.create('posts_search', {
columns: ['title', 'body']
});
db.fts.insert('posts_search', {
title: 'SQLite ORM Native',
body: 'fast local first database'
});
const results = db.fts.search('posts_search', 'native');
console.log(results);Introspection
console.log(db.inspect.tables());
console.log(db.inspect.columns('users'));
console.log(db.inspect.indexes('users'));
console.log(db.inspect.foreignKeys('posts'));Seeder and factory
Factory
db.factory(User, i => ({
name: `User ${i}`,
email: `user${i}@test.local`
})).createMany(100);Seeder
db.seed([
() => User.insertMany([
{ name: 'A', email: '[email protected]' },
{ name: 'B', email: '[email protected]' }
]),
() => Post.create({ user_id: 1, title: 'Hello' })
]);Export and import
JSON
db.export.json('users', 'users.json');
db.import.json('users_copy', 'users.json');CSV
db.export.csv('users', 'users.csv');CSV import is not currently implemented; JSON import is implemented.
Repository helper
class UserRepo {
constructor(model, db) {
this.model = model;
this.db = db;
}
findByEmail(email) {
return this.model.query().where('email', '=', email).first();
}
}
const users = db.repo(User, UserRepo);
console.log(users.findByEmail('[email protected]'));Error classes
const { errors } = require('@ghuts/liteorm');Available classes:
errors.ORMErrorerrors.ValidationErrorerrors.QueryErrorerrors.MigrationErrorerrors.ConflictErrorerrors.NotFoundErrorerrors.SQLiteBusyError
Example:
try {
User.create({ email: 'broken' });
} catch (err) {
if (err instanceof errors.ValidationError) {
console.error('validation failed', err.message);
}
}CLI
After install:
lite-orm <command>From project source:
node bin/lite-orm.js <command>init
lite-orm init .Creates:
migrations/orm.config.js
inspect
lite-orm inspect app.sqlitePrints tables and columns.
make:migration
lite-orm make:migration create_users_table --dir migrationsCreates a migration file template.
studio non-interactive SQL
lite-orm studio app.sqlite --exec "SELECT COUNT(*) AS n FROM users"Prints JSON rows.
export JSON
lite-orm export:json app.sqlite users users.jsonExports the table to JSON.
doctor
lite-orm doctorChecks the Node version, package metadata, platform/architecture support, native addon loading, SQLite version, JSON1, FTS5, and temp directory write access.
Runnable examples
The npm package includes runnable examples. From a source checkout after building:
npm run build
node examples/todo/index.js
node examples/blog/index.js
node examples/auth/index.jsRun all examples:
npm run test:examplesUse a persistent database file by setting LITEORM_DB:
LITEORM_DB=./todo.sqlite node examples/todo/index.jsSee also:
docs/examples.mddocs/v1.1.mddocs/package-readiness.md
TypeScript example
import { Database, defineModel, field } from '@ghuts/liteorm';
type UserRow = {
id: number;
name: string;
email: string;
role: string;
version: number;
};
const db = new Database('app.sqlite');
const User = defineModel<UserRow>(db, 'users', {
fields: {
name: field.text().required(),
email: field.text().required().email(),
role: field.text().default('user'),
version: field.integer().default(0)
},
optimisticLock: true
});
const user = User.create({
name: 'Adit',
email: '[email protected]'
});
const found = User.query()
.where('email', '=', '[email protected]')
.first();Complete blog example
const { Database, defineModel, field } = require('@ghuts/liteorm');
const db = new Database('blog.sqlite');
db.tune({ journalMode: 'WAL', synchronous: 'NORMAL', busyTimeout: 5000 });
db.schema.createTable('users', t => {
t.increments('id');
t.text('name').notNull();
t.text('email').notNull().unique();
t.text('password').notNull();
t.integer('version').default(0);
t.timestamps();
t.softDeletes();
});
db.schema.createTable('posts', t => {
t.increments('id');
t.integer('user_id').notNull().references('users', 'id');
t.text('title').notNull();
t.text('body');
t.json('meta');
t.timestamps();
t.softDeletes();
});
const User = defineModel(db, 'users', {
fields: {
name: field.text().required().min(2),
email: field.text().required().email(),
password: field.text().hidden(),
version: field.integer().default(0)
},
timestamps: true,
softDelete: true,
optimisticLock: true,
hidden: ['password'],
relations: {
posts: { type: 'hasMany', model: 'posts', foreignKey: 'user_id' }
}
});
const Post = defineModel(db, 'posts', {
fields: {
user_id: field.integer().required(),
title: field.text().required(),
body: field.text(),
meta: field.json().default({})
},
timestamps: true,
softDelete: true,
json: ['meta'],
relations: {
user: { type: 'belongsTo', model: 'users', foreignKey: 'user_id' }
}
});
const user = User.create({
name: 'Adit',
email: '[email protected]',
password: 'secret'
});
Post.insertMany([
{ user_id: user.id, title: 'Hello SQLite', body: 'Native ORM', meta: { tags: ['sqlite'] } },
{ user_id: user.id, title: 'FTS5 Search', body: 'Fast local search', meta: { tags: ['search'] } }
]);
const loaded = User.query()
.with('posts')
.withCount('posts')
.where('id', '=', user.id)
.first();
console.log(loaded.toJSON());
console.log(loaded.posts_count);
console.log(loaded.posts.map(p => p.title));Package structure
lite-orm/
bin/
lite-orm.js CLI
lib/
index.js ORM JavaScript layer
src/
addon.cc Native C++ SQLite addon
types/
index.d.ts TypeScript declarations
examples/ runnable examples
docs/ release and package docs
deps/sqlite/ vendored SQLite amalgamation
binding.gyp node-gyp build config
README.md
LICENSE
package.jsonDevelopment
git clone <repo>
cd lite-orm
npm install
npm run build
npm testRun tests:
npm testBuild native addon:
npm run buildCreate package tarball:
npm packPublish
The package is prepared for npm publish as v1.2.0.
Pre-publish validation:
npm run build
npm test
npm pack --dry-run
npm publish --dry-run --access publicPublish:
npm publish --access publicVerify registry:
npm view @ghuts/liteorm versionExpected output:
1.2.0Smoke test from tarball
cd lite-orm
PACK_DIR="$(mktemp -d)"
SMOKE_DIR="$(mktemp -d)"
npm pack --pack-destination "$PACK_DIR"
PKG_PATH="$(node -e "const fs=require('fs'),path=require('path'); const d=process.argv[1]; const f=fs.readdirSync(d).find(x=>x.endsWith('.tgz')); if(!f) throw new Error('tarball not found'); console.log(path.join(d,f));" "$PACK_DIR")"
cd "$SMOKE_DIR"
npm init -y
npm install "$PKG_PATH"
node - <<'NODE'
const { Database, defineModel, field } = require('@ghuts/liteorm');
const db = new Database(':memory:');
db.schema.createTable('users', t => {
t.increments('id');
t.text('email').notNull().unique();
t.text('name');
});
const User = defineModel(db, 'users', {
fields: {
email: field.text().email().required(),
name: field.text().min(2)
}
});
User.create({ email: '[email protected]', name: 'Smoke' });
console.log(User.query().count());
NODEExpected output:
1Current verification status
Last verified in this project:
npm run build: pass
npm test: all tests pass
npm run test:types: pass
npm run test:examples: pass
npm pack --dry-run: pass
npm publish --dry-run --access public: pass
smoke install from ghuts-liteorm-1.2.0.tgz: passNotes and implementation details
- Runtime npm dependencies: none.
- Native addon builds against the vendored SQLite amalgamation in
deps/sqlite/. db.prepare()uses native SQLite prepared statements with explicit finalization and statement-cache support.db.async.*is Promise-compatible but uses the current synchronous native backend internally.- JSON support uses SQLite JSON1 functions for
whereJson. - FTS support requires SQLite compiled with FTS5.
- Encryption uses Node built-in
cryptoand AES-256-GCM.
Maintainer
Maintained by Lsow: https://github.com/yeweroooo
Repository: https://github.com/yeweroooo/lite-orm
License
MIT
