@yss123/cage-files 0.3.2 → 0.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/README.md +14 -86
  2. package/package.json +2 -2
package/README.md CHANGED
@@ -1,100 +1,28 @@
1
1
  # @yss123/cage-files
2
2
 
3
- Cage 的私有文件服务。管理上传会话、可恢复分片、SHA-256 校验、配额、私有下载和过期清理,内置本地磁盘实现,并提供自定义对象存储适配接口。适合业务附件;字段声明和业务事务内绑定仍由 kernel 负责。
3
+ 私有字节服务:上传会话、可恢复分片、摘要、配额、授权下载与过期清理。字段原语与业务事务绑定属于 kernel,本包不直接保存领域业务结果。
4
4
 
5
- 上传完成只得到临时文件 ID,调用业务命令成功后才正式绑定。文件字节、存储路径和公开 URL 不进入业务字段。
5
+ ## 使用位置
6
6
 
7
- ## 安装与服务端配置
8
-
9
- 需要 Node.js 24+、PostgreSQL 和持久存储,与其他 Cage 包保持同版本:
10
-
11
- ```powershell
12
- pnpm add @yss123/cage-files
13
- ```
14
-
15
- 标准 `@yss123/cage-http` 已装配本包。定制存储时在 API 入口配置,以下例子里的 `@app/domain` 来自脚手架应用:
7
+ 在服务端安装 pnpm add @yss123/cage-files,Node.js 24+、PostgreSQL 和持久存储由环境提供。标准 cage-http 已装配服务;需要自定义时在 createServer 的 files 选项提供 FileStorage 或 LocalFileStorage。
16
8
 
17
9
  ```ts
18
- /** API 私有文件装配;目录持久保存,不能作为静态资源公开。 */
19
- import { createServer } from '@yss123/cage-http';
20
10
  import { LocalFileStorage } from '@yss123/cage-files';
21
- import * as domain from '@app/domain';
22
11
 
23
- const server = createServer({
24
- domain,
25
- files: {
26
- storage: new LocalFileStorage('.cage-files'),
27
- partBytes: 16 * 1024 * 1024,
28
- maxFileBytes: 2 * 1024 ** 3,
29
- retentionMs: 24 * 3600_000,
30
- },
31
- });
32
- await server.listen();
33
- process.once('SIGINT', () => void server.close());
34
- process.once('SIGTERM', () => void server.close());
12
+ /** 交给 HTTP 的 files 配置,目录需持久保存且不能作为公开静态目录。 */
13
+ const files = {
14
+ storage: new LocalFileStorage('.cage-files'),
15
+ partBytes: 16 * 1024 * 1024,
16
+ maxFileBytes: 2 * 1024 ** 3,
17
+ };
35
18
  ```
36
19
 
