Skip to content

Node API

Complete API reference for the @tabula-lens/node package.

Terminal window
npm i @tabula-lens/node

You must also install the database driver for your chosen database engine:

Database Driver package
PostgreSQL / CockroachDB pg
MySQL / MariaDB mysql2
SQLite better-sqlite3
SQL Server tedious

Example for PostgreSQL:

Terminal window
npm i @tabula-lens/node pg

The main class for backend database querying and HTTP API implementation.

new TabulaLens(config: string | TabulaLensConfig, options?: TabulaLensOptions)

Creates a new TabulaLens instance with the specified database connection and options. Supports both the legacy string form and the new config-object form.

Parameter Type Required Description
config string | TabulaLensConfig Yes Database connection string or config object
options TabulaLensOptions No Configuration options (only used when config is a string)
interface TabulaLensConfig {
url: string;
type?: DatabaseType;
logger?: Logger;
logLevel?: LogLevel;
enableQueryLogging?: boolean;
enableRequestLogging?: boolean;
sensitiveDataMasking?: boolean;
logFormat?: 'json' | 'text' | 'pretty';
}
Option Type Required Default Description
url string Yes - Database connection string or file path
type DatabaseType No Auto-detected Database type ('pg', 'mysql', 'sqlite', 'mssql')
logger Logger No Default logger Custom logger instance
logLevel LogLevel No - Log level: 'error' | 'warn' | 'info' | 'debug' | 'silent'
enableQueryLogging boolean No true Enable query-level logging
enableRequestLogging boolean No true Enable request-level logging
sensitiveDataMasking boolean No true Mask sensitive data (like database URLs) in logs
logFormat 'json' | 'text' | 'pretty' No - Log output format
type DatabaseType = 'pg' | 'mysql' | 'sqlite' | 'mssql';

Represents the supported database engines. The value is auto-detected from the connection URL when omitted.

Option Type Default Description
logger Logger - Custom logger instance (if not provided, default logger is created)
logLevel LogLevel - Log level: 'error' | 'warn' | 'info' | 'debug' | 'silent'
enableQueryLogging boolean true Enable query-level logging
enableRequestLogging boolean true Enable request-level logging
sensitiveDataMasking boolean true Mask sensitive data (like database URLs) in logs
logFormat 'json' | 'text' | 'pretty' - Log output format

String form (legacy, still supported):

import { TabulaLens } from '@tabula-lens/node';
const tabulaLens = new TabulaLens('postgresql://user:password@localhost:5432/mydb', {
logLevel: 'info',
enableQueryLogging: true,
enableRequestLogging: true,
sensitiveDataMasking: true,
logFormat: 'pretty'
});

Config-object form:

import { TabulaLens } from '@tabula-lens/node';
const tabulaLens = new TabulaLens({
url: 'mysql://user:password@localhost:3306/mydb',
type: 'mysql', // optional — auto-detected from URL
logLevel: 'info',
enableQueryLogging: true,
sensitiveDataMasking: true,
});

Auto-detection from a file path:

import { TabulaLens } from '@tabula-lens/node';
const tabulaLens = new TabulaLens({
url: './data.sqlite',
// type: 'sqlite' is auto-detected
});
async query(options: QueryOptions): Promise<QueryResult>

Executes a database query based on the provided parameters.

Parameter Type Required Default Description
table string No 'users' Table name to query
page number No 1 Page number (1-indexed)
limit number No 10 Number of rows per page
sort string No - Sort specification (format: column:direction,column:direction)
filter string No - Filter string for searching across text columns
columns string[] No - Specific columns to return
filterColumns string[] No - Specific columns to filter (comma-separated)

Promise<QueryResult> - The query result containing data and metadata.

Field Type Description
data Record<string, unknown>[] Array of data records
columns string[] Array of column names
pagination object Pagination metadata
pagination.page number Current page number
pagination.limit number Number of records per page
pagination.total number Total number of records
pagination.totalPages number Total number of pages
const result = await tabulaLens.query({
table: 'users',
page: 1,
limit: 25,
filter: 'john',
filterColumns: ['name', 'email'],
sort: 'created_at:desc',
columns: ['id', 'name', 'email', 'created_at']
});
console.log(result.data);
console.log(result.pagination);
async handle(context: RequestContext): Promise<ResponseContext>

Handles an HTTP request and returns a response context. This is the main method used by framework adapters.

Parameter Type Required Description
context RequestContext Yes HTTP request context
Field Type Description
method string HTTP method (GET, POST, etc.)
path string Request path
query Record<string, string> Query parameters
body unknown Request body (optional)

Promise<ResponseContext> - HTTP response context.

