@flashaim-gmb/startupbase-draft
v0.0.7
Published
Common interface for front-end and back-end
Downloads
30
Readme
📝 StartupBase Draft - 共用介面定義
StartupBase 專案的共用型別定義套件,提供前端和後端之間的介面規範,確保資料結構的一致性。
📦 套件資訊
- 名稱:
@flashaim-gmb/startupbase-draft - 版本: 0.0.5
- 描述: 前後端共用介面定義
- 作者: [email protected]
- 授權: MIT
🎯 設計目標
型別安全
- 提供 TypeScript 型別定義
- 確保前後端資料結構一致
- 減少型別錯誤和執行時錯誤
程式碼重用
- 避免重複定義相同介面
- 統一資料驗證邏輯
- 簡化維護成本
版本控制
- 獨立的版本管理
- 向後相容性保證
- 清楚的變更紀錄
🏗️ 核心介面
基礎介面
DBbase
export interface DBbase {
created_at?: number; // 建立時間戳
updated_at?: number; // 更新時間戳
deleted_at?: number; // 刪除時間戳 (軟刪除)
}所有資料庫實體的基礎介面,提供統一的時間戳記欄位。
草稿系統
DraftType
export type DraftType =
| 'office' // 辦公室租賃
| 'houseShort' // 住宅短租
| 'houseLong' // 住宅長租
| 'appoint' // 委任書
| 'address' // 借址合約
| 'trademark' // 商標委任書
| 'website' // 網站設計合約
| 'other'; // 其他合約DraftBase
export interface DraftBase extends DBbase {
id?: string; // 草稿 ID
type: DraftType; // 草稿類型
creator_uid: string; // 建立者 UID
reviewer_uid?: string; // 審核者 UID
status: DraftStatus; // 草稿狀態
rejectionReason?: string; // 駁回原因
reviewDate?: number; // 審核日期
contractNumber?: string; // 合約編號
taskId?: number; // 點點簽任務 ID
creator?: any; // 建立者資訊
originalDraftId?: string; // 原草稿 ID (續約用)
renewedDraftId?: string; // 續約草稿 ID
cardRef?: string; // 付款卡參考路徑
fileMissionLogId?: string; // 合併任務紀錄 ID
mergeUserId?: string; // 合併用戶 ID
}草稿狀態
type DraftStatus =
| '資料待填寫' // 初始狀態
| '合約處理中' // 處理中
| '主管駁回合約' // 被駁回
| '合約已審核' // 審核通過
| '合約送合併' // 送合併
| '合約已發送' // 已發送
| '合約已簽署' // 已簽署
| '合約終止'; // 已終止具體草稿類型
辦公室租賃合約
export interface OfficeDraft extends DraftBase {
name: '辦公室租賃合約';
type: 'office';
draftDetail: OfficeDraftDetail;
}借址合約
export interface AddressDraft extends DraftBase {
name: '借址合約';
type: 'address';
draftDetail: AddressDraftDetail;
}住宅租賃合約
export interface HouseShortDraft extends DraftBase {
name: '住宅短租合約';
type: 'houseShort';
draftDetail: HouseDraftDetail;
}
export interface HouseLongDraft extends DraftBase {
name: '住宅長租合約';
type: 'houseLong';
draftDetail: HouseDraftDetail;
}委任書
export interface AppointDraft extends DraftBase {
name: '委任書';
type: 'appoint';
draftDetail: AppointDraftDetail;
}商標委任書
export interface TrademarkDraft extends DraftBase {
name: '商標委任書';
type: 'trademark';
draftDetail: TrademarkDraftDetail;
}網站設計合約
export interface WebsiteDraft extends DraftBase {
name: '網站設計及保固合約';
type: 'website';
draftDetail: WebsiteDraftDetail;
}其他合約
export interface OtherDraft extends DraftBase {
name: '其他合約';
type: 'other';
draftDetail: OtherDraftDetail;
}聯合類型
export type Draft =
| OfficeDraft
| AddressDraft
| HouseLongDraft
| HouseShortDraft
| AppointDraft
| OtherDraft
| TrademarkDraft
| WebsiteDraft;🔍 型別守衛函式
套件提供了型別守衛函式,用於執行時型別檢查:
// 檢查是否為特定草稿類型
export function isOffice(draft: DraftBase): draft is OfficeDraft;
export function isAddress(draft: DraftBase): draft is AddressDraft;
export function isHouseShort(draft: DraftBase): draft is HouseShortDraft;
export function isHouseLong(draft: DraftBase): draft is HouseLongDraft;
export function isAppoint(draft: DraftBase): draft is AppointDraft;
export function isTrademark(draft: DraftBase): draft is TrademarkDraft;
export function isWebsite(draft: DraftBase): draft is WebsiteDraft;
// 解析草稿名稱
export function ParseDraftName(type: string): string;使用範例
import { Draft, isOffice, isAddress } from '@flashaim-gmb/startupbase-draft/contractDraft';
function processDraft(draft: Draft) {
if (isOffice(draft)) {
// TypeScript 現在知道 draft 是 OfficeDraft
console.log(draft.draftDetail.officeInfo);
} else if (isAddress(draft)) {
// TypeScript 現在知道 draft 是 AddressDraft
console.log(draft.draftDetail.addressInfo);
}
}🚀 使用方式
安裝
npm install @flashaim-gmb/startupbase-draft在前端使用 (Angular)
// 匯入型別定義
import { Draft, DraftType, DraftBase } from '@flashaim-gmb/startupbase-draft/contractDraft';
import { DBbase } from '@flashaim-gmb/startupbase-draft';
// 在元件中使用
@Component({...})
export class DraftComponent {
drafts: Draft[] = [];
processDraft(draft: Draft) {
// 型別安全的操作
}
}在後端使用 (Firebase Functions)
// 匯入型別定義
import { Draft, isOffice } from '@flashaim-gmb/startupbase-draft/contractDraft';
// 在 Cloud Function 中使用
export const processDraft = onDocumentWritten(
'drafts/{draftId}',
(event) => {
const draft = event.data?.after.data() as Draft;
if (isOffice(draft)) {
// 處理辦公室租賃合約
}
}
);🔧 開發指南
建置專案
# 安裝依賴
npm install
# 編譯 TypeScript
npm run build
# 準備發布
npm run prepare專案結構
draft/
├── 📄 index.ts # 基礎介面匯出
├── 📄 contractDraft.ts # 草稿相關介面
├── 📄 contractDraft.d.ts # 型別宣告檔
├── 📄 contractDraft.js # 編譯後的 JS
├── 📦 package.json # 套件設定
└── 🔧 tsconfig.json # TypeScript 設定版本發布
# 更新版本
npm version patch|minor|major
# 發布到 NPM
npm publish
# 更新專案中的依賴
cd ../angular && npm update @flashaim-gmb/startupbase-draft
cd ../functions && npm update @flashaim-gmb/startupbase-draft📋 最佳實踐
介面設計原則
- 向後相容: 新增欄位時使用可選屬性
- 語義清晰: 使用有意義的欄位名稱
- 型別嚴格: 避免使用
any,優先使用具體類型 - 文件完整: 為每個介面提供清楚的註解
版本管理
- 語義版本: 遵循 SemVer 規範
- 變更日誌: 記錄每次版本的變更內容
- 漸進升級: 提供平滑的升級路徑
測試策略
// 型別測試範例
describe('Draft Types', () => {
it('should validate office draft structure', () => {
const draft: OfficeDraft = {
type: 'office',
name: '辦公室租賃合約',
creator_uid: 'test-uid',
status: '資料待填寫',
draftDetail: {
// ... 詳細資料
}
};
expect(isOffice(draft)).toBe(true);
});
});📚 相關文件
🤝 貢獻指南
- 新增介面時確保向後相容
- 提供完整的型別守衛函式
- 更新版本號和變更日誌
- 測試前後端整合
- 遵循 TypeScript 最佳實踐
開發團隊: FlashAim GMB | 語言: TypeScript | 套件類型: 共用介面庫
