Skip to main content

Intro

Node OData Framework (TypeScript)

A powerful Node.js framework for building REST APIs with full OData v4 query capabilities. This framework provides a decorator-based approach to define models and automatically generates OData-compliant endpoints with advanced querying features.

Why This Package?

Building REST APIs with complex querying capabilities can be time-consuming and error-prone. Traditional approaches require you to manually implement filtering, sorting, pagination, and relationship expansion for each endpoint. This package solves these problems by:

  • Eliminating Boilerplate: Define your data models once using decorators, and get fully functional OData endpoints automatically
  • Type Safety: Built with TypeScript from the ground up, providing excellent IntelliSense and compile-time type checking
  • Framework Flexibility: Works with Express.js, Next.js, serverless functions, and any other Node.js framework
  • OData v4 Compliance: Supports standard OData query options ($filter, $select, $expand, $orderby, $top, $skip, $count) out of the box
  • Database Agnostic: Currently supports PostgreSQL, MySQL, SQLite, and other Sequelize-compatible databases
  • Developer Experience: Intuitive decorator-based API that feels natural to TypeScript developers

We created this package because existing OData solutions for Node.js were either too complex, lacked TypeScript support, or were tightly coupled to specific frameworks. Our goal was to provide a modern, flexible, and developer-friendly solution that works seamlessly across different Node.js environments.

Key Features

  • Decorator-Based Model Definition: Use TypeScript decorators to define your data models
  • Full OData v4 Query Support: $select, $filter, $expand, $orderby, $top, $skip, $count
  • Advanced Filter Capabilities: Comparison, logical, arithmetic operators, string/date/math functions
  • Powerful Expansion Features: Nested expansions (5+ levels), filters on relations, and more
  • Relationship Support: One-to-many, one-to-one, and many-to-one relationships
  • Multiple Integration Options: Express.js Router and OpenRouter for Next.js/serverless
  • OData Metadata Endpoint: Automatic $metadata endpoint for API discovery
  • Type-Safe Query Results: Full TypeScript support with proper type inference
  • Database Agnostic: PostgreSQL, MySQL, SQLite, MariaDB, MSSQL, Oracle
  • Webpack Compatible: Special handling for circular dependencies in bundled environments

Installation

npm install @phrasecode/odata

You'll also need to install a database driver. See the Installation Guide for details.

Quick Start

import {
Model,
Table,
Column,
DataTypes,
DataSource,
ExpressRouter,
ODataControler,
} from '@phrasecode/odata';
import express from 'express';

// Define a model
@Table({ tableName: 'users' })
class User extends Model<User> {
@Column({
dataType: DataTypes.INTEGER,
isPrimaryKey: true,
isAutoIncrement: true,
})
id: number;

@Column({ dataType: DataTypes.STRING })
name: string;

@Column({ dataType: DataTypes.STRING })
email: string;
}

// Create data source
const dataSource = new DataSource({
dialect: 'postgres',
database: 'mydb',
username: 'user',
password: 'password',
host: 'localhost',
port: 5432,
models: [User],
});

// Set up Express router
const app = express();
const userController = new ODataControler({
model: User,
allowedMethod: ['get'],
});
new ExpressRouter(app, { controllers: [userController], dataSource });

app.listen(3000);
// Now you can query: GET http://localhost:3000/User?$select=name,email&$filter=name eq 'John'
// Metadata endpoint: GET http://localhost:3000/$metadata

For more detailed examples, see the Quick Start Guide.

Documentation

🚀 Getting Started Guides

Choose your integration approach:

📚 Core Documentation

Quick Reference

OData Query Examples

# Select specific fields
GET /User?$select=name,email

# Filter results
GET /User?$filter=age gt 18 and status eq 'active'

# Expand relations
GET /User?$expand=department,orders

# Combine multiple options
GET /User?$filter=age gt 18&$expand=department&$select=name,email&$orderby=name asc&$top=20

# Advanced: Navigation property count
GET /Department?$filter=users/$count gt 5

# Advanced: Arithmetic expressions
GET /Order?$filter=((price mul quantity) sub discount) gt 1000

For complete query syntax and examples, see the OData Querying Guide.

Performance Tips

Connection Pooling

Critical for production! Connection pooling improves query performance by 10-15x:

const dataSource = new DataSource({
// ... other config
pool: {
max: 10,
min: 2,
idle: 10000,
},
});

Performance Impact:

  • Without pooling: 1000-1500ms per query
  • With pooling: 85-110ms per query

See the Best Practices Guide for more optimization tips.

Contributing

We welcome contributions! Please see CONTRIBUTING.md for guidelines.