From 5d0ab0a9a131dc1e03bdeea7a3d6baea6457b39e Mon Sep 17 00:00:00 2001 From: MyPrototypeWhat Date: Tue, 19 Aug 2025 11:13:03 +0800 Subject: [PATCH] feat(aiCore): update vitest version and enhance provider validation - Upgraded `vitest` dependency to version 3.2.4 in package.json and yarn.lock for improved testing capabilities. - Removed console error logging in provider validation functions to streamline error handling. - Added comprehensive tests for the AiProviderRegistry functionality, ensuring robust provider management and dynamic registration. - Introduced new test cases for provider schemas to validate configurations and IDs. - Deleted outdated registry test file to maintain a clean test suite. --- packages/aiCore/package.json | 2 +- .../__tests__/registry-functionality.test.ts | 568 ++++++++++++++++++ .../core/providers/__tests__/registry.test.ts | 131 ---- .../core/providers/__tests__/schemas.test.ts | 393 ++++++++++++ packages/aiCore/src/core/providers/schemas.ts | 2 - packages/aiCore/vitest.config.ts | 5 +- yarn.lock | 313 +--------- 7 files changed, 971 insertions(+), 443 deletions(-) create mode 100644 packages/aiCore/src/core/providers/__tests__/registry-functionality.test.ts delete mode 100644 packages/aiCore/src/core/providers/__tests__/registry.test.ts create mode 100644 packages/aiCore/src/core/providers/__tests__/schemas.test.ts diff --git a/packages/aiCore/package.json b/packages/aiCore/package.json index a3c54e7482..a5732ff4ee 100644 --- a/packages/aiCore/package.json +++ b/packages/aiCore/package.json @@ -48,7 +48,7 @@ "devDependencies": { "tsdown": "^0.12.9", "typescript": "^5.0.0", - "vitest": "^1.0.0" + "vitest": "^3.2.4" }, "sideEffects": false, "engines": { diff --git a/packages/aiCore/src/core/providers/__tests__/registry-functionality.test.ts b/packages/aiCore/src/core/providers/__tests__/registry-functionality.test.ts new file mode 100644 index 0000000000..cabbda15f1 --- /dev/null +++ b/packages/aiCore/src/core/providers/__tests__/registry-functionality.test.ts @@ -0,0 +1,568 @@ +/** + * 测试真正的 AiProviderRegistry 功能 + */ + +import { beforeEach, describe, expect, it, vi } from 'vitest' + +// 模拟 AI SDK +vi.mock('@ai-sdk/openai', () => ({ + createOpenAI: vi.fn(() => ({ name: 'openai-mock' })) +})) + +vi.mock('@ai-sdk/anthropic', () => ({ + createAnthropic: vi.fn(() => ({ name: 'anthropic-mock' })) +})) + +vi.mock('@ai-sdk/azure', () => ({ + createAzure: vi.fn(() => ({ name: 'azure-mock' })) +})) + +vi.mock('@ai-sdk/deepseek', () => ({ + createDeepSeek: vi.fn(() => ({ name: 'deepseek-mock' })) +})) + +vi.mock('@ai-sdk/google', () => ({ + createGoogleGenerativeAI: vi.fn(() => ({ name: 'google-mock' })) +})) + +vi.mock('@ai-sdk/openai-compatible', () => ({ + createOpenAICompatible: vi.fn(() => ({ name: 'openai-compatible-mock' })) +})) + +vi.mock('@ai-sdk/xai', () => ({ + createXai: vi.fn(() => ({ name: 'xai-mock' })) +})) + +import { + AiProviderRegistry, + cleanup, + getAllDynamicMappings, + getAllProviders, + getAllValidProviderIds, + getDynamicProviders, + getProvider, + getProviderMapping, + isDynamicProvider, + isProviderSupported, + registerDynamicProvider, + registerMultipleProviders, + registerProvider, + validateProviderIdRegistry +} from '../registry' +import type { DynamicProviderRegistration, ProviderConfig } from '../schemas' + +describe('AiProviderRegistry 功能测试', () => { + beforeEach(() => { + // 清理状态 + cleanup() + }) + + describe('基础功能', () => { + it('能够获取所有 providers', () => { + const providers = getAllProviders() + expect(Array.isArray(providers)).toBe(true) + expect(providers.length).toBeGreaterThan(0) + + // 包含基础 providers + const providerIds = providers.map((p) => p.id) + expect(providerIds).toContain('openai') + expect(providerIds).toContain('anthropic') + expect(providerIds).toContain('google') + }) + + it('能够检查 provider 支持状态', () => { + expect(isProviderSupported('openai')).toBe(true) + expect(isProviderSupported('anthropic')).toBe(true) + expect(isProviderSupported('google')).toBe(true) + expect(isProviderSupported('non-existent')).toBe(true) // validateProviderId 通过 + expect(isProviderSupported('')).toBe(false) + }) + + it('能够获取有效的 provider IDs', () => { + const allIds = getAllValidProviderIds() + expect(Array.isArray(allIds)).toBe(true) + expect(allIds).toContain('openai') + expect(allIds).toContain('anthropic') + }) + + it('能够根据 ID 获取特定的 provider', () => { + // 获取存在的 provider + const openaiProvider = getProvider('openai') + expect(openaiProvider).toBeDefined() + expect(openaiProvider?.id).toBe('openai') + expect(openaiProvider?.name).toBe('OpenAI') + + // 获取不存在的 provider,fallback到openai-compatible + const nonExistentProvider = getProvider('non-existent') + expect(nonExistentProvider).toBeDefined() + expect(nonExistentProvider?.id).toBe('openai-compatible') + }) + + it('能够验证 provider ID', () => { + expect(validateProviderIdRegistry('valid-id')).toBe(true) + expect(validateProviderIdRegistry('another-valid-id')).toBe(true) + expect(validateProviderIdRegistry('')).toBe(false) + // 注意:单个空格字符被认为是有效的,因为它不是空字符串 + // 如果需要更严格的验证,schemas 包含更多验证规则 + expect(validateProviderIdRegistry(' ')).toBe(true) + }) + }) + + describe('动态 Provider 注册', () => { + it('能够注册动态 provider', () => { + const config = { + id: 'custom-provider', + name: 'Custom Provider', + creator: vi.fn(() => ({ name: 'custom' })), + supportsImageGeneration: false + } + + const success = registerDynamicProvider(config) + expect(success).toBe(true) + + expect(isDynamicProvider('custom-provider')).toBe(true) + expect(isProviderSupported('custom-provider')).toBe(true) + + const allIds = getAllValidProviderIds() + expect(allIds).toContain('custom-provider') + }) + + it('拒绝与基础 provider 冲突的配置', () => { + const config = { + id: 'openai', + name: 'Duplicate OpenAI', + creator: vi.fn(() => ({ name: 'duplicate' })), + supportsImageGeneration: false + } + + const success = registerDynamicProvider(config) + expect(success).toBe(false) + expect(isDynamicProvider('openai')).toBe(false) + }) + + it('拒绝无效的配置', () => { + // 缺少必要字段 + const invalidConfig = { + id: 'invalid-provider' + // 缺少 name, creator 等 + } + + const success = registerDynamicProvider(invalidConfig as any) + expect(success).toBe(false) + }) + + it('能够批量注册动态 providers', () => { + const configs: DynamicProviderRegistration[] = [ + { + id: 'provider-1', + name: 'Provider 1', + creator: vi.fn(() => ({ name: 'provider-1' })), + supportsImageGeneration: false + }, + { + id: 'provider-2', + name: 'Provider 2', + creator: vi.fn(() => ({ name: 'provider-2' })), + supportsImageGeneration: true + }, + { + id: 'openai', // 这个失败,因为与基础 provider 冲突 + name: 'Invalid Provider', + creator: vi.fn(() => ({ name: 'invalid' })), + supportsImageGeneration: false + } + ] + + const successCount = registerMultipleProviders(configs) + expect(successCount).toBe(2) // 只有前两个成功 + + expect(isDynamicProvider('provider-1')).toBe(true) + expect(isDynamicProvider('provider-2')).toBe(true) + expect(isDynamicProvider('openai')).toBe(false) // 基础 provider,不是动态的 + }) + + it('支持带映射关系的动态 provider', () => { + const configWithMappings: DynamicProviderRegistration = { + id: 'custom-provider-with-mappings', + name: 'Custom Provider with Mappings', + creator: vi.fn(() => ({ name: 'custom-mapped' })), + supportsImageGeneration: false, + mappings: { + 'custom-alias-1': 'custom-provider-with-mappings', + 'custom-alias-2': 'custom-provider-with-mappings' + } + } + + const success = registerDynamicProvider(configWithMappings) + expect(success).toBe(true) + + // 验证映射关系 + expect(getProviderMapping('custom-alias-1')).toBe('custom-provider-with-mappings') + expect(getProviderMapping('custom-alias-2')).toBe('custom-provider-with-mappings') + expect(getProviderMapping('custom-provider-with-mappings')).toBe('custom-provider-with-mappings') + }) + }) + + describe('Registry 管理', () => { + it('能够清理动态 providers', () => { + // 注册动态 provider + registerDynamicProvider({ + id: 'temp-provider', + name: 'Temp Provider', + creator: vi.fn(() => ({ name: 'temp' })), + supportsImageGeneration: false + }) + + expect(isDynamicProvider('temp-provider')).toBe(true) + + // 清理 + cleanup() + + expect(isDynamicProvider('temp-provider')).toBe(false) + expect(isProviderSupported('openai')).toBe(true) // 基础 providers 仍存在 + }) + + it('保持单例模式', () => { + const instance1 = AiProviderRegistry.getInstance() + const instance2 = AiProviderRegistry.getInstance() + expect(instance1).toBe(instance2) + }) + + it('能够注册基础 provider', () => { + const customConfig: ProviderConfig = { + id: 'custom-base-provider', + name: 'Custom Base Provider', + creator: vi.fn(() => ({ name: 'custom-base' })), + supportsImageGeneration: false + } + + // 注册基础 provider 不抛出错误 + expect(() => registerProvider(customConfig)).not.toThrow() + + // 验证注册成功 + const registeredProvider = getProvider('custom-base-provider') + expect(registeredProvider).toBeDefined() + expect(registeredProvider?.id).toBe('custom-base-provider') + expect(registeredProvider?.name).toBe('Custom Base Provider') + }) + + it('能够获取动态 providers 列表', () => { + // 初始状态没有动态 providers + expect(getDynamicProviders()).toEqual([]) + + // 注册一些动态 providers + registerDynamicProvider({ + id: 'dynamic-1', + name: 'Dynamic 1', + creator: vi.fn(() => ({ name: 'dynamic-1' })), + supportsImageGeneration: false + }) + + registerDynamicProvider({ + id: 'dynamic-2', + name: 'Dynamic 2', + creator: vi.fn(() => ({ name: 'dynamic-2' })), + supportsImageGeneration: true + }) + + const dynamicProviders = getDynamicProviders() + expect(Array.isArray(dynamicProviders)).toBe(true) + expect(dynamicProviders).toContain('dynamic-1') + expect(dynamicProviders).toContain('dynamic-2') + expect(dynamicProviders.length).toBe(2) + }) + + it('能够获取所有动态映射', () => { + // 初始状态没有动态映射 + expect(getAllDynamicMappings()).toEqual({}) + + // 注册带映射的动态 provider + registerDynamicProvider({ + id: 'mapped-provider', + name: 'Mapped Provider', + creator: vi.fn(() => ({ name: 'mapped' })), + supportsImageGeneration: false, + mappings: { + 'alias-1': 'mapped-provider', + 'alias-2': 'mapped-provider', + 'custom-name': 'mapped-provider' + } + }) + + const allMappings = getAllDynamicMappings() + expect(allMappings).toEqual({ + 'alias-1': 'mapped-provider', + 'alias-2': 'mapped-provider', + 'custom-name': 'mapped-provider' + }) + }) + }) + + describe('错误处理', () => { + it('优雅处理空配置', () => { + const success = registerDynamicProvider(null as any) + expect(success).toBe(false) + }) + + it('优雅处理未定义配置', () => { + const success = registerDynamicProvider(undefined as any) + expect(success).toBe(false) + }) + + it('处理空字符串 ID', () => { + const config = { + id: '', + name: 'Empty ID Provider', + creator: vi.fn(() => ({ name: 'empty' })), + supportsImageGeneration: false + } + + const success = registerDynamicProvider(config) + expect(success).toBe(false) + }) + + it('处理注册基础 provider 时的无效 ID', () => { + const invalidConfig: ProviderConfig = { + id: '', // 无效 ID + name: 'Invalid Provider', + creator: vi.fn(() => ({ name: 'invalid' })), + supportsImageGeneration: false + } + + expect(() => registerProvider(invalidConfig)).toThrow('Invalid provider ID:') + }) + + it('处理获取不存在映射时的情况', () => { + expect(getProviderMapping('non-existent-mapping')).toBeUndefined() + }) + + it('处理批量注册时的部分失败', () => { + const mixedConfigs: DynamicProviderRegistration[] = [ + { + id: 'valid-provider-1', + name: 'Valid Provider 1', + creator: vi.fn(() => ({ name: 'valid-1' })), + supportsImageGeneration: false + }, + { + id: '', // 无效配置 + name: 'Invalid Provider', + creator: vi.fn(() => ({ name: 'invalid' })), + supportsImageGeneration: false + }, + { + id: 'valid-provider-2', + name: 'Valid Provider 2', + creator: vi.fn(() => ({ name: 'valid-2' })), + supportsImageGeneration: true + } + ] + + const successCount = registerMultipleProviders(mixedConfigs) + expect(successCount).toBe(2) // 只有两个有效配置成功 + + expect(isDynamicProvider('valid-provider-1')).toBe(true) + expect(isDynamicProvider('valid-provider-2')).toBe(true) + expect(getDynamicProviders()).not.toContain('') + }) + }) + + describe('集成测试', () => { + it('正确处理复杂的注册、映射和清理场景', () => { + // 初始状态验证 + const initialProviders = getAllProviders() + const initialIds = getAllValidProviderIds() + expect(initialProviders.length).toBeGreaterThan(0) + expect(getDynamicProviders()).toEqual([]) + expect(getAllDynamicMappings()).toEqual({}) + + // 注册多个带映射的动态 providers + const configs: DynamicProviderRegistration[] = [ + { + id: 'integration-provider-1', + name: 'Integration Provider 1', + creator: vi.fn(() => ({ name: 'integration-1' })), + supportsImageGeneration: false, + mappings: { + 'alias-1': 'integration-provider-1', + 'short-name-1': 'integration-provider-1' + } + }, + { + id: 'integration-provider-2', + name: 'Integration Provider 2', + creator: vi.fn(() => ({ name: 'integration-2' })), + supportsImageGeneration: true, + mappings: { + 'alias-2': 'integration-provider-2', + 'short-name-2': 'integration-provider-2' + } + } + ] + + const successCount = registerMultipleProviders(configs) + expect(successCount).toBe(2) + + // 验证注册后的状态 + const afterRegisterProviders = getAllProviders() + const afterRegisterIds = getAllValidProviderIds() + expect(afterRegisterProviders.length).toBe(initialProviders.length + 2) + expect(afterRegisterIds.length).toBeGreaterThanOrEqual(initialIds.length + 2) + + // 验证动态 providers + const dynamicProviders = getDynamicProviders() + expect(dynamicProviders).toContain('integration-provider-1') + expect(dynamicProviders).toContain('integration-provider-2') + + // 验证映射 + const mappings = getAllDynamicMappings() + expect(mappings['alias-1']).toBe('integration-provider-1') + expect(mappings['alias-2']).toBe('integration-provider-2') + expect(mappings['short-name-1']).toBe('integration-provider-1') + expect(mappings['short-name-2']).toBe('integration-provider-2') + + // 验证通过映射能够获取 provider + expect(getProviderMapping('alias-1')).toBe('integration-provider-1') + expect(getProviderMapping('integration-provider-1')).toBe('integration-provider-1') + + // 清理 + cleanup() + + // 验证清理后的状态 + const afterCleanupProviders = getAllProviders() + const afterCleanupIds = getAllValidProviderIds() + expect(afterCleanupProviders.length).toBe(initialProviders.length) + expect(afterCleanupIds.length).toBe(initialIds.length) + expect(getDynamicProviders()).toEqual([]) + expect(getAllDynamicMappings()).toEqual({}) + }) + + it('正确处理 provider 的优先级和 fallback 机制', () => { + // 验证 getProvider 的 fallback 机制 + const existingProvider = getProvider('openai') + expect(existingProvider?.id).toBe('openai') + + const nonExistentProvider = getProvider('definitely-non-existent') + expect(nonExistentProvider?.id).toBe('openai-compatible') // fallback + + // 注册自定义 provider 后能直接获取 + registerDynamicProvider({ + id: 'priority-test-provider', + name: 'Priority Test Provider', + creator: vi.fn(() => ({ name: 'priority-test' })), + supportsImageGeneration: false + }) + + const customProvider = getProvider('priority-test-provider') + expect(customProvider?.id).toBe('priority-test-provider') + expect(customProvider?.name).toBe('Priority Test Provider') + }) + + it('正确处理大量动态 providers 的注册和管理', () => { + const largeConfigList: DynamicProviderRegistration[] = [] + + // 生成100个动态 providers + for (let i = 0; i < 100; i++) { + largeConfigList.push({ + id: `bulk-provider-${i}`, + name: `Bulk Provider ${i}`, + creator: vi.fn(() => ({ name: `bulk-${i}` })), + supportsImageGeneration: i % 2 === 0, // 偶数支持图像生成 + mappings: { + [`alias-${i}`]: `bulk-provider-${i}`, + [`short-${i}`]: `bulk-provider-${i}` + } + }) + } + + const successCount = registerMultipleProviders(largeConfigList) + expect(successCount).toBe(100) + + // 验证所有 providers 都被正确注册 + const dynamicProviders = getDynamicProviders() + expect(dynamicProviders.length).toBe(100) + + // 验证映射数量 + const mappings = getAllDynamicMappings() + expect(Object.keys(mappings).length).toBe(200) // 每个 provider 有2个映射 + + // 随机验证几个 providers + expect(isDynamicProvider('bulk-provider-0')).toBe(true) + expect(isDynamicProvider('bulk-provider-50')).toBe(true) + expect(isDynamicProvider('bulk-provider-99')).toBe(true) + + // 验证映射工作正常 + expect(getProviderMapping('alias-25')).toBe('bulk-provider-25') + expect(getProviderMapping('short-75')).toBe('bulk-provider-75') + + // 清理能正确处理大量数据 + cleanup() + expect(getDynamicProviders()).toEqual([]) + expect(getAllDynamicMappings()).toEqual({}) + }) + }) + + describe('边界测试', () => { + it('处理包含特殊字符的 provider IDs', () => { + const specialCharsConfigs: DynamicProviderRegistration[] = [ + { + id: 'provider-with-dashes', + name: 'Provider With Dashes', + creator: vi.fn(() => ({ name: 'dashes' })), + supportsImageGeneration: false + }, + { + id: 'provider_with_underscores', + name: 'Provider With Underscores', + creator: vi.fn(() => ({ name: 'underscores' })), + supportsImageGeneration: false + }, + { + id: 'provider.with.dots', + name: 'Provider With Dots', + creator: vi.fn(() => ({ name: 'dots' })), + supportsImageGeneration: false + } + ] + + const successCount = registerMultipleProviders(specialCharsConfigs) + expect(successCount).toBeGreaterThan(0) // 至少有一些成功 + + // 验证支持的特殊字符格式 + if (isDynamicProvider('provider-with-dashes')) { + expect(getProvider('provider-with-dashes')).toBeDefined() + } + if (isDynamicProvider('provider_with_underscores')) { + expect(getProvider('provider_with_underscores')).toBeDefined() + } + }) + + it('处理空的批量注册', () => { + const successCount = registerMultipleProviders([]) + expect(successCount).toBe(0) + expect(getDynamicProviders()).toEqual([]) + }) + + it('处理重复的 provider 注册', () => { + const config: DynamicProviderRegistration = { + id: 'duplicate-test-provider', + name: 'Duplicate Test Provider', + creator: vi.fn(() => ({ name: 'duplicate' })), + supportsImageGeneration: false + } + + // 第一次注册成功 + expect(registerDynamicProvider(config)).toBe(true) + expect(isDynamicProvider('duplicate-test-provider')).toBe(true) + + // 重复注册相同的 provider + expect(registerDynamicProvider(config)).toBe(true) // 允许覆盖 + expect(isDynamicProvider('duplicate-test-provider')).toBe(true) + + // 验证只有一个实例 + const dynamicProviders = getDynamicProviders() + const duplicateCount = dynamicProviders.filter((id) => id === 'duplicate-test-provider').length + expect(duplicateCount).toBe(1) + }) + }) +}) diff --git a/packages/aiCore/src/core/providers/__tests__/registry.test.ts b/packages/aiCore/src/core/providers/__tests__/registry.test.ts deleted file mode 100644 index 19984bb769..0000000000 --- a/packages/aiCore/src/core/providers/__tests__/registry.test.ts +++ /dev/null @@ -1,131 +0,0 @@ -/** - * 测试真正的 registry 代码 - 尝试不同的导入方式 - */ - -import { beforeEach, describe, expect, it, vi } from 'vitest' - -// 模拟 AI SDK - 使用简单版本 -vi.mock('@ai-sdk/openai', () => ({ - createOpenAI: vi.fn(() => ({ name: 'openai-mock' })) -})) - -vi.mock('@ai-sdk/anthropic', () => ({ - createAnthropic: vi.fn(() => ({ name: 'anthropic-mock' })) -})) - -vi.mock('@ai-sdk/azure', () => ({ - createAzure: vi.fn(() => ({ name: 'azure-mock' })) -})) - -vi.mock('@ai-sdk/deepseek', () => ({ - createDeepSeek: vi.fn(() => ({ name: 'deepseek-mock' })) -})) - -vi.mock('@ai-sdk/google', () => ({ - createGoogleGenerativeAI: vi.fn(() => ({ name: 'google-mock' })) -})) - -vi.mock('@ai-sdk/openai-compatible', () => ({ - createOpenAICompatible: vi.fn(() => ({ name: 'openai-compatible-mock' })) -})) - -vi.mock('@ai-sdk/xai', () => ({ - createXai: vi.fn(() => ({ name: 'xai-mock' })) -})) - -describe('Real Registry Test', () => { - beforeEach(() => { - // 清理模块缓存,强制重新加载 - vi.resetModules() - }) - - it('应该能够通过动态导入访问真正的 registry', async () => { - console.log('🔍 Real test - Testing dynamic import...') - - try { - // 使用动态导入,每次都重新导入 - const { AiProviderRegistry } = await import('../registry') - - console.log('🔍 Real test - AiProviderRegistry imported:', { - type: typeof AiProviderRegistry, - isClass: AiProviderRegistry?.prototype?.constructor === AiProviderRegistry - }) - - if (AiProviderRegistry) { - // 创建新实例,跳过单例模式 - const testRegistry = Object.create(AiProviderRegistry.prototype) - - // 手动调用构造函数逻辑,但跳过有问题的初始化 - testRegistry.registry = new Map() - testRegistry.dynamicMappings = new Map() - testRegistry.dynamicProviders = new Set() - - // 手动添加一些测试数据 - testRegistry.registry.set('test-provider', { - id: 'test-provider', - name: 'Test Provider', - creator: () => ({ name: 'test' }), - supportsImageGeneration: false - }) - - // 测试基本功能 - const allIds = testRegistry.getAllValidProviderIds?.() - console.log('🔍 Real test - getAllValidProviderIds result:', allIds) - - if (allIds) { - expect(Array.isArray(allIds)).toBe(true) - expect(allIds).toContain('test-provider') - } - } - } catch (error) { - console.error('🔍 Real test - Error:', error) - throw error - } - }) - - it('应该能够通过模块原型访问方法', async () => { - console.log('🔍 Real test - Testing prototype access...') - - try { - const registryModule = await import('../registry') - console.log('🔍 Real test - Registry module keys:', Object.keys(registryModule)) - - // 检查是否有任何可用的导出 - const availableExports = Object.keys(registryModule).filter((key) => registryModule[key] !== undefined) - - console.log('🔍 Real test - Available exports:', availableExports) - - if (availableExports.length === 0) { - console.log('🔍 Real test - No exports available, trying alternative approach...') - - // 尝试直接访问模块的内部结构 - const moduleEntries = Object.entries(registryModule) - console.log('🔍 Real test - Module entries:', moduleEntries) - } - } catch (error) { - console.error('🔍 Real test - Prototype access error:', error) - } - }) - - it('应该能够通过 require 访问模块', async () => { - console.log('🔍 Real test - Testing require access...') - - try { - // 尝试使用 require 而不是 import - const path = require('path') - const moduleId = path.resolve(__dirname, '../registry.ts') - - console.log('🔍 Real test - Module ID:', moduleId) - - // 检查模块是否在缓存中 - const cached = require.cache[moduleId] - console.log('🔍 Real test - Module cached:', !!cached) - - if (cached) { - console.log('🔍 Real test - Cached exports:', Object.keys(cached.exports || {})) - } - } catch (error) { - console.error('🔍 Real test - Require access error:', error) - } - }) -}) diff --git a/packages/aiCore/src/core/providers/__tests__/schemas.test.ts b/packages/aiCore/src/core/providers/__tests__/schemas.test.ts new file mode 100644 index 0000000000..3addc0708a --- /dev/null +++ b/packages/aiCore/src/core/providers/__tests__/schemas.test.ts @@ -0,0 +1,393 @@ +import { describe, expect, it, vi } from 'vitest' + +import { + type BaseProviderId, + baseProviderIds, + baseProviderIdSchema, + baseProviders, + type DynamicProviderId, + dynamicProviderIdSchema, + dynamicProviderRegistrationSchema, + getBaseProviderConfig, + isBaseProviderId, + isValidDynamicProviderId, + providerConfigSchema, + type ProviderId, + providerIdSchema, + validateDynamicProviderRegistration, + validateProviderConfig, + validateProviderId +} from '../schemas' + +describe('Provider Schemas', () => { + describe('baseProviders', () => { + it('包含所有预期的基础 providers', () => { + expect(baseProviders).toBeDefined() + expect(Array.isArray(baseProviders)).toBe(true) + expect(baseProviders.length).toBeGreaterThan(0) + + const expectedIds = [ + 'openai', + 'openai-responses', + 'openai-compatible', + 'anthropic', + 'google', + 'xai', + 'azure', + 'deepseek' + ] + const actualIds = baseProviders.map((p) => p.id) + expectedIds.forEach((id) => { + expect(actualIds).toContain(id) + }) + }) + + it('每个基础 provider 有必要的属性', () => { + baseProviders.forEach((provider) => { + expect(provider).toHaveProperty('id') + expect(provider).toHaveProperty('name') + expect(provider).toHaveProperty('creator') + expect(provider).toHaveProperty('supportsImageGeneration') + + expect(typeof provider.id).toBe('string') + expect(typeof provider.name).toBe('string') + expect(typeof provider.creator).toBe('function') + expect(typeof provider.supportsImageGeneration).toBe('boolean') + }) + }) + + it('provider ID 是唯一的', () => { + const ids = baseProviders.map((p) => p.id) + const uniqueIds = [...new Set(ids)] + expect(ids).toEqual(uniqueIds) + }) + }) + + describe('baseProviderIds', () => { + it('正确提取所有基础 provider IDs', () => { + expect(baseProviderIds).toBeDefined() + expect(Array.isArray(baseProviderIds)).toBe(true) + expect(baseProviderIds.length).toBe(baseProviders.length) + + baseProviders.forEach((provider) => { + expect(baseProviderIds).toContain(provider.id) + }) + }) + }) + + describe('baseProviderIdSchema', () => { + it('验证有效的基础 provider IDs', () => { + baseProviderIds.forEach((id) => { + expect(baseProviderIdSchema.safeParse(id).success).toBe(true) + }) + }) + + it('拒绝无效的基础 provider IDs', () => { + const invalidIds = ['invalid', 'not-exists', ''] + invalidIds.forEach((id) => { + expect(baseProviderIdSchema.safeParse(id).success).toBe(false) + }) + }) + }) + + describe('dynamicProviderIdSchema', () => { + it('接受有效的动态 provider IDs', () => { + const validIds = ['custom-provider', 'my-ai-service', 'company-llm-v2'] + validIds.forEach((id) => { + expect(dynamicProviderIdSchema.safeParse(id).success).toBe(true) + }) + }) + + it('拒绝与基础 provider IDs 冲突的 IDs', () => { + baseProviderIds.forEach((id) => { + expect(dynamicProviderIdSchema.safeParse(id).success).toBe(false) + }) + }) + + it('拒绝空字符串', () => { + expect(dynamicProviderIdSchema.safeParse('').success).toBe(false) + }) + }) + + describe('providerIdSchema', () => { + it('接受基础 provider IDs', () => { + baseProviderIds.forEach((id) => { + expect(providerIdSchema.safeParse(id).success).toBe(true) + }) + }) + + it('接受有效的动态 provider IDs', () => { + const validDynamicIds = ['custom-provider', 'my-ai-service'] + validDynamicIds.forEach((id) => { + expect(providerIdSchema.safeParse(id).success).toBe(true) + }) + }) + + it('拒绝无效的 IDs', () => { + const invalidIds = ['', undefined, null, 123] + invalidIds.forEach((id) => { + expect(providerIdSchema.safeParse(id).success).toBe(false) + }) + }) + }) + + describe('providerConfigSchema', () => { + it('验证带有 creator 的有效配置', () => { + const validConfig = { + id: 'openai', + name: 'OpenAI', + creator: vi.fn(), + supportsImageGeneration: true + } + expect(providerConfigSchema.safeParse(validConfig).success).toBe(true) + }) + + it('验证带有 import 配置的有效配置', () => { + const validConfig = { + id: 'custom-provider', + name: 'Custom Provider', + import: vi.fn(), + creatorFunctionName: 'createCustom', + supportsImageGeneration: false + } + expect(providerConfigSchema.safeParse(validConfig).success).toBe(true) + }) + + it('拒绝既没有 creator 也没有 import 配置的配置', () => { + const invalidConfig = { + id: 'invalid', + name: 'Invalid Provider', + supportsImageGeneration: false + } + expect(providerConfigSchema.safeParse(invalidConfig).success).toBe(false) + }) + + it('为 supportsImageGeneration 设置默认值', () => { + const config = { + id: 'test', + name: 'Test', + creator: vi.fn() + } + const result = providerConfigSchema.safeParse(config) + expect(result.success).toBe(true) + if (result.success) { + expect(result.data.supportsImageGeneration).toBe(false) + } + }) + + it('拒绝缺少必需字段的配置', () => { + const invalidConfigs = [ + { name: 'Missing ID', creator: vi.fn() }, + { id: 'missing-name', creator: vi.fn() }, + { id: '', name: 'Empty ID', creator: vi.fn() }, + { id: 'valid', name: '', creator: vi.fn() } + ] + + invalidConfigs.forEach((config) => { + expect(providerConfigSchema.safeParse(config).success).toBe(false) + }) + }) + }) + + describe('dynamicProviderRegistrationSchema', () => { + it('验证有效的动态 provider 注册配置', () => { + const validConfig = { + id: 'custom-provider', + name: 'Custom Provider', + creator: vi.fn(), + supportsImageGeneration: true, + mappings: { model1: 'mapped-model1' } + } + expect(dynamicProviderRegistrationSchema.safeParse(validConfig).success).toBe(true) + }) + + it('拒绝使用基础 provider ID 的配置', () => { + const invalidConfig = { + id: 'openai', + name: 'Should Fail', + creator: vi.fn() + } + expect(dynamicProviderRegistrationSchema.safeParse(invalidConfig).success).toBe(false) + }) + + it('要求 creator 或 import 配置', () => { + const configWithoutCreator = { + id: 'custom-provider', + name: 'Custom Provider' + } + expect(dynamicProviderRegistrationSchema.safeParse(configWithoutCreator).success).toBe(false) + }) + }) + + describe('validateProviderId', () => { + it('验证基础 provider IDs', () => { + baseProviderIds.forEach((id) => { + expect(validateProviderId(id)).toBe(true) + }) + }) + + it('验证有效的动态 provider IDs', () => { + const validDynamicIds = ['custom-provider', 'my-service', 'company-llm'] + validDynamicIds.forEach((id) => { + expect(validateProviderId(id)).toBe(true) + }) + }) + + it('拒绝无效的 IDs', () => { + const invalidIds = [undefined as any, null as any, 123 as any] + invalidIds.forEach((id) => { + expect(validateProviderId(id)).toBe(false) + }) + + // 空字符串和只有空格的字符串会被当作有效的动态 provider ID + expect(validateProviderId('')).toBe(false) + }) + }) + + describe('isBaseProviderId', () => { + it('正确识别基础 provider IDs', () => { + baseProviderIds.forEach((id) => { + expect(isBaseProviderId(id)).toBe(true) + }) + }) + + it('拒绝动态 provider IDs', () => { + const dynamicIds = ['custom-provider', 'my-service'] + dynamicIds.forEach((id) => { + expect(isBaseProviderId(id)).toBe(false) + }) + }) + + it('拒绝无效的 IDs', () => { + const invalidIds = ['', 'invalid', undefined as any] + invalidIds.forEach((id) => { + expect(isBaseProviderId(id)).toBe(false) + }) + }) + }) + + describe('isValidDynamicProviderId', () => { + it('接受有效的动态 provider IDs', () => { + const validIds = ['custom-provider', 'my-ai-service', 'company-llm-v2'] + validIds.forEach((id) => { + expect(isValidDynamicProviderId(id)).toBe(true) + }) + }) + + it('拒绝基础 provider IDs', () => { + baseProviderIds.forEach((id) => { + expect(isValidDynamicProviderId(id)).toBe(false) + }) + }) + + it('拒绝无效的 IDs', () => { + const invalidIds = [undefined as any, null as any] + invalidIds.forEach((id) => { + expect(isValidDynamicProviderId(id)).toBe(false) + }) + + // 空字符串会被 schema 拒绝 + expect(isValidDynamicProviderId('')).toBe(false) + // 只有空格的字符串是有效的动态 provider ID(但不推荐使用) + expect(isValidDynamicProviderId(' ')).toBe(true) + }) + }) + + describe('validateProviderConfig', () => { + it('返回有效配置', () => { + const validConfig = { + id: 'openai', + name: 'OpenAI', + creator: vi.fn(), + supportsImageGeneration: true + } + const result = validateProviderConfig(validConfig) + expect(result).not.toBeNull() + expect(result?.id).toBe('openai') + expect(result?.name).toBe('OpenAI') + }) + + it('对无效配置返回 null', () => { + const invalidConfig = { + id: '', + name: 'Invalid' + } + const result = validateProviderConfig(invalidConfig) + expect(result).toBeNull() + }) + + it('处理完全无效的输入', () => { + const invalidInputs = [undefined, null, 'string', 123, []] + invalidInputs.forEach((input) => { + const result = validateProviderConfig(input) + expect(result).toBeNull() + }) + }) + }) + + describe('validateDynamicProviderRegistration', () => { + it('返回有效的动态 provider 注册配置', () => { + const validConfig = { + id: 'custom-provider', + name: 'Custom Provider', + creator: vi.fn(), + mappings: { model1: 'mapped-model1' } + } + const result = validateDynamicProviderRegistration(validConfig) + expect(result).not.toBeNull() + expect(result?.id).toBe('custom-provider') + expect(result?.name).toBe('Custom Provider') + }) + + it('对无效配置返回 null', () => { + const invalidConfig = { + id: 'openai', + name: 'Should Fail' + } + const result = validateDynamicProviderRegistration(invalidConfig) + expect(result).toBeNull() + }) + }) + + describe('getBaseProviderConfig', () => { + it('返回有效基础 provider ID 的配置', () => { + const config = getBaseProviderConfig('openai') + expect(config).toBeDefined() + expect(config?.id).toBe('openai') + expect(config?.name).toBe('OpenAI') + expect(config?.creator).toBeDefined() + }) + + it('对无效 ID 返回 undefined', () => { + const config = getBaseProviderConfig('invalid' as BaseProviderId) + expect(config).toBeUndefined() + }) + + it('返回所有基础 providers 的配置', () => { + baseProviderIds.forEach((id) => { + const config = getBaseProviderConfig(id) + expect(config).toBeDefined() + expect(config?.id).toBe(id) + }) + }) + }) + + describe('类型推导', () => { + it('BaseProviderId 类型正确', () => { + const id: BaseProviderId = 'openai' + expect(baseProviderIds).toContain(id) + }) + + it('DynamicProviderId 类型是字符串', () => { + const id: DynamicProviderId = 'custom-provider' + expect(typeof id).toBe('string') + }) + + it('ProviderId 类型支持基础和动态 IDs', () => { + const baseId: ProviderId = 'openai' + const dynamicId: ProviderId = 'custom-provider' + expect(typeof baseId).toBe('string') + expect(typeof dynamicId).toBe('string') + }) + }) +}) diff --git a/packages/aiCore/src/core/providers/schemas.ts b/packages/aiCore/src/core/providers/schemas.ts index c7ed0cc406..c003e6de36 100644 --- a/packages/aiCore/src/core/providers/schemas.ts +++ b/packages/aiCore/src/core/providers/schemas.ts @@ -173,7 +173,6 @@ export function validateProviderConfig(config: unknown): ProviderConfig | null { if (result.success) { return result.data } - console.error('Invalid provider config:', result.error.errors) return null } @@ -185,7 +184,6 @@ export function validateDynamicProviderRegistration(config: unknown): DynamicPro if (result.success) { return result.data } - console.error('Invalid dynamic provider registration:', result.error.errors) return null } diff --git a/packages/aiCore/vitest.config.ts b/packages/aiCore/vitest.config.ts index e59e598d32..0cc6b51df4 100644 --- a/packages/aiCore/vitest.config.ts +++ b/packages/aiCore/vitest.config.ts @@ -2,10 +2,7 @@ import { defineConfig } from 'vitest/config' export default defineConfig({ test: { - globals: true, - environment: 'node', - setupFiles: ['./setupVitest.ts'], - include: ['src/**/*.{test,spec}.{ts,tsx}', 'src/**/__tests__/**/*.{test,spec}.{ts,tsx}'] + globals: true }, resolve: { alias: { diff --git a/yarn.lock b/yarn.lock index 372f8404f1..92e688a820 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2205,7 +2205,7 @@ __metadata: ai: "npm:5.0.0" tsdown: "npm:^0.12.9" typescript: "npm:^5.0.0" - vitest: "npm:^1.0.0" + vitest: "npm:^3.2.4" zod: "npm:^3.25.0" languageName: unknown linkType: soft @@ -3737,15 +3737,6 @@ __metadata: languageName: node linkType: hard -"@jest/schemas@npm:^29.6.3": - version: 29.6.3 - resolution: "@jest/schemas@npm:29.6.3" - dependencies: - "@sinclair/typebox": "npm:^0.27.8" - checksum: 10c0/b329e89cd5f20b9278ae1233df74016ebf7b385e0d14b9f4c1ad18d096c4c19d1e687aa113a9c976b16ec07f021ae53dea811fb8c1248a50ac34fbe009fdf6be - languageName: node - linkType: hard - "@jridgewell/gen-mapping@npm:^0.3.12, @jridgewell/gen-mapping@npm:^0.3.5": version: 0.3.12 resolution: "@jridgewell/gen-mapping@npm:0.3.12" @@ -5849,13 +5840,6 @@ __metadata: languageName: node linkType: hard -"@sinclair/typebox@npm:^0.27.8": - version: 0.27.8 - resolution: "@sinclair/typebox@npm:0.27.8" - checksum: 10c0/ef6351ae073c45c2ac89494dbb3e1f87cc60a93ce4cde797b782812b6f97da0d620ae81973f104b43c9b7eaa789ad20ba4f6a1359f1cc62f63729a55a7d22d4e - languageName: node - linkType: hard - "@sindresorhus/is@npm:^4.0.0": version: 4.6.0 resolution: "@sindresorhus/is@npm:4.6.0" @@ -8642,17 +8626,6 @@ __metadata: languageName: node linkType: hard -"@vitest/expect@npm:1.6.1": - version: 1.6.1 - resolution: "@vitest/expect@npm:1.6.1" - dependencies: - "@vitest/spy": "npm:1.6.1" - "@vitest/utils": "npm:1.6.1" - chai: "npm:^4.3.10" - checksum: 10c0/278164b2a32a7019b443444f21111c5e32e4cadee026cae047ae2a3b347d99dca1d1fb7b79509c88b67dc3db19fa9a16265b7d7a8377485f7e37f7851e44495a - languageName: node - linkType: hard - "@vitest/expect@npm:3.2.4": version: 3.2.4 resolution: "@vitest/expect@npm:3.2.4" @@ -8694,17 +8667,6 @@ __metadata: languageName: node linkType: hard -"@vitest/runner@npm:1.6.1": - version: 1.6.1 - resolution: "@vitest/runner@npm:1.6.1" - dependencies: - "@vitest/utils": "npm:1.6.1" - p-limit: "npm:^5.0.0" - pathe: "npm:^1.1.1" - checksum: 10c0/36333f1a596c4ad85d42c6126cc32959c984d584ef28d366d366fa3672678c1a0f5e5c2e8717a36675b6620b57e8830f765d6712d1687f163ed0a8ebf23c87db - languageName: node - linkType: hard - "@vitest/runner@npm:3.2.4": version: 3.2.4 resolution: "@vitest/runner@npm:3.2.4" @@ -8716,17 +8678,6 @@ __metadata: languageName: node linkType: hard -"@vitest/snapshot@npm:1.6.1": - version: 1.6.1 - resolution: "@vitest/snapshot@npm:1.6.1" - dependencies: - magic-string: "npm:^0.30.5" - pathe: "npm:^1.1.1" - pretty-format: "npm:^29.7.0" - checksum: 10c0/68bbc3132c195ec37376469e4b183fc408e0aeedd827dffcc899aac378e9ea324825f0873062786e18f00e3da9dd8a93c9bb871c07471ee483e8df963cb272eb - languageName: node - linkType: hard - "@vitest/snapshot@npm:3.2.4": version: 3.2.4 resolution: "@vitest/snapshot@npm:3.2.4" @@ -8738,15 +8689,6 @@ __metadata: languageName: node linkType: hard -"@vitest/spy@npm:1.6.1": - version: 1.6.1 - resolution: "@vitest/spy@npm:1.6.1" - dependencies: - tinyspy: "npm:^2.2.0" - checksum: 10c0/5207ec0e7882819f0e0811293ae6d14163e26927e781bb4de7d40b3bd99c1fae656934c437bb7a30443a3e7e736c5bccb037bbf4436dbbc83d29e65247888885 - languageName: node - linkType: hard - "@vitest/spy@npm:3.2.4": version: 3.2.4 resolution: "@vitest/spy@npm:3.2.4" @@ -8773,18 +8715,6 @@ __metadata: languageName: node linkType: hard -"@vitest/utils@npm:1.6.1": - version: 1.6.1 - resolution: "@vitest/utils@npm:1.6.1" - dependencies: - diff-sequences: "npm:^29.6.3" - estree-walker: "npm:^3.0.3" - loupe: "npm:^2.3.7" - pretty-format: "npm:^29.7.0" - checksum: 10c0/0d4c619e5688cbc22a60c412719c6baa40376b7671bdbdc3072552f5c5a5ee5d24a96ea328b054018debd49e0626a5e3db672921b2c6b5b17b9a52edd296806a - languageName: node - linkType: hard - "@vitest/utils@npm:3.2.4": version: 3.2.4 resolution: "@vitest/utils@npm:3.2.4" @@ -9169,24 +9099,6 @@ __metadata: languageName: node linkType: hard -"acorn-walk@npm:^8.3.2": - version: 8.3.4 - resolution: "acorn-walk@npm:8.3.4" - dependencies: - acorn: "npm:^8.11.0" - checksum: 10c0/76537ac5fb2c37a64560feaf3342023dadc086c46da57da363e64c6148dc21b57d49ace26f949e225063acb6fb441eabffd89f7a3066de5ad37ab3e328927c62 - languageName: node - linkType: hard - -"acorn@npm:^8.11.0": - version: 8.15.0 - resolution: "acorn@npm:8.15.0" - bin: - acorn: bin/acorn - checksum: 10c0/dec73ff59b7d6628a01eebaece7f2bdb8bb62b9b5926dcad0f8931f2b8b79c2be21f6c68ac095592adb5adb15831a3635d9343e6a91d028bbe85d564875ec3ec - languageName: node - linkType: hard - "acorn@npm:^8.14.0": version: 8.14.1 resolution: "acorn@npm:8.14.1" @@ -9667,13 +9579,6 @@ __metadata: languageName: node linkType: hard -"assertion-error@npm:^1.1.0": - version: 1.1.0 - resolution: "assertion-error@npm:1.1.0" - checksum: 10c0/25456b2aa333250f01143968e02e4884a34588a8538fbbf65c91a637f1dbfb8069249133cd2f4e530f10f624d206a664e7df30207830b659e9f5298b00a4099b - languageName: node - linkType: hard - "assertion-error@npm:^2.0.1": version: 2.0.1 resolution: "assertion-error@npm:2.0.1" @@ -10268,21 +10173,6 @@ __metadata: languageName: node linkType: hard -"chai@npm:^4.3.10": - version: 4.5.0 - resolution: "chai@npm:4.5.0" - dependencies: - assertion-error: "npm:^1.1.0" - check-error: "npm:^1.0.3" - deep-eql: "npm:^4.1.3" - get-func-name: "npm:^2.0.2" - loupe: "npm:^2.3.6" - pathval: "npm:^1.1.1" - type-detect: "npm:^4.1.0" - checksum: 10c0/b8cb596bd1aece1aec659e41a6e479290c7d9bee5b3ad63d2898ad230064e5b47889a3bc367b20100a0853b62e026e2dc514acf25a3c9385f936aa3614d4ab4d - languageName: node - linkType: hard - "chai@npm:^5.2.0": version: 5.2.0 resolution: "chai@npm:5.2.0" @@ -10396,15 +10286,6 @@ __metadata: languageName: node linkType: hard -"check-error@npm:^1.0.3": - version: 1.0.3 - resolution: "check-error@npm:1.0.3" - dependencies: - get-func-name: "npm:^2.0.2" - checksum: 10c0/94aa37a7315c0e8a83d0112b5bfb5a8624f7f0f81057c73e4707729cdd8077166c6aefb3d8e2b92c63ee130d4a2ff94bad46d547e12f3238cc1d78342a973841 - languageName: node - linkType: hard - "check-error@npm:^2.1.1": version: 2.1.1 resolution: "check-error@npm:2.1.1" @@ -11688,15 +11569,6 @@ __metadata: languageName: node linkType: hard -"deep-eql@npm:^4.1.3": - version: 4.1.4 - resolution: "deep-eql@npm:4.1.4" - dependencies: - type-detect: "npm:^4.0.0" - checksum: 10c0/264e0613493b43552fc908f4ff87b8b445c0e6e075656649600e1b8a17a57ee03e960156fce7177646e4d2ddaf8e5ee616d76bd79929ff593e5c79e4e5e6c517 - languageName: node - linkType: hard - "deep-eql@npm:^5.0.1": version: 5.0.2 resolution: "deep-eql@npm:5.0.2" @@ -11896,13 +11768,6 @@ __metadata: languageName: node linkType: hard -"diff-sequences@npm:^29.6.3": - version: 29.6.3 - resolution: "diff-sequences@npm:29.6.3" - checksum: 10c0/32e27ac7dbffdf2fb0eb5a84efd98a9ad084fbabd5ac9abb8757c6770d5320d2acd172830b28c4add29bb873d59420601dfc805ac4064330ce59b1adfd0593b2 - languageName: node - linkType: hard - "diff@npm:^7.0.0": version: 7.0.0 resolution: "diff@npm:7.0.0" @@ -13896,13 +13761,6 @@ __metadata: languageName: node linkType: hard -"get-func-name@npm:^2.0.1, get-func-name@npm:^2.0.2": - version: 2.0.2 - resolution: "get-func-name@npm:2.0.2" - checksum: 10c0/89830fd07623fa73429a711b9daecdb304386d237c71268007f788f113505ef1d4cc2d0b9680e072c5082490aec9df5d7758bf5ac6f1c37062855e8e3dc0b9df - languageName: node - linkType: hard - "get-intrinsic@npm:^1.2.5, get-intrinsic@npm:^1.2.6, get-intrinsic@npm:^1.3.0": version: 1.3.0 resolution: "get-intrinsic@npm:1.3.0" @@ -15912,16 +15770,6 @@ __metadata: languageName: node linkType: hard -"local-pkg@npm:^0.5.0": - version: 0.5.1 - resolution: "local-pkg@npm:0.5.1" - dependencies: - mlly: "npm:^1.7.3" - pkg-types: "npm:^1.2.1" - checksum: 10c0/ade8346f1dc04875921461adee3c40774b00d4b74095261222ebd4d5fd0a444676e36e325f76760f21af6a60bc82480e154909b54d2d9f7173671e36dacf1808 - languageName: node - linkType: hard - "local-pkg@npm:^1.0.0": version: 1.1.1 resolution: "local-pkg@npm:1.1.1" @@ -16081,15 +15929,6 @@ __metadata: languageName: node linkType: hard -"loupe@npm:^2.3.6, loupe@npm:^2.3.7": - version: 2.3.7 - resolution: "loupe@npm:2.3.7" - dependencies: - get-func-name: "npm:^2.0.1" - checksum: 10c0/71a781c8fc21527b99ed1062043f1f2bb30bdaf54fa4cf92463427e1718bc6567af2988300bc243c1f276e4f0876f29e3cbf7b58106fdc186915687456ce5bf4 - languageName: node - linkType: hard - "loupe@npm:^3.1.0": version: 3.1.3 resolution: "loupe@npm:3.1.3" @@ -16189,7 +16028,7 @@ __metadata: languageName: node linkType: hard -"magic-string@npm:^0.30.17, magic-string@npm:^0.30.5": +"magic-string@npm:^0.30.17": version: 0.30.17 resolution: "magic-string@npm:0.30.17" dependencies: @@ -17617,7 +17456,7 @@ __metadata: languageName: node linkType: hard -"mlly@npm:^1.7.3, mlly@npm:^1.7.4": +"mlly@npm:^1.7.4": version: 1.7.4 resolution: "mlly@npm:1.7.4" dependencies: @@ -18294,15 +18133,6 @@ __metadata: languageName: node linkType: hard -"p-limit@npm:^5.0.0": - version: 5.0.0 - resolution: "p-limit@npm:5.0.0" - dependencies: - yocto-queue: "npm:^1.0.0" - checksum: 10c0/574e93b8895a26e8485eb1df7c4b58a1a6e8d8ae41b1750cc2cc440922b3d306044fc6e9a7f74578a883d46802d9db72b30f2e612690fcef838c173261b1ed83 - languageName: node - linkType: hard - "p-locate@npm:^3.0.0": version: 3.0.0 resolution: "p-locate@npm:3.0.0" @@ -18574,13 +18404,6 @@ __metadata: languageName: node linkType: hard -"pathe@npm:^1.1.1": - version: 1.1.2 - resolution: "pathe@npm:1.1.2" - checksum: 10c0/64ee0a4e587fb0f208d9777a6c56e4f9050039268faaaaecd50e959ef01bf847b7872785c36483fa5cdcdbdfdb31fef2ff222684d4fc21c330ab60395c681897 - languageName: node - linkType: hard - "pathe@npm:^2.0.1, pathe@npm:^2.0.3": version: 2.0.3 resolution: "pathe@npm:2.0.3" @@ -18588,13 +18411,6 @@ __metadata: languageName: node linkType: hard -"pathval@npm:^1.1.1": - version: 1.1.1 - resolution: "pathval@npm:1.1.1" - checksum: 10c0/f63e1bc1b33593cdf094ed6ff5c49c1c0dc5dc20a646ca9725cc7fe7cd9995002d51d5685b9b2ec6814342935748b711bafa840f84c0bb04e38ff40a335c94dc - languageName: node - linkType: hard - "pathval@npm:^2.0.0": version: 2.0.0 resolution: "pathval@npm:2.0.0" @@ -18669,7 +18485,7 @@ __metadata: languageName: node linkType: hard -"picocolors@npm:^1.0.0, picocolors@npm:^1.1.1": +"picocolors@npm:^1.1.1": version: 1.1.1 resolution: "picocolors@npm:1.1.1" checksum: 10c0/e2e3e8170ab9d7c7421969adaa7e1b31434f789afb9b3f115f6b96d91945041ac3ceb02e9ec6fe6510ff036bcc0bf91e69a1772edc0b707e12b19c0f2d6bcf58 @@ -18736,7 +18552,7 @@ __metadata: languageName: node linkType: hard -"pkg-types@npm:^1.2.1, pkg-types@npm:^1.3.0": +"pkg-types@npm:^1.3.0": version: 1.3.1 resolution: "pkg-types@npm:1.3.1" dependencies: @@ -18928,17 +18744,6 @@ __metadata: languageName: node linkType: hard -"pretty-format@npm:^29.7.0": - version: 29.7.0 - resolution: "pretty-format@npm:29.7.0" - dependencies: - "@jest/schemas": "npm:^29.6.3" - ansi-styles: "npm:^5.0.0" - react-is: "npm:^18.0.0" - checksum: 10c0/edc5ff89f51916f036c62ed433506b55446ff739358de77207e63e88a28ca2894caac6e73dcb68166a606e51c8087d32d400473e6a9fdd2dbe743f46c9c0276f - languageName: node - linkType: hard - "proc-log@npm:^2.0.1": version: 2.0.1 resolution: "proc-log@npm:2.0.1" @@ -21307,7 +21112,7 @@ __metadata: languageName: node linkType: hard -"std-env@npm:^3.5.0, std-env@npm:^3.9.0": +"std-env@npm:^3.9.0": version: 3.9.0 resolution: "std-env@npm:3.9.0" checksum: 10c0/4a6f9218aef3f41046c3c7ecf1f98df00b30a07f4f35c6d47b28329bc2531eef820828951c7d7b39a1c5eb19ad8a46e3ddfc7deb28f0a2f3ceebee11bab7ba50 @@ -21514,15 +21319,6 @@ __metadata: languageName: node linkType: hard -"strip-literal@npm:^2.0.0": - version: 2.1.1 - resolution: "strip-literal@npm:2.1.1" - dependencies: - js-tokens: "npm:^9.0.1" - checksum: 10c0/66a7353f5ba1ae6a4fb2805b4aba228171847200640083117c41512692e6b2c020e18580402984f55c0ae69c30f857f9a55abd672863e4ca8fdb463fdf93ba19 - languageName: node - linkType: hard - "strip-literal@npm:^3.0.0": version: 3.0.0 resolution: "strip-literal@npm:3.0.0" @@ -21850,7 +21646,7 @@ __metadata: languageName: node linkType: hard -"tinybench@npm:^2.5.1, tinybench@npm:^2.9.0": +"tinybench@npm:^2.9.0": version: 2.9.0 resolution: "tinybench@npm:2.9.0" checksum: 10c0/c3500b0f60d2eb8db65250afe750b66d51623057ee88720b7f064894a6cb7eb93360ca824a60a31ab16dab30c7b1f06efe0795b352e37914a9d4bad86386a20c @@ -21891,13 +21687,6 @@ __metadata: languageName: node linkType: hard -"tinypool@npm:^0.8.3": - version: 0.8.4 - resolution: "tinypool@npm:0.8.4" - checksum: 10c0/779c790adcb0316a45359652f4b025958c1dff5a82460fe49f553c864309b12ad732c8288be52f852973bc76317f5e7b3598878aee0beb8a33322c0e72c4a66c - languageName: node - linkType: hard - "tinypool@npm:^1.1.1": version: 1.1.1 resolution: "tinypool@npm:1.1.1" @@ -21912,13 +21701,6 @@ __metadata: languageName: node linkType: hard -"tinyspy@npm:^2.2.0": - version: 2.2.1 - resolution: "tinyspy@npm:2.2.1" - checksum: 10c0/0b4cfd07c09871e12c592dfa7b91528124dc49a4766a0b23350638c62e6a483d5a2a667de7e6282246c0d4f09996482ddaacbd01f0c05b7ed7e0f79d32409bdc - languageName: node - linkType: hard - "tinyspy@npm:^4.0.3": version: 4.0.3 resolution: "tinyspy@npm:4.0.3" @@ -22234,13 +22016,6 @@ __metadata: languageName: node linkType: hard -"type-detect@npm:^4.0.0, type-detect@npm:^4.1.0": - version: 4.1.0 - resolution: "type-detect@npm:4.1.0" - checksum: 10c0/df8157ca3f5d311edc22885abc134e18ff8ffbc93d6a9848af5b682730ca6a5a44499259750197250479c5331a8a75b5537529df5ec410622041650a7f293e2a - languageName: node - linkType: hard - "type-fest@npm:^0.13.1": version: 0.13.1 resolution: "type-fest@npm:0.13.1" @@ -22823,21 +22598,6 @@ __metadata: languageName: node linkType: hard -"vite-node@npm:1.6.1": - version: 1.6.1 - resolution: "vite-node@npm:1.6.1" - dependencies: - cac: "npm:^6.7.14" - debug: "npm:^4.3.4" - pathe: "npm:^1.1.1" - picocolors: "npm:^1.0.0" - vite: "npm:^5.0.0" - bin: - vite-node: vite-node.mjs - checksum: 10c0/4d96da9f11bd0df8b60c46e65a740edaad7dd2d1aff3cdb3da5714ea8c10b5f2683111b60bfe45545c7e8c1f33e7e8a5095573d5e9ba55f50a845233292c2e02 - languageName: node - linkType: hard - "vite-node@npm:3.2.4": version: 3.2.4 resolution: "vite-node@npm:3.2.4" @@ -22908,56 +22668,6 @@ __metadata: languageName: node linkType: hard -"vitest@npm:^1.0.0": - version: 1.6.1 - resolution: "vitest@npm:1.6.1" - dependencies: - "@vitest/expect": "npm:1.6.1" - "@vitest/runner": "npm:1.6.1" - "@vitest/snapshot": "npm:1.6.1" - "@vitest/spy": "npm:1.6.1" - "@vitest/utils": "npm:1.6.1" - acorn-walk: "npm:^8.3.2" - chai: "npm:^4.3.10" - debug: "npm:^4.3.4" - execa: "npm:^8.0.1" - local-pkg: "npm:^0.5.0" - magic-string: "npm:^0.30.5" - pathe: "npm:^1.1.1" - picocolors: "npm:^1.0.0" - std-env: "npm:^3.5.0" - strip-literal: "npm:^2.0.0" - tinybench: "npm:^2.5.1" - tinypool: "npm:^0.8.3" - vite: "npm:^5.0.0" - vite-node: "npm:1.6.1" - why-is-node-running: "npm:^2.2.2" - peerDependencies: - "@edge-runtime/vm": "*" - "@types/node": ^18.0.0 || >=20.0.0 - "@vitest/browser": 1.6.1 - "@vitest/ui": 1.6.1 - happy-dom: "*" - jsdom: "*" - peerDependenciesMeta: - "@edge-runtime/vm": - optional: true - "@types/node": - optional: true - "@vitest/browser": - optional: true - "@vitest/ui": - optional: true - happy-dom: - optional: true - jsdom: - optional: true - bin: - vitest: vitest.mjs - checksum: 10c0/511d27d7f697683964826db2fad7ac303f9bc7eeb59d9422111dc488371ccf1f9eed47ac3a80eb47ca86b7242228ba5ca9cc3613290830d0e916973768cac215 - languageName: node - linkType: hard - "vitest@npm:^3.2.4": version: 3.2.4 resolution: "vitest@npm:3.2.4" @@ -23233,7 +22943,7 @@ __metadata: languageName: node linkType: hard -"why-is-node-running@npm:^2.2.2, why-is-node-running@npm:^2.3.0": +"why-is-node-running@npm:^2.3.0": version: 2.3.0 resolution: "why-is-node-running@npm:2.3.0" dependencies: @@ -23573,13 +23283,6 @@ __metadata: languageName: node linkType: hard -"yocto-queue@npm:^1.0.0": - version: 1.2.1 - resolution: "yocto-queue@npm:1.2.1" - checksum: 10c0/5762caa3d0b421f4bdb7a1926b2ae2189fc6e4a14469258f183600028eb16db3e9e0306f46e8ebf5a52ff4b81a881f22637afefbef5399d6ad440824e9b27f9f - languageName: node - linkType: hard - "zip-stream@npm:^6.0.1": version: 6.0.1 resolution: "zip-stream@npm:6.0.1"