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.
- package/README.md +154 -0
- package/dist/bin/postgres-ai.js +2911 -255
- package/package.json +12 -3
- package/schemas/A002.schema.json +63 -0
- package/schemas/A003.schema.json +73 -0
- package/schemas/A004.schema.json +81 -0
- package/schemas/A007.schema.json +71 -0
- package/schemas/A013.schema.json +61 -0
- package/schemas/D001.schema.json +71 -0
- package/schemas/D004.schema.json +136 -0
- package/schemas/F001.schema.json +73 -0
- package/schemas/F002.schema.json +108 -0
- package/schemas/F003.schema.json +138 -0
- package/schemas/F004.schema.json +125 -0
- package/schemas/F005.schema.json +131 -0
- package/schemas/F009.schema.json +155 -0
- package/schemas/G001.schema.json +135 -0
- package/schemas/G003.schema.json +90 -0
- package/schemas/H001.schema.json +141 -0
- package/schemas/H002.schema.json +129 -0
- package/schemas/H004.schema.json +128 -0
- package/schemas/I001.schema.json +149 -0
- package/schemas/K001.schema.json +161 -0
- package/schemas/K003.schema.json +163 -0
- package/schemas/K004.schema.json +110 -0
- package/schemas/K005.schema.json +110 -0
- package/schemas/K006.schema.json +110 -0
- package/schemas/K007.schema.json +110 -0
- package/schemas/K008.schema.json +110 -0
- package/schemas/M001.schema.json +119 -0
- package/schemas/M002.schema.json +110 -0
- package/schemas/M003.schema.json +128 -0
- package/schemas/N001.schema.json +161 -0
- package/schemas/query.schema.json +62 -0
- package/CHANGELOG.md +0 -11
- package/bin/postgres-ai.ts +0 -5578
- package/bun.lock +0 -258
- package/bunfig.toml +0 -20
- package/lib/aas-onboard.ts +0 -251
- package/lib/auth-server.ts +0 -285
- package/lib/checkup-api.ts +0 -526
- package/lib/checkup-dictionary.ts +0 -103
- package/lib/checkup-summary.ts +0 -338
- package/lib/checkup.ts +0 -2261
- package/lib/config.ts +0 -171
- package/lib/init.ts +0 -1152
- package/lib/instances.ts +0 -245
- package/lib/issues.ts +0 -1060
- package/lib/mcp-server.ts +0 -667
- package/lib/metrics-loader.ts +0 -134
- package/lib/pkce.ts +0 -79
- package/lib/reports.ts +0 -373
- package/lib/storage.ts +0 -367
- package/lib/supabase.ts +0 -826
- package/lib/util.ts +0 -134
- package/packages/postgres-ai/README.md +0 -26
- package/packages/postgres-ai/bin/postgres-ai.js +0 -27
- package/packages/postgres-ai/package.json +0 -27
- package/scripts/embed-checkup-dictionary.ts +0 -115
- package/scripts/embed-metrics.ts +0 -160
- package/scripts/generate-release-notes.ts +0 -668
- package/test/PERMISSION_CHECK_TEST_SUMMARY.md +0 -139
- package/test/aas-onboard.test.ts +0 -301
- package/test/auth.test.ts +0 -287
- package/test/checkup.integration.test.ts +0 -413
- package/test/checkup.test.ts +0 -3626
- package/test/compose-cmd.test.ts +0 -120
- package/test/config-consistency.test.ts +0 -352
- package/test/init.integration.test.ts +0 -438
- package/test/init.test.ts +0 -1816
- package/test/issues.cli.test.ts +0 -1162
- package/test/issues.test.ts +0 -456
- package/test/mcp-server.test.ts +0 -2530
- package/test/monitoring.test.ts +0 -746
- package/test/permission-check-sql.test.ts +0 -116
- package/test/reports.cli.test.ts +0 -793
- package/test/reports.test.ts +0 -977
- package/test/schema-validation.test.ts +0 -231
- package/test/storage.test.ts +0 -935
- package/test/supabase.test.ts +0 -709
- package/test/targets-add-config.test.ts +0 -28
- package/test/test-utils.ts +0 -190
- package/test/upgrade.test.ts +0 -1056
- package/test/util.test.ts +0 -44
- 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
|
-
});
|
package/test/test-utils.ts
DELETED
|
@@ -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
|
-
}
|