postgresdk 0.18.15 → 0.18.17

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.
Files changed (3) hide show
  1. package/dist/cli.js +58 -18
  2. package/dist/index.js +58 -18
  3. package/package.json +1 -1
package/dist/cli.js CHANGED
@@ -2740,8 +2740,8 @@ async function introspect(connectionString, schema) {
2740
2740
  c.column_default,
2741
2741
  a.atttypmod
2742
2742
  FROM information_schema.columns c
2743
- LEFT JOIN pg_catalog.pg_class cl ON cl.relname = c.table_name
2744
- LEFT JOIN pg_catalog.pg_namespace n ON n.oid = cl.relnamespace AND n.nspname = c.table_schema
2743
+ LEFT JOIN pg_catalog.pg_namespace n ON n.nspname = c.table_schema
2744
+ LEFT JOIN pg_catalog.pg_class cl ON cl.relname = c.table_name AND cl.relnamespace = n.oid
2745
2745
  LEFT JOIN pg_catalog.pg_attribute a ON a.attrelid = cl.oid AND a.attname = c.column_name
2746
2746
  WHERE c.table_schema = $1
2747
2747
  ORDER BY c.table_name, c.ordinal_position
@@ -3128,8 +3128,9 @@ export const ${Type}ListParamsSchema = z.object({
3128
3128
  offset: z.number().int().nonnegative().optional(),
3129
3129
  where: z.any().optional(),
3130
3130
  vector: VectorSearchParamsSchema.optional(),
3131
- orderBy: z.enum([${columnNames}]).optional(),
3132
- order: z.enum(["asc", "desc"]).optional()
3131
+ orderBy: z.union([z.enum([${columnNames}]), z.array(z.enum([${columnNames}]))]).optional(),
3132
+ order: z.union([z.enum(["asc", "desc"]), z.array(z.enum(["asc", "desc"]))]).optional(),
3133
+ distinctOn: z.union([z.enum([${columnNames}]), z.array(z.enum([${columnNames}]))]).optional()
3133
3134
  }).strict();
3134
3135
 
3135
3136
  // Schema for ordering parameters
@@ -3263,7 +3264,8 @@ const listSchema = z.object({
3263
3264
  limit: z.number().int().positive().max(1000).optional(),
3264
3265
  offset: z.number().int().min(0).optional(),
3265
3266
  orderBy: z.union([columnEnum, z.array(columnEnum)]).optional(),
3266
- order: z.union([z.enum(["asc", "desc"]), z.array(z.enum(["asc", "desc"]))]).optional(),${hasVectorColumns ? `
3267
+ order: z.union([z.enum(["asc", "desc"]), z.array(z.enum(["asc", "desc"]))]).optional(),
3268
+ distinctOn: z.union([columnEnum, z.array(columnEnum)]).optional(),${hasVectorColumns ? `
3267
3269
  vector: z.object({
3268
3270
  field: z.string(),
3269
3271
  query: z.array(z.number()),
@@ -3939,6 +3941,7 @@ ${hasJsonbColumns ? ` /**
3939
3941
  };` : ""}
3940
3942
  orderBy?: string | string[];
3941
3943
  order?: "asc" | "desc" | ("asc" | "desc")[];
3944
+ distinctOn?: string | string[];
3942
3945
  }): Promise<PaginatedResponse<Partial<Select${Type}<TJsonb>>${hasVectorColumns ? " & { _distance?: number }" : ""}>>;
3943
3946
  /**
3944
3947
  * List ${table.name} records with field exclusion
@@ -3959,6 +3962,7 @@ ${hasJsonbColumns ? ` /**
3959
3962
  };` : ""}
3960
3963
  orderBy?: string | string[];
3961
3964
  order?: "asc" | "desc" | ("asc" | "desc")[];
3965
+ distinctOn?: string | string[];
3962
3966
  }): Promise<PaginatedResponse<Partial<Select${Type}<TJsonb>>${hasVectorColumns ? " & { _distance?: number }" : ""}>>;
3963
3967
  /**
3964
3968
  * List ${table.name} records with pagination and filtering
@@ -3990,6 +3994,7 @@ ${hasJsonbColumns ? ` /**
3990
3994
  };` : ""}
3991
3995
  orderBy?: string | string[];
3992
3996
  order?: "asc" | "desc" | ("asc" | "desc")[];
3997
+ distinctOn?: string | string[];
3993
3998
  }): Promise<PaginatedResponse<${Type}WithIncludes<TInclude>${hasVectorColumns ? " & { _distance?: number }" : ""}>>;
3994
3999
  async list<TJsonb extends Partial<Select${Type}> = {}>(params?: {
3995
4000
  include?: ${Type}IncludeSpec;
@@ -4006,6 +4011,7 @@ ${hasJsonbColumns ? ` /**
4006
4011
  };` : ""}
4007
4012
  orderBy?: string | string[];
4008
4013
  order?: "asc" | "desc" | ("asc" | "desc")[];
4014
+ distinctOn?: string | string[];
4009
4015
  }): Promise<PaginatedResponse<Select${Type}<TJsonb> | Partial<Select${Type}<TJsonb>>>> {
4010
4016
  return this.post<PaginatedResponse<Select${Type}<TJsonb>${hasVectorColumns ? " & { _distance?: number }" : ""}>>(\`\${this.resource}/list\`, params ?? {});
4011
4017
  }` : ` /**
@@ -4027,6 +4033,7 @@ ${hasJsonbColumns ? ` /**
4027
4033
  };` : ""}
4028
4034
  orderBy?: string | string[];
4029
4035
  order?: "asc" | "desc" | ("asc" | "desc")[];
4036
+ distinctOn?: string | string[];
4030
4037
  }): Promise<PaginatedResponse<Partial<Select${Type}>${hasVectorColumns ? " & { _distance?: number }" : ""}>>;
4031
4038
  /**
4032
4039
  * List ${table.name} records with field exclusion
@@ -4047,6 +4054,7 @@ ${hasJsonbColumns ? ` /**
4047
4054
  };` : ""}
4048
4055
  orderBy?: string | string[];
4049
4056
  order?: "asc" | "desc" | ("asc" | "desc")[];
4057
+ distinctOn?: string | string[];
4050
4058
  }): Promise<PaginatedResponse<Partial<Select${Type}>${hasVectorColumns ? " & { _distance?: number }" : ""}>>;
4051
4059
  /**
4052
4060
  * List ${table.name} records with pagination and filtering
@@ -4072,6 +4080,7 @@ ${hasJsonbColumns ? ` /**
4072
4080
  };` : ""}
4073
4081
  orderBy?: string | string[];
4074
4082
  order?: "asc" | "desc" | ("asc" | "desc")[];
4083
+ distinctOn?: string | string[];
4075
4084
  }): Promise<PaginatedResponse<${Type}WithIncludes<TInclude>${hasVectorColumns ? " & { _distance?: number }" : ""}>>;
4076
4085
  async list(params?: {
4077
4086
  include?: ${Type}IncludeSpec;
@@ -4088,6 +4097,7 @@ ${hasJsonbColumns ? ` /**
4088
4097
  };` : ""}
4089
4098
  orderBy?: string | string[];
4090
4099
  order?: "asc" | "desc" | ("asc" | "desc")[];
4100
+ distinctOn?: string | string[];
4091
4101
  }): Promise<PaginatedResponse<Select${Type} | Partial<Select${Type}>>> {
4092
4102
  return this.post<PaginatedResponse<Select${Type}${hasVectorColumns ? " & { _distance?: number }" : ""}>>(\`\${this.resource}/list\`, params ?? {});
4093
4103
  }`}
@@ -6218,6 +6228,7 @@ export async function listRecords(
6218
6228
  include?: any;
6219
6229
  orderBy?: string | string[];
6220
6230
  order?: "asc" | "desc" | ("asc" | "desc")[];
6231
+ distinctOn?: string | string[];
6221
6232
  vector?: {
6222
6233
  field: string;
6223
6234
  query: number[];
@@ -6227,7 +6238,11 @@ export async function listRecords(
6227
6238
  }
6228
6239
  ): Promise<{ data?: any; total?: number; limit?: number; offset?: number; hasMore?: boolean; error?: string; issues?: any; needsIncludes?: boolean; includeSpec?: any; status: number }> {
6229
6240
  try {
6230
- const { where: whereClause, limit = 50, offset = 0, include, orderBy, order, vector } = params;
6241
+ const { where: whereClause, limit = 50, offset = 0, include, orderBy, order, vector, distinctOn } = params;
6242
+
6243
+ // DISTINCT ON support
6244
+ const distinctCols: string[] | null = distinctOn ? (Array.isArray(distinctOn) ? distinctOn : [distinctOn]) : null;
6245
+ const _distinctOnColsSQL = distinctCols ? distinctCols.map(c => '"' + c + '"').join(', ') : '';
6231
6246
 
6232
6247
  // Get distance operator if vector search
6233
6248
  const distanceOp = vector ? getVectorDistanceOperator(vector.metric) : "";
@@ -6286,26 +6301,49 @@ export async function listRecords(
6286
6301
  }
6287
6302
 
6288
6303
  // Build SELECT clause
6304
+ const _distinctOnPrefix = distinctCols ? 'DISTINCT ON (' + _distinctOnColsSQL + ') ' : '';
6289
6305
  const baseColumns = buildColumnList(ctx.select, ctx.exclude, ctx.allColumnNames);
6290
6306
  const selectClause = vector
6291
- ? \`\${baseColumns}, ("\${vector.field}" \${distanceOp} ($1)::vector) AS _distance\`
6292
- : baseColumns;
6307
+ ? \`\${_distinctOnPrefix}\${baseColumns}, ("\${vector.field}" \${distanceOp} ($1)::vector) AS _distance\`
6308
+ : \`\${_distinctOnPrefix}\${baseColumns}\`;
6293
6309
 
6294
6310
  // Build ORDER BY clause
6295
6311
  let orderBySQL = "";
6296
6312
  if (vector) {
6297
6313
  // For vector search, always order by distance
6298
6314
  orderBySQL = \`ORDER BY "\${vector.field}" \${distanceOp} ($1)::vector\`;
6299
- } else if (orderBy) {
6300
- const columns = Array.isArray(orderBy) ? orderBy : [orderBy];
6301
- const directions = Array.isArray(order) ? order : (order ? Array(columns.length).fill(order) : Array(columns.length).fill("asc"));
6302
-
6303
- const orderParts = columns.map((col, i) => {
6304
- const dir = (directions[i] || "asc").toUpperCase();
6305
- return \`"\${col}" \${dir}\`;
6306
- });
6315
+ } else {
6316
+ const userCols = orderBy ? (Array.isArray(orderBy) ? orderBy : [orderBy]) : [];
6317
+ const userDirs: ("asc" | "desc")[] = orderBy
6318
+ ? (Array.isArray(order) ? order : (order ? Array(userCols.length).fill(order) : Array(userCols.length).fill("asc")))
6319
+ : [];
6320
+
6321
+ const finalCols: string[] = [];
6322
+ const finalDirs: string[] = [];
6323
+
6324
+ if (distinctCols) {
6325
+ // DISTINCT ON requires its columns to be the leftmost ORDER BY prefix
6326
+ for (const col of distinctCols) {
6327
+ const userIdx = userCols.indexOf(col);
6328
+ finalCols.push(col);
6329
+ finalDirs.push(userIdx >= 0 ? (userDirs[userIdx] || "asc") : "asc");
6330
+ }
6331
+ // Append remaining user-specified cols not already covered by distinctOn
6332
+ for (let i = 0; i < userCols.length; i++) {
6333
+ if (!distinctCols.includes(userCols[i]!)) {
6334
+ finalCols.push(userCols[i]!);
6335
+ finalDirs.push(userDirs[i] || "asc");
6336
+ }
6337
+ }
6338
+ } else {
6339
+ finalCols.push(...userCols);
6340
+ finalDirs.push(...userDirs.map(d => d || "asc"));
6341
+ }
6307
6342
 
6308
- orderBySQL = \`ORDER BY \${orderParts.join(", ")}\`;
6343
+ if (finalCols.length > 0) {
6344
+ const orderParts = finalCols.map((c, i) => \`"\${c}" \${finalDirs[i]!.toUpperCase()}\`);
6345
+ orderBySQL = \`ORDER BY \${orderParts.join(", ")}\`;
6346
+ }
6309
6347
  }
6310
6348
 
6311
6349
  // Add limit and offset params
@@ -6314,7 +6352,9 @@ export async function listRecords(
6314
6352
  const allParams = [...queryParams, ...whereParams, limit, offset];
6315
6353
 
6316
6354
  // Get total count for pagination
6317
- const countText = \`SELECT COUNT(*) FROM "\${ctx.table}" \${countWhereSQL}\`;
6355
+ const countText = distinctCols
6356
+ ? \`SELECT COUNT(*) FROM (SELECT DISTINCT ON (\${_distinctOnColsSQL}) 1 FROM "\${ctx.table}" \${countWhereSQL} ORDER BY \${_distinctOnColsSQL}) __distinct_count\`
6357
+ : \`SELECT COUNT(*) FROM "\${ctx.table}" \${countWhereSQL}\`;
6318
6358
  log.debug(\`LIST \${ctx.table} COUNT SQL:\`, countText, "params:", countParams);
6319
6359
  const countResult = await ctx.pg.query(countText, countParams);
6320
6360
  const total = parseInt(countResult.rows[0].count, 10);
package/dist/index.js CHANGED
@@ -1779,8 +1779,8 @@ async function introspect(connectionString, schema) {
1779
1779
  c.column_default,
1780
1780
  a.atttypmod
1781
1781
  FROM information_schema.columns c
1782
- LEFT JOIN pg_catalog.pg_class cl ON cl.relname = c.table_name
1783
- LEFT JOIN pg_catalog.pg_namespace n ON n.oid = cl.relnamespace AND n.nspname = c.table_schema
1782
+ LEFT JOIN pg_catalog.pg_namespace n ON n.nspname = c.table_schema
1783
+ LEFT JOIN pg_catalog.pg_class cl ON cl.relname = c.table_name AND cl.relnamespace = n.oid
1784
1784
  LEFT JOIN pg_catalog.pg_attribute a ON a.attrelid = cl.oid AND a.attname = c.column_name
1785
1785
  WHERE c.table_schema = $1
1786
1786
  ORDER BY c.table_name, c.ordinal_position
@@ -2167,8 +2167,9 @@ export const ${Type}ListParamsSchema = z.object({
2167
2167
  offset: z.number().int().nonnegative().optional(),
2168
2168
  where: z.any().optional(),
2169
2169
  vector: VectorSearchParamsSchema.optional(),
2170
- orderBy: z.enum([${columnNames}]).optional(),
2171
- order: z.enum(["asc", "desc"]).optional()
2170
+ orderBy: z.union([z.enum([${columnNames}]), z.array(z.enum([${columnNames}]))]).optional(),
2171
+ order: z.union([z.enum(["asc", "desc"]), z.array(z.enum(["asc", "desc"]))]).optional(),
2172
+ distinctOn: z.union([z.enum([${columnNames}]), z.array(z.enum([${columnNames}]))]).optional()
2172
2173
  }).strict();
2173
2174
 
2174
2175
  // Schema for ordering parameters
@@ -2302,7 +2303,8 @@ const listSchema = z.object({
2302
2303
  limit: z.number().int().positive().max(1000).optional(),
2303
2304
  offset: z.number().int().min(0).optional(),
2304
2305
  orderBy: z.union([columnEnum, z.array(columnEnum)]).optional(),
2305
- order: z.union([z.enum(["asc", "desc"]), z.array(z.enum(["asc", "desc"]))]).optional(),${hasVectorColumns ? `
2306
+ order: z.union([z.enum(["asc", "desc"]), z.array(z.enum(["asc", "desc"]))]).optional(),
2307
+ distinctOn: z.union([columnEnum, z.array(columnEnum)]).optional(),${hasVectorColumns ? `
2306
2308
  vector: z.object({
2307
2309
  field: z.string(),
2308
2310
  query: z.array(z.number()),
@@ -2978,6 +2980,7 @@ ${hasJsonbColumns ? ` /**
2978
2980
  };` : ""}
2979
2981
  orderBy?: string | string[];
2980
2982
  order?: "asc" | "desc" | ("asc" | "desc")[];
2983
+ distinctOn?: string | string[];
2981
2984
  }): Promise<PaginatedResponse<Partial<Select${Type}<TJsonb>>${hasVectorColumns ? " & { _distance?: number }" : ""}>>;
2982
2985
  /**
2983
2986
  * List ${table.name} records with field exclusion
@@ -2998,6 +3001,7 @@ ${hasJsonbColumns ? ` /**
2998
3001
  };` : ""}
2999
3002
  orderBy?: string | string[];
3000
3003
  order?: "asc" | "desc" | ("asc" | "desc")[];
3004
+ distinctOn?: string | string[];
3001
3005
  }): Promise<PaginatedResponse<Partial<Select${Type}<TJsonb>>${hasVectorColumns ? " & { _distance?: number }" : ""}>>;
3002
3006
  /**
3003
3007
  * List ${table.name} records with pagination and filtering
@@ -3029,6 +3033,7 @@ ${hasJsonbColumns ? ` /**
3029
3033
  };` : ""}
3030
3034
  orderBy?: string | string[];
3031
3035
  order?: "asc" | "desc" | ("asc" | "desc")[];
3036
+ distinctOn?: string | string[];
3032
3037
  }): Promise<PaginatedResponse<${Type}WithIncludes<TInclude>${hasVectorColumns ? " & { _distance?: number }" : ""}>>;
3033
3038
  async list<TJsonb extends Partial<Select${Type}> = {}>(params?: {
3034
3039
  include?: ${Type}IncludeSpec;
@@ -3045,6 +3050,7 @@ ${hasJsonbColumns ? ` /**
3045
3050
  };` : ""}
3046
3051
  orderBy?: string | string[];
3047
3052
  order?: "asc" | "desc" | ("asc" | "desc")[];
3053
+ distinctOn?: string | string[];
3048
3054
  }): Promise<PaginatedResponse<Select${Type}<TJsonb> | Partial<Select${Type}<TJsonb>>>> {
3049
3055
  return this.post<PaginatedResponse<Select${Type}<TJsonb>${hasVectorColumns ? " & { _distance?: number }" : ""}>>(\`\${this.resource}/list\`, params ?? {});
3050
3056
  }` : ` /**
@@ -3066,6 +3072,7 @@ ${hasJsonbColumns ? ` /**
3066
3072
  };` : ""}
3067
3073
  orderBy?: string | string[];
3068
3074
  order?: "asc" | "desc" | ("asc" | "desc")[];
3075
+ distinctOn?: string | string[];
3069
3076
  }): Promise<PaginatedResponse<Partial<Select${Type}>${hasVectorColumns ? " & { _distance?: number }" : ""}>>;
3070
3077
  /**
3071
3078
  * List ${table.name} records with field exclusion
@@ -3086,6 +3093,7 @@ ${hasJsonbColumns ? ` /**
3086
3093
  };` : ""}
3087
3094
  orderBy?: string | string[];
3088
3095
  order?: "asc" | "desc" | ("asc" | "desc")[];
3096
+ distinctOn?: string | string[];
3089
3097
  }): Promise<PaginatedResponse<Partial<Select${Type}>${hasVectorColumns ? " & { _distance?: number }" : ""}>>;
3090
3098
  /**
3091
3099
  * List ${table.name} records with pagination and filtering
@@ -3111,6 +3119,7 @@ ${hasJsonbColumns ? ` /**
3111
3119
  };` : ""}
3112
3120
  orderBy?: string | string[];
3113
3121
  order?: "asc" | "desc" | ("asc" | "desc")[];
3122
+ distinctOn?: string | string[];
3114
3123
  }): Promise<PaginatedResponse<${Type}WithIncludes<TInclude>${hasVectorColumns ? " & { _distance?: number }" : ""}>>;
3115
3124
  async list(params?: {
3116
3125
  include?: ${Type}IncludeSpec;
@@ -3127,6 +3136,7 @@ ${hasJsonbColumns ? ` /**
3127
3136
  };` : ""}
3128
3137
  orderBy?: string | string[];
3129
3138
  order?: "asc" | "desc" | ("asc" | "desc")[];
3139
+ distinctOn?: string | string[];
3130
3140
  }): Promise<PaginatedResponse<Select${Type} | Partial<Select${Type}>>> {
3131
3141
  return this.post<PaginatedResponse<Select${Type}${hasVectorColumns ? " & { _distance?: number }" : ""}>>(\`\${this.resource}/list\`, params ?? {});
3132
3142
  }`}
@@ -5257,6 +5267,7 @@ export async function listRecords(
5257
5267
  include?: any;
5258
5268
  orderBy?: string | string[];
5259
5269
  order?: "asc" | "desc" | ("asc" | "desc")[];
5270
+ distinctOn?: string | string[];
5260
5271
  vector?: {
5261
5272
  field: string;
5262
5273
  query: number[];
@@ -5266,7 +5277,11 @@ export async function listRecords(
5266
5277
  }
5267
5278
  ): Promise<{ data?: any; total?: number; limit?: number; offset?: number; hasMore?: boolean; error?: string; issues?: any; needsIncludes?: boolean; includeSpec?: any; status: number }> {
5268
5279
  try {
5269
- const { where: whereClause, limit = 50, offset = 0, include, orderBy, order, vector } = params;
5280
+ const { where: whereClause, limit = 50, offset = 0, include, orderBy, order, vector, distinctOn } = params;
5281
+
5282
+ // DISTINCT ON support
5283
+ const distinctCols: string[] | null = distinctOn ? (Array.isArray(distinctOn) ? distinctOn : [distinctOn]) : null;
5284
+ const _distinctOnColsSQL = distinctCols ? distinctCols.map(c => '"' + c + '"').join(', ') : '';
5270
5285
 
5271
5286
  // Get distance operator if vector search
5272
5287
  const distanceOp = vector ? getVectorDistanceOperator(vector.metric) : "";
@@ -5325,26 +5340,49 @@ export async function listRecords(
5325
5340
  }
5326
5341
 
5327
5342
  // Build SELECT clause
5343
+ const _distinctOnPrefix = distinctCols ? 'DISTINCT ON (' + _distinctOnColsSQL + ') ' : '';
5328
5344
  const baseColumns = buildColumnList(ctx.select, ctx.exclude, ctx.allColumnNames);
5329
5345
  const selectClause = vector
5330
- ? \`\${baseColumns}, ("\${vector.field}" \${distanceOp} ($1)::vector) AS _distance\`
5331
- : baseColumns;
5346
+ ? \`\${_distinctOnPrefix}\${baseColumns}, ("\${vector.field}" \${distanceOp} ($1)::vector) AS _distance\`
5347
+ : \`\${_distinctOnPrefix}\${baseColumns}\`;
5332
5348
 
5333
5349
  // Build ORDER BY clause
5334
5350
  let orderBySQL = "";
5335
5351
  if (vector) {
5336
5352
  // For vector search, always order by distance
5337
5353
  orderBySQL = \`ORDER BY "\${vector.field}" \${distanceOp} ($1)::vector\`;
5338
- } else if (orderBy) {
5339
- const columns = Array.isArray(orderBy) ? orderBy : [orderBy];
5340
- const directions = Array.isArray(order) ? order : (order ? Array(columns.length).fill(order) : Array(columns.length).fill("asc"));
5341
-
5342
- const orderParts = columns.map((col, i) => {
5343
- const dir = (directions[i] || "asc").toUpperCase();
5344
- return \`"\${col}" \${dir}\`;
5345
- });
5354
+ } else {
5355
+ const userCols = orderBy ? (Array.isArray(orderBy) ? orderBy : [orderBy]) : [];
5356
+ const userDirs: ("asc" | "desc")[] = orderBy
5357
+ ? (Array.isArray(order) ? order : (order ? Array(userCols.length).fill(order) : Array(userCols.length).fill("asc")))
5358
+ : [];
5359
+
5360
+ const finalCols: string[] = [];
5361
+ const finalDirs: string[] = [];
5362
+
5363
+ if (distinctCols) {
5364
+ // DISTINCT ON requires its columns to be the leftmost ORDER BY prefix
5365
+ for (const col of distinctCols) {
5366
+ const userIdx = userCols.indexOf(col);
5367
+ finalCols.push(col);
5368
+ finalDirs.push(userIdx >= 0 ? (userDirs[userIdx] || "asc") : "asc");
5369
+ }
5370
+ // Append remaining user-specified cols not already covered by distinctOn
5371
+ for (let i = 0; i < userCols.length; i++) {
5372
+ if (!distinctCols.includes(userCols[i]!)) {
5373
+ finalCols.push(userCols[i]!);
5374
+ finalDirs.push(userDirs[i] || "asc");
5375
+ }
5376
+ }
5377
+ } else {
5378
+ finalCols.push(...userCols);
5379
+ finalDirs.push(...userDirs.map(d => d || "asc"));
5380
+ }
5346
5381
 
5347
- orderBySQL = \`ORDER BY \${orderParts.join(", ")}\`;
5382
+ if (finalCols.length > 0) {
5383
+ const orderParts = finalCols.map((c, i) => \`"\${c}" \${finalDirs[i]!.toUpperCase()}\`);
5384
+ orderBySQL = \`ORDER BY \${orderParts.join(", ")}\`;
5385
+ }
5348
5386
  }
5349
5387
 
5350
5388
  // Add limit and offset params
@@ -5353,7 +5391,9 @@ export async function listRecords(
5353
5391
  const allParams = [...queryParams, ...whereParams, limit, offset];
5354
5392
 
5355
5393
  // Get total count for pagination
5356
- const countText = \`SELECT COUNT(*) FROM "\${ctx.table}" \${countWhereSQL}\`;
5394
+ const countText = distinctCols
5395
+ ? \`SELECT COUNT(*) FROM (SELECT DISTINCT ON (\${_distinctOnColsSQL}) 1 FROM "\${ctx.table}" \${countWhereSQL} ORDER BY \${_distinctOnColsSQL}) __distinct_count\`
5396
+ : \`SELECT COUNT(*) FROM "\${ctx.table}" \${countWhereSQL}\`;
5357
5397
  log.debug(\`LIST \${ctx.table} COUNT SQL:\`, countText, "params:", countParams);
5358
5398
  const countResult = await ctx.pg.query(countText, countParams);
5359
5399
  const total = parseInt(countResult.rows[0].count, 10);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "postgresdk",
3
- "version": "0.18.15",
3
+ "version": "0.18.17",
4
4
  "description": "Generate a typed server/client SDK from a Postgres schema (includes, Zod, Hono).",
5
5
  "type": "module",
6
6
  "bin": {