ソースを参照

✨ feat(shared-types): 创建共享类型库

- 初始化共享类型库项目结构
- 定义核心API响应类型(ApiResponse, PaginatedResponse)
- 添加分页(Pagination)和查询参数(QueryParams)类型
- 创建状态枚举(EnableStatus, DeleteStatus)及中文映射
- 定义认证上下文(AuthContextType)和全局配置(GlobalConfig)类型
- 添加单元测试验证所有类型定义

✅ test(shared-types): 添加类型单元测试

- 为所有类型定义编写单元测试
- 验证ApiResponse成功和错误两种状态
- 测试分页对象和分页响应结构
- 验证查询参数的各种使用场景
- 检查枚举值和名称映射的正确性
- 测试认证上下文和全局配置类型

📦 build(shared-types): 配置构建和开发环境

- 添加package.json配置项目元信息
- 配置TypeScript编译选项(tsconfig.json)
- 添加typecheck和test脚本
- 设置开发依赖(typescript, vitest)
- 配置模块导出规则
yourname 4 週間 前
コミット
f5a9ede3ef

+ 28 - 0
packages/shared-types/package.json

@@ -0,0 +1,28 @@
+{
+  "name": "@d8d/shared-types",
+  "version": "1.0.0",
+  "type": "module",
+  "description": "D8D Shared Type Definitions",
+  "main": "src/index.ts",
+  "types": "src/index.ts",
+  "exports": {
+    ".": {
+      "import": "./src/index.ts",
+      "require": "./src/index.ts",
+      "types": "./src/index.ts"
+    }
+  },
+  "scripts": {
+    "typecheck": "tsc --noEmit",
+    "test": "vitest",
+    "test:unit": "vitest run tests/unit"
+  },
+  "dependencies": {},
+  "devDependencies": {
+    "typescript": "^5.8.3",
+    "vitest": "^3.2.4"
+  },
+  "files": [
+    "src"
+  ]
+}

+ 69 - 0
packages/shared-types/src/index.ts

@@ -0,0 +1,69 @@
+// 通用响应类型
+export interface ApiResponse<T = any> {
+  success: boolean;
+  data?: T;
+  message?: string;
+  error?: string;
+}
+
+// 分页类型
+export interface Pagination {
+  page: number;
+  pageSize: number;
+  total: number;
+  totalPages: number;
+}
+
+// 分页响应类型
+export interface PaginatedResponse<T = any> extends ApiResponse<T[]> {
+  pagination: Pagination;
+}
+
+// 查询参数类型
+export interface QueryParams {
+  page?: number;
+  pageSize?: number;
+  sortBy?: string;
+  sortOrder?: 'ASC' | 'DESC';
+  [key: string]: any;
+}
+
+// 启用/禁用状态枚举
+export enum EnableStatus {
+  DISABLED = 0, // 禁用
+  ENABLED = 1   // 启用
+}
+
+// 启用/禁用状态中文映射
+export const EnableStatusNameMap: Record<EnableStatus, string> = {
+  [EnableStatus.DISABLED]: '禁用',
+  [EnableStatus.ENABLED]: '启用'
+};
+
+// 删除状态枚举
+export enum DeleteStatus {
+  NOT_DELETED = 0, // 未删除
+  DELETED = 1      // 已删除
+}
+
+// 删除状态中文映射
+export const DeleteStatusNameMap: Record<DeleteStatus, string> = {
+  [DeleteStatus.NOT_DELETED]: '未删除',
+  [DeleteStatus.DELETED]: '已删除'
+};
+
+// 认证上下文类型
+export interface AuthContextType<T> {
+  user: T | null;
+  token: string | null;
+  login: (username: string, password: string, latitude?: number, longitude?: number) => Promise<void>;
+  logout: () => Promise<void>;
+  isAuthenticated: boolean;
+  isLoading: boolean;
+}
+
+// 全局配置常量
+export interface GlobalConfig {
+  OSS_BASE_URL: string;
+  APP_NAME: string;
+}

+ 156 - 0
packages/shared-types/tests/unit/index.test.ts

