@lumifai/harness-tool-pack-postgres 0.0.1

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 (48) hide show
  1. package/README.md +84 -0
  2. package/dist/cast-types.d.ts +1 -0
  3. package/dist/cast-types.js +24 -0
  4. package/dist/cast-types.js.map +1 -0
  5. package/dist/catalog-cache.d.ts +9 -0
  6. package/dist/catalog-cache.js +49 -0
  7. package/dist/catalog-cache.js.map +1 -0
  8. package/dist/catalog.d.ts +45 -0
  9. package/dist/catalog.js +221 -0
  10. package/dist/catalog.js.map +1 -0
  11. package/dist/constants.d.ts +45 -0
  12. package/dist/constants.js +94 -0
  13. package/dist/constants.js.map +1 -0
  14. package/dist/errors.d.ts +18 -0
  15. package/dist/errors.js +29 -0
  16. package/dist/errors.js.map +1 -0
  17. package/dist/identifiers.d.ts +1 -0
  18. package/dist/identifiers.js +21 -0
  19. package/dist/identifiers.js.map +1 -0
  20. package/dist/index.d.ts +7 -0
  21. package/dist/index.js +22 -0
  22. package/dist/index.js.map +1 -0
  23. package/dist/insert-compiler.d.ts +21 -0
  24. package/dist/insert-compiler.js +126 -0
  25. package/dist/insert-compiler.js.map +1 -0
  26. package/dist/insert-executor.d.ts +25 -0
  27. package/dist/insert-executor.js +101 -0
  28. package/dist/insert-executor.js.map +1 -0
  29. package/dist/insert-language.d.ts +56 -0
  30. package/dist/insert-language.js +218 -0
  31. package/dist/insert-language.js.map +1 -0
  32. package/dist/postgres.d.ts +39 -0
  33. package/dist/postgres.js +503 -0
  34. package/dist/postgres.js.map +1 -0
  35. package/dist/query-compiler.d.ts +16 -0
  36. package/dist/query-compiler.js +504 -0
  37. package/dist/query-compiler.js.map +1 -0
  38. package/dist/query-executor.d.ts +27 -0
  39. package/dist/query-executor.js +223 -0
  40. package/dist/query-executor.js.map +1 -0
  41. package/dist/query-language.d.ts +208 -0
  42. package/dist/query-language.js +500 -0
  43. package/dist/query-language.js.map +1 -0
  44. package/dist/workspace-file.d.ts +6 -0
  45. package/dist/workspace-file.js +47 -0
  46. package/dist/workspace-file.js.map +1 -0
  47. package/package.json +43 -0
  48. package/skills/postgres/SKILL.md +144 -0
