permas-database-adapter
TypeScript icon, indicating that this package has built-in type declarations

0.1.5 • Public • Published

Permas Database Adapter

A flexible database adapter library that provides a unified interface for working with different database providers.

Supported Database Providers

The library supports the following database providers:

  1. MongoDB - Standard MongoDB database
  2. Azure Cosmos DB with MongoDB API - Azure Cosmos DB using the MongoDB API
  3. Azure Cosmos DB - Native Azure Cosmos DB using the Cosmos SDK
  4. AWS DynamoDB - Amazon DynamoDB
  5. Supabase - Supabase database

Features

  • Unified API for multiple database types
  • Type-safe with full TypeScript support
  • Validation using Zod schemas
  • Multi-database federation for distributing collections across different databases
  • Feature detection to check database capabilities
  • Browser compatible with appropriate security measures
  • Error handling with standardized error types

Installation

npm install permas-database-adapter

Usage

Basic Usage

const { createDatabaseAdapter, DatabaseProvider } = require('permas-database-adapter');

// Create a database adapter for MongoDB
const adapter = createDatabaseAdapter(DatabaseProvider.MONGODB, {
    uri: 'mongodb://localhost:27017/mydb',
    databaseName: 'mydb',
    options: {
        useNewUrlParser: true,
        useUnifiedTopology: true
    }
});

// Connect to the database
await adapter.connect();

// Create a document
const document = await adapter.create('users', {
    name: 'John Doe',
    email: 'john@example.com'
});

// Find documents
const users = await adapter.find('users', {
    filter: { name: 'John Doe' }
});

// Disconnect
await adapter.disconnect();

Azure Cosmos DB with MongoDB API

This library provides a specialized adapter for Azure Cosmos DB with MongoDB API that handles the specific requirements and limitations of Cosmos DB:

const { createDatabaseAdapter, DatabaseProvider } = require('permas-database-adapter');

// Method 1: Using the factory function with COSMOS_MONGODB provider
const adapter = createDatabaseAdapter(DatabaseProvider.COSMOS_MONGODB, {
    uri: 'mongodb://username:password@account.mongo.cosmos.azure.com:10255/?ssl=true&replicaSet=globaldb&retrywrites=false&maxIdleTimeMS=120000&appName=@account@',
    options: {
        useNewUrlParser: true,
        useUnifiedTopology: true,
        retryWrites: false,
        ssl: true
    }
});

// Method 2: Using the dedicated factory function
const { createCosmosMongoDBAdapter } = require('permas-database-adapter');
const adapter = createCosmosMongoDBAdapter({
    uri: 'mongodb://username:password@account.mongo.cosmos.azure.com:10255/?ssl=true&replicaSet=globaldb&retrywrites=false&maxIdleTimeMS=120000&appName=@account@',
    options: {
        useNewUrlParser: true,
        useUnifiedTopology: true,
        retryWrites: false,
        ssl: true
    }
});

Key features of the Cosmos MongoDB adapter:

  • Automatically uses the admin database as recommended by Microsoft
  • Sanitizes collection names for Cosmos DB compatibility
  • Intelligently handles MongoDB ObjectIds and string IDs
  • Optimizes queries for Cosmos DB's limitations
  • Safely handles complex update operations that might otherwise fail in Cosmos DB

Enhanced Array Update Operations

The adapter provides specialized methods to handle array operations that are commonly challenging with Cosmos DB:

// Update a specific array element using a compatible approach
await adapter.updateArrayField(
  'events',
  eventId,
  'sessions',               // array field name
  { title: 'Session X' },   // item identifier
  { duration: 90, room: 'A101' }  // update data
);

// Update all array elements in one operation
await adapter.updateAllArrayItems(
  'events',
  eventId,
  'sessions',
  { status: 'confirmed', lastUpdated: new Date() }
);

Smart Array Filter Alternative

