Armazenamento de arquivos em buckets compatíveis com S3 (R2, S3, MinIO) e disco local, com uploads assinados
Instalar
genpm add @core/storageO que você recebe
- Código em src/lib/storage/, 11 arquivos. (22,7 kB)
- Regras de IA em src/lib/storage/AGENTS.md, mais arquivos de regras da IDE.
- Variáveis de ambiente adicionadas ao .env.example: STORAGE_DRIVER, STORAGE_BUCKET, STORAGE_ENDPOINT, STORAGE_ACCESS_KEY_ID, STORAGE_SECRET_ACCESS_KEY, STORAGE_PUBLIC_URL, STORAGE_SECRET, STORAGE_LOCAL_DIR.
README
Este pacote não tem README.
Isto é exatamente o que sua IA lê quando trabalha em src/lib/storage. Nada mais é adicionado ao contexto dela.
@core/storage — rules for AI agents
Purpose
One StorageProvider interface to store and serve files: S3-compatible buckets (Cloudflare R2, AWS S3, MinIO, B2)
signed with SigV4 (aws4fetch, works on Node and Workers), plus local (disk) and memory drivers for development
and tests. Signed direct uploads from the browser with the exact size and content type signed. No media library,
no image processing (that is @core/media). No tables.
Map
index.ts— public API:getStorage(),setStorage(),generateKey(),assertSafeKey(),s3Storage(), types.s3.ts— S3 driver.memory.ts— local/memory drivers and signed tokens.local-routes.ts— handlers for them.adapters/hono.ts,adapters/next.ts— upload/download route, only needed withlocal/memory.
Integration
- Env for S3/R2 (default driver):
STORAGE_ENDPOINT(R2:https://<account>.r2.cloudflarestorage.com),STORAGE_BUCKET,STORAGE_ACCESS_KEY_ID,STORAGE_SECRET_ACCESS_KEY, optionalSTORAGE_REGION(defaultauto) andSTORAGE_PUBLIC_URL(CDN/custom domain serving thepublic/prefix). Local dev:STORAGE_DRIVER=local,STORAGE_SECRET(≥ 32 chars),STORAGE_PUBLIC_URL=http://localhost:3000(files go toSTORAGE_LOCAL_DIR, default.storage/: add it to.gitignore), and mount the route: Honoapp.route('/api/storage', localStorageRoutes()); Next.jsapp/api/storage/[[...key]]/route.tswithexport { localStoragePut as PUT, localStorageGet as GET } from '@/lib/storage/adapters/next'. - Bucket CORS (S3/R2): allow
PUTfrom your origin with headercontent-type. - Direct upload: server creates
const key = generateKey('public/media', file.name)andawait getStorage().presignUpload(key, { contentType, size, maxBytes: 10_000_000 }); the browser doesfetch(url, { method: 'PUT', headers, body: file }). - Verify: upload a small file, then
getStorage().head(key)returns its size.
Conventions
- Keys are generated by the server (
generateKey); never use the user's filename or path as the key. - Everything is private unless its key starts with
public/; serve private files withpresignDownloadafter an authorization check. - Store the key in your table, not the URL (URLs change with the CDN or driver).
- A presigned upload URL can be reused until it expires. If the server validates or transforms the file after upload,
presign a private key (e.g.
uploads/pending/…) and have the server copy the validated bytes to the finalpublic/key.
Don't
- Don't make the whole bucket public or proxy private files without checking permissions.
- Don't trust the client's content type for security decisions; @core/media sniffs the real type after upload.
- Don't log storage credentials or presigned URLs.
# @core/storage — rules for AI agents
## Purpose
One `StorageProvider` interface to store and serve files: S3-compatible buckets (Cloudflare R2, AWS S3, MinIO, B2)
signed with SigV4 (`aws4fetch`, works on Node and Workers), plus `local` (disk) and `memory` drivers for development
and tests. Signed direct uploads from the browser with the exact size and content type signed. No media library,
no image processing (that is @core/media). No tables.
## Map
- `index.ts` — public API: `getStorage()`, `setStorage()`, `generateKey()`, `assertSafeKey()`, `s3Storage()`, types.
- `s3.ts` — S3 driver. `memory.ts` — local/memory drivers and signed tokens. `local-routes.ts` — handlers for them.
- `adapters/hono.ts`, `adapters/next.ts` — upload/download route, only needed with `local`/`memory`.
## Integration
1. Env for S3/R2 (default driver): `STORAGE_ENDPOINT` (R2: `https://<account>.r2.cloudflarestorage.com`),
`STORAGE_BUCKET`, `STORAGE_ACCESS_KEY_ID`, `STORAGE_SECRET_ACCESS_KEY`, optional `STORAGE_REGION` (default `auto`)
and `STORAGE_PUBLIC_URL` (CDN/custom domain serving the `public/` prefix).
Local dev: `STORAGE_DRIVER=local`, `STORAGE_SECRET` (≥ 32 chars), `STORAGE_PUBLIC_URL=http://localhost:3000`
(files go to `STORAGE_LOCAL_DIR`, default `.storage/`: add it to `.gitignore`), and
mount the route: Hono `app.route('/api/storage', localStorageRoutes())`; Next.js
`app/api/storage/[[...key]]/route.ts` with `export { localStoragePut as PUT, localStorageGet as GET } from '@/lib/storage/adapters/next'`.
2. Bucket CORS (S3/R2): allow `PUT` from your origin with header `content-type`.
3. Direct upload: server creates `const key = generateKey('public/media', file.name)` and
`await getStorage().presignUpload(key, { contentType, size, maxBytes: 10_000_000 })`; the browser does
`fetch(url, { method: 'PUT', headers, body: file })`.
4. Verify: upload a small file, then `getStorage().head(key)` returns its size.
## Conventions
- Keys are generated by the server (`generateKey`); never use the user's filename or path as the key.
- Everything is private unless its key starts with `public/`; serve private files with `presignDownload` after an authorization check.
- Store the key in your table, not the URL (URLs change with the CDN or driver).
- A presigned upload URL can be reused until it expires. If the server validates or transforms the file after upload,
presign a private key (e.g. `uploads/pending/…`) and have the server copy the validated bytes to the final `public/` key.
## Don't
- Don't make the whole bucket public or proxy private files without checking permissions.
- Don't trust the client's content type for security decisions; @core/media sniffs the real type after upload.
- Don't log storage credentials or presigned URLs.
A árvore exata que será injetada, após o .genpmignore. Fixada em
Este pacote não declara servidores MCP.
| Versão | Commit | Publicado | Análise |
|---|---|---|---|
| 1.0.1 | 5b6a9cc | há 2 horas | análise aprovada |
- genpm
- nenhum
- proposto
- O GenPM propõe o comando npm e só o executa se você disser sim.
- Usado por (1)
- @core/media ^1.0.0
- análise
- análise aprovada · 0 achados
- commit
- v1.0.1 → 5b6a9cc5574ad638d71214af234145082f01cb98 · verificado após o download
- scripts
- Nenhum. O GenPM nunca executa código de pacotes.
- licença
- MIT
- Qualidade
- 100/100
- Licença reconhecidacumprido
- AGENTS.md explica o propósitocumprido
- AGENTS.md tem passos de integraçãocumprido
- AGENTS.md lista convenções ou proibiçõescumprido
- Inclui testescumprido
- Escaneamento de segurança aprovadocumprido
- Publicado nos últimos 6 mesescumprido
- Publicador verificadocumprido
- Resumo e palavras-chavecumprido
- denúncia
- Viu algo errado?