設定檔

Saavo 範本的設定規則、共用型別和設定檔索引。

專案設定統一放在 config/ 目錄。修改網站資訊、功能開關、產品、付款或第三方服務時,應先找到對應的設定檔,再依 Schema 和呼叫程式碼確認欄位要求。

設定檔不能儲存金鑰

config/ 中的內容會提交到 Git,也可能進入用戶端或建置產物。密碼、API Key、存取權杖和簽章金鑰必須放在環境變數或 Cloudflare Secret 中。

設定檔只能儲存靜態值

設定項目只能填入字串、數字、布林值、陣列和一般物件等靜態值。函式、類別實例、Promise,以及需要在執行階段計算的內容,都不能放進設定檔。5 * 1024 * 1024 這類在載入時就能確定結果的常數運算式可以使用。依賴目前請求、使用者、資料庫、系統時間或隨機數的邏輯,應寫在對應的業務程式碼中。

讀取設定

config/ 中的檔案都是一般的 TypeScript 模組,應用程式會直接匯入設定常數,不需要轉換成 JSON。大多數設定物件以 as const satisfies ...Input 結尾:

  • as const 會保留產品 ID、角色名稱等字面值,其他程式碼可以據此推導出精確的聯集型別。
  • satisfies 會檢查欄位名稱和輸入型別,同時保留原物件的精確型別。
import type { WebsiteDeployCfgInput } from '@/libs/config/schemas/deploy';

export const websiteDeployCfg = {
    // 設定內容
} as const satisfies WebsiteDeployCfgInput;

伺服器端透過下列函式讀取完整設定:

getServerConfig(): AppConfig

第一次呼叫時,程式會合併所有設定,再交由 AppConfigSchema 驗證。驗證通過後,結果會保存在設定登錄表中,後續呼叫會直接讀取這份設定。驗證失敗時,程式會回報 Configuration validation failed at startup,並中止啟動。

瀏覽器端透過下列函式讀取公開設定:

getClientConfig(): typeof _rawConfig

用戶端設定目前只包含 base、i18n、scopes、ads 和 analytics。這些內容會打包到瀏覽器端,訪客可以直接查看,因此不能包含敏感資訊。

型別檢查與啟動驗證是不同的檢查

satisfies 只能檢查 TypeScript 能表達的限制。電子郵件地址格式、數值範圍、時間間隔格式,以及產品與聯盟行銷設定之間的引用關係,仍須由 Zod 在啟動時檢查。因此,修改設定後,不能只看編輯器是否回報錯誤。

...Input 是設定檔使用的輸入型別,通常與 satisfies 搭配使用。不含 Input 的同名型別,一般表示 Zod 驗證後的結果。如果欄位帶有預設值、前置處理規則或選用設定,這兩種型別可能不同。填寫設定時,以 Input 型別為準,業務程式碼則透過 getServerConfig() 讀取驗證後的設定。

共用型別

多個設定檔都會使用 LocalizedText 和 DateIntervalType。這兩個型別的欄位意義和填寫規則,統一說明如下。

LocalizedText

LocalizedText 用於填寫多語言文案,定義在 src/libs/i18n/types.ts。它是包含 value 和 key 的物件,不能直接填入一般字串。

Prop

Type

value 和 key 至少填寫一項。需要支援多語言時,通常兩項都填:頁面先依 key 讀取目前語言的文案,找不到時再顯示 value。

{
    value: 'Saavo Starter',
    key: 'website.title',
}

DateIntervalType

DateIntervalType 以字串填寫時間長度,常用於工作階段有效期間、快取時間、請求速率限制週期和聯盟行銷結算週期。格式為數字加上時間單位,數字與單位之間可以留空白。

單位意義範例
ms毫秒500ms
s秒30s
m分鐘15m
h小時2h
d天7d
w週2w
mo月1mo
y年1y

單位也可以寫成 seconds、minutes、hours 等完整英文單字。只寫數字會以毫秒處理,容易填錯,建議一律寫明單位。請注意,m 表示分鐘,mo 才表示月。

修改設定

找到負責該功能的檔案

先從下方表格進入對應文章,確認欄位路徑、型別、範本預設值和用途。不要只因欄位名稱相似,就將設定寫進不相關的檔案。

依既有結構修改

保留匯出變數名稱和末尾的 satisfies 型別限制。新增物件鍵時,優先使用穩定、容易閱讀的英文識別字。需要顯示給使用者的文字,請使用 LocalizedText,不要直接將中文當成產品 ID、角色名稱或授權範圍(Scope)。

修改多語言文案的鍵名時,應同步更新所有已支援語言的 JSON 檔案。修改 Stripe Price ID、Cloudflare 資源名稱、電子郵件地址或第三方服務識別字時,也要到對應平台確認資源已建立,並檢查使用的帳號是否有權存取。

完整檢查

依序執行 npm run lint、npx tsc --noEmit 和 npm run build。正式環境建置會觸發內容產生和應用程式建置,更容易找出只在啟動或打包階段出現的設定錯誤。

設定檔一覽

檔案用途
base.ts網站名稱、SEO 分享圖片、社群帳號、管理員電子郵件地址和郵件地址
i18n.ts網站支援的語言和預設語言
deploy.ts主機、安全性原則、儲存、電子郵件、身分驗證、流量統計和內容開關
payment.ts付款服務供應商、Checkout 和帳單入口
products.ts產品、方案、Stripe Price ID、購買後取得的角色和權益
capability.ts角色和權益使用的能力定義
roles.ts角色及其靜態能力
entitlements.ts權益及其包含的能力
scopes.tsOAuth 2.0 授權範圍(Scope)
upgrade.tsOAuth 授權頁面的方案升級建議,預設為空
affiliate.ts聯盟行銷、佣金和結算規則
analytics.ts第三方統計服務
notifications.ts外部通知管道
cookie-consent.tsCookie 同意模式、分類和第三方服務
header-menu.ts頁首導覽
footer-menu.ts頁尾導覽
ads.ts廣告服務的瀏覽器端設定

應用程式啟動時,會使用 src/libs/config/schemas/ 中的 Zod Schema 驗證設定。TypeScript 型別檢查可以找出欄位名稱和型別錯誤,Zod 還會檢查電子郵件地址格式、數值範圍和跨檔案引用等內容。

一般注意事項

  • 不要任意修改設定檔的匯出變數名稱。src/libs/config/client.ts 和 src/libs/config/index.ts 會直接匯入這些變數,重新命名後,必須同步修改載入程式碼。
  • base.ts、i18n.ts、scopes.ts、ads.ts 和 analytics.ts 會進入用戶端設定,所有欄位都應視為公開資訊。其他設定也會提交到儲存庫,同樣不能儲存金鑰。
  • 設定之間存在引用關係。角色引用能力,產品引用角色和權益,聯盟行銷引用產品與方案,升級建議引用 OAuth 授權範圍(Scope)。重新命名或刪除前,請搜尋整個專案,不能只修改定義處。
  • TypeScript 和 Zod 無法確認外部資源一定存在。Stripe Price ID、Cloudflare Binding、郵件網域和第三方服務帳號,仍須到對應平台核對。
  • 不要將環境差異寫死在設定檔中。網域、金鑰,以及開發、預覽、正式環境各自不同的值,應放在環境變數、Cloudflare Secret 或對應的部署設定中。
  • 修改預設陣列或物件時,要注意順序。有些頁面會依設定順序展示選單、產品和選項,即使型別檢查沒有錯誤,調換順序也可能改變使用者看到的結果。