feat: initial release v0.3.0

This commit is contained in:
saturn
2026-03-08 03:15:27 +08:00
commit 881ed44996
1311 changed files with 225407 additions and 0 deletions

View File

@@ -0,0 +1,161 @@
/**
* 模拟完整的图像生成和显示流程
* 运行: npx tsx scripts/test-full-image-flow.ts
*/
import { config } from 'dotenv'
config()
import { uploadObject, getStorageProvider } from '../src/lib/storage'
import { extractStorageKeyFromLegacyValue, resolveMediaRefFromLegacyValue, getMediaObjectByPublicId } from '../src/lib/media/service'
import { attachMediaFieldsToProject } from '../src/lib/media/attach'
import { randomUUID } from 'crypto'
async function testFullImageFlow() {
console.log('🧪 模拟完整图像生成和显示流程...\n')
const provider = getStorageProvider()
console.log(`存储类型: ${provider.kind}\n`)
// 1. 模拟图像生成后的上传
console.log('1⃣ 模拟图像生成后上传:')
const testKey = `images/location-${randomUUID()}.jpg`
const testImageContent = Buffer.from('fake-generated-image-data')
const storedKey = await uploadObject(testImageContent, testKey)
console.log(` ✅ 上传成功,返回 key: ${storedKey}`)
// 2. 模拟数据库存储(存储 key
console.log('\n2⃣ 模拟数据库存储:')
const mockDbLocation = {
id: 'loc-test-123',
name: '测试场景',
images: [
{
id: 'img-1',
imageUrl: storedKey, // 存储的是 key不是完整 URL
imageIndex: 0,
}
]
}
console.log(` 存储的 imageUrl: ${storedKey}`)
// 3. 测试 extractStorageKeyFromLegacyValue
console.log('\n3⃣ 测试 extractStorageKeyFromLegacyValue:')
const extractedKey = extractStorageKeyFromLegacyValue(storedKey)
console.log(` 输入: ${storedKey}`)
console.log(` 输出: ${extractedKey}`)
if (extractedKey) {
console.log(` ✅ 成功提取 storageKey`)
} else {
console.log(` ❌ 未能提取 storageKey - 这是问题所在!`)
}
// 4. 测试 resolveMediaRefFromLegacyValue创建 MediaObject
console.log('\n4⃣ 测试 resolveMediaRefFromLegacyValue:')
try {
const mediaRef = await resolveMediaRefFromLegacyValue(storedKey)
if (mediaRef) {
console.log(` ✅ MediaObject 创建/获取成功`)
console.log(` id: ${mediaRef.id}`)
console.log(` publicId: ${mediaRef.publicId}`)
console.log(` url: ${mediaRef.url}`)
console.log(` storageKey: ${mediaRef.storageKey}`)
} else {
console.log(` ❌ MediaRef 为 null`)
}
} catch (error) {
console.log(` ❌ 失败:`, error)
}
// 5. 测试 attachMediaFieldsToProject完整流程
console.log('\n5⃣ 测试 attachMediaFieldsToProjectAPI 层转换):')
try {
const mockProject = {
id: 'proj-test',
locations: [mockDbLocation]
}
const result = await attachMediaFieldsToProject(mockProject)
const location = result.locations?.[0]
const image = location?.images?.[0]
console.log(` 转换后的 imageUrl: ${image?.imageUrl}`)
if (image?.imageUrl?.startsWith('/m/')) {
console.log(` ✅ 正确生成了 /m/ 格式的 URL`)
// 提取 publicId
const publicId = image.imageUrl.replace('/m/', '').split('?')[0]
console.log(` publicId: ${publicId}`)
// 验证 MediaObject 存在
const media = await getMediaObjectByPublicId(publicId)
if (media) {
console.log(` ✅ MediaObject 存在storageKey: ${media.storageKey}`)
} else {
console.log(` ❌ MediaObject 不存在!`)
}
} else if (image?.imageUrl?.startsWith('http')) {
console.log(` ⚠️ 返回了完整 HTTP URL: ${image.imageUrl}`)
} else if (!image?.imageUrl) {
console.log(` ❌ imageUrl 为空!`)
} else {
console.log(` ⚠️ URL 格式: ${image.imageUrl}`)
}
} catch (error) {
console.log(` ❌ 失败:`, error)
}
// 6. 测试访问 /m/ URL
console.log('\n6⃣ 测试访问 /m/ URL:')
try {
const mockProject = {
id: 'proj-test',
locations: [mockDbLocation]
}
const result = await attachMediaFieldsToProject(mockProject)
const imageUrl = result.locations?.[0]?.images?.[0]?.imageUrl
if (imageUrl?.startsWith('/m/')) {
const fullUrl = `http://localhost:3000${imageUrl}`
console.log(` 尝试访问: ${fullUrl}`)
try {
const response = await fetch(fullUrl, { redirect: 'manual' })
console.log(` 状态: ${response.status}`)
if (response.status === 200) {
console.log(` ✅ /m/ 端点工作正常`)
} else if (response.status === 307 || response.status === 302) {
console.log(` ✅ /m/ 端点返回重定向(正常)`)
console.log(` Location: ${response.headers.get('location')?.substring(0, 80)}...`)
} else if (response.status === 404) {
console.log(` ❌ MediaObject 未找到404`)
} else {
console.log(` ⚠️ 状态码: ${response.status}`)
}
} catch (error) {
console.log(` ⚠️ 请求失败(可能服务器未启动):`, error)
}
} else {
console.log(` 跳过测试URL 格式不正确)`)
}
} catch (error) {
console.log(` 跳过测试:`, error)
}
// 清理
console.log('\n7⃣ 清理测试数据:')
try {
const { deleteObject } = await import('../src/lib/storage')
await deleteObject(storedKey)
console.log(` ✅ 删除成功`)
} catch (error) {
console.log(` ⚠️ 删除失败:`, error)
}
console.log('\n✨ 测试完成!')
}
testFullImageFlow().catch(console.error)