postgresai 0.16.0-rc.4 → 0.16.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 (85) hide show
  1. package/README.md +154 -0
  2. package/dist/bin/postgres-ai.js +2911 -255
  3. package/package.json +12 -3
  4. package/schemas/A002.schema.json +63 -0
  5. package/schemas/A003.schema.json +73 -0
  6. package/schemas/A004.schema.json +81 -0
  7. package/schemas/A007.schema.json +71 -0
  8. package/schemas/A013.schema.json +61 -0
  9. package/schemas/D001.schema.json +71 -0
  10. package/schemas/D004.schema.json +136 -0
  11. package/schemas/F001.schema.json +73 -0
  12. package/schemas/F002.schema.json +108 -0
  13. package/schemas/F003.schema.json +138 -0
  14. package/schemas/F004.schema.json +125 -0
  15. package/schemas/F005.schema.json +131 -0
  16. package/schemas/F009.schema.json +155 -0
  17. package/schemas/G001.schema.json +135 -0
  18. package/schemas/G003.schema.json +90 -0
  19. package/schemas/H001.schema.json +141 -0
  20. package/schemas/H002.schema.json +129 -0
  21. package/schemas/H004.schema.json +128 -0
  22. package/schemas/I001.schema.json +149 -0
  23. package/schemas/K001.schema.json +161 -0
  24. package/schemas/K003.schema.json +163 -0
  25. package/schemas/K004.schema.json +110 -0
  26. package/schemas/K005.schema.json +110 -0
  27. package/schemas/K006.schema.json +110 -0
  28. package/schemas/K007.schema.json +110 -0
  29. package/schemas/K008.schema.json +110 -0
  30. package/schemas/M001.schema.json +119 -0
  31. package/schemas/M002.schema.json +110 -0
  32. package/schemas/M003.schema.json +128 -0
  33. package/schemas/N001.schema.json +161 -0
  34. package/schemas/query.schema.json +62 -0
  35. package/CHANGELOG.md +0 -11
  36. package/bin/postgres-ai.ts +0 -5578
  37. package/bun.lock +0 -258
  38. package/bunfig.toml +0 -20
  39. package/lib/aas-onboard.ts +0 -251
  40. package/lib/auth-server.ts +0 -285
  41. package/lib/checkup-api.ts +0 -526
  42. package/lib/checkup-dictionary.ts +0 -103
  43. package/lib/checkup-summary.ts +0 -338
  44. package/lib/checkup.ts +0 -2261
  45. package/lib/config.ts +0 -171
  46. package/lib/init.ts +0 -1152
  47. package/lib/instances.ts +0 -245
  48. package/lib/issues.ts +0 -1060
  49. package/lib/mcp-server.ts +0 -667
  50. package/lib/metrics-loader.ts +0 -134
  51. package/lib/pkce.ts +0 -79
  52. package/lib/reports.ts +0 -373
  53. package/lib/storage.ts +0 -367
  54. package/lib/supabase.ts +0 -826
  55. package/lib/util.ts +0 -134
  56. package/packages/postgres-ai/README.md +0 -26
  57. package/packages/postgres-ai/bin/postgres-ai.js +0 -27
  58. package/packages/postgres-ai/package.json +0 -27
  59. package/scripts/embed-checkup-dictionary.ts +0 -115
  60. package/scripts/embed-metrics.ts +0 -160
  61. package/scripts/generate-release-notes.ts +0 -668
  62. package/test/PERMISSION_CHECK_TEST_SUMMARY.md +0 -139
  63. package/test/aas-onboard.test.ts +0 -301
  64. package/test/auth.test.ts +0 -287
  65. package/test/checkup.integration.test.ts +0 -413
  66. package/test/checkup.test.ts +0 -3626
  67. package/test/compose-cmd.test.ts +0 -120
  68. package/test/config-consistency.test.ts +0 -352
  69. package/test/init.integration.test.ts +0 -438
  70. package/test/init.test.ts +0 -1816
  71. package/test/issues.cli.test.ts +0 -1162
  72. package/test/issues.test.ts +0 -456
  73. package/test/mcp-server.test.ts +0 -2530
  74. package/test/monitoring.test.ts +0 -746
  75. package/test/permission-check-sql.test.ts +0 -116
  76. package/test/reports.cli.test.ts +0 -793
  77. package/test/reports.test.ts +0 -977
  78. package/test/schema-validation.test.ts +0 -231
  79. package/test/storage.test.ts +0 -935
  80. package/test/supabase.test.ts +0 -709
  81. package/test/targets-add-config.test.ts +0 -28
  82. package/test/test-utils.ts +0 -190
  83. package/test/upgrade.test.ts +0 -1056
  84. package/test/util.test.ts +0 -44
  85. package/tsconfig.json +0 -20
