隆重推出 Forge:用於生成 SDK、CLI、文件等的開源生成流水線

Dimitri Mitropoulos、Matt “TK” Taylor和Samuel Macleod

閱讀時間:6 分鐘

這篇文章亦提供 English、Deutsch、Español、Español (Latinoamérica)、Français、Italiano、日本語、한국어、简体中文、Português和Nederlands.

今天,我們推出 Forge——一種生成 SDK、CLI、文件和函式庫的全新方式。Forge 是一款開源的可插拔生成流水線,任何人都可以免費部署和執行。

Forge 尚處於早期階段,但已經能夠生成 cf CLI 所需的輸出,並將在未來幾個月內為 Cloudflare 的 API 文件、SDK 以及更多內容提供支援。

我們構建 Forge 是因為我們自己需要它,以便將 AI 智慧體視為我們的客戶。現在,我們將其開源,因為我們認為每個人都應該能夠生成 AI 智慧體所需的所有介面。過去,只有面向開發者的產品才需要 CLI、API SDK 和 MCP 伺服器,以及與之配套的出色文件。如今,這些已成為每個產品的基本門檻。

我們的 API 超出了生成器的處理能力

Cloudflare 的 API 擁有超過 3,500 個操作,驅動這些 API 的數百個服務以多種語言編寫,包括 Rust、Go、TypeScript 和 Python。當我們著手為整個 Cloudflare API(包括 SDK 和 API 文件)建構一個 CLI 時,我們需要一個能夠應對這種規模的程式碼生成流水線。該流水線需要足夠靈活,能夠跨語言工作,並適應我們各個工程團隊的運作方式。

我們需要一種方法來減少團隊之間的協調開銷。當 Cloudflare 產品團隊進行 API 變更時,他們需要在合併變更並發佈給客戶之前,能夠使用即將生成的 Cloudflare 全域 CLI、SDK 和文件網站的預覽版本。我們需要一種方式確保他們不會無意中破壞生成流水線。我們還需要一個可以擴展的系統,用於生成不僅限於 SDK 的內容——從 Cap'n Web 到 MCP,乃至更多。

我們需要一個工具,來針對數百個程式碼庫中的每一個 Pull 請求產生預覽。

我們試用過幾款試圖解決此問題的託管產品,並在生產中依賴了其中一些。但沒有一款真正為我們解決了這個問題,部分甚至已經完全關閉。一個團隊合併了一個無意中破壞生成流水線的變更,另一個團隊在發佈時才發現問題,我們浪費了太多時間在無法掌控的託管工具中逆流而上,協調團隊與供應商之間的變更。

這就是我們開始建構 Forge 的起因。

Forge 旨在解決所有這些問題:它在 CI 中執行,在每個團隊的 API 倉庫上執行,就像我們的 AI 程式碼審查員和測試流水線一樣。它對每次變更進行 lint 檢查,然後生成 CLI、文件和 SDK 的預覽版本,僅突出顯示您的變更,您可以安裝並測試。這與 Workers Previews 的理念相同:為每次變更提供完整的預覽版本建構,但應用於大規模的 SDK 生成——即使 API 介面分佈在數百個服務和倉庫中也不例外。這就是 Forge 致力於實現的目標。

Forge 可幫助您在 CI 中的問題導致下游問題之前偵測到它們。

Forge 轉換器可以生成任何內容,包括 Cap'n Web

Cloudflare 比大多數公司更有理由需要一個能夠遠超常規語言目標的生成器。Cap'n Web 是 Cloudflare 的 RPC 系統,它讓 TypeScript 可以像呼叫本地方法一樣呼叫遠端 API。

// Authenticate, get the user's ID, fetch their profile, and fetch every friend's profile...
let authed = api.authenticate(apiToken);
let profile = api.getUserProfile(authed.getUserId());
let friends = authed.getFriendIds().map(id => api.getUserProfile(id));

// ...in a *single* request
let [me, myFriends] = await Promise.all([profile, friends]);

借助 Forge,可以取得一份 OpenAPI 規格並直接生成 Cap'n Web。這為從 Workers 到其他 API 的繫結生成打開了大門。畢竟,Workers 執行環境中的繫結是作為公開 RPC 方法的 Workers 來實作的。

這並非 Cap'n Web 獨有的需求:您可能已經依賴的其他熱門工具也有同樣的需求。如果您使用 TanStack Query,理想情況下,您會希望能夠直接從 API 本身生成適合您應用程式的 TanStack Query 繫結。始終保持最新,始終根據您的真實 API 進行驗證。生成 Zod 或 Valibot 結構描述、MCP 伺服器,或任何其他讓 API 更易消費的內容,道理也是一樣。

