SupDesk SDK のご紹介
本格的なプロダクトを開発していると、いずれ統合レイヤーを書くことになります。受信箱から読み込むスクリプト、ボードを同期する cron ジョブ、自社 UI からフィードバックを登録するエンドポイントなどです。キーボードに向かっているときは SupDesk コンソールが最適ですが、自動化したいと思った瞬間から API が必要になり、API の利便性はそれを操作するクライアントの出来に左右されます。
本日、4 つの SDK をリリースします。
SDK のラインナップ
- JavaScript / TypeScript — npm の
supdesk。ランタイム依存関係ゼロで、Node 18+、Deno、Bun、Cloudflare Workers 上でそのまま動作します。 - Python — PyPI の
supdesk。単一の httpx コアを共有する同期のSupDeskクライアントと非同期のAsyncSupDeskクライアント。 - Go —
github.com/rabinapps/supdesk-go。標準ライブラリのみで構成されているため、GOOS=wasip1による Cloudflare Workers を含め、Go 1.23+ が動作するあらゆる環境でビルド可能です。 - Dart — pub.dev の
supdesk。dio をベースに構築されているため、インターセプター、CancelToken、プロキシアダプターがすべて想定通りに機能します。
インストール
npm install supdeskpip install supdeskgo get github.com/rabinapps/supdesk-godependencies:
supdesk: ^0.1.01 つの API、4 つの言語
これらの SDK は単に 4 つの別個のラッパーではありません。すべての言語で同じセマンティクスを持つ同一の API です。いずれか 1 つの言語で投稿を読み込む方法を理解していれば、4 つすべてで同様に操作できます。
自動ページネーション。 list() は非同期イテラブルでもあるページを返します。for await で全ページを巡回することも、必要なときに最初のページだけを取得することも可能です。
型付きリソース。 投稿、フィードバック、チェンジログエントリー、メッセージ、ウェイトリスト登録、ベータプログラムとテスター、ヘルプセンターの文言・カテゴリーなど、各リソースには想定通りのメソッドと型付きパラメーターが備わっており、タイポは本番環境ではなくコンパイル時に検知されます。
型付きエラー。 すべてのエラーは単一のベースクラス(JS/Python では SupDeskError、Go では APIError、Dart では SupDeskException)を継承しています。そのため、1 つの catch ですべてを処理しつつ、instanceof や errors.As で特定のケースに絞り込むことができます。
Webhook。 constructEventFromRequest、construct_event_from_headers、ConstructEvent、constructEventFromHeaders は定数時間で SupDesk の署名を検証するため、受信側が処理するデータの信頼性を確保できます。
組み込みのレジリエンス。 すべてのクライアントは指数バックオフとジッターで再試行を行い、Retry-After を尊重します。また、すでに受理された可能性のある従量課金対象の POST を再試行することはありません。不安定なネットワークによってユーザーのチケットが二重送信される心配はありません。
サーバーサイド専用設計
SupDesk API キーはプロジェクト全体として認証を行うため、SDK はブラウザー上での実行を拒否します。JS および Dart のコンストラクターは DOM やクライアントビルドを検出すると例外をスローし、README にはその理由が明記されています。キーは、自身が管理するエンドポイントの背後にあるサーバーサイドの環境変数に保管してください。
補足として知っておくべき 2 つの点:読み取りは全プランで機能しますが、書き込み(POST/PATCH/DELETE)には有料プランが必要です。また、キーはプロジェクトスコープであるため、環境ごとに独自のキーを割り当てれば、他の環境に影響を与えることなく 1 つだけを失効させることができます。
SupDesk の適用領域
これらの SDK は、SupDesk SaaS 統合ガイド のバックエンド側の役割を果たします。自社システムにサポート機能を埋め込みたいプロダクト向けに、マルチテナントサポート、API アクセス、Webhook を提供します。完全なリファレンスは API ドキュメント をご覧ください。
はじめる
ワークスペース設定 → API キー から API キーを取得し、お使いのスタックに対応するクライアントをインストールして、このページのクイックスタートを実行してください。その後、リポジトリをクローンして README をご覧ください。
バックエンド統合のためのサーバーサイドSDK
各SDKのGitHubリポジトリから取得したライブコード例。
import { SupDesk } from "supdesk";
const supdesk = new SupDesk({ apiKey: process.env.SUPDESK_API_KEY! });
// Auto-pages: iterating walks every page for you.
for await (const submission of await supdesk.submissions.list({
status: "open",
})) {
console.log(submission.title);
}
await supdesk.submissions.create({
type: "bug",
title: "Export button does nothing",
email: "user@example.com",
body: "Clicking Export on the reports page has no effect.",
});from supdesk import SupDesk
supdesk = SupDesk() # api_key=... or $SUPDESK_API_KEY
# Auto-pages: iterating walks every page for you.
for submission in supdesk.submissions.list(status="open"):
print(submission.title)
supdesk.submissions.create(
type="bug",
title="Export button does nothing",
email="user@example.com",
body="Clicking Export on the reports page has no effect.",
)import "github.com/rabinapps/supdesk-go/supdesk"
client, err := supdesk.New(os.Getenv("SUPDESK_API_KEY"))
if err != nil {
log.Fatal(err)
}
page, err := client.Submissions.List(ctx, supdesk.SubmissionsListParams{
Status: ptr("open"),
})
if err != nil {
return err
}
// Auto-pages: All walks every page for you.
for sub, err := range page.All(ctx) {
if err != nil {
return err
}
fmt.Println(sub.Title)
}
_, err = client.Submissions.Create(ctx, supdesk.SubmissionsCreateParams{
Type: supdesk.SubmissionTypeBug,
Title: "Export button does nothing",
Email: "user@example.com",
Body: "Clicking Export on the reports page has no effect.",
})import 'dart:io';
import 'package:supdesk/supdesk.dart';
final supdesk = SupDesk(apiKey: Platform.environment['SUPDESK_API_KEY']!);
// Auto-pages: the stream walks every page for you.
final page = await supdesk.submissions.list(status: PostStatus.open);
await for (final submission in page.autoPaging()) {
print(submission.title);
}
await supdesk.submissions.create(
type: SubmissionType.bug,
title: 'Export button does nothing',
email: 'user@example.com',
body: 'Clicking Export on the reports page has no effect.',
);