@@ -0,0 +1,156 @@
+import { describe, it, expect } from 'vitest';
+import {
+  ApiResponse,
+  Pagination,
+  PaginatedResponse,
+  QueryParams,
+  EnableStatus,
+  DeleteStatus,
+  EnableStatusNameMap,
+  DeleteStatusNameMap,
+  AuthContextType,
+  GlobalConfig
+} from '../../src/index.js';
+
+describe('共享类型', () => {
+  describe('ApiResponse', () => {
+    it('应该创建成功的 ApiResponse', () => {
+      const response: ApiResponse<string> = {
+        success: true,
+        data: 'test data',
+        message: 'Operation successful'
+      };
+
+      expect(response.success).toBe(true);
+      expect(response.data).toBe('test data');
+      expect(response.message).toBe('Operation successful');
+    });
+
+    it('应该创建错误的 ApiResponse', () => {
+      const response: ApiResponse = {
+        success: false,
+        error: 'Something went wrong'
+      };
+
+      expect(response.success).toBe(false);
+      expect(response.error).toBe('Something went wrong');
+    });
+  });
+
+  describe('分页', () => {
+    it('应该创建分页对象', () => {
+      const pagination: Pagination = {
+        page: 1,
+        pageSize: 10,
+        total: 100,
+        totalPages: 10
+      };
+
+      expect(pagination.page).toBe(1);
+      expect(pagination.pageSize).toBe(10);
+      expect(pagination.total).toBe(100);
+      expect(pagination.totalPages).toBe(10);
+    });
+  });
+
+  describe('分页响应', () => {
+    it('应该创建分页响应', () => {
+      const response: PaginatedResponse<string> = {
+        success: true,
+        data: ['item1', 'item2'],
+        pagination: {
+          page: 1,
+          pageSize: 10,
+          total: 20,
+          totalPages: 2
+        }
+      };
+
+      expect(response.success).toBe(true);
+      expect(response.data).toEqual(['item1', 'item2']);
+      expect(response.pagination.page).toBe(1);
+    });
+  });
+
+  describe('查询参数', () => {
+    it('应该创建带分页的查询参数', () => {
+      const params: QueryParams = {
+        page: 1,
+        pageSize: 10,
+        sortBy: 'name',
+        sortOrder: 'ASC'
+      };
+
+      expect(params.page).toBe(1);
+      expect(params.pageSize).toBe(10);
+      expect(params.sortBy).toBe('name');
+      expect(params.sortOrder).toBe('ASC');
+    });
+
+    it('应该创建带额外过滤器的查询参数', () => {
+      const params: QueryParams = {
+        page: 1,
+        status: 'active',
+        category: 'tech'
+      };
+
+      expect(params.page).toBe(1);
+      expect(params.status).toBe('active');
+      expect(params.category).toBe('tech');
+    });
+  });
+
+  describe('启用状态', () => {
+    it('应该有正确的枚举值', () => {
+      expect(EnableStatus.DISABLED).toBe(0);
+      expect(EnableStatus.ENABLED).toBe(1);
+    });
+
+    it('应该有正确的名称映射', () => {
+      expect(EnableStatusNameMap[EnableStatus.DISABLED]).toBe('禁用');
+      expect(EnableStatusNameMap[EnableStatus.ENABLED]).toBe('启用');
+    });
+  });
+
+  describe('删除状态', () => {
+    it('应该有正确的枚举值', () => {
+      expect(DeleteStatus.NOT_DELETED).toBe(0);
+      expect(DeleteStatus.DELETED).toBe(1);
+    });
+
+    it('应该有正确的名称映射', () => {
+      expect(DeleteStatusNameMap[DeleteStatus.NOT_DELETED]).toBe('未删除');
+      expect(DeleteStatusNameMap[DeleteStatus.DELETED]).toBe('已删除');
+    });
+  });
+
+  describe('认证上下文类型', () => {
+    it('应该定义认证上下文类型结构', () => {
+      const authContext: AuthContextType<{ id: string; name: string }> = {
+        user: { id: '1', name: 'Test User' },
+        token: 'test-token',
+        login: async () => {},
+        logout: async () => {},
+        isAuthenticated: true,
+        isLoading: false
+      };
+
+      expect(authContext.user?.id).toBe('1');
+      expect(authContext.token).toBe('test-token');
+      expect(authContext.isAuthenticated).toBe(true);
+      expect(authContext.isLoading).toBe(false);
+    });
+  });
+
+  describe('全局配置', () => {
+    it('应该定义全局配置结构', () => {
+      const config: GlobalConfig = {
+        OSS_BASE_URL: 'https://oss.example.com',
+        APP_NAME: 'Test App'
+      };
+
+      expect(config.OSS_BASE_URL).toBe('https://oss.example.com');
+      expect(config.APP_NAME).toBe('Test App');
+    });
+  });
+});

+ 28 - 0
packages/shared-types/tsconfig.json

@@ -0,0 +1,28 @@
+{
+  "compilerOptions": {
+    "composite": true,
+    "target": "ES2022",
+    "module": "ESNext",
+    "moduleResolution": "bundler",
+    "allowSyntheticDefaultImports": true,
+    "esModuleInterop": true,
+    "resolveJsonModule": true,
+    "isolatedModules": true,
+    "noEmit": false,
+    "strict": true,
+    "noUncheckedIndexedAccess": true,
+    "noImplicitOverride": true,
+    "outDir": "./dist",
+    "rootDir": ".",
+    "declaration": true,
+    "skipLibCheck": true
+  },
+  "include": [
+    "src/**/*",
+    "tests/**/*"
+  ],
+  "exclude": [
+    "node_modules",
+    "dist"
+  ]
+}