S3 兼容存储桶(R2、S3、MinIO)与本地磁盘的文件存储,支持签名直传
代码11 个文件上下文约 697 个 token扫描通过
安装
$
genpm add @core/storage你将获得
- 源代码位于 src/lib/storage/,共 11 个文件。 (22.7 kB)
- AI 规则位于 src/lib/storage/AGENTS.md,另附 IDE 规则文件。
- 添加到 .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
此包没有 README。
约 697 个 token→ src/lib/storage/AGENTS.md→ .cursor/rules/genpm-core-storage.mdc
这正是你的 AI 在 src/lib/storage 中工作时读取的内容。不会向其上下文添加其他任何内容。
@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.
应用 .genpmignore 后将被注入的确切目录树。固定于
// Adaptador Hono (solo drivers `local`/`memory`): `app.route('/api/storage', localStorageRoutes())`.
import { Hono } from 'hono';
import { getStorage, handleLocalDownload, handleLocalUpload } from '../index.ts';
export function localStorageRoutes(secret = process.env.STORAGE_SECRET ?? '', routePath = '/api/storage') {
return new Hono()
.put('/', (c) => handleLocalUpload(c.req.raw, getStorage(), secret))
.get('/*', (c) => handleLocalDownload(c.req.raw, getStorage(), secret, routePath));
}
此包未声明 MCP 服务器。
| 版本 | 提交 | 发布时间 | 扫描 |
|---|---|---|---|
| 1.0.1 | 5b6a9cc | 8小时前 | 扫描通过 |
- genpm
- 无
- 建议
- GenPM 会给出 npm 命令建议,只有你同意时才会运行。
- 被以下包使用(1)
- @core/media ^1.0.0
- 扫描
- 扫描通过 · 0 个问题
- 提交
- v1.0.1 → 5b6a9cc5574ad638d71214af234145082f01cb98 · 获取后已校验
- 脚本
- 无。GenPM 从不运行包中的代码。
- 许可证
- MIT
- 质量
- 100/100
- 可识别的许可证已满足
- AGENTS.md 说明了用途已满足
- AGENTS.md 包含集成步骤已满足
- AGENTS.md 列出约定或禁止事项已满足
- 包含测试已满足
- 通过安全扫描已满足
- 最近 6 个月内发布已满足
- 已验证的发布者已满足
- 摘要和关键词已满足
- 举报
- 发现问题了吗?