For operations that would normally require array filters (which aren't supported in Cosmos DB), the adapter uses a fetch-modify-update pattern automatically:

// This operation would normally require array filters in MongoDB,
// but will work seamlessly with our adapter on Cosmos DB
await adapter.updateById('events', eventId, {
  complexNestedData: { ... },
  deeplyNestedArray: [ ... ],
  'deeply.nested.property': 'value'
});

Cosmos DB Limitations Handled

The adapter intelligently handles these Cosmos DB limitations:

  • No support for arrayFilters in updates
  • Complex update operators may cause conflicts
  • Limited transaction support
  • Specific requirements for indexing
  • Automatic detection and routing of complex operations through safer patterns

Azure Cosmos DB Native

For using the native Azure Cosmos DB SDK:

const { createDatabaseAdapter, DatabaseProvider } = require('permas-database-adapter');

const adapter = createDatabaseAdapter(DatabaseProvider.COSMOSDB, {
    endpoint: 'https://your-account.documents.azure.com:443/',
    key: 'your-primary-key',
    databaseId: 'mydb',
    partitionKey: '/id'
});

AWS DynamoDB

const { createDatabaseAdapter, DatabaseProvider } = require('permas-database-adapter');

const adapter = createDatabaseAdapter(DatabaseProvider.DYNAMODB, {
    region: 'us-east-1',
    tableName: 'my-table',
    credentials: {
        accessKeyId: 'your-access-key',
        secretAccessKey: 'your-secret-key'
    }
});

Supabase

const { createDatabaseAdapter, DatabaseProvider } = require('permas-database-adapter');

const adapter = createDatabaseAdapter(DatabaseProvider.SUPABASE, {
    url: 'https://your-project.supabase.co',
    apiKey: 'your-api-key',
    schema: 'public'
});

Multi-Database Federation

You can distribute collections across different databases:

import { createMultiDatabaseAdapter } from 'permas-database-adapter';

const db = createMultiDatabaseAdapter({
  // Primary database for all collections not explicitly mapped
  primary: {
    provider: 'mongodb',
    config: { uri: 'mongodb://localhost:27017/primary' }
  },
  
  // Collection-specific database mappings
  collections: {
    'users': {
      provider: 'mongodb',
      config: { uri: 'mongodb://localhost:27017/users' }
    },
    'logs': {
      provider: 'dynamodb',
      config: {
        region: 'us-east-1',
        credentials: {
          accessKeyId: 'YOUR_ACCESS_KEY',
          secretAccessKey: 'YOUR_SECRET_KEY'
        }
      }
    }
  }
});

Validation

The library uses Zod for validation of configuration and data:

import { mongodbConfigSchema, validateSchema } from 'permas-database-adapter';

// This will throw a detailed error if invalid
const validConfig = validateSchema(
  mongodbConfigSchema,
  {
    uri: 'mongodb://localhost:27017/mydb',
    options: { useNewUrlParser: true }
  },
  'Invalid MongoDB configuration'
);

Error Handling

All errors are standardized:

import { DatabaseAdapterError, DatabaseErrorType } from 'permas-database-adapter';

try {
  await db.findById('users', 'invalid-id');
} catch (error) {
  if (error instanceof DatabaseAdapterError) {
    console.log(error.type); // e.g., DatabaseErrorType.NOT_FOUND
    console.log(error.message); // Descriptive error message
    
    // Handle different error types
    switch (error.type) {
      case DatabaseErrorType.CONNECTION:
        // Handle connection errors
        break;
      case DatabaseErrorType.VALIDATION:
        // Handle validation errors
        break;
      // etc.
    }
  }
}

Browser Usage

For security reasons, direct database access from browsers is not recommended. However, you can use the library's types and validation utilities:

import { DatabaseAdapter } from 'permas-database-adapter';

// Define your API client that implements the DatabaseAdapter interface
class ApiClient implements DatabaseAdapter {
  // ...implement the methods by calling your backend API
}

Supported Database Features

Check if a specific feature is supported:

if (db.supportsFeature('transactions')) {
  // Use transactions
}

API Reference

DatabaseAdapter Interface

All database adapters implement the following interface:

interface DatabaseAdapter {
    // Connect to the database
    connect(): Promise<void>;
    
    // Disconnect from the database
    disconnect(): Promise<void>;
    
    // Check if connected to the database
    isConnected(): boolean;
    
    // Create a new item
    create<T>(collection: string, data: Partial<T>): Promise<T>;
    
    // Find items with optional filters and pagination
    find<T>(collection: string, options?: FindOptions): Promise<PaginatedResult<T>>;
    
    // Find a single item by ID
    findById<T>(collection: string, id: string): Promise<T | null>;
    
    // Find a single item by custom filter
    findOne<T>(collection: string, filter: Record<string, any>): Promise<T | null>;
    
    // Update an item by ID
    updateById<T>(collection: string, id: string, data: Partial<T>): Promise<T | null>;
    
    // Delete an item by ID
    deleteById(collection: string, id: string): Promise<boolean>;
    
    // Count documents matching a filter
    count(collection: string, filter?: Record<string, any>): Promise<number>;
    
    // Get the native client/driver for direct operations
    getNativeClient(): any;
}

Extended Methods in CosmosMongoDBAdapter

The CosmosMongoDBAdapter implements additional methods specifically for working with Azure Cosmos DB:

interface CosmosMongoDBAdapter extends DatabaseAdapter {
    // Update a specific element within an array field
    updateArrayField<T>(
        collection: string, 
        id: string,
        arrayField: string,
        arrayItemFilter: Record<string, unknown>,
        updateData: Record<string, unknown>
    ): Promise<T | null>;
    
    // Update all items in an array field
    updateAllArrayItems<T>(
        collection: string,
        id: string,
        arrayField: string,
        updateData: Record<string, unknown>
    ): Promise<T | null>;
    
    // Get the MongoDB collection object for direct operations
    getCollection(collection: string): Collection;
}

Adapters

  • createDatabaseAdapter(provider, config) - Create a database adapter
  • createMultiDatabaseAdapter(config) - Create a multi-database adapter
  • createCosmosMongoDBAdapter(config) - Create an Azure Cosmos DB with MongoDB API adapter

Database Providers

  • DatabaseProvider.MONGODB - MongoDB adapter
  • DatabaseProvider.COSMOS_MONGODB - Azure Cosmos DB with MongoDB API adapter
  • DatabaseProvider.COSMOSDB - Azure CosmosDB native adapter
  • DatabaseProvider.DYNAMODB - AWS DynamoDB adapter
  • DatabaseProvider.SUPABASE - Supabase adapter

Core Methods

  • connect() - Connect to the database
  • disconnect() - Disconnect from the database
  • isConnected() - Check if connected to the database
  • create(collection, data) - Create a document
  • find(collection, options) - Find documents
  • findById(collection, id) - Find a document by ID
  • findOne(collection, filter) - Find a document by filter
  • updateById(collection, id, data) - Update a document by ID
  • deleteById(collection, id) - Delete a document by ID
  • count(collection, filter) - Count documents
  • getNativeClient() - Get the native database client
  • supportsFeature(feature) - Check if a feature is supported

License

MIT

Package Sidebar

Install

npm i permas-database-adapter

Weekly Downloads

1

Version

0.1.5

License

MIT

Unpacked Size

808 kB

Total Files

37

Last publish

Collaborators

  • perceptivefocusinc