@kozou/introspect 0.1.0 → 0.2.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/dist/filter.d.ts +10 -0
- package/dist/filter.d.ts.map +1 -0
- package/dist/filter.js +94 -0
- package/dist/filter.js.map +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +8 -6
- package/dist/index.js.map +1 -1
- package/dist/tables.d.ts.map +1 -1
- package/dist/tables.js +16 -2
- package/dist/tables.js.map +1 -1
- package/package.json +5 -4
package/dist/filter.d.ts
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { RawTable, RawView } from '@kozou/core';
|
|
2
|
+
export type FilterOptions = {
|
|
3
|
+
include?: readonly string[];
|
|
4
|
+
exclude?: readonly string[];
|
|
5
|
+
};
|
|
6
|
+
export declare function shouldRetain(qualified: string, includeRes: readonly RegExp[], excludeRes: readonly RegExp[]): boolean;
|
|
7
|
+
export declare function filterTables(tables: readonly RawTable[], opts: FilterOptions): RawTable[];
|
|
8
|
+
export declare function filterViews(views: readonly RawView[], opts: FilterOptions): RawView[];
|
|
9
|
+
export declare function pruneDanglingForeignKeys(tables: RawTable[]): void;
|
|
10
|
+
//# sourceMappingURL=filter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"filter.d.ts","sourceRoot":"","sources":["../src/filter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAiB,QAAQ,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AA2CpE,MAAM,MAAM,aAAa,GAAG;IAC1B,OAAO,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAC5B,OAAO,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CAC7B,CAAC;AASF,wBAAgB,YAAY,CAC1B,SAAS,EAAE,MAAM,EACjB,UAAU,EAAE,SAAS,MAAM,EAAE,EAC7B,UAAU,EAAE,SAAS,MAAM,EAAE,GAC5B,OAAO,CAQT;AAED,wBAAgB,YAAY,CAC1B,MAAM,EAAE,SAAS,QAAQ,EAAE,EAC3B,IAAI,EAAE,aAAa,GAClB,QAAQ,EAAE,CASZ;AAED,wBAAgB,WAAW,CACzB,KAAK,EAAE,SAAS,OAAO,EAAE,EACzB,IAAI,EAAE,aAAa,GAClB,OAAO,EAAE,CASX;AAMD,wBAAgB,wBAAwB,CAAC,MAAM,EAAE,QAAQ,EAAE,GAAG,IAAI,CAWjE"}
|
package/dist/filter.js
ADDED
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
// Convert one user-facing glob into a RegExp that matches a fully
|
|
2
|
+
// qualified `schema.name` string.
|
|
3
|
+
//
|
|
4
|
+
// - Supported wildcards: `*` (zero or more chars except `.`) and `?`
|
|
5
|
+
// (exactly one char except `.`). All other regex metacharacters are
|
|
6
|
+
// escaped, so callers can safely use names containing `+`, `(`, etc.
|
|
7
|
+
// - A pattern without a `.` is treated as `*.<pattern>` so users can
|
|
8
|
+
// write `users` to mean "the `users` table in any schema".
|
|
9
|
+
// - `*` does not cross schema boundaries: `*.users` matches
|
|
10
|
+
// `public.users` but not `public.audit.users` (which is not a valid
|
|
11
|
+
// PostgreSQL identifier anyway, but the constraint keeps the
|
|
12
|
+
// semantics predictable).
|
|
13
|
+
function compilePattern(pattern) {
|
|
14
|
+
const qualified = pattern.includes('.') ? pattern : `*.${pattern}`;
|
|
15
|
+
let body = '';
|
|
16
|
+
for (const ch of qualified) {
|
|
17
|
+
if (ch === '*') {
|
|
18
|
+
body += '[^.]*';
|
|
19
|
+
}
|
|
20
|
+
else if (ch === '?') {
|
|
21
|
+
body += '[^.]';
|
|
22
|
+
}
|
|
23
|
+
else if (/[.+^${}()|[\]\\]/.test(ch)) {
|
|
24
|
+
body += `\\${ch}`;
|
|
25
|
+
}
|
|
26
|
+
else {
|
|
27
|
+
body += ch;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
return new RegExp(`^${body}$`);
|
|
31
|
+
}
|
|
32
|
+
function compilePatterns(patterns) {
|
|
33
|
+
if (!patterns || patterns.length === 0)
|
|
34
|
+
return [];
|
|
35
|
+
return patterns.map(compilePattern);
|
|
36
|
+
}
|
|
37
|
+
function matchesAny(qualified, regexes) {
|
|
38
|
+
for (const re of regexes) {
|
|
39
|
+
if (re.test(qualified))
|
|
40
|
+
return true;
|
|
41
|
+
}
|
|
42
|
+
return false;
|
|
43
|
+
}
|
|
44
|
+
// Returns true if `qualified` should be retained given the filter.
|
|
45
|
+
// Semantics:
|
|
46
|
+
// - If `include` is non-empty, the name must match at least one include
|
|
47
|
+
// pattern.
|
|
48
|
+
// - If `exclude` is non-empty, the name must not match any exclude
|
|
49
|
+
// pattern.
|
|
50
|
+
// - Both lists can be combined; exclude wins over include on conflict.
|
|
51
|
+
export function shouldRetain(qualified, includeRes, excludeRes) {
|
|
52
|
+
if (includeRes.length > 0 && !matchesAny(qualified, includeRes)) {
|
|
53
|
+
return false;
|
|
54
|
+
}
|
|
55
|
+
if (excludeRes.length > 0 && matchesAny(qualified, excludeRes)) {
|
|
56
|
+
return false;
|
|
57
|
+
}
|
|
58
|
+
return true;
|
|
59
|
+
}
|
|
60
|
+
export function filterTables(tables, opts) {
|
|
61
|
+
const includeRes = compilePatterns(opts.include);
|
|
62
|
+
const excludeRes = compilePatterns(opts.exclude);
|
|
63
|
+
if (includeRes.length === 0 && excludeRes.length === 0) {
|
|
64
|
+
return [...tables];
|
|
65
|
+
}
|
|
66
|
+
return tables.filter((t) => shouldRetain(`${t.schema}.${t.name}`, includeRes, excludeRes));
|
|
67
|
+
}
|
|
68
|
+
export function filterViews(views, opts) {
|
|
69
|
+
const includeRes = compilePatterns(opts.include);
|
|
70
|
+
const excludeRes = compilePatterns(opts.exclude);
|
|
71
|
+
if (includeRes.length === 0 && excludeRes.length === 0) {
|
|
72
|
+
return [...views];
|
|
73
|
+
}
|
|
74
|
+
return views.filter((v) => shouldRetain(`${v.schema}.${v.name}`, includeRes, excludeRes));
|
|
75
|
+
}
|
|
76
|
+
// When a table is filtered out, any FK that points to it becomes a
|
|
77
|
+
// dangling reference. Drop those FKs so downstream consumers (graph
|
|
78
|
+
// builder in @kozou/core, MCP responses) never have to handle
|
|
79
|
+
// references to tables that aren't in `tables`.
|
|
80
|
+
export function pruneDanglingForeignKeys(tables) {
|
|
81
|
+
const present = new Set();
|
|
82
|
+
for (const t of tables)
|
|
83
|
+
present.add(`${t.schema}.${t.name}`);
|
|
84
|
+
for (const t of tables) {
|
|
85
|
+
const kept = [];
|
|
86
|
+
for (const fk of t.foreignKeys) {
|
|
87
|
+
const target = `${fk.referencedSchema}.${fk.referencedTable}`;
|
|
88
|
+
if (present.has(target))
|
|
89
|
+
kept.push(fk);
|
|
90
|
+
}
|
|
91
|
+
t.foreignKeys = kept;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
//# sourceMappingURL=filter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"filter.js","sourceRoot":"","sources":["../src/filter.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAU,YAAY,EAAE,MAAM,IAAI,CAAC;AAC/C,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAMpD,OAAO,EAAE,oBAAoB,EAAY,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAU,YAAY,EAAE,MAAM,IAAI,CAAC;AAC/C,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAMpD,OAAO,EAAE,oBAAoB,EAAY,MAAM,aAAa,CAAC;AAK7D,MAAM,MAAM,iBAAiB,GAAG;IAC9B,UAAU,EAAE,MAAM,GAAG,YAAY,CAAC;IAClC,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,CAAC;AAEF,OAAO,EAAE,oBAAoB,EAAE,CAAC;AAChC,YAAY,EAAE,2BAA2B,EAAE,MAAM,aAAa,CAAC;AAkB/D,wBAAsB,UAAU,CAAC,IAAI,EAAE,iBAAiB,GAAG,OAAO,CAAC,gBAAgB,CAAC,CA4EnF"}
|
package/dist/index.js
CHANGED
|
@@ -5,6 +5,7 @@ import { fetchChecks } from './checks.js';
|
|
|
5
5
|
import { fetchViews } from './views.js';
|
|
6
6
|
import { fetchEnums } from './enums.js';
|
|
7
7
|
import { KozouIntrospectError, runQuery } from './errors.js';
|
|
8
|
+
import { filterTables, filterViews, pruneDanglingForeignKeys } from './filter.js';
|
|
8
9
|
const PgClient = pkg.Client;
|
|
9
10
|
export { KozouIntrospectError };
|
|
10
11
|
function isPgErrorLike(value) {
|
|
@@ -17,9 +18,6 @@ async function fetchExistingSchemas(client, schemas) {
|
|
|
17
18
|
export async function introspect(opts) {
|
|
18
19
|
const schemas = opts.schemas ?? ['public'];
|
|
19
20
|
const timeoutMs = opts.timeoutMs ?? 10_000;
|
|
20
|
-
if (opts.include?.length || opts.exclude?.length) {
|
|
21
|
-
console.warn('[@kozou/introspect] opts.include / opts.exclude are not implemented in v0.1 (warning only)');
|
|
22
|
-
}
|
|
23
21
|
const baseConfig = typeof opts.connection === 'string'
|
|
24
22
|
? { connectionString: opts.connection }
|
|
25
23
|
: { ...opts.connection };
|
|
@@ -44,12 +42,16 @@ export async function introspect(opts) {
|
|
|
44
42
|
}
|
|
45
43
|
}
|
|
46
44
|
const validSchemas = schemas.filter((s) => existing.includes(s));
|
|
47
|
-
const
|
|
45
|
+
const allTables = await fetchTables(client, validSchemas);
|
|
48
46
|
const fks = await fetchForeignKeys(client, validSchemas);
|
|
49
47
|
const checks = await fetchChecks(client, validSchemas);
|
|
50
|
-
mergeTableMetadata(
|
|
51
|
-
const
|
|
48
|
+
mergeTableMetadata(allTables, fks, checks);
|
|
49
|
+
const allViews = await fetchViews(client, validSchemas);
|
|
52
50
|
const enums = await fetchEnums(client, validSchemas);
|
|
51
|
+
const filterOpts = { include: opts.include, exclude: opts.exclude };
|
|
52
|
+
const tables = filterTables(allTables, filterOpts);
|
|
53
|
+
pruneDanglingForeignKeys(tables);
|
|
54
|
+
const views = filterViews(allViews, filterOpts);
|
|
53
55
|
return {
|
|
54
56
|
serverVersion,
|
|
55
57
|
introspectedAt: new Date().toISOString(),
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,GAAG,MAAM,IAAI,CAAC;AAGrB,OAAO,EAAE,WAAW,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AAC9D,OAAO,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAC;AAC5C,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AACxC,OAAO,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AACxC,OAAO,EAAE,oBAAoB,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/tables.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tables.d.ts","sourceRoot":"","sources":["../src/tables.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,IAAI,CAAC;AACjC,OAAO,KAAK,EAAE,QAAQ,EAAa,aAAa,EAAY,QAAQ,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"tables.d.ts","sourceRoot":"","sources":["../src/tables.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,IAAI,CAAC;AACjC,OAAO,KAAK,EAAE,QAAQ,EAAa,aAAa,EAAY,QAAQ,EAAE,MAAM,aAAa,CAAC;AAqC1F,wBAAsB,WAAW,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,QAAQ,EAAE,CAAC,CA6JxF;AAED,wBAAgB,kBAAkB,CAChC,MAAM,EAAE,QAAQ,EAAE,EAClB,GAAG,EAAE,GAAG,CAAC,MAAM,EAAE,aAAa,EAAE,CAAC,EACjC,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,QAAQ,EAAE,CAAC,GAC9B,IAAI,CAMN"}
|
package/dist/tables.js
CHANGED
|
@@ -2,10 +2,17 @@ import { runQuery } from './errors.js';
|
|
|
2
2
|
export async function fetchTables(client, schemas) {
|
|
3
3
|
if (schemas.length === 0)
|
|
4
4
|
return [];
|
|
5
|
-
const tableRows = await runQuery(client,
|
|
5
|
+
const tableRows = await runQuery(client,
|
|
6
|
+
// `c.reltuples` is the planner's row-count estimate, maintained by
|
|
7
|
+
// ANALYZE / autovacuum. PostgreSQL uses -1 to mark "never
|
|
8
|
+
// analyzed", which we surface as null so downstream consumers
|
|
9
|
+
// always see "non-negative count or unknown" instead of mixing the
|
|
10
|
+
// sentinel into the numeric domain.
|
|
11
|
+
`SELECT
|
|
6
12
|
n.nspname AS schema,
|
|
7
13
|
c.relname AS name,
|
|
8
|
-
d.description AS comment
|
|
14
|
+
d.description AS comment,
|
|
15
|
+
CASE WHEN c.reltuples < 0 THEN NULL ELSE c.reltuples::float8 END AS row_count_estimate
|
|
9
16
|
FROM pg_class c
|
|
10
17
|
JOIN pg_namespace n ON n.oid = c.relnamespace
|
|
11
18
|
LEFT JOIN pg_description d ON d.objoid = c.oid AND d.objsubid = 0
|
|
@@ -115,6 +122,13 @@ export async function fetchTables(client, schemas) {
|
|
|
115
122
|
foreignKeys: [],
|
|
116
123
|
checks: [],
|
|
117
124
|
indexes: indexByTable.get(key) ?? [],
|
|
125
|
+
// pg returns float8 as a JS number; round to integer because
|
|
126
|
+
// the dev_spec contract (§7.3.1) types this as `number | null`
|
|
127
|
+
// and a fractional estimate would be misleading at the MCP
|
|
128
|
+
// surface.
|
|
129
|
+
rowCountEstimate: row.row_count_estimate === null
|
|
130
|
+
? null
|
|
131
|
+
: Math.round(row.row_count_estimate),
|
|
118
132
|
};
|
|
119
133
|
});
|
|
120
134
|
}
|
package/dist/tables.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tables.js","sourceRoot":"","sources":["../src/tables.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"tables.js","sourceRoot":"","sources":["../src/tables.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kozou/introspect",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"description": "PostgreSQL DDL / COMMENT / VIEW introspection (Kozou v0.1 spec §5).",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"repository": {
|
|
@@ -31,13 +31,14 @@
|
|
|
31
31
|
},
|
|
32
32
|
"dependencies": {
|
|
33
33
|
"pg": "^8.13.0",
|
|
34
|
-
"@kozou/core": "0.
|
|
34
|
+
"@kozou/core": "0.2.0"
|
|
35
35
|
},
|
|
36
36
|
"devDependencies": {
|
|
37
|
-
"@types/pg": "^8.11.0"
|
|
37
|
+
"@types/pg": "^8.11.0",
|
|
38
|
+
"@kozou/test-utils": "0.0.0"
|
|
38
39
|
},
|
|
39
40
|
"scripts": {
|
|
40
|
-
"typecheck": "tsc
|
|
41
|
+
"typecheck": "tsc -p tsconfig.test.json",
|
|
41
42
|
"build": "tsc",
|
|
42
43
|
"test": "vitest run --coverage"
|
|
43
44
|
}
|