package/README.md ADDED
@@ -0,0 +1,84 @@
1
+ # @lumifai/harness-tool-pack-postgres
2
+
3
+ PostgreSQL schema inspection, JSON query, and guarded insert tools for the Lumif harness.
4
+
5
+ ## Setup
6
+
7
+ ```ts
8
+ import { createPostgresToolPack } from '@lumifai/harness-tool-pack-postgres';
9
+
10
+ createPostgresToolPack({
11
+ connectionString: process.env.DATABASE_URL,
12
+ // Per-tenant credentials: return a connection string for a least-privilege,
13
+ // RLS-bound role. Access control is enforced in PostgreSQL, not in the pack.
14
+ resolveConnectionString: async (context) => tenantDatabaseUrl(context),
15
+ });
16
+ ```
17
+
18
+ Access control (which schemas, tables, columns, and rows are visible or writable)
19
+ is enforced in the database by the connection role's `GRANT`s and row-level
20
+ security policies. Provision a dedicated role with the minimum privileges needed
21
+ (for example `SELECT` for reads and `INSERT` only on approved tables) and connect
22
+ as that role; the tools expose exactly what the role can see and write.
23
+
24
+ ## Tools
25
+
26
+ | Tool | Purpose |
27
+ | ----------------------------- | ----------------------------------------------- |
28
+ | `postgres_list_schemas` | List accessible schemas with relation counts |
29
+ | `postgres_get_schema_details` | Columns, keys, foreign keys, optional indexes |
30
+ | `postgres_preview_data` | Bounded preview of one relation |
31
+ | `postgres_query` | Execute a validated JSON `QueryPlan` |
32
+ | `postgres_insert` | Insert rows from inline JSON or a workspace CSV |
33
+
34
+ Raw SQL is intentionally unsupported.
35
+
36
+ ## Insert sources
37
+
38
+ `postgres_insert` accepts one table target and a discriminated source:
39
+
40
+ ```json
41
+ {
42
+ "schema": "public",
43
+ "relation": "users",
44
+ "source": {
45
+ "kind": "json",
46
+ "columns": ["email", "active"],
47
+ "rows": [["a@example.com", true]]
48
+ }
49
+ }
50
+ ```
51
+
52
+ ```json
53
+ {
54
+ "schema": "public",
55
+ "relation": "users",
56
+ "source": {
57
+ "kind": "csv",
58
+ "path": "/data/users.csv"
59
+ }
60
+ }
61
+ ```
62
+
63
+ CSV paths must be absolute within the Mastra workspace filesystem
64
+ (for example `/data/users.csv`). Host filesystem paths are rejected. Partial
65
+ success is intentional: valid rows commit; rejected rows are returned with
66
+ row indexes and error codes. Structural failures (missing workspace, bad CSV,
67
+ unknown table) fail the tool call.
68
+
69
+ ## Security model
70
+
71
+ Defense in depth:
72
+
73
+ 1. PostgreSQL least-privilege role, RLS, column grants, and per-tenant credentials (the authority for access control)
74
+ 2. No raw SQL: the model emits validated JSON plans or insert payloads, compiled server-side and parameterized via `pg-sql2`
75
+ 3. Read-only transactions for queries; read-write transactions with per-row savepoints for inserts; timeouts; hard row/byte/cell limits
76
+ 4. Schema metadata is loaded on demand (schema list is a single lightweight query; details/query compile load only the schemas they need) and cached briefly per connection fingerprint
77
+ 5. CSV inserts read only through the configured Mastra workspace filesystem
78
+
79
+ Extension functions are disabled by default. If enabled, configure and call them
80
+ with the exact schema-qualified name, such as `public.mask_email`. Use
81
+ `date_part(field, source)` instead of `EXTRACT`. `current_date` /
82
+ `current_timestamp` are supported as niladic keywords.
83
+
84
+ Bundled agent skills ship in this package and are merged into `workspace.skills` when the pack is enabled.
@@ -0,0 +1 @@
1
+ export declare function assertAllowedCastType(type: string): void;
@@ -0,0 +1,24 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.assertAllowedCastType = assertAllowedCastType;
4
+ const errors_1 = require("./errors");
5
+ const ALLOWED_CAST_TYPES = new Set([
6
+ 'text',
7
+ 'varchar',
8
+ 'integer',
9
+ 'bigint',
10
+ 'numeric',
11
+ 'boolean',
12
+ 'date',
13
+ 'timestamp',
14
+ 'timestamptz',
15
+ 'json',
16
+ 'jsonb',
17
+ 'uuid',
18
+ ]);
19
+ function assertAllowedCastType(type) {
20
+ if (!ALLOWED_CAST_TYPES.has(type.toLowerCase())) {
21
+ throw new errors_1.PostgresToolError('COMPILATION_ERROR', `Cast type "${type}" is not allowed.`);
22
+ }
23
+ }
24
+ //# sourceMappingURL=cast-types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cast-types.js","sourceRoot":"","sources":["../src/cast-types.ts"],"names":[],"mappings":";;AAiBA,sDAIC;AArBD,qCAA6C;AAE7C,MAAM,kBAAkB,GAAG,IAAI,GAAG,CAAC;IACjC,MAAM;IACN,SAAS;IACT,SAAS;IACT,QAAQ;IACR,SAAS;IACT,SAAS;IACT,MAAM;IACN,WAAW;IACX,aAAa;IACb,MAAM;IACN,OAAO;IACP,MAAM;CACP,CAAC,CAAC;AAEH,SAAgB,qBAAqB,CAAC,IAAY;IAChD,IAAI,CAAC,kBAAkB,CAAC,GAAG,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC,EAAE,CAAC;QAChD,MAAM,IAAI,0BAAiB,CAAC,mBAAmB,EAAE,cAAc,IAAI,mBAAmB,CAAC,CAAC;IAC1F,CAAC;AACH,CAAC"}
@@ -0,0 +1,9 @@
1
+ import type { Client } from 'pg';
2
+ import type { PostgresCatalog } from './catalog';
3
+ /**
4
+ * Loads a schema-scoped catalog, reusing an in-memory entry keyed by connection
5
+ * fingerprint + sorted schema list for a short TTL.
6
+ */
7
+ export declare function loadCachedCatalog(connectionString: string, client: Client, schemas: string[], ttlMs?: number): Promise<PostgresCatalog>;
8
+ /** Test helper — clears the process-local catalog cache. */
9
+ export declare function clearCatalogCache(): void;
@@ -0,0 +1,49 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.loadCachedCatalog = loadCachedCatalog;
4
+ exports.clearCatalogCache = clearCatalogCache;
5
+ const node_crypto_1 = require("node:crypto");
6
+ const catalog_1 = require("./catalog");
7
+ const constants_1 = require("./constants");
8
+ const catalogCache = new Map();
9
+ function hashConnectionKey(connectionString) {
10
+ return (0, node_crypto_1.createHash)('sha256').update(connectionString, 'utf8').digest('hex');
11
+ }
12
+ function cacheKey(connectionString, schemas) {
13
+ return `${hashConnectionKey(connectionString)}::${[...schemas].sort().join(',')}`;
14
+ }
15
+ function pruneExpiredEntries(now) {
16
+ for (const [key, entry] of catalogCache) {
17
+ if (entry.expiresAt <= now) {
18
+ catalogCache.delete(key);
19
+ }
20
+ }
21
+ }
22
+ /**
23
+ * Loads a schema-scoped catalog, reusing an in-memory entry keyed by connection
24
+ * fingerprint + sorted schema list for a short TTL.
25
+ */
26
+ async function loadCachedCatalog(connectionString, client, schemas, ttlMs = constants_1.DEFAULT_CATALOG_CACHE_TTL_MS) {
27
+ const uniqueSchemas = [...new Set(schemas)].sort();
28
+ if (uniqueSchemas.length === 0) {
29
+ return { schemas: new Set(), relations: new Map() };
30
+ }
31
+ const key = cacheKey(connectionString, uniqueSchemas);
32
+ const now = Date.now();
33
+ const cached = catalogCache.get(key);
34
+ if (cached) {
35
+ if (cached.expiresAt > now) {
36
+ return cached.catalog;
37
+ }
38
+ catalogCache.delete(key);
39
+ }
40
+ const catalog = await (0, catalog_1.loadPostgresCatalog)(client, { schemas: uniqueSchemas });
41
+ pruneExpiredEntries(now);
42
+ catalogCache.set(key, { catalog, expiresAt: now + Math.max(ttlMs, 0) });
43
+ return catalog;
44
+ }
45
+ /** Test helper — clears the process-local catalog cache. */
46
+ function clearCatalogCache() {
47
+ catalogCache.clear();
48
+ }
49
+ //# sourceMappingURL=catalog-cache.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"catalog-cache.js","sourceRoot":"","sources":["../src/catalog-cache.ts"],"names":[],"mappings":";;AAmCA,8CAyBC;AAGD,8CAEC;AAjED,6CAAyC;AAKzC,uCAAgD;AAChD,2CAA2D;AAO3D,MAAM,YAAY,GAAG,IAAI,GAAG,EAAsB,CAAC;AAEnD,SAAS,iBAAiB,CAAC,gBAAwB;IACjD,OAAO,IAAA,wBAAU,EAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,gBAAgB,EAAE,MAAM,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;AAC7E,CAAC;AAED,SAAS,QAAQ,CAAC,gBAAwB,EAAE,OAAiB;IAC3D,OAAO,GAAG,iBAAiB,CAAC,gBAAgB,CAAC,KAAK,CAAC,GAAG,OAAO,CAAC,CAAC,IAAI,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;AACpF,CAAC;AAED,SAAS,mBAAmB,CAAC,GAAW;IACtC,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,YAAY,EAAE,CAAC;QACxC,IAAI,KAAK,CAAC,SAAS,IAAI,GAAG,EAAE,CAAC;YAC3B,YAAY,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QAC3B,CAAC;IACH,CAAC;AACH,CAAC;AAED;;;GAGG;AACI,KAAK,UAAU,iBAAiB,CACrC,gBAAwB,EACxB,MAAc,EACd,OAAiB,EACjB,QAAgB,wCAA4B;IAE5C,MAAM,aAAa,GAAG,CAAC,GAAG,IAAI,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;IACnD,IAAI,aAAa,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC/B,OAAO,EAAE,OAAO,EAAE,IAAI,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,GAAG,EAAE,EAAE,CAAC;IACtD,CAAC;IAED,MAAM,GAAG,GAAG,QAAQ,CAAC,gBAAgB,EAAE,aAAa,CAAC,CAAC;IACtD,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IACvB,MAAM,MAAM,GAAG,YAAY,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IACrC,IAAI,MAAM,EAAE,CAAC;QACX,IAAI,MAAM,CAAC,SAAS,GAAG,GAAG,EAAE,CAAC;YAC3B,OAAO,MAAM,CAAC,OAAO,CAAC;QACxB,CAAC;QACD,YAAY,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;IAC3B,CAAC;IAED,MAAM,OAAO,GAAG,MAAM,IAAA,6BAAmB,EAAC,MAAM,EAAE,EAAE,OAAO,EAAE,aAAa,EAAE,CAAC,CAAC;IAC9E,mBAAmB,CAAC,GAAG,CAAC,CAAC;IACzB,YAAY,CAAC,GAAG,CAAC,GAAG,EAAE,EAAE,OAAO,EAAE,SAAS,EAAE,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC;IACxE,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,4DAA4D;AAC5D,SAAgB,iBAAiB;IAC/B,YAAY,CAAC,KAAK,EAAE,CAAC;AACvB,CAAC"}
@@ -0,0 +1,45 @@
1
+ import type { Client } from 'pg';
2
+ export type CatalogColumn = {
3
+ name: string;
4
+ dataType: string;
5
+ isNullable: boolean;
6
+ ordinalPosition: number;
7
+ };
8
+ export type CatalogRelation = {
9
+ schema: string;
10
+ name: string;
11
+ kind: 'table' | 'view';
12
+ columns: CatalogColumn[];
13
+ primaryKey: string[];
14
+ uniqueKeys: string[][];
15
+ foreignKeys: {
16
+ name: string;
17
+ columns: string[];
18
+ referencedSchema: string;
19
+ referencedTable: string;
20
+ referencedColumns: string[];
21
+ }[];
22
+ indexes?: {
23
+ name: string;
24
+ columns: string[];
25
+ isUnique: boolean;
26
+ }[];
27
+ };
28
+ export type PostgresCatalog = {
29
+ schemas: Set<string>;
30
+ relations: Map<string, CatalogRelation>;
31
+ };
32
+ export type SchemaSummary = {
33
+ name: string;
34
+ relation_count: number;
35
+ };
36
+ /**
37
+ * Lightweight schema listing: one query for names + relation counts.
38
+ * Does not load columns, keys, or foreign keys.
39
+ */
40
+ export declare function listSchemaSummaries(client: Client): Promise<SchemaSummary[]>;
41
+ export declare function loadPostgresCatalog(client: Client, options?: {
42
+ schemas?: string[];
43
+ }): Promise<PostgresCatalog>;
44
+ export declare function loadRelationIndexes(client: Client, schema: string, relation: string): Promise<CatalogRelation['indexes']>;
45
+ export declare function getCatalogRelation(catalog: PostgresCatalog, schema: string, name: string): CatalogRelation | undefined;
@@ -0,0 +1,221 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.listSchemaSummaries = listSchemaSummaries;
4
+ exports.loadPostgresCatalog = loadPostgresCatalog;
5
+ exports.loadRelationIndexes = loadRelationIndexes;
6
+ exports.getCatalogRelation = getCatalogRelation;
7
+ const constants_1 = require("./constants");
8
+ function relationKey(schema, name) {
9
+ return `${schema}.${name}`;
10
+ }
11
+ /**
12
+ * Lightweight schema listing: one query for names + relation counts.
13
+ * Does not load columns, keys, or foreign keys.
14
+ */
15
+ async function listSchemaSummaries(client) {
16
+ const result = await client.query(`SELECT
17
+ s.schema_name,
18
+ COALESCE(t.relation_count, 0)::text AS relation_count
19
+ FROM information_schema.schemata s
20
+ LEFT JOIN (
21
+ SELECT table_schema, COUNT(*)::int AS relation_count
22
+ FROM information_schema.tables
23
+ WHERE table_type IN ('BASE TABLE', 'VIEW')
24
+ GROUP BY table_schema
25
+ ) t ON t.table_schema = s.schema_name
26
+ WHERE s.schema_name NOT IN ('pg_catalog', 'information_schema', 'pg_toast')
27
+ AND s.schema_name NOT LIKE 'pg_temp_%'
28
+ AND s.schema_name NOT LIKE 'pg_toast_temp_%'
29
+ ORDER BY s.schema_name`);
30
+ return result.rows
31
+ .filter((row) => !constants_1.SYSTEM_SCHEMAS.has(row.schema_name))
32
+ .map((row) => ({
33
+ name: row.schema_name,
34
+ relation_count: Number(row.relation_count),
35
+ }));
36
+ }
37
+ async function loadPostgresCatalog(client, options) {
38
+ let schemas;
39
+ if (options?.schemas) {
40
+ const requested = options.schemas.filter((name) => name.length > 0 && !constants_1.SYSTEM_SCHEMAS.has(name));
41
+ if (requested.length === 0) {
42
+ return { schemas: new Set(), relations: new Map() };
43
+ }
44
+ const schemasResult = await client.query(`SELECT schema_name
45
+ FROM information_schema.schemata
46
+ WHERE schema_name = ANY($1::text[])`, [requested]);
47
+ schemas = new Set(schemasResult.rows.map((row) => row.schema_name));
48
+ }
49
+ else {
50
+ const schemasResult = await client.query(`SELECT schema_name
51
+ FROM information_schema.schemata
52
+ WHERE schema_name NOT IN ('pg_catalog', 'information_schema', 'pg_toast')
53
+ AND schema_name NOT LIKE 'pg_temp_%'
54
+ AND schema_name NOT LIKE 'pg_toast_temp_%'`);
55
+ schemas = new Set(schemasResult.rows.map((row) => row.schema_name).filter((name) => !constants_1.SYSTEM_SCHEMAS.has(name)));
56
+ }
57
+ if (schemas.size === 0) {
58
+ return { schemas, relations: new Map() };
59
+ }
60
+ const schemaList = Array.from(schemas);
61
+ const tablesResult = await client.query(`SELECT table_schema, table_name, table_type
62
+ FROM information_schema.tables
63
+ WHERE table_schema = ANY($1::text[])
64
+ AND table_type IN ('BASE TABLE', 'VIEW')
65
+ ORDER BY table_schema, table_name`, [schemaList]);
66
+ const columnsResult = await client.query(`SELECT table_schema, table_name, column_name, data_type, is_nullable, ordinal_position
67
+ FROM information_schema.columns
68
+ WHERE table_schema = ANY($1::text[])
69
+ ORDER BY table_schema, table_name, ordinal_position`, [schemaList]);
70
+ const pkResult = await client.query(`SELECT tc.table_schema, tc.table_name, kcu.column_name, kcu.ordinal_position
71
+ FROM information_schema.table_constraints tc
72
+ JOIN information_schema.key_column_usage kcu
73
+ ON tc.constraint_name = kcu.constraint_name
74
+ AND tc.table_schema = kcu.table_schema
75
+ WHERE tc.constraint_type = 'PRIMARY KEY'
76
+ AND tc.table_schema = ANY($1::text[])
77
+ ORDER BY tc.table_schema, tc.table_name, kcu.ordinal_position`, [schemaList]);
78
+ const uniqueResult = await client.query(`SELECT tc.table_schema, tc.table_name, tc.constraint_name, kcu.column_name, kcu.ordinal_position
79
+ FROM information_schema.table_constraints tc
80
+ JOIN information_schema.key_column_usage kcu
81
+ ON tc.constraint_name = kcu.constraint_name
82
+ AND tc.table_schema = kcu.table_schema
83
+ WHERE tc.constraint_type = 'UNIQUE'
84
+ AND tc.table_schema = ANY($1::text[])
85
+ ORDER BY tc.table_schema, tc.table_name, tc.constraint_name, kcu.ordinal_position`, [schemaList]);
86
+ const fkResult = await client.query(`SELECT
87
+ kcu.table_schema,
88
+ kcu.table_name,
89
+ kcu.constraint_name,
90
+ kcu.column_name,
91
+ kcu.ordinal_position,
92
+ fcu.table_schema AS foreign_table_schema,
93
+ fcu.table_name AS foreign_table_name,
94
+ fcu.column_name AS foreign_column_name
95
+ FROM information_schema.referential_constraints rc
96
+ JOIN information_schema.key_column_usage kcu
97
+ ON kcu.constraint_name = rc.constraint_name
98
+ AND kcu.constraint_schema = rc.constraint_schema
99
+ JOIN information_schema.key_column_usage fcu
100
+ ON fcu.constraint_name = rc.unique_constraint_name
101
+ AND fcu.constraint_schema = rc.unique_constraint_schema
102
+ AND fcu.ordinal_position = kcu.position_in_unique_constraint
103
+ WHERE kcu.table_schema = ANY($1::text[])
104
+ ORDER BY kcu.table_schema, kcu.table_name, kcu.constraint_name, kcu.ordinal_position`, [schemaList]);
105
+ const relations = new Map();
106
+ for (const table of tablesResult.rows) {
107
+ if (!schemas.has(table.table_schema)) {
108
+ continue;
109
+ }
110
+ relations.set(relationKey(table.table_schema, table.table_name), {
111
+ schema: table.table_schema,
112
+ name: table.table_name,
113
+ kind: table.table_type === 'VIEW' ? 'view' : 'table',
114
+ columns: [],
115
+ primaryKey: [],
116
+ uniqueKeys: [],
117
+ foreignKeys: [],
118
+ });
119
+ }
120
+ for (const column of columnsResult.rows) {
121
+ const relation = relations.get(relationKey(column.table_schema, column.table_name));
122
+ if (!relation) {
123
+ continue;
124
+ }
125
+ relation.columns.push({
126
+ name: column.column_name,
127
+ dataType: column.data_type,
128
+ isNullable: column.is_nullable === 'YES',
129
+ ordinalPosition: column.ordinal_position,
130
+ });
131
+ }
132
+ const pkByRelation = new Map();
133
+ for (const row of pkResult.rows) {
134
+ const key = relationKey(row.table_schema, row.table_name);
135
+ const columns = pkByRelation.get(key) ?? [];
136
+ columns.push(row.column_name);
137
+ pkByRelation.set(key, columns);
138
+ }
139
+ for (const [key, columns] of pkByRelation) {
140
+ const relation = relations.get(key);
141
+ if (relation) {
142
+ relation.primaryKey = columns;
143
+ }
144
+ }
145
+ const uniqueByConstraint = new Map();
146
+ for (const row of uniqueResult.rows) {
147
+ const key = `${row.table_schema}.${row.table_name}.${row.constraint_name}`;
148
+ const columns = uniqueByConstraint.get(key) ?? [];
149
+ columns.push(row.column_name);
150
+ uniqueByConstraint.set(key, columns);
151
+ }
152
+ for (const relation of relations.values()) {
153
+ relation.uniqueKeys = Array.from(uniqueByConstraint.entries())
154
+ .filter(([key]) => key.startsWith(`${relation.schema}.${relation.name}.`))
155
+ .map(([, columns]) => columns);
156
+ }
157
+ const fkByConstraint = new Map();
158
+ for (const row of fkResult.rows) {
159
+ const key = `${row.table_schema}.${row.table_name}.${row.constraint_name}`;
160
+ const existing = fkByConstraint.get(key) ?? {
161
+ name: row.constraint_name,
162
+ columns: [],
163
+ referencedSchema: row.foreign_table_schema,
164
+ referencedTable: row.foreign_table_name,
165
+ referencedColumns: [],
166
+ };
167
+ existing.columns.push(row.column_name);
168
+ existing.referencedColumns.push(row.foreign_column_name);
169
+ fkByConstraint.set(key, existing);
170
+ }
171
+ for (const relation of relations.values()) {
172
+ relation.foreignKeys = Array.from(fkByConstraint.entries())
173
+ .filter(([key]) => key.startsWith(`${relation.schema}.${relation.name}.`))
174
+ .map(([, fk]) => fk);
175
+ }
176
+ return { schemas, relations };
177
+ }
178
+ async function loadRelationIndexes(client, schema, relation) {
179
+ const result = await client.query(`SELECT indexname, indexdef
180
+ FROM pg_indexes
181
+ WHERE schemaname = $1 AND tablename = $2
182
+ ORDER BY indexname`, [schema, relation]);
183
+ return result.rows.flatMap((row) => {
184
+ const columns = extractIndexColumns(row.indexdef);
185
+ if (!columns) {
186
+ return [];
187
+ }
188
+ return [
189
+ {
190
+ name: row.indexname,
191
+ columns,
192
+ isUnique: /^CREATE\s+UNIQUE\s+INDEX\b/i.test(row.indexdef),
193
+ },
194
+ ];
195
+ });
196
+ }
197
+ function extractIndexColumns(indexDef) {
198
+ if (/\b(?:WHERE|INCLUDE)\b/i.test(indexDef)) {
199
+ return undefined;
200
+ }
201
+ const open = indexDef.indexOf('(');
202
+ const close = indexDef.indexOf(')', open + 1);
203
+ if (open < 0 || close < 0) {
204
+ return undefined;
205
+ }
206
+ const definition = indexDef.slice(open + 1, close);
207
+ if (!definition || definition.includes('(')) {
208
+ return undefined;
209
+ }
210
+ const columns = definition.split(',').map((part) => {
211
+ const identifier = part
212
+ .trim()
213
+ .match(/^"?([a-zA-Z_][a-zA-Z0-9_]*)"?(?:\s+(?:ASC|DESC))?(?:\s+NULLS\s+(?:FIRST|LAST))?$/i);
214
+ return identifier?.[1] ?? undefined;
215
+ });
216
+ return columns.every((column) => column !== undefined) ? columns : undefined;
217
+ }
218
+ function getCatalogRelation(catalog, schema, name) {
219
+ return catalog.relations.get(relationKey(schema, name));
220
+ }
221
+ //# sourceMappingURL=catalog.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"catalog.js","sourceRoot":"","sources":["../src/catalog.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,45 @@
1
+ export declare const QUERY_PLAN_VERSION: 1;
2
+ export declare const DEFAULT_POSTGRES_QUERY_LIMIT = 100;
3
+ export declare const MAX_POSTGRES_QUERY_LIMIT = 500;
4
+ export declare const DEFAULT_PREVIEW_LIMIT = 10;
5
+ export declare const MAX_PREVIEW_LIMIT = 50;
6
+ export declare const DEFAULT_STATEMENT_TIMEOUT_MS = 10000;
7
+ export declare const MAX_STATEMENT_TIMEOUT_MS = 120000;
8
+ export declare const DEFAULT_TEMP_FILE_LIMIT_KB: number;
9
+ export declare const MAX_TEMP_FILE_LIMIT_KB: number;
10
+ export declare const DEFAULT_LOCK_TIMEOUT_MS = 2000;
11
+ export declare const DEFAULT_IDLE_IN_TRANSACTION_TIMEOUT_MS = 5000;
12
+ export declare const DEFAULT_MAX_RESULT_BYTES = 256000;
13
+ export declare const MAX_RESULT_BYTES = 4194304;
14
+ export declare const DEFAULT_MAX_CELL_BYTES = 8192;
15
+ export declare const CURSOR_BATCH_SIZE = 200;
16
+ export declare const MAX_QUERY_INPUT_DEPTH = 64;
17
+ export declare const MAX_QUERY_INPUT_NODES = 4096;
18
+ export declare const DEFAULT_MAX_JOINS = 5;
19
+ export declare const DEFAULT_MAX_CTES = 3;
20
+ export declare const DEFAULT_MAX_SELECT_ITEMS = 64;
21
+ export declare const DEFAULT_MAX_IN_LIST_SIZE = 100;
22
+ export declare const DEFAULT_MAX_EXPRESSION_DEPTH = 8;
23
+ export declare const DEFAULT_MAX_QUERY_NODES = 200;
24
+ export declare const DEFAULT_EXPLAIN_COST_LIMIT = 50000;
25
+ export declare const SYSTEM_SCHEMAS: Set<string>;
26
+ export declare const COMPARISON_OPERATORS: readonly ["eq", "ne", "lt", "lte", "gt", "gte", "like", "ilike"];
27
+ export declare const AGGREGATE_FUNCTIONS: readonly ["count", "sum", "avg", "min", "max", "count_distinct"];
28
+ export declare const JOIN_TYPES: readonly ["inner", "left", "right", "full"];
29
+ export declare const SET_OPERATIONS: readonly ["union", "union_all", "intersect", "except"];
30
+ export declare const WINDOW_FUNCTIONS: readonly ["count", "sum", "avg", "min", "max", "row_number", "rank", "dense_rank", "lag", "lead"];
31
+ /** Niladic SQL keywords that must not be emitted as "name"(). */
32
+ export declare const NILADIC_KEYWORDS: Set<string>;
33
+ /**
34
+ * Built-in functions that compile as identifier(args).
35
+ * Prefer date_part(field, source) over EXTRACT — EXTRACT needs keyword syntax.
36
+ * Window-only functions live in WINDOW_FUNCTIONS, not here.
37
+ */
38
+ export declare const BUILTIN_FUNCTIONS: Set<string>;
39
+ export declare const DEFAULT_CATALOG_CACHE_TTL_MS = 30000;
40
+ export declare const DEFAULT_MAX_INSERT_ROWS = 1000;
41
+ export declare const MAX_INSERT_ROWS = 5000;
42
+ export declare const DEFAULT_MAX_INSERT_CSV_BYTES = 1048576;
43
+ export declare const MAX_INSERT_CSV_BYTES = 4194304;
44
+ export declare const DEFAULT_MAX_INSERT_REJECTION_DETAILS = 200;
45
+ export declare const MAX_INSERT_REJECTION_DETAILS = 1000;
@@ -0,0 +1,94 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.MAX_INSERT_REJECTION_DETAILS = exports.DEFAULT_MAX_INSERT_REJECTION_DETAILS = exports.MAX_INSERT_CSV_BYTES = exports.DEFAULT_MAX_INSERT_CSV_BYTES = exports.MAX_INSERT_ROWS = exports.DEFAULT_MAX_INSERT_ROWS = exports.DEFAULT_CATALOG_CACHE_TTL_MS = exports.BUILTIN_FUNCTIONS = exports.NILADIC_KEYWORDS = exports.WINDOW_FUNCTIONS = exports.SET_OPERATIONS = exports.JOIN_TYPES = exports.AGGREGATE_FUNCTIONS = exports.COMPARISON_OPERATORS = exports.SYSTEM_SCHEMAS = exports.DEFAULT_EXPLAIN_COST_LIMIT = exports.DEFAULT_MAX_QUERY_NODES = exports.DEFAULT_MAX_EXPRESSION_DEPTH = exports.DEFAULT_MAX_IN_LIST_SIZE = exports.DEFAULT_MAX_SELECT_ITEMS = exports.DEFAULT_MAX_CTES = exports.DEFAULT_MAX_JOINS = exports.MAX_QUERY_INPUT_NODES = exports.MAX_QUERY_INPUT_DEPTH = exports.CURSOR_BATCH_SIZE = exports.DEFAULT_MAX_CELL_BYTES = exports.MAX_RESULT_BYTES = exports.DEFAULT_MAX_RESULT_BYTES = exports.DEFAULT_IDLE_IN_TRANSACTION_TIMEOUT_MS = exports.DEFAULT_LOCK_TIMEOUT_MS = exports.MAX_TEMP_FILE_LIMIT_KB = exports.DEFAULT_TEMP_FILE_LIMIT_KB = exports.MAX_STATEMENT_TIMEOUT_MS = exports.DEFAULT_STATEMENT_TIMEOUT_MS = exports.MAX_PREVIEW_LIMIT = exports.DEFAULT_PREVIEW_LIMIT = exports.MAX_POSTGRES_QUERY_LIMIT = exports.DEFAULT_POSTGRES_QUERY_LIMIT = exports.QUERY_PLAN_VERSION = void 0;
4
+ exports.QUERY_PLAN_VERSION = 1;
5
+ exports.DEFAULT_POSTGRES_QUERY_LIMIT = 100;
6
+ exports.MAX_POSTGRES_QUERY_LIMIT = 500;
7
+ exports.DEFAULT_PREVIEW_LIMIT = 10;
8
+ exports.MAX_PREVIEW_LIMIT = 50;
9
+ exports.DEFAULT_STATEMENT_TIMEOUT_MS = 10_000;
10
+ exports.MAX_STATEMENT_TIMEOUT_MS = 120_000;
11
+ exports.DEFAULT_TEMP_FILE_LIMIT_KB = 64 * 1024;
12
+ exports.MAX_TEMP_FILE_LIMIT_KB = 256 * 1024;
13
+ exports.DEFAULT_LOCK_TIMEOUT_MS = 2_000;
14
+ exports.DEFAULT_IDLE_IN_TRANSACTION_TIMEOUT_MS = 5_000;
15
+ exports.DEFAULT_MAX_RESULT_BYTES = 256_000;
16
+ exports.MAX_RESULT_BYTES = 4_194_304;
17
+ exports.DEFAULT_MAX_CELL_BYTES = 8_192;
18
+ exports.CURSOR_BATCH_SIZE = 200;
19
+ exports.MAX_QUERY_INPUT_DEPTH = 64;
20
+ exports.MAX_QUERY_INPUT_NODES = 4_096;
21
+ exports.DEFAULT_MAX_JOINS = 5;
22
+ exports.DEFAULT_MAX_CTES = 3;
23
+ exports.DEFAULT_MAX_SELECT_ITEMS = 64;
24
+ exports.DEFAULT_MAX_IN_LIST_SIZE = 100;
25
+ exports.DEFAULT_MAX_EXPRESSION_DEPTH = 8;
26
+ exports.DEFAULT_MAX_QUERY_NODES = 200;
27
+ exports.DEFAULT_EXPLAIN_COST_LIMIT = 50_000;
28
+ exports.SYSTEM_SCHEMAS = new Set(['pg_catalog', 'information_schema', 'pg_toast']);
29
+ exports.COMPARISON_OPERATORS = [
30
+ 'eq',
31
+ 'ne',
32
+ 'lt',
33
+ 'lte',
34
+ 'gt',
35
+ 'gte',
36
+ 'like',
37
+ 'ilike',
38
+ ];
39
+ exports.AGGREGATE_FUNCTIONS = ['count', 'sum', 'avg', 'min', 'max', 'count_distinct'];
40
+ exports.JOIN_TYPES = ['inner', 'left', 'right', 'full'];
41
+ exports.SET_OPERATIONS = ['union', 'union_all', 'intersect', 'except'];
42
+ exports.WINDOW_FUNCTIONS = [
43
+ 'count',
44
+ 'sum',
45
+ 'avg',
46
+ 'min',
47
+ 'max',
48
+ 'row_number',
49
+ 'rank',
50
+ 'dense_rank',
51
+ 'lag',
52
+ 'lead',
53
+ ];
54
+ /** Niladic SQL keywords that must not be emitted as "name"(). */
55
+ exports.NILADIC_KEYWORDS = new Set(['current_date', 'current_timestamp']);
56
+ /**
57
+ * Built-in functions that compile as identifier(args).
58
+ * Prefer date_part(field, source) over EXTRACT — EXTRACT needs keyword syntax.
59
+ * Window-only functions live in WINDOW_FUNCTIONS, not here.
60
+ */
61
+ exports.BUILTIN_FUNCTIONS = new Set([
62
+ 'coalesce',
63
+ 'nullif',
64
+ 'lower',
65
+ 'upper',
66
+ 'trim',
67
+ 'length',
68
+ 'abs',
69
+ 'round',
70
+ 'floor',
71
+ 'ceil',
72
+ 'date_trunc',
73
+ 'date_part',
74
+ 'now',
75
+ 'concat',
76
+ 'substring',
77
+ 'replace',
78
+ 'split_part',
79
+ 'to_char',
80
+ 'to_date',
81
+ 'to_timestamp',
82
+ 'greatest',
83
+ 'least',
84
+ 'jsonb_build_object',
85
+ 'jsonb_extract_path_text',
86
+ ]);
87
+ exports.DEFAULT_CATALOG_CACHE_TTL_MS = 30_000;
88
+ exports.DEFAULT_MAX_INSERT_ROWS = 1000;
89
+ exports.MAX_INSERT_ROWS = 5000;
90
+ exports.DEFAULT_MAX_INSERT_CSV_BYTES = 1_048_576;
91
+ exports.MAX_INSERT_CSV_BYTES = 4_194_304;
92
+ exports.DEFAULT_MAX_INSERT_REJECTION_DETAILS = 200;
93
+ exports.MAX_INSERT_REJECTION_DETAILS = 1000;
94
+ //# sourceMappingURL=constants.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"constants.js","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,18 @@
1
+ export type PostgresToolErrorCode = 'INVALID_INPUT' | 'POLICY_DENIED' | 'UNKNOWN_RELATION' | 'UNKNOWN_COLUMN' | 'COMPLEXITY_EXCEEDED' | 'COMPILATION_ERROR' | 'EXECUTION_ERROR' | 'TIMEOUT' | 'COST_EXCEEDED' | 'CONFIGURATION_ERROR';
2
+ export declare class PostgresToolError extends Error {
3
+ readonly code: PostgresToolErrorCode;
4
+ readonly path?: string;
5
+ readonly hint?: string;
6
+ constructor(code: PostgresToolErrorCode, message: string, options?: {
7
+ path?: string;
8
+ hint?: string;
9
+ cause?: unknown;
10
+ });
11
+ toJSON(): {
12
+ code: PostgresToolErrorCode;
13
+ message: string;
14
+ path?: string;
15
+ hint?: string;
16
+ };
17
+ }
18
+ export declare function isPostgresToolError(error: unknown): error is PostgresToolError;
package/dist/errors.js ADDED
@@ -0,0 +1,29 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.PostgresToolError = void 0;
4
+ exports.isPostgresToolError = isPostgresToolError;
5
+ class PostgresToolError extends Error {
6
+ code;
7
+ path;
8
+ hint;
9
+ constructor(code, message, options) {
10
+ super(message, { cause: options?.cause });
11
+ this.name = 'PostgresToolError';
12
+ this.code = code;
13
+ this.path = options?.path;
14
+ this.hint = options?.hint;
15
+ }
16
+ toJSON() {
17
+ return {
18
+ code: this.code,
19
+ message: this.message,
20
+ ...(this.path ? { path: this.path } : {}),
21
+ ...(this.hint ? { hint: this.hint } : {}),
22
+ };
23
+ }
24
+ }
25
+ exports.PostgresToolError = PostgresToolError;
26
+ function isPostgresToolError(error) {
27
+ return error instanceof PostgresToolError;
28
+ }
29
+ //# sourceMappingURL=errors.js.map