@@ -1,28 +0,0 @@
1
- import { describe, expect, test } from "bun:test";
2
- import { readFileSync } from "fs";
3
- import { resolve } from "path";
4
-
5
- const cliSource = readFileSync(resolve(import.meta.dir, "../bin/postgres-ai.ts"), "utf8");
6
-
7
- describe("mon targets configuration apply", () => {
8
- test("targets add regenerates sources and restarts pgwatch collectors after saving", () => {
9
- expect(cliSource).toContain("async function applyMonitoringTargetsConfig()");
10
- expect(cliSource).toContain('runCompose(["run", "--rm", "sources-generator"])');
11
- expect(cliSource).toContain(
12
- 'runCompose(["up", "-d", "--force-recreate", "pgwatch-prometheus", "pgwatch-postgres"])'
13
- );
14
-
15
- const saveIndex = cliSource.indexOf("addInstanceToFile(file, buildInstance(instanceName, connStr))");
16
- const applyIndex = cliSource.indexOf("await applyMonitoringTargetsConfig()", saveIndex);
17
- expect(saveIndex).toBeGreaterThan(-1);
18
- expect(applyIndex).toBeGreaterThan(saveIndex);
19
- });
20
-
21
- test("targets remove regenerates sources and restarts pgwatch collectors after saving", () => {
22
- const removeIndex = cliSource.indexOf("removeInstanceFromFile(file, name)");
23
- const applyIndex = cliSource.indexOf("await applyMonitoringTargetsConfig()", removeIndex);
24
- expect(removeIndex).toBeGreaterThan(-1);
25
- expect(applyIndex).toBeGreaterThan(-1);
26
- expect(applyIndex).toBeGreaterThan(removeIndex);
27
- });
28
- });
@@ -1,190 +0,0 @@
1
- /**
2
- * Shared test utilities for CLI tests.
3
- */
4
-
5
- export interface MockClientOptions {
6
- /** Database name returned by current_database() queries (default: "testdb") */
7
- databaseName?: string;
8
- /** Version rows for pg_settings version query (default: PG 16.3) */
9
- versionRows?: any[];
10
- settingsRows?: any[];
11
- databaseSizesRows?: any[];
12
- dbStatsRows?: any[];
13
- connectionStatesRows?: any[];
14
- uptimeRows?: any[];
15
- invalidIndexesRows?: any[];
16
- unusedIndexesRows?: any[];
17
- redundantIndexesRows?: any[];
18
- tableBloatRows?: any[];
19
- indexBloatRows?: any[];
20
- deadTuplesRows?: any[];
21
- vacuumStatsRows?: any[];
22
- bloatCapabilityRows?: any[];
23
- deadlockStatsRows?: any[];
24
- pgStatStatementsExtensionRows?: any[];
25
- pgStatStatementsStatsRows?: any[];
26
- pgStatStatementsSampleRows?: any[];
27
- pgStatKcacheExtensionRows?: any[];
28
- pgStatKcacheStatsRows?: any[];
29
- pgStatKcacheSampleRows?: any[];
30
- sensitiveColumnsRows?: any[];
31
- }
32
-
33
- const DEFAULT_VERSION_ROWS = [
34
- { name: "server_version", setting: "16.3" },
35
- { name: "server_version_num", setting: "160003" },
36
- ];
37
-
38
- const defaultSettingsRows = [
39
- { tag_setting_name: "shared_buffers", tag_setting_value: "128MB", tag_unit: "", tag_category: "Resource Usage / Memory", tag_vartype: "string", is_default: 1, setting_normalized: null, unit_normalized: null },
40
- { tag_setting_name: "work_mem", tag_setting_value: "4MB", tag_unit: "", tag_category: "Resource Usage / Memory", tag_vartype: "string", is_default: 1, setting_normalized: null, unit_normalized: null },
41
- { tag_setting_name: "autovacuum", tag_setting_value: "on", tag_unit: "", tag_category: "Autovacuum", tag_vartype: "bool", is_default: 1, setting_normalized: null, unit_normalized: null },
42
- { tag_setting_name: "pg_stat_statements.max", tag_setting_value: "5000", tag_unit: "", tag_category: "Custom", tag_vartype: "integer", is_default: 0, setting_normalized: null, unit_normalized: null },
43
- ];
44
-
45
- /**
46
- * Create a mock PostgreSQL client for testing report generators.
47
- * Routes SQL queries to appropriate mock data based on query patterns.
48
- */
49
- export function createMockClient(options: MockClientOptions = {}) {
50
- const {
51
- databaseName = "testdb",
52
- versionRows = DEFAULT_VERSION_ROWS,
53
- settingsRows = defaultSettingsRows,
54
- databaseSizesRows = [],
55
- dbStatsRows = [],
56
- connectionStatesRows = [],
57
- uptimeRows = [],
58
- invalidIndexesRows = [],
59
- unusedIndexesRows = [],
60
- redundantIndexesRows = [],
61
- tableBloatRows = [],
62
- indexBloatRows = [],
63
- deadTuplesRows = [],
64
- vacuumStatsRows = [],
65
- bloatCapabilityRows = [{ schema_exists: true, schema_usage: true, view_exists: true, view_select: true }],
66
- deadlockStatsRows = [{ deadlocks: "0", conflicts: "0", stats_reset: null }],
67
- pgStatStatementsExtensionRows = [],
68
- pgStatStatementsStatsRows = [],
69
- pgStatStatementsSampleRows = [],
70
- pgStatKcacheExtensionRows = [],
71
- pgStatKcacheStatsRows = [],
72
- pgStatKcacheSampleRows = [],
73
- sensitiveColumnsRows = [],
74
- } = options;
75
-
76
- return {
77
- query: async (sql: string) => {
78
- // Version query (simple inline - used by getPostgresVersion)
79
- if (sql.includes("server_version") && sql.includes("server_version_num") && sql.includes("pg_settings") && !sql.includes("tag_setting_name")) {
80
- return { rows: versionRows };
81
- }
82
- // Settings metric query (from metrics.yml - has tag_setting_name, tag_setting_value)
83
- if (sql.includes("tag_setting_name") && sql.includes("tag_setting_value") && sql.includes("pg_settings")) {
84
- return { rows: settingsRows };
85
- }
86
- // Database sizes (simple inline - lists all databases)
87
- if (sql.includes("pg_database") && sql.includes("pg_database_size") && sql.includes("datistemplate")) {
88
- return { rows: databaseSizesRows };
89
- }
90
- // db_size metric (current database size from metrics.yml)
91
- if (sql.includes("pg_database_size(current_database())") && sql.includes("size_b")) {
92
- return { rows: [{ tag_datname: databaseName, size_b: "1073741824" }] };
93
- }
94
- // db_stats metric (from metrics.yml)
95
- if (sql.includes("pg_stat_database") && sql.includes("xact_commit") && sql.includes("pg_control_system")) {
96
- return { rows: dbStatsRows };
97
- }
98
- // Stats reset metric (from metrics.yml)
99
- if (sql.includes("stats_reset") && sql.includes("pg_stat_database") && sql.includes("seconds_since_reset")) {
100
- return { rows: [{ tag_database_name: databaseName, stats_reset_epoch: "1704067200", seconds_since_reset: "2592000" }] };
101
- }
102
- // Postmaster startup time (simple inline - used by getStatsReset)
103
- if (sql.includes("pg_postmaster_start_time") && sql.includes("postmaster_startup_epoch")) {
104
- return { rows: [{ postmaster_startup_epoch: "1704067200", postmaster_startup_time: "2024-01-01 00:00:00+00" }] };
105
- }
106
- // Connection states (simple inline)
107
- if (sql.includes("pg_stat_activity") && sql.includes("state") && sql.includes("group by")) {
108
- return { rows: connectionStatesRows };
109
- }
110
- // Uptime info (simple inline)
111
- if (sql.includes("pg_postmaster_start_time()") && sql.includes("uptime") && !sql.includes("postmaster_startup_epoch")) {
112
- return { rows: uptimeRows };
113
- }
114
- // Invalid indexes (H001) - from metrics.yml
115
- if (sql.includes("indisvalid = false") && sql.includes("fk_indexes")) {
116
- return { rows: invalidIndexesRows };
117
- }
118
- // Unused indexes (H002) - from metrics.yml
119
- if (sql.includes("Never Used Indexes") && sql.includes("idx_scan = 0")) {
120
- return { rows: unusedIndexesRows };
121
- }
122
- // Redundant indexes (H004) - from metrics.yml
123
- if (sql.includes("redundant_indexes_grouped") && sql.includes("columns like")) {
124
- return { rows: redundantIndexesRows };
125
- }
126
- // F003: dead tuples metric from metrics.yml.
127
- // Must be matched BEFORE the F004/F005 vacuum-stats route below: the
128
- // pg_dead_tuples SQL also contains "pg_stat_user_tables" and "last_vacuum".
129
- if (sql.includes("autovacuum_disabled") && sql.includes("n_dead_tup")) {
130
- return { rows: deadTuplesRows };
131
- }
132
- // F004/F005: bloat metrics from metrics.yml
133
- if (sql.includes("to_regnamespace('postgres_ai')") && sql.includes("view_select")) {
134
- return { rows: bloatCapabilityRows };
135
- }
136
- if (sql.includes("tag_idxname") && sql.includes("bloat_size")) {
137
- return { rows: indexBloatRows };
138
- }
139
- if (sql.includes("tag_tblname") && sql.includes("bloat_size")) {
140
- return { rows: tableBloatRows };
141
- }
142
- // Vacuum stats used by F004/F005
143
- if (sql.includes("pg_stat_user_tables") && sql.includes("last_vacuum")) {
144
- return { rows: vacuumStatsRows };
145
- }
146
- // G003: Deadlock/conflict stats
147
- if (sql.includes("coalesce(sum(deadlocks)") && sql.includes("current_database()")) {
148
- return { rows: deadlockStatsRows };
149
- }
150
- // D004: pg_stat_statements extension check
151
- if (sql.includes("pg_extension") && sql.includes("pg_stat_statements")) {
152
- return { rows: pgStatStatementsExtensionRows };
153
- }
154
- // D004: pg_stat_statements aggregate and sample queries
155
- if (sql.includes("from pg_stat_statements") && sql.includes("count(*) as cnt")) {
156
- return { rows: pgStatStatementsStatsRows };
157
- }
158
- if (sql.includes("from pg_stat_statements s") && sql.includes("order by calls desc")) {
159
- return { rows: pgStatStatementsSampleRows };
160
- }
161
- // D004: pg_stat_kcache extension check
162
- if (sql.includes("pg_extension") && sql.includes("pg_stat_kcache")) {
163
- return { rows: pgStatKcacheExtensionRows };
164
- }
165
- // D004: pg_stat_kcache aggregate and sample queries
166
- if (sql.includes("from pg_stat_kcache") && sql.includes("count(*) as cnt")) {
167
- return { rows: pgStatKcacheStatsRows };
168
- }
169
- if (sql.includes("from pg_stat_kcache k") && sql.includes("order by")) {
170
- return { rows: pgStatKcacheSampleRows };
171
- }
172
- // G001: Memory settings query
173
- if (sql.includes("pg_size_bytes") && sql.includes("shared_buffers") && sql.includes("work_mem")) {
174
- return { rows: [{
175
- shared_buffers_bytes: "134217728",
176
- wal_buffers_bytes: "4194304",
177
- work_mem_bytes: "4194304",
178
- maintenance_work_mem_bytes: "67108864",
179
- effective_cache_size_bytes: "4294967296",
180
- max_connections: 100,
181
- }] };
182
- }
183
- // S001: Sensitive columns query (from metrics.yml)
184
- if (sql.includes("information_schema.columns") && sql.includes("tag_schema_name") && sql.includes("tag_column_name")) {
185
- return { rows: sensitiveColumnsRows };
186
- }
187
- throw new Error(`Unexpected query: ${sql}`);
188
- },
189
- };
190
- }