@hedystia/db 2.0.8 → 2.0.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"file":"repository.cjs","names":["QueryError","FileDriver","compileInsert","compileBulkInsert","compileUpdate","compileDelete","compileWhere","compileSelect"],"sources":["../../src/core/repository.ts"],"sourcesContent":["import type { CacheManager } from \"../cache\";\nimport { FileDriver } from \"../drivers/file\";\nimport {\n compileBulkInsert,\n compileDelete,\n compileInsert,\n compileSelect,\n compileUpdate,\n compileWhere,\n} from \"../drivers/sql-compiler\";\nimport { QueryError } from \"../errors\";\nimport type { SchemaRegistry } from \"../schema\";\nimport type {\n DatabaseDriver,\n DeleteOptions,\n QueryOptions,\n Repository,\n TableMetadata,\n UpdateOptions,\n WhereClause,\n} from \"../types\";\n\n/**\n * Repository implementation that provides CRUD operations for a table\n * @template T - The row type for this table\n */\nexport class TableRepository<T extends Record<string, any>> implements Repository<T> {\n private tableName: string;\n private driver: DatabaseDriver;\n private cache: CacheManager;\n private registry: SchemaRegistry;\n private meta: TableMetadata;\n private columnMap: Record<string, string>;\n private reverseColumnMap: Record<string, string>;\n private hasAliases: boolean;\n private tableCacheConfig?: { enabled: boolean; ttl?: number; maxTtl?: number };\n private jsonColumns: Set<string>;\n private jsonCodeKeys: Set<string>;\n\n constructor(\n tableName: string,\n driver: DatabaseDriver,\n cache: CacheManager,\n registry: SchemaRegistry,\n tableCacheConfig?: { enabled: boolean; ttl?: number; maxTtl?: number },\n ) {\n this.tableName = tableName;\n this.driver = driver;\n this.cache = cache;\n this.registry = registry;\n this.tableCacheConfig = tableCacheConfig;\n const meta = registry.getTable(tableName);\n if (!meta) {\n throw new QueryError(`Table \"${tableName}\" is not registered`);\n }\n this.meta = meta;\n this.columnMap = registry.getColumnMap(tableName);\n this.reverseColumnMap = registry.getReverseColumnMap(tableName);\n this.hasAliases = Object.entries(this.columnMap).some(\n ([codeKey, dbName]) => codeKey !== dbName,\n );\n this.jsonColumns = new Set(\n meta.columns.filter((c) => c.type === \"json\" || c.type === \"array\").map((c) => c.name),\n );\n this.jsonCodeKeys = new Set<string>();\n for (const col of meta.columns) {\n if (col.type === \"json\" || col.type === \"array\") {\n const codeKey = this.reverseColumnMap[col.name] ?? col.name;\n this.jsonCodeKeys.add(codeKey);\n }\n }\n }\n\n /**\n * Find all rows matching the query options\n * @param {QueryOptions<T>} [options] - Query options\n * @returns {Promise<T[]>} Array of matching rows\n */\n async find(options?: QueryOptions<T>): Promise<T[]> {\n return this.cache.getOrSetWithTableConfig(\n this.tableName,\n \"find\",\n options,\n async () => {\n const dbOptions = this.mapOptionsToDb(options);\n let rows: T[];\n if (this.driver instanceof FileDriver) {\n rows = this.mapRows(this.findFile(dbOptions as QueryOptions<T>));\n } else {\n rows = this.mapRows(await this.findSQL(dbOptions as QueryOptions<T>));\n }\n if (options?.with) {\n rows = await this.loadRelations(rows, options.with);\n }\n this.cacheEntities(rows);\n return rows;\n },\n this.tableCacheConfig,\n );\n }\n\n /**\n * Find all rows matching the query options (alias for find)\n * @param {QueryOptions<T>} [options] - Query options\n * @returns {Promise<T[]>} Array of matching rows\n */\n async findMany(options?: QueryOptions<T>): Promise<T[]> {\n return this.find(options);\n }\n\n /**\n * Find the first row matching the query options\n * @param {QueryOptions<T>} [options] - Query options\n * @returns {Promise<T | null>} The first matching row or null\n */\n async findFirst(options?: QueryOptions<T>): Promise<T | null> {\n return this.cache.getOrSetWithTableConfig(\n this.tableName,\n \"findFirst\",\n options,\n async () => {\n const dbOptions = this.mapOptionsToDb(options);\n const opts = { ...dbOptions, take: 1 };\n let rows: T[];\n if (this.driver instanceof FileDriver) {\n rows = this.mapRows(this.findFile(opts as QueryOptions<T>));\n } else {\n rows = this.mapRows(await this.findSQL(opts as QueryOptions<T>));\n }\n if (rows.length === 0) {\n return null;\n }\n if (options?.with) {\n rows = await this.loadRelations(rows, options.with);\n }\n const row = rows[0] ?? null;\n if (row) {\n this.cacheEntity(row);\n }\n return row;\n },\n this.tableCacheConfig,\n );\n }\n\n /**\n * Insert one or more rows\n * @param {Partial<T> | Partial<T>[]} data - Data to insert\n * @returns {Promise<T>} The inserted row\n */\n async insert(data: Partial<T> | Partial<T>[]): Promise<T> {\n const single = Array.isArray(data) ? data[0] : data;\n if (!single) {\n throw new QueryError(\"Insert data cannot be empty\");\n }\n\n this.cache.invalidateTable(this.tableName);\n const cleaned = this.toDbKeys(this.cleanData(single));\n\n if (this.driver instanceof FileDriver) {\n const id = (this.driver as FileDriver).insertRow(this.tableName, cleaned);\n const pk = this.registry.getPrimaryKey(this.tableName);\n if (pk) {\n cleaned[pk] = id;\n }\n const result = this.toCodeKeys(cleaned) as T;\n this.cacheEntity(result);\n return result;\n }\n\n const params: unknown[] = [];\n const sql = compileInsert(this.tableName, cleaned, params);\n const result = await this.driver.execute(sql, params);\n\n const pk = this.registry.getPrimaryKey(this.tableName);\n if (pk && result.insertId) {\n cleaned[pk] = result.insertId;\n }\n\n const mapped = this.toCodeKeys(cleaned) as T;\n this.cacheEntity(mapped);\n return mapped;\n }\n\n /**\n * Insert multiple rows\n * @param {Partial<T>[]} data - Array of data to insert\n * @returns {Promise<T[]>} The inserted rows\n */\n async insertMany(data: Partial<T>[]): Promise<T[]> {\n if (data.length === 0) {\n return [];\n }\n\n this.cache.invalidateTable(this.tableName);\n\n if (this.driver instanceof FileDriver) {\n const results: T[] = [];\n for (const item of data) {\n results.push(await this.insert(item));\n }\n return results;\n }\n\n const cleanedData = data.map((item) => this.toDbKeys(this.cleanData(item)));\n const params: unknown[] = [];\n const sql = compileBulkInsert(this.tableName, cleanedData, params);\n const result = await this.driver.execute(sql, params);\n\n const pk = this.registry.getPrimaryKey(this.tableName);\n if (pk && result.insertId) {\n for (let i = 0; i < cleanedData.length; i++) {\n const row = cleanedData[i];\n if (row) {\n row[pk] = result.insertId + i;\n }\n }\n }\n\n const finalRows = this.mapRows(cleanedData);\n this.cacheEntities(finalRows);\n return finalRows;\n }\n\n /**\n * Update rows matching the where clause\n * @param {UpdateOptions<T>} options - Update options with where and data\n * @returns {Promise<T[]>} The updated rows\n */\n async update(options: UpdateOptions<T>): Promise<T[]> {\n if (!options.where || Object.keys(options.where).length === 0) {\n throw new QueryError(\"Update requires a where clause\");\n }\n\n this.cache.invalidateTable(this.tableName);\n const cleaned = this.toDbKeys(this.cleanData(options.data));\n const dbWhere = this.mapWhereToDb(options.where as WhereClause);\n\n if (this.driver instanceof FileDriver) {\n const filter = this.buildFileFilter(dbWhere);\n (this.driver as FileDriver).updateRows(this.tableName, filter, cleaned);\n return this.find({ where: options.where } as QueryOptions<T>);\n }\n\n const params: unknown[] = [];\n const sql = compileUpdate(this.tableName, cleaned, dbWhere, params);\n await this.driver.execute(sql, params);\n\n return this.find({ where: options.where } as QueryOptions<T>);\n }\n\n /**\n * Delete rows matching the where clause\n * @param {DeleteOptions<T>} options - Delete options with where clause\n * @returns {Promise<number>} Number of deleted rows\n */\n async delete(options: DeleteOptions<T>): Promise<number> {\n if (!options.where || Object.keys(options.where).length === 0) {\n throw new QueryError(\"Delete requires a where clause\");\n }\n\n this.cache.invalidateTable(this.tableName);\n const dbWhere = this.mapWhereToDb(options.where as WhereClause);\n\n if (this.driver instanceof FileDriver) {\n const filter = this.buildFileFilter(dbWhere);\n return (this.driver as FileDriver).deleteRows(this.tableName, filter);\n }\n\n const params: unknown[] = [];\n const sql = compileDelete(this.tableName, dbWhere, params);\n const result = await this.driver.execute(sql, params);\n return result.affectedRows;\n }\n\n /**\n * Count rows matching the where clause\n * @param {Pick<QueryOptions<T>, \"where\">} [options] - Count options\n * @returns {Promise<number>} Row count\n */\n async count(options?: Pick<QueryOptions<T>, \"where\">): Promise<number> {\n return this.cache.getOrSetWithTableConfig(\n this.tableName,\n \"count\",\n options,\n async () => {\n const dbWhere = options?.where\n ? this.mapWhereToDb(options.where as WhereClause)\n : undefined;\n\n if (this.driver instanceof FileDriver) {\n const filter = dbWhere ? this.buildFileFilter(dbWhere) : undefined;\n return (this.driver as FileDriver).countRows(this.tableName, filter);\n }\n\n const params: unknown[] = [];\n let sql = `SELECT COUNT(*) as count FROM \\`${this.tableName}\\``;\n if (dbWhere && Object.keys(dbWhere).length > 0) {\n sql += ` WHERE ${compileWhere(dbWhere, params)}`;\n }\n const rows = await this.driver.query(sql, params);\n return rows[0]?.count ?? 0;\n },\n this.tableCacheConfig,\n );\n }\n\n /**\n * Check if any row exists matching the where clause\n * @param {Pick<QueryOptions<T>, \"where\">} options - Exists options\n * @returns {Promise<boolean>} Whether a matching row exists\n */\n async exists(options: Pick<QueryOptions<T>, \"where\">): Promise<boolean> {\n const c = await this.count(options);\n return c > 0;\n }\n\n /**\n * Insert or update a row based on the where clause\n * @param {object} options - Upsert options\n * @param {WhereClause<T>} options.where - Condition to check\n * @param {Partial<T>} options.create - Data to insert if not found\n * @param {Partial<T>} options.update - Data to update if found\n * @returns {Promise<T>} The upserted row\n */\n async upsert(options: {\n where: WhereClause<T>;\n create: Partial<T>;\n update: Partial<T>;\n }): Promise<T> {\n const existing = await this.findFirst({ where: options.where } as QueryOptions<T>);\n if (existing) {\n const updated = await this.update({ where: options.where, data: options.update });\n return updated[0] ?? existing;\n }\n return this.insert(options.create);\n }\n\n /**\n * Remove all rows from the table\n */\n async truncate(): Promise<void> {\n this.cache.invalidateTable(this.tableName);\n if (this.driver instanceof FileDriver) {\n (this.driver as FileDriver).truncateTable(this.tableName);\n return;\n }\n await this.driver.execute(`DELETE FROM \\`${this.tableName}\\``);\n }\n\n private async findSQL(options?: QueryOptions<T>): Promise<T[]> {\n const params: unknown[] = [];\n const sql = compileSelect(\n this.tableName,\n {\n select: options?.select as string[] | undefined,\n where: options?.where as WhereClause | undefined,\n orderBy: options?.orderBy as Record<string, \"asc\" | \"desc\"> | undefined,\n take: options?.take,\n skip: options?.skip,\n },\n params,\n );\n return this.driver.query(sql, params);\n }\n\n private findFile(options?: QueryOptions<T>): T[] {\n const fd = this.driver as FileDriver;\n const filter = options?.where ? this.buildFileFilter(options.where as WhereClause) : undefined;\n let rows = fd.findRows(this.tableName, filter) as T[];\n\n if (options?.select) {\n const selectSet = new Set(options.select as string[]);\n rows = rows.map((row) => {\n const filtered: Record<string, any> = {};\n for (const key of selectSet) {\n filtered[key as string] = row[key as string];\n }\n return filtered as T;\n });\n }\n\n if (options?.orderBy) {\n const entries = Object.entries(options.orderBy);\n rows.sort((a, b) => {\n for (const [col, dir] of entries) {\n const av = a[col];\n const bv = b[col];\n if (av < bv) {\n return dir === \"asc\" ? -1 : 1;\n }\n if (av > bv) {\n return dir === \"asc\" ? 1 : -1;\n }\n }\n return 0;\n });\n }\n\n if (options?.skip) {\n rows = rows.slice(options.skip);\n }\n if (options?.take) {\n rows = rows.slice(0, options.take);\n }\n\n return rows;\n }\n\n private buildFileFilter(where: WhereClause): (row: Record<string, unknown>) => boolean {\n return (row) => this.matchWhere(row, where);\n }\n\n private matchWhere(row: Record<string, unknown>, where: WhereClause): boolean {\n for (const [key, value] of Object.entries(where)) {\n if (key === \"OR\" && Array.isArray(value)) {\n const any = (value as WhereClause[]).some((sub) => this.matchWhere(row, sub));\n if (!any) {\n return false;\n }\n continue;\n }\n if (key === \"AND\" && Array.isArray(value)) {\n const all = (value as WhereClause[]).every((sub) => this.matchWhere(row, sub));\n if (!all) {\n return false;\n }\n continue;\n }\n\n if (value !== null && typeof value === \"object\" && !Array.isArray(value)) {\n const cond = value as any;\n const rowVal = row[key];\n if (cond.eq !== undefined && rowVal !== cond.eq) {\n return false;\n }\n if (cond.neq !== undefined && rowVal === cond.neq) {\n return false;\n }\n if (cond.gt !== undefined && !((rowVal as any) > cond.gt)) {\n return false;\n }\n if (cond.gte !== undefined && !((rowVal as any) >= cond.gte)) {\n return false;\n }\n if (cond.lt !== undefined && !((rowVal as any) < cond.lt)) {\n return false;\n }\n if (cond.lte !== undefined && !((rowVal as any) <= cond.lte)) {\n return false;\n }\n if (\n cond.like !== undefined &&\n !String(rowVal).match(new RegExp(cond.like.replace(/%/g, \".*\"), \"i\"))\n ) {\n return false;\n }\n if (\n cond.notLike !== undefined &&\n String(rowVal).match(new RegExp(cond.notLike.replace(/%/g, \".*\"), \"i\"))\n ) {\n return false;\n }\n if (cond.in !== undefined && !cond.in.includes(rowVal)) {\n return false;\n }\n if (cond.notIn?.includes(rowVal)) {\n return false;\n }\n if (cond.isNull === true && rowVal !== null && rowVal !== undefined) {\n return false;\n }\n if (cond.isNull === false && (rowVal === null || rowVal === undefined)) {\n return false;\n }\n if (cond.between !== undefined) {\n if ((rowVal as any) < cond.between[0] || (rowVal as any) > cond.between[1]) {\n return false;\n }\n }\n } else {\n if (row[key] !== value) {\n return false;\n }\n }\n }\n return true;\n }\n\n private async loadRelations(\n rows: T[],\n withOpts: Record<string, boolean | QueryOptions>,\n ): Promise<T[]> {\n if (rows.length === 0) {\n return rows;\n }\n const relations = this.registry.getRelations(this.tableName);\n\n for (const [relationName, opts] of Object.entries(withOpts)) {\n if (!opts) {\n continue;\n }\n const relation = relations.find((r) => r.relationName === relationName);\n if (!relation) {\n continue;\n }\n\n const isParent = relation.from.table === this.tableName;\n if (isParent) {\n const ids = rows.map((r) => r[relation.from.column]).filter((v) => v != null);\n if (ids.length === 0) {\n continue;\n }\n const uniqueIds = [...new Set(ids)];\n const relatedOpts: QueryOptions = typeof opts === \"object\" ? opts : {};\n const related = await this.findRelated(\n relation.to.table,\n relation.to.column,\n uniqueIds,\n relatedOpts,\n );\n const relatedMap = new Map<unknown, unknown[]>();\n for (const r of related) {\n const key = (r as any)[relation.to.column];\n if (!relatedMap.has(key)) {\n relatedMap.set(key, []);\n }\n relatedMap.get(key)!.push(r);\n }\n for (const row of rows) {\n const key = row[relation.from.column];\n const relRows = relatedMap.get(key);\n (row as any)[relationName] = relRows ?? [];\n }\n } else {\n const pk = this.registry.getPrimaryKey(this.tableName);\n if (!pk) {\n continue;\n }\n const ids = rows.map((r) => r[pk]).filter((v) => v != null);\n if (ids.length === 0) {\n continue;\n }\n const uniqueIds = [...new Set(ids)];\n const relatedOpts: QueryOptions = typeof opts === \"object\" ? opts : {};\n const related = await this.findRelated(\n relation.to.table,\n relation.to.column,\n uniqueIds,\n relatedOpts,\n );\n const relatedMap = new Map<unknown, unknown[]>();\n for (const r of related) {\n const key = (r as any)[relation.to.column];\n if (!relatedMap.has(key)) {\n relatedMap.set(key, []);\n }\n relatedMap.get(key)!.push(r);\n }\n for (const row of rows) {\n const key = row[pk];\n (row as any)[relationName] = relatedMap.get(key) ?? [];\n }\n }\n }\n\n return rows;\n }\n\n private async findRelated(\n tableName: string,\n column: string,\n ids: unknown[],\n options: QueryOptions,\n ): Promise<any[]> {\n if (this.driver instanceof FileDriver) {\n const fd = this.driver as FileDriver;\n const filter = (row: Record<string, unknown>) => ids.includes(row[column]);\n return fd.findRows(tableName, filter);\n }\n\n const params: unknown[] = [];\n const placeholders = ids.map(() => \"?\").join(\", \");\n params.push(...ids);\n\n let sql = `SELECT * FROM \\`${tableName}\\` WHERE \\`${column}\\` IN (${placeholders})`;\n if (options.orderBy) {\n const orderParts = Object.entries(options.orderBy).map(\n ([col, dir]) => `\\`${col}\\` ${(dir as string).toUpperCase()}`,\n );\n if (orderParts.length > 0) {\n sql += ` ORDER BY ${orderParts.join(\", \")}`;\n }\n }\n if (options.take) {\n sql += ` LIMIT ${options.take}`;\n }\n\n return this.driver.query(sql, params);\n }\n\n private cleanData(data: Partial<T>): Record<string, unknown> {\n const cleaned: Record<string, unknown> = {};\n const dbColumnNames = new Set(this.meta.columns.map((c) => c.name));\n const codeKeys = new Set(Object.keys(this.columnMap));\n const shouldSerialize = !(this.driver instanceof FileDriver);\n for (const [key, value] of Object.entries(data as Record<string, unknown>)) {\n if (codeKeys.has(key) || dbColumnNames.has(key)) {\n if (\n shouldSerialize &&\n (this.jsonCodeKeys.has(key) || this.jsonColumns.has(key)) &&\n value != null &&\n typeof value === \"object\"\n ) {\n cleaned[key] = JSON.stringify(value);\n } else {\n cleaned[key] = value;\n }\n }\n }\n return cleaned;\n }\n\n private cacheEntities(rows: T[]): void {\n const pk = this.registry.getPrimaryKey(this.tableName);\n if (!pk) {\n return;\n }\n for (const row of rows) {\n if (row[pk] != null) {\n this.cache.setEntity(this.tableName, row[pk], row);\n }\n }\n }\n\n private cacheEntity(row: T): void {\n const pk = this.registry.getPrimaryKey(this.tableName);\n if (!pk || row[pk] == null) {\n return;\n }\n this.cache.setEntity(this.tableName, row[pk], row);\n }\n\n private toDbKeys(data: Record<string, unknown>): Record<string, unknown> {\n if (!this.hasAliases) {\n return data;\n }\n const result: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(data)) {\n result[this.columnMap[key] ?? key] = value;\n }\n return result;\n }\n\n private toCodeKeys(row: Record<string, unknown>): Record<string, unknown> {\n if (!this.hasAliases) {\n return row;\n }\n const result: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(row)) {\n result[this.reverseColumnMap[key] ?? key] = value;\n }\n return result;\n }\n\n private mapWhereToDb(where: WhereClause): WhereClause {\n if (!this.hasAliases) {\n return where;\n }\n const result: WhereClause = {};\n for (const [key, value] of Object.entries(where)) {\n if (key === \"OR\" || key === \"AND\") {\n (result as any)[key] = (value as WhereClause[]).map((sub) => this.mapWhereToDb(sub));\n } else {\n result[this.columnMap[key] ?? key] = value;\n }\n }\n return result;\n }\n\n private mapSelectToDb(select: string[]): string[] {\n if (!this.hasAliases) {\n return select;\n }\n return select.map((key) => this.columnMap[key] ?? key);\n }\n\n private mapOrderByToDb(orderBy: Record<string, \"asc\" | \"desc\">): Record<string, \"asc\" | \"desc\"> {\n if (!this.hasAliases) {\n return orderBy;\n }\n const result: Record<string, \"asc\" | \"desc\"> = {};\n for (const [key, value] of Object.entries(orderBy)) {\n result[this.columnMap[key] ?? key] = value;\n }\n return result;\n }\n\n private mapOptionsToDb(options?: QueryOptions<T>): QueryOptions | undefined {\n if (!options || !this.hasAliases) {\n return options as QueryOptions | undefined;\n }\n const mapped: QueryOptions = { ...options } as any;\n if (options.where) {\n mapped.where = this.mapWhereToDb(options.where as WhereClause);\n }\n if (options.select) {\n mapped.select = this.mapSelectToDb(options.select);\n }\n if (options.orderBy) {\n mapped.orderBy = this.mapOrderByToDb(options.orderBy as Record<string, \"asc\" | \"desc\">);\n }\n return mapped;\n }\n\n private mapRows(rows: Record<string, unknown>[]): T[] {\n const shouldDeserialize = this.jsonCodeKeys.size > 0 && !(this.driver instanceof FileDriver);\n if (!this.hasAliases && !shouldDeserialize) {\n return rows as T[];\n }\n return rows.map((row) => {\n const mapped = this.hasAliases ? this.toCodeKeys(row) : { ...row };\n if (shouldDeserialize) {\n for (const key of this.jsonCodeKeys) {\n const val = mapped[key];\n if (typeof val === \"string\") {\n try {\n mapped[key] = JSON.parse(val);\n } catch {}\n }\n }\n }\n return mapped as T;\n });\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"repository.cjs","names":["QueryError","FileDriver","S3Driver","compileInsert","compileBulkInsert","compileUpdate","compileDelete","compileWhere","compileSelect"],"sources":["../../src/core/repository.ts"],"sourcesContent":["import type { CacheManager } from \"../cache\";\nimport { FileDriver } from \"../drivers/file\";\nimport { S3Driver } from \"../drivers/s3\";\nimport {\n compileBulkInsert,\n compileDelete,\n compileInsert,\n compileSelect,\n compileUpdate,\n compileWhere,\n} from \"../drivers/sql-compiler\";\nimport { QueryError } from \"../errors\";\nimport type { SchemaRegistry } from \"../schema\";\nimport type {\n DatabaseDriver,\n DeleteOptions,\n QueryOptions,\n Repository,\n TableMetadata,\n UpdateOptions,\n WhereClause,\n} from \"../types\";\n\n/**\n * Repository implementation that provides CRUD operations for a table\n * @template T - The row type for this table\n */\nexport class TableRepository<T extends Record<string, any>> implements Repository<T> {\n private tableName: string;\n private driver: DatabaseDriver;\n private cache: CacheManager;\n private registry: SchemaRegistry;\n private meta: TableMetadata;\n private columnMap: Record<string, string>;\n private reverseColumnMap: Record<string, string>;\n private hasAliases: boolean;\n private tableCacheConfig?: { enabled: boolean; ttl?: number; maxTtl?: number };\n private jsonColumns: Set<string>;\n private jsonCodeKeys: Set<string>;\n private isFileLikeDriver: boolean;\n private dateColumns: Set<string>;\n\n constructor(\n tableName: string,\n driver: DatabaseDriver,\n cache: CacheManager,\n registry: SchemaRegistry,\n tableCacheConfig?: { enabled: boolean; ttl?: number; maxTtl?: number },\n ) {\n this.tableName = tableName;\n this.driver = driver;\n this.cache = cache;\n this.registry = registry;\n this.tableCacheConfig = tableCacheConfig;\n const meta = registry.getTable(tableName);\n if (!meta) {\n throw new QueryError(`Table \"${tableName}\" is not registered`);\n }\n this.meta = meta;\n this.columnMap = registry.getColumnMap(tableName);\n this.reverseColumnMap = registry.getReverseColumnMap(tableName);\n this.hasAliases = Object.entries(this.columnMap).some(\n ([codeKey, dbName]) => codeKey !== dbName,\n );\n this.jsonColumns = new Set(\n meta.columns.filter((c) => c.type === \"json\" || c.type === \"array\").map((c) => c.name),\n );\n this.jsonCodeKeys = new Set<string>();\n for (const col of meta.columns) {\n if (col.type === \"json\" || col.type === \"array\") {\n const codeKey = this.reverseColumnMap[col.name] ?? col.name;\n this.jsonCodeKeys.add(codeKey);\n }\n }\n this.dateColumns = new Set<string>();\n for (const col of meta.columns) {\n if (col.type === \"datetime\" || col.type === \"timestamp\") {\n const codeKey = this.reverseColumnMap[col.name] ?? col.name;\n this.dateColumns.add(codeKey);\n }\n }\n this.isFileLikeDriver = driver instanceof FileDriver || driver instanceof S3Driver;\n }\n\n /**\n * Find all rows matching the query options\n * @param {QueryOptions<T>} [options] - Query options\n * @returns {Promise<T[]>} Array of matching rows\n */\n async find(options?: QueryOptions<T>): Promise<T[]> {\n return this.cache.getOrSetWithTableConfig(\n this.tableName,\n \"find\",\n options,\n async () => {\n const dbOptions = this.mapOptionsToDb(options);\n let rows: T[];\n if (this.isFileLikeDriver) {\n rows = this.mapRows(this.findFile(dbOptions as QueryOptions<T>));\n } else {\n rows = this.mapRows(await this.findSQL(dbOptions as QueryOptions<T>));\n }\n if (options?.with) {\n rows = await this.loadRelations(rows, options.with);\n }\n this.cacheEntities(rows);\n return rows;\n },\n this.tableCacheConfig,\n );\n }\n\n /**\n * Find all rows matching the query options (alias for find)\n * @param {QueryOptions<T>} [options] - Query options\n * @returns {Promise<T[]>} Array of matching rows\n */\n async findMany(options?: QueryOptions<T>): Promise<T[]> {\n return this.find(options);\n }\n\n /**\n * Find the first row matching the query options\n * @param {QueryOptions<T>} [options] - Query options\n * @returns {Promise<T | null>} The first matching row or null\n */\n async findFirst(options?: QueryOptions<T>): Promise<T | null> {\n return this.cache.getOrSetWithTableConfig(\n this.tableName,\n \"findFirst\",\n options,\n async () => {\n const dbOptions = this.mapOptionsToDb(options);\n const opts = { ...dbOptions, take: 1 };\n let rows: T[];\n if (this.isFileLikeDriver) {\n rows = this.mapRows(this.findFile(opts as QueryOptions<T>));\n } else {\n rows = this.mapRows(await this.findSQL(opts as QueryOptions<T>));\n }\n if (rows.length === 0) {\n return null;\n }\n if (options?.with) {\n rows = await this.loadRelations(rows, options.with);\n }\n const row = rows[0] ?? null;\n if (row) {\n this.cacheEntity(row);\n }\n return row;\n },\n this.tableCacheConfig,\n );\n }\n\n /**\n * Insert one or more rows\n * @param {Partial<T> | Partial<T>[]} data - Data to insert\n * @returns {Promise<T>} The inserted row\n */\n async insert(data: Partial<T> | Partial<T>[]): Promise<T> {\n const single = Array.isArray(data) ? data[0] : data;\n if (!single) {\n throw new QueryError(\"Insert data cannot be empty\");\n }\n\n this.cache.invalidateTable(this.tableName);\n const cleaned = this.toDbKeys(this.cleanData(single));\n\n if (this.isFileLikeDriver) {\n const id = (this.driver as FileDriver | S3Driver).insertRow(this.tableName, cleaned);\n const pk = this.registry.getPrimaryKey(this.tableName);\n if (pk) {\n cleaned[pk] = id;\n }\n const result = this.toCodeKeys(cleaned) as T;\n this.cacheEntity(result);\n return result;\n }\n\n const params: unknown[] = [];\n const sql = compileInsert(this.tableName, cleaned, params);\n const result = await this.driver.execute(sql, params);\n\n const pk = this.registry.getPrimaryKey(this.tableName);\n if (pk && result.insertId) {\n cleaned[pk] = result.insertId;\n }\n\n const mapped = this.toCodeKeys(cleaned) as T;\n this.cacheEntity(mapped);\n return mapped;\n }\n\n /**\n * Insert multiple rows\n * @param {Partial<T>[]} data - Array of data to insert\n * @returns {Promise<T[]>} The inserted rows\n */\n async insertMany(data: Partial<T>[]): Promise<T[]> {\n if (data.length === 0) {\n return [];\n }\n\n this.cache.invalidateTable(this.tableName);\n\n if (this.isFileLikeDriver) {\n const results: T[] = [];\n for (const item of data) {\n results.push(await this.insert(item));\n }\n return results;\n }\n\n const cleanedData = data.map((item) => this.toDbKeys(this.cleanData(item)));\n const params: unknown[] = [];\n const sql = compileBulkInsert(this.tableName, cleanedData, params);\n const result = await this.driver.execute(sql, params);\n\n const pk = this.registry.getPrimaryKey(this.tableName);\n if (pk && result.insertId) {\n for (let i = 0; i < cleanedData.length; i++) {\n const row = cleanedData[i];\n if (row) {\n row[pk] = result.insertId + i;\n }\n }\n }\n\n const finalRows = this.mapRows(cleanedData);\n this.cacheEntities(finalRows);\n return finalRows;\n }\n\n /**\n * Update rows matching the where clause\n * @param {UpdateOptions<T>} options - Update options with where and data\n * @returns {Promise<T[]>} The updated rows\n */\n async update(options: UpdateOptions<T>): Promise<T[]> {\n if (!options.where || Object.keys(options.where).length === 0) {\n throw new QueryError(\"Update requires a where clause\");\n }\n\n this.cache.invalidateTable(this.tableName);\n const cleaned = this.toDbKeys(this.cleanData(options.data));\n const dbWhere = this.mapWhereToDb(options.where as WhereClause);\n\n if (this.isFileLikeDriver) {\n const filter = this.buildFileFilter(dbWhere);\n (this.driver as FileDriver | S3Driver).updateRows(this.tableName, filter, cleaned);\n return this.find({ where: options.where } as QueryOptions<T>);\n }\n\n const params: unknown[] = [];\n const sql = compileUpdate(this.tableName, cleaned, dbWhere, params);\n await this.driver.execute(sql, params);\n\n return this.find({ where: options.where } as QueryOptions<T>);\n }\n\n /**\n * Delete rows matching the where clause\n * @param {DeleteOptions<T>} options - Delete options with where clause\n * @returns {Promise<number>} Number of deleted rows\n */\n async delete(options: DeleteOptions<T>): Promise<number> {\n if (!options.where || Object.keys(options.where).length === 0) {\n throw new QueryError(\"Delete requires a where clause\");\n }\n\n this.cache.invalidateTable(this.tableName);\n const dbWhere = this.mapWhereToDb(options.where as WhereClause);\n\n if (this.isFileLikeDriver) {\n const filter = this.buildFileFilter(dbWhere);\n return (this.driver as FileDriver | S3Driver).deleteRows(this.tableName, filter);\n }\n\n const params: unknown[] = [];\n const sql = compileDelete(this.tableName, dbWhere, params);\n const result = await this.driver.execute(sql, params);\n return result.affectedRows;\n }\n\n /**\n * Count rows matching the where clause\n * @param {Pick<QueryOptions<T>, \"where\">} [options] - Count options\n * @returns {Promise<number>} Row count\n */\n async count(options?: Pick<QueryOptions<T>, \"where\">): Promise<number> {\n return this.cache.getOrSetWithTableConfig(\n this.tableName,\n \"count\",\n options,\n async () => {\n const dbWhere = options?.where\n ? this.mapWhereToDb(options.where as WhereClause)\n : undefined;\n\n if (this.isFileLikeDriver) {\n const filter = dbWhere ? this.buildFileFilter(dbWhere) : undefined;\n return (this.driver as FileDriver | S3Driver).countRows(this.tableName, filter);\n }\n\n const params: unknown[] = [];\n let sql = `SELECT COUNT(*) as count FROM \\`${this.tableName}\\``;\n if (dbWhere && Object.keys(dbWhere).length > 0) {\n sql += ` WHERE ${compileWhere(dbWhere, params)}`;\n }\n const rows = await this.driver.query(sql, params);\n return rows[0]?.count ?? 0;\n },\n this.tableCacheConfig,\n );\n }\n\n /**\n * Check if any row exists matching the where clause\n * @param {Pick<QueryOptions<T>, \"where\">} options - Exists options\n * @returns {Promise<boolean>} Whether a matching row exists\n */\n async exists(options: Pick<QueryOptions<T>, \"where\">): Promise<boolean> {\n const c = await this.count(options);\n return c > 0;\n }\n\n /**\n * Insert or update a row based on the where clause\n * @param {object} options - Upsert options\n * @param {WhereClause<T>} options.where - Condition to check\n * @param {Partial<T>} options.create - Data to insert if not found\n * @param {Partial<T>} options.update - Data to update if found\n * @returns {Promise<T>} The upserted row\n */\n async upsert(options: {\n where: WhereClause<T>;\n create: Partial<T>;\n update: Partial<T>;\n }): Promise<T> {\n const existing = await this.findFirst({ where: options.where } as QueryOptions<T>);\n if (existing) {\n const updated = await this.update({ where: options.where, data: options.update });\n return updated[0] ?? existing;\n }\n return this.insert(options.create);\n }\n\n /**\n * Remove all rows from the table\n */\n async truncate(): Promise<void> {\n this.cache.invalidateTable(this.tableName);\n if (this.isFileLikeDriver) {\n (this.driver as FileDriver | S3Driver).truncateTable(this.tableName);\n return;\n }\n await this.driver.execute(`DELETE FROM \\`${this.tableName}\\``);\n }\n\n private async findSQL(options?: QueryOptions<T>): Promise<T[]> {\n const params: unknown[] = [];\n const sql = compileSelect(\n this.tableName,\n {\n select: options?.select as string[] | undefined,\n where: options?.where as WhereClause | undefined,\n orderBy: options?.orderBy as Record<string, \"asc\" | \"desc\"> | undefined,\n take: options?.take,\n skip: options?.skip,\n },\n params,\n );\n return this.driver.query(sql, params);\n }\n\n private findFile(options?: QueryOptions<T>): T[] {\n const fd = this.driver as FileDriver | S3Driver;\n const filter = options?.where ? this.buildFileFilter(options.where as WhereClause) : undefined;\n let rows = fd.findRows(this.tableName, filter) as T[];\n\n if (options?.select) {\n const selectSet = new Set(options.select as string[]);\n rows = rows.map((row) => {\n const filtered: Record<string, any> = {};\n for (const key of selectSet) {\n filtered[key as string] = row[key as string];\n }\n return filtered as T;\n });\n }\n\n if (options?.orderBy) {\n const entries = Object.entries(options.orderBy);\n rows.sort((a, b) => {\n for (const [col, dir] of entries) {\n const av = a[col];\n const bv = b[col];\n if (av < bv) {\n return dir === \"asc\" ? -1 : 1;\n }\n if (av > bv) {\n return dir === \"asc\" ? 1 : -1;\n }\n }\n return 0;\n });\n }\n\n if (options?.skip) {\n rows = rows.slice(options.skip);\n }\n if (options?.take) {\n rows = rows.slice(0, options.take);\n }\n\n return rows;\n }\n\n private buildFileFilter(where: WhereClause): (row: Record<string, unknown>) => boolean {\n return (row) => this.matchWhere(row, where);\n }\n\n private matchWhere(row: Record<string, unknown>, where: WhereClause): boolean {\n for (const [key, value] of Object.entries(where)) {\n if (key === \"OR\" && Array.isArray(value)) {\n const any = (value as WhereClause[]).some((sub) => this.matchWhere(row, sub));\n if (!any) {\n return false;\n }\n continue;\n }\n if (key === \"AND\" && Array.isArray(value)) {\n const all = (value as WhereClause[]).every((sub) => this.matchWhere(row, sub));\n if (!all) {\n return false;\n }\n continue;\n }\n\n if (value !== null && typeof value === \"object\" && !Array.isArray(value)) {\n const cond = value as any;\n const rowVal = row[key];\n if (cond.eq !== undefined && rowVal !== cond.eq) {\n return false;\n }\n if (cond.neq !== undefined && rowVal === cond.neq) {\n return false;\n }\n if (cond.gt !== undefined && !((rowVal as any) > cond.gt)) {\n return false;\n }\n if (cond.gte !== undefined && !((rowVal as any) >= cond.gte)) {\n return false;\n }\n if (cond.lt !== undefined && !((rowVal as any) < cond.lt)) {\n return false;\n }\n if (cond.lte !== undefined && !((rowVal as any) <= cond.lte)) {\n return false;\n }\n if (\n cond.like !== undefined &&\n !String(rowVal).match(new RegExp(cond.like.replace(/%/g, \".*\"), \"i\"))\n ) {\n return false;\n }\n if (\n cond.notLike !== undefined &&\n String(rowVal).match(new RegExp(cond.notLike.replace(/%/g, \".*\"), \"i\"))\n ) {\n return false;\n }\n if (cond.in !== undefined && !cond.in.includes(rowVal)) {\n return false;\n }\n if (cond.notIn?.includes(rowVal)) {\n return false;\n }\n if (cond.isNull === true && rowVal !== null && rowVal !== undefined) {\n return false;\n }\n if (cond.isNull === false && (rowVal === null || rowVal === undefined)) {\n return false;\n }\n if (cond.between !== undefined) {\n if ((rowVal as any) < cond.between[0] || (rowVal as any) > cond.between[1]) {\n return false;\n }\n }\n } else {\n if (row[key] !== value) {\n return false;\n }\n }\n }\n return true;\n }\n\n private async loadRelations(\n rows: T[],\n withOpts: Record<string, boolean | QueryOptions>,\n ): Promise<T[]> {\n if (rows.length === 0) {\n return rows;\n }\n const relations = this.registry.getRelations(this.tableName);\n\n for (const [relationName, opts] of Object.entries(withOpts)) {\n if (!opts) {\n continue;\n }\n const relation = relations.find((r) => r.relationName === relationName);\n if (!relation) {\n continue;\n }\n\n const isParent = relation.from.table === this.tableName;\n if (isParent) {\n const ids = rows.map((r) => r[relation.from.column]).filter((v) => v != null);\n if (ids.length === 0) {\n continue;\n }\n const uniqueIds = [...new Set(ids)];\n const relatedOpts: QueryOptions = typeof opts === \"object\" ? opts : {};\n const related = await this.findRelated(\n relation.to.table,\n relation.to.column,\n uniqueIds,\n relatedOpts,\n );\n const relatedMap = new Map<unknown, unknown[]>();\n for (const r of related) {\n const key = (r as any)[relation.to.column];\n if (!relatedMap.has(key)) {\n relatedMap.set(key, []);\n }\n relatedMap.get(key)!.push(r);\n }\n for (const row of rows) {\n const key = row[relation.from.column];\n const relRows = relatedMap.get(key);\n (row as any)[relationName] = relRows ?? [];\n }\n } else {\n const pk = this.registry.getPrimaryKey(this.tableName);\n if (!pk) {\n continue;\n }\n const ids = rows.map((r) => r[pk]).filter((v) => v != null);\n if (ids.length === 0) {\n continue;\n }\n const uniqueIds = [...new Set(ids)];\n const relatedOpts: QueryOptions = typeof opts === \"object\" ? opts : {};\n const related = await this.findRelated(\n relation.to.table,\n relation.to.column,\n uniqueIds,\n relatedOpts,\n );\n const relatedMap = new Map<unknown, unknown[]>();\n for (const r of related) {\n const key = (r as any)[relation.to.column];\n if (!relatedMap.has(key)) {\n relatedMap.set(key, []);\n }\n relatedMap.get(key)!.push(r);\n }\n for (const row of rows) {\n const key = row[pk];\n (row as any)[relationName] = relatedMap.get(key) ?? [];\n }\n }\n }\n\n return rows;\n }\n\n private async findRelated(\n tableName: string,\n column: string,\n ids: unknown[],\n options: QueryOptions,\n ): Promise<any[]> {\n if (this.isFileLikeDriver) {\n const fd = this.driver as FileDriver | S3Driver;\n const filter = (row: Record<string, unknown>) => ids.includes(row[column]);\n return fd.findRows(tableName, filter);\n }\n\n const params: unknown[] = [];\n const placeholders = ids.map(() => \"?\").join(\", \");\n params.push(...ids);\n\n let sql = `SELECT * FROM \\`${tableName}\\` WHERE \\`${column}\\` IN (${placeholders})`;\n if (options.orderBy) {\n const orderParts = Object.entries(options.orderBy).map(\n ([col, dir]) => `\\`${col}\\` ${(dir as string).toUpperCase()}`,\n );\n if (orderParts.length > 0) {\n sql += ` ORDER BY ${orderParts.join(\", \")}`;\n }\n }\n if (options.take) {\n sql += ` LIMIT ${options.take}`;\n }\n\n return this.driver.query(sql, params);\n }\n\n private cleanData(data: Partial<T>): Record<string, unknown> {\n const cleaned: Record<string, unknown> = {};\n const dbColumnNames = new Set(this.meta.columns.map((c) => c.name));\n const codeKeys = new Set(Object.keys(this.columnMap));\n const shouldSerialize = !this.isFileLikeDriver;\n for (const [key, value] of Object.entries(data as Record<string, unknown>)) {\n if (codeKeys.has(key) || dbColumnNames.has(key)) {\n if (\n shouldSerialize &&\n (this.jsonCodeKeys.has(key) || this.jsonColumns.has(key)) &&\n value != null &&\n typeof value === \"object\"\n ) {\n cleaned[key] = JSON.stringify(value);\n } else {\n cleaned[key] = value;\n }\n }\n }\n return cleaned;\n }\n\n private cacheEntities(rows: T[]): void {\n const pk = this.registry.getPrimaryKey(this.tableName);\n if (!pk) {\n return;\n }\n for (const row of rows) {\n if (row[pk] != null) {\n this.cache.setEntity(this.tableName, row[pk], row);\n }\n }\n }\n\n private cacheEntity(row: T): void {\n const pk = this.registry.getPrimaryKey(this.tableName);\n if (!pk || row[pk] == null) {\n return;\n }\n this.cache.setEntity(this.tableName, row[pk], row);\n }\n\n private toDbKeys(data: Record<string, unknown>): Record<string, unknown> {\n if (!this.hasAliases) {\n return data;\n }\n const result: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(data)) {\n result[this.columnMap[key] ?? key] = value;\n }\n return result;\n }\n\n private toCodeKeys(row: Record<string, unknown>): Record<string, unknown> {\n if (!this.hasAliases) {\n return row;\n }\n const result: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(row)) {\n result[this.reverseColumnMap[key] ?? key] = value;\n }\n return result;\n }\n\n private mapWhereToDb(where: WhereClause): WhereClause {\n if (!this.hasAliases) {\n return where;\n }\n const result: WhereClause = {};\n for (const [key, value] of Object.entries(where)) {\n if (key === \"OR\" || key === \"AND\") {\n (result as any)[key] = (value as WhereClause[]).map((sub) => this.mapWhereToDb(sub));\n } else {\n result[this.columnMap[key] ?? key] = value;\n }\n }\n return result;\n }\n\n private mapSelectToDb(select: string[]): string[] {\n if (!this.hasAliases) {\n return select;\n }\n return select.map((key) => this.columnMap[key] ?? key);\n }\n\n private mapOrderByToDb(orderBy: Record<string, \"asc\" | \"desc\">): Record<string, \"asc\" | \"desc\"> {\n if (!this.hasAliases) {\n return orderBy;\n }\n const result: Record<string, \"asc\" | \"desc\"> = {};\n for (const [key, value] of Object.entries(orderBy)) {\n result[this.columnMap[key] ?? key] = value;\n }\n return result;\n }\n\n private mapOptionsToDb(options?: QueryOptions<T>): QueryOptions | undefined {\n if (!options || !this.hasAliases) {\n return options as QueryOptions | undefined;\n }\n const mapped: QueryOptions = { ...options } as any;\n if (options.where) {\n mapped.where = this.mapWhereToDb(options.where as WhereClause);\n }\n if (options.select) {\n mapped.select = this.mapSelectToDb(options.select);\n }\n if (options.orderBy) {\n mapped.orderBy = this.mapOrderByToDb(options.orderBy as Record<string, \"asc\" | \"desc\">);\n }\n return mapped;\n }\n\n private mapRows(rows: Record<string, unknown>[]): T[] {\n const shouldDeserialize = (this.jsonCodeKeys.size > 0 || this.dateColumns.size > 0) && !this.isFileLikeDriver;\n if (!this.hasAliases && !shouldDeserialize) {\n return rows as T[];\n }\n return rows.map((row) => {\n const mapped = this.hasAliases ? this.toCodeKeys(row) : { ...row };\n if (shouldDeserialize) {\n for (const key of this.jsonCodeKeys) {\n const val = mapped[key];\n if (typeof val === \"string\") {\n try {\n mapped[key] = JSON.parse(val);\n } catch {}\n }\n }\n for (const key of this.dateColumns) {\n const val = mapped[key];\n if (typeof val === \"string\") {\n mapped[key] = new Date(val);\n } else if (typeof val === \"number\") {\n mapped[key] = new Date(val);\n }\n }\n }\n return mapped as T;\n });\n }\n}\n"],"mappings":"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"}
@@ -19,6 +19,8 @@ declare class TableRepository<T extends Record<string, any>> implements Reposito
19
19
  private tableCacheConfig?;
