tldraw/packages/tlschema/src/createTLSchema.ts
Steve Ruiz fd29006538
[feature] add meta property to records (#1627)
This PR adds a `meta` property to shapes and other records.

It adds it to:
- asset
- camera
- document
- instance
- instancePageState
- instancePresence
- page
- pointer
- rootShape

## Setting meta

This data can generally be added wherever you would normally update the
corresponding record.

An exception exists for shapes, which can be updated using a partial of
the `meta` in the same way that we update shapes with a partial of
`props`.

```ts
this.updateShapes([{
    id: myShape.id,
    type: "geo",
    meta: { 
      nemesis: "steve",
      special: true
    }
])
```

## `Editor.getInitialMetaForShape`

The `Editor.getInitialMetaForShape` method is kind of a hack to set the
initial meta property for newly created shapes. You can set it
externally. Escape hatch!

### Change Type

- [x] `minor` — New feature

### Test Plan

todo

- [ ] Unit Tests (todo)

### Release Notes

- todo
2023-06-28 14:24:05 +00:00

65 lines
2.3 KiB
TypeScript

import { Migrations, StoreSchema } from '@tldraw/store'
import { objectMapValues } from '@tldraw/utils'
import { TLStoreProps, createIntegrityChecker, onValidationFailure } from './TLStore'
import { AssetRecordType } from './records/TLAsset'
import { CameraRecordType } from './records/TLCamera'
import { DocumentRecordType } from './records/TLDocument'
import { createInstanceRecordType } from './records/TLInstance'
import { PageRecordType } from './records/TLPage'
import { InstancePageStateRecordType } from './records/TLPageState'
import { PointerRecordType } from './records/TLPointer'
import { InstancePresenceRecordType } from './records/TLPresence'
import { TLRecord } from './records/TLRecord'
import { createShapeRecordType, getShapePropKeysByStyle } from './records/TLShape'
import { storeMigrations } from './store-migrations'
import { StyleProp } from './styles/StyleProp'
/** @public */
export type SchemaShapeInfo = {
migrations?: Migrations
props?: Record<string, { validate: (prop: any) => any }>
meta?: Record<string, { validate: (prop: any) => any }>
}
/** @public */
export type TLSchema = StoreSchema<TLRecord, TLStoreProps>
/**
* Create a TLSchema with custom shapes. Custom shapes cannot override default shapes.
*
* @param opts - Options
*
* @public */
export function createTLSchema({ shapes }: { shapes: Record<string, SchemaShapeInfo> }): TLSchema {
const stylesById = new Map<string, StyleProp<unknown>>()
for (const shape of objectMapValues(shapes)) {
for (const style of getShapePropKeysByStyle(shape.props ?? {}).keys()) {
if (stylesById.has(style.id) && stylesById.get(style.id) !== style) {
throw new Error(`Multiple StyleProp instances with the same id: ${style.id}`)
}
stylesById.set(style.id, style)
}
}
const ShapeRecordType = createShapeRecordType(shapes)
const InstanceRecordType = createInstanceRecordType(stylesById)
return StoreSchema.create(
{
asset: AssetRecordType,
camera: CameraRecordType,
document: DocumentRecordType,
instance: InstanceRecordType,
instance_page_state: InstancePageStateRecordType,
page: PageRecordType,
shape: ShapeRecordType,
instance_presence: InstancePresenceRecordType,
pointer: PointerRecordType,
},
{
snapshotMigrations: storeMigrations,
onValidationFailure,
createIntegrityChecker: createIntegrityChecker,
}
)
}