Assets
Asset management with file upload, storage integration, and schema-driven validation.
Database schema
The assetsTable stores asset metadata linked to files via @repo/storage:
import { assetsTable, assetsRelations } from '@repo/cms/database'
| Column | Type | Description |
|---|---|---|
id | uuid | Primary key |
name | text | Asset name (required) |
description | text | Optional description |
fileId | uuid | FK to filesTable (cascade delete) |
createdBy | text | User who created |
updatedBy | text | User who last updated |
The assetsRelations defines a one-to-one relation to filesTable.
Zod schemas
Auto-generated schemas for validation:
import {
assetsTableInsertSchema,
assetsTableSelectSchema,
assetsTableUpdateSchema,
} from '@repo/cms'
Additional schemas for form integration:
import { assetInsertSchema, getAssetUpdateSchema, assetListSchema } from '@repo/cms'
assetInsertSchema-- wrapsfileInsertSchemawithFileField.RootcomponentgetAssetUpdateSchema(clientFileManager)-- includes optional file replacement with URL previewassetListSchema-- partial pick ofnameanddescriptionfor list filtering
AssetRepository
Server-side CRUD for assets. Extends Repository from @repo/db.
import { AssetRepository } from '@repo/cms/server'
const repo = new AssetRepository(getDbContext, serverFileManager, fileRepository, clientFileManager)
Methods
| Method | Description |
|---|---|
get(id) | Fetch asset with file metadata |
overview(config) | Paginated list with count |
select(config?) | Returns { label, value }[] for dropdowns |
listWithUrl(ids?) | Returns { [id]: { url } } map for rendering |
create(data) | Upload file and create asset record |
update(data, id) | Update metadata, optionally replace file |
remove(id) | Delete asset and its file (cascade) |
Usage in a remote function
import { query } from '$app/server'
import { AssetRepository } from '@repo/cms/server'
import { z } from 'zod'
export const getAssets = query(z.object({}), async () => {
const repo = new AssetRepository(getDbContext, serverFileManager, fileRepository, clientFileManager)
return repo.overview({ page: 1, perPage: 20 })
})
Asset references in blocks
Reference assets in block schemas using zaf with a group:
import { zaf } from '@repo/form'
import { z } from 'zod'
const schema = z.object({
image: zaf(z.string(), {
component: AssetAutocompleteField,
group: 'assets',
}),
})
The group option lets getGroupsFromBlocks collect all asset IDs across blocks for batch loading:
import { getGroupsFromBlocks } from '@repo/cms'
const groups = getGroupsFromBlocks({ value: blockValues, blocks })
const assetUrls = await assetRepo.listWithUrl(groups.assets)
Types
import type { Asset, AssetWithFile } from '@repo/cms'
// Asset = assetsTable.$inferSelect
// AssetWithFile = Asset & { file: ManagedFile }