relq 1.0.38 → 1.0.39

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.
@@ -28,6 +28,22 @@ class ConnectedSelectBuilder {
28
28
  this.tableName = tableName;
29
29
  this.columns = columns;
30
30
  this.schemaKey = schemaKey;
31
+ this.setupColumnResolver();
32
+ }
33
+ setupColumnResolver() {
34
+ const internal = this.relq[methods_1.INTERNAL];
35
+ const tableDef = internal.getTableDef(this.schemaKey || this.tableName);
36
+ if (!tableDef) {
37
+ return;
38
+ }
39
+ const tableColumns = tableDef.$columns || tableDef;
40
+ this.builder.setColumnResolver((column) => {
41
+ const columnDef = tableColumns[column];
42
+ if (columnDef) {
43
+ return columnDef.$sqlName || columnDef.$name || camelToSnake(column);
44
+ }
45
+ return camelToSnake(column);
46
+ });
31
47
  }
32
48
  where(callback) {
33
49
  this.builder.where(callback);
@@ -21,12 +21,47 @@ class SelectBuilder {
21
21
  distinctOnColumns = [];
22
22
  lockingClause;
23
23
  unionQueries = [];
24
+ columnResolver;
24
25
  constructor(tableName, columns) {
25
26
  this.tableName = tableName;
26
27
  if (columns) {
27
28
  this.selectColumns = Array.isArray(columns) ? columns : [columns];
28
29
  }
29
30
  }
31
+ setColumnResolver(resolver) {
32
+ this.columnResolver = resolver;
33
+ return this;
34
+ }
35
+ transformConditionColumns(conditions) {
36
+ if (!this.columnResolver) {
37
+ return conditions;
38
+ }
39
+ return conditions.map(cond => {
40
+ if (!cond.column) {
41
+ return cond;
42
+ }
43
+ if (cond.method === 'raw') {
44
+ return cond;
45
+ }
46
+ if (cond.method === 'or' || cond.method === 'and') {
47
+ return {
48
+ ...cond,
49
+ values: this.transformConditionColumns(cond.values)
50
+ };
51
+ }
52
+ if (cond.column.includes('.')) {
53
+ const [tableRef, colName] = cond.column.split('.');
54
+ return {
55
+ ...cond,
56
+ column: `${tableRef}.${this.columnResolver(colName)}`
57
+ };
58
+ }
59
+ return {
60
+ ...cond,
61
+ column: this.columnResolver(cond.column)
62
+ };
63
+ });
64
+ }
30
65
  setTableAlias(alias) {
31
66
  this.tableAlias = alias;
32
67
  return this;
@@ -273,18 +308,20 @@ class SelectBuilder {
273
308
  query += ' ' + structuredJoinSQL;
274
309
  }
275
310
  if (this.whereConditions.length > 0) {
276
- const conditions = hasJoins
277
- ? this.qualifyWhereConditions(this.whereConditions, tableRef)
278
- : this.whereConditions;
311
+ let conditions = this.transformConditionColumns(this.whereConditions);
312
+ if (hasJoins) {
313
+ conditions = this.qualifyWhereConditions(conditions, tableRef);
314
+ }
279
315
  query += ' WHERE ' + (0, condition_collector_1.buildConditionsSQL)(conditions);
280
316
  }
281
317
  if (this.groupByColumns.length > 0) {
282
318
  query += ' GROUP BY ' + this.groupByColumns.map(col => pg_format_1.default.ident(col)).join(', ');
283
319
  }
284
320
  if (this.havingConditions.length > 0) {
285
- const havingConds = hasJoins
286
- ? this.qualifyWhereConditions(this.havingConditions, tableRef)
287
- : this.havingConditions;
321
+ let havingConds = this.transformConditionColumns(this.havingConditions);
322
+ if (hasJoins) {
323
+ havingConds = this.qualifyWhereConditions(havingConds, tableRef);
324
+ }
288
325
  query += ' HAVING ' + (0, condition_collector_1.buildConditionsSQL)(havingConds);
289
326
  }
290
327
  if (this.orderByColumns.length > 0) {
@@ -336,18 +373,20 @@ class SelectBuilder {
336
373
  query += ' ' + structuredJoinSQL;
337
374
  }
338
375
  if (this.whereConditions.length > 0) {
339
- const conditions = hasJoins
340
- ? this.qualifyWhereConditions(this.whereConditions, tableRef)
341
- : this.whereConditions;
376
+ let conditions = this.transformConditionColumns(this.whereConditions);
377
+ if (hasJoins) {
378
+ conditions = this.qualifyWhereConditions(conditions, tableRef);
379
+ }
342
380
  query += ' WHERE ' + (0, condition_collector_1.buildConditionsSQL)(conditions);
343
381
  }
344
382
  if (this.groupByColumns.length > 0) {
345
383
  query += ' GROUP BY ' + this.groupByColumns.map(col => pg_format_1.default.ident(col)).join(', ');
346
384
  }
347
385
  if (this.havingConditions.length > 0) {
348
- const havingConds = hasJoins
349
- ? this.qualifyWhereConditions(this.havingConditions, tableRef)
350
- : this.havingConditions;
386
+ let havingConds = this.transformConditionColumns(this.havingConditions);
387
+ if (hasJoins) {
388
+ havingConds = this.qualifyWhereConditions(havingConds, tableRef);
389
+ }
351
390
  query += ' HAVING ' + (0, condition_collector_1.buildConditionsSQL)(havingConds);
352
391
  }
353
392
  return query;
@@ -22,6 +22,22 @@ export class ConnectedSelectBuilder {
22
22
  this.tableName = tableName;
23
23
  this.columns = columns;
24
24
  this.schemaKey = schemaKey;
25
+ this.setupColumnResolver();
26
+ }
27
+ setupColumnResolver() {
28
+ const internal = this.relq[INTERNAL];
29
+ const tableDef = internal.getTableDef(this.schemaKey || this.tableName);
30
+ if (!tableDef) {
31
+ return;
32
+ }
33
+ const tableColumns = tableDef.$columns || tableDef;
34
+ this.builder.setColumnResolver((column) => {
35
+ const columnDef = tableColumns[column];
36
+ if (columnDef) {
37
+ return columnDef.$sqlName || columnDef.$name || camelToSnake(column);
38
+ }
39
+ return camelToSnake(column);
40
+ });
25
41
  }
26
42
  where(callback) {
27
43
  this.builder.where(callback);
@@ -15,12 +15,47 @@ export class SelectBuilder {
15
15
  distinctOnColumns = [];
16
16
  lockingClause;
17
17
  unionQueries = [];
18
+ columnResolver;
18
19
  constructor(tableName, columns) {
19
20
  this.tableName = tableName;
20
21
  if (columns) {
21
22
  this.selectColumns = Array.isArray(columns) ? columns : [columns];
22
23
  }
23
24
  }
25
+ setColumnResolver(resolver) {
26
+ this.columnResolver = resolver;
27
+ return this;
28
+ }
29
+ transformConditionColumns(conditions) {
30
+ if (!this.columnResolver) {
31
+ return conditions;
32
+ }
33
+ return conditions.map(cond => {
34
+ if (!cond.column) {
35
+ return cond;
36
+ }
37
+ if (cond.method === 'raw') {
38
+ return cond;
39
+ }
40
+ if (cond.method === 'or' || cond.method === 'and') {
41
+ return {
42
+ ...cond,
43
+ values: this.transformConditionColumns(cond.values)
44
+ };
45
+ }
46
+ if (cond.column.includes('.')) {
47
+ const [tableRef, colName] = cond.column.split('.');
48
+ return {
49
+ ...cond,
50
+ column: `${tableRef}.${this.columnResolver(colName)}`
51
+ };
52
+ }
53
+ return {
54
+ ...cond,
55
+ column: this.columnResolver(cond.column)
56
+ };
57
+ });
58
+ }
24
59
  setTableAlias(alias) {
25
60
  this.tableAlias = alias;
26
61
  return this;
@@ -267,18 +302,20 @@ export class SelectBuilder {
267
302
  query += ' ' + structuredJoinSQL;
268
303
  }
269
304
  if (this.whereConditions.length > 0) {
270
- const conditions = hasJoins
271
- ? this.qualifyWhereConditions(this.whereConditions, tableRef)
272
- : this.whereConditions;
305
+ let conditions = this.transformConditionColumns(this.whereConditions);
306
+ if (hasJoins) {
307
+ conditions = this.qualifyWhereConditions(conditions, tableRef);
308
+ }
273
309
  query += ' WHERE ' + buildConditionsSQL(conditions);
274
310
  }
275
311
  if (this.groupByColumns.length > 0) {
276
312
  query += ' GROUP BY ' + this.groupByColumns.map(col => format.ident(col)).join(', ');
277
313
  }
278
314
  if (this.havingConditions.length > 0) {
279
- const havingConds = hasJoins
280
- ? this.qualifyWhereConditions(this.havingConditions, tableRef)
281
- : this.havingConditions;
315
+ let havingConds = this.transformConditionColumns(this.havingConditions);
316
+ if (hasJoins) {
317
+ havingConds = this.qualifyWhereConditions(havingConds, tableRef);
318
+ }
282
319
  query += ' HAVING ' + buildConditionsSQL(havingConds);
283
320
  }
284
321
  if (this.orderByColumns.length > 0) {
@@ -330,18 +367,20 @@ export class SelectBuilder {
330
367
  query += ' ' + structuredJoinSQL;
331
368
  }
332
369
  if (this.whereConditions.length > 0) {
333
- const conditions = hasJoins
334
- ? this.qualifyWhereConditions(this.whereConditions, tableRef)
335
- : this.whereConditions;
370
+ let conditions = this.transformConditionColumns(this.whereConditions);
371
+ if (hasJoins) {
372
+ conditions = this.qualifyWhereConditions(conditions, tableRef);
373
+ }
336
374
  query += ' WHERE ' + buildConditionsSQL(conditions);
337
375
  }
338
376
  if (this.groupByColumns.length > 0) {
339
377
  query += ' GROUP BY ' + this.groupByColumns.map(col => format.ident(col)).join(', ');
340
378
  }
341
379
  if (this.havingConditions.length > 0) {
342
- const havingConds = hasJoins
343
- ? this.qualifyWhereConditions(this.havingConditions, tableRef)
344
- : this.havingConditions;
380
+ let havingConds = this.transformConditionColumns(this.havingConditions);
381
+ if (hasJoins) {
382
+ havingConds = this.qualifyWhereConditions(havingConds, tableRef);
383
+ }
345
384
  query += ' HAVING ' + buildConditionsSQL(havingConds);
346
385
  }
347
386
  return query;
package/dist/index.d.ts CHANGED
@@ -1330,10 +1330,23 @@ export declare class SelectBuilder {
1330
1330
  private distinctOnColumns;
1331
1331
  private lockingClause?;
1332
1332
  private unionQueries;
1333
+ private columnResolver?;
1333
1334
  constructor(tableName: string, columns?: string | Array<string | [
1334
1335
  string,
1335
1336
  string
1336
1337
  ]>);
1338
+ /**
1339
+ * Set a column resolver to transform column names (e.g., camelCase to snake_case).
1340
+ * Used by ConnectedSelectBuilder to map TypeScript property names to SQL column names.
1341
+ * @internal
1342
+ */
1343
+ setColumnResolver(resolver: (column: string) => string): SelectBuilder;
1344
+ /**
1345
+ * Transform column names in conditions using the column resolver.
1346
+ * Recursively handles nested or/and conditions.
1347
+ * @internal
1348
+ */
1349
+ private transformConditionColumns;
1337
1350
  /**
1338
1351
  * Set an alias for the main table.
1339
1352
  * @internal Used by ConnectedSelectBuilder for self-joins
@@ -6038,6 +6051,9 @@ export interface JoinManyInternals extends JoinConditionInternals {
6038
6051
  toWhereSQL(): string;
6039
6052
  getInnerJoins(): InnerJoinSpec[];
6040
6053
  }
6054
+ type Prettify$1<T> = {
6055
+ [K in keyof T]: T[K];
6056
+ } & {};
6041
6057
  /**
6042
6058
  * Extract only actual column names from a table type
6043
6059
  * Uses $inferSelect if available (Drizzle tables), otherwise keyof
@@ -6048,10 +6064,11 @@ export type ColumnKeys<T> = T extends {
6048
6064
  /**
6049
6065
  * Pick columns from a table's row type
6050
6066
  * Handles both table definitions (with $inferSelect) and plain interfaces
6067
+ * Uses Prettify to flatten the type for better IDE display
6051
6068
  */
6052
6069
  export type PickColumns<T, K extends string> = T extends {
6053
6070
  $inferSelect: infer TSelect;
6054
- } ? Pick<TSelect, K & keyof TSelect> : Pick<T, K & keyof T>;
6071
+ } ? Prettify$1<Pick<TSelect, K & keyof TSelect>> : Prettify$1<Pick<T, K & keyof T>>;
6055
6072
  type ColumnValue$1<T, K extends ColumnKeys<T>> = T extends {
6056
6073
  $inferSelect: infer TSelect;
6057
6074
  } ? K extends keyof TSelect ? TSelect[K] : unknown : K extends keyof T ? T[K] : unknown;
@@ -7101,7 +7118,7 @@ export type TableAccessor<TSchema, TRelq> = {
7101
7118
  } & {
7102
7119
  [K in keyof TSchema & string]: ConnectedQueryBuilder<TSchema, TSchema[K]>;
7103
7120
  };
7104
- type Prettify$1<T> = {
7121
+ type Prettify$2<T> = {
7105
7122
  [K in keyof T]: T[K];
7106
7123
  } & {};
7107
7124
  /**
@@ -7109,9 +7126,9 @@ type Prettify$1<T> = {
7109
7126
  */
7110
7127
  export type InferRowType<TTable> = TTable extends {
7111
7128
  $inferSelect: infer TSelect;
7112
- } ? Prettify$1<TSelect> : TTable extends {
7129
+ } ? Prettify$2<TSelect> : TTable extends {
7113
7130
  $columns: infer TCols;
7114
- } ? Prettify$1<{
7131
+ } ? Prettify$2<{
7115
7132
  [K in keyof TCols]: any;
7116
7133
  }> : TTable;
7117
7134
  /**
@@ -7146,6 +7163,12 @@ declare class ConnectedSelectBuilder<TSchema = any, TTable = any, TColumns exten
7146
7163
  ]>) | undefined,
7147
7164
  /** Schema key (camelCase) - used for join callback params */
7148
7165
  schemaKey?: string | undefined);
7166
+ /**
7167
+ * Set up column resolver to transform property names to SQL column names.
7168
+ * Uses schema metadata to resolve column names.
7169
+ * @internal
7170
+ */
7171
+ private setupColumnResolver;
7149
7172
  where(callback: (q: TypedConditionBuilder<TTable>) => TypedConditionBuilder<TTable>): this;
7150
7173
  orderBy(column: ColumnName<TTable>, direction?: "ASC" | "DESC"): this;
7151
7174
  limit(count: number): this;
@@ -7430,13 +7453,13 @@ declare class ConnectedSelectBuilder<TSchema = any, TTable = any, TColumns exten
7430
7453
  * @param withMetadata - If true, returns { data, metadata }
7431
7454
  * @param asRequired - If true, all fields are required (removes optional)
7432
7455
  */
7433
- all(): Promise<Prettify$1<InferResultType<TSchema, TTable, TColumns> & TJoined>[]>;
7456
+ all(): Promise<Prettify$2<InferResultType<TSchema, TTable, TColumns> & TJoined>[]>;
7434
7457
  all(withMetadata: true): Promise<{
7435
- data: Prettify$1<InferResultType<TSchema, TTable, TColumns> & TJoined>[];
7458
+ data: Prettify$2<InferResultType<TSchema, TTable, TColumns> & TJoined>[];
7436
7459
  metadata: RelqMetadata;
7437
7460
  }>;
7438
7461
  all<R extends boolean>(withMetadata: true, asRequired: R): Promise<{
7439
- data: Prettify$1<R extends true ? Required<InferResultType<TSchema, TTable, TColumns> & TJoined> : InferResultType<TSchema, TTable, TColumns> & TJoined>[];
7462
+ data: Prettify$2<R extends true ? Required<InferResultType<TSchema, TTable, TColumns> & TJoined> : InferResultType<TSchema, TTable, TColumns> & TJoined>[];
7440
7463
  metadata: RelqMetadata;
7441
7464
  }>;
7442
7465
  /**
@@ -7445,13 +7468,13 @@ declare class ConnectedSelectBuilder<TSchema = any, TTable = any, TColumns exten
7445
7468
  * @param withMetadata - If true, returns { data, metadata }
7446
7469
  * @param asRequired - If true, all fields are required (removes optional)
7447
7470
  */
7448
- get(): Promise<Prettify$1<InferResultType<TSchema, TTable, TColumns> & TJoined> | null>;
7471
+ get(): Promise<Prettify$2<InferResultType<TSchema, TTable, TColumns> & TJoined> | null>;
7449
7472
  get(withMetadata: true): Promise<{
7450
- data: Prettify$1<InferResultType<TSchema, TTable, TColumns> & TJoined> | null;
7473
+ data: Prettify$2<InferResultType<TSchema, TTable, TColumns> & TJoined> | null;
7451
7474
  metadata: RelqMetadata;
7452
7475
  }>;
7453
7476
  get<R extends boolean>(withMetadata: true, asRequired: R): Promise<{
7454
- data: Prettify$1<R extends true ? Required<InferResultType<TSchema, TTable, TColumns> & TJoined> : InferResultType<TSchema, TTable, TColumns> & TJoined> | null;
7477
+ data: Prettify$2<R extends true ? Required<InferResultType<TSchema, TTable, TColumns> & TJoined> : InferResultType<TSchema, TTable, TColumns> & TJoined> | null;
7455
7478
  metadata: RelqMetadata;
7456
7479
  }>;
7457
7480
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "relq",
3
- "version": "1.0.38",
3
+ "version": "1.0.39",
4
4
  "description": "The Fully-Typed PostgreSQL ORM for TypeScript",
5
5
  "author": "Olajide Mathew O. <olajide.mathew@yuniq.solutions>",
6
6
  "license": "MIT",