UNPKG

bun-sqlite-orm

Version:

A lightweight TypeScript ORM for Bun runtime with Bun SQLite, featuring Active Record pattern and decorator-based entities

80 lines (66 loc) 3.26 kB
import 'reflect-metadata'; import { getGlobalMetadataContainer } from '../container'; import type { ColumnMetadata, ColumnOptions, IndexMetadata } from '../types'; export function Column(options: ColumnOptions = {}) { return (target: object, propertyKey: string) => { const metadataContainer = getGlobalMetadataContainer(); // Get TypeScript type information const type = Reflect.getMetadata('design:type', target, propertyKey); // Infer SQLite type from TypeScript type let sqliteType: 'text' | 'integer' | 'real' | 'blob' | 'json' = 'text'; if (type === Number) { sqliteType = options.type === 'real' ? 'real' : 'integer'; } else if (type === String || type === Date) { sqliteType = 'text'; } else if (type === Boolean) { sqliteType = 'integer'; // SQLite stores booleans as integers } else if (type === Object || type === Array) { // For complex objects/arrays, default to 'json' if no type specified sqliteType = options.type || 'json'; } // Check if property type includes null/undefined for nullable inference const isNullable = options.nullable ?? false; // TODO: improve nullable detection const columnMetadata: ColumnMetadata = { propertyName: propertyKey, type: options.type || sqliteType, nullable: isNullable, unique: options.unique || false, default: options.default, sqlDefault: options.sqlDefault, isPrimary: false, isGenerated: false, transformer: options.transformer, }; const entityConstructor = target.constructor as new () => unknown; // Auto-register entity if not already registered (will be marked as non-explicit) if (!metadataContainer.hasEntity(entityConstructor)) { const tableName = entityConstructor.name.toLowerCase(); metadataContainer.addEntity(entityConstructor, tableName, false); } metadataContainer.addColumn(entityConstructor, propertyKey, columnMetadata); // Handle index option if specified if (options.index !== undefined) { const tableName = metadataContainer.getTableName(entityConstructor); // Extract index configuration let indexName: string; let isUnique = false; if (typeof options.index === 'string') { // Custom name, non-unique indexName = options.index; } else if (typeof options.index === 'object') { // Object with name and/or unique options indexName = options.index.name || `idx_${tableName}_${propertyKey}`; isUnique = !!options.index.unique; } else { // Boolean true - auto-generate name, non-unique indexName = `idx_${tableName}_${propertyKey}`; } const indexMetadata: IndexMetadata = { name: indexName, columns: [propertyKey], unique: isUnique, }; metadataContainer.addIndex(entityConstructor, indexMetadata); } }; }