Typebase:把整個後端塞進一個 TypeScript 資料夾
GitHub (typebase-io/monorepo) · 2026-08-30
一個名為 Typebase 的後端框架以 Show HN 形式登上 Hacker News:它把資料庫 schema、伺服器端 action、身份驗證設定全部收進應用程式裡的單一 typebase/ 資料夾,不需要額外的後端 repo 或後台 dashboard。專案目前在 GitHub 上為 typebase-io/monorepo,累積 41 顆星、2 個 fork、178 次 commit,採 MIT 授權。框架建立在 Drizzle ORM、oRPC 與 better-auth 之上。
核心設計
Typebase 的主張是型別從資料庫一路貫穿到前端:開發者在 typebase/db/schema.ts 定義資料表,在 typebase/actions 下寫 query 與 mutation,CLI 會據此產生型別安全的用戶端呼叫介面。安裝與初始化流程如下:
npm install typebase-io
npm install -D typebase-io-cli
npx typebase-io-cli init # 產生 typebase/ 目錄與範例
npx typebase-io-cli codegen # 依 schema/action 變更重新產生型別
npx typebase-io-cli deploy devServer action 的寫法接近 oRPC 的 procedure 定義,例如查詢單筆資料:
export const getOne = action
.input(z.object({ id: z.number() }))
.output(z.object({ id: z.number(), value: z.string() }))
.handler(async ({ db, input }) => {
// 伺服器端邏輯
});授權邏輯採取顯式檢查而非資料庫層的 Row-Level Security。官方文件稱之為「authorization as code」:權限判斷寫在 action handler 內部,而不是隱藏在資料庫規則裡,目的是讓權限規則可以被一般程式碼審查與測試涵蓋。
影響範圍
- 前端整合:Next.js、SvelteKit、Nuxt、Expo 均提供原生 client
- 部署目標:Vercel、Cloudflare Workers、Deno Deploy,並支援自架
- 資料庫:透過 Drizzle ORM 定義 schema,並在部署時代管 Neon PostgreSQL 佈建
「no vendor lock-in」是專案主要賣點:使用者可以隨時把 typebase/ 目錄的產物 eject 出來自行接手,不綁定特定平台。專案目前仍屬早期階段,尚未釋出正式版號。
產業案例研究:Rust 的 Typestate 與 Newtype 模式,什麼情況才划算
ACM Digital Library (SIGPLAN FSA Workshop) · 2026-08-29
一篇發表於《Proceedings of the 4th ACM SIGPLAN International Workshop on Functional Software Architecture》的經驗報告 10.1145/3830438.3830958,針對 Rust 生態中兩個常見型別設計模式——typestate 與 newtype——做了三個正式產品程式碼的案例研究。作者 Leon Heuer、Falk Woldmann Lu、Jan Haase 透過專家訪談、靜態程式碼分析與效能 benchmark 交叉驗證,量化這兩種模式對程式碼品質的實際影響,而非僅止於理論上的型別安全論述。
背景
Typestate 把物件的「狀態」編碼進型別本身,例如用 Fsm<StateA> 與 Fsm<StateB> 表示同一個狀態機的不同階段,配合 PhantomData 讓狀態資訊在執行期為零成本,非法的狀態轉換會在編譯期被擋下而不是留到執行期才爆炸。Newtype 則是把基礎型別包進一個 struct 以避免混用語意不同但底層型別相同的值(例如 UserId 與 OrderId 都是 u64),常搭配「parse, don't validate」原則——資料一旦被解析成 newtype,其餘程式碼就不必再重複驗證。
研究發現
論文的兩項主要結論分別對應這兩種模式:
| 模式 | 效益 | 成本 | 最適用情境 |
|---|---|---|---|
| Typestate | 提升程式碼 faultlessness 與可測試性 | 樣板程式碼增加,可能降低可讀性 | 分支邏輯繁多、不變量(invariant)眾多的程式碼 |
| Newtype + parse-don't-validate | 以低成本提升程式碼品質 | 幾乎無額外負擔 | 幾乎所有需要輸入驗證的場景,能在執行期阻擋非法狀態 |
換句話說,Typestate 不是無條件划算的模式:它在狀態轉換規則複雜、容易寫錯的模組上效益最明顯,但若強加在邏輯簡單的程式碼上,換來的只是更多樣板與更差的可讀性。Newtype 搭配 parse-don't-validate 的效益則幾乎沒有反例,論文將其歸類為低成本、高報酬的重構起手式。
影響範圍
這份報告的資料來自三個生產環境的案例研究,而非合成範例,因此其結論對正在評估是否在 Rust 專案中導入 typestate 的團隊具有參考價值:決策依據不再只是「型別系統能不能表達」,而是「這段程式碼的不變量密度是否值得付出樣板成本」。
原始來源:ACM DL:Functional State Machines in Rust: Typestate and Newtype Patterns (Experience Report)
不靠可執行堆疊呼叫 GCC 巢狀函式:跳板指標擷取術
Martin Uecker 個人部落格 · 2026-08-29
GCC 的巢狀函式(nested function)擴充功能長期以來依賴堆疊上的可執行跳板(trampoline)來實作 closure 呼叫,這在啟用 -z noexecstack或其他堆疊不可執行的強化環境(W^X)下會直接失效。GCC 貢獻者 Martin Uecker 在部落格文章中示範了兩種不需要執行跳板本身、就能呼叫巢狀函式的手法,並將實作放進他的實驗性 C 函式庫 noplate。
背景
當 C 程式使用 GCC 的巢狀函式(Nested Functions 擴充)取得內層函式的指標時,編譯器會在堆疊上生成一段跳板:一段內嵌了目的地址與 static chain(外層 frame 指標)兩個立即數的機器碼,呼叫者跳進這段碼、載入暫存器後再跳到真正的函式本體。x86-64 上的典型跳板長這樣:
movq $bar.0, %r11
movq $frame, %r10
jmp *%r11問題在於跳板本身必須被「執行」,因此堆疊必須具備可執行權限,這與現代作業系統對可執行堆疊的限制直接衝突。
兩種擷取手法
第一種手法是直接從跳板的位元組佈局讀出兩個立即數,完全不執行這段機器碼,改用 GCC 的 __builtin_call_with_static_chain 內建函式手動組出呼叫:
unsigned char (*tramp)[24] = (void*)bar;
void *code = peek(uint64_t, &array_slice(tramp, 2, 10));
void *chain = peek(uint64_t, &array_slice(tramp, 12, 20));這裡的 peek 與 array_slice 是 noplate 函式庫提供的邊界檢查工具,用來從固定 offset(2–10 與 12–20 位元組)取出目的地址與 static chain 指標,堆疊全程維持不可執行狀態也能運作。
第二種手法更進一步,把跳板整體當成一份「函式描述子」(function descriptor),在呼叫端用一個極簡的解譯器解析出必要指標,同樣不需要真的跳進去執行那段碼。作者表示 GCC 17 起新增的 __builtin_call_with_static_chain 與相關內建函式讓這個做法更穩固,舊版 GCC 則只能依賴上述的手動位元組擷取當作 fallback。
影響範圍
noplate 目前已同時支援 GCC 與 Clang 上的巢狀函式閉包,讓開發者可以在 堆疊全程不可執行 的強化環境中使用巢狀函式閉包(作者以 patchelf --clear-execstack 驗證了這點)。這對需要在 SELinux 或其他 W^X 強制環境下部署、卻又想使用 C 巢狀函式做輕量 closure 的專案有直接幫助,避免了為了相容性放棄這個 GCC 擴充功能。
原始來源:Martin Uecker:Indirect Calling of Nested Functions on GCC Without Executable Stack、noplate(Codeberg)、GCC Nested Functions 文件