20
20
  private jsonColumns;
21
21
  private jsonCodeKeys;
22
+ private isFileLikeDriver;
23
+ private dateColumns;
22
24
  constructor(tableName: string, driver: DatabaseDriver, cache: CacheManager, registry: SchemaRegistry, tableCacheConfig?: {
23
25
  enabled: boolean;
24
26
  ttl?: number;
@@ -19,6 +19,8 @@ declare class TableRepository<T extends Record<string, any>> implements Reposito
19
19
  private tableCacheConfig?;
20
20
  private jsonColumns;
21
21
  private jsonCodeKeys;
22
+ private isFileLikeDriver;
23
+ private dateColumns;
22
24
  constructor(tableName: string, driver: DatabaseDriver, cache: CacheManager, registry: SchemaRegistry, tableCacheConfig?: {
23
25
  enabled: boolean;
24
26
  ttl?: number;
@@ -2,10 +2,12 @@ import { __esmMin } from "../_virtual/_rolldown/runtime.mjs";
2
2
  import { QueryError, init_errors } from "../errors.mjs";
3
3
  import { FileDriver, init_file } from "../drivers/file.mjs";
4
4
  import { compileBulkInsert, compileDelete, compileInsert, compileSelect, compileUpdate, compileWhere, init_sql_compiler } from "../drivers/sql-compiler.mjs";
5
+ import { S3Driver, init_s3 } from "../drivers/s3.mjs";
5
6
  //#region src/core/repository.ts
6
7
  var TableRepository;
7
8
  var init_repository = __esmMin((() => {
8
9
  init_file();
10
+ init_s3();
9
11
  init_sql_compiler();
10
12
  init_errors();
11
13
  TableRepository = class {
@@ -20,6 +22,8 @@ var init_repository = __esmMin((() => {
20
22
  tableCacheConfig;
21
23
  jsonColumns;
22
24
  jsonCodeKeys;
25
+ isFileLikeDriver;
26
+ dateColumns;
23
27
  constructor(tableName, driver, cache, registry, tableCacheConfig) {
24
28
  this.tableName = tableName;
25
29
  this.driver = driver;
@@ -38,6 +42,12 @@ var init_repository = __esmMin((() => {
38
42
  const codeKey = this.reverseColumnMap[col.name] ?? col.name;
39
43
  this.jsonCodeKeys.add(codeKey);
40
44
  }
45
+ this.dateColumns = /* @__PURE__ */ new Set();
46
+ for (const col of meta.columns) if (col.type === "datetime" || col.type === "timestamp") {
47
+ const codeKey = this.reverseColumnMap[col.name] ?? col.name;
48
+ this.dateColumns.add(codeKey);
49
+ }
50
+ this.isFileLikeDriver = driver instanceof FileDriver || driver instanceof S3Driver;
41
51
  }
42
52
  /**
43
53
  * Find all rows matching the query options
@@ -48,7 +58,7 @@ var init_repository = __esmMin((() => {
48
58
  return this.cache.getOrSetWithTableConfig(this.tableName, "find", options, async () => {
49
59
  const dbOptions = this.mapOptionsToDb(options);
50
60
  let rows;
51
- if (this.driver instanceof FileDriver) rows = this.mapRows(this.findFile(dbOptions));
61
+ if (this.isFileLikeDriver) rows = this.mapRows(this.findFile(dbOptions));
52
62
  else rows = this.mapRows(await this.findSQL(dbOptions));
53
63
  if (options?.with) rows = await this.loadRelations(rows, options.with);
54
64
  this.cacheEntities(rows);
@@ -75,7 +85,7 @@ var init_repository = __esmMin((() => {
75
85
  take: 1
76
86
  };
77
87
  let rows;
78
- if (this.driver instanceof FileDriver) rows = this.mapRows(this.findFile(opts));
88
+ if (this.isFileLikeDriver) rows = this.mapRows(this.findFile(opts));
79
89
  else rows = this.mapRows(await this.findSQL(opts));
80
90
  if (rows.length === 0) return null;
81
91
  if (options?.with) rows = await this.loadRelations(rows, options.with);
@@ -94,7 +104,7 @@ var init_repository = __esmMin((() => {
94
104
  if (!single) throw new QueryError("Insert data cannot be empty");
95
105
  this.cache.invalidateTable(this.tableName);
96
106
  const cleaned = this.toDbKeys(this.cleanData(single));
97
- if (this.driver instanceof FileDriver) {
107
+ if (this.isFileLikeDriver) {
98
108
  const id = this.driver.insertRow(this.tableName, cleaned);
99
109
  const pk = this.registry.getPrimaryKey(this.tableName);
100
110
  if (pk) cleaned[pk] = id;
@@ -119,7 +129,7 @@ var init_repository = __esmMin((() => {
119
129
  async insertMany(data) {
120
130
  if (data.length === 0) return [];
121
131
  this.cache.invalidateTable(this.tableName);
122
- if (this.driver instanceof FileDriver) {
132
+ if (this.isFileLikeDriver) {
123
133
  const results = [];
124
134
  for (const item of data) results.push(await this.insert(item));
125
135
  return results;
@@ -147,7 +157,7 @@ var init_repository = __esmMin((() => {
147
157
  this.cache.invalidateTable(this.tableName);
148
158
  const cleaned = this.toDbKeys(this.cleanData(options.data));
149
159
  const dbWhere = this.mapWhereToDb(options.where);
150
- if (this.driver instanceof FileDriver) {
160
+ if (this.isFileLikeDriver) {
151
161
  const filter = this.buildFileFilter(dbWhere);
152
162
  this.driver.updateRows(this.tableName, filter, cleaned);
153
163
  return this.find({ where: options.where });
@@ -166,7 +176,7 @@ var init_repository = __esmMin((() => {
166
176
  if (!options.where || Object.keys(options.where).length === 0) throw new QueryError("Delete requires a where clause");
167
177
  this.cache.invalidateTable(this.tableName);
168
178
  const dbWhere = this.mapWhereToDb(options.where);
169
- if (this.driver instanceof FileDriver) {
179
+ if (this.isFileLikeDriver) {
170
180
  const filter = this.buildFileFilter(dbWhere);
171
181
  return this.driver.deleteRows(this.tableName, filter);
172
182
  }
@@ -182,7 +192,7 @@ var init_repository = __esmMin((() => {
182
192
  async count(options) {
183
193
  return this.cache.getOrSetWithTableConfig(this.tableName, "count", options, async () => {
184
194
  const dbWhere = options?.where ? this.mapWhereToDb(options.where) : void 0;
185
- if (this.driver instanceof FileDriver) {
195
+ if (this.isFileLikeDriver) {
186
196
  const filter = dbWhere ? this.buildFileFilter(dbWhere) : void 0;
187
197
  return this.driver.countRows(this.tableName, filter);
188
198
  }
@@ -221,7 +231,7 @@ var init_repository = __esmMin((() => {
221
231
  */
222
232
  async truncate() {
223
233
  this.cache.invalidateTable(this.tableName);
224
- if (this.driver instanceof FileDriver) {
234
+ if (this.isFileLikeDriver) {
225
235
  this.driver.truncateTable(this.tableName);
226
236
  return;
227
237
  }
@@ -347,7 +357,7 @@ var init_repository = __esmMin((() => {
347
357
  return rows;
348
358
  }
349
359
  async findRelated(tableName, column, ids, options) {
350
- if (this.driver instanceof FileDriver) {
360
+ if (this.isFileLikeDriver) {
351
361
  const fd = this.driver;
352
362
  const filter = (row) => ids.includes(row[column]);
353
363
  return fd.findRows(tableName, filter);
@@ -367,7 +377,7 @@ var init_repository = __esmMin((() => {
367
377
  const cleaned = {};
368
378
  const dbColumnNames = new Set(this.meta.columns.map((c) => c.name));
369
379
  const codeKeys = new Set(Object.keys(this.columnMap));
370
- const shouldSerialize = !(this.driver instanceof FileDriver);
380
+ const shouldSerialize = !this.isFileLikeDriver;
371
381
  for (const [key, value] of Object.entries(data)) if (codeKeys.has(key) || dbColumnNames.has(key)) if (shouldSerialize && (this.jsonCodeKeys.has(key) || this.jsonColumns.has(key)) && value != null && typeof value === "object") cleaned[key] = JSON.stringify(value);
372
382
  else cleaned[key] = value;
373
383
  return cleaned;
@@ -420,15 +430,22 @@ var init_repository = __esmMin((() => {
420
430
  return mapped;
421
431
  }
422
432
  mapRows(rows) {
423
- const shouldDeserialize = this.jsonCodeKeys.size > 0 && !(this.driver instanceof FileDriver);
433
+ const shouldDeserialize = (this.jsonCodeKeys.size > 0 || this.dateColumns.size > 0) && !this.isFileLikeDriver;
424
434
  if (!this.hasAliases && !shouldDeserialize) return rows;
425
435
  return rows.map((row) => {
426
436
  const mapped = this.hasAliases ? this.toCodeKeys(row) : { ...row };
427
- if (shouldDeserialize) for (const key of this.jsonCodeKeys) {
428
- const val = mapped[key];
429
- if (typeof val === "string") try {
430
- mapped[key] = JSON.parse(val);
431
- } catch {}
437
+ if (shouldDeserialize) {
438
+ for (const key of this.jsonCodeKeys) {
439
+ const val = mapped[key];
440
+ if (typeof val === "string") try {
441
+ mapped[key] = JSON.parse(val);
442
+ } catch {}
443
+ }
444
+ for (const key of this.dateColumns) {
445
+ const val = mapped[key];
446
+ if (typeof val === "string") mapped[key] = new Date(val);
447
+ else if (typeof val === "number") mapped[key] = new Date(val);
448
+ }
432
449
  }
433
450
  return mapped;
434
451
  });
@@ -1 +1 @@
1
- {"version":3,"file":"repository.mjs","names":[],"sources":["../../src/core/repository.ts"],"sourcesContent":["import type { CacheManager } from \"../cache\";\nimport { FileDriver } from \"../drivers/file\";\nimport {\n compileBulkInsert,\n compileDelete,\n compileInsert,\n compileSelect,\n compileUpdate,\n compileWhere,\n} from \"../drivers/sql-compiler\";\nimport { QueryError } from \"../errors\";\nimport type { SchemaRegistry } from \"../schema\";\nimport type {\n DatabaseDriver,\n DeleteOptions,\n QueryOptions,\n Repository,\n TableMetadata,\n UpdateOptions,\n WhereClause,\n} from \"../types\";\n\n/**\n * Repository implementation that provides CRUD operations for a table\n * @template T - The row type for this table\n */\nexport class TableRepository<T extends Record<string, any>> implements Repository<T> {\n private tableName: string;\n private driver: DatabaseDriver;\n private cache: CacheManager;\n private registry: SchemaRegistry;\n private meta: TableMetadata;\n private columnMap: Record<string, string>;\n private reverseColumnMap: Record<string, string>;\n private hasAliases: boolean;\n private tableCacheConfig?: { enabled: boolean; ttl?: number; maxTtl?: number };\n private jsonColumns: Set<string>;\n private jsonCodeKeys: Set<string>;\n\n constructor(\n tableName: string,\n driver: DatabaseDriver,\n cache: CacheManager,\n registry: SchemaRegistry,\n tableCacheConfig?: { enabled: boolean; ttl?: number; maxTtl?: number },\n ) {\n this.tableName = tableName;\n this.driver = driver;\n this.cache = cache;\n this.registry = registry;\n this.tableCacheConfig = tableCacheConfig;\n const meta = registry.getTable(tableName);\n if (!meta) {\n throw new QueryError(`Table \"${tableName}\" is not registered`);\n }\n this.meta = meta;\n this.columnMap = registry.getColumnMap(tableName);\n this.reverseColumnMap = registry.getReverseColumnMap(tableName);\n this.hasAliases = Object.entries(this.columnMap).some(\n ([codeKey, dbName]) => codeKey !== dbName,\n );\n this.jsonColumns = new Set(\n meta.columns.filter((c) => c.type === \"json\" || c.type === \"array\").map((c) => c.name),\n );\n this.jsonCodeKeys = new Set<string>();\n for (const col of meta.columns) {\n if (col.type === \"json\" || col.type === \"array\") {\n const codeKey = this.reverseColumnMap[col.name] ?? col.name;\n this.jsonCodeKeys.add(codeKey);\n }\n }\n }\n\n /**\n * Find all rows matching the query options\n * @param {QueryOptions<T>} [options] - Query options\n * @returns {Promise<T[]>} Array of matching rows\n */\n async find(options?: QueryOptions<T>): Promise<T[]> {\n return this.cache.getOrSetWithTableConfig(\n this.tableName,\n \"find\",\n options,\n async () => {\n const dbOptions = this.mapOptionsToDb(options);\n let rows: T[];\n if (this.driver instanceof FileDriver) {\n rows = this.mapRows(this.findFile(dbOptions as QueryOptions<T>));\n } else {\n rows = this.mapRows(await this.findSQL(dbOptions as QueryOptions<T>));\n }\n if (options?.with) {\n rows = await this.loadRelations(rows, options.with);\n }\n this.cacheEntities(rows);\n return rows;\n },\n this.tableCacheConfig,\n );\n }\n\n /**\n * Find all rows matching the query options (alias for find)\n * @param {QueryOptions<T>} [options] - Query options\n * @returns {Promise<T[]>} Array of matching rows\n */\n async findMany(options?: QueryOptions<T>): Promise<T[]> {\n return this.find(options);\n }\n\n /**\n * Find the first row matching the query options\n * @param {QueryOptions<T>} [options] - Query options\n * @returns {Promise<T | null>} The first matching row or null\n */\n async findFirst(options?: QueryOptions<T>): Promise<T | null> {\n return this.cache.getOrSetWithTableConfig(\n this.tableName,\n \"findFirst\",\n options,\n async () => {\n const dbOptions = this.mapOptionsToDb(options);\n const opts = { ...dbOptions, take: 1 };\n let rows: T[];\n if (this.driver instanceof FileDriver) {\n rows = this.mapRows(this.findFile(opts as QueryOptions<T>));\n } else {\n rows = this.mapRows(await this.findSQL(opts as QueryOptions<T>));\n }\n if (rows.length === 0) {\n return null;\n }\n if (options?.with) {\n rows = await this.loadRelations(rows, options.with);\n }\n const row = rows[0] ?? null;\n if (row) {\n this.cacheEntity(row);\n }\n return row;\n },\n this.tableCacheConfig,\n );\n }\n\n /**\n * Insert one or more rows\n * @param {Partial<T> | Partial<T>[]} data - Data to insert\n * @returns {Promise<T>} The inserted row\n */\n async insert(data: Partial<T> | Partial<T>[]): Promise<T> {\n const single = Array.isArray(data) ? data[0] : data;\n if (!single) {\n throw new QueryError(\"Insert data cannot be empty\");\n }\n\n this.cache.invalidateTable(this.tableName);\n const cleaned = this.toDbKeys(this.cleanData(single));\n\n if (this.driver instanceof FileDriver) {\n const id = (this.driver as FileDriver).insertRow(this.tableName, cleaned);\n const pk = this.registry.getPrimaryKey(this.tableName);\n if (pk) {\n cleaned[pk] = id;\n }\n const result = this.toCodeKeys(cleaned) as T;\n this.cacheEntity(result);\n return result;\n }\n\n const params: unknown[] = [];\n const sql = compileInsert(this.tableName, cleaned, params);\n const result = await this.driver.execute(sql, params);\n\n const pk = this.registry.getPrimaryKey(this.tableName);\n if (pk && result.insertId) {\n cleaned[pk] = result.insertId;\n }\n\n const mapped = this.toCodeKeys(cleaned) as T;\n this.cacheEntity(mapped);\n return mapped;\n }\n\n /**\n * Insert multiple rows\n * @param {Partial<T>[]} data - Array of data to insert\n * @returns {Promise<T[]>} The inserted rows\n */\n async insertMany(data: Partial<T>[]): Promise<T[]> {\n if (data.length === 0) {\n return [];\n }\n\n this.cache.invalidateTable(this.tableName);\n\n if (this.driver instanceof FileDriver) {\n const results: T[] = [];\n for (const item of data) {\n results.push(await this.insert(item));\n }\n return results;\n }\n\n const cleanedData = data.map((item) => this.toDbKeys(this.cleanData(item)));\n const params: unknown[] = [];\n const sql = compileBulkInsert(this.tableName, cleanedData, params);\n const result = await this.driver.execute(sql, params);\n\n const pk = this.registry.getPrimaryKey(this.tableName);\n if (pk && result.insertId) {\n for (let i = 0; i < cleanedData.length; i++) {\n const row = cleanedData[i];\n if (row) {\n row[pk] = result.insertId + i;\n }\n }\n }\n\n const finalRows = this.mapRows(cleanedData);\n this.cacheEntities(finalRows);\n return finalRows;\n }\n\n /**\n * Update rows matching the where clause\n * @param {UpdateOptions<T>} options - Update options with where and data\n * @returns {Promise<T[]>} The updated rows\n */\n async update(options: UpdateOptions<T>): Promise<T[]> {\n if (!options.where || Object.keys(options.where).length === 0) {\n throw new QueryError(\"Update requires a where clause\");\n }\n\n this.cache.invalidateTable(this.tableName);\n const cleaned = this.toDbKeys(this.cleanData(options.data));\n const dbWhere = this.mapWhereToDb(options.where as WhereClause);\n\n if (this.driver instanceof FileDriver) {\n const filter = this.buildFileFilter(dbWhere);\n (this.driver as FileDriver).updateRows(this.tableName, filter, cleaned);\n return this.find({ where: options.where } as QueryOptions<T>);\n }\n\n const params: unknown[] = [];\n const sql = compileUpdate(this.tableName, cleaned, dbWhere, params);\n await this.driver.execute(sql, params);\n\n return this.find({ where: options.where } as QueryOptions<T>);\n }\n\n /**\n * Delete rows matching the where clause\n * @param {DeleteOptions<T>} options - Delete options with where clause\n * @returns {Promise<number>} Number of deleted rows\n */\n async delete(options: DeleteOptions<T>): Promise<number> {\n if (!options.where || Object.keys(options.where).length === 0) {\n throw new QueryError(\"Delete requires a where clause\");\n }\n\n this.cache.invalidateTable(this.tableName);\n const dbWhere = this.mapWhereToDb(options.where as WhereClause);\n\n if (this.driver instanceof FileDriver) {\n const filter = this.buildFileFilter(dbWhere);\n return (this.driver as FileDriver).deleteRows(this.tableName, filter);\n }\n\n const params: unknown[] = [];\n const sql = compileDelete(this.tableName, dbWhere, params);\n const result = await this.driver.execute(sql, params);\n return result.affectedRows;\n }\n\n /**\n * Count rows matching the where clause\n * @param {Pick<QueryOptions<T>, \"where\">} [options] - Count options\n * @returns {Promise<number>} Row count\n */\n async count(options?: Pick<QueryOptions<T>, \"where\">): Promise<number> {\n return this.cache.getOrSetWithTableConfig(\n this.tableName,\n \"count\",\n options,\n async () => {\n const dbWhere = options?.where\n ? this.mapWhereToDb(options.where as WhereClause)\n : undefined;\n\n if (this.driver instanceof FileDriver) {\n const filter = dbWhere ? this.buildFileFilter(dbWhere) : undefined;\n return (this.driver as FileDriver).countRows(this.tableName, filter);\n }\n\n const params: unknown[] = [];\n let sql = `SELECT COUNT(*) as count FROM \\`${this.tableName}\\``;\n if (dbWhere && Object.keys(dbWhere).length > 0) {\n sql += ` WHERE ${compileWhere(dbWhere, params)}`;\n }\n const rows = await this.driver.query(sql, params);\n return rows[0]?.count ?? 0;\n },\n this.tableCacheConfig,\n );\n }\n\n /**\n * Check if any row exists matching the where clause\n * @param {Pick<QueryOptions<T>, \"where\">} options - Exists options\n * @returns {Promise<boolean>} Whether a matching row exists\n */\n async exists(options: Pick<QueryOptions<T>, \"where\">): Promise<boolean> {\n const c = await this.count(options);\n return c > 0;\n }\n\n /**\n * Insert or update a row based on the where clause\n * @param {object} options - Upsert options\n * @param {WhereClause<T>} options.where - Condition to check\n * @param {Partial<T>} options.create - Data to insert if not found\n * @param {Partial<T>} options.update - Data to update if found\n * @returns {Promise<T>} The upserted row\n */\n async upsert(options: {\n where: WhereClause<T>;\n create: Partial<T>;\n update: Partial<T>;\n }): Promise<T> {\n const existing = await this.findFirst({ where: options.where } as QueryOptions<T>);\n if (existing) {\n const updated = await this.update({ where: options.where, data: options.update });\n return updated[0] ?? existing;\n }\n return this.insert(options.create);\n }\n\n /**\n * Remove all rows from the table\n */\n async truncate(): Promise<void> {\n this.cache.invalidateTable(this.tableName);\n if (this.driver instanceof FileDriver) {\n (this.driver as FileDriver).truncateTable(this.tableName);\n return;\n }\n await this.driver.execute(`DELETE FROM \\`${this.tableName}\\``);\n }\n\n private async findSQL(options?: QueryOptions<T>): Promise<T[]> {\n const params: unknown[] = [];\n const sql = compileSelect(\n this.tableName,\n {\n select: options?.select as string[] | undefined,\n where: options?.where as WhereClause | undefined,\n orderBy: options?.orderBy as Record<string, \"asc\" | \"desc\"> | undefined,\n take: options?.take,\n skip: options?.skip,\n },\n params,\n );\n return this.driver.query(sql, params);\n }\n\n private findFile(options?: QueryOptions<T>): T[] {\n const fd = this.driver as FileDriver;\n const filter = options?.where ? this.buildFileFilter(options.where as WhereClause) : undefined;\n let rows = fd.findRows(this.tableName, filter) as T[];\n\n if (options?.select) {\n const selectSet = new Set(options.select as string[]);\n rows = rows.map((row) => {\n const filtered: Record<string, any> = {};\n for (const key of selectSet) {\n filtered[key as string] = row[key as string];\n }\n return filtered as T;\n });\n }\n\n if (options?.orderBy) {\n const entries = Object.entries(options.orderBy);\n rows.sort((a, b) => {\n for (const [col, dir] of entries) {\n const av = a[col];\n const bv = b[col];\n if (av < bv) {\n return dir === \"asc\" ? -1 : 1;\n }\n if (av > bv) {\n return dir === \"asc\" ? 1 : -1;\n }\n }\n return 0;\n });\n }\n\n if (options?.skip) {\n rows = rows.slice(options.skip);\n }\n if (options?.take) {\n rows = rows.slice(0, options.take);\n }\n\n return rows;\n }\n\n private buildFileFilter(where: WhereClause): (row: Record<string, unknown>) => boolean {\n return (row) => this.matchWhere(row, where);\n }\n\n private matchWhere(row: Record<string, unknown>, where: WhereClause): boolean {\n for (const [key, value] of Object.entries(where)) {\n if (key === \"OR\" && Array.isArray(value)) {\n const any = (value as WhereClause[]).some((sub) => this.matchWhere(row, sub));\n if (!any) {\n return false;\n }\n continue;\n }\n if (key === \"AND\" && Array.isArray(value)) {\n const all = (value as WhereClause[]).every((sub) => this.matchWhere(row, sub));\n if (!all) {\n return false;\n }\n continue;\n }\n\n if (value !== null && typeof value === \"object\" && !Array.isArray(value)) {\n const cond = value as any;\n const rowVal = row[key];\n if (cond.eq !== undefined && rowVal !== cond.eq) {\n return false;\n }\n if (cond.neq !== undefined && rowVal === cond.neq) {\n return false;\n }\n if (cond.gt !== undefined && !((rowVal as any) > cond.gt)) {\n return false;\n }\n if (cond.gte !== undefined && !((rowVal as any) >= cond.gte)) {\n return false;\n }\n if (cond.lt !== undefined && !((rowVal as any) < cond.lt)) {\n return false;\n }\n if (cond.lte !== undefined && !((rowVal as any) <= cond.lte)) {\n return false;\n }\n if (\n cond.like !== undefined &&\n !String(rowVal).match(new RegExp(cond.like.replace(/%/g, \".*\"), \"i\"))\n ) {\n return false;\n }\n if (\n cond.notLike !== undefined &&\n String(rowVal).match(new RegExp(cond.notLike.replace(/%/g, \".*\"), \"i\"))\n ) {\n return false;\n }\n if (cond.in !== undefined && !cond.in.includes(rowVal)) {\n return false;\n }\n if (cond.notIn?.includes(rowVal)) {\n return false;\n }\n if (cond.isNull === true && rowVal !== null && rowVal !== undefined) {\n return false;\n }\n if (cond.isNull === false && (rowVal === null || rowVal === undefined)) {\n return false;\n }\n if (cond.between !== undefined) {\n if ((rowVal as any) < cond.between[0] || (rowVal as any) > cond.between[1]) {\n return false;\n }\n }\n } else {\n if (row[key] !== value) {\n return false;\n }\n }\n }\n return true;\n }\n\n private async loadRelations(\n rows: T[],\n withOpts: Record<string, boolean | QueryOptions>,\n ): Promise<T[]> {\n if (rows.length === 0) {\n return rows;\n }\n const relations = this.registry.getRelations(this.tableName);\n\n for (const [relationName, opts] of Object.entries(withOpts)) {\n if (!opts) {\n continue;\n }\n const relation = relations.find((r) => r.relationName === relationName);\n if (!relation) {\n continue;\n }\n\n const isParent = relation.from.table === this.tableName;\n if (isParent) {\n const ids = rows.map((r) => r[relation.from.column]).filter((v) => v != null);\n if (ids.length === 0) {\n continue;\n }\n const uniqueIds = [...new Set(ids)];\n const relatedOpts: QueryOptions = typeof opts === \"object\" ? opts : {};\n const related = await this.findRelated(\n relation.to.table,\n relation.to.column,\n uniqueIds,\n relatedOpts,\n );\n const relatedMap = new Map<unknown, unknown[]>();\n for (const r of related) {\n const key = (r as any)[relation.to.column];\n if (!relatedMap.has(key)) {\n relatedMap.set(key, []);\n }\n relatedMap.get(key)!.push(r);\n }\n for (const row of rows) {\n const key = row[relation.from.column];\n const relRows = relatedMap.get(key);\n (row as any)[relationName] = relRows ?? [];\n }\n } else {\n const pk = this.registry.getPrimaryKey(this.tableName);\n if (!pk) {\n continue;\n }\n const ids = rows.map((r) => r[pk]).filter((v) => v != null);\n if (ids.length === 0) {\n continue;\n }\n const uniqueIds = [...new Set(ids)];\n const relatedOpts: QueryOptions = typeof opts === \"object\" ? opts : {};\n const related = await this.findRelated(\n relation.to.table,\n relation.to.column,\n uniqueIds,\n relatedOpts,\n );\n const relatedMap = new Map<unknown, unknown[]>();\n for (const r of related) {\n const key = (r as any)[relation.to.column];\n if (!relatedMap.has(key)) {\n relatedMap.set(key, []);\n }\n relatedMap.get(key)!.push(r);\n }\n for (const row of rows) {\n const key = row[pk];\n (row as any)[relationName] = relatedMap.get(key) ?? [];\n }\n }\n }\n\n return rows;\n }\n\n private async findRelated(\n tableName: string,\n column: string,\n ids: unknown[],\n options: QueryOptions,\n ): Promise<any[]> {\n if (this.driver instanceof FileDriver) {\n const fd = this.driver as FileDriver;\n const filter = (row: Record<string, unknown>) => ids.includes(row[column]);\n return fd.findRows(tableName, filter);\n }\n\n const params: unknown[] = [];\n const placeholders = ids.map(() => \"?\").join(\", \");\n params.push(...ids);\n\n let sql = `SELECT * FROM \\`${tableName}\\` WHERE \\`${column}\\` IN (${placeholders})`;\n if (options.orderBy) {\n const orderParts = Object.entries(options.orderBy).map(\n ([col, dir]) => `\\`${col}\\` ${(dir as string).toUpperCase()}`,\n );\n if (orderParts.length > 0) {\n sql += ` ORDER BY ${orderParts.join(\", \")}`;\n }\n }\n if (options.take) {\n sql += ` LIMIT ${options.take}`;\n }\n\n return this.driver.query(sql, params);\n }\n\n private cleanData(data: Partial<T>): Record<string, unknown> {\n const cleaned: Record<string, unknown> = {};\n const dbColumnNames = new Set(this.meta.columns.map((c) => c.name));\n const codeKeys = new Set(Object.keys(this.columnMap));\n const shouldSerialize = !(this.driver instanceof FileDriver);\n for (const [key, value] of Object.entries(data as Record<string, unknown>)) {\n if (codeKeys.has(key) || dbColumnNames.has(key)) {\n if (\n shouldSerialize &&\n (this.jsonCodeKeys.has(key) || this.jsonColumns.has(key)) &&\n value != null &&\n typeof value === \"object\"\n ) {\n cleaned[key] = JSON.stringify(value);\n } else {\n cleaned[key] = value;\n }\n }\n }\n return cleaned;\n }\n\n private cacheEntities(rows: T[]): void {\n const pk = this.registry.getPrimaryKey(this.tableName);\n if (!pk) {\n return;\n }\n for (const row of rows) {\n if (row[pk] != null) {\n this.cache.setEntity(this.tableName, row[pk], row);\n }\n }\n }\n\n private cacheEntity(row: T): void {\n const pk = this.registry.getPrimaryKey(this.tableName);\n if (!pk || row[pk] == null) {\n return;\n }\n this.cache.setEntity(this.tableName, row[pk], row);\n }\n\n private toDbKeys(data: Record<string, unknown>): Record<string, unknown> {\n if (!this.hasAliases) {\n return data;\n }\n const result: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(data)) {\n result[this.columnMap[key] ?? key] = value;\n }\n return result;\n }\n\n private toCodeKeys(row: Record<string, unknown>): Record<string, unknown> {\n if (!this.hasAliases) {\n return row;\n }\n const result: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(row)) {\n result[this.reverseColumnMap[key] ?? key] = value;\n }\n return result;\n }\n\n private mapWhereToDb(where: WhereClause): WhereClause {\n if (!this.hasAliases) {\n return where;\n }\n const result: WhereClause = {};\n for (const [key, value] of Object.entries(where)) {\n if (key === \"OR\" || key === \"AND\") {\n (result as any)[key] = (value as WhereClause[]).map((sub) => this.mapWhereToDb(sub));\n } else {\n result[this.columnMap[key] ?? key] = value;\n }\n }\n return result;\n }\n\n private mapSelectToDb(select: string[]): string[] {\n if (!this.hasAliases) {\n return select;\n }\n return select.map((key) => this.columnMap[key] ?? key);\n }\n\n private mapOrderByToDb(orderBy: Record<string, \"asc\" | \"desc\">): Record<string, \"asc\" | \"desc\"> {\n if (!this.hasAliases) {\n return orderBy;\n }\n const result: Record<string, \"asc\" | \"desc\"> = {};\n for (const [key, value] of Object.entries(orderBy)) {\n result[this.columnMap[key] ?? key] = value;\n }\n return result;\n }\n\n private mapOptionsToDb(options?: QueryOptions<T>): QueryOptions | undefined {\n if (!options || !this.hasAliases) {\n return options as QueryOptions | undefined;\n }\n const mapped: QueryOptions = { ...options } as any;\n if (options.where) {\n mapped.where = this.mapWhereToDb(options.where as WhereClause);\n }\n if (options.select) {\n mapped.select = this.mapSelectToDb(options.select);\n }\n if (options.orderBy) {\n mapped.orderBy = this.mapOrderByToDb(options.orderBy as Record<string, \"asc\" | \"desc\">);\n }\n return mapped;\n }\n\n private mapRows(rows: Record<string, unknown>[]): T[] {\n const shouldDeserialize = this.jsonCodeKeys.size > 0 && !(this.driver instanceof FileDriver);\n if (!this.hasAliases && !shouldDeserialize) {\n return rows as T[];\n }\n return rows.map((row) => {\n const mapped = this.hasAliases ? this.toCodeKeys(row) : { ...row };\n if (shouldDeserialize) {\n for (const key of this.jsonCodeKeys) {\n const val = mapped[key];\n if (typeof val === \"string\") {\n try {\n mapped[key] = JSON.parse(val);\n } catch {}\n }\n }\n }\n return mapped as T;\n });\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"repository.mjs","names":[],"sources":["../../src/core/repository.ts"],"sourcesContent":["import type { CacheManager } from \"../cache\";\nimport { FileDriver } from \"../drivers/file\";\nimport { S3Driver } from \"../drivers/s3\";\nimport {\n compileBulkInsert,\n compileDelete,\n compileInsert,\n compileSelect,\n compileUpdate,\n compileWhere,\n} from \"../drivers/sql-compiler\";\nimport { QueryError } from \"../errors\";\nimport type { SchemaRegistry } from \"../schema\";\nimport type {\n DatabaseDriver,\n DeleteOptions,\n QueryOptions,\n Repository,\n TableMetadata,\n UpdateOptions,\n WhereClause,\n} from \"../types\";\n\n/**\n * Repository implementation that provides CRUD operations for a table\n * @template T - The row type for this table\n */\nexport class TableRepository<T extends Record<string, any>> implements Repository<T> {\n private tableName: string;\n private driver: DatabaseDriver;\n private cache: CacheManager;\n private registry: SchemaRegistry;\n private meta: TableMetadata;\n private columnMap: Record<string, string>;\n private reverseColumnMap: Record<string, string>;\n private hasAliases: boolean;\n private tableCacheConfig?: { enabled: boolean; ttl?: number; maxTtl?: number };\n private jsonColumns: Set<string>;\n private jsonCodeKeys: Set<string>;\n private isFileLikeDriver: boolean;\n private dateColumns: Set<string>;\n\n constructor(\n tableName: string,\n driver: DatabaseDriver,\n cache: CacheManager,\n registry: SchemaRegistry,\n tableCacheConfig?: { enabled: boolean; ttl?: number; maxTtl?: number },\n ) {\n this.tableName = tableName;\n this.driver = driver;\n this.cache = cache;\n this.registry = registry;\n this.tableCacheConfig = tableCacheConfig;\n const meta = registry.getTable(tableName);\n if (!meta) {\n throw new QueryError(`Table \"${tableName}\" is not registered`);\n }\n this.meta = meta;\n this.columnMap = registry.getColumnMap(tableName);\n this.reverseColumnMap = registry.getReverseColumnMap(tableName);\n this.hasAliases = Object.entries(this.columnMap).some(\n ([codeKey, dbName]) => codeKey !== dbName,\n );\n this.jsonColumns = new Set(\n meta.columns.filter((c) => c.type === \"json\" || c.type === \"array\").map((c) => c.name),\n );\n this.jsonCodeKeys = new Set<string>();\n for (const col of meta.columns) {\n if (col.type === \"json\" || col.type === \"array\") {\n const codeKey = this.reverseColumnMap[col.name] ?? col.name;\n this.jsonCodeKeys.add(codeKey);\n }\n }\n this.dateColumns = new Set<string>();\n for (const col of meta.columns) {\n if (col.type === \"datetime\" || col.type === \"timestamp\") {\n const codeKey = this.reverseColumnMap[col.name] ?? col.name;\n this.dateColumns.add(codeKey);\n }\n }\n this.isFileLikeDriver = driver instanceof FileDriver || driver instanceof S3Driver;\n }\n\n /**\n * Find all rows matching the query options\n * @param {QueryOptions<T>} [options] - Query options\n * @returns {Promise<T[]>} Array of matching rows\n */\n async find(options?: QueryOptions<T>): Promise<T[]> {\n return this.cache.getOrSetWithTableConfig(\n this.tableName,\n \"find\",\n options,\n async () => {\n const dbOptions = this.mapOptionsToDb(options);\n let rows: T[];\n if (this.isFileLikeDriver) {\n rows = this.mapRows(this.findFile(dbOptions as QueryOptions<T>));\n } else {\n rows = this.mapRows(await this.findSQL(dbOptions as QueryOptions<T>));\n }\n if (options?.with) {\n rows = await this.loadRelations(rows, options.with);\n }\n this.cacheEntities(rows);\n return rows;\n },\n this.tableCacheConfig,\n );\n }\n\n /**\n * Find all rows matching the query options (alias for find)\n * @param {QueryOptions<T>} [options] - Query options\n * @returns {Promise<T[]>} Array of matching rows\n */\n async findMany(options?: QueryOptions<T>): Promise<T[]> {\n return this.find(options);\n }\n\n /**\n * Find the first row matching the query options\n * @param {QueryOptions<T>} [options] - Query options\n * @returns {Promise<T | null>} The first matching row or null\n */\n async findFirst(options?: QueryOptions<T>): Promise<T | null> {\n return this.cache.getOrSetWithTableConfig(\n this.tableName,\n \"findFirst\",\n options,\n async () => {\n const dbOptions = this.mapOptionsToDb(options);\n const opts = { ...dbOptions, take: 1 };\n let rows: T[];\n if (this.isFileLikeDriver) {\n rows = this.mapRows(this.findFile(opts as QueryOptions<T>));\n } else {\n rows = this.mapRows(await this.findSQL(opts as QueryOptions<T>));\n }\n if (rows.length === 0) {\n return null;\n }\n if (options?.with) {\n rows = await this.loadRelations(rows, options.with);\n }\n const row = rows[0] ?? null;\n if (row) {\n this.cacheEntity(row);\n }\n return row;\n },\n this.tableCacheConfig,\n );\n }\n\n /**\n * Insert one or more rows\n * @param {Partial<T> | Partial<T>[]} data - Data to insert\n * @returns {Promise<T>} The inserted row\n */\n async insert(data: Partial<T> | Partial<T>[]): Promise<T> {\n const single = Array.isArray(data) ? data[0] : data;\n if (!single) {\n throw new QueryError(\"Insert data cannot be empty\");\n }\n\n this.cache.invalidateTable(this.tableName);\n const cleaned = this.toDbKeys(this.cleanData(single));\n\n if (this.isFileLikeDriver) {\n const id = (this.driver as FileDriver | S3Driver).insertRow(this.tableName, cleaned);\n const pk = this.registry.getPrimaryKey(this.tableName);\n if (pk) {\n cleaned[pk] = id;\n }\n const result = this.toCodeKeys(cleaned) as T;\n this.cacheEntity(result);\n return result;\n }\n\n const params: unknown[] = [];\n const sql = compileInsert(this.tableName, cleaned, params);\n const result = await this.driver.execute(sql, params);\n\n const pk = this.registry.getPrimaryKey(this.tableName);\n if (pk && result.insertId) {\n cleaned[pk] = result.insertId;\n }\n\n const mapped = this.toCodeKeys(cleaned) as T;\n this.cacheEntity(mapped);\n return mapped;\n }\n\n /**\n * Insert multiple rows\n * @param {Partial<T>[]} data - Array of data to insert\n * @returns {Promise<T[]>} The inserted rows\n */\n async insertMany(data: Partial<T>[]): Promise<T[]> {\n if (data.length === 0) {\n return [];\n }\n\n this.cache.invalidateTable(this.tableName);\n\n if (this.isFileLikeDriver) {\n const results: T[] = [];\n for (const item of data) {\n results.push(await this.insert(item));\n }\n return results;\n }\n\n const cleanedData = data.map((item) => this.toDbKeys(this.cleanData(item)));\n const params: unknown[] = [];\n const sql = compileBulkInsert(this.tableName, cleanedData, params);\n const result = await this.driver.execute(sql, params);\n\n const pk = this.registry.getPrimaryKey(this.tableName);\n if (pk && result.insertId) {\n for (let i = 0; i < cleanedData.length; i++) {\n const row = cleanedData[i];\n if (row) {\n row[pk] = result.insertId + i;\n }\n }\n }\n\n const finalRows = this.mapRows(cleanedData);\n this.cacheEntities(finalRows);\n return finalRows;\n }\n\n /**\n * Update rows matching the where clause\n * @param {UpdateOptions<T>} options - Update options with where and data\n * @returns {Promise<T[]>} The updated rows\n */\n async update(options: UpdateOptions<T>): Promise<T[]> {\n if (!options.where || Object.keys(options.where).length === 0) {\n throw new QueryError(\"Update requires a where clause\");\n }\n\n this.cache.invalidateTable(this.tableName);\n const cleaned = this.toDbKeys(this.cleanData(options.data));\n const dbWhere = this.mapWhereToDb(options.where as WhereClause);\n\n if (this.isFileLikeDriver) {\n const filter = this.buildFileFilter(dbWhere);\n (this.driver as FileDriver | S3Driver).updateRows(this.tableName, filter, cleaned);\n return this.find({ where: options.where } as QueryOptions<T>);\n }\n\n const params: unknown[] = [];\n const sql = compileUpdate(this.tableName, cleaned, dbWhere, params);\n await this.driver.execute(sql, params);\n\n return this.find({ where: options.where } as QueryOptions<T>);\n }\n\n /**\n * Delete rows matching the where clause\n * @param {DeleteOptions<T>} options - Delete options with where clause\n * @returns {Promise<number>} Number of deleted rows\n */\n async delete(options: DeleteOptions<T>): Promise<number> {\n if (!options.where || Object.keys(options.where).length === 0) {\n throw new QueryError(\"Delete requires a where clause\");\n }\n\n this.cache.invalidateTable(this.tableName);\n const dbWhere = this.mapWhereToDb(options.where as WhereClause);\n\n if (this.isFileLikeDriver) {\n const filter = this.buildFileFilter(dbWhere);\n return (this.driver as FileDriver | S3Driver).deleteRows(this.tableName, filter);\n }\n\n const params: unknown[] = [];\n const sql = compileDelete(this.tableName, dbWhere, params);\n const result = await this.driver.execute(sql, params);\n return result.affectedRows;\n }\n\n /**\n * Count rows matching the where clause\n * @param {Pick<QueryOptions<T>, \"where\">} [options] - Count options\n * @returns {Promise<number>} Row count\n */\n async count(options?: Pick<QueryOptions<T>, \"where\">): Promise<number> {\n return this.cache.getOrSetWithTableConfig(\n this.tableName,\n \"count\",\n options,\n async () => {\n const dbWhere = options?.where\n ? this.mapWhereToDb(options.where as WhereClause)\n : undefined;\n\n if (this.isFileLikeDriver) {\n const filter = dbWhere ? this.buildFileFilter(dbWhere) : undefined;\n return (this.driver as FileDriver | S3Driver).countRows(this.tableName, filter);\n }\n\n const params: unknown[] = [];\n let sql = `SELECT COUNT(*) as count FROM \\`${this.tableName}\\``;\n if (dbWhere && Object.keys(dbWhere).length > 0) {\n sql += ` WHERE ${compileWhere(dbWhere, params)}`;\n }\n const rows = await this.driver.query(sql, params);\n return rows[0]?.count ?? 0;\n },\n this.tableCacheConfig,\n );\n }\n\n /**\n * Check if any row exists matching the where clause\n * @param {Pick<QueryOptions<T>, \"where\">} options - Exists options\n * @returns {Promise<boolean>} Whether a matching row exists\n */\n async exists(options: Pick<QueryOptions<T>, \"where\">): Promise<boolean> {\n const c = await this.count(options);\n return c > 0;\n }\n\n /**\n * Insert or update a row based on the where clause\n * @param {object} options - Upsert options\n * @param {WhereClause<T>} options.where - Condition to check\n * @param {Partial<T>} options.create - Data to insert if not found\n * @param {Partial<T>} options.update - Data to update if found\n * @returns {Promise<T>} The upserted row\n */\n async upsert(options: {\n where: WhereClause<T>;\n create: Partial<T>;\n update: Partial<T>;\n }): Promise<T> {\n const existing = await this.findFirst({ where: options.where } as QueryOptions<T>);\n if (existing) {\n const updated = await this.update({ where: options.where, data: options.update });\n return updated[0] ?? existing;\n }\n return this.insert(options.create);\n }\n\n /**\n * Remove all rows from the table\n */\n async truncate(): Promise<void> {\n this.cache.invalidateTable(this.tableName);\n if (this.isFileLikeDriver) {\n (this.driver as FileDriver | S3Driver).truncateTable(this.tableName);\n return;\n }\n await this.driver.execute(`DELETE FROM \\`${this.tableName}\\``);\n }\n\n private async findSQL(options?: QueryOptions<T>): Promise<T[]> {\n const params: unknown[] = [];\n const sql = compileSelect(\n this.tableName,\n {\n select: options?.select as string[] | undefined,\n where: options?.where as WhereClause | undefined,\n orderBy: options?.orderBy as Record<string, \"asc\" | \"desc\"> | undefined,\n take: options?.take,\n skip: options?.skip,\n },\n params,\n );\n return this.driver.query(sql, params);\n }\n\n private findFile(options?: QueryOptions<T>): T[] {\n const fd = this.driver as FileDriver | S3Driver;\n const filter = options?.where ? this.buildFileFilter(options.where as WhereClause) : undefined;\n let rows = fd.findRows(this.tableName, filter) as T[];\n\n if (options?.select) {\n const selectSet = new Set(options.select as string[]);\n rows = rows.map((row) => {\n const filtered: Record<string, any> = {};\n for (const key of selectSet) {\n filtered[key as string] = row[key as string];\n }\n return filtered as T;\n });\n }\n\n if (options?.orderBy) {\n const entries = Object.entries(options.orderBy);\n rows.sort((a, b) => {\n for (const [col, dir] of entries) {\n const av = a[col];\n const bv = b[col];\n if (av < bv) {\n return dir === \"asc\" ? -1 : 1;\n }\n if (av > bv) {\n return dir === \"asc\" ? 1 : -1;\n }\n }\n return 0;\n });\n }\n\n if (options?.skip) {\n rows = rows.slice(options.skip);\n }\n if (options?.take) {\n rows = rows.slice(0, options.take);\n }\n\n return rows;\n }\n\n private buildFileFilter(where: WhereClause): (row: Record<string, unknown>) => boolean {\n return (row) => this.matchWhere(row, where);\n }\n\n private matchWhere(row: Record<string, unknown>, where: WhereClause): boolean {\n for (const [key, value] of Object.entries(where)) {\n if (key === \"OR\" && Array.isArray(value)) {\n const any = (value as WhereClause[]).some((sub) => this.matchWhere(row, sub));\n if (!any) {\n return false;\n }\n continue;\n }\n if (key === \"AND\" && Array.isArray(value)) {\n const all = (value as WhereClause[]).every((sub) => this.matchWhere(row, sub));\n if (!all) {\n return false;\n }\n continue;\n }\n\n if (value !== null && typeof value === \"object\" && !Array.isArray(value)) {\n const cond = value as any;\n const rowVal = row[key];\n if (cond.eq !== undefined && rowVal !== cond.eq) {\n return false;\n }\n if (cond.neq !== undefined && rowVal === cond.neq) {\n return false;\n }\n if (cond.gt !== undefined && !((rowVal as any) > cond.gt)) {\n return false;\n }\n if (cond.gte !== undefined && !((rowVal as any) >= cond.gte)) {\n return false;\n }\n if (cond.lt !== undefined && !((rowVal as any) < cond.lt)) {\n return false;\n }\n if (cond.lte !== undefined && !((rowVal as any) <= cond.lte)) {\n return false;\n }\n if (\n cond.like !== undefined &&\n !String(rowVal).match(new RegExp(cond.like.replace(/%/g, \".*\"), \"i\"))\n ) {\n return false;\n }\n if (\n cond.notLike !== undefined &&\n String(rowVal).match(new RegExp(cond.notLike.replace(/%/g, \".*\"), \"i\"))\n ) {\n return false;\n }\n if (cond.in !== undefined && !cond.in.includes(rowVal)) {\n return false;\n }\n if (cond.notIn?.includes(rowVal)) {\n return false;\n }\n if (cond.isNull === true && rowVal !== null && rowVal !== undefined) {\n return false;\n }\n if (cond.isNull === false && (rowVal === null || rowVal === undefined)) {\n return false;\n }\n if (cond.between !== undefined) {\n if ((rowVal as any) < cond.between[0] || (rowVal as any) > cond.between[1]) {\n return false;\n }\n }\n } else {\n if (row[key] !== value) {\n return false;\n }\n }\n }\n return true;\n }\n\n private async loadRelations(\n rows: T[],\n withOpts: Record<string, boolean | QueryOptions>,\n ): Promise<T[]> {\n if (rows.length === 0) {\n return rows;\n }\n const relations = this.registry.getRelations(this.tableName);\n\n for (const [relationName, opts] of Object.entries(withOpts)) {\n if (!opts) {\n continue;\n }\n const relation = relations.find((r) => r.relationName === relationName);\n if (!relation) {\n continue;\n }\n\n const isParent = relation.from.table === this.tableName;\n if (isParent) {\n const ids = rows.map((r) => r[relation.from.column]).filter((v) => v != null);\n if (ids.length === 0) {\n continue;\n }\n const uniqueIds = [...new Set(ids)];\n const relatedOpts: QueryOptions = typeof opts === \"object\" ? opts : {};\n const related = await this.findRelated(\n relation.to.table,\n relation.to.column,\n uniqueIds,\n relatedOpts,\n );\n const relatedMap = new Map<unknown, unknown[]>();\n for (const r of related) {\n const key = (r as any)[relation.to.column];\n if (!relatedMap.has(key)) {\n relatedMap.set(key, []);\n }\n relatedMap.get(key)!.push(r);\n }\n for (const row of rows) {\n const key = row[relation.from.column];\n const relRows = relatedMap.get(key);\n (row as any)[relationName] = relRows ?? [];\n }\n } else {\n const pk = this.registry.getPrimaryKey(this.tableName);\n if (!pk) {\n continue;\n }\n const ids = rows.map((r) => r[pk]).filter((v) => v != null);\n if (ids.length === 0) {\n continue;\n }\n const uniqueIds = [...new Set(ids)];\n const relatedOpts: QueryOptions = typeof opts === \"object\" ? opts : {};\n const related = await this.findRelated(\n relation.to.table,\n relation.to.column,\n uniqueIds,\n relatedOpts,\n );\n const relatedMap = new Map<unknown, unknown[]>();\n for (const r of related) {\n const key = (r as any)[relation.to.column];\n if (!relatedMap.has(key)) {\n relatedMap.set(key, []);\n }\n relatedMap.get(key)!.push(r);\n }\n for (const row of rows) {\n const key = row[pk];\n (row as any)[relationName] = relatedMap.get(key) ?? [];\n }\n }\n }\n\n return rows;\n }\n\n private async findRelated(\n tableName: string,\n column: string,\n ids: unknown[],\n options: QueryOptions,\n ): Promise<any[]> {\n if (this.isFileLikeDriver) {\n const fd = this.driver as FileDriver | S3Driver;\n const filter = (row: Record<string, unknown>) => ids.includes(row[column]);\n return fd.findRows(tableName, filter);\n }\n\n const params: unknown[] = [];\n const placeholders = ids.map(() => \"?\").join(\", \");\n params.push(...ids);\n\n let sql = `SELECT * FROM \\`${tableName}\\` WHERE \\`${column}\\` IN (${placeholders})`;\n if (options.orderBy) {\n const orderParts = Object.entries(options.orderBy).map(\n ([col, dir]) => `\\`${col}\\` ${(dir as string).toUpperCase()}`,\n );\n if (orderParts.length > 0) {\n sql += ` ORDER BY ${orderParts.join(\", \")}`;\n }\n }\n if (options.take) {\n sql += ` LIMIT ${options.take}`;\n }\n\n return this.driver.query(sql, params);\n }\n\n private cleanData(data: Partial<T>): Record<string, unknown> {\n const cleaned: Record<string, unknown> = {};\n const dbColumnNames = new Set(this.meta.columns.map((c) => c.name));\n const codeKeys = new Set(Object.keys(this.columnMap));\n const shouldSerialize = !this.isFileLikeDriver;\n for (const [key, value] of Object.entries(data as Record<string, unknown>)) {\n if (codeKeys.has(key) || dbColumnNames.has(key)) {\n if (\n shouldSerialize &&\n (this.jsonCodeKeys.has(key) || this.jsonColumns.has(key)) &&\n value != null &&\n typeof value === \"object\"\n ) {\n cleaned[key] = JSON.stringify(value);\n } else {\n cleaned[key] = value;\n }\n }\n }\n return cleaned;\n }\n\n private cacheEntities(rows: T[]): void {\n const pk = this.registry.getPrimaryKey(this.tableName);\n if (!pk) {\n return;\n }\n for (const row of rows) {\n if (row[pk] != null) {\n this.cache.setEntity(this.tableName, row[pk], row);\n }\n }\n }\n\n private cacheEntity(row: T): void {\n const pk = this.registry.getPrimaryKey(this.tableName);\n if (!pk || row[pk] == null) {\n return;\n }\n this.cache.setEntity(this.tableName, row[pk], row);\n }\n\n private toDbKeys(data: Record<string, unknown>): Record<string, unknown> {\n if (!this.hasAliases) {\n return data;\n }\n const result: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(data)) {\n result[this.columnMap[key] ?? key] = value;\n }\n return result;\n }\n\n private toCodeKeys(row: Record<string, unknown>): Record<string, unknown> {\n if (!this.hasAliases) {\n return row;\n }\n const result: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(row)) {\n result[this.reverseColumnMap[key] ?? key] = value;\n }\n return result;\n }\n\n private mapWhereToDb(where: WhereClause): WhereClause {\n if (!this.hasAliases) {\n return where;\n }\n const result: WhereClause = {};\n for (const [key, value] of Object.entries(where)) {\n if (key === \"OR\" || key === \"AND\") {\n (result as any)[key] = (value as WhereClause[]).map((sub) => this.mapWhereToDb(sub));\n } else {\n result[this.columnMap[key] ?? key] = value;\n }\n }\n return result;\n }\n\n private mapSelectToDb(select: string[]): string[] {\n if (!this.hasAliases) {\n return select;\n }\n return select.map((key) => this.columnMap[key] ?? key);\n }\n\n private mapOrderByToDb(orderBy: Record<string, \"asc\" | \"desc\">): Record<string, \"asc\" | \"desc\"> {\n if (!this.hasAliases) {\n return orderBy;\n }\n const result: Record<string, \"asc\" | \"desc\"> = {};\n for (const [key, value] of Object.entries(orderBy)) {\n result[this.columnMap[key] ?? key] = value;\n }\n return result;\n }\n\n private mapOptionsToDb(options?: QueryOptions<T>): QueryOptions | undefined {\n if (!options || !this.hasAliases) {\n return options as QueryOptions | undefined;\n }\n const mapped: QueryOptions = { ...options } as any;\n if (options.where) {\n mapped.where = this.mapWhereToDb(options.where as WhereClause);\n }\n if (options.select) {\n mapped.select = this.mapSelectToDb(options.select);\n }\n if (options.orderBy) {\n mapped.orderBy = this.mapOrderByToDb(options.orderBy as Record<string, \"asc\" | \"desc\">);\n }\n return mapped;\n }\n\n private mapRows(rows: Record<string, unknown>[]): T[] {\n const shouldDeserialize = (this.jsonCodeKeys.size > 0 || this.dateColumns.size > 0) && !this.isFileLikeDriver;\n if (!this.hasAliases && !shouldDeserialize) {\n return rows as T[];\n }\n return rows.map((row) => {\n const mapped = this.hasAliases ? this.toCodeKeys(row) : { ...row };\n if (shouldDeserialize) {\n for (const key of this.jsonCodeKeys) {\n const val = mapped[key];\n if (typeof val === \"string\") {\n try {\n mapped[key] = JSON.parse(val);\n } catch {}\n }\n }\n for (const key of this.dateColumns) {\n const val = mapped[key];\n if (typeof val === \"string\") {\n mapped[key] = new Date(val);\n } else if (typeof val === \"number\") {\n mapped[key] = new Date(val);\n }\n }\n }\n return mapped as T;\n });\n }\n}\n"],"mappings":"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"}
@@ -3,6 +3,7 @@ require("./driver.cjs");
3
3
  const require_file = require("./file.cjs");
4
4
  require("./sql-compiler.cjs");
5
5
  const require_mysql = require("./mysql.cjs");
6
+ const require_s3 = require("./s3.cjs");
6
7
  const require_sqlite = require("./sqlite.cjs");
7
8
  //#region src/drivers/index.ts
8
9
  /**
@@ -19,6 +20,7 @@ function createDriver(type, config) {
19
20
  case "mysql":
20
21
  case "mariadb": return new require_mysql.MySQLDriver(config, provider);
21
22
  case "file": return new require_file.FileDriver(config);
23
+ case "s3": return new require_s3.S3Driver(config);
22
24
  default: throw new require_errors.DriverError(`Unsupported database type: ${name}`);
23
25
  }
24
26
  }
@@ -1 +1 @@
1
- {"version":3,"file":"index.cjs","names":["SQLiteDriver","MySQLDriver","FileDriver","DriverError"],"sources":["../../src/drivers/index.ts"],"sourcesContent":["import { DriverError } from \"../errors\";\nimport type { ConnectionConfig, DatabaseDriver, DatabaseType } from \"../types\";\nimport { FileDriver } from \"./file\";\nimport { MySQLDriver } from \"./mysql\";\nimport { SQLiteDriver } from \"./sqlite\";\n\nexport { BaseDriver } from \"./driver\";\nexport { FileDriver } from \"./file\";\nexport { MySQLDriver } from \"./mysql\";\nexport * from \"./sql-compiler\";\nexport { SQLiteDriver } from \"./sqlite\";\n\n/**\n * Create a database driver instance based on the database type\n * @param {DatabaseType} type - Database type\n * @param {ConnectionConfig} config - Connection configuration\n * @returns {DatabaseDriver} The created driver\n */\nexport function createDriver(type: DatabaseType, config: ConnectionConfig): DatabaseDriver {\n const name = typeof type === \"string\" ? type : type.name;\n const provider = typeof type === \"string\" ? undefined : type.provider;\n\n switch (name) {\n case \"sqlite\":\n return new SQLiteDriver(config as any, provider as any);\n case \"mysql\":\n case \"mariadb\":\n return new MySQLDriver(config as any, provider as any);\n case \"file\":\n return new FileDriver(config as any);\n default:\n throw new DriverError(`Unsupported database type: ${name}`);\n }\n}\n"],"mappings":";;;;;;;;;;;;;AAkBA,SAAgB,aAAa,MAAoB,QAA0C;CACzF,MAAM,OAAO,OAAO,SAAS,WAAW,OAAO,KAAK;CACpD,MAAM,WAAW,OAAO,SAAS,WAAW,KAAA,IAAY,KAAK;AAE7D,SAAQ,MAAR;EACE,KAAK,SACH,QAAO,IAAIA,eAAAA,aAAa,QAAe,SAAgB;EACzD,KAAK;EACL,KAAK,UACH,QAAO,IAAIC,cAAAA,YAAY,QAAe,SAAgB;EACxD,KAAK,OACH,QAAO,IAAIC,aAAAA,WAAW,OAAc;EACtC,QACE,OAAM,IAAIC,eAAAA,YAAY,8BAA8B,OAAO"}
1
+ {"version":3,"file":"index.cjs","names":["SQLiteDriver","MySQLDriver","FileDriver","S3Driver","DriverError"],"sources":["../../src/drivers/index.ts"],"sourcesContent":["import { DriverError } from \"../errors\";\nimport type { ConnectionConfig, DatabaseDriver, DatabaseType } from \"../types\";\nimport { FileDriver } from \"./file\";\nimport { MySQLDriver } from \"./mysql\";\nimport { S3Driver } from \"./s3\";\nimport { SQLiteDriver } from \"./sqlite\";\n\nexport { BaseDriver } from \"./driver\";\nexport { FileDriver } from \"./file\";\nexport { MySQLDriver } from \"./mysql\";\nexport { S3Driver } from \"./s3\";\nexport * from \"./sql-compiler\";\nexport { SQLiteDriver } from \"./sqlite\";\n\n/**\n * Create a database driver instance based on the database type\n * @param {DatabaseType} type - Database type\n * @param {ConnectionConfig} config - Connection configuration\n * @returns {DatabaseDriver} The created driver\n */\nexport function createDriver(type: DatabaseType, config: ConnectionConfig): DatabaseDriver {\n const name = typeof type === \"string\" ? type : type.name;\n const provider = typeof type === \"string\" ? undefined : type.provider;\n\n switch (name) {\n case \"sqlite\":\n return new SQLiteDriver(config as any, provider as any);\n case \"mysql\":\n case \"mariadb\":\n return new MySQLDriver(config as any, provider as any);\n case \"file\":\n return new FileDriver(config as any);\n case \"s3\":\n return new S3Driver(config as any);\n default:\n throw new DriverError(`Unsupported database type: ${name}`);\n }\n}\n"],"mappings":";;;;;;;;;;;;;;AAoBA,SAAgB,aAAa,MAAoB,QAA0C;CACzF,MAAM,OAAO,OAAO,SAAS,WAAW,OAAO,KAAK;CACpD,MAAM,WAAW,OAAO,SAAS,WAAW,KAAA,IAAY,KAAK;AAE7D,SAAQ,MAAR;EACE,KAAK,SACH,QAAO,IAAIA,eAAAA,aAAa,QAAe,SAAgB;EACzD,KAAK;EACL,KAAK,UACH,QAAO,IAAIC,cAAAA,YAAY,QAAe,SAAgB;EACxD,KAAK,OACH,QAAO,IAAIC,aAAAA,WAAW,OAAc;EACtC,KAAK,KACH,QAAO,IAAIC,WAAAA,SAAS,OAAc;EACpC,QACE,OAAM,IAAIC,eAAAA,YAAY,8BAA8B,OAAO"}
@@ -4,6 +4,7 @@ import "./driver.mjs";
4
4
  import { FileDriver, init_file } from "./file.mjs";
5
5
  import { init_sql_compiler } from "./sql-compiler.mjs";
6
6
  import { MySQLDriver, init_mysql } from "./mysql.mjs";
7
+ import { S3Driver, init_s3 } from "./s3.mjs";
7
8
  import { SQLiteDriver, init_sqlite } from "./sqlite.mjs";
8
9
  //#region src/drivers/index.ts
9
10
  /**
@@ -20,6 +21,7 @@ function createDriver(type, config) {
20
21
  case "mysql":
21
22
  case "mariadb": return new MySQLDriver(config, provider);
22
23
  case "file": return new FileDriver(config);
24
+ case "s3": return new S3Driver(config);
23
25
  default: throw new DriverError(`Unsupported database type: ${name}`);
24
26
  }
25
27
  }
@@ -27,6 +29,7 @@ var init_drivers = __esmMin((() => {
27
29
  init_errors();
28
30
  init_file();
29
31
  init_mysql();
32
+ init_s3();
30
33
  init_sqlite();
31
34
  init_sql_compiler();
32
35
  }));
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","names":[],"sources":["../../src/drivers/index.ts"],"sourcesContent":["import { DriverError } from \"../errors\";\nimport type { ConnectionConfig, DatabaseDriver, DatabaseType } from \"../types\";\nimport { FileDriver } from \"./file\";\nimport { MySQLDriver } from \"./mysql\";\nimport { SQLiteDriver } from \"./sqlite\";\n\nexport { BaseDriver } from \"./driver\";\nexport { FileDriver } from \"./file\";\nexport { MySQLDriver } from \"./mysql\";\nexport * from \"./sql-compiler\";\nexport { SQLiteDriver } from \"./sqlite\";\n\n/**\n * Create a database driver instance based on the database type\n * @param {DatabaseType} type - Database type\n * @param {ConnectionConfig} config - Connection configuration\n * @returns {DatabaseDriver} The created driver\n */\nexport function createDriver(type: DatabaseType, config: ConnectionConfig): DatabaseDriver {\n const name = typeof type === \"string\" ? type : type.name;\n const provider = typeof type === \"string\" ? undefined : type.provider;\n\n switch (name) {\n case \"sqlite\":\n return new SQLiteDriver(config as any, provider as any);\n case \"mysql\":\n case \"mariadb\":\n return new MySQLDriver(config as any, provider as any);\n case \"file\":\n return new FileDriver(config as any);\n default:\n throw new DriverError(`Unsupported database type: ${name}`);\n }\n}\n"],"mappings":";;;;;;;;;;;;;;AAkBA,SAAgB,aAAa,MAAoB,QAA0C;CACzF,MAAM,OAAO,OAAO,SAAS,WAAW,OAAO,KAAK;CACpD,MAAM,WAAW,OAAO,SAAS,WAAW,KAAA,IAAY,KAAK;AAE7D,SAAQ,MAAR;EACE,KAAK,SACH,QAAO,IAAI,aAAa,QAAe,SAAgB;EACzD,KAAK;EACL,KAAK,UACH,QAAO,IAAI,YAAY,QAAe,SAAgB;EACxD,KAAK,OACH,QAAO,IAAI,WAAW,OAAc;EACtC,QACE,OAAM,IAAI,YAAY,8BAA8B,OAAO;;;;cA/BzB;YAEJ;aACE;cACE"}
1
+ {"version":3,"file":"index.mjs","names":[],"sources":["../../src/drivers/index.ts"],"sourcesContent":["import { DriverError } from \"../errors\";\nimport type { ConnectionConfig, DatabaseDriver, DatabaseType } from \"../types\";\nimport { FileDriver } from \"./file\";\nimport { MySQLDriver } from \"./mysql\";\nimport { S3Driver } from \"./s3\";\nimport { SQLiteDriver } from \"./sqlite\";\n\nexport { BaseDriver } from \"./driver\";\nexport { FileDriver } from \"./file\";\nexport { MySQLDriver } from \"./mysql\";\nexport { S3Driver } from \"./s3\";\nexport * from \"./sql-compiler\";\nexport { SQLiteDriver } from \"./sqlite\";\n\n/**\n * Create a database driver instance based on the database type\n * @param {DatabaseType} type - Database type\n * @param {ConnectionConfig} config - Connection configuration\n * @returns {DatabaseDriver} The created driver\n */\nexport function createDriver(type: DatabaseType, config: ConnectionConfig): DatabaseDriver {\n const name = typeof type === \"string\" ? type : type.name;\n const provider = typeof type === \"string\" ? undefined : type.provider;\n\n switch (name) {\n case \"sqlite\":\n return new SQLiteDriver(config as any, provider as any);\n case \"mysql\":\n case \"mariadb\":\n return new MySQLDriver(config as any, provider as any);\n case \"file\":\n return new FileDriver(config as any);\n case \"s3\":\n return new S3Driver(config as any);\n default:\n throw new DriverError(`Unsupported database type: ${name}`);\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;AAoBA,SAAgB,aAAa,MAAoB,QAA0C;CACzF,MAAM,OAAO,OAAO,SAAS,WAAW,OAAO,KAAK;CACpD,MAAM,WAAW,OAAO,SAAS,WAAW,KAAA,IAAY,KAAK;AAE7D,SAAQ,MAAR;EACE,KAAK,SACH,QAAO,IAAI,aAAa,QAAe,SAAgB;EACzD,KAAK;EACL,KAAK,UACH,QAAO,IAAI,YAAY,QAAe,SAAgB;EACxD,KAAK,OACH,QAAO,IAAI,WAAW,OAAc;EACtC,KAAK,KACH,QAAO,IAAI,SAAS,OAAc;EACpC,QACE,OAAM,IAAI,YAAY,8BAA8B,OAAO;;;;cAnCzB;YAEJ;aACE;UACN;cACQ"}
@@ -31,7 +31,8 @@ var MySQLDriver = class extends require_driver.BaseDriver {
31
31
  waitForConnections: true,
32
32
  connectionLimit: 10,
33
33
  enableKeepAlive: true,
34
- keepAliveInitialDelay: 1e4
34
+ keepAliveInitialDelay: 1e4,
35
+ decimalNumbers: true
35
36
  });
36
37
  this.connected = true;
37
38
  return;