feat(slack): add the Slack Web API SDK - #551
Merged
Merged
Conversation
Mkassabov
force-pushed
the
feat/slack-sdk
branch
from
September 7, 2026 12:17
72db3b1 to
7fb1fa9
Compare
Contributor
|
Install the packages built from this commit: Distilled@distilled.cloud/core bun add https://pkg.ing/@distilled.cloud/core/7fb1fa9@distilled.cloud/aws bun add https://pkg.ing/@distilled.cloud/aws/7fb1fa9@distilled.cloud/axiom bun add https://pkg.ing/@distilled.cloud/axiom/7fb1fa9@distilled.cloud/azure bun add https://pkg.ing/@distilled.cloud/azure/7fb1fa9@distilled.cloud/cloudflare bun add https://pkg.ing/@distilled.cloud/cloudflare/7fb1fa9@distilled.cloud/coinbase bun add https://pkg.ing/@distilled.cloud/coinbase/7fb1fa9@distilled.cloud/discord bun add https://pkg.ing/@distilled.cloud/discord/7fb1fa9@distilled.cloud/expo-eas bun add https://pkg.ing/@distilled.cloud/expo-eas/7fb1fa9@distilled.cloud/fly-io bun add https://pkg.ing/@distilled.cloud/fly-io/7fb1fa9@distilled.cloud/forgejo bun add https://pkg.ing/@distilled.cloud/forgejo/7fb1fa9@distilled.cloud/gcp bun add https://pkg.ing/@distilled.cloud/gcp/7fb1fa9@distilled.cloud/github bun add https://pkg.ing/@distilled.cloud/github/7fb1fa9@distilled.cloud/hetzner bun add https://pkg.ing/@distilled.cloud/hetzner/7fb1fa9@distilled.cloud/kubernetes bun add https://pkg.ing/@distilled.cloud/kubernetes/7fb1fa9@distilled.cloud/mongodb-atlas bun add https://pkg.ing/@distilled.cloud/mongodb-atlas/7fb1fa9@distilled.cloud/neon bun add https://pkg.ing/@distilled.cloud/neon/7fb1fa9@distilled.cloud/planetscale bun add https://pkg.ing/@distilled.cloud/planetscale/7fb1fa9@distilled.cloud/posthog bun add https://pkg.ing/@distilled.cloud/posthog/7fb1fa9@distilled.cloud/prisma-postgres bun add https://pkg.ing/@distilled.cloud/prisma-postgres/7fb1fa9@distilled.cloud/railway bun add https://pkg.ing/@distilled.cloud/railway/7fb1fa9@distilled.cloud/stripe bun add https://pkg.ing/@distilled.cloud/stripe/7fb1fa9@distilled.cloud/supabase bun add https://pkg.ing/@distilled.cloud/supabase/7fb1fa9@distilled.cloud/turso bun add https://pkg.ing/@distilled.cloud/turso/7fb1fa9@distilled.cloud/typesense bun add https://pkg.ing/@distilled.cloud/typesense/7fb1fa9@distilled.cloud/vercel bun add https://pkg.ing/@distilled.cloud/vercel/7fb1fa9@distilled.cloud/workos bun add https://pkg.ing/@distilled.cloud/workos/7fb1fa9 |
github-merge-queue
Bot
removed this pull request from the merge queue due to a manual request
Sep 7, 2026
Add @distilled.cloud/forgejo: one service module per API tag, compiled from the Swagger 2.0 template Forgejo ships at a release tag. The spec-mirror-forgejo fetch script (stacks/distilled-submodules/spec-repos/ forgejo) pins the tag and fills in the two server-side placeholders the way a root-mounted instance renders them. Credentials carry the instance URL alongside the token, since a self-hosted forge has no default API root; the protocol sends Forgejo's `token` authorization scheme. Patches type what the document leaves out: the 500 an organization delete answers while it still owns repositories, the 403s the list endpoints answer for a non-member, the 409 an organization repository create answers for a taken name, the path/body `username` clash on adminCreateOrg, and the always-present members of the response definitions the Go structs never omit.
Smithy-pointer patches now apply in finalizeConvert (the pipeline #545 introduced) instead of a per-slug loop in convert; the one such patch targets the operation by its verbNoun name (DeleteOrg).
Slack has no OpenAPI document (slack-api-specs froze in 2020), but every
docs.slack.dev reference page serves a structured JSON twin by appending
.json to the URL. The pipeline mirrors cloudflare's committed-docs flow:
scripts/download-docs.ts crawl the method index + 317 method JSON twins
(plus scopes/types/objects lists) into specs/
scripts/convert.ts method pages -> per-family OpenAPI slices ->
34 Smithy models via core's shared converter
scripts/generate.ts Smithy models -> src/services (317 operations)
Provider shape:
- ok/error envelope at HTTP 200: SlackProtocol dispatches the error slug
(auth slugs -> Unauthorized, rate_limited -> SlackRateLimited with
Retry-After, server hiccups -> retryable 5xx classes, everything else
-> SlackError carrying the slug; per-method slugs are listed in each
operation's doc comment)
- form-urlencoded is the default input encoding (JSON only where the
docs declare json_input_supported - verified live that JSON bodies
are ignored without an Authorization header); the protocol serializes
Slack-style: ID arrays comma-joined, rich values JSON-encoded
- tokenless OAuth exchange methods work via an empty-token credential
(the Authorization header is omitted)
- admin.analytics.getFile's gzipped file answer returns as raw bytes
Verified live against slack.com/api: api.test round-trip, form + query +
JSON encodings, and the error mapping (not_authed/invalid_auth ->
Unauthorized, invalid_code -> SlackError).
…eric code Core's ErrorMatcher codes are numeric; Slack's are string slugs. The slug already rides in the matcher's message argument, so patch-declared per-op classes match on status/message. Fixes the strict (--noCheck false) CI typecheck.
Slack's cursor convention (pass cursor, follow
response_metadata.next_cursor, empty string = done) maps directly onto
core's paginateCursor traversal:
- convert.ts stamps smithy.api#paginated on every method that takes a
cursor arg and has an identifiable items list (the sole top-level
array member of its documented output, plus explicit overrides for
conversations.history/replies whose outputs carry several arrays) —
42 operations across 11 families
- the typed response_metadata.next_cursor struct is modeled uniformly
on every cursor op's output (the docs model it on only ~2/3, some as
an opaque ref), so the traversal has a cursor to follow and callers
can read it
- src/pagination.ts supplies the slackPaginate strategy; the plain
SlackProtocol already keeps response_metadata (a modeled member), so
no separate paginated protocol is needed
Cursor methods whose docs model no items list (admin.emoji.list's map,
admin.conversations.getTeams' missing member) stay plain operations
rather than guessing — patch territory.
Rebased on main after #545/#548/#549. convert ends in finalizeConvert. Operation names are verbNoun: a camelCase Slack action is used as-is (chat.postMessage → postMessage); a bare action is handed to the converter as Object_action so its policy orders it (admin.apps.permissions.add → addAppsPermissions, conversations.archive → archiveConversation). package.json uses the named pnpm catalogs, and slack is registered as a blocked spec repo (the docs JSON twins are committed in-repo).
Mkassabov
force-pushed
the
feat/slack-sdk
branch
from
September 7, 2026 12:36
7fb1fa9 to
ee33cd5
Compare
Base automatically changed from
feat/forgejo-sdk
to
feat/google-workspace-sdk
September 7, 2026 12:42
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds
@distilled.cloud/slack— a full Slack Web API SDK (317 operations across 34 service modules), generated from the JSON twins of the docs.slack.dev method reference.Slack has no OpenAPI document (slack-api-specs froze in 2020), but every docs.slack.dev reference page serves a structured JSON twin by appending
.jsonto the URL. The pipeline mirrors cloudflare's committed-docs flow:scripts/download-docs.ts— crawls the method index + 317 method JSON twins (plus scopes/types/objects lists) intospecs/(committed). Example blocks are stripped at download time: they embed realistic-looking third-party credentials that trip push protection, and the converter never reads them.scripts/convert.ts— method pages → per-family OpenAPI slices → 34 Smithy models via core's sharedconvertOpenApiToSmithy. Named refs ({"schema": "channel"}) have no JSON twins upstream, so ID-like names (mined from the corpus —channelis always the ID string) inline asstring; object refs inline as loose Documents, enrichable later via patches.scripts/generate.ts— the provider spec for the shared smithy→SDK compiler. Wire-verbatim snake_case args; per-method error slugs and required scopes in every operation's doc comment.Provider shape
SlackProtocoldispatches theerrorslug — auth slugs →Unauthorized,rate_limited→SlackRateLimited(honoringRetry-After), server hiccups → retryable 5xx classes, everything else →SlackErrorcarrying the slug.json_input_supported: true. Verified live that Slack ignores JSON bodies without an Authorization header, which is exactly what the tokenless OAuth exchange methods send. The protocol serializes Slack-style: ID arrays comma-joined, rich values JSON-encoded (core's bracket notation is not Slack's dialect).oauth.v2.access,openid.connect.token, …) works via an empty-token credential — the Authorization header is omitted.admin.analytics.getFile's gzipped-file answer returns as raw bytes.Verification
Live against
slack.com/api:api.testround-trip; form, query, and JSON encodings all parse server-side; error mapping (not_authed/invalid_auth→Unauthorized,invalid_code→SlackError; tokenlessoauth.v2.accessproves the form path transmits args). Both tsconfigs typecheck clean; package is wired into the root build andgenerate-all.Known gaps (follow-ups)
unknown) where Slack's docs don't structure them (message, conversation, user, …) — patch territory.response_metadata.next_cursorstays a plain response member).Supersedes #453 (same commits, on an
originbranch) rebased onto the convert-time patch / verbNoun pipeline from #545/#548/#549. Operation names are now verbNoun (postMessage,archiveConversation,listUsers,uploadFile).