UNPKG

dynamic-orm

Version:

A flexible and powerful dynamic ORM for SQL databases with Redis caching support and many-to-many relationship handling

241 lines (192 loc) 6.31 kB
# Dynamic ORM A flexible and powerful ORM for SQL databases with Redis caching support. ## Features - Fluent query builder with support for complex filtering and pagination - Support for table relationships with automatic JOIN generation - Redis caching for improved performance - Transaction support - TypeScript support with full type definitions ## Installation ```bash npm install dynamic-orm ``` ## Basic Usage ```javascript const { createORM } = require('dynamic-orm'); const { prepare, transaction } = require('your-database-module'); const redis = require('your-redis-module'); // Create ORM instance const orm = createORM({ db: { prepare, transaction }, // Your database adapter redis: redis, // Your Redis client useCache: true // Enable caching }); // Create a model for a specific table const userModel = orm.createModel('users', { primaryKey: 'id', searchableFields: ['firstName', 'lastName', 'email'], defaultLimit: 50, maxLimit: 500 }); // Now you can use the model to interact with the database async function example() { // Find all users with filtering, pagination, and sorting const result = await userModel.findAll({ filters: { role: 'admin', status: 'active', createdAt: { gt: '2023-01-01' } }, sort: { lastName: 'asc', firstName: 'asc' }, pagination: { page: 2, limit: 25 }, fields: ['id', 'firstName', 'lastName', 'email'], search: 'john' }); console.log(result.data); // Array of user objects console.log(result.pagination); // Pagination metadata // Find a user by ID const user = await userModel.findById('user-123'); // Find a user by email const userByEmail = await userModel.findByField('email', 'user@example.com'); // Create a new user const newUser = await userModel.create({ firstName: 'John', lastName: 'Doe', email: 'john@example.com' }); // Update a user const updatedUser = await userModel.update('user-123', { status: 'inactive' }); // Delete a user await userModel.delete('user-123'); // Count users const count = await userModel.count({ status: 'active' }); } ``` ## Advanced Usage ### Relationships You can fetch related data using the `relations` option: ```javascript const result = await userModel.findAll({ filters: { status: 'active' }, relations: [ { table: 'orders', foreignKey: 'userId', localKey: 'id', as: 'orders', type: 'many', // or 'left', 'inner', 'right' for JOIN types select: ['id', 'total', 'createdAt'], filters: { status: 'completed' } } ] }); // Result will include user records with their orders as nested objects console.log(result.data); ``` ### Many-to-Many Relationships For many-to-many relationships that use a junction table, use the `through` option: ```javascript // Example: Vehicles with their features through a junction table const result = await vehicleModel.findAll({ filters: { status: 'active' }, relations: [ { table: 'features', // Target table (features) foreignKey: 'id', // Primary key in the features table as: 'features', // Property name in the result select: ['id', 'name'], // Fields to select from features table through: 'vehicle_feature_links', // Junction table name throughLocalKey: 'stock_id', // FK in junction table that references the main table (vehicles) throughForeignKey: 'feature_id'// FK in junction table that references the related table (features) } ] }); // Each vehicle will have an array of features console.log(result.data[0].features); // [{id: 1, name: 'GPS'}, {id: 2, name: 'Bluetooth'}, ...] ``` This approach handles the two joins required for many-to-many relationships and properly organizes the results, avoiding duplicates. #### Simplified Arrays for Single Fields When you select just a single field from a many-to-many relationship, the ORM automatically simplifies the result to an array of values rather than an array of objects: ```javascript // Example: Getting just feature names as a simple array const result = await vehicleModel.findAll({ filters: { status: 'active' }, relations: [ { table: 'features', foreignKey: 'id', as: 'features', select: ['name'], // When selecting just one field, it returns a simplified array through: 'vehicle_feature_links', throughLocalKey: 'stock_id', throughForeignKey: 'feature_id' } ] }); // Each vehicle will have features as a simple array of strings console.log(result.data[0]); // Output: // { // stock_id: 'ABC123', // make: 'Toyota', // model: 'Camry', // features: ['GPS Navigation', 'Bluetooth', 'Backup Camera'] // } ``` This makes it easier to work with lists of related values when you only need a single property. ### Transactions Execute multiple operations in a transaction: ```javascript const result = await orderModel.withTransaction(async (tr) => { // Create the order const order = await tr.create({ customerId: 'cust-123', total: 99.99 }); // Add order items await tr.executeQuery( 'INSERT INTO order_items (order_id, product_id, quantity) VALUES (?, ?, ?)', [order.id, 'prod-456', 2] ); return order; }); ``` ### Custom Queries Execute raw SQL queries when needed: ```javascript const results = await userModel.executeQuery( 'SELECT id, email FROM users WHERE last_login > ? AND role = ?', ['2023-01-01', 'admin'] ); ``` ## TypeScript Support The package includes full TypeScript definitions: ```typescript import { createORM, Types } from 'dynamic-orm'; // Define your record type interface User { id: string; firstName: string; lastName: string; email: string; role: string; status: string; createdAt: string; } // Create strongly typed model const orm = createORM({ db, redis, useCache: true }); const userModel = orm.createModel<User>('users', { primaryKey: 'id', searchableFields: ['firstName', 'lastName', 'email'] }); // Now all queries will be properly typed const result = await userModel.findAll({ filters: { status: 'active' } }); // result.data will be User[] const users: User[] = result.data; ``` ## License MIT