37
- 未传 `storage` 时会创建本地实现,目录由 `files.directory`、`CAGE_FILES_DIR` 或默认 `.cage-files` 决定。这个目录不属于可再生的 `.cage`;容器应使用持久卷,数据库元数据与文件字节应配套备份。
38
-
39
- ## 业务接入的三个步骤
40
-
41
- 1. 在聚合 `fields` 使用 kernel 的 `file/files`,并在目标用户命令 input 中声明同名 UUID 或 UUID 数组。字段只能位于聚合顶层。
42
- 2. 运行 `pnpm gen`,审查迁移并执行 `pnpm migrate`,授予目标命令及所需读取/范围能力。
43
- 3. 浏览器使用 `client.upload` 上传,成功后将返回 ID 交给目标业务命令;字段绑定与业务记录同事务提交。
44
-
45
- 字段片段合并到已有聚合,不能单独作为完整 domain:
46
-
47
- ```ts
48
- import { files } from '@yss123/cage-kernel';
49
-
50
- // 每个文件最多 20 MiB、最多 5 个,仅允许明确的 MIME 类型。
51
- const attachments = files({
52
- maxCount: 5,
53
- maxBytes: 20 * 1024 * 1024,
54
- accept: ['application/pdf', 'image/png'],
55
- });
56
- // 放入聚合 fields: { attachments };命令 input 需同名 z.array(z.string().uuid())。
57
- ```
58
-
59
- 下例为采购模板的页面操作,`selectedFile` 来自文件选择框。其他业务应替换目标命令、字段与生成契约:
60
-
61
- ```ts
62
- import { client, purchaseOrder } from '@app/contracts';
63
-
64
- /** 上传失败会抛错;业务保存失败仍须展示结果,不能把上传成功当作订单已保存。 */
65
- async function createWithAttachment(selectedFile: File) {
66
- const task = client.upload(selectedFile, {
67
- command: 'PurchaseOrder.create',
68
- field: 'attachments',
69
- });
70
- try {
71
- const uploaded = await task.start();
72
- return await purchaseOrder.create({
73
- amount: '100.00',
74
- items: [{ sku: 'A-01', qty: 1 }],
75
- attachments: [uploaded.id],
76
- });
77
- } finally {
78
- task.dispose();
79
- }
80
- }
81
- ```
82
-
83
- 调用方捕获上传异常并检查返回值 `ok`。修改已有记录时,上传目标还须传 `targetId`。刷新后通过客户端查询本人会话,重新选择原文件,再传 `uploadId` 恢复;SDK 会核对已确认分片内容。
84
-
85
- ## 公开入口与边界
86
-
87
- | 入口 | 作用 |
88
- | --- | --- |
89
- | `FileService`、`FileServiceOptions` | 协调授权、会话、配额、上传、下载和清理;通常由 HTTP 层持有 |
90
- | `LocalFileStorage` | 流式写入、校验、合并及范围读取的磁盘实现 |
91
- | `FileStorage`、`StoredPart`、`ByteRange` | 自定义存储协议;适配 writePart/complete/read/remove/prune |
92
- | `beginUploadSchema`、`UploadSession`、`FileInfo` | 服务端输入校验与公开上传/文件描述 |
20
+ 应用的 file/files 字段声明 MIME、字节和数量,用户命令 input 接收文件 ID。浏览器使用 cage-client 上传,ready 后再调用领域命令绑定,业务失败不等于正式保存成功。
93
21
 
94
- 一个文件只能绑定一个对象的一个字段,不能覆盖原文件;替换需新 ID。下载依当前 Cookie 会话、对象范围和字段引用重新授权,不提供永久公开链接。分片/完成操作的预检查不保证最终命令必定通过。
22
+ ## 生命周期
95
23
 
96
- API 启动后及每分钟执行有界清理;独立持有 `FileService` 时须自行定期调用 `cleanup()`,退出时 `close()`。本地多实例必须共享同一目录,不能只共享数据库。代理需允许分片请求体、关闭上传缓冲并配置合并超时。
24
+ 上传支持暂停和摘要核对后续传;下载每次检查当前绑定对象授权。已绑定文件通过业务命令移除,临时文件按策略清理。长 IO 使用租约与 token 防迟到回写。
97
25
 
98
- 目前只内置本地存储;`FileStorage` 不代表已提供 S3/OSS SDK 或签名直传。内容头校验也不等于病毒扫描或完整格式验证。
26
+ 内置本地存储和对象存储适配接口,尚无内置 S3/OSS、签名直传、病毒扫描或共享文件服务。部署需规划持久化、配额及清理,完成上传与业务提交分别显示。
99
27
 
100
- 完整说明:[私有文件字段与断点续传](https://github.com/shunshunyue/cage/blob/main/docs/development/guides/files.md)。源码与反馈:[GitHub](https://github.com/shunshunyue/cage)。许可证:[MIT](https://github.com/shunshunyue/cage/blob/main/LICENSE)。
28
+ [附件接入](https://github.com/shunshunyue/cage/blob/main/docs/development/guides/files.md) · [事务边界](https://github.com/shunshunyue/cage/blob/main/docs/development/reference/execution.md)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@yss123/cage-files",
3
- "version": "0.3.2",
3
+ "version": "0.4.1",
4
4
  "description": "Cage 私有文件与可恢复分片上传:本地存储及对象存储适配接口",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -18,7 +18,7 @@
18
18
  "kysely": "^0.28.5",
19
19
  "zod": "^4.1.5",
20
20
  "file-type": "^21.0.0",
21
- "@yss123/cage-kernel": "0.3.2"
21
+ "@yss123/cage-kernel": "0.4.1"
22
22
  },
23
23
  "license": "MIT",
24
24
  "repository": {