@neverinfamous/postgres-mcp 1.2.0 → 2.0.0

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 (293) hide show
  1. package/README.md +202 -148
  2. package/dist/__tests__/benchmarks/codemode.bench.d.ts +10 -0
  3. package/dist/__tests__/benchmarks/codemode.bench.d.ts.map +1 -0
  4. package/dist/__tests__/benchmarks/codemode.bench.js +159 -0
  5. package/dist/__tests__/benchmarks/codemode.bench.js.map +1 -0
  6. package/dist/__tests__/benchmarks/connection-pool.bench.d.ts +10 -0
  7. package/dist/__tests__/benchmarks/connection-pool.bench.d.ts.map +1 -0
  8. package/dist/__tests__/benchmarks/connection-pool.bench.js +123 -0
  9. package/dist/__tests__/benchmarks/connection-pool.bench.js.map +1 -0
  10. package/dist/__tests__/benchmarks/handler-dispatch.bench.d.ts +11 -0
  11. package/dist/__tests__/benchmarks/handler-dispatch.bench.d.ts.map +1 -0
  12. package/dist/__tests__/benchmarks/handler-dispatch.bench.js +199 -0
  13. package/dist/__tests__/benchmarks/handler-dispatch.bench.js.map +1 -0
  14. package/dist/__tests__/benchmarks/logger-sanitization.bench.d.ts +15 -0
  15. package/dist/__tests__/benchmarks/logger-sanitization.bench.d.ts.map +1 -0
  16. package/dist/__tests__/benchmarks/logger-sanitization.bench.js +155 -0
  17. package/dist/__tests__/benchmarks/logger-sanitization.bench.js.map +1 -0
  18. package/dist/__tests__/benchmarks/resource-prompts.bench.d.ts +10 -0
  19. package/dist/__tests__/benchmarks/resource-prompts.bench.d.ts.map +1 -0
  20. package/dist/__tests__/benchmarks/resource-prompts.bench.js +181 -0
  21. package/dist/__tests__/benchmarks/resource-prompts.bench.js.map +1 -0
  22. package/dist/__tests__/benchmarks/schema-parsing.bench.d.ts +11 -0
  23. package/dist/__tests__/benchmarks/schema-parsing.bench.d.ts.map +1 -0
  24. package/dist/__tests__/benchmarks/schema-parsing.bench.js +209 -0
  25. package/dist/__tests__/benchmarks/schema-parsing.bench.js.map +1 -0
  26. package/dist/__tests__/benchmarks/tool-filtering.bench.d.ts +9 -0
  27. package/dist/__tests__/benchmarks/tool-filtering.bench.d.ts.map +1 -0
  28. package/dist/__tests__/benchmarks/tool-filtering.bench.js +83 -0
  29. package/dist/__tests__/benchmarks/tool-filtering.bench.js.map +1 -0
  30. package/dist/__tests__/benchmarks/transport-auth.bench.d.ts +10 -0
  31. package/dist/__tests__/benchmarks/transport-auth.bench.d.ts.map +1 -0
  32. package/dist/__tests__/benchmarks/transport-auth.bench.js +128 -0
  33. package/dist/__tests__/benchmarks/transport-auth.bench.js.map +1 -0
  34. package/dist/__tests__/benchmarks/utilities.bench.d.ts +10 -0
  35. package/dist/__tests__/benchmarks/utilities.bench.d.ts.map +1 -0
  36. package/dist/__tests__/benchmarks/utilities.bench.js +164 -0
  37. package/dist/__tests__/benchmarks/utilities.bench.js.map +1 -0
  38. package/dist/adapters/DatabaseAdapter.d.ts.map +1 -1
  39. package/dist/adapters/DatabaseAdapter.js +12 -0
  40. package/dist/adapters/DatabaseAdapter.js.map +1 -1
  41. package/dist/adapters/postgresql/PostgresAdapter.d.ts.map +1 -1
  42. package/dist/adapters/postgresql/PostgresAdapter.js +56 -3
  43. package/dist/adapters/postgresql/PostgresAdapter.js.map +1 -1
  44. package/dist/adapters/postgresql/prompts/ltree.js +2 -2
  45. package/dist/adapters/postgresql/prompts/ltree.js.map +1 -1
  46. package/dist/adapters/postgresql/schemas/admin.d.ts +10 -5
  47. package/dist/adapters/postgresql/schemas/admin.d.ts.map +1 -1
  48. package/dist/adapters/postgresql/schemas/admin.js +10 -5
  49. package/dist/adapters/postgresql/schemas/admin.js.map +1 -1
  50. package/dist/adapters/postgresql/schemas/backup.d.ts +45 -27
  51. package/dist/adapters/postgresql/schemas/backup.d.ts.map +1 -1
  52. package/dist/adapters/postgresql/schemas/backup.js +64 -26
  53. package/dist/adapters/postgresql/schemas/backup.js.map +1 -1
  54. package/dist/adapters/postgresql/schemas/core.d.ts +53 -19
  55. package/dist/adapters/postgresql/schemas/core.d.ts.map +1 -1
  56. package/dist/adapters/postgresql/schemas/core.js +61 -17
  57. package/dist/adapters/postgresql/schemas/core.js.map +1 -1
  58. package/dist/adapters/postgresql/schemas/cron.d.ts +51 -32
  59. package/dist/adapters/postgresql/schemas/cron.d.ts.map +1 -1
  60. package/dist/adapters/postgresql/schemas/cron.js +64 -44
  61. package/dist/adapters/postgresql/schemas/cron.js.map +1 -1
  62. package/dist/adapters/postgresql/schemas/extensions.d.ts +224 -110
  63. package/dist/adapters/postgresql/schemas/extensions.d.ts.map +1 -1
  64. package/dist/adapters/postgresql/schemas/extensions.js +245 -96
  65. package/dist/adapters/postgresql/schemas/extensions.js.map +1 -1
  66. package/dist/adapters/postgresql/schemas/index.d.ts +7 -6
  67. package/dist/adapters/postgresql/schemas/index.d.ts.map +1 -1
  68. package/dist/adapters/postgresql/schemas/index.js +16 -8
  69. package/dist/adapters/postgresql/schemas/index.js.map +1 -1
  70. package/dist/adapters/postgresql/schemas/introspection.d.ts +445 -0
  71. package/dist/adapters/postgresql/schemas/introspection.d.ts.map +1 -0
  72. package/dist/adapters/postgresql/schemas/introspection.js +478 -0
  73. package/dist/adapters/postgresql/schemas/introspection.js.map +1 -0
  74. package/dist/adapters/postgresql/schemas/jsonb.d.ts +102 -42
  75. package/dist/adapters/postgresql/schemas/jsonb.d.ts.map +1 -1
  76. package/dist/adapters/postgresql/schemas/jsonb.js +125 -30
  77. package/dist/adapters/postgresql/schemas/jsonb.js.map +1 -1
  78. package/dist/adapters/postgresql/schemas/monitoring.d.ts +69 -36
  79. package/dist/adapters/postgresql/schemas/monitoring.d.ts.map +1 -1
  80. package/dist/adapters/postgresql/schemas/monitoring.js +98 -40
  81. package/dist/adapters/postgresql/schemas/monitoring.js.map +1 -1
  82. package/dist/adapters/postgresql/schemas/partitioning.d.ts +21 -24
  83. package/dist/adapters/postgresql/schemas/partitioning.d.ts.map +1 -1
  84. package/dist/adapters/postgresql/schemas/partitioning.js +26 -14
  85. package/dist/adapters/postgresql/schemas/partitioning.js.map +1 -1
  86. package/dist/adapters/postgresql/schemas/partman.d.ts +69 -0
  87. package/dist/adapters/postgresql/schemas/partman.d.ts.map +1 -1
  88. package/dist/adapters/postgresql/schemas/partman.js +46 -33
  89. package/dist/adapters/postgresql/schemas/partman.js.map +1 -1
  90. package/dist/adapters/postgresql/schemas/performance.d.ts +97 -49
  91. package/dist/adapters/postgresql/schemas/performance.d.ts.map +1 -1
  92. package/dist/adapters/postgresql/schemas/performance.js +139 -34
  93. package/dist/adapters/postgresql/schemas/performance.js.map +1 -1
  94. package/dist/adapters/postgresql/schemas/postgis.d.ts +20 -0
  95. package/dist/adapters/postgresql/schemas/postgis.d.ts.map +1 -1
  96. package/dist/adapters/postgresql/schemas/postgis.js +40 -0
  97. package/dist/adapters/postgresql/schemas/postgis.js.map +1 -1
  98. package/dist/adapters/postgresql/schemas/schema-mgmt.d.ts +50 -30
  99. package/dist/adapters/postgresql/schemas/schema-mgmt.d.ts.map +1 -1
  100. package/dist/adapters/postgresql/schemas/schema-mgmt.js +105 -33
  101. package/dist/adapters/postgresql/schemas/schema-mgmt.js.map +1 -1
  102. package/dist/adapters/postgresql/schemas/stats.d.ts +33 -20
  103. package/dist/adapters/postgresql/schemas/stats.d.ts.map +1 -1
  104. package/dist/adapters/postgresql/schemas/stats.js +36 -20
  105. package/dist/adapters/postgresql/schemas/stats.js.map +1 -1
  106. package/dist/adapters/postgresql/schemas/text-search.d.ts +34 -19
  107. package/dist/adapters/postgresql/schemas/text-search.d.ts.map +1 -1
  108. package/dist/adapters/postgresql/schemas/text-search.js +52 -13
  109. package/dist/adapters/postgresql/schemas/text-search.js.map +1 -1
  110. package/dist/adapters/postgresql/tools/admin.d.ts.map +1 -1
  111. package/dist/adapters/postgresql/tools/admin.js +272 -186
  112. package/dist/adapters/postgresql/tools/admin.js.map +1 -1
  113. package/dist/adapters/postgresql/tools/backup/dump.d.ts.map +1 -1
  114. package/dist/adapters/postgresql/tools/backup/dump.js +376 -350
  115. package/dist/adapters/postgresql/tools/backup/dump.js.map +1 -1
  116. package/dist/adapters/postgresql/tools/citext.d.ts.map +1 -1
  117. package/dist/adapters/postgresql/tools/citext.js +333 -243
  118. package/dist/adapters/postgresql/tools/citext.js.map +1 -1
  119. package/dist/adapters/postgresql/tools/codemode/index.d.ts.map +1 -1
  120. package/dist/adapters/postgresql/tools/codemode/index.js +2 -11
  121. package/dist/adapters/postgresql/tools/codemode/index.js.map +1 -1
  122. package/dist/adapters/postgresql/tools/core/convenience.d.ts +9 -1
  123. package/dist/adapters/postgresql/tools/core/convenience.d.ts.map +1 -1
  124. package/dist/adapters/postgresql/tools/core/convenience.js +101 -19
  125. package/dist/adapters/postgresql/tools/core/convenience.js.map +1 -1
  126. package/dist/adapters/postgresql/tools/core/error-helpers.d.ts +48 -0
  127. package/dist/adapters/postgresql/tools/core/error-helpers.d.ts.map +1 -0
  128. package/dist/adapters/postgresql/tools/core/error-helpers.js +256 -0
  129. package/dist/adapters/postgresql/tools/core/error-helpers.js.map +1 -0
  130. package/dist/adapters/postgresql/tools/core/health.d.ts.map +1 -1
  131. package/dist/adapters/postgresql/tools/core/health.js +18 -4
  132. package/dist/adapters/postgresql/tools/core/health.js.map +1 -1
  133. package/dist/adapters/postgresql/tools/core/indexes.d.ts.map +1 -1
  134. package/dist/adapters/postgresql/tools/core/indexes.js +48 -6
  135. package/dist/adapters/postgresql/tools/core/indexes.js.map +1 -1
  136. package/dist/adapters/postgresql/tools/core/objects.d.ts.map +1 -1
  137. package/dist/adapters/postgresql/tools/core/objects.js +104 -85
  138. package/dist/adapters/postgresql/tools/core/objects.js.map +1 -1
  139. package/dist/adapters/postgresql/tools/core/query.d.ts.map +1 -1
  140. package/dist/adapters/postgresql/tools/core/query.js +100 -42
  141. package/dist/adapters/postgresql/tools/core/query.js.map +1 -1
  142. package/dist/adapters/postgresql/tools/core/schemas.d.ts +51 -25
  143. package/dist/adapters/postgresql/tools/core/schemas.d.ts.map +1 -1
  144. package/dist/adapters/postgresql/tools/core/schemas.js +51 -25
  145. package/dist/adapters/postgresql/tools/core/schemas.js.map +1 -1
  146. package/dist/adapters/postgresql/tools/core/tables.d.ts.map +1 -1
  147. package/dist/adapters/postgresql/tools/core/tables.js +72 -32
  148. package/dist/adapters/postgresql/tools/core/tables.js.map +1 -1
  149. package/dist/adapters/postgresql/tools/cron.d.ts.map +1 -1
  150. package/dist/adapters/postgresql/tools/cron.js +333 -206
  151. package/dist/adapters/postgresql/tools/cron.js.map +1 -1
  152. package/dist/adapters/postgresql/tools/introspection.d.ts +15 -0
  153. package/dist/adapters/postgresql/tools/introspection.d.ts.map +1 -0
  154. package/dist/adapters/postgresql/tools/introspection.js +1682 -0
  155. package/dist/adapters/postgresql/tools/introspection.js.map +1 -0
  156. package/dist/adapters/postgresql/tools/jsonb/advanced.d.ts.map +1 -1
  157. package/dist/adapters/postgresql/tools/jsonb/advanced.js +394 -297
  158. package/dist/adapters/postgresql/tools/jsonb/advanced.js.map +1 -1
  159. package/dist/adapters/postgresql/tools/jsonb/basic.d.ts.map +1 -1
  160. package/dist/adapters/postgresql/tools/jsonb/basic.js +686 -398
  161. package/dist/adapters/postgresql/tools/jsonb/basic.js.map +1 -1
  162. package/dist/adapters/postgresql/tools/kcache.d.ts.map +1 -1
  163. package/dist/adapters/postgresql/tools/kcache.js +278 -246
  164. package/dist/adapters/postgresql/tools/kcache.js.map +1 -1
  165. package/dist/adapters/postgresql/tools/ltree.d.ts.map +1 -1
  166. package/dist/adapters/postgresql/tools/ltree.js +137 -38
  167. package/dist/adapters/postgresql/tools/ltree.js.map +1 -1
  168. package/dist/adapters/postgresql/tools/monitoring.d.ts.map +1 -1
  169. package/dist/adapters/postgresql/tools/monitoring.js +86 -55
  170. package/dist/adapters/postgresql/tools/monitoring.js.map +1 -1
  171. package/dist/adapters/postgresql/tools/partitioning.d.ts.map +1 -1
  172. package/dist/adapters/postgresql/tools/partitioning.js +79 -15
  173. package/dist/adapters/postgresql/tools/partitioning.js.map +1 -1
  174. package/dist/adapters/postgresql/tools/partman/management.d.ts.map +1 -1
  175. package/dist/adapters/postgresql/tools/partman/management.js +43 -56
  176. package/dist/adapters/postgresql/tools/partman/management.js.map +1 -1
  177. package/dist/adapters/postgresql/tools/partman/operations.d.ts.map +1 -1
  178. package/dist/adapters/postgresql/tools/partman/operations.js +137 -24
  179. package/dist/adapters/postgresql/tools/partman/operations.js.map +1 -1
  180. package/dist/adapters/postgresql/tools/performance/analysis.d.ts.map +1 -1
  181. package/dist/adapters/postgresql/tools/performance/analysis.js +276 -165
  182. package/dist/adapters/postgresql/tools/performance/analysis.js.map +1 -1
  183. package/dist/adapters/postgresql/tools/performance/explain.d.ts.map +1 -1
  184. package/dist/adapters/postgresql/tools/performance/explain.js +61 -21
  185. package/dist/adapters/postgresql/tools/performance/explain.js.map +1 -1
  186. package/dist/adapters/postgresql/tools/performance/monitoring.d.ts.map +1 -1
  187. package/dist/adapters/postgresql/tools/performance/monitoring.js +52 -12
  188. package/dist/adapters/postgresql/tools/performance/monitoring.js.map +1 -1
  189. package/dist/adapters/postgresql/tools/performance/optimization.d.ts.map +1 -1
  190. package/dist/adapters/postgresql/tools/performance/optimization.js +92 -81
  191. package/dist/adapters/postgresql/tools/performance/optimization.js.map +1 -1
  192. package/dist/adapters/postgresql/tools/performance/stats.d.ts.map +1 -1
  193. package/dist/adapters/postgresql/tools/performance/stats.js +182 -60
  194. package/dist/adapters/postgresql/tools/performance/stats.js.map +1 -1
  195. package/dist/adapters/postgresql/tools/pgcrypto.d.ts.map +1 -1
  196. package/dist/adapters/postgresql/tools/pgcrypto.js +277 -102
  197. package/dist/adapters/postgresql/tools/pgcrypto.js.map +1 -1
  198. package/dist/adapters/postgresql/tools/postgis/advanced.d.ts.map +1 -1
  199. package/dist/adapters/postgresql/tools/postgis/advanced.js +298 -230
  200. package/dist/adapters/postgresql/tools/postgis/advanced.js.map +1 -1
  201. package/dist/adapters/postgresql/tools/postgis/basic.d.ts.map +1 -1
  202. package/dist/adapters/postgresql/tools/postgis/basic.js +370 -251
  203. package/dist/adapters/postgresql/tools/postgis/basic.js.map +1 -1
  204. package/dist/adapters/postgresql/tools/postgis/standalone.d.ts.map +1 -1
  205. package/dist/adapters/postgresql/tools/postgis/standalone.js +135 -51
  206. package/dist/adapters/postgresql/tools/postgis/standalone.js.map +1 -1
  207. package/dist/adapters/postgresql/tools/schema.d.ts.map +1 -1
  208. package/dist/adapters/postgresql/tools/schema.js +580 -233
  209. package/dist/adapters/postgresql/tools/schema.js.map +1 -1
  210. package/dist/adapters/postgresql/tools/stats/advanced.d.ts.map +1 -1
  211. package/dist/adapters/postgresql/tools/stats/advanced.js +567 -506
  212. package/dist/adapters/postgresql/tools/stats/advanced.js.map +1 -1
  213. package/dist/adapters/postgresql/tools/stats/basic.d.ts.map +1 -1
  214. package/dist/adapters/postgresql/tools/stats/basic.js +340 -316
  215. package/dist/adapters/postgresql/tools/stats/basic.js.map +1 -1
  216. package/dist/adapters/postgresql/tools/text.d.ts.map +1 -1
  217. package/dist/adapters/postgresql/tools/text.js +690 -337
  218. package/dist/adapters/postgresql/tools/text.js.map +1 -1
  219. package/dist/adapters/postgresql/tools/transactions.d.ts.map +1 -1
  220. package/dist/adapters/postgresql/tools/transactions.js +157 -50
  221. package/dist/adapters/postgresql/tools/transactions.js.map +1 -1
  222. package/dist/adapters/postgresql/tools/vector/advanced.d.ts.map +1 -1
  223. package/dist/adapters/postgresql/tools/vector/advanced.js +18 -0
  224. package/dist/adapters/postgresql/tools/vector/advanced.js.map +1 -1
  225. package/dist/adapters/postgresql/tools/vector/basic.d.ts.map +1 -1
  226. package/dist/adapters/postgresql/tools/vector/basic.js +100 -53
  227. package/dist/adapters/postgresql/tools/vector/basic.js.map +1 -1
  228. package/dist/auth/auth-context.d.ts +28 -0
  229. package/dist/auth/auth-context.d.ts.map +1 -0
  230. package/dist/auth/auth-context.js +37 -0
  231. package/dist/auth/auth-context.js.map +1 -0
  232. package/dist/auth/scope-map.d.ts +20 -0
  233. package/dist/auth/scope-map.d.ts.map +1 -0
  234. package/dist/auth/scope-map.js +40 -0
  235. package/dist/auth/scope-map.js.map +1 -0
  236. package/dist/auth/scopes.d.ts.map +1 -1
  237. package/dist/auth/scopes.js +2 -0
  238. package/dist/auth/scopes.js.map +1 -1
  239. package/dist/cli.js +1 -1
  240. package/dist/cli.js.map +1 -1
  241. package/dist/codemode/api.d.ts +1 -0
  242. package/dist/codemode/api.d.ts.map +1 -1
  243. package/dist/codemode/api.js +35 -1
  244. package/dist/codemode/api.js.map +1 -1
  245. package/dist/codemode/index.d.ts +0 -2
  246. package/dist/codemode/index.d.ts.map +1 -1
  247. package/dist/codemode/index.js +0 -4
  248. package/dist/codemode/index.js.map +1 -1
  249. package/dist/codemode/sandbox.d.ts +14 -1
  250. package/dist/codemode/sandbox.d.ts.map +1 -1
  251. package/dist/codemode/sandbox.js +58 -19
  252. package/dist/codemode/sandbox.js.map +1 -1
  253. package/dist/codemode/types.d.ts.map +1 -1
  254. package/dist/codemode/types.js +3 -0
  255. package/dist/codemode/types.js.map +1 -1
  256. package/dist/constants/ServerInstructions.d.ts +5 -1
  257. package/dist/constants/ServerInstructions.d.ts.map +1 -1
  258. package/dist/constants/ServerInstructions.js +117 -31
  259. package/dist/constants/ServerInstructions.js.map +1 -1
  260. package/dist/filtering/ToolConstants.d.ts +22 -19
  261. package/dist/filtering/ToolConstants.d.ts.map +1 -1
  262. package/dist/filtering/ToolConstants.js +48 -37
  263. package/dist/filtering/ToolConstants.js.map +1 -1
  264. package/dist/filtering/ToolFilter.d.ts.map +1 -1
  265. package/dist/filtering/ToolFilter.js +10 -13
  266. package/dist/filtering/ToolFilter.js.map +1 -1
  267. package/dist/pool/ConnectionPool.js +1 -1
  268. package/dist/pool/ConnectionPool.js.map +1 -1
  269. package/dist/transports/http.d.ts +1 -0
  270. package/dist/transports/http.d.ts.map +1 -1
  271. package/dist/transports/http.js +75 -21
  272. package/dist/transports/http.js.map +1 -1
  273. package/dist/types/filtering.d.ts +2 -2
  274. package/dist/types/filtering.d.ts.map +1 -1
  275. package/dist/utils/icons.d.ts.map +1 -1
  276. package/dist/utils/icons.js +5 -0
  277. package/dist/utils/icons.js.map +1 -1
  278. package/dist/utils/where-clause.d.ts.map +1 -1
  279. package/dist/utils/where-clause.js +24 -0
  280. package/dist/utils/where-clause.js.map +1 -1
  281. package/package.json +20 -13
  282. package/dist/codemode/sandbox-factory.d.ts +0 -72
  283. package/dist/codemode/sandbox-factory.d.ts.map +0 -1
  284. package/dist/codemode/sandbox-factory.js +0 -88
  285. package/dist/codemode/sandbox-factory.js.map +0 -1
  286. package/dist/codemode/worker-sandbox.d.ts +0 -82
  287. package/dist/codemode/worker-sandbox.d.ts.map +0 -1
  288. package/dist/codemode/worker-sandbox.js +0 -244
  289. package/dist/codemode/worker-sandbox.js.map +0 -1
  290. package/dist/codemode/worker-script.d.ts +0 -8
  291. package/dist/codemode/worker-script.d.ts.map +0 -1
  292. package/dist/codemode/worker-script.js +0 -113
  293. package/dist/codemode/worker-script.js.map +0 -1
