mirror of
https://github.com/fsolla/teqo.git
synced 2026-11-13 15:13:07 +00:00
- payload.config.ts: vercelBlobStorage -> s3Storage (@payloadcms/storage-s3) com endpoint Garage (forcePathStyle, region garage); bucket privado — o staticHandler do plugin streama os objetos em /api/media/file/<filename>, mantendo o contrato de URL relativa das 40 rows pré-existentes - src/utilities/mediaStorage.ts: resolveS3StorageEnv fail-closed (S3_* parcial -> throw no boot com a lista exata; nenhuma -> storage local dev/test) - seed-posts: remove pre-delete do @vercel/blob (S3 sobrescreve nativamente) - worktree-env.mjs: s3EnvCopiedLines all-or-nothing (unit-testada) - envs S3_BUCKET/S3_ENDPOINT/S3_REGION/S3_ACCESS_KEY_ID/S3_SECRET_ACCESS_KEY no .env.example/.env.test; cloud-setup.sh sem o sed morto do blob - deps: -storage-vercel-blob -@vercel/blob +storage-s3; importMap regenerado - docs: impl plan (revisão A->B: Garage v2 sem acesso anônimo na API S3), AGENTS.md, changelog 2026-08-18-ops52
56 lines
1.9 KiB
TypeScript
56 lines
1.9 KiB
TypeScript
// @vitest-environment node
|
|
|
|
import { describe, expect, it } from 'vitest'
|
|
|
|
import { resolveS3StorageEnv, S3_STORAGE_ENV_KEYS } from '../../src/utilities/mediaStorage'
|
|
|
|
const fullEnv = (): Record<string, string> => ({
|
|
S3_BUCKET: 'teqo-media',
|
|
S3_ENDPOINT: 'http://100.119.220.31:3900',
|
|
S3_ACCESS_KEY_ID: 'AK-test',
|
|
S3_SECRET_ACCESS_KEY: 'secret',
|
|
})
|
|
|
|
describe('resolveS3StorageEnv (OPS52)', () => {
|
|
it('desabilita o storage S3 quando nenhuma env S3_* está presente', () => {
|
|
expect(resolveS3StorageEnv({})).toEqual({ enabled: false })
|
|
expect(resolveS3StorageEnv({ DATABASE_URL: 'x', PAYLOAD_SECRET: 'y' })).toEqual({
|
|
enabled: false,
|
|
})
|
|
})
|
|
|
|
it('habilita o storage com todas as envs e region default do Garage', () => {
|
|
expect(resolveS3StorageEnv(fullEnv())).toEqual({
|
|
enabled: true,
|
|
bucket: 'teqo-media',
|
|
endpoint: 'http://100.119.220.31:3900',
|
|
region: 'garage',
|
|
accessKeyId: 'AK-test',
|
|
secretAccessKey: 'secret',
|
|
})
|
|
})
|
|
|
|
it('aceita S3_REGION explícita', () => {
|
|
const resolved = resolveS3StorageEnv({ ...fullEnv(), S3_REGION: 'garage-dev' })
|
|
expect(resolved.enabled && resolved.region).toBe('garage-dev')
|
|
})
|
|
|
|
it('lança com a lista exata de envs faltantes na configuração parcial', () => {
|
|
const partial: Record<string, string> = { ...fullEnv() }
|
|
delete partial.S3_SECRET_ACCESS_KEY
|
|
delete partial.S3_ENDPOINT
|
|
expect(() => resolveS3StorageEnv(partial)).toThrowError(
|
|
/faltam S3_ENDPOINT, S3_SECRET_ACCESS_KEY/,
|
|
)
|
|
})
|
|
|
|
it('ignora envs setadas com valor em branco na contagem de parcial', () => {
|
|
const env = { ...fullEnv(), S3_BUCKET: ' ' }
|
|
expect(() => resolveS3StorageEnv(env)).toThrowError(/faltam S3_BUCKET/)
|
|
})
|
|
|
|
it('lista todas as envs esperadas como obrigatórias (exceto region)', () => {
|
|
expect(S3_STORAGE_ENV_KEYS).toHaveLength(4)
|
|
expect(S3_STORAGE_ENV_KEYS).not.toContain('S3_REGION')
|
|
})
|
|
})
|