mirror of
https://github.com/CherryHQ/cherry-studio.git
synced 2025-12-27 21:01:32 +08:00
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.
This commit is contained in:
parent
d93a36e5c9
commit
5d0ab0a9a1
@ -48,7 +48,7 @@
|
||||
"devDependencies": {
|
||||
"tsdown": "^0.12.9",
|
||||
"typescript": "^5.0.0",
|
||||
"vitest": "^1.0.0"
|
||||
"vitest": "^3.2.4"
|
||||
},
|
||||
"sideEffects": false,
|
||||
"engines": {
|
||||
|
||||
@ -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)
|
||||
})
|
||||
})
|
||||
})
|
||||
@ -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)
|
||||
}
|
||||
})
|
||||
})
|
||||
393
packages/aiCore/src/core/providers/__tests__/schemas.test.ts
Normal file
393
packages/aiCore/src/core/providers/__tests__/schemas.test.ts
Normal file
@ -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')
|
||||
})
|
||||
})
|
||||
})
|
||||
@ -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
|
||||
}
|
||||
|
||||
|
||||
@ -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: {
|
||||
|
||||
313
yarn.lock
313
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"
|
||||
|
||||
Loading…
Reference in New Issue
Block a user