This is a WASM-based Foreign Data Wrapper (FDW) for integrating Slack data into PostgreSQL through Supabase Wrappers.
The Slack FDW allows querying Slack workspace data directly from PostgreSQL using SQL. It supports all major Slack entities:
- Users: Workspace members with detailed profile information
- User Groups: User groups (aka user groups) with metadata
- User Group Members: Relationships between users and groups
- Messages: Channel messages with thread support
- Channels: Public and private channels in the workspace
- Files: Files shared in workspace channels
- Team Info: Details about the Slack workspace
This FDW is implemented in Rust and compiled to WebAssembly (WASM) to run within PostgreSQL using Supabase Wrappers. It follows a layered architecture:
+------------------------------------------+
| PostgreSQL (SQL queries) |
+------------------------------------------+
| Supabase Wrappers (WASM host interface) |
+------------------------------------------+
| Slack FDW (Resource handling) |
| |-- API Layer (Slack API calls) |
| |-- Data Models (Response structures) |
| |-- Query Push (Filter optimization) |
+------------------------------------------+
| Slack API (HTTP endpoints) |
+------------------------------------------+
- src/lib.rs: Core FDW implementation with control flow
- src/models.rs: Data structures for Slack API responses
- src/api.rs: Test utilities for Slack API interactions
- wit/world.wit: WebAssembly interface definitions
- Cargo.toml: Rust dependencies and build configuration
All entity models are defined in models.rs:
-
Users:
Userstruct with profile, status, role properties- Mapping to PostgreSQL via
user_to_row() - Support for filtering, sorting, and pagination
-
User Groups:
UserGroupstruct with metadata and user lists- Mapping via
usergroup_to_row() - Supports filtering by team_id and sorting
-
User Group Members:
UserGroupMembershipstruct for group-user relationships- Many-to-many relationship handling
- Pagination support
-
Messages:
Messagestruct with threading and reaction support- Channel-based filtering (
channel_idrequired) - Pagination with cursors for large result sets
-
Channels:
Channelstruct with metadata- Support for filtering by type (public/private)
- Pagination support
-
Files:
Filestruct with metadata and permissions- Filtering by user, channel, and date ranges
- Pagination support
-
Team Info:
TeamInfostruct with workspace details- Single-row resource with domain and icon metadata
-
Request Handling:
- SQL queries map to resource types via table options
- WHERE clauses are analyzed for query pushdown
- PostgreSQL types are mapped to Slack API parameters
-
API Communication:
- Authenticated requests to Slack API endpoints
- Rate limiting and error handling
- Response parsing into typed Rust structures
-
Result Processing:
- Pagination handling for large result sets
- Structure conversion to PostgreSQL rows
- Null handling for optional fields
The FDW implements query pushdown for:
| Resource | Supported Filters | Sorting | Limit/Offset |
|---|---|---|---|
| messages | channel_id, oldest, latest | No | Yes* |
| users | name, email, team_id | name, real_name, email | Yes |
| usergroups | team_id, include_disabled | name, handle, date_create, date_update | Yes |
| usergroup_members | (no filter support) | No | Yes |
| channels | types (public/private) | No | Yes* |
| files | channel_id, user_id, ts_from, ts_to | No | No |
| team-info | (no filter support) | No | No |
* Pagination is supported through cursor-based pagination from the Slack API
CREATE SERVER slack_server
FOREIGN DATA WRAPPER wasm_wrapper
OPTIONS (
fdw_package_url 'https://github.com/supabase/wrappers/releases/download/wasm_slack_fdw_v0.0.6/slack_fdw.wasm',
fdw_package_name 'supabase:slack-fdw',
fdw_package_version '0.0.6',
fdw_package_checksum '(checksum will be generated on release)',
api_token 'xoxb-your-slack-token',
workspace 'your-workspace-name'
);-- Users table
CREATE FOREIGN TABLE slack.users (
id text,
name text,
real_name text,
display_name text,
email text,
is_admin boolean,
is_bot boolean,
status_text text,
team_id text
)
SERVER slack_server
OPTIONS (
resource 'users'
);
-- Messages table
CREATE FOREIGN TABLE slack.messages (
ts text,
user_id text,
channel_id text,
text text,
thread_ts text,
reply_count integer
)
SERVER slack_server
OPTIONS (
resource 'messages'
);
-- Channels table
CREATE FOREIGN TABLE slack.channels (
id text,
name text,
is_private boolean,
created bigint,
creator text
)
SERVER slack_server
OPTIONS (
resource 'channels'
);
-- Files table
CREATE FOREIGN TABLE slack.files (
id text,
name text,
title text,
mimetype text,
size bigint,
url_private text,
user_id text,
created bigint
)
SERVER slack_server
OPTIONS (
resource 'files'
);
-- Team info table
CREATE FOREIGN TABLE slack.team_info (
id text,
name text,
domain text,
email_domain text
)
SERVER slack_server
OPTIONS (
resource 'team-info'
);
-- User groups table
CREATE FOREIGN TABLE slack.usergroups (
id text,
team_id text,
name text,
handle text,
description text,
is_external boolean,
date_create bigint,
date_update bigint,
date_delete bigint,
auto_type text,
created_by text,
updated_by text,
deleted_by text,
user_count integer,
channel_count integer
)
SERVER slack_server
OPTIONS (
resource 'usergroups'
);
-- User group members table
CREATE FOREIGN TABLE slack.usergroup_members (
usergroup_id text,
usergroup_name text,
usergroup_handle text,
user_id text
)
SERVER slack_server
OPTIONS (
resource 'usergroup_members'
);-- Get all users
SELECT * FROM slack.users;
-- Get messages from a specific channel
SELECT * FROM slack.messages WHERE channel_id = 'C01234ABCDE';
-- Get all channels
SELECT * FROM slack.channels;
-- Get files uploaded by a specific user
SELECT * FROM slack.files WHERE user_id = 'U01234ABCDE';
-- Get team information
SELECT * FROM slack.team_info;
-- Get all user groups
SELECT * FROM slack.usergroups;
-- Get members of a specific user group
SELECT * FROM slack.usergroup_members WHERE usergroup_id = 'S01234ABCDE';| Option | Description | Required |
|---|---|---|
| api_token | Slack OAuth token (starts with xoxp- or xoxb-) | Yes |
| api_token_id | Vault key ID for Slack token (alternative to api_token) | Yes (if api_token not provided) |
| workspace | Slack workspace name for logging | No |
| Option | Description | Required |
|---|---|---|
| resource | Resource type to query (users, messages, channels, etc.) | Yes |
This FDW implements rate limiting handling according to Slack's guidelines:
- Automatic retry with backoff for rate-limited requests (429 responses)
- Respects Retry-After headers when provided
- Batch size limits to avoid excessive API usage
Each entity type requires specific OAuth scopes:
| Entity Type | Required Scopes | Error If Missing |
|---|---|---|
| users | users:read |
"The token used is not granted the required scopes" |
| users (emails) | users:read.email |
"missing_scope" on email fields |
| usergroups | usergroups:read |
"missing_scope" when querying user groups |
| usergroup_members | usergroups:read |
"missing_scope" when querying user group members |
| channels | channels:read |
"missing_scope" when querying channels |
| messages | channels:history, channels:read |
"missing_scope" when querying messages |
| files | files:read |
"missing_scope" when querying files |
| team-info | team:read |
"missing_scope" when querying team info |
| reactions | reactions:read |
Missing reactions data in responses |
For production use, we recommend installing your app with all of these scopes from the beginning to avoid permission issues later.
cargo build --target wasm32-wasicargo test- Add model structs in
models.rs - Implement row conversion method in
lib.rs(entity_to_row) - Implement fetch method in
lib.rs(fetch_entity) - Update resource handling in
begin_scan,iter_scan,re_scan, andend_scan
If extending or modifying this FDW, consider:
- API Changes: Slack API evolves - check latest endpoints and fields
- Query Pushdown: Add new filter conditions when possible
- Error Handling: Rate limiting and API errors require careful handling
- Response Mapping: Ensure consistent handling of optional fields
- Pagination: All list operations should support pagination
All core features are implemented. Future enhancements could include:
- Support for more advanced filters
- Additional Slack entities (emoji, stars, etc.)
- Cache support for performance optimization
- Statistics for query optimization