Field Type Description
status number HTTP status code
headers Record<string, string> Response headers
body unknown Response body
// Query data — path must be '/query' (the subpath after the mount point)
const response = await tabulaLens.handle({
method: 'GET',
path: '/query',
query: { table: 'users', page: '1', limit: '25' }
});
console.log(response.status); // 200
console.log(response.body); // Query result data
// List tables
const tablesResponse = await tabulaLens.handle({
method: 'GET',
path: '/tables',
query: {}
});
console.log(tablesResponse.body); // ['users', 'products', ...]
getLogger(): Logger

Returns the logger instance used by this TabulaLens instance.

Logger - The logger instance.

const logger = tabulaLens.getLogger();
logger.info('Custom log message', { customData: 'value' });
async getTables(): Promise<string[]>

Returns a list of all tables in the database.

Promise<string[]> - Array of table names.

const tables = await tabulaLens.getTables();
console.log('Available tables:', tables);
async getFilterableColumns(table: string): Promise<string[]>

Returns a list of text-based columns that can be used for filtering in the specified table.

Parameter Type Required Description
table string Yes Table name

Promise<string[]> - Array of filterable column names.

const filterableColumns = await tabulaLens.getFilterableColumns('users');
console.log('Filterable columns:', filterableColumns);
// Output: ['name', 'email', 'status', ...]

Custom error class for Tabula Lens-specific errors.

constructor(statusCode: number, code: string, message: string, details?: unknown)
Parameter Type Required Description
statusCode number Yes HTTP status code
code string Yes Machine-readable error code
message string Yes Human-readable error message
details unknown No Additional error details
import { TabulaLensError } from '@tabula-lens/node';
throw new TabulaLensError(
404,
'TABLE_NOT_FOUND',
'Table does not exist',
{ table: 'users' }
);
interface Logger {
error(message: string, context?: LogContext): void;
warn(message: string, context?: LogContext): void;
info(message: string, context?: LogContext): void;
debug(message: string, context?: LogContext): void;
}
interface LogContext {
component?: string;
operation?: string;
requestId?: string;
userId?: string;
table?: string;
query?: Record<string, unknown>;
error?: Error | string;
stack?: string;
timestamp?: string;
[key: string]: unknown;
}
type LogLevel = 'error' | 'warn' | 'info' | 'debug' | 'silent';
interface LoggerOptions {
level?: LogLevel;
includeStack?: boolean;
includeTimestamp?: boolean;
colorize?: boolean;
format?: 'json' | 'text' | 'pretty';
}
function createLogger(options?: LoggerOptions): Logger

Creates a new logger instance with the specified options.

import { createLogger } from '@tabula-lens/node';
const logger = createLogger({
level: 'debug',
format: 'pretty',
colorize: true,
includeTimestamp: true,
includeStack: false
});
logger.info('Application started', { port: 3000 });
function generateId(): string

Generates a unique ID for request tracking.

string - A unique identifier.

import { generateId } from '@tabula-lens/node';
const requestId = generateId();
console.log(requestId); // e.g., "a1b2c3d4"
function maskSensitiveData(data: string): string

Masks sensitive data (like database connection strings) for logging.

Parameter Type Required Description
data string Yes Data to mask

string - Masked data.

import { maskSensitiveData } from '@tabula-lens/node';
const connectionString = 'postgresql://user:password@localhost:5432/mydb';
const masked = maskSensitiveData(connectionString);
console.log(masked); // "postgresql://user:****@localhost:5432/mydb"
function detectDatabaseType(url: string): DatabaseType

Detects the database type from a connection URL or file path. TabulaLens calls this internally when the type field is omitted, but you can use it directly for debugging or validation.

Parameter Type Required Description
url string Yes Database connection URL or file path

DatabaseType - The detected database type ('pg', 'mysql', 'sqlite', or 'mssql').

Pattern Detected type Example
postgresql://, postgres://, pgsql:// pg postgresql://localhost/mydb
mysql://, mysql2://, mysqlx://, mariadb:// mysql mysql://localhost/mydb
sqlite://, sqlite:, file:, :memory:, paths ending in .db / .sqlite / .sqlite3 / .db3 sqlite ./data.sqlite
mssql://, sqlserver://, mssql+tcp://, mssql+udp:// mssql mssql://localhost/mydb
import { detectDatabaseType } from '@tabula-lens/node';
const type = detectDatabaseType('mysql://user:password@localhost:3306/mydb');
console.log(type); // 'mysql'
function validateDatabaseType(type: string): DatabaseType

Validates that a string is a supported database type. Returns the type narrowed to DatabaseType, or throws a TabulaLensError for unsupported values.

Parameter Type Required Description
type string Yes Database type string to validate