@@ -7,10 +7,11 @@
7
7
  * pg_cron enables scheduling of SQL commands using familiar cron syntax.
8
8
  * Supports standard cron (minute granularity) and interval scheduling.
9
9
  */
10
- import { z } from "zod";
10
+ import { z, ZodError } from "zod";
11
11
  import { readOnly, write, destructive } from "../../../utils/annotations.js";
12
12
  import { getToolIcons } from "../../../utils/icons.js";
13
- import { CronScheduleSchema, CronScheduleSchemaBase, CronScheduleInDatabaseSchema, CronScheduleInDatabaseSchemaBase, CronAlterJobSchema, CronUnscheduleSchema, CronJobRunDetailsSchema, CronCleanupHistorySchema, CronCleanupHistorySchemaBase,
13
+ import { formatPostgresError } from "./core/error-helpers.js";
14
+ import { CronScheduleSchema, CronScheduleSchemaBase, CronScheduleInDatabaseSchema, CronScheduleInDatabaseSchemaBase, CronAlterJobSchemaBase, CronAlterJobSchema, CronUnscheduleSchemaBase, CronUnscheduleSchema, CronJobRunDetailsSchemaBase, CronJobRunDetailsSchema, CronCleanupHistorySchema, CronCleanupHistorySchemaBase,
14
15
  // Output schemas
15
16
  CronCreateExtensionOutputSchema, CronScheduleOutputSchema, CronScheduleInDatabaseOutputSchema, CronUnscheduleOutputSchema, CronAlterJobOutputSchema, CronListJobsOutputSchema, CronJobRunDetailsOutputSchema, CronCleanupHistoryOutputSchema, } from "../schemas/index.js";
16
17
  /**
@@ -52,7 +53,7 @@ function createCronExtensionTool(adapter) {
52
53
  function createCronScheduleTool(adapter) {
53
54
  return {
54
55
  name: "pg_cron_schedule",
55
- description: `Schedule a new cron job. Supports standard cron syntax (e.g., "0 2 * * *" for 2 AM daily)
56
+ description: `Schedule a new cron job. Supports standard cron syntax (e.g., "0 2 * * *" for 2 AM daily)
56
57
  or interval syntax (e.g., "30 seconds"). Note: pg_cron allows duplicate job names; use unique names to avoid confusion. Returns the job ID.`,
57
58
  group: "cron",
58
59
  // Use base schema for MCP so properties are properly exposed
@@ -61,31 +62,45 @@ or interval syntax (e.g., "30 seconds"). Note: pg_cron allows duplicate job name
61
62
  annotations: write("Schedule Cron Job"),
62
63
  icons: getToolIcons("cron", write("Schedule Cron Job")),
63
64
  handler: async (params, _context) => {
64
- // Use transformed schema with alias resolution for validation
65
- const { schedule, command, jobName } = CronScheduleSchema.parse(params);
66
- let sql;
67
- let queryParams;
68
- if (jobName !== undefined) {
69
- sql = "SELECT cron.schedule($1, $2, $3) as jobid";
70
- queryParams = [jobName, schedule, command];
65
+ try {
66
+ // Use transformed schema with alias resolution for validation
67
+ const { schedule, command, jobName } = CronScheduleSchema.parse(params);
68
+ let sql;
69
+ let queryParams;
70
+ if (jobName !== undefined) {
71
+ sql = "SELECT cron.schedule($1, $2, $3) as jobid";
72
+ queryParams = [jobName, schedule, command];
73
+ }
74
+ else {
75
+ sql = "SELECT cron.schedule($1, $2) as jobid";
76
+ queryParams = [schedule, command];
77
+ }
78
+ const result = await adapter.executeQuery(sql, queryParams);
79
+ const jobId = result.rows?.[0]?.["jobid"];
80
+ return {
81
+ success: true,
82
+ jobId,
83
+ jobName: jobName ?? null,
84
+ schedule,
85
+ command,
86
+ message: `Job scheduled with ID ${String(jobId)}`,
87
+ hint: jobName
88
+ ? "Use pg_cron_list_jobs to verify job was created with expected name"
89
+ : undefined,
90
+ };
71
91
  }
72
- else {
73
- sql = "SELECT cron.schedule($1, $2) as jobid";
74
- queryParams = [schedule, command];
92
+ catch (error) {
93
+ if (error instanceof ZodError) {
94
+ return {
95
+ success: false,
96
+ error: error.issues.map((e) => e.message).join("; "),
97
+ };
98
+ }
99
+ return {
100
+ success: false,
101
+ error: formatPostgresError(error, { tool: "pg_cron_schedule" }),
102
+ };
75
103
  }
76
- const result = await adapter.executeQuery(sql, queryParams);
77
- const jobId = result.rows?.[0]?.["jobid"];
78
- return {
79
- success: true,
80
- jobId,
81
- jobName: jobName ?? null,
82
- schedule,
83
- command,
84
- message: `Job scheduled with ID ${String(jobId)}`,
85
- hint: jobName
86
- ? "Use pg_cron_list_jobs to verify job was created with expected name"
87
- : undefined,
88
- };
89
104
  },
90
105
  };
91
106
  }
@@ -95,7 +110,7 @@ or interval syntax (e.g., "30 seconds"). Note: pg_cron allows duplicate job name
95
110
  function createCronScheduleInDatabaseTool(adapter) {
96
111
  return {
97
112
  name: "pg_cron_schedule_in_database",
98
- description: `Schedule a cron job to run in a different database. Useful for cross-database
113
+ description: `Schedule a cron job to run in a different database. Useful for cross-database
99
114
  maintenance tasks. Returns the job ID.`,
100
115
  group: "cron",
101
116
  // Use base schema for MCP so properties are properly exposed
@@ -104,31 +119,47 @@ maintenance tasks. Returns the job ID.`,
104
119
  annotations: write("Schedule Cron in Database"),
105
120
  icons: getToolIcons("cron", write("Schedule Cron in Database")),
106
121
  handler: async (params, _context) => {
107
- // Use transformed schema with alias resolution for validation
108
- const { jobName, schedule, command, database, username, active } = CronScheduleInDatabaseSchema.parse(params);
109
- const activeVal = active ?? true;
110
- const sql = `SELECT cron.schedule_in_database($1, $2, $3, $4, $5, $6) as jobid`;
111
- const queryParams = [
112
- jobName,
113
- schedule,
114
- command,
115
- database,
116
- username ?? null,
117
- activeVal,
118
- ];
119
- const result = await adapter.executeQuery(sql, queryParams);
120
- const jobId = result.rows?.[0]?.["jobid"];
121
- return {
122
- success: true,
123
- jobId,
124
- jobName,
125
- schedule,
126
- command,
127
- database,
128
- username: username ?? null,
129
- active: activeVal,
130
- message: `Job scheduled in database '${database}' with ID ${String(jobId)}`,
131
- };
122
+ try {
123
+ // Use transformed schema with alias resolution for validation
124
+ const { jobName, schedule, command, database, username, active } = CronScheduleInDatabaseSchema.parse(params);
125
+ const activeVal = active ?? true;
126
+ const sql = `SELECT cron.schedule_in_database($1, $2, $3, $4, $5, $6) as jobid`;
127
+ const queryParams = [
128
+ jobName,
129
+ schedule,
130
+ command,
131
+ database,
132
+ username ?? null,
133
+ activeVal,
134
+ ];
135
+ const result = await adapter.executeQuery(sql, queryParams);
136
+ const jobId = result.rows?.[0]?.["jobid"];
137
+ return {
138
+ success: true,
139
+ jobId,
140
+ jobName,
141
+ schedule,
142
+ command,
143
+ database,
144
+ username: username ?? null,
145
+ active: activeVal,
146
+ message: `Job scheduled in database '${database}' with ID ${String(jobId)}`,
147
+ };
148
+ }
149
+ catch (error) {
150
+ if (error instanceof ZodError) {
151
+ return {
152
+ success: false,
153
+ error: error.issues.map((e) => e.message).join("; "),
154
+ };
155
+ }
156
+ return {
157
+ success: false,
158
+ error: formatPostgresError(error, {
159
+ tool: "pg_cron_schedule_in_database",
160
+ }),
161
+ };
162
+ }
132
163
  },
133
164
  };
134
165
  }
@@ -140,65 +171,79 @@ function createCronUnscheduleTool(adapter) {
140
171
  name: "pg_cron_unschedule",
141
172
  description: "Remove a scheduled cron job by its ID or name. If both are provided, jobName takes precedence. Job ID accepts numbers or numeric strings. Works for both active and inactive jobs.",
142
173
  group: "cron",
143
- inputSchema: CronUnscheduleSchema,
174
+ inputSchema: CronUnscheduleSchemaBase,
144
175
  outputSchema: CronUnscheduleOutputSchema,
145
176
  annotations: destructive("Unschedule Cron Job"),
146
177
  icons: getToolIcons("cron", destructive("Unschedule Cron Job")),
147
178
  handler: async (params, _context) => {
148
- const parsed = CronUnscheduleSchema.parse(params);
149
- // Prefer jobName over jobId when both provided
150
- const useJobName = parsed.jobName !== undefined;
151
- const warning = parsed.jobId !== undefined && parsed.jobName !== undefined
152
- ? "Both jobId and jobName provided; using jobName"
153
- : undefined;
154
- // Look up job info before deletion to return complete response
155
- let jobInfo = null;
156
179
  try {
157
- const lookupSql = useJobName
158
- ? "SELECT jobid, jobname FROM cron.job WHERE jobname = $1"
159
- : "SELECT jobid, jobname FROM cron.job WHERE jobid = $1::bigint";
160
- const lookupResult = await adapter.executeQuery(lookupSql, [
161
- useJobName ? parsed.jobName : parsed.jobId,
162
- ]);
163
- if (lookupResult.rows && lookupResult.rows.length > 0) {
164
- const row = lookupResult.rows[0];
165
- jobInfo = {
166
- jobid: Number(row.jobid),
167
- jobname: row.jobname,
168
- };
180
+ const parsed = CronUnscheduleSchema.parse(params);
181
+ // Prefer jobName over jobId when both provided
182
+ const useJobName = parsed.jobName !== undefined;
183
+ const warning = parsed.jobId !== undefined && parsed.jobName !== undefined
184
+ ? "Both jobId and jobName provided; using jobName"
185
+ : undefined;
186
+ // Look up job info before deletion to return complete response
187
+ let jobInfo = null;
188
+ try {
189
+ const lookupSql = useJobName
190
+ ? "SELECT jobid, jobname FROM cron.job WHERE jobname = $1"
191
+ : "SELECT jobid, jobname FROM cron.job WHERE jobid = $1::bigint";
192
+ const lookupResult = await adapter.executeQuery(lookupSql, [
193
+ useJobName ? parsed.jobName : parsed.jobId,
194
+ ]);
195
+ if (lookupResult.rows && lookupResult.rows.length > 0) {
196
+ const row = lookupResult.rows[0];
197
+ jobInfo = {
198
+ jobid: Number(row.jobid),
199
+ jobname: row.jobname,
200
+ };
201
+ }
169
202
  }
203
+ catch {
204
+ // Lookup failed, continue with unschedule attempt
205
+ }
206
+ // Use explicit type casting to ensure correct pg_cron function overload:
207
+ // - cron.unschedule(bigint) works for both active and inactive jobs
208
+ // - cron.unschedule(text) only finds active jobs by name
209
+ let sql;
210
+ let queryParams;
211
+ if (useJobName) {
212
+ sql = "SELECT cron.unschedule($1::text) as removed";
213
+ queryParams = [parsed.jobName];
214
+ }
215
+ else {
216
+ sql = "SELECT cron.unschedule($1::bigint) as removed";
217
+ queryParams = [parsed.jobId];
218
+ }
219
+ const result = await adapter.executeQuery(sql, queryParams);
220
+ const removed = result.rows?.[0]?.["removed"];
221
+ // Return complete job info from lookup
222
+ const resolvedJobId = jobInfo?.jobid ?? parsed.jobId ?? null;
223
+ const resolvedJobName = jobInfo?.jobname ?? parsed.jobName ?? null;
224
+ return {
225
+ success: removed,
226
+ jobId: resolvedJobId,
227
+ jobName: resolvedJobName,
228
+ usedIdentifier: useJobName ? "jobName" : "jobId",
229
+ warning,
230
+ message: removed
231
+ ? `Job ${resolvedJobId !== null ? `ID ${String(resolvedJobId)}` : `"${String(resolvedJobName)}"`} removed successfully`
232
+ : "Job not found",
233
+ };
170
234
  }
171
- catch {
172
- // Lookup failed, continue with unschedule attempt
173
- }
174
- // Use explicit type casting to ensure correct pg_cron function overload:
175
- // - cron.unschedule(bigint) works for both active and inactive jobs
176
- // - cron.unschedule(text) only finds active jobs by name
177
- let sql;
178
- let queryParams;
179
- if (useJobName) {
180
- sql = "SELECT cron.unschedule($1::text) as removed";
181
- queryParams = [parsed.jobName];
182
- }
183
- else {
184
- sql = "SELECT cron.unschedule($1::bigint) as removed";
185
- queryParams = [parsed.jobId];
235
+ catch (error) {
236
+ if (error instanceof ZodError) {
237
+ return {
238
+ success: false,
239
+ error: error.issues.map((e) => e.message).join("; "),
240
+ };
241
+ }
242
+ return {
243
+ success: false,
244
+ error: formatPostgresError(error, { tool: "pg_cron_unschedule" }),
245
+ };
186
246
  }
187
- const result = await adapter.executeQuery(sql, queryParams);
188
- const removed = result.rows?.[0]?.["removed"];
189
- // Return complete job info from lookup
190
- const resolvedJobId = jobInfo?.jobid ?? parsed.jobId ?? null;
191
- const resolvedJobName = jobInfo?.jobname ?? parsed.jobName ?? null;
192
- return {
193
- success: removed,
194
- jobId: resolvedJobId,
195
- jobName: resolvedJobName,
196
- usedIdentifier: useJobName ? "jobName" : "jobId",
197
- warning,
198
- message: removed
199
- ? `Job ${resolvedJobId !== null ? `ID ${String(resolvedJobId)}` : `"${String(resolvedJobName)}"`} removed successfully`
200
- : "Job not found",
201
- };
202
247
  },
203
248
  };
204
249
  }
@@ -208,37 +253,58 @@ function createCronUnscheduleTool(adapter) {
208
253
  function createCronAlterJobTool(adapter) {
209
254
  return {
210
255
  name: "pg_cron_alter_job",
211
- description: `Modify an existing cron job. Can change schedule, command, database, username,
256
+ description: `Modify an existing cron job. Can change schedule, command, database, username,
212
257
  or active status. Only specify the parameters you want to change.`,
213
258
  group: "cron",
214
- inputSchema: CronAlterJobSchema,
259
+ inputSchema: CronAlterJobSchemaBase,
215
260
  outputSchema: CronAlterJobOutputSchema,
216
261
  annotations: write("Alter Cron Job"),
217
262
  icons: getToolIcons("cron", write("Alter Cron Job")),
218
263
  handler: async (params, _context) => {
219
- const { jobId, schedule, command, database, username, active } = CronAlterJobSchema.parse(params);
220
- const sql = `SELECT cron.alter_job($1, $2, $3, $4, $5, $6)`;
221
- const queryParams = [
222
- jobId,
223
- schedule ?? null,
224
- command ?? null,
225
- database ?? null,
226
- username ?? null,
227
- active ?? null,
228
- ];
229
- await adapter.executeQuery(sql, queryParams);
230
- return {
231
- success: true,
232
- jobId,
233
- changes: {
234
- schedule: schedule ?? undefined,
235
- command: command ?? undefined,
236
- database: database ?? undefined,
237
- username: username ?? undefined,
238
- active: active ?? undefined,
239
- },
240
- message: `Job ${String(jobId)} updated successfully`,
241
- };
264
+ let parsedJobId;
265
+ try {
266
+ const { jobId, schedule, command, database, username, active } = CronAlterJobSchema.parse(params);
267
+ parsedJobId = jobId;
268
+ const sql = `SELECT cron.alter_job($1, $2, $3, $4, $5, $6)`;
269
+ const queryParams = [
270
+ jobId,
271
+ schedule ?? null,
272
+ command ?? null,
273
+ database ?? null,
274
+ username ?? null,
275
+ active ?? null,
276
+ ];
277
+ await adapter.executeQuery(sql, queryParams);
278
+ return {
279
+ success: true,
280
+ jobId,
281
+ changes: {
282
+ schedule: schedule ?? undefined,
283
+ command: command ?? undefined,
284
+ database: database ?? undefined,
285
+ username: username ?? undefined,
286
+ active: active ?? undefined,
287
+ },
288
+ message: `Job ${String(jobId)} updated successfully`,
289
+ };
290
+ }
291
+ catch (error) {
292
+ if (error instanceof ZodError) {
293
+ return {
294
+ success: false,
295
+ error: error.issues.map((e) => e.message).join("; "),
296
+ };
297
+ }
298
+ return {
299
+ success: false,
300
+ error: formatPostgresError(error, {
301
+ tool: "pg_cron_alter_job",
302
+ ...(parsedJobId !== undefined && {
303
+ target: String(parsedJobId),
304
+ }),
305
+ }),
306
+ };
307
+ }
242
308
  },
243
309
  };
244
310
  }
@@ -264,7 +330,7 @@ function createCronListJobsTool(adapter) {
264
330
  handler: async (params, _context) => {
265
331
  const parsed = ListJobsSchema.parse(params ?? {});
266
332
  let sql = `
267
- SELECT
333
+ SELECT
268
334
  jobid,
269
335
  jobname,
270
336
  schedule,
@@ -326,40 +392,50 @@ function createCronListJobsTool(adapter) {
326
392
  function createCronJobRunDetailsTool(adapter) {
327
393
  return {
328
394
  name: "pg_cron_job_run_details",
329
- description: `View execution history for cron jobs. Shows start/end times, status, and return messages.
395
+ description: `View execution history for cron jobs. Shows start/end times, status, and return messages.
330
396
  Useful for monitoring and debugging scheduled jobs.`,
331
397
  group: "cron",
332
- inputSchema: CronJobRunDetailsSchema,
398
+ inputSchema: CronJobRunDetailsSchemaBase,
333
399
  outputSchema: CronJobRunDetailsOutputSchema,
334
400
  annotations: readOnly("Cron Job Run Details"),
335
401
  icons: getToolIcons("cron", readOnly("Cron Job Run Details")),
336
402
  handler: async (params, _context) => {
337
- const { jobId, status, limit } = CronJobRunDetailsSchema.parse(params);
338
- const conditions = [];
339
- const queryParams = [];
340
- let paramIndex = 1;
341
- if (jobId !== undefined) {
342
- conditions.push(`jobid = $${String(paramIndex++)}`);
343
- queryParams.push(jobId);
344
- }
345
- if (status !== undefined) {
346
- conditions.push(`status = $${String(paramIndex++)}`);
347
- queryParams.push(status);
348
- }
349
- const whereClause = conditions.length > 0 ? `WHERE ${conditions.join(" AND ")}` : "";
350
- // Handle limit: 0 as "no limit" (return all rows), consistent with other AI-optimized tools
351
- const limitVal = limit === 0 ? null : (limit ?? 50);
352
- // Get total count for truncation indicator (only needed when limiting)
353
- let totalCount;
354
- if (limitVal !== null) {
355
- const countSql = `SELECT COUNT(*)::int as total FROM cron.job_run_details ${whereClause}`;
356
- const countResult = await adapter.executeQuery(countSql, queryParams);
357
- totalCount =
358
- countResult.rows?.[0]?.total ?? 0;
359
- }
360
- const limitClause = limitVal !== null ? `LIMIT ${String(limitVal)}` : "";
361
- const sql = `
362
- SELECT
403
+ try {
404
+ const { jobId, status, limit } = CronJobRunDetailsSchema.parse(params);
405
+ // Handler-level validation for status (relaxed from z.enum to z.string for structured errors)
406
+ const VALID_STATUSES = ["running", "succeeded", "failed"];
407
+ if (status !== undefined && !VALID_STATUSES.includes(status)) {
408
+ return {
409
+ success: false,
410
+ error: `Invalid status "${status}". Valid statuses: ${VALID_STATUSES.join(", ")}`,
411
+ };
412
+ }
413
+ const conditions = [];
414
+ const queryParams = [];
415
+ let paramIndex = 1;
416
+ if (jobId !== undefined) {
417
+ conditions.push(`jobid = $${String(paramIndex++)}`);
418
+ queryParams.push(jobId);
419
+ }
420
+ if (status !== undefined) {
421
+ conditions.push(`status = $${String(paramIndex)}`);
422
+ queryParams.push(status);
423
+ }
424
+ const whereClause = conditions.length > 0 ? `WHERE ${conditions.join(" AND ")}` : "";
425
+ // Handle limit: 0 as "no limit" (return all rows), consistent with other AI-optimized tools
426
+ const limitVal = limit === 0 ? null : (limit ?? 50);
427
+ // Get total count for truncation indicator (only needed when limiting)
428
+ let totalCount;
429
+ if (limitVal !== null) {
430
+ const countSql = `SELECT COUNT(*)::int as total FROM cron.job_run_details ${whereClause}`;
431
+ const countResult = await adapter.executeQuery(countSql, queryParams);
432
+ totalCount =
433
+ countResult.rows?.[0]?.total ??
434
+ 0;
435
+ }
436
+ const limitClause = limitVal !== null ? `LIMIT ${String(limitVal)}` : "";
437
+ const sql = `
438
+ SELECT
363
439
  runid,
364
440
  jobid,
365
441
  job_pid,
@@ -375,34 +451,53 @@ Useful for monitoring and debugging scheduled jobs.`,
375
451
  ORDER BY start_time DESC
376
452
  ${limitClause}
377
453
  `;
378
- const result = await adapter.executeQuery(sql, queryParams);
379
- // Normalize runid and jobid to numbers (PostgreSQL BIGINT may return as strings)
380
- const rows = (result.rows ?? []).map((r) => ({
381
- ...r,
382
- runid: r["runid"] !== null && r["runid"] !== undefined
383
- ? Number(r["runid"])
384
- : null,
385
- jobid: r["jobid"] !== null && r["jobid"] !== undefined
386
- ? Number(r["jobid"])
387
- : null,
388
- }));
389
- const succeeded = rows.filter((r) => r["status"] === "succeeded").length;
390
- const failed = rows.filter((r) => r["status"] === "failed").length;
391
- const running = rows.filter((r) => r["status"] === "running").length;
392
- // Determine if results were truncated (only when limiting)
393
- const truncated = limitVal !== null &&
394
- totalCount !== undefined &&
395
- rows.length < totalCount;
396
- return {
397
- runs: rows,
398
- count: rows.length,
399
- ...(truncated ? { truncated: true, totalCount } : {}),
400
- summary: {
401
- succeeded,
402
- failed,
403
- running,
404
- },
405
- };
454
+ const result = await adapter.executeQuery(sql, queryParams);
455
+ // Normalize runid and jobid to numbers (PostgreSQL BIGINT may return as strings)
456
+ const rows = (result.rows ?? []).map((r) => ({
457
+ ...r,
458
+ runid: r["runid"] !== null && r["runid"] !== undefined
459
+ ? Number(r["runid"])
460
+ : null,
461
+ jobid: r["jobid"] !== null && r["jobid"] !== undefined
462
+ ? Number(r["jobid"])
463
+ : null,
464
+ }));
465
+ const succeeded = rows.filter((r) => r["status"] === "succeeded").length;
466
+ const failed = rows.filter((r) => r["status"] === "failed").length;
467
+ const running = rows.filter((r) => r["status"] === "running").length;
468
+ // Determine if results were truncated (only when limiting)
469
+ const truncated = limitVal !== null &&
470
+ totalCount !== undefined &&
471
+ rows.length < totalCount;
472
+ return {
473
+ runs: rows,
474
+ count: rows.length,
475
+ ...(truncated ? { truncated: true, totalCount } : {}),
476
+ summary: {
477
+ succeeded,
478
+ failed,
479
+ running,
480
+ },
481
+ };
482
+ }
483
+ catch (error) {
484
+ if (error instanceof ZodError) {
485
+ return {
486
+ runs: [],
487
+ count: 0,
488
+ summary: { succeeded: 0, failed: 0, running: 0 },
489
+ error: error.issues.map((e) => e.message).join("; "),
490
+ };
491
+ }
492
+ return {
493
+ runs: [],
494
+ count: 0,
495
+ summary: { succeeded: 0, failed: 0, running: 0 },
496
+ error: formatPostgresError(error, {
497
+ tool: "pg_cron_job_run_details",
498
+ }),
499
+ };
500
+ }
406
501
  },
407
502
  };
408
503
  }
@@ -412,7 +507,7 @@ Useful for monitoring and debugging scheduled jobs.`,
412
507
  function createCronCleanupHistoryTool(adapter) {
413
508
  return {
414
509
  name: "pg_cron_cleanup_history",
415
- description: `Delete old job run history records. Helps prevent the cron.job_run_details table
510
+ description: `Delete old job run history records. Helps prevent the cron.job_run_details table
416
511
  from growing too large. By default, removes records older than 7 days.`,
417
512
  group: "cron",
418
513
  // Use base schema for MCP visibility
@@ -421,29 +516,61 @@ from growing too large. By default, removes records older than 7 days.`,
421
516
  annotations: destructive("Cleanup Cron History"),
422
517
  icons: getToolIcons("cron", destructive("Cleanup Cron History")),
423
518
  handler: async (params, _context) => {
424
- // Use transformed schema for validation with alias support
425
- const { olderThanDays, jobId } = CronCleanupHistorySchema.parse(params);
426
- const days = olderThanDays ?? 7;
427
- const conditions = [
428
- `end_time < now() - interval '${String(days)} days'`,
429
- ];
430
- const queryParams = [];
431
- if (jobId !== undefined) {
432
- conditions.push("jobid = $1");
433
- queryParams.push(jobId);
434
- }
435
- const sql = `
519
+ try {
520
+ // Use transformed schema for validation with alias support
521
+ const { olderThanDays, jobId } = CronCleanupHistorySchema.parse(params);
522
+ const days = olderThanDays ?? 7;
523
+ // Handler-level validation for negative days (relaxed from z.min for structured errors)
524
+ if (days < 0) {
525
+ return {
526
+ success: false,
527
+ deletedCount: 0,
528
+ olderThanDays: days,
529
+ jobId: jobId ?? null,
530
+ message: `olderThanDays must be non-negative, got ${String(days)}`,
531
+ };
532
+ }
533
+ const conditions = [
534
+ `end_time < now() - ($1 || ' days')::interval`,
535
+ ];
536
+ const queryParams = [String(days)];
537
+ if (jobId !== undefined) {
538
+ conditions.push("jobid = $2");
539
+ queryParams.push(jobId);
540
+ }
541
+ const sql = `
436
542
  DELETE FROM cron.job_run_details
437
543
  WHERE ${conditions.join(" AND ")}
438
544
  `;
439
- const result = await adapter.executeQuery(sql, queryParams);
440
- return {
441
- success: true,
442
- deletedCount: result.rowsAffected ?? 0,
443
- olderThanDays: days,
444
- jobId: jobId ?? null,
445
- message: `Deleted ${String(result.rowsAffected ?? 0)} old job run records`,
446
- };
545
+ const result = await adapter.executeQuery(sql, queryParams);
546
+ return {
547
+ success: true,
548
+ deletedCount: result.rowsAffected ?? 0,
549
+ olderThanDays: days,
550
+ jobId: jobId ?? null,
551
+ message: `Deleted ${String(result.rowsAffected ?? 0)} old job run records`,
552
+ };
553
+ }
554
+ catch (error) {
555
+ if (error instanceof ZodError) {
556
+ return {
557
+ success: false,
558
+ deletedCount: 0,
559
+ olderThanDays: 0,
560
+ jobId: null,
561
+ message: error.issues.map((e) => e.message).join("; "),
562
+ };
563
+ }
564
+ return {
565
+ success: false,
566
+ deletedCount: 0,
567
+ olderThanDays: 0,
568
+ jobId: null,
569
+ message: formatPostgresError(error, {
570
+ tool: "pg_cron_cleanup_history",
571
+ }),
572
+ };
573
+ }
447
574
  },
448
575
  };
449
576
  }