215 lines
5.2 KiB
TypeScript
215 lines
5.2 KiB
TypeScript
/**
|
|
* Simple PostgreSQL client for testing
|
|
*/
|
|
export class SimplePostgresClient {
|
|
private tables = new Map<string, any[]>();
|
|
private connected = false;
|
|
|
|
constructor(private config: any) {}
|
|
|
|
async query(sql: string, params?: any[]): Promise<{ rows: any[]; rowCount: number }> {
|
|
// Simple mock implementation
|
|
return { rows: [], rowCount: 0 };
|
|
}
|
|
|
|
async findOne(table: string, where: any): Promise<any | null> {
|
|
const rows = this.tables.get(table) || [];
|
|
for (const row of rows) {
|
|
let match = true;
|
|
for (const [key, value] of Object.entries(where)) {
|
|
if (row[key] !== value) {
|
|
match = false;
|
|
break;
|
|
}
|
|
}
|
|
if (match) {
|
|
return row;
|
|
}
|
|
}
|
|
return null;
|
|
}
|
|
|
|
async find(table: string, where: any): Promise<any[]> {
|
|
const rows = this.tables.get(table) || [];
|
|
if (Object.keys(where).length === 0) {
|
|
return rows;
|
|
}
|
|
|
|
return rows.filter(row => {
|
|
for (const [key, value] of Object.entries(where)) {
|
|
if (row[key] !== value) {
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
});
|
|
}
|
|
|
|
async insert(table: string, data: any): Promise<any> {
|
|
const rows = this.tables.get(table) || [];
|
|
const newRow = { ...data, id: rows.length + 1 };
|
|
rows.push(newRow);
|
|
this.tables.set(table, rows);
|
|
return newRow;
|
|
}
|
|
|
|
async update(table: string, where: any, data: any): Promise<number> {
|
|
const rows = this.tables.get(table) || [];
|
|
let updated = 0;
|
|
|
|
for (const row of rows) {
|
|
let match = true;
|
|
for (const [key, value] of Object.entries(where)) {
|
|
if (row[key] !== value) {
|
|
match = false;
|
|
break;
|
|
}
|
|
}
|
|
if (match) {
|
|
Object.assign(row, data);
|
|
updated++;
|
|
}
|
|
}
|
|
|
|
return updated;
|
|
}
|
|
|
|
async delete(table: string, where: any): Promise<number> {
|
|
const rows = this.tables.get(table) || [];
|
|
const remaining = rows.filter(row => {
|
|
for (const [key, value] of Object.entries(where)) {
|
|
if (row[key] !== value) {
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
});
|
|
|
|
const deleted = rows.length - remaining.length;
|
|
this.tables.set(table, remaining);
|
|
return deleted;
|
|
}
|
|
|
|
async healthCheck(): Promise<{ status: string; isConnected: boolean; error?: string }> {
|
|
return {
|
|
status: 'healthy',
|
|
isConnected: true,
|
|
};
|
|
}
|
|
|
|
async disconnect(): Promise<void> {
|
|
this.connected = false;
|
|
}
|
|
}
|
|
|
|
export class SimpleQueryBuilder {
|
|
private parts: string[] = [];
|
|
private params: any[] = [];
|
|
|
|
select(columns: string[] | string = '*'): SimpleQueryBuilder {
|
|
const cols = Array.isArray(columns) ? columns.join(', ') : columns;
|
|
this.parts.push(`SELECT ${cols}`);
|
|
return this;
|
|
}
|
|
|
|
from(table: string): SimpleQueryBuilder {
|
|
this.parts.push(`FROM ${table}`);
|
|
return this;
|
|
}
|
|
|
|
where(conditions: any): SimpleQueryBuilder {
|
|
const whereClause = Object.entries(conditions)
|
|
.map(([key], i) => {
|
|
this.params.push(conditions[key]);
|
|
return `${key} = $${this.params.length}`;
|
|
})
|
|
.join(' AND ');
|
|
|
|
this.parts.push(`WHERE ${whereClause}`);
|
|
return this;
|
|
}
|
|
|
|
orderBy(column: string, direction = 'ASC'): SimpleQueryBuilder {
|
|
this.parts.push(`ORDER BY ${column} ${direction}`);
|
|
return this;
|
|
}
|
|
|
|
limit(count: number): SimpleQueryBuilder {
|
|
this.parts.push(`LIMIT ${count}`);
|
|
return this;
|
|
}
|
|
|
|
insert(table: string, data: any): SimpleQueryBuilder {
|
|
const columns = Object.keys(data);
|
|
const values = Object.values(data);
|
|
this.params.push(...values);
|
|
|
|
const placeholders = columns.map((_, i) => `$${i + 1}`);
|
|
this.parts.push(
|
|
`INSERT INTO ${table} (${columns.join(', ')}) VALUES (${placeholders.join(', ')})`
|
|
);
|
|
return this;
|
|
}
|
|
|
|
update(table: string): SimpleQueryBuilder {
|
|
this.parts.push(`UPDATE ${table}`);
|
|
return this;
|
|
}
|
|
|
|
set(data: any): SimpleQueryBuilder {
|
|
const setClause = Object.entries(data)
|
|
.map(([key, value]) => {
|
|
this.params.push(value);
|
|
return `${key} = $${this.params.length}`;
|
|
})
|
|
.join(', ');
|
|
|
|
this.parts.push(`SET ${setClause}`);
|
|
return this;
|
|
}
|
|
|
|
delete(table: string): SimpleQueryBuilder {
|
|
this.parts.push(`DELETE FROM ${table}`);
|
|
return this;
|
|
}
|
|
|
|
returning(columns: string): SimpleQueryBuilder {
|
|
this.parts.push(`RETURNING ${columns}`);
|
|
return this;
|
|
}
|
|
|
|
join(table: string, condition: string): SimpleQueryBuilder {
|
|
this.parts.push(`JOIN ${table} ON ${condition}`);
|
|
return this;
|
|
}
|
|
|
|
build(): { text: string; values: any[] } {
|
|
return {
|
|
text: this.parts.join(' '),
|
|
values: this.params,
|
|
};
|
|
}
|
|
}
|
|
|
|
export class SimpleTransactionManager {
|
|
constructor(private pool: any) {}
|
|
|
|
async transaction<T>(fn: (client: any) => Promise<T>): Promise<T> {
|
|
const mockClient = {
|
|
query: async (sql?: string) => ({ rows: [], rowCount: 0 }),
|
|
release: () => {},
|
|
};
|
|
|
|
await mockClient.query('BEGIN');
|
|
try {
|
|
const result = await fn(mockClient);
|
|
await mockClient.query('COMMIT');
|
|
return result;
|
|
} catch (error) {
|
|
await mockClient.query('ROLLBACK');
|
|
throw error;
|
|
} finally {
|
|
mockClient.release();
|
|
}
|
|
}
|
|
}
|