Domain Model
@nx/assetkhông sở hữu schema nào. Entity duy nhất nó đọc/ghi —MetaLink— được định nghĩa trong@nx/coređể các package khác (commerce, ledger) có thể tham chiếu mà không gây dependency vòng.
1. ERD đầy đủ
Quan hệ là đa hình mềm —
principalIdlà một cộttextthường, được resolve với bảng nào khớpprincipalType. Không có khóa ngoại DB.
2. Entities
MetaLink
| Thuộc tính | Giá trị |
|---|---|
| Bảng | public.MetaLink |
| Nguồn | packages/core/src/models/schemas/public/meta-link/schema.ts |
| Soft-delete | không — dùng timestamp generateTzColumnDefs(); asset xóa qua hard deleteAll |
| Cột Owner ID | principalId (đa hình, optional) |
Trường:
| Trường | Kiểu | Bắt buộc | Mặc định | Mô tả |
|---|---|---|---|---|
id | text | ✓ | Snowflake | Khóa chính |
bucketName | text | ✓ | — | Bucket S3/Minio |
objectName | text | ✓ | — | Object key trong bucket |
link | text | ✓ | — | Path truy cập tương đối (/assets/objects/{name}) |
mimetype | text | ✓ | — | Content type từ stat metadata |
size | integer | ✓ | — | Kích thước object theo byte |
etag | text | — | S3 etag | |
variant | text | — | Tag variant do caller cung cấp (vd vai trò thumbnail) | |
metadata | jsonb | — | Record<string, any> — stat metadata thô của S3 | |
storageType | text | ✓ | — | Hiện luôn là s3 |
isSynced | boolean | ✓ | false | True khi MetaLink phản chiếu object đã lưu (đặt khi upload) |
principalType | text | — | Loại entity sở hữu — xem enum | |
principalId | text | — | ID entity sở hữu | |
createdAt / updatedAt | timestamp | ✓ | now() | Từ generateTzColumnDefs() |
Enum principal type (MetaLinkPrincipalTypes):
| Giá trị | Mô tả |
|---|---|
Product | Ảnh / tài liệu sản phẩm |
ProductVariant | Media riêng cho variant |
Organizer | Branding của Organizer |
Ledger | PDF/XLSX được tạo (output ledger) |
Category | Artwork danh mục |
Định nghĩa
MetaLink.relations()trong core cũng khai báo quan hệmerchantvàuser(khớp trênprincipalId), dù các giá trị đó không nằm trong tập validationMetaLinkPrincipalTypes.
Index & constraint:
| Tên | Cột | Loại |
|---|---|---|
PK_MetaLink | id | Khóa chính |
IDX_MetaLink_bucket_name | bucketName | Btree |
IDX_MetaLink_object_name | objectName | Btree |
IDX_MetaLink_storage_type | storageType | Btree |
IDX_MetaLink_is_synced | isSynced | Btree |
IDX_MetaLink_principal_type_principal_id | principalType, principalId | Btree (composite) |
IDX_MetaLink_principal_id | principalId | Btree |
Quan hệ:
| Trường | Cardinality | Tham chiếu |
|---|---|---|
principalId (type Product) | M:1 | Product.id |
principalId (type ProductVariant) | M:1 | ProductVariant.id |
principalId (type Organizer) | M:1 | Organizer.id |
principalId (type Ledger) | M:1 | Ledger.id |
principalId (type Category) | M:1 | Category.id |
3. Bất biến xuyên entity
| Bất biến | Cách thực thi |
|---|---|
Một MetaLink phản chiếu đúng một object đã lưu (bucketName + objectName) | Tạo trong cùng handler với helper.upload |
| Xóa một object sẽ xóa các bản ghi MetaLink của nó | AssetController deleteAll({ where: { bucketName, objectName } }) sau removeObject (best-effort, async) |
storageType = 's3' | Hardcode khi create — không có backend khác hoạt động (xem ADR-0001) |
Owner đa hình chỉ resolve khi principalType ∈ MetaLinkPrincipalTypes | MetaLinkPrincipalTypes.isValid() (helper validation, không phải constraint DB) |
4. Hành vi Soft-delete
| Hành vi | Chi tiết |
|---|---|
| Đọc mặc định | Mọi bản ghi hiển thị — MetaLink không có cột deletedAt |
| Hard-delete | Có — deleteAll khi xóa object; CRUD /meta-links deleteById/deleteBy |
| Restore | Không hỗ trợ |