DatabaseType - The validated database type.

import { validateDatabaseType } from '@tabula-lens/node';
try {
validateDatabaseType('sqlite'); // 'sqlite'
validateDatabaseType('oracle'); // throws TabulaLensError
} catch (error) {
// Handle invalid database type
}

Tabula Lens provides adapters for 15+ Node.js frameworks. Each adapter implements the HTTP API contract using framework-specific patterns.

import express from 'express';
import { TabulaLens, expressAdapter } from '@tabula-lens/node';
const app = express();
const tabulaLens = new TabulaLens(process.env.DATABASE_URL);
// Mount at /api/tabula-lens — sub-routes (/query, /tables, /tables/:table) are handled internally
app.use('/api/tabula-lens', expressAdapter(tabulaLens));
app.listen(3000);
import express from 'express';
import { TabulaLens, express4Adapter } from '@tabula-lens/node';
const app = express();
const tabulaLens = new TabulaLens(process.env.DATABASE_URL);
app.use('/api/tabula-lens', express4Adapter(tabulaLens));
app.listen(3000);
import Fastify from 'fastify';
import { TabulaLens, fastifyAdapter } from '@tabula-lens/node';
const fastify = Fastify();
const tabulaLens = new TabulaLens(process.env.DATABASE_URL);
fastify.all('/api/tabula-lens/*', fastifyAdapter(tabulaLens));
fastify.listen({ port: 3000 });
import Koa from 'koa';
import { TabulaLens, koaAdapter } from '@tabula-lens/node';
const app = new Koa();
const tabulaLens = new TabulaLens(process.env.DATABASE_URL);
// Koa adapter passes ctx.path directly to handle(), so you need to mount
// it via a router or filter by path prefix in middleware
app.use(koaAdapter(tabulaLens));
app.listen(3000);
import Hapi from '@hapi/hapi';
import { TabulaLens, hapiAdapter } from '@tabula-lens/node';
const server = Hapi.server({ port: 3000 });
const tabulaLens = new TabulaLens(process.env.DATABASE_URL);
server.route({
method: 'GET',
path: '/api/tabula-lens/{path*}',
handler: hapiAdapter(tabulaLens),
});
await server.start();
import restify from 'restify';
import { TabulaLens, restifyAdapter } from '@tabula-lens/node';
const server = restify.createServer();
const tabulaLens = new TabulaLens(process.env.DATABASE_URL);
server.get('/api/tabula-lens/*', restifyAdapter(tabulaLens));
server.listen(3000);
// app/api/tabula-lens/[...path]/route.ts (App Router)
import { TabulaLens, createNextRouteHandler } from '@tabula-lens/node';
const tabulaLens = new TabulaLens(process.env.DATABASE_URL);
const handler = createNextRouteHandler(tabulaLens);
export { handler as GET };
import { TabulaLens, createTanStackStartHandler } from '@tabula-lens/node';
const tabulaLens = new TabulaLens(process.env.DATABASE_URL);
const handler = createTanStackStartHandler(tabulaLens);
export const APIRoute = createAPIFileRoute('/api/tabula-lens/$')({
GET: ({ request }) => handler(request),
});
// app/routes/api.tabula-lens.$.ts
import { TabulaLens, createRemixHandler } from '@tabula-lens/node';
const tabulaLens = new TabulaLens(process.env.DATABASE_URL);
const handler = createRemixHandler(tabulaLens);
export const loader = ({ request }: { request: Request }) => handler(request);
src/routes/api/tabula-lens/[...path]/+server.ts
import { TabulaLens, createSvelteKitHandler } from '@tabula-lens/node';
const tabulaLens = new TabulaLens(process.env.DATABASE_URL);
const handler = createSvelteKitHandler(tabulaLens);
export const GET = (event: { request: Request; url: URL }) => handler(event);
import { Hono } from 'hono';
import { TabulaLens, createHonoMiddleware } from '@tabula-lens/node';
const app = new Hono();
const tabulaLens = new TabulaLens(process.env.DATABASE_URL);
app.all('/api/tabula-lens/*', createHonoMiddleware(tabulaLens));
export default app;
import { Elysia } from 'elysia';
import { TabulaLens, createElysiaHandler } from '@tabula-lens/node';
const app = new Elysia();
const tabulaLens = new TabulaLens(process.env.DATABASE_URL);
app.all('/api/tabula-lens/*', createElysiaHandler(tabulaLens));
app.listen(3000);
routes/api/tabula-lens/[...path].ts
import { TabulaLens, createFreshHandler } from '@tabula-lens/node';
const tabulaLens = new TabulaLens(process.env.DATABASE_URL);
const handler = createFreshHandler(tabulaLens);
export const handlers = { GET: (req: Request) => handler(req) };
import http from 'http';
import { TabulaLens, nativeAdapter } from '@tabula-lens/node';
const tabulaLens = new TabulaLens(process.env.DATABASE_URL);
const handler = nativeAdapter(tabulaLens);
http.createServer(handler).listen(3000);
  • Traditional: Express (4.x & 5.x), Fastify, Koa, Hapi, Restify
  • Modern: Next.js, TanStack Start, Remix, SvelteKit
  • Edge: Hono, Elysia, Fresh
  • Native: Native adapter for custom implementations
