From 53be9239218d051b05dad3723520d0cabc62f239 Mon Sep 17 00:00:00 2001 From: Steve Ruiz Date: Mon, 22 May 2023 22:46:24 +0100 Subject: [PATCH] [refactor] record migrations (#1430) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This PR removes comments from our record types, makes initial version optional, and unifies the order of initial / current version. - Initial versions are zero by default - If no current version is provided to `defineMigrations`, migrations should be undefined - Fixes TypeScript quirks in versioning (e.g. only initial version) This PR also: - Makes migrations optional when empty - Removes reference to empty migrations ### Change Type - [x] `major` — Breaking Change ### Test Plan - [x] Unit Tests - [ ] Webdriver tests ### Release Notes - [tlschema] Improve `defineMigrations` - [editor] Simplify migration definitions --- .prettierignore | 4 +- .../shapeutils/TLArrowUtil/TLArrowUtil.tsx | 4 +- .../TLBookmarkUtil/TLBookmarkUtil.tsx | 4 +- .../app/shapeutils/TLDrawUtil/TLDrawUtil.tsx | 4 +- .../shapeutils/TLEmbedUtil/TLEmbedUtil.tsx | 4 +- .../shapeutils/TLFrameUtil/TLFrameUtil.tsx | 2 - .../app/shapeutils/TLGeoUtil/TLGeoUtil.tsx | 4 +- .../shapeutils/TLGroupUtil/TLGroupUtil.tsx | 8 +- .../shapeutils/TLImageUtil/TLImageUtil.tsx | 4 +- .../app/shapeutils/TLLineUtil/TLLineUtil.tsx | 8 +- .../app/shapeutils/TLNoteUtil/TLNoteUtil.tsx | 4 +- .../app/shapeutils/TLTextUtil/TLTextUtil.tsx | 4 +- .../shapeutils/TLVideoUtil/TLVideoUtil.tsx | 4 +- .../src/lib/test/tools/translating.test.ts | 2 +- packages/tlschema/api-report.md | 45 +--- packages/tlschema/package.json | 3 - packages/tlschema/scripts/new-asset.js | 78 ------ packages/tlschema/scripts/new-record.js | 78 ------ .../tlschema/src/assets/TLBookmarkAsset.ts | 16 +- packages/tlschema/src/assets/TLImageAsset.ts | 8 - packages/tlschema/src/assets/TLVideoAsset.ts | 8 - packages/tlschema/src/createTLSchema.ts | 62 ++--- packages/tlschema/src/index.ts | 40 +-- packages/tlschema/src/migrations.test.ts | 52 ++-- packages/tlschema/src/records/TLAsset.ts | 13 - packages/tlschema/src/records/TLCamera.ts | 21 +- packages/tlschema/src/records/TLDocument.ts | 21 +- packages/tlschema/src/records/TLInstance.ts | 8 - .../src/records/TLInstancePageState.ts | 6 - .../src/records/TLInstancePresence.ts | 7 - packages/tlschema/src/records/TLPage.ts | 21 +- packages/tlschema/src/records/TLShape.ts | 7 - packages/tlschema/src/records/TLUser.ts | 22 +- .../tlschema/src/records/TLUserDocument.ts | 20 +- .../tlschema/src/records/TLUserPresence.ts | 8 - packages/tlschema/src/schema.ts | 7 - packages/tlschema/src/shapes/TLArrowShape.ts | 10 +- .../tlschema/src/shapes/TLBookmarkShape.ts | 10 +- packages/tlschema/src/shapes/TLDrawShape.ts | 10 +- packages/tlschema/src/shapes/TLEmbedShape.ts | 10 +- packages/tlschema/src/shapes/TLFrameShape.ts | 17 +- packages/tlschema/src/shapes/TLGeoShape.ts | 10 +- packages/tlschema/src/shapes/TLGroupShape.ts | 17 +- packages/tlschema/src/shapes/TLIconShape.ts | 17 +- packages/tlschema/src/shapes/TLImageShape.ts | 10 +- packages/tlschema/src/shapes/TLLineShape.ts | 17 +- packages/tlschema/src/shapes/TLNoteShape.ts | 10 +- packages/tlschema/src/shapes/TLTextShape.ts | 9 +- packages/tlschema/src/shapes/TLVideoShape.ts | 10 +- packages/tlstore/api-report.md | 20 +- packages/tlstore/src/lib/migrate.ts | 52 ++-- .../src/lib/test/defineMigrations.test.ts | 229 ++++++++++++++++++ .../tlstore/src/lib/test/testSchema.v0.ts | 35 +-- .../tlstore/src/lib/test/testSchema.v1.ts | 14 +- 54 files changed, 427 insertions(+), 691 deletions(-) delete mode 100644 packages/tlschema/scripts/new-asset.js delete mode 100644 packages/tlschema/scripts/new-record.js create mode 100644 packages/tlstore/src/lib/test/defineMigrations.test.ts diff --git a/.prettierignore b/.prettierignore index 841824041..63b3db0f4 100644 --- a/.prettierignore +++ b/.prettierignore @@ -12,4 +12,6 @@ apps/docs/content.json apps/vscode/extension/editor/index.js apps/vscode/extension/editor/tldraw-assets.json -apps/webdriver/www/index.js \ No newline at end of file +apps/webdriver/www/index.js +apps/vscode/extension/editor/* +apps/examples/www \ No newline at end of file diff --git a/packages/editor/src/lib/app/shapeutils/TLArrowUtil/TLArrowUtil.tsx b/packages/editor/src/lib/app/shapeutils/TLArrowUtil/TLArrowUtil.tsx index 146457629..78550cb94 100644 --- a/packages/editor/src/lib/app/shapeutils/TLArrowUtil/TLArrowUtil.tsx +++ b/packages/editor/src/lib/app/shapeutils/TLArrowUtil/TLArrowUtil.tsx @@ -11,7 +11,7 @@ import { VecLike, } from '@tldraw/primitives' import { - arrowShapeMigrations, + arrowShapeTypeMigrations, arrowShapeTypeValidator, TLArrowheadType, TLArrowShape, @@ -1141,5 +1141,5 @@ export const TLArrowShapeDef = defineShape({ type: 'arrow', getShapeUtil: () => TLArrowUtil, validator: arrowShapeTypeValidator, - migrations: arrowShapeMigrations, + migrations: arrowShapeTypeMigrations, }) diff --git a/packages/editor/src/lib/app/shapeutils/TLBookmarkUtil/TLBookmarkUtil.tsx b/packages/editor/src/lib/app/shapeutils/TLBookmarkUtil/TLBookmarkUtil.tsx index 6f45f1616..b2272d9ff 100644 --- a/packages/editor/src/lib/app/shapeutils/TLBookmarkUtil/TLBookmarkUtil.tsx +++ b/packages/editor/src/lib/app/shapeutils/TLBookmarkUtil/TLBookmarkUtil.tsx @@ -1,6 +1,6 @@ import { toDomPrecision } from '@tldraw/primitives' import { - bookmarkShapeMigrations, + bookmarkShapeTypeMigrations, bookmarkShapeTypeValidator, TLAsset, TLAssetId, @@ -197,5 +197,5 @@ export const TLBookmarkShapeDef = defineShape({ type: 'bookmark', getShapeUtil: () => TLBookmarkUtil, validator: bookmarkShapeTypeValidator, - migrations: bookmarkShapeMigrations, + migrations: bookmarkShapeTypeMigrations, }) diff --git a/packages/editor/src/lib/app/shapeutils/TLDrawUtil/TLDrawUtil.tsx b/packages/editor/src/lib/app/shapeutils/TLDrawUtil/TLDrawUtil.tsx index 1f81b7b73..c4a894d1b 100644 --- a/packages/editor/src/lib/app/shapeutils/TLDrawUtil/TLDrawUtil.tsx +++ b/packages/editor/src/lib/app/shapeutils/TLDrawUtil/TLDrawUtil.tsx @@ -10,7 +10,7 @@ import { VecLike, } from '@tldraw/primitives' import { - drawShapeMigrations, + drawShapeTypeMigrations, drawShapeTypeValidator, TLDrawShape, TLDrawShapeSegment, @@ -314,7 +314,7 @@ export class TLDrawUtil extends TLShapeUtil { export const TLDrawShapeDef = defineShape({ type: 'draw', getShapeUtil: () => TLDrawUtil, - migrations: drawShapeMigrations, + migrations: drawShapeTypeMigrations, validator: drawShapeTypeValidator, }) diff --git a/packages/editor/src/lib/app/shapeutils/TLEmbedUtil/TLEmbedUtil.tsx b/packages/editor/src/lib/app/shapeutils/TLEmbedUtil/TLEmbedUtil.tsx index abb0080a4..76e093323 100644 --- a/packages/editor/src/lib/app/shapeutils/TLEmbedUtil/TLEmbedUtil.tsx +++ b/packages/editor/src/lib/app/shapeutils/TLEmbedUtil/TLEmbedUtil.tsx @@ -1,7 +1,7 @@ /* eslint-disable react-hooks/rules-of-hooks */ import { toDomPrecision } from '@tldraw/primitives' import { - embedShapeMigrations, + embedShapeTypeMigrations, embedShapeTypeValidator, TLEmbedShape, tlEmbedShapePermissionDefaults, @@ -236,5 +236,5 @@ export const TLEmbedShapeDef = defineShape({ type: 'embed', getShapeUtil: () => TLEmbedUtil, validator: embedShapeTypeValidator, - migrations: embedShapeMigrations, + migrations: embedShapeTypeMigrations, }) diff --git a/packages/editor/src/lib/app/shapeutils/TLFrameUtil/TLFrameUtil.tsx b/packages/editor/src/lib/app/shapeutils/TLFrameUtil/TLFrameUtil.tsx index 48323bdf2..2676b547b 100644 --- a/packages/editor/src/lib/app/shapeutils/TLFrameUtil/TLFrameUtil.tsx +++ b/packages/editor/src/lib/app/shapeutils/TLFrameUtil/TLFrameUtil.tsx @@ -1,6 +1,5 @@ import { canolicalizeRotation, SelectionEdge, toDomPrecision } from '@tldraw/primitives' import { - frameShapeMigrations, frameShapeTypeValidator, TLFrameShape, TLShape, @@ -218,5 +217,4 @@ export const TLFrameShapeDef = defineShape({ type: 'frame', getShapeUtil: () => TLFrameUtil, validator: frameShapeTypeValidator, - migrations: frameShapeMigrations, }) diff --git a/packages/editor/src/lib/app/shapeutils/TLGeoUtil/TLGeoUtil.tsx b/packages/editor/src/lib/app/shapeutils/TLGeoUtil/TLGeoUtil.tsx index fd4a641c9..1987d9812 100644 --- a/packages/editor/src/lib/app/shapeutils/TLGeoUtil/TLGeoUtil.tsx +++ b/packages/editor/src/lib/app/shapeutils/TLGeoUtil/TLGeoUtil.tsx @@ -13,7 +13,7 @@ import { VecLike, } from '@tldraw/primitives' import { - geoShapeMigrations, + geoShapeTypeMigrations, geoShapeTypeValidator, TLDashType, TLGeoShape, @@ -1008,5 +1008,5 @@ export const TLGeoShapeDef = defineShape({ type: 'geo', getShapeUtil: () => TLGeoUtil, validator: geoShapeTypeValidator, - migrations: geoShapeMigrations, + migrations: geoShapeTypeMigrations, }) diff --git a/packages/editor/src/lib/app/shapeutils/TLGroupUtil/TLGroupUtil.tsx b/packages/editor/src/lib/app/shapeutils/TLGroupUtil/TLGroupUtil.tsx index 542934d0e..76ee5327e 100644 --- a/packages/editor/src/lib/app/shapeutils/TLGroupUtil/TLGroupUtil.tsx +++ b/packages/editor/src/lib/app/shapeutils/TLGroupUtil/TLGroupUtil.tsx @@ -1,10 +1,5 @@ import { Box2d, Matrix2d } from '@tldraw/primitives' -import { - TLGroupShape, - Vec2dModel, - groupShapeMigrations, - groupShapeTypeValidator, -} from '@tldraw/tlschema' +import { TLGroupShape, Vec2dModel, groupShapeTypeValidator } from '@tldraw/tlschema' import { SVGContainer } from '../../../components/SVGContainer' import { defineShape } from '../../../config/TLShapeDefinition' import { OnChildrenChangeHandler, TLShapeUtil } from '../TLShapeUtil' @@ -115,5 +110,4 @@ export const TLGroupShapeDef = defineShape({ type: 'group', getShapeUtil: () => TLGroupUtil, validator: groupShapeTypeValidator, - migrations: groupShapeMigrations, }) diff --git a/packages/editor/src/lib/app/shapeutils/TLImageUtil/TLImageUtil.tsx b/packages/editor/src/lib/app/shapeutils/TLImageUtil/TLImageUtil.tsx index 48c08596c..c0aef4dc9 100644 --- a/packages/editor/src/lib/app/shapeutils/TLImageUtil/TLImageUtil.tsx +++ b/packages/editor/src/lib/app/shapeutils/TLImageUtil/TLImageUtil.tsx @@ -3,7 +3,7 @@ import { Vec2d, toDomPrecision } from '@tldraw/primitives' import { TLImageShape, TLShapePartial, - imageShapeMigrations, + imageShapeTypeMigrations, imageShapeTypeValidator, } from '@tldraw/tlschema' import { deepCopy } from '@tldraw/utils' @@ -275,7 +275,7 @@ export const TLImageShapeDef = defineShape({ type: 'image', getShapeUtil: () => TLImageUtil, validator: imageShapeTypeValidator, - migrations: imageShapeMigrations, + migrations: imageShapeTypeMigrations, }) /** diff --git a/packages/editor/src/lib/app/shapeutils/TLLineUtil/TLLineUtil.tsx b/packages/editor/src/lib/app/shapeutils/TLLineUtil/TLLineUtil.tsx index 6f26751f1..657cfabbe 100644 --- a/packages/editor/src/lib/app/shapeutils/TLLineUtil/TLLineUtil.tsx +++ b/packages/editor/src/lib/app/shapeutils/TLLineUtil/TLLineUtil.tsx @@ -9,12 +9,7 @@ import { intersectLineSegmentPolyline, pointNearToPolyline, } from '@tldraw/primitives' -import { - TLHandle, - TLLineShape, - lineShapeMigrations, - lineShapeTypeValidator, -} from '@tldraw/tlschema' +import { TLHandle, TLLineShape, lineShapeTypeValidator } from '@tldraw/tlschema' import { deepCopy } from '@tldraw/utils' import { SVGContainer } from '../../../components/SVGContainer' import { defineShape } from '../../../config/TLShapeDefinition' @@ -345,7 +340,6 @@ export const TLLineShapeDef = defineShape({ type: 'line', getShapeUtil: () => TLLineUtil, validator: lineShapeTypeValidator, - migrations: lineShapeMigrations, }) /** @public */ diff --git a/packages/editor/src/lib/app/shapeutils/TLNoteUtil/TLNoteUtil.tsx b/packages/editor/src/lib/app/shapeutils/TLNoteUtil/TLNoteUtil.tsx index ffca2b283..5807d9734 100644 --- a/packages/editor/src/lib/app/shapeutils/TLNoteUtil/TLNoteUtil.tsx +++ b/packages/editor/src/lib/app/shapeutils/TLNoteUtil/TLNoteUtil.tsx @@ -1,5 +1,5 @@ import { Box2d, toDomPrecision, Vec2d } from '@tldraw/primitives' -import { noteShapeMigrations, noteShapeTypeValidator, TLNoteShape } from '@tldraw/tlschema' +import { noteShapeTypeMigrations, noteShapeTypeValidator, TLNoteShape } from '@tldraw/tlschema' import { defineShape } from '../../../config/TLShapeDefinition' import { FONT_FAMILIES, LABEL_FONT_SIZES, TEXT_PROPS } from '../../../constants' import { App } from '../../App' @@ -202,7 +202,7 @@ export const TLNoteShapeDef = defineShape({ getShapeUtil: () => TLNoteUtil, type: 'note', validator: noteShapeTypeValidator, - migrations: noteShapeMigrations, + migrations: noteShapeTypeMigrations, }) function getGrowY(app: App, shape: TLNoteShape, prevGrowY = 0) { diff --git a/packages/editor/src/lib/app/shapeutils/TLTextUtil/TLTextUtil.tsx b/packages/editor/src/lib/app/shapeutils/TLTextUtil/TLTextUtil.tsx index 68407f8ee..6fe4060e8 100644 --- a/packages/editor/src/lib/app/shapeutils/TLTextUtil/TLTextUtil.tsx +++ b/packages/editor/src/lib/app/shapeutils/TLTextUtil/TLTextUtil.tsx @@ -1,6 +1,6 @@ /* eslint-disable react-hooks/rules-of-hooks */ import { Box2d, toDomPrecision, Vec2d } from '@tldraw/primitives' -import { textShapeMigrations, textShapeTypeValidator, TLTextShape } from '@tldraw/tlschema' +import { textShapeTypeMigrations, textShapeTypeValidator, TLTextShape } from '@tldraw/tlschema' import { HTMLContainer } from '../../../components/HTMLContainer' import { defineShape } from '../../../config/TLShapeDefinition' import { FONT_FAMILIES, FONT_SIZES, TEXT_PROPS } from '../../../constants' @@ -374,7 +374,7 @@ export const TLTextShapeDef = defineShape({ type: 'text', getShapeUtil: () => TLTextUtil, validator: textShapeTypeValidator, - migrations: textShapeMigrations, + migrations: textShapeTypeMigrations, }) function getTextSize(app: App, props: TLTextShape['props']) { diff --git a/packages/editor/src/lib/app/shapeutils/TLVideoUtil/TLVideoUtil.tsx b/packages/editor/src/lib/app/shapeutils/TLVideoUtil/TLVideoUtil.tsx index c5e5cb575..d0b305ebe 100644 --- a/packages/editor/src/lib/app/shapeutils/TLVideoUtil/TLVideoUtil.tsx +++ b/packages/editor/src/lib/app/shapeutils/TLVideoUtil/TLVideoUtil.tsx @@ -1,5 +1,5 @@ import { toDomPrecision } from '@tldraw/primitives' -import { TLVideoShape, videoShapeMigrations, videoShapeTypeValidator } from '@tldraw/tlschema' +import { TLVideoShape, videoShapeTypeMigrations, videoShapeTypeValidator } from '@tldraw/tlschema' import * as React from 'react' import { track } from 'signia-react' import { HTMLContainer } from '../../../components/HTMLContainer' @@ -54,7 +54,7 @@ export const TLVideoShapeDef = defineShape({ type: 'video', getShapeUtil: () => TLVideoUtil, validator: videoShapeTypeValidator, - migrations: videoShapeMigrations, + migrations: videoShapeTypeMigrations, }) // Function from v1, could be improved bu explicitly using this.model.time (?) diff --git a/packages/editor/src/lib/test/tools/translating.test.ts b/packages/editor/src/lib/test/tools/translating.test.ts index 8b82bec68..056374f2f 100644 --- a/packages/editor/src/lib/test/tools/translating.test.ts +++ b/packages/editor/src/lib/test/tools/translating.test.ts @@ -45,7 +45,7 @@ const __TopLeftSnapOnlyShapeDef = defineShape<__TopLeftSnapOnlyShape, __TopLeftS type: '__test_top_left_snap_only', getShapeUtil: () => __TopLeftSnapOnlyShapeUtil, validator: { validate: (record) => record as __TopLeftSnapOnlyShape }, - migrations: defineMigrations({ currentVersion: 0, firstVersion: 0, migrators: {} }), + migrations: defineMigrations({}), }) const configWithCustomShape = new TldrawEditorConfig({ shapes: [__TopLeftSnapOnlyShapeDef] }) diff --git a/packages/tlschema/api-report.md b/packages/tlschema/api-report.md index 2c760b549..496392379 100644 --- a/packages/tlschema/api-report.md +++ b/packages/tlschema/api-report.md @@ -5,7 +5,6 @@ ```ts import { BaseRecord } from '@tldraw/tlstore'; -import { defineMigrations } from '@tldraw/tlstore'; import { ID } from '@tldraw/tlstore'; import { Migrations } from '@tldraw/tlstore'; import { RecordType } from '@tldraw/tlstore'; @@ -24,7 +23,7 @@ export const alignValidator: T.Validator<"end" | "middle" | "start">; export const arrowheadValidator: T.Validator<"arrow" | "bar" | "diamond" | "dot" | "inverted" | "none" | "pipe" | "square" | "triangle">; // @public (undocumented) -export const arrowShapeMigrations: Migrations; +export const arrowShapeTypeMigrations: Migrations; // @public (undocumented) export const arrowShapeTypeValidator: T.Validator; @@ -48,7 +47,7 @@ export const bookmarkAssetMigrations: Migrations; export const bookmarkAssetTypeValidator: T.Validator; // @public (undocumented) -export const bookmarkShapeMigrations: Migrations; +export const bookmarkShapeTypeMigrations: Migrations; // @public (undocumented) export const bookmarkShapeTypeValidator: T.Validator; @@ -65,9 +64,6 @@ export interface Box2dModel { y: number; } -// @public (undocumented) -export const cameraTypeMigrations: Migrations; - // @public (undocumented) export const cameraTypeValidator: T.Validator; @@ -124,7 +120,7 @@ export const cursorValidator: T.Validator; // @public (undocumented) export type CustomShapeTypeInfo = { type: string; - migrations: ReturnType; + migrations?: Migrations; validator?: StoreValidator; }; @@ -134,14 +130,11 @@ export const dashValidator: T.Validator<"dashed" | "dotted" | "draw" | "solid">; // @internal (undocumented) export const defaultDerivePresenceState: (store: TLStore) => Signal; -// @public (undocumented) -export const documentTypeMigrations: Migrations; - // @public (undocumented) export const documentTypeValidator: T.Validator; // @public (undocumented) -export const drawShapeMigrations: Migrations; +export const drawShapeTypeMigrations: Migrations; // @public (undocumented) export const drawShapeTypeValidator: T.Validator; @@ -334,7 +327,7 @@ export type EmbedDefinition = { }; // @public (undocumented) -export const embedShapeMigrations: Migrations; +export const embedShapeTypeMigrations: Migrations; // @public (undocumented) export const embedShapeTypeValidator: T.Validator; @@ -351,14 +344,11 @@ export function fixupRecord(oldRecord: TLRecord): { // @internal (undocumented) export const fontValidator: T.Validator<"draw" | "mono" | "sans" | "serif">; -// @public (undocumented) -export const frameShapeMigrations: Migrations; - // @public (undocumented) export const frameShapeTypeValidator: T.Validator; // @public (undocumented) -export const geoShapeMigrations: Migrations; +export const geoShapeTypeMigrations: Migrations; // @public (undocumented) export const geoShapeTypeValidator: T.Validator; @@ -366,18 +356,12 @@ export const geoShapeTypeValidator: T.Validator; // @internal (undocumented) export const geoValidator: T.Validator<"arrow-down" | "arrow-left" | "arrow-right" | "arrow-up" | "check-box" | "diamond" | "ellipse" | "hexagon" | "octagon" | "oval" | "pentagon" | "rectangle" | "rhombus-2" | "rhombus" | "star" | "trapezoid" | "triangle" | "x-box">; -// @public (undocumented) -export const groupShapeMigrations: Migrations; - // @public (undocumented) export const groupShapeTypeValidator: T.Validator; // @public (undocumented) export const handleTypeValidator: T.Validator; -// @public (undocumented) -export const iconShapeMigrations: Migrations; - // @public (undocumented) export const iconShapeTypeValidator: T.Validator; @@ -394,7 +378,7 @@ export const imageAssetMigrations: Migrations; export const imageAssetTypeValidator: T.Validator; // @public (undocumented) -export const imageShapeMigrations: Migrations; +export const imageShapeTypeMigrations: Migrations; // @public (undocumented) export const imageShapeTypeValidator: T.Validator; @@ -420,14 +404,11 @@ export function isShape(record?: BaseRecord): record is TLShape; // @public (undocumented) export function isShapeId(id?: string): id is TLShapeId; -// @public (undocumented) -export const lineShapeMigrations: Migrations; - // @public (undocumented) export const lineShapeTypeValidator: T.Validator; // @public (undocumented) -export const noteShapeMigrations: Migrations; +export const noteShapeTypeMigrations: Migrations; // @public (undocumented) export const noteShapeTypeValidator: T.Validator; @@ -441,9 +422,6 @@ export const opacityValidator: T.Validator<"0.1" | "0.25" | "0.5" | "0.75" | "1" // @internal (undocumented) export const pageIdValidator: T.Validator; -// @public (undocumented) -export const pageTypeMigrations: Migrations; - // @public (undocumented) export const pageTypeValidator: T.Validator; @@ -477,7 +455,7 @@ export const splineValidator: T.Validator<"cubic" | "line">; export const storeMigrations: Migrations; // @public (undocumented) -export const textShapeMigrations: Migrations; +export const textShapeTypeMigrations: Migrations; // @public (undocumented) export const textShapeTypeValidator: T.Validator; @@ -1390,9 +1368,6 @@ export const userPresenceTypeMigrations: Migrations; // @public (undocumented) export const userPresenceTypeValidator: T.Validator; -// @public (undocumented) -export const userTypeMigrations: Migrations; - // @public (undocumented) export const userTypeValidator: T.Validator; @@ -1413,7 +1388,7 @@ export const videoAssetMigrations: Migrations; export const videoAssetTypeValidator: T.Validator; // @public (undocumented) -export const videoShapeMigrations: Migrations; +export const videoShapeTypeMigrations: Migrations; // @public (undocumented) export const videoShapeTypeValidator: T.Validator; diff --git a/packages/tlschema/package.json b/packages/tlschema/package.json index 4173111a9..3350838f0 100644 --- a/packages/tlschema/package.json +++ b/packages/tlschema/package.json @@ -33,9 +33,6 @@ "scripts": { "test": "lazy inherit", "test-coverage": "lazy inherit", - "new-record": "node ./scripts/new-record.js", - "new-shape": "node ./scripts/new-shape.js", - "new-asset": "node ./scripts/new-asset.js", "index": "node ./scripts/build-index.js && yarn format", "format": "yarn run -T prettier --write \"src/**/*.{ts,tsx,js,jsx,json,md}\"", "build": "yarn run -T tsx ../../scripts/build-package.ts", diff --git a/packages/tlschema/scripts/new-asset.js b/packages/tlschema/scripts/new-asset.js deleted file mode 100644 index 3b2a2fbac..000000000 --- a/packages/tlschema/scripts/new-asset.js +++ /dev/null @@ -1,78 +0,0 @@ -// @ts-check -/* eslint-disable */ - -const kleur = require('kleur') -const fs = require('fs') -const path = require('path') - -const typeName = process.argv[2] -const lowerAssetName = typeName[2].toLowerCase() + typeName.slice(3) - -if (!typeName.match(/^TL[A-Z][a-z]+[a-zA-Z0-9]+Asset$/)) { - console.error( - kleur.red('ERROR: Type name must start with'), - `'${kleur.bold('TL')}'`, - kleur.red('and be in'), - kleur.bold('PascalCase'), - kleur.red('and end in'), - kleur.bold('Asset') - ) - process.exit(1) -} - -const recordsDir = path.join(__dirname, '..', 'src', 'assets') -if (!fs.existsSync(recordsDir)) { - console.error(kleur.red("ERROR: Can't find assets directory at path"), recordsDir) - process.exit(1) -} - -const filePath = path.join(recordsDir, `${typeName}.ts`) - -if (fs.existsSync(filePath)) { - console.error(kleur.red('ERROR: File already exists at path'), filePath) - process.exit(1) -} - -const snakeCaseName = - typeName[2].toLowerCase() + - typeName - .slice(3, -5) - .replace(/[A-Z]/g, (match) => `_${match.toLowerCase()}`) - .trimStart() - -fs.writeFileSync( - filePath, - `import { defineMigrations } from '@tldraw/tlstore' -import { TLAsset } from '../records/TLAsset' - -declare module '../records/TLAsset' { - interface GlobalAssetPropsMap { - ${snakeCaseName}: ${typeName}Props - } -} - -// IMPORTANT: If you update this interface, you must also bump the version number and add a migration -export type ${typeName}Props = {} - -export type ${typeName} = Extract - -// --- MIGRATIONS --- -// STEP 1: Add a new version number here, give it a meaningful name. -// It should be 1 higher than the current version -const Versions = { - Initial: 0, -} as const - -export const ${lowerAssetName}Migrations = defineMigrations({ - // STEP 2: Update the current version to point to your latest version - currentVersion: Versions.Initial, - firstVersion: Versions.Initial, - migrators: { - // STEP 3: Add an up+down migration for the new version here - }, -}) - -` -) - -console.log(kleur.green('Created new record type at path'), filePath) diff --git a/packages/tlschema/scripts/new-record.js b/packages/tlschema/scripts/new-record.js deleted file mode 100644 index 2a77a2645..000000000 --- a/packages/tlschema/scripts/new-record.js +++ /dev/null @@ -1,78 +0,0 @@ -// @ts-check -/* eslint-disable */ - -const kleur = require('kleur') -const fs = require('fs') -const path = require('path') - -const typeName = process.argv[2] - -if (!typeName.match(/^TL[A-Z][a-z]+[a-zA-Z0-9]+$/)) { - console.error( - kleur.red('ERROR: Type name must start with'), - `'${kleur.bold('TL')}'`, - kleur.red('and be in'), - kleur.bold('PascalCase') - ) - process.exit(1) -} - -const lowerCaseName = typeName[2].toLowerCase() + typeName.slice(3) - -const recordsDir = path.join(__dirname, '..', 'src', 'records') -if (!fs.existsSync(recordsDir)) { - console.error(kleur.red("ERROR: Can't find records directory at path"), recordsDir) - process.exit(1) -} - -const filePath = path.join(recordsDir, `${typeName}.ts`) - -if (fs.existsSync(filePath)) { - console.error(kleur.red('ERROR: File already exists at path'), filePath) - process.exit(1) -} - -const snakeCaseName = - typeName[2].toLowerCase() + - typeName - .slice(3) - .replace(/[A-Z]/g, (match) => `_${match.toLowerCase()}`) - .trimStart() - -fs.writeFileSync( - filePath, - `import { BaseRecord, defineMigrations, createRecordType, ID } from '@tldraw/tlstore' - -// --- MIGRATIONS --- -// STEP 1: Add a new version number here, give it a meaningful name. -// It should be 1 higher than the current version -const Versions = { - Initial: 0, -} as const - -export const ${lowerCaseName}TypeMigrations = defineMigrations({ - // STEP 2: Update the current version to point to your latest version - currentVersion: Versions.Initial, - firstVersion: Versions.Initial, - migrators: { - // STEP 3: Add an up+down migration for the new version here - }, -}) - -/** - * ${typeName} - */ -export interface ${typeName} extends BaseRecord<'${snakeCaseName}'> {} - - -export const ${typeName} = createRecordType<${typeName}>('${snakeCaseName}', { - migrations: ${lowerCaseName}TypeMigrations, -}).withDefaultProperties(() => ({ -})) - -export type ${typeName}Id = ID<${typeName}> - -` -) - -console.log(kleur.green('Created new record type at path'), filePath) diff --git a/packages/tlschema/src/assets/TLBookmarkAsset.ts b/packages/tlschema/src/assets/TLBookmarkAsset.ts index 02261c914..04c637ddf 100644 --- a/packages/tlschema/src/assets/TLBookmarkAsset.ts +++ b/packages/tlschema/src/assets/TLBookmarkAsset.ts @@ -14,7 +14,6 @@ export type TLBookmarkAsset = TLBaseAsset< } > -// --- VALIDATION --- /** @public */ export const bookmarkAssetTypeValidator: T.Validator = createAssetValidator( 'bookmark', @@ -26,18 +25,5 @@ export const bookmarkAssetTypeValidator: T.Validator = createAs }) ) -// --- MIGRATIONS --- -// STEP 1: Add a new version number here, give it a meaningful name. -// It should be 1 higher than the current version -const Versions = { - Initial: 0, -} as const - /** @public */ -export const bookmarkAssetMigrations = defineMigrations({ - firstVersion: Versions.Initial, - // STEP 2: Update the current version to point to your latest version - currentVersion: Versions.Initial, - // STEP 3: Add an up+down migration for the new version here - migrators: {}, -}) +export const bookmarkAssetMigrations = defineMigrations({}) diff --git a/packages/tlschema/src/assets/TLImageAsset.ts b/packages/tlschema/src/assets/TLImageAsset.ts index 1b7f121a5..fc37a9990 100644 --- a/packages/tlschema/src/assets/TLImageAsset.ts +++ b/packages/tlschema/src/assets/TLImageAsset.ts @@ -16,7 +16,6 @@ export type TLImageAsset = TLBaseAsset< } > -// --- VALIDATION --- /** @public */ export const imageAssetTypeValidator: T.Validator = createAssetValidator( 'image', @@ -30,21 +29,14 @@ export const imageAssetTypeValidator: T.Validator = createAssetVal }) ) -// --- MIGRATIONS --- -// STEP 1: Add a new version number here, give it a meaningful name. -// It should be 1 higher than the current version const Versions = { - Initial: 0, AddIsAnimated: 1, RenameWidthHeight: 2, } as const /** @public */ export const imageAssetMigrations = defineMigrations({ - firstVersion: Versions.Initial, - // STEP 2: Update the current version to point to your latest version currentVersion: Versions.RenameWidthHeight, - // STEP 3: Add an up+down migration for the new version here migrators: { [Versions.AddIsAnimated]: { up: (asset) => { diff --git a/packages/tlschema/src/assets/TLVideoAsset.ts b/packages/tlschema/src/assets/TLVideoAsset.ts index 3de01290d..eb7c68e48 100644 --- a/packages/tlschema/src/assets/TLVideoAsset.ts +++ b/packages/tlschema/src/assets/TLVideoAsset.ts @@ -17,7 +17,6 @@ export type TLVideoAsset = TLBaseAsset< } > -// --- VALIDATION --- /** @public */ export const videoAssetTypeValidator: T.Validator = createAssetValidator( 'video', @@ -31,21 +30,14 @@ export const videoAssetTypeValidator: T.Validator = createAssetVal }) ) -// --- MIGRATIONS --- -// STEP 1: Add a new version number here, give it a meaningful name. -// It should be 1 higher than the current version const Versions = { - Initial: 0, AddIsAnimated: 1, RenameWidthHeight: 2, } as const /** @public */ export const videoAssetMigrations = defineMigrations({ - firstVersion: Versions.Initial, - // STEP 2: Update the current version to point to your latest version currentVersion: Versions.RenameWidthHeight, - // STEP 3: Add an up+down migration for the new version here migrators: { [Versions.AddIsAnimated]: { up: (asset) => { diff --git a/packages/tlschema/src/createTLSchema.ts b/packages/tlschema/src/createTLSchema.ts index 6284204cd..97c1ad109 100644 --- a/packages/tlschema/src/createTLSchema.ts +++ b/packages/tlschema/src/createTLSchema.ts @@ -1,4 +1,10 @@ -import { StoreSchema, StoreValidator, createRecordType, defineMigrations } from '@tldraw/tlstore' +import { + Migrations, + StoreSchema, + StoreValidator, + createRecordType, + defineMigrations, +} from '@tldraw/tlstore' import { T } from '@tldraw/tlvalidate' import { Signal } from 'signia' import { TLRecord } from './TLRecord' @@ -16,42 +22,42 @@ import { TLUser } from './records/TLUser' import { TLUserDocument } from './records/TLUserDocument' import { TLUserPresence } from './records/TLUserPresence' import { storeMigrations } from './schema' -import { arrowShapeMigrations, arrowShapeTypeValidator } from './shapes/TLArrowShape' -import { bookmarkShapeMigrations, bookmarkShapeTypeValidator } from './shapes/TLBookmarkShape' -import { drawShapeMigrations, drawShapeTypeValidator } from './shapes/TLDrawShape' -import { embedShapeMigrations, embedShapeTypeValidator } from './shapes/TLEmbedShape' -import { frameShapeMigrations, frameShapeTypeValidator } from './shapes/TLFrameShape' -import { geoShapeMigrations, geoShapeTypeValidator } from './shapes/TLGeoShape' -import { groupShapeMigrations, groupShapeTypeValidator } from './shapes/TLGroupShape' -import { imageShapeMigrations, imageShapeTypeValidator } from './shapes/TLImageShape' -import { lineShapeMigrations, lineShapeTypeValidator } from './shapes/TLLineShape' -import { noteShapeMigrations, noteShapeTypeValidator } from './shapes/TLNoteShape' -import { textShapeMigrations, textShapeTypeValidator } from './shapes/TLTextShape' -import { videoShapeMigrations, videoShapeTypeValidator } from './shapes/TLVideoShape' +import { arrowShapeTypeMigrations, arrowShapeTypeValidator } from './shapes/TLArrowShape' +import { bookmarkShapeTypeMigrations, bookmarkShapeTypeValidator } from './shapes/TLBookmarkShape' +import { drawShapeTypeMigrations, drawShapeTypeValidator } from './shapes/TLDrawShape' +import { embedShapeTypeMigrations, embedShapeTypeValidator } from './shapes/TLEmbedShape' +import { frameShapeTypeMigrations, frameShapeTypeValidator } from './shapes/TLFrameShape' +import { geoShapeTypeMigrations, geoShapeTypeValidator } from './shapes/TLGeoShape' +import { groupShapeTypeMigrations, groupShapeTypeValidator } from './shapes/TLGroupShape' +import { imageShapeTypeMigrations, imageShapeTypeValidator } from './shapes/TLImageShape' +import { lineShapeTypeMigrations, lineShapeTypeValidator } from './shapes/TLLineShape' +import { noteShapeTypeMigrations, noteShapeTypeValidator } from './shapes/TLNoteShape' +import { textShapeTypeMigrations, textShapeTypeValidator } from './shapes/TLTextShape' +import { videoShapeTypeMigrations, videoShapeTypeValidator } from './shapes/TLVideoShape' const CORE_SHAPE_DEFS: readonly CustomShapeTypeInfo[] = [ - { type: 'draw', migrations: drawShapeMigrations, validator: drawShapeTypeValidator }, - { type: 'text', migrations: textShapeMigrations, validator: textShapeTypeValidator }, - { type: 'line', migrations: lineShapeMigrations, validator: lineShapeTypeValidator }, - { type: 'arrow', migrations: arrowShapeMigrations, validator: arrowShapeTypeValidator }, - { type: 'image', migrations: imageShapeMigrations, validator: imageShapeTypeValidator }, - { type: 'video', migrations: videoShapeMigrations, validator: videoShapeTypeValidator }, - { type: 'geo', migrations: geoShapeMigrations, validator: geoShapeTypeValidator }, - { type: 'note', migrations: noteShapeMigrations, validator: noteShapeTypeValidator }, - { type: 'group', migrations: groupShapeMigrations, validator: groupShapeTypeValidator }, + { type: 'draw', migrations: drawShapeTypeMigrations, validator: drawShapeTypeValidator }, + { type: 'text', migrations: textShapeTypeMigrations, validator: textShapeTypeValidator }, + { type: 'line', migrations: lineShapeTypeMigrations, validator: lineShapeTypeValidator }, + { type: 'arrow', migrations: arrowShapeTypeMigrations, validator: arrowShapeTypeValidator }, + { type: 'image', migrations: imageShapeTypeMigrations, validator: imageShapeTypeValidator }, + { type: 'video', migrations: videoShapeTypeMigrations, validator: videoShapeTypeValidator }, + { type: 'geo', migrations: geoShapeTypeMigrations, validator: geoShapeTypeValidator }, + { type: 'note', migrations: noteShapeTypeMigrations, validator: noteShapeTypeValidator }, + { type: 'group', migrations: groupShapeTypeMigrations, validator: groupShapeTypeValidator }, { type: 'bookmark', - migrations: bookmarkShapeMigrations, + migrations: bookmarkShapeTypeMigrations, validator: bookmarkShapeTypeValidator, }, - { type: 'frame', migrations: frameShapeMigrations, validator: frameShapeTypeValidator }, - { type: 'embed', migrations: embedShapeMigrations, validator: embedShapeTypeValidator }, + { type: 'frame', migrations: frameShapeTypeMigrations, validator: frameShapeTypeValidator }, + { type: 'embed', migrations: embedShapeTypeMigrations, validator: embedShapeTypeValidator }, ] /** @public */ export type CustomShapeTypeInfo = { type: string - migrations: ReturnType + migrations?: Migrations validator?: StoreValidator } @@ -79,7 +85,9 @@ export function createTLSchema({ firstVersion: rootShapeTypeMigrations.firstVersion, migrators: rootShapeTypeMigrations.migrators, subTypeKey: 'type', - subTypeMigrations: Object.fromEntries(allShapeDefs.map((def) => [def.type, def.migrations])), + subTypeMigrations: Object.fromEntries( + allShapeDefs.map((def) => [def.type, def.migrations ?? {}]) + ) as Record, }) let shapeValidator = T.union('type', { diff --git a/packages/tlschema/src/index.ts b/packages/tlschema/src/index.ts index 30b2a37a4..5d0692a96 100644 --- a/packages/tlschema/src/index.ts +++ b/packages/tlschema/src/index.ts @@ -37,18 +37,8 @@ export { type TLAssetPartial, type TLAssetShape, } from './records/TLAsset' -export { - TLCamera, - cameraTypeMigrations, - cameraTypeValidator, - type TLCameraId, -} from './records/TLCamera' -export { - TLDOCUMENT_ID, - TLDocument, - documentTypeMigrations, - documentTypeValidator, -} from './records/TLDocument' +export { TLCamera, cameraTypeValidator, type TLCameraId } from './records/TLCamera' +export { TLDOCUMENT_ID, TLDocument, documentTypeValidator } from './records/TLDocument' export { TLInstance, instanceTypeMigrations, @@ -63,7 +53,7 @@ export { type TLInstancePageStateId, } from './records/TLInstancePageState' export { TLInstancePresence } from './records/TLInstancePresence' -export { TLPage, pageTypeMigrations, pageTypeValidator, type TLPageId } from './records/TLPage' +export { TLPage, pageTypeValidator, type TLPageId } from './records/TLPage' export { createCustomShapeId, createShapeId, @@ -80,7 +70,7 @@ export { type TLShapeType, type TLUnknownShape, } from './records/TLShape' -export { TLUser, userTypeMigrations, userTypeValidator, type TLUserId } from './records/TLUser' +export { TLUser, userTypeValidator, type TLUserId } from './records/TLUser' export { TLUserDocument, userDocumentTypeMigrations, @@ -96,7 +86,7 @@ export { export { storeMigrations } from './schema' export { TL_ARROW_TERMINAL_TYPE, - arrowShapeMigrations, + arrowShapeTypeMigrations, arrowShapeTypeValidator, arrowTerminalTypeValidator, type TLArrowHeadModel, @@ -106,14 +96,14 @@ export { type TLArrowTerminalType, } from './shapes/TLArrowShape' export { - bookmarkShapeMigrations, + bookmarkShapeTypeMigrations, bookmarkShapeTypeValidator, type TLBookmarkShape, type TLBookmarkShapeProps, } from './shapes/TLBookmarkShape' export { TL_DRAW_SHAPE_SEGMENT_TYPE, - drawShapeMigrations, + drawShapeTypeMigrations, drawShapeTypeValidator, type TLDrawShape, type TLDrawShapeProps, @@ -121,7 +111,7 @@ export { } from './shapes/TLDrawShape' export { EMBED_DEFINITIONS, - embedShapeMigrations, + embedShapeTypeMigrations, embedShapeTypeValidator, tlEmbedShapePermissionDefaults, type EmbedDefinition, @@ -131,56 +121,52 @@ export { type TLEmbedShapeProps, } from './shapes/TLEmbedShape' export { - frameShapeMigrations, frameShapeTypeValidator, type TLFrameShape, type TLFrameShapeProps, } from './shapes/TLFrameShape' export { - geoShapeMigrations, + geoShapeTypeMigrations, geoShapeTypeValidator, type TLGeoShape, type TLGeoShapeProps, } from './shapes/TLGeoShape' export { - groupShapeMigrations, groupShapeTypeValidator, type TLGroupShape, type TLGroupShapeProps, } from './shapes/TLGroupShape' export { - iconShapeMigrations, iconShapeTypeValidator, type TLIconShape, type TLIconShapeProps, } from './shapes/TLIconShape' export { - imageShapeMigrations, + imageShapeTypeMigrations, imageShapeTypeValidator, type TLImageCrop, type TLImageShape, type TLImageShapeProps, } from './shapes/TLImageShape' export { - lineShapeMigrations, lineShapeTypeValidator, type TLLineShape, type TLLineShapeProps, } from './shapes/TLLineShape' export { - noteShapeMigrations, + noteShapeTypeMigrations, noteShapeTypeValidator, type TLNoteShape, type TLNoteShapeProps, } from './shapes/TLNoteShape' export { - textShapeMigrations, + textShapeTypeMigrations, textShapeTypeValidator, type TLTextShape, type TLTextShapeProps, } from './shapes/TLTextShape' export { - videoShapeMigrations, + videoShapeTypeMigrations, videoShapeTypeValidator, type TLVideoShape, type TLVideoShapeProps, diff --git a/packages/tlschema/src/migrations.test.ts b/packages/tlschema/src/migrations.test.ts index acad1436e..69efe0a8b 100644 --- a/packages/tlschema/src/migrations.test.ts +++ b/packages/tlschema/src/migrations.test.ts @@ -10,15 +10,15 @@ import { rootShapeTypeMigrations, TLShape } from './records/TLShape' import { userDocumentTypeMigrations, userDocumentVersions } from './records/TLUserDocument' import { userPresenceTypeMigrations } from './records/TLUserPresence' import { storeMigrations } from './schema' -import { arrowShapeMigrations } from './shapes/TLArrowShape' -import { bookmarkShapeMigrations } from './shapes/TLBookmarkShape' -import { drawShapeMigrations } from './shapes/TLDrawShape' -import { embedShapeMigrations } from './shapes/TLEmbedShape' -import { geoShapeMigrations } from './shapes/TLGeoShape' -import { imageShapeMigrations } from './shapes/TLImageShape' -import { noteShapeMigrations } from './shapes/TLNoteShape' -import { textShapeMigrations } from './shapes/TLTextShape' -import { videoShapeMigrations } from './shapes/TLVideoShape' +import { arrowShapeTypeMigrations } from './shapes/TLArrowShape' +import { bookmarkShapeTypeMigrations } from './shapes/TLBookmarkShape' +import { drawShapeTypeMigrations } from './shapes/TLDrawShape' +import { embedShapeTypeMigrations } from './shapes/TLEmbedShape' +import { geoShapeTypeMigrations } from './shapes/TLGeoShape' +import { imageShapeTypeMigrations } from './shapes/TLImageShape' +import { noteShapeTypeMigrations } from './shapes/TLNoteShape' +import { textShapeTypeMigrations } from './shapes/TLTextShape' +import { videoShapeTypeMigrations } from './shapes/TLVideoShape' const assetModules = fs .readdirSync('src/assets') @@ -90,7 +90,9 @@ for (const [fileName, module] of allModules) { test('all modules export migrations', () => { const modulesWithoutMigrations = allModules - .filter(([, module]) => !Object.keys(module).find((k) => k.endsWith('igrations'))) + .filter(([, module]) => { + return !Object.keys(module).find((k) => k.endsWith('igrations')) + }) .map(([fileName]) => fileName) // IF THIS LINE IS FAILING YOU NEED TO MAKE SURE THE MIGRATIONS ARE EXPORTED @@ -280,10 +282,10 @@ describe('Adding snap mode', () => { describe('Adding url props', () => { for (const [name, { up, down }] of [ - ['video shape', videoShapeMigrations.migrators[1]], - ['note shape', noteShapeMigrations.migrators[1]], - ['geo shape', geoShapeMigrations.migrators[1]], - ['image shape', imageShapeMigrations.migrators[1]], + ['video shape', videoShapeTypeMigrations.migrators[1]], + ['note shape', noteShapeTypeMigrations.migrators[1]], + ['geo shape', geoShapeTypeMigrations.migrators[1]], + ['image shape', imageShapeTypeMigrations.migrators[1]], ] as const) { test(`${name}: up works as expected`, () => { const before = { props: {} } @@ -300,7 +302,7 @@ describe('Adding url props', () => { }) describe('Bookmark null asset id', () => { - const { up, down } = bookmarkShapeMigrations.migrators[1] + const { up, down } = bookmarkShapeTypeMigrations.migrators[1] test('up works as expected', () => { const before = { props: {} } const after = { props: { assetId: null } } @@ -376,7 +378,7 @@ describe('Cleaning up junk data in instance.propsForNextShape', () => { }) describe('Generating original URL from embed URL in GenOriginalUrlInEmbed', () => { - const { up, down } = embedShapeMigrations.migrators[1] + const { up, down } = embedShapeTypeMigrations.migrators[1] test('up works as expected', () => { expect(up({ props: { url: 'https://codepen.io/Rplus/embed/PWZYRM' } })).toEqual({ props: { @@ -417,7 +419,7 @@ describe('Generating original URL from embed URL in GenOriginalUrlInEmbed', () = }) describe('Adding isPen prop', () => { - const { up, down } = drawShapeMigrations.migrators[1] + const { up, down } = drawShapeTypeMigrations.migrators[1] test('up works as expected with a shape that is not a pen shape', () => { expect( @@ -502,8 +504,8 @@ describe('Adding isLocked prop', () => { describe('Adding labelColor prop to geo / arrow shapes', () => { for (const [name, { up, down }] of [ - ['arrow shape', arrowShapeMigrations.migrators[1]], - ['geo shape', geoShapeMigrations.migrators[2]], + ['arrow shape', arrowShapeTypeMigrations.migrators[1]], + ['geo shape', geoShapeTypeMigrations.migrators[2]], ] as const) { test(`${name}: up works as expected`, () => { expect(up({ props: { color: 'red' } })).toEqual({ @@ -600,9 +602,9 @@ describe('Adding zoomBrush prop to instance', () => { describe('Removing align=justify from shape align props', () => { for (const [name, { up, down }] of [ - ['text', textShapeMigrations.migrators[1]], - ['note', noteShapeMigrations.migrators[2]], - ['geo', geoShapeMigrations.migrators[3]], + ['text', textShapeTypeMigrations.migrators[1]], + ['note', noteShapeTypeMigrations.migrators[2]], + ['geo', geoShapeTypeMigrations.migrators[3]], ] as const) { test(`${name}: up works as expected`, () => { expect(up({ props: { align: 'justify' } })).toEqual({ @@ -622,7 +624,7 @@ describe('Removing align=justify from shape align props', () => { }) describe('Add crop=null to image shapes', () => { - const { up, down } = imageShapeMigrations.migrators[2] + const { up, down } = imageShapeTypeMigrations.migrators[2] test('up works as expected', () => { expect(up({ props: { w: 100 } })).toEqual({ props: { w: 100, crop: null }, @@ -655,7 +657,7 @@ describe('Adding instance_presence to the schema', () => { }) describe('Adding check-box to geo shape', () => { - const { up, down } = geoShapeMigrations.migrators[4] + const { up, down } = geoShapeTypeMigrations.migrators[4] test('up works as expected', () => { expect(up({ props: { geo: 'rectangle' } })).toEqual({ props: { geo: 'rectangle' } }) @@ -667,7 +669,7 @@ describe('Adding check-box to geo shape', () => { }) describe('Add verticalAlign to geo shape', () => { - const { up, down } = geoShapeMigrations.migrators[5] + const { up, down } = geoShapeTypeMigrations.migrators[5] test('up works as expected', () => { expect(up({ props: { type: 'ellipse' } })).toEqual({ diff --git a/packages/tlschema/src/records/TLAsset.ts b/packages/tlschema/src/records/TLAsset.ts index 6049ea99b..8d9872d0e 100644 --- a/packages/tlschema/src/records/TLAsset.ts +++ b/packages/tlschema/src/records/TLAsset.ts @@ -14,7 +14,6 @@ import { TLShape } from './TLShape' /** @public */ export type TLAsset = TLImageAsset | TLVideoAsset | TLBookmarkAsset -// --- VALIDATION --- /** @public */ export const assetTypeValidator: T.Validator = T.model( 'asset', @@ -25,20 +24,8 @@ export const assetTypeValidator: T.Validator = T.model( }) ) -// --- MIGRATIONS --- -// STEP 1: Add a new version number here, give it a meaningful name. -// It should be 1 higher than the current version -const Versions = { - Initial: 0, -} as const - /** @public */ export const assetTypeMigrations = defineMigrations({ - firstVersion: Versions.Initial, - // STEP 2: Update the current version to point to your latest version - currentVersion: Versions.Initial, - // STEP 3: Add an up+down migration for the new version here - migrators: {}, subTypeKey: 'type', subTypeMigrations: { image: imageAssetMigrations, diff --git a/packages/tlschema/src/records/TLCamera.ts b/packages/tlschema/src/records/TLCamera.ts index 41e71e3d9..2ada5e3ee 100644 --- a/packages/tlschema/src/records/TLCamera.ts +++ b/packages/tlschema/src/records/TLCamera.ts @@ -16,7 +16,6 @@ export interface TLCamera extends BaseRecord<'camera'> { /** @public */ export type TLCameraId = ID -// --- VALIDATION --- /** @public */ export const cameraTypeValidator: T.Validator = T.model( 'camera', @@ -29,25 +28,8 @@ export const cameraTypeValidator: T.Validator = T.model( }) ) -// --- MIGRATIONS --- -// STEP 1: Add a new version number here, give it a meaningful name. -// It should be 1 higher than the current version -const Versions = { - Initial: 0, -} as const - -/** @public */ -export const cameraTypeMigrations = defineMigrations({ - firstVersion: Versions.Initial, - // STEP 2: Update the current version to point to your latest version - currentVersion: Versions.Initial, - // STEP 3: Add an up+down migration for the new version here - migrators: {}, -}) - /** @public */ export const TLCamera = createRecordType('camera', { - migrations: cameraTypeMigrations, validator: cameraTypeValidator, scope: 'instance', }).withDefaultProperties( @@ -57,3 +39,6 @@ export const TLCamera = createRecordType('camera', { z: 1, }) ) + +/** @public */ +export const cameraTypeMigrations = defineMigrations({}) diff --git a/packages/tlschema/src/records/TLDocument.ts b/packages/tlschema/src/records/TLDocument.ts index 9ff7773c3..799bb2e39 100644 --- a/packages/tlschema/src/records/TLDocument.ts +++ b/packages/tlschema/src/records/TLDocument.ts @@ -10,7 +10,6 @@ export interface TLDocument extends BaseRecord<'document'> { gridSize: number } -// --- VALIDATION --- /** @public */ export const documentTypeValidator: T.Validator = T.model( 'document', @@ -21,25 +20,8 @@ export const documentTypeValidator: T.Validator = T.model( }) ) -// --- MIGRATIONS --- -// STEP 1: Add a new version number here, give it a meaningful name. -// It should be 1 higher than the current version -const Versions = { - Initial: 0, -} as const - -/** @public */ -export const documentTypeMigrations = defineMigrations({ - firstVersion: Versions.Initial, - // STEP 2: Update the current version to point to your latest version - currentVersion: Versions.Initial, - // STEP 3: Add an up+down migration for the new version here - migrators: {}, -}) - /** @public */ export const TLDocument = createRecordType('document', { - migrations: documentTypeMigrations, validator: documentTypeValidator, scope: 'document', }).withDefaultProperties( @@ -51,3 +33,6 @@ export const TLDocument = createRecordType('document', { // all document records have the same ID: 'document:document' /** @public */ export const TLDOCUMENT_ID: ID = TLDocument.createCustomId('document') + +/** @public */ +export const documentTypeMigrations = defineMigrations({}) diff --git a/packages/tlschema/src/records/TLInstance.ts b/packages/tlschema/src/records/TLInstance.ts index d9903725d..01d36a835 100644 --- a/packages/tlschema/src/records/TLInstance.ts +++ b/packages/tlschema/src/records/TLInstance.ts @@ -53,7 +53,6 @@ export interface TLInstance extends BaseRecord<'instance'> { /** @public */ export type TLInstanceId = ID -// --- VALIDATION --- /** @public */ export const instanceTypeValidator: T.Validator = T.model( 'instance', @@ -91,11 +90,7 @@ export const instanceTypeValidator: T.Validator = T.model( }) ) -// --- MIGRATIONS --- -// STEP 1: Add a new version number here, give it a meaningful name. -// It should be 1 higher than the current version const Versions = { - Initial: 0, AddTransparentExportBgs: 1, RemoveDialog: 2, AddToolLockMode: 3, @@ -110,10 +105,7 @@ const Versions = { /** @public */ export const instanceTypeMigrations = defineMigrations({ - firstVersion: Versions.Initial, - // STEP 2: Update the current version to point to your latest version currentVersion: Versions.AddScribbleDelay, - // STEP 3: Add an up+down migration for the new version here migrators: { [Versions.AddTransparentExportBgs]: { up: (instance: TLInstance) => { diff --git a/packages/tlschema/src/records/TLInstancePageState.ts b/packages/tlschema/src/records/TLInstancePageState.ts index ee8579bf3..7d36ecda4 100644 --- a/packages/tlschema/src/records/TLInstancePageState.ts +++ b/packages/tlschema/src/records/TLInstancePageState.ts @@ -26,7 +26,6 @@ export interface TLInstancePageState extends BaseRecord<'instance_page_state'> { focusLayerId: TLShapeId | null } -// --- VALIDATION --- /** @public */ export const instancePageStateTypeValidator: T.Validator = T.model( 'instance_page_state', @@ -46,17 +45,12 @@ export const instancePageStateTypeValidator: T.Validator = }) ) -// --- MIGRATIONS --- -// STEP 1: Add a new version number here, give it a meaningful name. -// It should be 1 higher than the current version const Versions = { - Initial: 0, AddCroppingId: 1, } as const /** @public */ export const instancePageStateMigrations = defineMigrations({ - firstVersion: Versions.Initial, currentVersion: Versions.AddCroppingId, migrators: { [Versions.AddCroppingId]: { diff --git a/packages/tlschema/src/records/TLInstancePresence.ts b/packages/tlschema/src/records/TLInstancePresence.ts index 7b9c570dc..cd5175ecd 100644 --- a/packages/tlschema/src/records/TLInstancePresence.ts +++ b/packages/tlschema/src/records/TLInstancePresence.ts @@ -65,20 +65,13 @@ export const instancePresenceTypeValidator: T.Validator = T. }) ) -// --- MIGRATIONS --- -// STEP 1: Add a new version number here, give it a meaningful name. -// It should be 1 higher than the current version const Versions = { - Initial: 0, AddScribbleDelay: 1, } as const export const instancePresenceTypeMigrations = defineMigrations({ - // STEP 2: Update the current version to point to your latest version - firstVersion: Versions.Initial, currentVersion: Versions.AddScribbleDelay, migrators: { - // STEP 3: Add an up+down migration for the new version here [Versions.AddScribbleDelay]: { up: (instance) => { if (instance.scribble !== null) { diff --git a/packages/tlschema/src/records/TLPage.ts b/packages/tlschema/src/records/TLPage.ts index b7dfdfcfb..0b245c986 100644 --- a/packages/tlschema/src/records/TLPage.ts +++ b/packages/tlschema/src/records/TLPage.ts @@ -15,7 +15,6 @@ export interface TLPage extends BaseRecord<'page'> { /** @public */ export type TLPageId = ID -// --- VALIDATION --- /** @public */ export const pageTypeValidator: T.Validator = T.model( 'page', @@ -27,25 +26,11 @@ export const pageTypeValidator: T.Validator = T.model( }) ) -// --- MIGRATIONS --- -// STEP 1: Add a new version number here, give it a meaningful name. -// It should be 1 higher than the current version -const Versions = { - Initial: 0, -} as const - -/** @public */ -export const pageTypeMigrations = defineMigrations({ - firstVersion: Versions.Initial, - // STEP 2: Update the current version to point to your latest version - currentVersion: Versions.Initial, - // STEP 3: Add an up+down migration for the new version here - migrators: {}, -}) - /** @public */ export const TLPage = createRecordType('page', { - migrations: pageTypeMigrations, validator: pageTypeValidator, scope: 'document', }) + +/** @public */ +export const pageTypeMigrations = defineMigrations({}) diff --git a/packages/tlschema/src/records/TLShape.ts b/packages/tlschema/src/records/TLShape.ts index 9131e3c30..7390c86a5 100644 --- a/packages/tlschema/src/records/TLShape.ts +++ b/packages/tlschema/src/records/TLShape.ts @@ -68,21 +68,14 @@ export type TLParentId = TLPageId | TLShapeId /** @public */ export type TLNullableShapeProps = { [K in TLShapeProp]?: TLShapeProps[K] | null } -// --- MIGRATIONS --- -// STEP 1: Add a new version number here, give it a meaningful name. -// It should be 1 higher than the current version const Versions = { - Initial: 0, AddIsLocked: 1, } as const /** @internal */ export const rootShapeTypeMigrations = defineMigrations({ - // STEP 2: Update the current version to point to your latest version currentVersion: Versions.AddIsLocked, - firstVersion: Versions.Initial, migrators: { - // STEP 3: Add an up+down migration for the new version here [Versions.AddIsLocked]: { up: (record) => { return { diff --git a/packages/tlschema/src/records/TLUser.ts b/packages/tlschema/src/records/TLUser.ts index b76df633c..c4364ad60 100644 --- a/packages/tlschema/src/records/TLUser.ts +++ b/packages/tlschema/src/records/TLUser.ts @@ -15,7 +15,6 @@ export interface TLUser extends BaseRecord<'user'> { /** @public */ export type TLUserId = ID -// --- VALIDATION --- /** @public */ export const userTypeValidator: T.Validator = T.model( 'user', @@ -27,26 +26,8 @@ export const userTypeValidator: T.Validator = T.model( }) ) -// --- MIGRATIONS --- -// STEP 1: Add a new version number here, give it a meaningful name. -// It should be 1 higher than the current version -const Versions = { - Initial: 0, -} as const - -/** @public */ -export const userTypeMigrations = defineMigrations({ - // STEP 2: Update the current version to point to your latest version - currentVersion: Versions.Initial, - firstVersion: Versions.Initial, - migrators: { - // STEP 3: Add an up+down migration for the new version here - }, -}) - /** @public */ export const TLUser = createRecordType('user', { - migrations: userTypeMigrations, validator: userTypeValidator, scope: 'instance', }).withDefaultProperties((): Omit => { @@ -59,3 +40,6 @@ export const TLUser = createRecordType('user', { locale, } }) + +/** @public */ +export const userTypeMigrations = defineMigrations({}) diff --git a/packages/tlschema/src/records/TLUserDocument.ts b/packages/tlschema/src/records/TLUserDocument.ts index eaaa61004..5a7c9028a 100644 --- a/packages/tlschema/src/records/TLUserDocument.ts +++ b/packages/tlschema/src/records/TLUserDocument.ts @@ -26,7 +26,6 @@ export interface TLUserDocument extends BaseRecord<'user_document'> { /** @public */ export type TLUserDocumentId = ID -// --- VALIDATION --- /** @public */ export const userDocumentTypeValidator: T.Validator = T.model( 'user_document', @@ -44,11 +43,7 @@ export const userDocumentTypeValidator: T.Validator = T.model( }) ) -// --- MIGRATIONS --- -// STEP 1: Add a new version number here, give it a meaningful name. -// It should be 1 higher than the current version -export const userDocumentVersions = { - Initial: 0, +export const Versions = { AddSnapMode: 1, AddMissingIsMobileMode: 2, RemoveIsReadOnly: 3, @@ -56,12 +51,9 @@ export const userDocumentVersions = { /** @public */ export const userDocumentTypeMigrations = defineMigrations({ - firstVersion: userDocumentVersions.Initial, - // STEP 2: Update the current version to point to your latest version - currentVersion: userDocumentVersions.RemoveIsReadOnly, - // STEP 3: Add an up+down migration for the new version here + currentVersion: Versions.RemoveIsReadOnly, migrators: { - [userDocumentVersions.AddSnapMode]: { + [Versions.AddSnapMode]: { up: (userDocument: TLUserDocument) => { return { ...userDocument, isSnapMode: false } }, @@ -69,7 +61,7 @@ export const userDocumentTypeMigrations = defineMigrations({ return userDocument }, }, - [userDocumentVersions.AddMissingIsMobileMode]: { + [Versions.AddMissingIsMobileMode]: { up: (userDocument: TLUserDocument) => { return { ...userDocument, isMobileMode: userDocument.isMobileMode ?? false } }, @@ -77,7 +69,7 @@ export const userDocumentTypeMigrations = defineMigrations({ return userDocument }, }, - [userDocumentVersions.RemoveIsReadOnly]: { + [Versions.RemoveIsReadOnly]: { up: ({ isReadOnly: _, ...userDocument }: TLUserDocument & { isReadOnly: boolean }) => { return userDocument }, @@ -107,3 +99,5 @@ export const TLUserDocument = createRecordType('user_document', lastUsedTabId: null, }) ) + +export { Versions as userDocumentVersions } diff --git a/packages/tlschema/src/records/TLUserPresence.ts b/packages/tlschema/src/records/TLUserPresence.ts index 78dc716b8..50accc08b 100644 --- a/packages/tlschema/src/records/TLUserPresence.ts +++ b/packages/tlschema/src/records/TLUserPresence.ts @@ -18,7 +18,6 @@ export interface TLUserPresence extends BaseRecord<'user_presence'> { /** @public */ export type TLUserPresenceId = ID -// --- VALIDATION --- /** @public */ export const userPresenceTypeValidator: T.Validator = T.model( 'user_presence', @@ -34,21 +33,14 @@ export const userPresenceTypeValidator: T.Validator = T.model( }) ) -// --- MIGRATIONS --- -// STEP 1: Add a new version number here, give it a meaningful name. -// It should be 1 higher than the current version const Versions = { - Initial: 0, AddViewportPageBounds: 1, } as const /** @public */ export const userPresenceTypeMigrations = defineMigrations({ - // STEP 2: Update the current version to point to your latest version currentVersion: Versions.AddViewportPageBounds, - firstVersion: Versions.Initial, migrators: { - // STEP 3: Add an up+down migration for the new version here [Versions.AddViewportPageBounds]: { up: (record) => { return { diff --git a/packages/tlschema/src/schema.ts b/packages/tlschema/src/schema.ts index 8175eb914..432688543 100644 --- a/packages/tlschema/src/schema.ts +++ b/packages/tlschema/src/schema.ts @@ -1,22 +1,15 @@ import { defineMigrations, StoreSnapshot } from '@tldraw/tlstore' import { TLRecord } from './TLRecord' -// --- MIGRATIONS --- -// STEP 1: Add a new version number here, give it a meaningful name. -// It should be 1 higher than the current version const Versions = { - Initial: 0, RemoveCodeAndIconShapeTypes: 1, AddInstancePresenceType: 2, } as const /** @public */ export const storeMigrations = defineMigrations({ - // STEP 2: Update the current version to point to your latest version - firstVersion: Versions.Initial, currentVersion: Versions.AddInstancePresenceType, migrators: { - // STEP 3: Add an up+down migration for the new version here [Versions.RemoveCodeAndIconShapeTypes]: { up: (store: StoreSnapshot) => { return Object.fromEntries( diff --git a/packages/tlschema/src/shapes/TLArrowShape.ts b/packages/tlschema/src/shapes/TLArrowShape.ts index dd678ec81..8a203b74e 100644 --- a/packages/tlschema/src/shapes/TLArrowShape.ts +++ b/packages/tlschema/src/shapes/TLArrowShape.ts @@ -70,7 +70,6 @@ export interface TLArrowHeadModel { type: TLArrowheadType } -// --- VALIDATION --- /** @public */ export const arrowTerminalTypeValidator: T.Validator = T.union('type', { binding: T.object({ @@ -106,21 +105,14 @@ export const arrowShapeTypeValidator: T.Validator = createShapeVal }) ) -// --- MIGRATIONS --- -// STEP 1: Add a new version number here, give it a meaningful name. -// It should be 1 higher than the current version const Versions = { - Initial: 0, AddLabelColor: 1, } as const /** @public */ -export const arrowShapeMigrations = defineMigrations({ - // STEP 2: Update the current version to point to your latest version +export const arrowShapeTypeMigrations = defineMigrations({ currentVersion: Versions.AddLabelColor, - firstVersion: Versions.Initial, migrators: { - // STEP 3: Add an up+down migration for the new version here [Versions.AddLabelColor]: { up: (record) => { return { diff --git a/packages/tlschema/src/shapes/TLBookmarkShape.ts b/packages/tlschema/src/shapes/TLBookmarkShape.ts index bd18ebb38..b79abbb5c 100644 --- a/packages/tlschema/src/shapes/TLBookmarkShape.ts +++ b/packages/tlschema/src/shapes/TLBookmarkShape.ts @@ -17,7 +17,6 @@ export type TLBookmarkShapeProps = { /** @public */ export type TLBookmarkShape = TLBaseShape<'bookmark', TLBookmarkShapeProps> -// --- VALIDATION --- /** @public */ export const bookmarkShapeTypeValidator: T.Validator = createShapeValidator( 'bookmark', @@ -30,20 +29,13 @@ export const bookmarkShapeTypeValidator: T.Validator = createSh }) ) -// --- MIGRATIONS --- -// STEP 1: Add a new version number here, give it a meaningful name. -// It should be 1 higher than the current version const Versions = { - Initial: 0, NullAssetId: 1, } as const /** @public */ -export const bookmarkShapeMigrations = defineMigrations({ - firstVersion: Versions.Initial, - // STEP 2: Update the current version to point to your latest version +export const bookmarkShapeTypeMigrations = defineMigrations({ currentVersion: Versions.NullAssetId, - // STEP 3: Add an up+down migration for the new version here migrators: { [Versions.NullAssetId]: { up: (shape: TLBookmarkShape) => { diff --git a/packages/tlschema/src/shapes/TLDrawShape.ts b/packages/tlschema/src/shapes/TLDrawShape.ts index 1bed747e1..d2b17499b 100644 --- a/packages/tlschema/src/shapes/TLDrawShape.ts +++ b/packages/tlschema/src/shapes/TLDrawShape.ts @@ -37,7 +37,6 @@ export type TLDrawShapeProps = { /** @public */ export type TLDrawShape = TLBaseShape<'draw', TLDrawShapeProps> -// --- VALIDATION --- /** @public */ export const drawShapeTypeValidator: T.Validator = createShapeValidator( 'draw', @@ -59,21 +58,14 @@ export const drawShapeTypeValidator: T.Validator = createShapeValid }) ) -// --- MIGRATIONS --- -// STEP 1: Add a new version number here, give it a meaningful name. -// It should be 1 higher than the current version const Versions = { - Initial: 0, AddInPen: 1, } as const /** @public */ -export const drawShapeMigrations = defineMigrations({ - // STEP 2: Update the current version to point to your latest version - firstVersion: Versions.Initial, +export const drawShapeTypeMigrations = defineMigrations({ currentVersion: Versions.AddInPen, migrators: { - // STEP 3: Add an up+down migration for the new version here [Versions.AddInPen]: { up: (shape) => { // Rather than checking to see whether the shape is a pen at runtime, diff --git a/packages/tlschema/src/shapes/TLEmbedShape.ts b/packages/tlschema/src/shapes/TLEmbedShape.ts index 87b605623..6786473ba 100644 --- a/packages/tlschema/src/shapes/TLEmbedShape.ts +++ b/packages/tlschema/src/shapes/TLEmbedShape.ts @@ -78,7 +78,6 @@ export type TLEmbedShapeProps = { /** @public */ export type TLEmbedShape = TLBaseShape<'embed', TLEmbedShapeProps> -// --- VALIDATION --- /** @public */ export const embedShapeTypeValidator: T.Validator = createShapeValidator( 'embed', @@ -605,21 +604,14 @@ export const EMBED_DEFINITIONS = [ }, ] as const satisfies readonly EmbedDefinition[] -// --- MIGRATIONS --- -// STEP 1: Add a new version number here, give it a meaningful name. -// It should be 1 higher than the current version const Versions = { - Initial: 0, GenOriginalUrlInEmbed: 1, } as const /** @public */ -export const embedShapeMigrations = defineMigrations({ - // STEP 2: Update the current version to point to your latest version +export const embedShapeTypeMigrations = defineMigrations({ currentVersion: Versions.GenOriginalUrlInEmbed, - firstVersion: Versions.Initial, migrators: { - // STEP 3: Add an up+down migration for the new version here [Versions.GenOriginalUrlInEmbed]: { // add tmpOldUrl property up: (shape) => { diff --git a/packages/tlschema/src/shapes/TLFrameShape.ts b/packages/tlschema/src/shapes/TLFrameShape.ts index c5de357f2..853389cc5 100644 --- a/packages/tlschema/src/shapes/TLFrameShape.ts +++ b/packages/tlschema/src/shapes/TLFrameShape.ts @@ -15,7 +15,6 @@ export type TLFrameShapeProps = { /** @public */ export type TLFrameShape = TLBaseShape<'frame', TLFrameShapeProps> -// --- VALIDATION --- /** @public */ export const frameShapeTypeValidator: T.Validator = createShapeValidator( 'frame', @@ -27,19 +26,5 @@ export const frameShapeTypeValidator: T.Validator = createShapeVal }) ) -// --- MIGRATIONS --- -// STEP 1: Add a new version number here, give it a meaningful name. -// It should be 1 higher than the current version -const Versions = { - Initial: 0, -} as const - /** @public */ -export const frameShapeMigrations = defineMigrations({ - // STEP 2: Update the current version to point to your latest version - currentVersion: Versions.Initial, - firstVersion: Versions.Initial, - migrators: { - // STEP 3: Add an up+down migration for the new version here - }, -}) +export const frameShapeTypeMigrations = defineMigrations({}) diff --git a/packages/tlschema/src/shapes/TLGeoShape.ts b/packages/tlschema/src/shapes/TLGeoShape.ts index 613276659..4e67d5dd8 100644 --- a/packages/tlschema/src/shapes/TLGeoShape.ts +++ b/packages/tlschema/src/shapes/TLGeoShape.ts @@ -46,7 +46,6 @@ export type TLGeoShapeProps = { /** @public */ export type TLGeoShape = TLBaseShape<'geo', TLGeoShapeProps> -// --- VALIDATION --- /** @public */ export const geoShapeTypeValidator: T.Validator = createShapeValidator( 'geo', @@ -69,11 +68,7 @@ export const geoShapeTypeValidator: T.Validator = createShapeValidat }) ) -// --- MIGRATIONS --- -// STEP 1: Add a new version number here, give it a meaningful name. -// It should be 1 higher than the current version const Versions = { - Initial: 0, AddUrlProp: 1, AddLabelColor: 2, RemoveJustify: 3, @@ -82,12 +77,9 @@ const Versions = { } as const /** @public */ -export const geoShapeMigrations = defineMigrations({ - // STEP 2: Update the current version to point to your latest version - firstVersion: Versions.Initial, +export const geoShapeTypeMigrations = defineMigrations({ currentVersion: Versions.AddVerticalAlign, migrators: { - // STEP 3: Add an up+down migration for the new version here [Versions.AddUrlProp]: { up: (shape) => { return { ...shape, props: { ...shape.props, url: '' } } diff --git a/packages/tlschema/src/shapes/TLGroupShape.ts b/packages/tlschema/src/shapes/TLGroupShape.ts index ecffde6a3..adf1b6ad8 100644 --- a/packages/tlschema/src/shapes/TLGroupShape.ts +++ b/packages/tlschema/src/shapes/TLGroupShape.ts @@ -12,7 +12,6 @@ export type TLGroupShapeProps = { /** @public */ export type TLGroupShape = TLBaseShape<'group', TLGroupShapeProps> -// --- VALIDATION --- /** @public */ export const groupShapeTypeValidator: T.Validator = createShapeValidator( 'group', @@ -21,19 +20,5 @@ export const groupShapeTypeValidator: T.Validator = createShapeVal }) ) -// --- MIGRATIONS --- -// STEP 1: Add a new version number here, give it a meaningful name. -// It should be 1 higher than the current version -const Versions = { - Initial: 0, -} as const - /** @public */ -export const groupShapeMigrations = defineMigrations({ - // STEP 2: Update the current version to point to your latest version - currentVersion: Versions.Initial, - firstVersion: Versions.Initial, - migrators: { - // STEP 3: Add an up+down migration for the new version here - }, -}) +export const groupShapeTypeMigrations = defineMigrations({}) diff --git a/packages/tlschema/src/shapes/TLIconShape.ts b/packages/tlschema/src/shapes/TLIconShape.ts index 3d3a0072c..87b453c8e 100644 --- a/packages/tlschema/src/shapes/TLIconShape.ts +++ b/packages/tlschema/src/shapes/TLIconShape.ts @@ -23,7 +23,6 @@ export type TLIconShapeProps = { /** @public */ export type TLIconShape = TLBaseShape<'icon', TLIconShapeProps> -// --- VALIDATION --- /** @public */ export const iconShapeTypeValidator: T.Validator = createShapeValidator( 'icon', @@ -37,19 +36,5 @@ export const iconShapeTypeValidator: T.Validator = createShapeValid }) ) -// --- MIGRATIONS --- -// STEP 1: Add a new version number here, give it a meaningful name. -// It should be 1 higher than the current version -const Versions = { - Initial: 0, -} as const - /** @public */ -export const iconShapeMigrations = defineMigrations({ - // STEP 2: Update the current version to point to your latest version - currentVersion: Versions.Initial, - firstVersion: Versions.Initial, - migrators: { - // STEP 3: Add an up+down migration for the new version here - }, -}) +export const iconShapeTypeMigrations = defineMigrations({}) diff --git a/packages/tlschema/src/shapes/TLImageShape.ts b/packages/tlschema/src/shapes/TLImageShape.ts index 83ec13fd5..df8b67739 100644 --- a/packages/tlschema/src/shapes/TLImageShape.ts +++ b/packages/tlschema/src/shapes/TLImageShape.ts @@ -32,7 +32,6 @@ export const cropValidator = T.object({ /** @public */ export type TLImageShape = TLBaseShape<'image', TLImageShapeProps> -// --- VALIDATION --- /** @public */ export const imageShapeTypeValidator: T.Validator = createShapeValidator( 'image', @@ -47,22 +46,15 @@ export const imageShapeTypeValidator: T.Validator = createShapeVal }) ) -// --- MIGRATIONS --- -// STEP 1: Add a new version number here, give it a meaningful name. -// It should be 1 higher than the current version const Versions = { - Initial: 0, AddUrlProp: 1, AddCropProp: 2, } as const /** @public */ -export const imageShapeMigrations = defineMigrations({ - // STEP 2: Update the current version to point to your latest version - firstVersion: Versions.Initial, +export const imageShapeTypeMigrations = defineMigrations({ currentVersion: Versions.AddCropProp, migrators: { - // STEP 3: Add an up+down migration for the new version here [Versions.AddUrlProp]: { up: (shape) => { return { ...shape, props: { ...shape.props, url: '' } } diff --git a/packages/tlschema/src/shapes/TLLineShape.ts b/packages/tlschema/src/shapes/TLLineShape.ts index 1500680d7..8fc6fdfcd 100644 --- a/packages/tlschema/src/shapes/TLLineShape.ts +++ b/packages/tlschema/src/shapes/TLLineShape.ts @@ -26,7 +26,6 @@ export type TLLineShapeProps = { /** @public */ export type TLLineShape = TLBaseShape<'line', TLLineShapeProps> -// --- VALIDATION --- /** @public */ export const lineShapeTypeValidator: T.Validator = createShapeValidator( 'line', @@ -40,19 +39,5 @@ export const lineShapeTypeValidator: T.Validator = createShapeValid }) ) -// --- MIGRATIONS --- -// STEP 1: Add a new version number here, give it a meaningful name. -// It should be 1 higher than the current version -const Versions = { - Initial: 0, -} as const - /** @public */ -export const lineShapeMigrations = defineMigrations({ - // STEP 2: Update the current version to point to your latest version - currentVersion: Versions.Initial, - firstVersion: Versions.Initial, - migrators: { - // STEP 3: Add an up+down migration for the new version here - }, -}) +export const lineShapeTypeMigrations = defineMigrations({}) diff --git a/packages/tlschema/src/shapes/TLNoteShape.ts b/packages/tlschema/src/shapes/TLNoteShape.ts index b92053de8..5929bb45c 100644 --- a/packages/tlschema/src/shapes/TLNoteShape.ts +++ b/packages/tlschema/src/shapes/TLNoteShape.ts @@ -25,7 +25,6 @@ export type TLNoteShapeProps = { /** @public */ export type TLNoteShape = TLBaseShape<'note', TLNoteShapeProps> -// --- VALIDATION --- /** @public */ export const noteShapeTypeValidator: T.Validator = createShapeValidator( 'note', @@ -41,22 +40,15 @@ export const noteShapeTypeValidator: T.Validator = createShapeValid }) ) -// --- MIGRATIONS --- -// STEP 1: Add a new version number here, give it a meaningful name. -// It should be 1 higher than the current version const Versions = { - Initial: 0, AddUrlProp: 1, RemoveJustify: 2, } as const /** @public */ -export const noteShapeMigrations = defineMigrations({ - // STEP 2: Update the current version to point to your latest version - firstVersion: Versions.Initial, +export const noteShapeTypeMigrations = defineMigrations({ currentVersion: Versions.RemoveJustify, migrators: { - // STEP 3: Add an up+down migration for the new version here [Versions.AddUrlProp]: { up: (shape) => { return { ...shape, props: { ...shape.props, url: '' } } diff --git a/packages/tlschema/src/shapes/TLTextShape.ts b/packages/tlschema/src/shapes/TLTextShape.ts index af5769dfb..50802eb7b 100644 --- a/packages/tlschema/src/shapes/TLTextShape.ts +++ b/packages/tlschema/src/shapes/TLTextShape.ts @@ -26,7 +26,6 @@ export type TLTextShapeProps = { /** @public */ export type TLTextShape = TLBaseShape<'text', TLTextShapeProps> -// --- VALIDATION --- /** @public */ export const textShapeTypeValidator: T.Validator = createShapeValidator( 'text', @@ -43,18 +42,12 @@ export const textShapeTypeValidator: T.Validator = createShapeValid }) ) -// --- MIGRATIONS --- -// STEP 1: Add a new version number here, give it a meaningful name. -// It should be 1 higher than the current version const Versions = { - Initial: 0, RemoveJustify: 1, } as const /** @public */ -export const textShapeMigrations = defineMigrations({ - // STEP 2: Update the current version to point to your latest version - firstVersion: Versions.Initial, +export const textShapeTypeMigrations = defineMigrations({ currentVersion: Versions.RemoveJustify, migrators: { [Versions.RemoveJustify]: { diff --git a/packages/tlschema/src/shapes/TLVideoShape.ts b/packages/tlschema/src/shapes/TLVideoShape.ts index de3712d5f..44c702a73 100644 --- a/packages/tlschema/src/shapes/TLVideoShape.ts +++ b/packages/tlschema/src/shapes/TLVideoShape.ts @@ -19,7 +19,6 @@ export type TLVideoShapeProps = { /** @public */ export type TLVideoShape = TLBaseShape<'video', TLVideoShapeProps> -// --- VALIDATION --- /** @public */ export const videoShapeTypeValidator: T.Validator = createShapeValidator( 'video', @@ -34,21 +33,14 @@ export const videoShapeTypeValidator: T.Validator = createShapeVal }) ) -// --- MIGRATIONS --- -// STEP 1: Add a new version number here, give it a meaningful name. -// It should be 1 higher than the current version const Versions = { - Initial: 0, AddUrlProp: 1, } as const /** @public */ -export const videoShapeMigrations = defineMigrations({ - // STEP 2: Update the current version to point to your latest version - firstVersion: Versions.Initial, +export const videoShapeTypeMigrations = defineMigrations({ currentVersion: Versions.AddUrlProp, migrators: { - // STEP 3: Add an up+down migration for the new version here [Versions.AddUrlProp]: { up: (shape) => { return { ...shape, props: { ...shape.props, url: '' } } diff --git a/packages/tlstore/api-report.md b/packages/tlstore/api-report.md index 44aea1f46..ff6a911a1 100644 --- a/packages/tlstore/api-report.md +++ b/packages/tlstore/api-report.md @@ -47,12 +47,16 @@ export function createRecordType(typeName: R['typeName'], }): RecordType>; // @public (undocumented) -export function defineMigrations({ firstVersion, currentVersion, migrators, subTypeKey, subTypeMigrations, }: { - firstVersion: FirstVersion; - currentVersion: CurrentVersion; - migrators: { +export function defineMigrations = EMPTY_SYMBOL>(opts: { + firstVersion?: CurrentVersion extends number ? FirstVersion : never; + currentVersion?: CurrentVersion; + migrators?: CurrentVersion extends number ? FirstVersion extends number ? CurrentVersion extends FirstVersion ? { + [version in Exclude, 0>]: Migration; + } : { [version in Exclude, FirstVersion>]: Migration; - }; + } : { + [version in Exclude, 0>]: Migration; + } : never; subTypeKey?: string; subTypeMigrations?: Record; }): Migrations; @@ -106,9 +110,9 @@ export function migrateRecord({ record, migrations, fromVe }): MigrationResult; // @public (undocumented) -export type Migration = { - up: (oldState: T) => T; - down: (newState: T) => T; +export type Migration = { + up: (oldState: Before) => After; + down: (newState: After) => Before; }; // @public (undocumented) diff --git a/packages/tlstore/src/lib/migrate.ts b/packages/tlstore/src/lib/migrate.ts index 0f88eb0ca..ea490a211 100644 --- a/packages/tlstore/src/lib/migrate.ts +++ b/packages/tlstore/src/lib/migrate.ts @@ -1,29 +1,49 @@ import { BaseRecord, isRecord } from './BaseRecord' import { SerializedSchema } from './StoreSchema' +type EMPTY_SYMBOL = symbol + /** @public */ -export function defineMigrations({ - firstVersion, - currentVersion, - migrators, - subTypeKey, - subTypeMigrations, -}: { - firstVersion: FirstVersion - currentVersion: CurrentVersion - migrators: { - [version in Exclude, FirstVersion>]: Migration - } +export function defineMigrations< + FirstVersion extends number | EMPTY_SYMBOL = EMPTY_SYMBOL, + CurrentVersion extends Exclude | EMPTY_SYMBOL = EMPTY_SYMBOL +>(opts: { + firstVersion?: CurrentVersion extends number ? FirstVersion : never + currentVersion?: CurrentVersion + migrators?: CurrentVersion extends number + ? FirstVersion extends number + ? CurrentVersion extends FirstVersion + ? { [version in Exclude, 0>]: Migration } + : { [version in Exclude, FirstVersion>]: Migration } + : { [version in Exclude, 0>]: Migration } + : never subTypeKey?: string subTypeMigrations?: Record }): Migrations { - return { currentVersion, firstVersion, migrators, subTypeKey, subTypeMigrations } + const { currentVersion, firstVersion, migrators = {}, subTypeKey, subTypeMigrations } = opts + + // Some basic guards against impossible version combinations, some of which will be caught by TypeScript + if (typeof currentVersion === 'number' && typeof firstVersion === 'number') { + if ((currentVersion as number) === (firstVersion as number)) { + throw Error(`Current version is equal to initial version.`) + } else if (currentVersion < firstVersion) { + throw Error(`Current version is lower than initial version.`) + } + } + + return { + firstVersion: (firstVersion as number) ?? 0, // defaults + currentVersion: (currentVersion as number) ?? 0, // defaults + migrators, + subTypeKey, + subTypeMigrations, + } } /** @public */ -export type Migration = { - up: (oldState: T) => T - down: (newState: T) => T +export type Migration = { + up: (oldState: Before) => After + down: (newState: After) => Before } interface BaseMigrationsInfo { diff --git a/packages/tlstore/src/lib/test/defineMigrations.test.ts b/packages/tlstore/src/lib/test/defineMigrations.test.ts new file mode 100644 index 000000000..0473be5aa --- /dev/null +++ b/packages/tlstore/src/lib/test/defineMigrations.test.ts @@ -0,0 +1,229 @@ +import { defineMigrations } from '../migrate' + +const Versions = { + Initial: 0, + January: 1, + February: 2, + March: 3, +} as const + +describe('define migrations tests', () => { + it('defines migrations', () => { + expect(() => { + // no versions + defineMigrations({ + // @ts-expect-error first version without current version + firstVersion: Versions.Initial, + }) + }).not.toThrowError() + + expect(() => { + // no versions + defineMigrations({ + // @ts-expect-error first version without current version + firstVersion: Versions.February, + }) + }).not.toThrowError() + + expect(() => { + // empty migrators + defineMigrations({ + // @ts-expect-error + migrators: {}, + }) + }).not.toThrowError() + + expect(() => { + // no versions! + defineMigrations({ + // @ts-expect-error + migrators: { + [Versions.February]: { + up: (rec: any) => rec, + down: (rec: any) => rec, + }, + }, + }) + }).not.toThrowError() + + expect(() => { + // wrong current version! + defineMigrations({ + currentVersion: Versions.January, + migrators: { + // @ts-expect-error + [Versions.February]: { + up: (rec: any) => rec, + down: (rec: any) => rec, + }, + }, + }) + }).not.toThrowError() + + expect(() => { + defineMigrations({ + currentVersion: Versions.February, + migrators: { + // has a default zero version + [Versions.January]: { + up: (rec: any) => rec, + down: (rec: any) => rec, + }, + // has a current version + [Versions.February]: { + up: (rec: any) => rec, + down: (rec: any) => rec, + }, + }, + }) + }).not.toThrowError() + + expect(() => { + // can't provide only first version + defineMigrations({ + // @ts-expect-error first version without current version + firstVersion: Versions.January, + // @ts-expect-error migrators without current version + migrators: {}, + }) + }).not.toThrowError() + + expect(() => { + // same version + defineMigrations({ + firstVersion: Versions.Initial, + currentVersion: Versions.Initial, + migrators: {}, + }) + }).toThrowError() + + expect(() => { + // only first version + defineMigrations({ + // @ts-expect-error + firstVersion: Versions.January, + // @ts-expect-error + migrators: {}, + }) + }).not.toThrowError() + + expect(() => { + // missing only version + defineMigrations({ + firstVersion: Versions.January, + currentVersion: Versions.January, + // @ts-expect-error + migrators: {}, + }) + }).toThrowError() + + expect(() => { + // only version, explicit start and current + defineMigrations({ + firstVersion: Versions.January, + currentVersion: Versions.January, + migrators: { + [Versions.January]: { + up: (rec: any) => rec, + down: (rec: any) => rec, + }, + }, + }) + }).toThrowError() + + expect(() => { + // missing later versions + defineMigrations({ + firstVersion: Versions.January, + currentVersion: Versions.February, + // @ts-expect-error + migrators: {}, + }) + }).not.toThrowError() + + expect(() => { + // missing later versions + defineMigrations({ + firstVersion: Versions.Initial, + currentVersion: Versions.February, + // @ts-expect-error + migrators: { + [Versions.January]: { + up: (rec: any) => rec, + down: (rec: any) => rec, + }, + }, + }) + }).not.toThrowError() + + expect(() => { + // missing earlier versions + defineMigrations({ + firstVersion: Versions.Initial, + currentVersion: Versions.February, + // @ts-expect-error + migrators: { + [Versions.February]: { + up: (rec: any) => rec, + down: (rec: any) => rec, + }, + }, + }) + }).not.toThrowError() + + expect(() => { + // got em all + defineMigrations({ + firstVersion: Versions.Initial, + currentVersion: Versions.February, + migrators: { + [Versions.January]: { + up: (rec: any) => rec, + down: (rec: any) => rec, + }, + [Versions.February]: { + up: (rec: any) => rec, + down: (rec: any) => rec, + }, + }, + }) + }).not.toThrowError() + + expect(() => { + // got em all starting later + defineMigrations({ + firstVersion: Versions.January, + currentVersion: Versions.March, + migrators: { + [Versions.February]: { + up: (rec: any) => rec, + down: (rec: any) => rec, + }, + [Versions.March]: { + up: (rec: any) => rec, + down: (rec: any) => rec, + }, + }, + }) + }).not.toThrowError() + + expect(() => { + // first migration should be first version + 1 + defineMigrations({ + firstVersion: Versions.February, + currentVersion: Versions.March, + migrators: { + // @ts-expect-error + [Versions.February]: { + up: (rec: any) => rec, + down: (rec: any) => rec, + }, + [Versions.March]: { + up: (rec: any) => rec, + down: (rec: any) => rec, + }, + }, + }) + }).not.toThrowError() + }) +}) diff --git a/packages/tlstore/src/lib/test/testSchema.v0.ts b/packages/tlstore/src/lib/test/testSchema.v0.ts index ad130984c..3d54d0b80 100644 --- a/packages/tlstore/src/lib/test/testSchema.v0.ts +++ b/packages/tlstore/src/lib/test/testSchema.v0.ts @@ -4,20 +4,12 @@ import { createRecordType } from '../RecordType' import { StoreSchema } from '../StoreSchema' import { defineMigrations } from '../migrate' -const UserVersion = { - Initial: 0, -} as const - /** A user of tldraw */ interface User extends BaseRecord<'user'> { name: string } -const userMigrations = defineMigrations({ - currentVersion: UserVersion.Initial, - firstVersion: UserVersion.Initial, - migrators: {}, -}) +const userMigrations = defineMigrations({}) const User = createRecordType('user', { migrations: userMigrations, @@ -32,14 +24,6 @@ const User = createRecordType('user', { scope: 'document', }) -const ShapeVersion = { - Initial: 0, -} as const - -const RectangleVersion = { - Initial: 0, -} as const - interface Shape extends BaseRecord<'shape'> { type: string x: number @@ -58,22 +42,15 @@ interface OvalProps { borderStyle: 'solid' | 'dashed' } -const shapeMigrations = defineMigrations({ - currentVersion: ShapeVersion.Initial, - firstVersion: ShapeVersion.Initial, - migrators: {}, +const shapeTypeMigrations = defineMigrations({ subTypeKey: 'type', subTypeMigrations: { - rectangle: defineMigrations({ - currentVersion: RectangleVersion.Initial, - firstVersion: RectangleVersion.Initial, - migrators: {}, - }), + rectangle: defineMigrations({}), }, }) const Shape = createRecordType>('shape', { - migrations: shapeMigrations, + migrations: shapeTypeMigrations, validator: { validate: (record) => { assert( @@ -100,7 +77,7 @@ interface Org extends BaseRecord<'org'> { } const Org = createRecordType('org', { - migrations: defineMigrations({ currentVersion: 0, firstVersion: 0, migrators: {} }), + migrations: defineMigrations({}), validator: { validate: (record) => { assert( @@ -119,6 +96,6 @@ export const testSchemaV0 = StoreSchema.create( org: Org, }, { - snapshotMigrations: defineMigrations({ currentVersion: 0, firstVersion: 0, migrators: {} }), + snapshotMigrations: defineMigrations({}), } ) diff --git a/packages/tlstore/src/lib/test/testSchema.v1.ts b/packages/tlstore/src/lib/test/testSchema.v1.ts index 024f83c7a..6128329de 100644 --- a/packages/tlstore/src/lib/test/testSchema.v1.ts +++ b/packages/tlstore/src/lib/test/testSchema.v1.ts @@ -6,7 +6,6 @@ import { StoreSchema } from '../StoreSchema' import { defineMigrations } from '../migrate' const UserVersion = { - Initial: 0, AddLocale: 1, AddPhoneNumber: 2, } as const @@ -20,7 +19,6 @@ interface User extends BaseRecord<'user'> { const userMigrations = defineMigrations({ currentVersion: UserVersion.AddPhoneNumber, - firstVersion: UserVersion.Initial, migrators: { [UserVersion.AddLocale]: { up: (record) => ({ @@ -69,18 +67,15 @@ const User = createRecordType('user', { })) const ShapeVersion = { - Initial: 0, AddRotation: 1, AddParent: 2, } as const const RectangleVersion = { - Initial: 0, AddOpacity: 1, } as const const OvalVersion = { - Initial: 0, AddBorderStyle: 1, } as const @@ -104,9 +99,8 @@ interface OvalProps { borderStyle: 'solid' | 'dashed' } -const shapeMigrations = defineMigrations({ +const shapeTypeMigrations = defineMigrations({ currentVersion: ShapeVersion.AddParent, - firstVersion: ShapeVersion.Initial, migrators: { [ShapeVersion.AddRotation]: { up: (record) => ({ @@ -135,7 +129,6 @@ const shapeMigrations = defineMigrations({ subTypeMigrations: { rectangle: defineMigrations({ currentVersion: RectangleVersion.AddOpacity, - firstVersion: RectangleVersion.Initial, migrators: { [RectangleVersion.AddOpacity]: { up: (record) => ({ @@ -157,7 +150,6 @@ const shapeMigrations = defineMigrations({ }), oval: defineMigrations({ currentVersion: OvalVersion.AddBorderStyle, - firstVersion: OvalVersion.Initial, migrators: { [OvalVersion.AddBorderStyle]: { up: (record) => ({ @@ -181,7 +173,7 @@ const shapeMigrations = defineMigrations({ }) const Shape = createRecordType>('shape', { - migrations: shapeMigrations, + migrations: shapeTypeMigrations, validator: { validate: (record) => { assert(record && typeof record === 'object') @@ -202,13 +194,11 @@ const Shape = createRecordType>('shape', { })) const StoreVersions = { - Initial: 0, RemoveOrg: 1, } const snapshotMigrations = defineMigrations({ currentVersion: StoreVersions.RemoveOrg, - firstVersion: StoreVersions.Initial, migrators: { [StoreVersions.RemoveOrg]: { up: (store: StoreSnapshot) => {