postgresai 0.14.0-dev.82 → 0.14.0-dev.83

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.
@@ -758,7 +758,7 @@ program
758
758
 
759
759
  const supabaseClient = new SupabaseClient(supabaseConfig);
760
760
 
761
- // Fetch database URL for JSON output (non-blocking, best-effort)
761
+ // Fetch database URL for JSON output (best-effort, errors return null)
762
762
  let databaseUrl: string | null = null;
763
763
  if (jsonOutput) {
764
764
  databaseUrl = await fetchPoolerDatabaseUrl(supabaseConfig, opts.monitoringUser);
@@ -1648,12 +1648,13 @@ program
1648
1648
  .option("--check-id <id>", `specific check to run (see list below), or ALL`, "ALL")
1649
1649
  .option("--node-name <name>", "node name for reports", "node-01")
1650
1650
  .option("--output <path>", "output directory for JSON files")
1651
- .option("--[no-]upload", "upload JSON results to PostgresAI (default: enabled; requires API key)", undefined)
1651
+ .option("--upload", "upload JSON results to PostgresAI (requires API key)")
1652
+ .option("--no-upload", "disable upload to PostgresAI")
1652
1653
  .option(
1653
1654
  "--project <project>",
1654
1655
  "project name or ID for remote upload (used with --upload; defaults to config defaultProject; auto-generated on first run)"
1655
1656
  )
1656
- .option("--json", "output JSON to stdout (implies --no-upload)")
1657
+ .option("--json", "output JSON to stdout")
1657
1658
  .addHelpText(
1658
1659
  "after",
1659
1660
  [
@@ -1678,7 +1679,9 @@ program
1678
1679
 
1679
1680
  const shouldPrintJson = !!opts.json;
1680
1681
  const uploadExplicitlyRequested = opts.upload === true;
1681
- const uploadExplicitlyDisabled = opts.upload === false || shouldPrintJson;
1682
+ // Note: --json and --upload/--no-upload are independent flags.
1683
+ // Use --no-upload to explicitly disable upload when using --json.
1684
+ const uploadExplicitlyDisabled = opts.upload === false;
1682
1685
  let shouldUpload = !uploadExplicitlyDisabled;
1683
1686
 
1684
1687
  // Preflight: validate/create output directory BEFORE connecting / running checks.
@@ -1830,7 +1833,8 @@ async function resolveOrInitPaths(): Promise<PathResolution> {
1830
1833
  */
1831
1834
  function isDockerRunning(): boolean {
1832
1835
  try {
1833
- const result = spawnSync("docker", ["info"], { stdio: "pipe", timeout: 5000 });
1836
+ // Note: timeout is supported by Bun but not in @types/bun
1837
+ const result = spawnSync("docker", ["info"], { stdio: "pipe", timeout: 5000 } as Parameters<typeof spawnSync>[2]);
1834
1838
  return result.status === 0;
1835
1839
  } catch {
1836
1840
  return false;
@@ -1842,7 +1846,7 @@ function isDockerRunning(): boolean {
1842
1846
  */
1843
1847
  function getComposeCmd(): string[] | null {
1844
1848
  const tryCmd = (cmd: string, args: string[]): boolean =>
1845
- spawnSync(cmd, args, { stdio: "ignore", timeout: 5000 }).status === 0;
1849
+ spawnSync(cmd, args, { stdio: "ignore", timeout: 5000 } as Parameters<typeof spawnSync>[2]).status === 0;
1846
1850
  if (tryCmd("docker-compose", ["version"])) return ["docker-compose"];
1847
1851
  if (tryCmd("docker", ["compose", "version"])) return ["docker", "compose"];
1848
1852
  return null;
@@ -1856,7 +1860,7 @@ function checkRunningContainers(): { running: boolean; containers: string[] } {
1856
1860
  const result = spawnSync(
1857
1861
  "docker",
1858
1862
  ["ps", "--filter", "name=grafana-with-datasources", "--filter", "name=pgwatch", "--format", "{{.Names}}"],
1859
- { stdio: "pipe", encoding: "utf8", timeout: 5000 }
1863
+ { stdio: "pipe", encoding: "utf8", timeout: 5000 } as Parameters<typeof spawnSync>[2]
1860
1864
  );
1861
1865
 
1862
1866
  if (result.status === 0 && result.stdout) {
package/bun.lock CHANGED
@@ -11,12 +11,12 @@
11
11
  "pg": "^8.16.3",
12
12
  },
13
13
  "devDependencies": {
14
- "@types/bun": "^1.1.14",
14
+ "@types/bun": "^1.3.6",
15
15
  "@types/js-yaml": "^4.0.9",
16
16
  "@types/pg": "^8.15.6",
17
17
  "ajv": "^8.17.1",
18
18
  "ajv-formats": "^3.0.1",
19
- "typescript": "^5.3.3",
19
+ "typescript": "^5.9.3",
20
20
  },
21
21
  },
22
22
  },
@@ -25,7 +25,7 @@
25
25
 
26
26
  "@modelcontextprotocol/sdk": ["@modelcontextprotocol/sdk@1.25.1", "", { "dependencies": { "@hono/node-server": "^1.19.7", "ajv": "^8.17.1", "ajv-formats": "^3.0.1", "content-type": "^1.0.5", "cors": "^2.8.5", "cross-spawn": "^7.0.5", "eventsource": "^3.0.2", "eventsource-parser": "^3.0.0", "express": "^5.0.1", "express-rate-limit": "^7.5.0", "jose": "^6.1.1", "json-schema-typed": "^8.0.2", "pkce-challenge": "^5.0.0", "raw-body": "^3.0.0", "zod": "^3.25 || ^4.0", "zod-to-json-schema": "^3.25.0" }, "peerDependencies": { "@cfworker/json-schema": "^4.1.1", "zod": "^3.25 || ^4.0" }, "optionalPeers": ["@cfworker/json-schema"] }, "sha512-yO28oVFFC7EBoiKdAn+VqRm+plcfv4v0xp6osG/VsCB0NlPZWi87ajbCZZ8f/RvOFLEu7//rSRmuZZ7lMoe3gQ=="],
27
27
 
28
- "@types/bun": ["@types/bun@1.3.5", "", { "dependencies": { "bun-types": "1.3.5" } }, "sha512-RnygCqNrd3srIPEWBd5LFeUYG7plCoH2Yw9WaZGyNmdTEei+gWaHqydbaIRkIkcbXwhBT94q78QljxN0Sk838w=="],
28
+ "@types/bun": ["@types/bun@1.3.6", "", { "dependencies": { "bun-types": "1.3.6" } }, "sha512-uWCv6FO/8LcpREhenN1d1b6fcspAB+cefwD7uti8C8VffIv0Um08TKMn98FynpTiU38+y2dUO55T11NgDt8VAA=="],
29
29
 
30
30
  "@types/js-yaml": ["@types/js-yaml@4.0.9", "", {}, "sha512-k4MGaQl5TGo/iipqb2UDG2UwjXziSWkh0uysQelTlJpX1qGlpUZYm8PnO4DxG1qBomtJUdYJ6qR6xdIah10JLg=="],
31
31
 
@@ -43,7 +43,7 @@
43
43
 
44
44
  "body-parser": ["body-parser@2.2.1", "", { "dependencies": { "bytes": "^3.1.2", "content-type": "^1.0.5", "debug": "^4.4.3", "http-errors": "^2.0.0", "iconv-lite": "^0.7.0", "on-finished": "^2.4.1", "qs": "^6.14.0", "raw-body": "^3.0.1", "type-is": "^2.0.1" } }, "sha512-nfDwkulwiZYQIGwxdy0RUmowMhKcFVcYXUU7m4QlKYim1rUtg83xm2yjZ40QjDuc291AJjjeSc9b++AWHSgSHw=="],
45
45
 
46
- "bun-types": ["bun-types@1.3.5", "", { "dependencies": { "@types/node": "*" } }, "sha512-inmAYe2PFLs0SUbFOWSVD24sg1jFlMPxOjOSSCYqUgn4Hsc3rDc7dFvfVYjFPNHtov6kgUeulV4SxbuIV/stPw=="],
46
+ "bun-types": ["bun-types@1.3.6", "", { "dependencies": { "@types/node": "*" } }, "sha512-OlFwHcnNV99r//9v5IIOgQ9Uk37gZqrNMCcqEaExdkVq3Avwqok1bJFmvGMCkCE0FqzdY8VMOZpfpR3lwI+CsQ=="],
47
47
 
48
48
  "bytes": ["bytes@3.1.2", "", {}, "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg=="],
49
49
 
@@ -13064,7 +13064,7 @@ var {
13064
13064
  // package.json
13065
13065
  var package_default = {
13066
13066
  name: "postgresai",
13067
- version: "0.14.0-dev.82",
13067
+ version: "0.14.0-dev.83",
13068
13068
  description: "postgres_ai CLI",
13069
13069
  license: "Apache-2.0",
13070
13070
  private: false,
@@ -13109,12 +13109,12 @@ var package_default = {
13109
13109
  pg: "^8.16.3"
13110
13110
  },
13111
13111
  devDependencies: {
13112
- "@types/bun": "^1.1.14",
13112
+ "@types/bun": "^1.3.6",
13113
13113
  "@types/js-yaml": "^4.0.9",
13114
13114
  "@types/pg": "^8.15.6",
13115
13115
  ajv: "^8.17.1",
13116
13116
  "ajv-formats": "^3.0.1",
13117
- typescript: "^5.3.3"
13117
+ typescript: "^5.9.3"
13118
13118
  },
13119
13119
  publishConfig: {
13120
13120
  access: "public"
@@ -15889,7 +15889,7 @@ var Result = import_lib.default.Result;
15889
15889
  var TypeOverrides = import_lib.default.TypeOverrides;
15890
15890
  var defaults = import_lib.default.defaults;
15891
15891
  // package.json
15892
- var version = "0.14.0-dev.82";
15892
+ var version = "0.14.0-dev.83";
15893
15893
  var package_default2 = {
15894
15894
  name: "postgresai",
15895
15895
  version,
@@ -15937,12 +15937,12 @@ var package_default2 = {
15937
15937
  pg: "^8.16.3"
15938
15938
  },
15939
15939
  devDependencies: {
15940
- "@types/bun": "^1.1.14",
15940
+ "@types/bun": "^1.3.6",
15941
15941
  "@types/js-yaml": "^4.0.9",
15942
15942
  "@types/pg": "^8.15.6",
15943
15943
  ajv: "^8.17.1",
15944
15944
  "ajv-formats": "^3.0.1",
15945
- typescript: "^5.3.3"
15945
+ typescript: "^5.9.3"
15946
15946
  },
15947
15947
  publishConfig: {
15948
15948
  access: "public"
@@ -25378,6 +25378,9 @@ class SupabaseClient {
25378
25378
  }
25379
25379
  async function fetchPoolerDatabaseUrl(config2, username) {
25380
25380
  const url = `${SUPABASE_API_BASE}/v1/projects/${encodeURIComponent(config2.projectRef)}/config/database/pooler`;
25381
+ const suffix = `.${config2.projectRef}`;
25382
+ const effectiveUsername = username.endsWith(suffix) ? username : `${username}${suffix}`;
25383
+ const encodedUsername = encodeURIComponent(effectiveUsername);
25381
25384
  try {
25382
25385
  const response = await fetch(url, {
25383
25386
  method: "GET",
@@ -25392,13 +25395,13 @@ async function fetchPoolerDatabaseUrl(config2, username) {
25392
25395
  if (Array.isArray(data) && data.length > 0) {
25393
25396
  const pooler = data[0];
25394
25397
  if (pooler.db_host && pooler.db_port && pooler.db_name) {
25395
- return `postgresql://${username}@${pooler.db_host}:${pooler.db_port}/${pooler.db_name}`;
25398
+ return `postgresql://${encodedUsername}@${pooler.db_host}:${pooler.db_port}/${pooler.db_name}`;
25396
25399
  }
25397
25400
  if (typeof pooler.connection_string === "string") {
25398
25401
  try {
25399
25402
  const connUrl = new URL(pooler.connection_string);
25400
25403
  const portPart = connUrl.port ? `:${connUrl.port}` : "";
25401
- return `postgresql://${username}@${connUrl.hostname}${portPart}${connUrl.pathname}`;
25404
+ return `postgresql://${encodedUsername}@${connUrl.hostname}${portPart}${connUrl.pathname}`;
25402
25405
  } catch {
25403
25406
  return null;
25404
25407
  }
@@ -27789,218 +27792,6 @@ async function generateF001(client, nodeName) {
27789
27792
  };
27790
27793
  return report;
27791
27794
  }
27792
- async function generateF004(client, nodeName) {
27793
- const report = createBaseReport("F004", "Autovacuum: heap bloat estimate", nodeName);
27794
- const postgresVersion = await getPostgresVersion(client);
27795
- let bloatData = [];
27796
- let bloatError = null;
27797
- try {
27798
- const result = await client.query(`
27799
- select
27800
- schemaname,
27801
- tblname,
27802
- (bs * tblpages)::bigint as real_size_bytes,
27803
- pg_size_pretty((bs * tblpages)::bigint) as real_size_pretty,
27804
- ((tblpages - est_tblpages) * bs)::bigint as extra_size_bytes,
27805
- pg_size_pretty(((tblpages - est_tblpages) * bs)::bigint) as extra_size_pretty,
27806
- case when tblpages > 0 and tblpages - est_tblpages > 0
27807
- then round(100.0 * (tblpages - est_tblpages) / tblpages, 2)
27808
- else 0
27809
- end as extra_pct,
27810
- fillfactor,
27811
- case when tblpages - est_tblpages_ff > 0
27812
- then ((tblpages - est_tblpages_ff) * bs)::bigint
27813
- else 0
27814
- end as bloat_size_bytes,
27815
- pg_size_pretty(case when tblpages - est_tblpages_ff > 0
27816
- then ((tblpages - est_tblpages_ff) * bs)::bigint
27817
- else 0
27818
- end) as bloat_size_pretty,
27819
- case when tblpages > 0 and tblpages - est_tblpages_ff > 0
27820
- then round(100.0 * (tblpages - est_tblpages_ff) / tblpages, 2)
27821
- else 0
27822
- end as bloat_pct,
27823
- is_na::text
27824
- from (
27825
- select
27826
- ceil(reltuples / ((bs - page_hdr) / tpl_size)) + ceil(toasttuples / 4) as est_tblpages,
27827
- ceil(reltuples / ((bs - page_hdr) * fillfactor / (tpl_size * 100))) + ceil(toasttuples / 4) as est_tblpages_ff,
27828
- tblpages, fillfactor, bs, schemaname, tblname, is_na
27829
- from (
27830
- select
27831
- (4 + tpl_hdr_size + tpl_data_size + (2 * ma)
27832
- - case when tpl_hdr_size % ma = 0 then ma else tpl_hdr_size % ma end
27833
- - case when ceil(tpl_data_size)::int % ma = 0 then ma else ceil(tpl_data_size)::int % ma end
27834
- ) as tpl_size,
27835
- (heappages + toastpages) as tblpages,
27836
- reltuples, toasttuples, bs, page_hdr, schemaname, tblname, fillfactor, is_na
27837
- from (
27838
- select
27839
- ns.nspname as schemaname,
27840
- tbl.relname as tblname,
27841
- tbl.reltuples,
27842
- tbl.relpages as heappages,
27843
- coalesce(toast.relpages, 0) as toastpages,
27844
- coalesce(toast.reltuples, 0) as toasttuples,
27845
- coalesce(substring(array_to_string(tbl.reloptions, ' ') from 'fillfactor=([0-9]+)')::smallint, 100) as fillfactor,
27846
- current_setting('block_size')::numeric as bs,
27847
- case when version() ~ 'mingw32' or version() ~ '64-bit|x86_64|ppc64|ia64|amd64' then 8 else 4 end as ma,
27848
- 24 as page_hdr,
27849
- 23 + case when max(coalesce(s.null_frac, 0)) > 0 then (7 + count(s.attname)) / 8 else 0::int end
27850
- + case when bool_or(att.attname = 'oid' and att.attnum < 0) then 4 else 0 end as tpl_hdr_size,
27851
- sum((1 - coalesce(s.null_frac, 0)) * coalesce(s.avg_width, 0)) as tpl_data_size,
27852
- (bool_or(att.atttypid = 'pg_catalog.name'::regtype)
27853
- or sum(case when att.attnum > 0 then 1 else 0 end) <> count(s.attname))::int as is_na
27854
- from pg_attribute as att
27855
- join pg_class as tbl on att.attrelid = tbl.oid
27856
- join pg_namespace as ns on ns.oid = tbl.relnamespace
27857
- left join pg_stats as s on s.schemaname = ns.nspname
27858
- and s.tablename = tbl.relname and s.attname = att.attname
27859
- left join pg_class as toast on tbl.reltoastrelid = toast.oid
27860
- where not att.attisdropped
27861
- and tbl.relkind in ('r', 'm')
27862
- and ns.nspname not in ('pg_catalog', 'information_schema', 'pg_toast')
27863
- group by ns.nspname, tbl.relname, tbl.reltuples, tbl.relpages, toast.relpages, toast.reltuples, tbl.reloptions
27864
- ) as s
27865
- ) as s2
27866
- ) as s3
27867
- where tblpages > 0 and (bs * tblpages) >= 1024 * 1024 -- exclude tables < 1 MiB
27868
- order by bloat_size_bytes desc
27869
- limit 100
27870
- `);
27871
- bloatData = result.rows;
27872
- } catch (err) {
27873
- const errorMsg = err instanceof Error ? err.message : String(err);
27874
- console.log(`[F004] Error estimating table bloat: ${errorMsg}`);
27875
- bloatError = errorMsg;
27876
- }
27877
- report.results[nodeName] = {
27878
- data: {
27879
- tables: bloatData,
27880
- ...bloatError && { error: bloatError }
27881
- },
27882
- postgres_version: postgresVersion
27883
- };
27884
- return report;
27885
- }
27886
- async function generateF005(client, nodeName) {
27887
- const report = createBaseReport("F005", "Autovacuum: index bloat estimate", nodeName);
27888
- const postgresVersion = await getPostgresVersion(client);
27889
- let bloatData = [];
27890
- let bloatError = null;
27891
- try {
27892
- const result = await client.query(`
27893
- select
27894
- nspname as schemaname,
27895
- tblname,
27896
- idxname,
27897
- (bs * relpages)::bigint as real_size_bytes,
27898
- pg_size_pretty((bs * relpages)::bigint) as real_size_pretty,
27899
- pg_relation_size(tbloid)::bigint as table_size_bytes,
27900
- pg_size_pretty(pg_relation_size(tbloid)) as table_size_pretty,
27901
- ((relpages - est_pages) * bs)::bigint as extra_size_bytes,
27902
- pg_size_pretty(((relpages - est_pages) * bs)::bigint) as extra_size_pretty,
27903
- round(100.0 * (relpages - est_pages) / relpages, 2) as extra_pct,
27904
- fillfactor,
27905
- case when relpages > est_pages_ff
27906
- then ((relpages - est_pages_ff) * bs)::bigint
27907
- else 0
27908
- end as bloat_size_bytes,
27909
- pg_size_pretty(case when relpages > est_pages_ff
27910
- then ((relpages - est_pages_ff) * bs)::bigint
27911
- else 0
27912
- end) as bloat_size_pretty,
27913
- case when relpages > est_pages_ff
27914
- then round(100.0 * (relpages - est_pages_ff) / relpages, 2)
27915
- else 0
27916
- end as bloat_pct,
27917
- is_na::text
27918
- from (
27919
- select
27920
- coalesce(1 + ceil(reltuples / floor((bs - pageopqdata - pagehdr) / (4 + nulldatahdrwidth)::float)), 0) as est_pages,
27921
- coalesce(1 + ceil(reltuples / floor((bs - pageopqdata - pagehdr) * fillfactor / (100 * (4 + nulldatahdrwidth)::float))), 0) as est_pages_ff,
27922
- bs, nspname, tblname, idxname, relpages, fillfactor, is_na, tbloid
27923
- from (
27924
- select
27925
- maxalign, bs, nspname, tblname, idxname, reltuples, relpages, idxoid, fillfactor, tbloid,
27926
- (index_tuple_hdr_bm + maxalign
27927
- - case when index_tuple_hdr_bm % maxalign = 0 then maxalign else index_tuple_hdr_bm % maxalign end
27928
- + nulldatawidth + maxalign
27929
- - case when nulldatawidth = 0 then 0
27930
- when nulldatawidth::integer % maxalign = 0 then maxalign
27931
- else nulldatawidth::integer % maxalign end
27932
- )::numeric as nulldatahdrwidth,
27933
- pagehdr, pageopqdata, is_na
27934
- from (
27935
- select
27936
- n.nspname, i.tblname, i.idxname, i.reltuples, i.relpages, i.tbloid, i.idxoid, i.fillfactor,
27937
- current_setting('block_size')::numeric as bs,
27938
- case when version() ~ 'mingw32' or version() ~ '64-bit|x86_64|ppc64|ia64|amd64' then 8 else 4 end as maxalign,
27939
- 24 as pagehdr,
27940
- 16 as pageopqdata,
27941
- case when max(coalesce(s.null_frac, 0)) = 0
27942
- then 8
27943
- else 8 + ((32 + 8 - 1) / 8)
27944
- end as index_tuple_hdr_bm,
27945
- sum((1 - coalesce(s.null_frac, 0)) * coalesce(s.avg_width, 1024)) as nulldatawidth,
27946
- (max(case when i.atttypid = 'pg_catalog.name'::regtype then 1 else 0 end) > 0)::int as is_na
27947
- from (
27948
- select
27949
- ct.relname as tblname, ct.relnamespace, ic.idxname, ic.attpos, ic.indkey,
27950
- ic.indkey[ic.attpos], ic.reltuples, ic.relpages, ic.tbloid, ic.idxoid, ic.fillfactor,
27951
- coalesce(a1.attnum, a2.attnum) as attnum,
27952
- coalesce(a1.attname, a2.attname) as attname,
27953
- coalesce(a1.atttypid, a2.atttypid) as atttypid,
27954
- case when a1.attnum is null then ic.idxname else ct.relname end as attrelname
27955
- from (
27956
- select
27957
- idxname, reltuples, relpages, tbloid, idxoid, fillfactor,
27958
- indkey, generate_subscripts(indkey, 1) as attpos
27959
- from (
27960
- select
27961
- ci.relname as idxname, ci.reltuples, ci.relpages, i.indrelid as tbloid,
27962
- i.indexrelid as idxoid,
27963
- coalesce(substring(array_to_string(ci.reloptions, ' ') from 'fillfactor=([0-9]+)')::smallint, 90) as fillfactor,
27964
- i.indkey
27965
- from pg_index as i
27966
- join pg_class as ci on ci.oid = i.indexrelid
27967
- join pg_namespace as ns on ns.oid = ci.relnamespace
27968
- join pg_am as am on am.oid = ci.relam
27969
- where am.amname = 'btree'
27970
- and ci.relpages > 0
27971
- and ns.nspname not in ('pg_catalog', 'information_schema', 'pg_toast')
27972
- ) as idx_data
27973
- ) as ic
27974
- join pg_class as ct on ct.oid = ic.tbloid
27975
- left join pg_attribute as a1 on a1.attrelid = ic.idxoid and a1.attnum = ic.indkey[ic.attpos]
27976
- left join pg_attribute as a2 on a2.attrelid = ic.tbloid and a2.attnum = ic.indkey[ic.attpos]
27977
- ) as i
27978
- join pg_namespace as n on n.oid = i.relnamespace
27979
- left join pg_stats as s on s.schemaname = n.nspname
27980
- and s.tablename = i.attrelname and s.attname = i.attname
27981
- group by n.nspname, i.tblname, i.idxname, i.reltuples, i.relpages, i.tbloid, i.idxoid, i.fillfactor
27982
- ) as rows_data_stats
27983
- ) as rows_hdr_pdg_stats
27984
- ) as relation_stats
27985
- where relpages > 0 and (bs * relpages) >= 1024 * 1024 -- exclude indexes < 1 MiB
27986
- order by bloat_size_bytes desc
27987
- limit 100
27988
- `);
27989
- bloatData = result.rows;
27990
- } catch (err) {
27991
- const errorMsg = err instanceof Error ? err.message : String(err);
27992
- console.log(`[F005] Error estimating index bloat: ${errorMsg}`);
27993
- bloatError = errorMsg;
27994
- }
27995
- report.results[nodeName] = {
27996
- data: {
27997
- indexes: bloatData,
27998
- ...bloatError && { error: bloatError }
27999
- },
28000
- postgres_version: postgresVersion
28001
- };
28002
- return report;
28003
- }
28004
27795
  async function generateG001(client, nodeName) {
28005
27796
  const report = createBaseReport("G001", "Memory-related settings", nodeName);
28006
27797
  const postgresVersion = await getPostgresVersion(client);
@@ -28151,8 +27942,6 @@ var REPORT_GENERATORS = {
28151
27942
  D001: generateD001,
28152
27943
  D004: generateD004,
28153
27944
  F001: generateF001,
28154
- F004: generateF004,
28155
- F005: generateF005,
28156
27945
  G001: generateG001,
28157
27946
  G003: generateG003,
28158
27947
  H001: generateH001,
@@ -29698,7 +29487,7 @@ program2.command("unprepare-db [conn]").description("remove monitoring setup: dr
29698
29487
  closeReadline();
29699
29488
  }
29700
29489
  });
29701
- program2.command("checkup [conn]").description("generate health check reports directly from PostgreSQL (express mode)").option("--check-id <id>", `specific check to run (see list below), or ALL`, "ALL").option("--node-name <name>", "node name for reports", "node-01").option("--output <path>", "output directory for JSON files").option("--[no-]upload", "upload JSON results to PostgresAI (default: enabled; requires API key)", undefined).option("--project <project>", "project name or ID for remote upload (used with --upload; defaults to config defaultProject; auto-generated on first run)").option("--json", "output JSON to stdout (implies --no-upload)").addHelpText("after", [
29490
+ program2.command("checkup [conn]").description("generate health check reports directly from PostgreSQL (express mode)").option("--check-id <id>", `specific check to run (see list below), or ALL`, "ALL").option("--node-name <name>", "node name for reports", "node-01").option("--output <path>", "output directory for JSON files").option("--upload", "upload JSON results to PostgresAI (requires API key)").option("--no-upload", "disable upload to PostgresAI").option("--project <project>", "project name or ID for remote upload (used with --upload; defaults to config defaultProject; auto-generated on first run)").option("--json", "output JSON to stdout").addHelpText("after", [
29702
29491
  "",
29703
29492
  "Available checks:",
29704
29493
  ...Object.entries(CHECK_INFO).map(([id, title]) => ` ${id}: ${title}`),
@@ -29718,7 +29507,7 @@ program2.command("checkup [conn]").description("generate health check reports di
29718
29507
  }
29719
29508
  const shouldPrintJson = !!opts.json;
29720
29509
  const uploadExplicitlyRequested = opts.upload === true;
29721
- const uploadExplicitlyDisabled = opts.upload === false || shouldPrintJson;
29510
+ const uploadExplicitlyDisabled = opts.upload === false;
29722
29511
  let shouldUpload = !uploadExplicitlyDisabled;
29723
29512
  const outputPath = prepareOutputDirectory(opts.output);
29724
29513
  if (outputPath === null) {