@tldraw/tlschema
Version:
tldraw infinite canvas SDK (schema).
156 lines (149 loc) • 3.89 kB
text/typescript
import { createMigrationIds, createRecordMigrationSequence } from '@tldraw/store'
import { T } from '@tldraw/validate'
import { RecordProps } from '../recordsWithProps'
import { TLBaseAsset, createAssetValidator } from './TLBaseAsset'
/**
* An asset for images such as PNGs and JPEGs, used by the TLImageShape.
*
* @public */
export type TLImageAsset = TLBaseAsset<
'image',
{
w: number
h: number
name: string
isAnimated: boolean
mimeType: string | null
src: string | null
fileSize?: number
pixelRatio?: number
}
>
/** @public */
export const imageAssetProps = {
w: T.number,
h: T.number,
name: T.string,
isAnimated: T.boolean,
mimeType: T.string.nullable(),
src: T.srcUrl.nullable(),
fileSize: T.nonZeroNumber.optional(),
pixelRatio: T.positiveNumber.optional(),
} satisfies RecordProps<TLImageAsset>
/** Validator for image assets. @public */
export const imageAssetValidator: T.Validator<TLImageAsset> = createAssetValidator(
'image',
T.object(imageAssetProps)
)
const Versions = createMigrationIds('com.tldraw.asset.image', {
AddIsAnimated: 1,
RenameWidthHeight: 2,
MakeUrlsValid: 3,
AddFileSize: 4,
MakeFileSizeOptional: 5,
AddPixelRatio: 6,
} as const)
/**
* Migration version identifiers for image assets. These define the different schema versions
* that image assets have gone through during the evolution of the tldraw data model.
*
* @example
* ```ts
* import { imageAssetVersions } from '@tldraw/tlschema'
*
* // Access specific version IDs
* console.log(imageAssetVersions.AddIsAnimated) // Version when isAnimated was added
* console.log(imageAssetVersions.RenameWidthHeight) // Version when width/height became w/h
* ```
*
* @public
*/
export { Versions as imageAssetVersions }
/**
* Migration sequence for image assets. Handles the evolution of the image asset schema
* over time, providing both forward (up) and backward (down) migration functions to
* maintain compatibility across different versions of the tldraw data model.
*
* The sequence includes migrations for:
* - Adding the `isAnimated` property to track animated images
* - Renaming `width`/`height` properties to shorter `w`/`h` names
* - Ensuring URLs are valid format
* - Adding file size tracking
* - Making file size optional
*
*
* @public
*/
export const imageAssetMigrations = createRecordMigrationSequence({
sequenceId: 'com.tldraw.asset.image',
recordType: 'asset',
filter: (asset) => (asset as TLImageAsset).type === 'image',
sequence: [
{
id: Versions.AddIsAnimated,
up: (asset: any) => {
asset.props.isAnimated = false
},
down: (asset: any) => {
delete asset.props.isAnimated
},
},
{
id: Versions.RenameWidthHeight,
up: (asset: any) => {
asset.props.w = asset.props.width
asset.props.h = asset.props.height
delete asset.props.width
delete asset.props.height
},
down: (asset: any) => {
asset.props.width = asset.props.w
asset.props.height = asset.props.h
delete asset.props.w
delete asset.props.h
},
},
{
id: Versions.MakeUrlsValid,
up: (asset: any) => {
if (!T.srcUrl.isValid(asset.props.src)) {
asset.props.src = ''
}
},
down: (_asset) => {
// noop
},
},
{
id: Versions.AddFileSize,
up: (asset: any) => {
asset.props.fileSize = -1
},
down: (asset: any) => {
delete asset.props.fileSize
},
},
{
id: Versions.MakeFileSizeOptional,
up: (asset: any) => {
if (asset.props.fileSize === -1) {
asset.props.fileSize = undefined
}
},
down: (asset: any) => {
if (asset.props.fileSize === undefined) {
asset.props.fileSize = -1
}
},
},
{
id: Versions.AddPixelRatio,
up: (_asset: any) => {
// noop — pixelRatio is optional and undefined by default
},
down: (asset: any) => {
delete asset.props.pixelRatio
},
},
],
})