@slates-integrations/postgresql 0.2.0-rc.6

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 ADDED
@@ -0,0 +1,61 @@
1
+ # <img src="https://provider-logos.metorial-cdn.com/postgresql.png" height="20"> Postgresql
2
+
3
+ Query, insert, update, and delete data in PostgreSQL relational databases. Explore schemas and tables, manage schemas, tables, indexes, views, materialized views, and database roles, and poll tables for row changes using timestamp or incrementing columns.
4
+
5
+ ## Tools
6
+
7
+ ### Delete Rows
8
+
9
+ Delete rows from a PostgreSQL table based on a WHERE condition. Supports returning the deleted rows and requires explicit confirmation for full-table deletes.
10
+
11
+ ### Describe Table
12
+
13
+ Get detailed schema information for a specific table, including columns, data types, constraints, indexes, and foreign keys. Useful for understanding table structure before building queries or modifying schemas.
14
+
15
+ ### Execute SQL Query
16
+
17
+ Execute an arbitrary SQL query against the PostgreSQL database. Supports all SQL operations including SELECT, INSERT, UPDATE, DELETE, CREATE, ALTER, DROP, and more. Returns column metadata and result rows for SELECT queries, or affected row counts for DML statements. Supports complex queries with joins, subqueries, CTEs, window functions, and aggregations.
18
+
19
+ ### Insert Rows
20
+
21
+ Insert one or more rows into a PostgreSQL table. Provide the data as an array of objects where keys are column names and values are the data to insert. Supports inserting multiple rows in a single operation and can optionally return the inserted rows.
22
+
23
+ ### List Schemas
24
+
25
+ List all schemas in the PostgreSQL database with their table counts and sizes. Useful for exploring the database structure and understanding the organization of tables across schemas.
26
+
27
+ ### Manage Schemas
28
+
29
+ Create, rename, or drop PostgreSQL schemas. Drop operations require explicit confirmation and can optionally cascade to contained objects.
30
+
31
+ ### List Tables
32
+
33
+ List all tables in the PostgreSQL database, optionally filtered by schema. Returns table names, schemas, row estimates, and size information. Also supports listing views and materialized views.
34
+
35
+ ### Manage Indexes
36
+
37
+ Create or drop indexes on PostgreSQL tables. Supports B-tree, Hash, GIN, GiST, and other index types. Can create unique indexes, partial indexes with WHERE conditions, and multi-column indexes.
38
+
39
+ ### Manage Roles
40
+
41
+ Manage PostgreSQL roles and their privileges. Supports creating and dropping roles, as well as granting and revoking privileges on databases, schemas, tables, and other objects.
42
+
43
+ ### Manage Table
44
+
45
+ Create, alter, or drop a PostgreSQL table. Supports creating tables with columns, constraints, and foreign keys. For altering tables, supports adding columns, dropping columns, renaming columns, altering column types, and renaming the table.
46
+
47
+ ### Manage Views
48
+
49
+ Create and drop PostgreSQL views or materialized views, and refresh materialized views. View definitions are restricted to a single read query for safer structured management.
50
+
51
+ ### Update Rows
52
+
53
+ Update rows in a PostgreSQL table based on a WHERE condition. Specify the columns to update and their new values. Supports returning updated rows and allows complex WHERE conditions.
54
+
55
+ ## License
56
+
57
+ This integration is licensed under the [FSL-1.1](https://github.com/metorial/metorial-platform/blob/dev/LICENSE).
58
+
59
+ <div align="center">
60
+ <sub>Built with ❤️ by <a href="https://metorial.com">Metorial</a></sub>
61
+ </div>
package/docs/SPEC.md ADDED
@@ -0,0 +1,109 @@
1
+ # Slates Specification for PostgreSQL
2
+
3
+ ## Overview
4
+
5
+ PostgreSQL is an open-source relational database management system used for storing, querying, and managing structured data. It supports SQL for data manipulation and definition, advanced data types, extensibility through plugins, and features like transactions, views, stored procedures, and triggers.
6
+
7
+ ## Authentication
8
+
9
+ PostgreSQL uses a direct database connection model rather than API keys or OAuth. The primary method for remote client authentication is **password-based authentication** via a connection string.
10
+
11
+ ### Connection String Authentication
12
+
13
+ To connect, the following credentials are required:
14
+
15
+ - **Host**: The server hostname or IP address
16
+ - **Port**: The port PostgreSQL listens on (default: `5432`)
17
+ - **Database**: The name of the target database
18
+ - **Username**: The database user
19
+ - **Password**: The user's password
20
+
21
+ The general format for a PostgreSQL connection string (URI) is: `postgresql://[user[:password]@][host][:port][/dbname][?options]`
22
+
23
+ Example: `postgresql://user:password@localhost:5432/mydatabase`
24
+
25
+ ### SSL/TLS Encryption
26
+
27
+ For a connection to be known SSL-secured, SSL usage must be configured on both the client and the server before the connection is made. The `sslmode` parameter controls SSL behavior:
28
+
29
+ - `disable` — No SSL
30
+ - `require` — Encrypt the connection, but don't verify the server certificate
31
+ - `verify-ca` — Verify that the server is trustworthy by checking the certificate chain up to the root certificate stored on the client
32
+ - `verify-full` — Also verify that the server host name matches the name stored in the server certificate
33
+
34
+ Example with SSL: `postgresql://user:password@localhost:5432/mydatabase?sslmode=require`
35
+
36
+ When using SSL with client certificates, additional parameters include `sslcert`, `sslkey`, and `sslrootcert` to specify file paths for the client certificate, private key, and root CA certificate respectively.
37
+
38
+ ### Password Hashing Methods
39
+
40
+ The server may be configured to use different password verification schemes:
41
+
42
+ - **SCRAM-SHA-256**: The most secure password-based authentication method in PostgreSQL. It uses the Salted Challenge Response Authentication Mechanism (SCRAM) with the SHA-256 hashing function.
43
+ - **MD5**: Password is hashed with MD5 before transmission. Considered legacy.
44
+ - **Plain password**: Sent in clear text; only safe over SSL.
45
+
46
+ The hashing method is configured server-side and is typically transparent to the connecting client.
47
+
48
+ ## Features
49
+
50
+ ### Data Querying and Manipulation
51
+
52
+ Execute SQL queries to read, insert, update, and delete data. Supports complex queries with joins, subqueries, aggregations, window functions, common table expressions (CTEs), and full-text search.
53
+
54
+ ### Schema Management
55
+
56
+ Create and alter databases, schemas, tables, columns, indexes, constraints, and sequences. Supports a rich type system including JSON/JSONB, arrays, enums, geometric types, network address types, and user-defined types.
57
+
58
+ ### Stored Procedures and Functions
59
+
60
+ Define reusable server-side logic using PL/pgSQL or other procedural languages (PL/Python, PL/Perl, etc.). Functions can return scalar values, rows, or sets of rows and can be used within queries.
61
+
62
+ ### Transactions
63
+
64
+ Full ACID-compliant transaction support with configurable isolation levels (Read Committed, Repeatable Read, Serializable). Supports savepoints for partial rollbacks within a transaction.
65
+
66
+ ### Views and Materialized Views
67
+
68
+ Create virtual tables (views) based on queries for simplified data access. Materialized views store query results physically and can be refreshed on demand for performance optimization.
69
+
70
+ ### Triggers
71
+
72
+ Define automatic actions that execute before, after, or instead of INSERT, UPDATE, or DELETE operations on specific tables. Triggers are essentially callbacks at the database level that can execute a defined function before, after, or instead of identified operations on the table(s) you specify.
73
+
74
+ ### User and Permission Management
75
+
76
+ Create and manage database roles (users and groups). Grant or revoke privileges at the database, schema, table, column, or function level. Supports row-level security policies for fine-grained access control.
77
+
78
+ ### Extensions
79
+
80
+ PostgreSQL supports extensions that add functionality, such as PostGIS (geospatial), pg_trgm (trigram matching), hstore (key-value pairs), and many others. Extensions are installed per-database.
81
+
82
+ ### Import and Export
83
+
84
+ Copy data in bulk using the `COPY` command, which supports CSV and binary formats for efficient data loading and extraction.
85
+
86
+ ## Events
87
+
88
+ PostgreSQL provides two built-in mechanisms for event-driven data capture:
89
+
90
+ ### LISTEN/NOTIFY
91
+
92
+ NOTIFY provides a simple interprocess communication mechanism for a collection of processes accessing the same PostgreSQL database. A payload string can be sent along with the notification, and higher-level mechanisms for passing structured data can be built by using tables in the database to pass additional data from notifier to listener(s).
93
+
94
+ - Clients subscribe to named channels using the `LISTEN` command and receive notifications sent via `NOTIFY` or the `pg_notify()` function.
95
+ - The payload from the message can be any text, up to 8kB in length.
96
+ - Commonly combined with triggers to automatically emit notifications on INSERT, UPDATE, or DELETE events on specific tables.
97
+ - If a NOTIFY is executed inside a transaction, the notify events are not delivered until and unless the transaction is committed.
98
+ - It is crucial that an application using the PostgreSQL notification capabilities are capable of missing events. Notifications are only sent to connected client connections. If the listener disconnects, notifications during that time are lost.
99
+
100
+ ### Logical Replication (Change Data Capture)
101
+
102
+ Logical replication is a method of replicating data objects and their changes, based upon their replication identity (usually a primary key). Logical replication uses a publish and subscribe model with one or more subscribers subscribing to one or more publications on a publisher node.
103
+
104
+ - Captures all row-level changes (INSERT, UPDATE, DELETE) from specified tables via the Write-Ahead Log (WAL).
105
+ - Since version 9.4, PostgreSQL offers logical replication, and Postgres versions 10 and later feature the default 'pgoutput' plugin. Older versions require manually installing plugins like `wal2json` or `decoderbufs`.
106
+ - Requires `wal_level` to be set to `logical` on the server and the connecting user to have replication privileges.
107
+ - Uses replication slots to track what data has been consumed, ensuring no changes are missed even if the consumer disconnects temporarily.
108
+ - Table creation and modification steps are not captured by these events. Only DML operations are streamed.
109
+ - Many managed PostgreSQL services, including AWS RDS, Google Cloud SQL, and Azure Database, support Logical Replication.
package/logo.png ADDED
Binary file
package/package.json ADDED
@@ -0,0 +1,19 @@
1
+ {
2
+ "name": "@slates-integrations/postgresql",
3
+ "main": "src/index.ts",
4
+ "type": "module",
5
+ "scripts": {
6
+ "build": "bunx @vercel/ncc build src/index.ts -o dist -m -s",
7
+ "typecheck": "tsc --noEmit"
8
+ },
9
+ "dependencies": {
10
+ "@lowerdeck/error": "^1.1.0",
11
+ "@slates/provider": "1.0.0-rc.11",
12
+ "@types/node": "^20",
13
+ "zod": "^4.2"
14
+ },
15
+ "devDependencies": {
16
+ "typescript": "^5"
17
+ },
18
+ "version": "0.2.0-rc.6"
19
+ }
package/slate.json ADDED
@@ -0,0 +1,18 @@
1
+ {
2
+ "name": "@metorial/postgresql",
3
+ "description": "Query, insert, update, and delete data in PostgreSQL relational databases. Explore schemas and tables, manage schemas, tables, indexes, views, materialized views, and database roles, and poll tables for row changes using timestamp or incrementing columns.",
4
+ "categories": ["apis-and-http-requests"],
5
+ "skills": [
6
+ "execute SQL queries",
7
+ "manage database schemas",
8
+ "insert and update data",
9
+ "delete table rows",
10
+ "describe tables",
11
+ "create and alter tables",
12
+ "manage indexes",
13
+ "create and refresh views and materialized views",
14
+ "manage database roles",
15
+ "poll tables for row changes"
16
+ ],
17
+ "logoUrl": "https://provider-logos.metorial-cdn.com/postgresql.png"
18
+ }
package/src/auth.ts ADDED
@@ -0,0 +1,134 @@
1
+ import { SlateAuth } from '@slates/provider';
2
+ import { z } from 'zod';
3
+ import { postgresServiceError } from './lib/errors';
4
+
5
+ export let auth = SlateAuth.create()
6
+ .output(
7
+ z.object({
8
+ host: z.string().describe('PostgreSQL server hostname or IP address'),
9
+ port: z.number().describe('PostgreSQL server port'),
10
+ database: z.string().describe('Target database name'),
11
+ username: z.string().describe('Database username'),
12
+ password: z.string().describe('Database password'),
13
+ sslMode: z
14
+ .enum(['disable', 'require', 'verify-ca', 'verify-full'])
15
+ .describe('SSL connection mode'),
16
+ connectionString: z.string().describe('Full PostgreSQL connection URI')
17
+ })
18
+ )
19
+ .addCustomAuth({
20
+ type: 'auth.custom',
21
+ name: 'Connection String',
22
+ key: 'connection_string',
23
+
24
+ inputSchema: z.object({
25
+ connectionString: z
26
+ .string()
27
+ .describe(
28
+ 'PostgreSQL connection URI (e.g., postgresql://user:password@host:5432/dbname?sslmode=require)'
29
+ )
30
+ }),
31
+
32
+ getOutput: async ctx => {
33
+ let connStr = ctx.input.connectionString.trim();
34
+ let parsed = parseConnectionString(connStr);
35
+
36
+ return {
37
+ output: {
38
+ host: parsed.host,
39
+ port: parsed.port,
40
+ database: parsed.database,
41
+ username: parsed.username,
42
+ password: parsed.password,
43
+ sslMode: parsed.sslMode,
44
+ connectionString: connStr
45
+ }
46
+ };
47
+ }
48
+ })
49
+ .addCustomAuth({
50
+ type: 'auth.custom',
51
+ name: 'Connection Parameters',
52
+ key: 'connection_params',
53
+
54
+ inputSchema: z.object({
55
+ host: z.string().describe('PostgreSQL server hostname or IP address'),
56
+ port: z.number().default(5432).describe('PostgreSQL server port (default: 5432)'),
57
+ database: z.string().describe('Target database name'),
58
+ username: z.string().describe('Database username'),
59
+ password: z.string().describe('Database password'),
60
+ sslMode: z
61
+ .enum(['disable', 'require', 'verify-ca', 'verify-full'])
62
+ .default('require')
63
+ .describe('SSL connection mode')
64
+ }),
65
+
66
+ getOutput: async ctx => {
67
+ let { host, port, database, username, password, sslMode } = ctx.input;
68
+ let encodedPassword = encodeURIComponent(password);
69
+ let encodedUsername = encodeURIComponent(username);
70
+ let sslParam = sslMode !== 'disable' ? `?sslmode=${sslMode}` : '';
71
+ let connectionString = `postgresql://${encodedUsername}:${encodedPassword}@${host}:${port}/${database}${sslParam}`;
72
+
73
+ return {
74
+ output: {
75
+ host,
76
+ port,
77
+ database,
78
+ username,
79
+ password,
80
+ sslMode,
81
+ connectionString
82
+ }
83
+ };
84
+ }
85
+ });
86
+
87
+ let parseConnectionString = (
88
+ connStr: string
89
+ ): {
90
+ host: string;
91
+ port: number;
92
+ database: string;
93
+ username: string;
94
+ password: string;
95
+ sslMode: 'disable' | 'require' | 'verify-ca' | 'verify-full';
96
+ } => {
97
+ // Parse postgresql://user:password@host:port/dbname?sslmode=require
98
+ let url: URL;
99
+ try {
100
+ url = new URL(connStr);
101
+ } catch {
102
+ throw postgresServiceError(
103
+ 'Invalid PostgreSQL connection string format. Expected: postgresql://user:password@host:port/dbname'
104
+ );
105
+ }
106
+
107
+ if (url.protocol !== 'postgresql:' && url.protocol !== 'postgres:') {
108
+ throw postgresServiceError(
109
+ 'Invalid PostgreSQL connection string protocol. Use postgresql:// or postgres://.'
110
+ );
111
+ }
112
+
113
+ let sslModeParam = url.searchParams.get('sslmode') || 'disable';
114
+ let validSslModes = ['disable', 'require', 'verify-ca', 'verify-full'] as const;
115
+ if (!validSslModes.includes(sslModeParam as (typeof validSslModes)[number])) {
116
+ throw postgresServiceError(
117
+ `Unsupported sslmode "${sslModeParam}". Supported values are disable, require, verify-ca, and verify-full.`
118
+ );
119
+ }
120
+
121
+ let port = url.port ? parseInt(url.port, 10) : 5432;
122
+ if (!Number.isInteger(port) || port <= 0 || port > 65535) {
123
+ throw postgresServiceError('Invalid PostgreSQL port in connection string.');
124
+ }
125
+
126
+ return {
127
+ host: url.hostname || 'localhost',
128
+ port,
129
+ database: url.pathname.replace(/^\//, '') || 'postgres',
130
+ username: decodeURIComponent(url.username || 'postgres'),
131
+ password: decodeURIComponent(url.password || ''),
132
+ sslMode: sslModeParam as (typeof validSslModes)[number]
133
+ };
134
+ };
package/src/config.ts ADDED
@@ -0,0 +1,16 @@
1
+ import { SlateConfig } from '@slates/provider';
2
+ import { z } from 'zod';
3
+
4
+ export let config = SlateConfig.create(
5
+ z.object({
6
+ defaultSchema: z
7
+ .string()
8
+ .default('public')
9
+ .describe('Default schema to use for queries when not explicitly specified'),
10
+ queryTimeout: z.number().default(30000).describe('Query timeout in milliseconds'),
11
+ maxRows: z
12
+ .number()
13
+ .default(1000)
14
+ .describe('Maximum number of rows to return from queries by default')
15
+ })
16
+ );
package/src/index.ts ADDED
@@ -0,0 +1,36 @@
1
+ import { Slate } from '@slates/provider';
2
+ import { spec } from './spec';
3
+ import {
4
+ executeQuery,
5
+ listTables,
6
+ describeTable,
7
+ insertRows,
8
+ updateRows,
9
+ deleteRows,
10
+ manageTable,
11
+ manageIndexes,
12
+ listSchemas,
13
+ manageRoles,
14
+ manageSchemas,
15
+ manageViews
16
+ } from './tools';
17
+ import { tableChanges, inboundWebhook } from './triggers';
18
+
19
+ export let provider = Slate.create({
20
+ spec,
21
+ tools: [
22
+ executeQuery,
23
+ listTables,
24
+ describeTable,
25
+ insertRows,
26
+ updateRows,
27
+ deleteRows,
28
+ manageTable,
29
+ manageIndexes,
30
+ listSchemas,
31
+ manageRoles,
32
+ manageSchemas,
33
+ manageViews
34
+ ],
35
+ triggers: [inboundWebhook, tableChanges]
36
+ });