npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@gravito/ion

v4.0.1

Published

Inertia.js v2 adapter for Gravito

Readme

🛰️ Orbit Inertia (Ion)

Gravito 的 Inertia.js v2 轉接器,用於建立現代化單體應用 (Modern Monolith)。支援 React、Vue 與 Svelte。

Orbit Inertia (@gravito/ion) 是一個高效能的轉接器,實現 Inertia.js v2 協議,讓您能夠使用傳統的伺服器端路由與控制器來建立單頁應用程式 (SPA)。它扮演了 Gravito (Photon) 與前端框架之間的「膠水」,消除了開發獨立 REST 或 GraphQL API 的需求。

✨ 核心特性

  • 🚀 現代化單體架構:結合伺服器端開發的高效率與 SPA 框架的高互動性。
  • 🛠️ 零 API 開發:直接將資料從控制器傳遞到組件作為具備型別的 Props,不再需要管理 API 端點或手動處理序列化。
  • ⚡ 高效能渲染:內建多層快取、版本快取 (60 秒 TTL) 與組件元資料最佳化,確保毫秒級的極低開銷。
  • 🛡️ 原生型別安全:完整的 TypeScript 支援,透過 Generics 確保從伺服器到前端的端到端型別安全。
  • 🔗 生態系整合:與 OrbitPrism (模板引擎) 及 Gravito 的 Session/Auth 模組完美協作。
  • 🔍 SEO 與 SSR 友善:專為現代 Web 需求設計,支援伺服器端渲染 (SSR) 模式以優化搜尋引擎可見度。
  • 🎨 多框架支援:官方支援 ReactVueSvelte
  • ✨ Inertia v2 協議:完整支援延遲 Props、合併策略、錯誤包與 CSRF 防護。

📦 安裝

bun add @gravito/ion

🚀 快速上手

1. 註冊 Orbit

在應用程式啟動程式碼中:

import { OrbitIon } from '@gravito/ion';
import { OrbitPrism } from '@gravito/prism'; // 渲染基礎 HTML 模板所需

const config = defineConfig({
  orbits: [OrbitPrism, OrbitIon],
});

2. 設定基礎模板

預設情況下,Ion 會尋找 src/views/app.html。使用 {{{ page }}} 佔位符來注入 Inertia 的資料:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <script type="module" src="/static/assets/app.js"></script>
    <link rel="stylesheet" href="/static/assets/app.css">
</head>
<body>
    <div id="app" data-page='{{{ page }}}'></div>
</body>
</html>

3. 從控制器回傳回應

使用 Context 中提供的 InertiaService

import { Context } from '@gravito/photon';
import { InertiaService } from '@gravito/ion';

export class DashboardController {
  index = async (c: Context) => {
    const inertia = c.get('inertia') as InertiaService;
    
    return inertia.render('Dashboard/Index', {
      user: c.get('user'),
      stats: { activeOrders: 5 }
    });
  };
}

🔧 Inertia v2 協議功能

延遲 Props (Deferred Props)

跳過初始渲染,在後續操作中單獨載入 Props:

inertia.render('Dashboard', {
  user: { id: 1, name: 'Carl' }, // 初始載入
  stats: InertiaService.defer(() => fetchStats(), 'heavy'), // 延遲載入
  notifications: InertiaService.defer(() => fetchNotifications(), 'notifications')
});

合併策略 (Merge Strategies)

控制局部重新載入時 Props 如何合併:

inertia.render('Products/List', {
  items: InertiaService.prepend([newProduct]), // 加到開頭
  filters: InertiaService.deepMerge({ status: 'active' }), // 遞迴合併
  config: InertiaService.merge({ sortBy: 'name' }) // 淺合併
});

錯誤包 (Error Bags)

按類別組織表單驗證錯誤:

inertia.withErrors({
  email: '電郵為必填',
  password: '必須為 8 個字元以上'
}, 'login'); // 命名包

inertia.withErrors({
  line_1: '無效的 CSV 格式'
}, 'import');

智慧重定向 (Smart Redirects)

自動為 Inertia 請求回傳 409,普通請求回傳 302:

if (!user) {
  return inertia.location('/login'); // 智慧重定向
}

瀏覽歷史控制 (History Control)

inertia.encryptHistory(true);   // 停用返回按鈕
inertia.clearHistory();         // 載入後清除歷史

CSRF 防護

自動產生 XSRF-TOKEN Cookie (與 Axios 相容):

const ion = new OrbitIon({
  csrf: {
    enabled: true,
    cookieName: 'XSRF-TOKEN' // Axios 會自動讀取
  }
});

🔧 進階功能

共享 Props (Shared Props)

自動在每個 Inertia 回應中共享資料 (例如:當前用戶、快閃訊息):

inertia.share('auth', { user: 'Carl' });

局部重新載入 (Partial Reloads)

Ion 支援 Inertia 的局部重載機制,搭配智慧合併策略,允許客戶端僅請求特定資料以節省頻寬。

方法鏈式調用 (Method Chaining)

所有方法都支援流暢介面:

return await inertia
  .encryptHistory()
  .clearHistory()
  .withErrors({ email: '無效' })
  .render('SecurePage', props);

手動序列化控制

自定義資料如何轉換為 JSON 傳遞給客戶端:

inertia.render('ProductDetail', {
  product: product.toShortArray() // 顯式控制
});

🛡️ 效能與可靠性

基準測試 (內部測試)

| 操作 | 延遲 (Latency) | |-----------|---------| | 回應生成 | < 0.2ms | | 模板注入 | < 0.1ms | | Props 序列化 | 優化後的 LRU 快取 |

錯誤代碼

Ion 透過 InertiaErrorCodes 提供詳細的錯誤類型:

  • CONFIG_VIEW_SERVICE_MISSING:請確保已載入 OrbitPrism
  • SERIALIZATION_FAILED:在 Props 中偵測到循環依賴。
  • TEMPLATE_RENDER_FAILED:找不到或無法解析基礎 HTML 模板。

📝 授權

MIT © Carl Lee