export type {
QueryOptions,
QueryResult,
RequestContext,
ResponseContext,
SortOption,
FilterOption,
TabulaLensOptions,
TabulaLensConfig,
DatabaseType,
Logger,
LogContext,
LogLevel,
LoggerOptions,
DialectStrategy,
ColumnInfo
};

The dialect strategy system provides database-specific operations for each supported database engine. This is used internally by TabulaLens but can also be used directly for advanced use cases.

interface DialectStrategy {
getTables(db: Knex): Promise<string[]>;
getColumns(db: Knex, table: string): Promise<ColumnInfo[]>;
getFilterableTypes(): string[];
getLikeOperator(): 'LIKE' | 'ILIKE';
}
Method Returns Description
getTables(db) Promise<string[]> Get all table names in the database
getColumns(db, table) Promise<ColumnInfo[]> Get column metadata for a specific table
getFilterableTypes() string[] Get data type names that support text filtering
getLikeOperator() 'LIKE' | 'ILIKE' Get the LIKE operator for case-insensitive matching
interface ColumnInfo {
name: string;
type: string;
}

Represents column metadata returned by dialect implementations.

Property Type Description
name string Column name
type string Data type (e.g., 'integer', 'character varying', 'text')
function createDialect(type: DatabaseType): DialectStrategy

Factory function to create a dialect strategy instance based on database type.

Parameter Type Required Description
type DatabaseType Yes Database type ('pg', 'mysql', 'sqlite', 'mssql')

A DialectStrategy instance for the specified database type.

import { createDialect } from '@tabula-lens/node';
import { DatabaseType } from '@tabula-lens/node';
// Create a PostgreSQL dialect
const postgresDialect = createDialect('pg');
// Create a MySQL dialect
const mysqlDialect = createDialect('mysql');
// Use the dialect
const tables = await postgresDialect.getTables(knexInstance);
const columns = await postgresDialect.getColumns(knexInstance, 'users');
const filterableTypes = postgresDialect.getFilterableTypes();
const likeOperator = postgresDialect.getLikeOperator(); // 'ILIKE' for PostgreSQL

You can also use the dialect classes directly if needed:

import { PostgresDialect, MySQLDialect, SQLiteDialect, MSSQLDialect } from '@tabula-lens/node';
// Use PostgreSQL dialect directly
const postgresDialect = new PostgresDialect();
const tables = await postgresDialect.getTables(knexInstance);

Each dialect implements the DialectStrategy interface with database-specific behavior:

Database LIKE Operator Filterable Types Example
PostgreSQL ILIKE (case-insensitive) ['character varying', 'text', 'varchar', 'char', 'character', 'uuid']
MySQL LIKE (case-insensitive by default) ['varchar', 'text', 'tinytext', 'mediumtext', 'longtext', 'char']
SQLite LIKE (case-insensitive by default) ['TEXT', 'text']
SQL Server LIKE (case-insensitive by default) ['varchar', 'nvarchar', 'text', 'char', 'nchar']

The dialect strategy system is useful for:

  • Building custom database introspection tools
  • Implementing custom query builders
  • Creating database-specific migrations
  • Building admin panels with dynamic column filtering
  • Implementing type-safe database operations

For most use cases, you don’t need to interact with dialects directly — TabulaLens handles this internally. The dialect API is primarily for advanced scenarios requiring direct database introspection.

import { TabulaLens, expressAdapter, createLogger } from '@tabula-lens/node';
import express from 'express';
// Create custom logger
const logger = createLogger({
level: 'info',
format: 'pretty',
colorize: true
});
// Initialize TabulaLens
const tabulaLens = new TabulaLens(process.env.DATABASE_URL, {
logger,
enableQueryLogging: true,
enableRequestLogging: true,
sensitiveDataMasking: true,
logFormat: 'pretty'
});
// Create Express app
const app = express();
// Add Tabula Lens endpoint (handles /query, /tables, /tables/:table sub-routes)
app.use('/api/tabula-lens', expressAdapter(tabulaLens));
// Start server
app.listen(3000, () => {
logger.info('Server started', { port: 3000 });
});