|
| 1 | +# @objectstack/driver-memory |
| 2 | + |
| 3 | +In-Memory Driver for ObjectStack. A reference implementation of the DriverInterface that stores data in memory using JavaScript arrays. |
| 4 | + |
| 5 | +## Plugin Capabilities |
| 6 | + |
| 7 | +This driver implements the ObjectStack plugin capability protocol: |
| 8 | +- **Type**: `driver` |
| 9 | +- **Protocol**: `com.objectstack.protocol.storage.v1` (partial conformance) |
| 10 | +- **Provides**: `DriverInterface` for data storage operations |
| 11 | +- **Features**: |
| 12 | + - ✅ Basic CRUD operations |
| 13 | + - ✅ Pagination (limit/offset) |
| 14 | + - ❌ Advanced query filters |
| 15 | + - ❌ Aggregations |
| 16 | + - ❌ Sorting |
| 17 | + - ❌ Transactions |
| 18 | + - ❌ Joins |
| 19 | + |
| 20 | +See [objectstack.config.ts](./objectstack.config.ts) for the complete capability manifest. |
| 21 | + |
| 22 | +## Features |
| 23 | + |
| 24 | +- 🚀 **Zero Dependencies**: Pure JavaScript implementation |
| 25 | +- 🧪 **Perfect for Testing**: Volatile storage ideal for unit tests |
| 26 | +- 📝 **TypeScript First**: Fully typed with TypeScript |
| 27 | +- 🔍 **Reference Implementation**: Clean example of DriverInterface |
| 28 | +- ⚡ **Fast**: In-memory operations are lightning fast |
| 29 | + |
| 30 | +## Installation |
| 31 | + |
| 32 | +```bash |
| 33 | +pnpm add @objectstack/driver-memory |
| 34 | +``` |
| 35 | + |
| 36 | +## Usage |
| 37 | + |
| 38 | +### With ObjectStack Runtime |
| 39 | + |
| 40 | +```typescript |
| 41 | +import { InMemoryDriver } from '@objectstack/driver-memory'; |
| 42 | +import { DriverPlugin } from '@objectstack/runtime'; |
| 43 | +import { ObjectKernel } from '@objectstack/runtime'; |
| 44 | + |
| 45 | +const kernel = new ObjectKernel(); |
| 46 | + |
| 47 | +// Create and register the driver |
| 48 | +const memoryDriver = new InMemoryDriver(); |
| 49 | +kernel.use(new DriverPlugin(memoryDriver, 'memory')); |
| 50 | + |
| 51 | +await kernel.bootstrap(); |
| 52 | +``` |
| 53 | + |
| 54 | +### Standalone Usage |
| 55 | + |
| 56 | +```typescript |
| 57 | +import { InMemoryDriver } from '@objectstack/driver-memory'; |
| 58 | + |
| 59 | +const driver = new InMemoryDriver({ |
| 60 | + seedData: true // Pre-populate with example data |
| 61 | +}); |
| 62 | + |
| 63 | +// Initialize |
| 64 | +await driver.connect(); |
| 65 | + |
| 66 | +// Create a record |
| 67 | +const user = await driver.create('user', { |
| 68 | + name: 'John Doe', |
| 69 | + email: 'john@example.com' |
| 70 | +}); |
| 71 | + |
| 72 | +// Find records |
| 73 | +const users = await driver.find('user', { |
| 74 | + limit: 10, |
| 75 | + offset: 0 |
| 76 | +}); |
| 77 | + |
| 78 | +// Get by ID |
| 79 | +const foundUser = await driver.findOne('user', user.id); |
| 80 | + |
| 81 | +// Update |
| 82 | +await driver.update('user', user.id, { |
| 83 | + name: 'Jane Doe' |
| 84 | +}); |
| 85 | + |
| 86 | +// Delete |
| 87 | +await driver.delete('user', user.id); |
| 88 | + |
| 89 | +// Count |
| 90 | +const count = await driver.count('user'); |
| 91 | + |
| 92 | +// Cleanup |
| 93 | +await driver.disconnect(); |
| 94 | +``` |
| 95 | + |
| 96 | +## API Reference |
| 97 | + |
| 98 | +### InMemoryDriver |
| 99 | + |
| 100 | +The main driver class that implements `DriverInterface`. |
| 101 | + |
| 102 | +#### Constructor Options |
| 103 | + |
| 104 | +```typescript |
| 105 | +interface DriverOptions { |
| 106 | + /** |
| 107 | + * Pre-populate the database with example data on startup |
| 108 | + * @default false |
| 109 | + */ |
| 110 | + seedData?: boolean; |
| 111 | + |
| 112 | + /** |
| 113 | + * Logger instance |
| 114 | + */ |
| 115 | + logger?: Logger; |
| 116 | +} |
| 117 | +``` |
| 118 | + |
| 119 | +#### Methods |
| 120 | + |
| 121 | +- `connect()` - Initialize the driver (no-op for in-memory) |
| 122 | +- `disconnect()` - Cleanup resources (clears all data) |
| 123 | +- `create(object, data)` - Create a new record |
| 124 | +- `find(object, query?)` - Query records with optional pagination |
| 125 | +- `findOne(object, id)` - Get a single record by ID |
| 126 | +- `update(object, id, data)` - Update a record |
| 127 | +- `delete(object, id)` - Delete a record |
| 128 | +- `count(object, query?)` - Count total records |
| 129 | +- `getSchema(object)` - Get object schema definition |
| 130 | +- `query(query)` - Execute a raw query (limited support) |
| 131 | + |
| 132 | +#### Capabilities |
| 133 | + |
| 134 | +The driver declares its capabilities via the `supports` property: |
| 135 | + |
| 136 | +```typescript |
| 137 | +{ |
| 138 | + transactions: false, |
| 139 | + queryFilters: false, |
| 140 | + queryAggregations: false, |
| 141 | + querySorting: false, |
| 142 | + queryPagination: true, // ✅ Supported via limit/offset |
| 143 | + queryWindowFunctions: false, |
| 144 | + querySubqueries: false, |
| 145 | + joins: false, |
| 146 | + fullTextSearch: false, |
| 147 | + vectorSearch: false, |
| 148 | + geoSpatial: false |
| 149 | +} |
| 150 | +``` |
| 151 | + |
| 152 | +## Data Storage |
| 153 | + |
| 154 | +The in-memory driver stores data in a simple Map structure: |
| 155 | + |
| 156 | +```typescript |
| 157 | +private tables: Map<string, Array<Record<string, any>>> = new Map(); |
| 158 | +``` |
| 159 | + |
| 160 | +**Important**: All data is lost when the process exits or `disconnect()` is called. This driver is **not suitable for production use**. |
| 161 | + |
| 162 | +## Use Cases |
| 163 | + |
| 164 | +✅ **Good for:** |
| 165 | +- Unit testing |
| 166 | +- Integration testing |
| 167 | +- Development/prototyping |
| 168 | +- CI/CD pipelines |
| 169 | +- Examples and tutorials |
| 170 | +- Learning ObjectStack |
| 171 | + |
| 172 | +❌ **Not suitable for:** |
| 173 | +- Production environments |
| 174 | +- Data persistence requirements |
| 175 | +- Large datasets (memory constraints) |
| 176 | +- Multi-process scenarios |
| 177 | +- Concurrent write operations |
| 178 | + |
| 179 | +## Testing Example |
| 180 | + |
| 181 | +```typescript |
| 182 | +import { describe, it, expect, beforeEach, afterEach } from 'vitest'; |
| 183 | +import { InMemoryDriver } from '@objectstack/driver-memory'; |
| 184 | + |
| 185 | +describe('User CRUD', () => { |
| 186 | + let driver: InMemoryDriver; |
| 187 | + |
| 188 | + beforeEach(async () => { |
| 189 | + driver = new InMemoryDriver(); |
| 190 | + await driver.connect(); |
| 191 | + }); |
| 192 | + |
| 193 | + afterEach(async () => { |
| 194 | + await driver.disconnect(); |
| 195 | + }); |
| 196 | + |
| 197 | + it('should create and retrieve a user', async () => { |
| 198 | + const user = await driver.create('user', { |
| 199 | + name: 'Test User', |
| 200 | + email: 'test@example.com' |
| 201 | + }); |
| 202 | + |
| 203 | + expect(user.id).toBeDefined(); |
| 204 | + |
| 205 | + const found = await driver.findOne('user', user.id); |
| 206 | + expect(found.name).toBe('Test User'); |
| 207 | + }); |
| 208 | +}); |
| 209 | +``` |
| 210 | + |
| 211 | +## Relationship to Other Drivers |
| 212 | + |
| 213 | +This driver serves as a reference implementation. For production use, consider: |
| 214 | + |
| 215 | +- **@objectstack/driver-postgres** - PostgreSQL driver with full SQL capabilities |
| 216 | +- **@objectstack/driver-mongodb** - MongoDB driver for document storage |
| 217 | +- **@objectstack/driver-redis** - Redis driver for caching and key-value storage |
| 218 | + |
| 219 | +## License |
| 220 | + |
| 221 | +Apache-2.0 |
| 222 | + |
| 223 | +## Related Packages |
| 224 | + |
| 225 | +- [@objectstack/runtime](../../runtime) - ObjectStack Runtime |
| 226 | +- [@objectstack/spec](../../spec) - ObjectStack Specifications |
| 227 | +- [@objectstack/core](../../core) - Core Interfaces and Types |
0 commit comments