這之所以可行,是因為 Forge 程式碼生成器足夠靈活。它們天生就是為了將資訊從一個輸出流向另一個輸出而建構的。

原始的 OpenAPI 定義內建在 TypeScript SDK 中,用於產生 cf CLI 和 Cap'n Web 規範。

Forge 轉換器可以鏈式呼叫:從其他輸出生成輸出

我們將 Forge 設計成可插拔的,並支援多種輸入和輸出類型。Forge 提供 CLI、SDK 和文件生成器,但沒有什麼能阻止您新增一個生成特定函式庫套件甚至完整儀表板或應用程式的轉換器。Forge 目前支援 OpenAPI 作為輸入類型,但我們的設計允許未來支援 AsyncAPI、GraphQL、Cap'n Proto、Protobuf 或其他輸入格式。

這不僅僅是相容性問題:它讓您可以鏈接目標,使用一個目標的輸出來生成其他目標。這在其他生成器中很常見,例如 CLI 和 Terraform 目標從 Go SDK 生成。然而,現有工具往往缺乏的一點(也是 Forge 所提供的)是讓使用者能夠自主控制這種串聯機制的能力。

Forge 可以鏈結目標以產生新的輸出。

我們自己也需要這個解決方案,因為我們的 cf CLI 是用 TypeScript 編寫的,而其他 SDK 生成器通常不會將 TypeScript 作為 CLI 的鏈式來源。但我們自身的處境讓我們認識到了更深層的問題:為什麼 SDK 生成器工具要替您做這個決定?也許您是一個 Python 團隊,希望 CLI 也用 Python 編寫。

如果您在想「這有什麼關係,但它是不是用 Python 寫的又有誰在乎呢?反正程式碼是自動生成的」——原因在於 CLI 是不同的。CLI 往往會引入一些只在本地有意義的行為,這些行為在 SDK 中並不合適。這些行為需要手動編寫,因為它們本質上不是由任何 API 呼叫支撐的。例如,cf CLI 有 cf dev 和 cf build 這樣的命令,它們是在其餘生成輸出之上額外新增的。這些命令需要呼叫其他套件(如 Vite)中的 TypeScript API。

現在,我們再把文件加入其中。如果您純粹從 OpenAPI 規格生成 CLI 和文件,您如何將那些手寫命令重新融入文件,使它們能與其餘內容一起得到記錄?

我們目前找不到能做到這一點的現有工具,然而這正是我們為 cf 所需要的。所以我們將它內建到 Forge 中。

在不影響使用者的情況下變更您的 API

Forge 也在為我們更好的 API 版本管理奠定基礎。Cloudflare 的 v4 API 10 年來一直是我們 API 的唯一主要版本。在此期間,表面上我們似乎沒有發佈任何新的主要版本,但按照 SemVer 的定義,我們其實進行了不少值得新主要版本的變更。與此同時,API 中的多個操作帶有內部的「v2」標籤或「beta」識別碼,而這些標籤早已超出了產品生命週期的那個階段。

經歷了這麼多年的 v4 API,我們深知一個全新的大版本 v5 會讓很多客戶無法跟進。這就是為什麼在 Forge 持續發佈產出的同時,我們正在研究一種 API 版本管理方案,使我們能夠發佈新的主要 API 版本,而不破壞舊的用戶端或 SDK。

關於我們的 SDK(包括 TypeScript、Rust、Python、Go、PHP 和 Terraform),我們很快會有更多消息分享。尤其是 Terraform。我們知道升級任何 Terraform 提供商都有其獨特的嚴格性要求,我們將為 Terraform 的過渡傾注格外細緻的心力。

關鍵工具應向所有人開放

我們相信,為 API建構工具是網際網路的核心組成部分,您應該能夠在無需 SaaS 產品的情況下做到這一點。您應該擁有自己的 SDK、CLI 和文件。如果您自己生成這些,那麼你應該能夠在任何地方、以任何方式、免費地做任何您想做的事。

這就是為什麼我們在寬鬆的 Apache 2.0 授權下將 Forge 以開源方式發佈。我們希望大家能加入我們的這段旅程,共同貢獻。

或者,如果您希望將一切保留為私有,那也完全沒問題!您可以出於任何目的、進行自訂修改、免費、私下執行 Forge。

致謝:本專案的實現,亦歸功於 Dan Carter、Steven Chong、Krishna Paritala 以及 Shelley Jones 在設計與實作上的付出。