@tldraw/tlschema 4.6.0-internal.c7df3c92455a → 4.6.0-internal.e29318c66fb0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist-cjs/index.js CHANGED
@@ -187,7 +187,7 @@ var import_translations = require("./translations/translations");
187
187
  var import_b64Vecs = require("./misc/b64Vecs");
188
188
  (0, import_utils.registerTldrawLibraryVersion)(
189
189
  "@tldraw/tlschema",
190
- "4.6.0-internal.c7df3c92455a",
190
+ "4.6.0-internal.e29318c66fb0",
191
191
  "cjs"
192
192
  );
193
193
  //# sourceMappingURL=index.js.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/records/TLCustomRecord.ts"],
4
- "sourcesContent": ["import {\n\tMigrationSequence,\n\tRecordId,\n\tRecordScope,\n\tUnknownRecord,\n\tcreateMigrationSequence,\n\tcreateRecordType,\n} from '@tldraw/store'\nimport { assert, mapObjectMapValues, uniqueId } from '@tldraw/utils'\nimport { T } from '@tldraw/validate'\nimport { TLPropsMigrations } from '../recordsWithProps'\n\n/**\n * Configuration for a custom record type in the schema.\n *\n * Custom record types allow you to add entirely new data types to the tldraw store\n * that don't fit into the existing shape, binding, or asset categories. This is useful\n * for storing domain-specific data like comments, annotations, or application state\n * that needs to participate in persistence and synchronization.\n *\n * @example\n * ```ts\n * const commentRecordConfig: CustomRecordInfo = {\n * scope: 'document',\n * validator: T.object({\n * id: T.string,\n * typeName: T.literal('comment'),\n * text: T.string,\n * shapeId: T.string,\n * authorId: T.string,\n * createdAt: T.number,\n * }),\n * migrations: createRecordMigrationSequence({\n * sequenceId: 'com.myapp.comment',\n * recordType: 'comment',\n * sequence: [],\n * }),\n * }\n * ```\n *\n * @public\n */\nexport interface CustomRecordInfo {\n\t/**\n\t * The scope determines how records of this type are persisted and synchronized:\n\t * - **document**: Persisted and synced across all clients\n\t * - **session**: Local to current session, not synced\n\t * - **presence**: Ephemeral presence data, may be synced but not persisted\n\t */\n\tscope: RecordScope\n\n\t/**\n\t * Validator for the complete record structure.\n\t *\n\t * Should validate the entire record including `id` and `typeName` fields.\n\t * Use validators like T.object, T.string, etc.\n\t */\n\tvalidator: T.Validatable<any>\n\n\t/**\n\t * Optional migration sequence for handling schema evolution over time.\n\t *\n\t * Can be a full MigrationSequence or a simplified TLPropsMigrations format.\n\t * If not provided, an empty migration sequence will be created automatically.\n\t */\n\tmigrations?: MigrationSequence | TLPropsMigrations\n\n\t/**\n\t * Optional factory function that returns default property values for new records.\n\t *\n\t * Called when creating new records to provide initial values for any properties\n\t * not explicitly provided during creation.\n\t */\n\t// eslint-disable-next-line @typescript-eslint/method-signature-style\n\tcreateDefaultProperties?: () => Record<string, unknown>\n}\n\n/**\n * Creates a RecordType for a custom record based on its configuration.\n *\n * @param typeName - The unique type name for this record type\n * @param config - Configuration for the custom record type\n * @returns A RecordType instance that can be used to create and manage records\n *\n * @internal\n */\nexport function createCustomRecordType(typeName: string, config: CustomRecordInfo) {\n\treturn createRecordType<UnknownRecord>(typeName, {\n\t\tscope: config.scope,\n\t\tvalidator: config.validator,\n\t}).withDefaultProperties(config.createDefaultProperties ?? (() => ({})))\n}\n\n/**\n * Processes migrations for custom record types.\n *\n * Converts the migration configuration from CustomRecordInfo into proper\n * MigrationSequence objects that can be used by the store system.\n *\n * @param records - Record of type names to their configuration\n * @returns Array of migration sequences for the custom record types\n *\n * @internal\n */\nexport function processCustomRecordMigrations(\n\trecords: Record<string, CustomRecordInfo>\n): MigrationSequence[] {\n\tconst result: MigrationSequence[] = []\n\n\tfor (const [typeName, config] of Object.entries(records)) {\n\t\tconst sequenceId = `com.tldraw.${typeName}`\n\t\tconst { migrations } = config\n\n\t\tif (!migrations) {\n\t\t\t// Provide empty migration sequence to allow for future migrations\n\t\t\tresult.push(\n\t\t\t\tcreateMigrationSequence({\n\t\t\t\t\tsequenceId,\n\t\t\t\t\tretroactive: true,\n\t\t\t\t\tsequence: [],\n\t\t\t\t})\n\t\t\t)\n\t\t} else if ('sequenceId' in migrations) {\n\t\t\t// Full MigrationSequence provided\n\t\t\tassert(\n\t\t\t\tsequenceId === migrations.sequenceId,\n\t\t\t\t`sequenceId mismatch for ${typeName} custom record migrations. Expected '${sequenceId}', got '${migrations.sequenceId}'`\n\t\t\t)\n\t\t\tresult.push(migrations)\n\t\t} else if ('sequence' in migrations) {\n\t\t\t// TLPropsMigrations format - convert to full MigrationSequence\n\t\t\tresult.push(\n\t\t\t\tcreateMigrationSequence({\n\t\t\t\t\tsequenceId,\n\t\t\t\t\tretroactive: true,\n\t\t\t\t\tsequence: migrations.sequence.map((m) => {\n\t\t\t\t\t\tif (!('id' in m)) return m\n\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\tid: m.id,\n\t\t\t\t\t\t\tdependsOn: m.dependsOn,\n\t\t\t\t\t\t\tscope: 'record' as const,\n\t\t\t\t\t\t\tfilter: (r: UnknownRecord) => r.typeName === typeName,\n\t\t\t\t\t\t\tup: (record: any) => {\n\t\t\t\t\t\t\t\tconst result = m.up(record)\n\t\t\t\t\t\t\t\tif (result) return result\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tdown:\n\t\t\t\t\t\t\t\ttypeof m.down === 'function'\n\t\t\t\t\t\t\t\t\t? (record: any) => {\n\t\t\t\t\t\t\t\t\t\t\tconst result = (m.down as (r: any) => any)(record)\n\t\t\t\t\t\t\t\t\t\t\tif (result) return result\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t: undefined,\n\t\t\t\t\t\t}\n\t\t\t\t\t}),\n\t\t\t\t})\n\t\t\t)\n\t\t}\n\t}\n\n\treturn result\n}\n\n/**\n * Creates properly formatted migration IDs for custom record migrations.\n *\n * Generates standardized migration IDs following the convention:\n * `com.tldraw.{recordType}/{version}`\n *\n * @param recordType - The type name of the custom record\n * @param ids - Record mapping migration names to version numbers\n * @returns Record with the same keys but formatted migration ID values\n *\n * @example\n * ```ts\n * const commentVersions = createCustomRecordMigrationIds('comment', {\n * AddAuthorId: 1,\n * AddCreatedAt: 2,\n * RefactorReactions: 3\n * })\n * // Result: {\n * // AddAuthorId: 'com.tldraw.comment/1',\n * // AddCreatedAt: 'com.tldraw.comment/2',\n * // RefactorReactions: 'com.tldraw.comment/3'\n * // }\n * ```\n *\n * @public\n */\nexport function createCustomRecordMigrationIds<\n\tconst S extends string,\n\tconst T extends Record<string, number>,\n>(recordType: S, ids: T): { [k in keyof T]: `com.tldraw.${S}/${T[k]}` } {\n\treturn mapObjectMapValues(ids, (_k, v) => `com.tldraw.${recordType}/${v}`) as any\n}\n\n/**\n * Creates a migration sequence for custom record types.\n *\n * This is a pass-through function that maintains the same structure as the input.\n * It's used for consistency and to provide a clear API for defining custom record migrations.\n *\n * @param migrations - The migration sequence to create\n * @returns The same migration sequence (pass-through)\n *\n * @example\n * ```ts\n * const commentMigrations = createCustomRecordMigrationSequence({\n * sequence: [\n * {\n * id: 'com.myapp.comment/1',\n * up: (record) => ({ ...record, authorId: record.authorId ?? 'unknown' }),\n * down: ({ authorId, ...record }) => record\n * }\n * ]\n * })\n * ```\n *\n * @public\n */\nexport function createCustomRecordMigrationSequence(\n\tmigrations: TLPropsMigrations\n): TLPropsMigrations {\n\treturn migrations\n}\n\n/**\n * Creates a unique ID for a custom record type.\n *\n * @param typeName - The type name of the custom record\n * @param id - Optional custom ID suffix. If not provided, a unique ID will be generated\n * @returns A properly formatted record ID\n *\n * @example\n * ```ts\n * // Create with auto-generated ID\n * const commentId = createCustomRecordId('comment') // 'comment:abc123'\n *\n * // Create with custom ID\n * const customId = createCustomRecordId('comment', 'my-comment') // 'comment:my-comment'\n * ```\n *\n * @public\n */\nexport function createCustomRecordId<T extends string>(\n\ttypeName: T,\n\tid?: string\n): RecordId<UnknownRecord> & `${T}:${string}` {\n\treturn `${typeName}:${id ?? uniqueId()}` as RecordId<UnknownRecord> & `${T}:${string}`\n}\n\n/**\n * Type guard to check if a string is a valid ID for a specific custom record type.\n *\n * @param typeName - The type name to check against\n * @param id - The string to check\n * @returns True if the string is a valid ID for the specified record type\n *\n * @example\n * ```ts\n * const id = 'comment:abc123'\n * if (isCustomRecordId('comment', id)) {\n * // id is now typed as a comment record ID\n * const comment = store.get(id)\n * }\n * ```\n *\n * @public\n */\nexport function isCustomRecordId(typeName: string, id?: string): boolean {\n\tif (!id) return false\n\treturn id.startsWith(`${typeName}:`)\n}\n\n/**\n * Type guard to check if a record is of a specific custom type.\n *\n * @param typeName - The type name to check against\n * @param record - The record to check\n * @returns True if the record is of the specified type\n *\n * @example\n * ```ts\n * function handleRecord(record: TLRecord) {\n * if (isCustomRecord('comment', record)) {\n * // Handle comment record\n * console.log(`Comment: ${record.text}`)\n * }\n * }\n * ```\n *\n * @public\n */\nexport function isCustomRecord(typeName: string, record?: UnknownRecord): boolean {\n\tif (!record) return false\n\treturn record.typeName === typeName\n}\n"],
4
+ "sourcesContent": ["import {\n\tMigrationSequence,\n\tRecordId,\n\tRecordScope,\n\tUnknownRecord,\n\tcreateMigrationSequence,\n\tcreateRecordType,\n} from '@tldraw/store'\nimport { assert, mapObjectMapValues, uniqueId } from '@tldraw/utils'\nimport { T } from '@tldraw/validate'\nimport { TLPropsMigrations } from '../recordsWithProps'\n\n/**\n * Configuration for a custom record type in the schema.\n *\n * Custom record types allow you to add entirely new data types to the tldraw store\n * that don't fit into the existing shape, binding, or asset categories. This is useful\n * for storing domain-specific data like comments, annotations, or application state\n * that needs to participate in persistence and synchronization.\n *\n * @example\n * ```ts\n * const commentRecordConfig: CustomRecordInfo = {\n * scope: 'document',\n * validator: T.object({\n * id: T.string,\n * typeName: T.literal('comment'),\n * text: T.string,\n * shapeId: T.string,\n * authorId: T.string,\n * createdAt: T.number,\n * }),\n * migrations: createRecordMigrationSequence({\n * sequenceId: 'com.myapp.comment',\n * recordType: 'comment',\n * sequence: [],\n * }),\n * }\n * ```\n *\n * @public\n */\nexport interface CustomRecordInfo {\n\t/**\n\t * The scope determines how records of this type are persisted and synchronized:\n\t * - **document**: Persisted and synced across all clients\n\t * - **session**: Local to current session, not synced\n\t * - **presence**: Ephemeral presence data, may be synced but not persisted\n\t */\n\tscope: RecordScope\n\n\t/**\n\t * Validator for the complete record structure.\n\t *\n\t * Should validate the entire record including `id` and `typeName` fields.\n\t * Use validators like T.object, T.string, etc.\n\t */\n\tvalidator: T.Validatable<any>\n\n\t/**\n\t * Optional migration sequence for handling schema evolution over time.\n\t *\n\t * Can be a full MigrationSequence or a simplified TLPropsMigrations format.\n\t * If not provided, an empty migration sequence will be created automatically.\n\t */\n\tmigrations?: MigrationSequence | TLPropsMigrations\n\n\t/**\n\t * Optional factory function that returns default property values for new records.\n\t *\n\t * Called when creating new records to provide initial values for any properties\n\t * not explicitly provided during creation.\n\t */\n\t// eslint-disable-next-line tldraw/method-signature-style\n\tcreateDefaultProperties?: () => Record<string, unknown>\n}\n\n/**\n * Creates a RecordType for a custom record based on its configuration.\n *\n * @param typeName - The unique type name for this record type\n * @param config - Configuration for the custom record type\n * @returns A RecordType instance that can be used to create and manage records\n *\n * @internal\n */\nexport function createCustomRecordType(typeName: string, config: CustomRecordInfo) {\n\treturn createRecordType<UnknownRecord>(typeName, {\n\t\tscope: config.scope,\n\t\tvalidator: config.validator,\n\t}).withDefaultProperties(config.createDefaultProperties ?? (() => ({})))\n}\n\n/**\n * Processes migrations for custom record types.\n *\n * Converts the migration configuration from CustomRecordInfo into proper\n * MigrationSequence objects that can be used by the store system.\n *\n * @param records - Record of type names to their configuration\n * @returns Array of migration sequences for the custom record types\n *\n * @internal\n */\nexport function processCustomRecordMigrations(\n\trecords: Record<string, CustomRecordInfo>\n): MigrationSequence[] {\n\tconst result: MigrationSequence[] = []\n\n\tfor (const [typeName, config] of Object.entries(records)) {\n\t\tconst sequenceId = `com.tldraw.${typeName}`\n\t\tconst { migrations } = config\n\n\t\tif (!migrations) {\n\t\t\t// Provide empty migration sequence to allow for future migrations\n\t\t\tresult.push(\n\t\t\t\tcreateMigrationSequence({\n\t\t\t\t\tsequenceId,\n\t\t\t\t\tretroactive: true,\n\t\t\t\t\tsequence: [],\n\t\t\t\t})\n\t\t\t)\n\t\t} else if ('sequenceId' in migrations) {\n\t\t\t// Full MigrationSequence provided\n\t\t\tassert(\n\t\t\t\tsequenceId === migrations.sequenceId,\n\t\t\t\t`sequenceId mismatch for ${typeName} custom record migrations. Expected '${sequenceId}', got '${migrations.sequenceId}'`\n\t\t\t)\n\t\t\tresult.push(migrations)\n\t\t} else if ('sequence' in migrations) {\n\t\t\t// TLPropsMigrations format - convert to full MigrationSequence\n\t\t\tresult.push(\n\t\t\t\tcreateMigrationSequence({\n\t\t\t\t\tsequenceId,\n\t\t\t\t\tretroactive: true,\n\t\t\t\t\tsequence: migrations.sequence.map((m) => {\n\t\t\t\t\t\tif (!('id' in m)) return m\n\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\tid: m.id,\n\t\t\t\t\t\t\tdependsOn: m.dependsOn,\n\t\t\t\t\t\t\tscope: 'record' as const,\n\t\t\t\t\t\t\tfilter: (r: UnknownRecord) => r.typeName === typeName,\n\t\t\t\t\t\t\tup: (record: any) => {\n\t\t\t\t\t\t\t\tconst result = m.up(record)\n\t\t\t\t\t\t\t\tif (result) return result\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tdown:\n\t\t\t\t\t\t\t\ttypeof m.down === 'function'\n\t\t\t\t\t\t\t\t\t? (record: any) => {\n\t\t\t\t\t\t\t\t\t\t\tconst result = (m.down as (r: any) => any)(record)\n\t\t\t\t\t\t\t\t\t\t\tif (result) return result\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t: undefined,\n\t\t\t\t\t\t}\n\t\t\t\t\t}),\n\t\t\t\t})\n\t\t\t)\n\t\t}\n\t}\n\n\treturn result\n}\n\n/**\n * Creates properly formatted migration IDs for custom record migrations.\n *\n * Generates standardized migration IDs following the convention:\n * `com.tldraw.{recordType}/{version}`\n *\n * @param recordType - The type name of the custom record\n * @param ids - Record mapping migration names to version numbers\n * @returns Record with the same keys but formatted migration ID values\n *\n * @example\n * ```ts\n * const commentVersions = createCustomRecordMigrationIds('comment', {\n * AddAuthorId: 1,\n * AddCreatedAt: 2,\n * RefactorReactions: 3\n * })\n * // Result: {\n * // AddAuthorId: 'com.tldraw.comment/1',\n * // AddCreatedAt: 'com.tldraw.comment/2',\n * // RefactorReactions: 'com.tldraw.comment/3'\n * // }\n * ```\n *\n * @public\n */\nexport function createCustomRecordMigrationIds<\n\tconst S extends string,\n\tconst T extends Record<string, number>,\n>(recordType: S, ids: T): { [k in keyof T]: `com.tldraw.${S}/${T[k]}` } {\n\treturn mapObjectMapValues(ids, (_k, v) => `com.tldraw.${recordType}/${v}`) as any\n}\n\n/**\n * Creates a migration sequence for custom record types.\n *\n * This is a pass-through function that maintains the same structure as the input.\n * It's used for consistency and to provide a clear API for defining custom record migrations.\n *\n * @param migrations - The migration sequence to create\n * @returns The same migration sequence (pass-through)\n *\n * @example\n * ```ts\n * const commentMigrations = createCustomRecordMigrationSequence({\n * sequence: [\n * {\n * id: 'com.myapp.comment/1',\n * up: (record) => ({ ...record, authorId: record.authorId ?? 'unknown' }),\n * down: ({ authorId, ...record }) => record\n * }\n * ]\n * })\n * ```\n *\n * @public\n */\nexport function createCustomRecordMigrationSequence(\n\tmigrations: TLPropsMigrations\n): TLPropsMigrations {\n\treturn migrations\n}\n\n/**\n * Creates a unique ID for a custom record type.\n *\n * @param typeName - The type name of the custom record\n * @param id - Optional custom ID suffix. If not provided, a unique ID will be generated\n * @returns A properly formatted record ID\n *\n * @example\n * ```ts\n * // Create with auto-generated ID\n * const commentId = createCustomRecordId('comment') // 'comment:abc123'\n *\n * // Create with custom ID\n * const customId = createCustomRecordId('comment', 'my-comment') // 'comment:my-comment'\n * ```\n *\n * @public\n */\nexport function createCustomRecordId<T extends string>(\n\ttypeName: T,\n\tid?: string\n): RecordId<UnknownRecord> & `${T}:${string}` {\n\treturn `${typeName}:${id ?? uniqueId()}` as RecordId<UnknownRecord> & `${T}:${string}`\n}\n\n/**\n * Type guard to check if a string is a valid ID for a specific custom record type.\n *\n * @param typeName - The type name to check against\n * @param id - The string to check\n * @returns True if the string is a valid ID for the specified record type\n *\n * @example\n * ```ts\n * const id = 'comment:abc123'\n * if (isCustomRecordId('comment', id)) {\n * // id is now typed as a comment record ID\n * const comment = store.get(id)\n * }\n * ```\n *\n * @public\n */\nexport function isCustomRecordId(typeName: string, id?: string): boolean {\n\tif (!id) return false\n\treturn id.startsWith(`${typeName}:`)\n}\n\n/**\n * Type guard to check if a record is of a specific custom type.\n *\n * @param typeName - The type name to check against\n * @param record - The record to check\n * @returns True if the record is of the specified type\n *\n * @example\n * ```ts\n * function handleRecord(record: TLRecord) {\n * if (isCustomRecord('comment', record)) {\n * // Handle comment record\n * console.log(`Comment: ${record.text}`)\n * }\n * }\n * ```\n *\n * @public\n */\nexport function isCustomRecord(typeName: string, record?: UnknownRecord): boolean {\n\tif (!record) return false\n\treturn record.typeName === typeName\n}\n"],
5
5
  "mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,mBAOO;AACP,mBAAqD;AA8E9C,SAAS,uBAAuB,UAAkB,QAA0B;AAClF,aAAO,+BAAgC,UAAU;AAAA,IAChD,OAAO,OAAO;AAAA,IACd,WAAW,OAAO;AAAA,EACnB,CAAC,EAAE,sBAAsB,OAAO,4BAA4B,OAAO,CAAC,GAAG;AACxE;AAaO,SAAS,8BACf,SACsB;AACtB,QAAM,SAA8B,CAAC;AAErC,aAAW,CAAC,UAAU,MAAM,KAAK,OAAO,QAAQ,OAAO,GAAG;AACzD,UAAM,aAAa,cAAc,QAAQ;AACzC,UAAM,EAAE,WAAW,IAAI;AAEvB,QAAI,CAAC,YAAY;AAEhB,aAAO;AAAA,YACN,sCAAwB;AAAA,UACvB;AAAA,UACA,aAAa;AAAA,UACb,UAAU,CAAC;AAAA,QACZ,CAAC;AAAA,MACF;AAAA,IACD,WAAW,gBAAgB,YAAY;AAEtC;AAAA,QACC,eAAe,WAAW;AAAA,QAC1B,2BAA2B,QAAQ,wCAAwC,UAAU,WAAW,WAAW,UAAU;AAAA,MACtH;AACA,aAAO,KAAK,UAAU;AAAA,IACvB,WAAW,cAAc,YAAY;AAEpC,aAAO;AAAA,YACN,sCAAwB;AAAA,UACvB;AAAA,UACA,aAAa;AAAA,UACb,UAAU,WAAW,SAAS,IAAI,CAAC,MAAM;AACxC,gBAAI,EAAE,QAAQ,GAAI,QAAO;AACzB,mBAAO;AAAA,cACN,IAAI,EAAE;AAAA,cACN,WAAW,EAAE;AAAA,cACb,OAAO;AAAA,cACP,QAAQ,CAAC,MAAqB,EAAE,aAAa;AAAA,cAC7C,IAAI,CAAC,WAAgB;AACpB,sBAAMA,UAAS,EAAE,GAAG,MAAM;AAC1B,oBAAIA,QAAQ,QAAOA;AAAA,cACpB;AAAA,cACA,MACC,OAAO,EAAE,SAAS,aACf,CAAC,WAAgB;AACjB,sBAAMA,UAAU,EAAE,KAAyB,MAAM;AACjD,oBAAIA,QAAQ,QAAOA;AAAA,cACpB,IACC;AAAA,YACL;AAAA,UACD,CAAC;AAAA,QACF,CAAC;AAAA,MACF;AAAA,IACD;AAAA,EACD;AAEA,SAAO;AACR;AA4BO,SAAS,+BAGd,YAAe,KAAuD;AACvE,aAAO,iCAAmB,KAAK,CAAC,IAAI,MAAM,cAAc,UAAU,IAAI,CAAC,EAAE;AAC1E;AA0BO,SAAS,oCACf,YACoB;AACpB,SAAO;AACR;AAoBO,SAAS,qBACf,UACA,IAC6C;AAC7C,SAAO,GAAG,QAAQ,IAAI,UAAM,uBAAS,CAAC;AACvC;AAoBO,SAAS,iBAAiB,UAAkB,IAAsB;AACxE,MAAI,CAAC,GAAI,QAAO;AAChB,SAAO,GAAG,WAAW,GAAG,QAAQ,GAAG;AACpC;AAqBO,SAAS,eAAe,UAAkB,QAAiC;AACjF,MAAI,CAAC,OAAQ,QAAO;AACpB,SAAO,OAAO,aAAa;AAC5B;",
6
6
  "names": ["result"]
7
7
  }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/records/TLPageState.ts"],
4
- "sourcesContent": ["import {\n\tBaseRecord,\n\tcreateMigrationIds,\n\tcreateRecordMigrationSequence,\n\tcreateRecordType,\n\tRecordId,\n} from '@tldraw/store'\nimport { JsonObject } from '@tldraw/utils'\nimport { T } from '@tldraw/validate'\nimport { idValidator } from '../misc/id-validator'\nimport { shapeIdValidator } from '../shapes/TLBaseShape'\nimport { pageIdValidator, TLPage } from './TLPage'\nimport { TLShapeId } from './TLShape'\n\n/**\n * State that is unique to a particular page within a particular browser tab.\n * This record tracks all page-specific interaction state including selected shapes,\n * editing state, hover state, and other transient UI state that is tied to\n * both a specific page and a specific browser session.\n *\n * Each combination of page and browser tab has its own TLInstancePageState record.\n *\n * @example\n * ```ts\n * const pageState: TLInstancePageState = {\n * id: 'instance_page_state:page1',\n * typeName: 'instance_page_state',\n * pageId: 'page:page1',\n * selectedShapeIds: ['shape:rect1', 'shape:circle2'],\n * hoveredShapeId: 'shape:text3',\n * editingShapeId: null,\n * focusedGroupId: null\n * }\n * ```\n *\n * @public\n */\nexport interface TLInstancePageState\n\textends BaseRecord<'instance_page_state', TLInstancePageStateId> {\n\tpageId: RecordId<TLPage>\n\tselectedShapeIds: TLShapeId[]\n\thintingShapeIds: TLShapeId[]\n\terasingShapeIds: TLShapeId[]\n\thoveredShapeId: TLShapeId | null\n\teditingShapeId: TLShapeId | null\n\tcroppingShapeId: TLShapeId | null\n\tfocusedGroupId: TLShapeId | null\n\tmeta: JsonObject\n}\n\n/**\n * Runtime validator for TLInstancePageState records. Validates the structure\n * and types of all instance page state properties to ensure data integrity.\n *\n * @example\n * ```ts\n * const pageState = {\n * id: 'instance_page_state:page1',\n * typeName: 'instance_page_state',\n * pageId: 'page:page1',\n * selectedShapeIds: ['shape:rect1'],\n * // ... other properties\n * }\n * const isValid = instancePageStateValidator.isValid(pageState) // true\n * ```\n *\n * @public\n */\nexport const instancePageStateValidator: T.Validator<TLInstancePageState> = T.model(\n\t'instance_page_state',\n\tT.object({\n\t\ttypeName: T.literal('instance_page_state'),\n\t\tid: idValidator<TLInstancePageStateId>('instance_page_state'),\n\t\tpageId: pageIdValidator,\n\t\tselectedShapeIds: T.arrayOf(shapeIdValidator),\n\t\thintingShapeIds: T.arrayOf(shapeIdValidator),\n\t\terasingShapeIds: T.arrayOf(shapeIdValidator),\n\t\thoveredShapeId: shapeIdValidator.nullable(),\n\t\teditingShapeId: shapeIdValidator.nullable(),\n\t\tcroppingShapeId: shapeIdValidator.nullable(),\n\t\tfocusedGroupId: shapeIdValidator.nullable(),\n\t\tmeta: T.jsonValue as T.ObjectValidator<JsonObject>,\n\t})\n)\n\n/**\n * Migration version identifiers for TLInstancePageState records. Each version\n * represents a schema change that requires data transformation when loading\n * older documents.\n *\n * @public\n */\nexport const instancePageStateVersions = createMigrationIds('com.tldraw.instance_page_state', {\n\tAddCroppingId: 1,\n\tRemoveInstanceIdAndCameraId: 2,\n\tAddMeta: 3,\n\tRenameProperties: 4,\n\tRenamePropertiesAgain: 5,\n} as const)\n\n/**\n * Migration sequence for TLInstancePageState records. Defines how to transform\n * instance page state records between different schema versions, ensuring data\n * compatibility when loading documents created with different versions.\n *\n * @example\n * ```ts\n * // Migrations are applied automatically when loading documents\n * const migrated = instancePageStateMigrations.migrate(oldState, targetVersion)\n * ```\n *\n * @public\n */\nexport const instancePageStateMigrations = createRecordMigrationSequence({\n\tsequenceId: 'com.tldraw.instance_page_state',\n\trecordType: 'instance_page_state',\n\tsequence: [\n\t\t{\n\t\t\tid: instancePageStateVersions.AddCroppingId,\n\t\t\tup(instance: any) {\n\t\t\t\tinstance.croppingShapeId = null\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tid: instancePageStateVersions.RemoveInstanceIdAndCameraId,\n\t\t\tup(instance: any) {\n\t\t\t\tdelete instance.instanceId\n\t\t\t\tdelete instance.cameraId\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tid: instancePageStateVersions.AddMeta,\n\t\t\tup: (record: any) => {\n\t\t\t\trecord.meta = {}\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tid: instancePageStateVersions.RenameProperties,\n\t\t\t// this migration is cursed: it was written wrong and doesn't do anything.\n\t\t\t// rather than replace it, I've added another migration below that fixes it.\n\t\t\tup: (_record) => {\n\t\t\t\t// noop\n\t\t\t},\n\t\t\tdown: (_record) => {\n\t\t\t\t// noop\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tid: instancePageStateVersions.RenamePropertiesAgain,\n\t\t\tup: (record: any) => {\n\t\t\t\trecord.selectedShapeIds = record.selectedIds\n\t\t\t\tdelete record.selectedIds\n\t\t\t\trecord.hintingShapeIds = record.hintingIds\n\t\t\t\tdelete record.hintingIds\n\t\t\t\trecord.erasingShapeIds = record.erasingIds\n\t\t\t\tdelete record.erasingIds\n\t\t\t\trecord.hoveredShapeId = record.hoveredId\n\t\t\t\tdelete record.hoveredId\n\t\t\t\trecord.editingShapeId = record.editingId\n\t\t\t\tdelete record.editingId\n\t\t\t\trecord.croppingShapeId = record.croppingShapeId ?? record.croppingId ?? null\n\t\t\t\tdelete record.croppingId\n\t\t\t\trecord.focusedGroupId = record.focusLayerId\n\t\t\t\tdelete record.focusLayerId\n\t\t\t},\n\t\t\tdown: (record: any) => {\n\t\t\t\trecord.selectedIds = record.selectedShapeIds\n\t\t\t\tdelete record.selectedShapeIds\n\t\t\t\trecord.hintingIds = record.hintingShapeIds\n\t\t\t\tdelete record.hintingShapeIds\n\t\t\t\trecord.erasingIds = record.erasingShapeIds\n\t\t\t\tdelete record.erasingShapeIds\n\t\t\t\trecord.hoveredId = record.hoveredShapeId\n\t\t\t\tdelete record.hoveredShapeId\n\t\t\t\trecord.editingId = record.editingShapeId\n\t\t\t\tdelete record.editingShapeId\n\t\t\t\trecord.croppingId = record.croppingShapeId\n\t\t\t\tdelete record.croppingShapeId\n\t\t\t\trecord.focusLayerId = record.focusedGroupId\n\t\t\t\tdelete record.focusedGroupId\n\t\t\t},\n\t\t},\n\t],\n})\n\n/**\n * The RecordType definition for TLInstancePageState records. Defines validation,\n * scope, and default properties for instance page state records.\n *\n * Instance page states are scoped to the session level, meaning they are\n * specific to a browser tab and don't persist across sessions or sync\n * in collaborative environments.\n *\n * @example\n * ```ts\n * const pageState = InstancePageStateRecordType.create({\n * id: 'instance_page_state:page1',\n * pageId: 'page:page1',\n * selectedShapeIds: ['shape:rect1']\n * })\n * ```\n *\n * @public\n */\nexport const InstancePageStateRecordType = createRecordType<TLInstancePageState>(\n\t'instance_page_state',\n\t{\n\t\tvalidator: instancePageStateValidator,\n\t\tscope: 'session',\n\t\tephemeralKeys: {\n\t\t\tpageId: false,\n\t\t\tselectedShapeIds: false,\n\t\t\teditingShapeId: false,\n\t\t\tcroppingShapeId: false,\n\t\t\tmeta: false,\n\n\t\t\thintingShapeIds: true,\n\t\t\terasingShapeIds: true,\n\t\t\thoveredShapeId: true,\n\t\t\tfocusedGroupId: true,\n\t\t},\n\t}\n).withDefaultProperties(\n\t(): Omit<TLInstancePageState, 'id' | 'typeName' | 'pageId'> => ({\n\t\teditingShapeId: null,\n\t\tcroppingShapeId: null,\n\t\tselectedShapeIds: [],\n\t\thoveredShapeId: null,\n\t\terasingShapeIds: [],\n\t\thintingShapeIds: [],\n\t\tfocusedGroupId: null,\n\t\tmeta: {},\n\t})\n)\n\n/**\n * A unique identifier for TLInstancePageState records.\n *\n * Instance page state IDs follow the format 'instance_page_state:' followed\n * by a unique identifier, typically related to the page ID.\n *\n * @example\n * ```ts\n * const stateId: TLInstancePageStateId = 'instance_page_state:page1'\n * ```\n *\n * @public\n */\nexport type TLInstancePageStateId = RecordId<TLInstancePageState>\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import {\n\tBaseRecord,\n\tcreateMigrationIds,\n\tcreateRecordMigrationSequence,\n\tcreateRecordType,\n\tRecordId,\n} from '@tldraw/store'\nimport { JsonObject } from '@tldraw/utils'\nimport { T } from '@tldraw/validate'\nimport { idValidator } from '../misc/id-validator'\nimport { shapeIdValidator } from '../shapes/TLBaseShape'\nimport { pageIdValidator, TLPage } from './TLPage'\nimport { TLShapeId } from './TLShape'\n\n/**\n * State that is unique to a particular page within a particular browser tab.\n * This record tracks all page-specific interaction state including selected shapes,\n * editing state, hover state, and other transient UI state that is tied to\n * both a specific page and a specific browser session.\n *\n * Each combination of page and browser tab has its own TLInstancePageState record.\n *\n * @example\n * ```ts\n * const pageState: TLInstancePageState = {\n * id: 'instance_page_state:page1',\n * typeName: 'instance_page_state',\n * pageId: 'page:page1',\n * selectedShapeIds: ['shape:rect1', 'shape:circle2'],\n * hoveredShapeId: 'shape:text3',\n * editingShapeId: null,\n * focusedGroupId: null\n * }\n * ```\n *\n * @public\n */\nexport interface TLInstancePageState extends BaseRecord<\n\t'instance_page_state',\n\tTLInstancePageStateId\n> {\n\tpageId: RecordId<TLPage>\n\tselectedShapeIds: TLShapeId[]\n\thintingShapeIds: TLShapeId[]\n\terasingShapeIds: TLShapeId[]\n\thoveredShapeId: TLShapeId | null\n\teditingShapeId: TLShapeId | null\n\tcroppingShapeId: TLShapeId | null\n\tfocusedGroupId: TLShapeId | null\n\tmeta: JsonObject\n}\n\n/**\n * Runtime validator for TLInstancePageState records. Validates the structure\n * and types of all instance page state properties to ensure data integrity.\n *\n * @example\n * ```ts\n * const pageState = {\n * id: 'instance_page_state:page1',\n * typeName: 'instance_page_state',\n * pageId: 'page:page1',\n * selectedShapeIds: ['shape:rect1'],\n * // ... other properties\n * }\n * const isValid = instancePageStateValidator.isValid(pageState) // true\n * ```\n *\n * @public\n */\nexport const instancePageStateValidator: T.Validator<TLInstancePageState> = T.model(\n\t'instance_page_state',\n\tT.object({\n\t\ttypeName: T.literal('instance_page_state'),\n\t\tid: idValidator<TLInstancePageStateId>('instance_page_state'),\n\t\tpageId: pageIdValidator,\n\t\tselectedShapeIds: T.arrayOf(shapeIdValidator),\n\t\thintingShapeIds: T.arrayOf(shapeIdValidator),\n\t\terasingShapeIds: T.arrayOf(shapeIdValidator),\n\t\thoveredShapeId: shapeIdValidator.nullable(),\n\t\teditingShapeId: shapeIdValidator.nullable(),\n\t\tcroppingShapeId: shapeIdValidator.nullable(),\n\t\tfocusedGroupId: shapeIdValidator.nullable(),\n\t\tmeta: T.jsonValue as T.ObjectValidator<JsonObject>,\n\t})\n)\n\n/**\n * Migration version identifiers for TLInstancePageState records. Each version\n * represents a schema change that requires data transformation when loading\n * older documents.\n *\n * @public\n */\nexport const instancePageStateVersions = createMigrationIds('com.tldraw.instance_page_state', {\n\tAddCroppingId: 1,\n\tRemoveInstanceIdAndCameraId: 2,\n\tAddMeta: 3,\n\tRenameProperties: 4,\n\tRenamePropertiesAgain: 5,\n} as const)\n\n/**\n * Migration sequence for TLInstancePageState records. Defines how to transform\n * instance page state records between different schema versions, ensuring data\n * compatibility when loading documents created with different versions.\n *\n * @example\n * ```ts\n * // Migrations are applied automatically when loading documents\n * const migrated = instancePageStateMigrations.migrate(oldState, targetVersion)\n * ```\n *\n * @public\n */\nexport const instancePageStateMigrations = createRecordMigrationSequence({\n\tsequenceId: 'com.tldraw.instance_page_state',\n\trecordType: 'instance_page_state',\n\tsequence: [\n\t\t{\n\t\t\tid: instancePageStateVersions.AddCroppingId,\n\t\t\tup(instance: any) {\n\t\t\t\tinstance.croppingShapeId = null\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tid: instancePageStateVersions.RemoveInstanceIdAndCameraId,\n\t\t\tup(instance: any) {\n\t\t\t\tdelete instance.instanceId\n\t\t\t\tdelete instance.cameraId\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tid: instancePageStateVersions.AddMeta,\n\t\t\tup: (record: any) => {\n\t\t\t\trecord.meta = {}\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tid: instancePageStateVersions.RenameProperties,\n\t\t\t// this migration is cursed: it was written wrong and doesn't do anything.\n\t\t\t// rather than replace it, I've added another migration below that fixes it.\n\t\t\tup: (_record) => {\n\t\t\t\t// noop\n\t\t\t},\n\t\t\tdown: (_record) => {\n\t\t\t\t// noop\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tid: instancePageStateVersions.RenamePropertiesAgain,\n\t\t\tup: (record: any) => {\n\t\t\t\trecord.selectedShapeIds = record.selectedIds\n\t\t\t\tdelete record.selectedIds\n\t\t\t\trecord.hintingShapeIds = record.hintingIds\n\t\t\t\tdelete record.hintingIds\n\t\t\t\trecord.erasingShapeIds = record.erasingIds\n\t\t\t\tdelete record.erasingIds\n\t\t\t\trecord.hoveredShapeId = record.hoveredId\n\t\t\t\tdelete record.hoveredId\n\t\t\t\trecord.editingShapeId = record.editingId\n\t\t\t\tdelete record.editingId\n\t\t\t\trecord.croppingShapeId = record.croppingShapeId ?? record.croppingId ?? null\n\t\t\t\tdelete record.croppingId\n\t\t\t\trecord.focusedGroupId = record.focusLayerId\n\t\t\t\tdelete record.focusLayerId\n\t\t\t},\n\t\t\tdown: (record: any) => {\n\t\t\t\trecord.selectedIds = record.selectedShapeIds\n\t\t\t\tdelete record.selectedShapeIds\n\t\t\t\trecord.hintingIds = record.hintingShapeIds\n\t\t\t\tdelete record.hintingShapeIds\n\t\t\t\trecord.erasingIds = record.erasingShapeIds\n\t\t\t\tdelete record.erasingShapeIds\n\t\t\t\trecord.hoveredId = record.hoveredShapeId\n\t\t\t\tdelete record.hoveredShapeId\n\t\t\t\trecord.editingId = record.editingShapeId\n\t\t\t\tdelete record.editingShapeId\n\t\t\t\trecord.croppingId = record.croppingShapeId\n\t\t\t\tdelete record.croppingShapeId\n\t\t\t\trecord.focusLayerId = record.focusedGroupId\n\t\t\t\tdelete record.focusedGroupId\n\t\t\t},\n\t\t},\n\t],\n})\n\n/**\n * The RecordType definition for TLInstancePageState records. Defines validation,\n * scope, and default properties for instance page state records.\n *\n * Instance page states are scoped to the session level, meaning they are\n * specific to a browser tab and don't persist across sessions or sync\n * in collaborative environments.\n *\n * @example\n * ```ts\n * const pageState = InstancePageStateRecordType.create({\n * id: 'instance_page_state:page1',\n * pageId: 'page:page1',\n * selectedShapeIds: ['shape:rect1']\n * })\n * ```\n *\n * @public\n */\nexport const InstancePageStateRecordType = createRecordType<TLInstancePageState>(\n\t'instance_page_state',\n\t{\n\t\tvalidator: instancePageStateValidator,\n\t\tscope: 'session',\n\t\tephemeralKeys: {\n\t\t\tpageId: false,\n\t\t\tselectedShapeIds: false,\n\t\t\teditingShapeId: false,\n\t\t\tcroppingShapeId: false,\n\t\t\tmeta: false,\n\n\t\t\thintingShapeIds: true,\n\t\t\terasingShapeIds: true,\n\t\t\thoveredShapeId: true,\n\t\t\tfocusedGroupId: true,\n\t\t},\n\t}\n).withDefaultProperties(\n\t(): Omit<TLInstancePageState, 'id' | 'typeName' | 'pageId'> => ({\n\t\teditingShapeId: null,\n\t\tcroppingShapeId: null,\n\t\tselectedShapeIds: [],\n\t\thoveredShapeId: null,\n\t\terasingShapeIds: [],\n\t\thintingShapeIds: [],\n\t\tfocusedGroupId: null,\n\t\tmeta: {},\n\t})\n)\n\n/**\n * A unique identifier for TLInstancePageState records.\n *\n * Instance page state IDs follow the format 'instance_page_state:' followed\n * by a unique identifier, typically related to the page ID.\n *\n * @example\n * ```ts\n * const stateId: TLInstancePageStateId = 'instance_page_state:page1'\n * ```\n *\n * @public\n */\nexport type TLInstancePageStateId = RecordId<TLInstancePageState>\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../src/recordsWithProps.ts"],
4
- "sourcesContent": ["import {\n\tMigration,\n\tMigrationId,\n\tMigrationSequence,\n\tRecordType,\n\tStandaloneDependsOn,\n\tUnknownRecord,\n\tcreateMigrationSequence,\n} from '@tldraw/store'\nimport { MakeUndefinedOptional, assert } from '@tldraw/utils'\nimport { T } from '@tldraw/validate'\nimport { SchemaPropsInfo } from './createTLSchema'\n\n/**\n * Maps a record's property types to their corresponding validators.\n *\n * This utility type takes a record type with a `props` object and creates\n * a mapping where each property key maps to a validator for that property's type.\n * This is used to define validation schemas for record properties.\n *\n * @example\n * ```ts\n * interface MyShape extends TLBaseShape<'custom', { width: number; color: string }> {}\n *\n * // Define validators for the shape properties\n * const myShapeProps: RecordProps<MyShape> = {\n * width: T.number,\n * color: T.string\n * }\n * ```\n *\n * @public\n */\nexport type RecordProps<R extends UnknownRecord & { props: object }> = {\n\t[K in keyof R['props']]: T.Validatable<R['props'][K]>\n}\n\n/**\n * Extracts the TypeScript types from a record properties configuration.\n *\n * Takes a configuration object where values are validators and returns the\n * corresponding TypeScript types, with undefined values made optional.\n *\n * @example\n * ```ts\n * const shapePropsConfig = {\n * width: T.number,\n * height: T.number,\n * color: T.optional(T.string)\n * }\n *\n * type ShapeProps = RecordPropsType<typeof shapePropsConfig>\n * // Result: { width: number; height: number; color?: string }\n * ```\n *\n * @public\n */\nexport type RecordPropsType<Config extends Record<string, T.Validatable<any>>> =\n\tMakeUndefinedOptional<{\n\t\t[K in keyof Config]: T.TypeOf<Config[K]>\n\t}>\n\n/**\n * A migration definition for shape or record properties.\n *\n * Defines how to transform record properties when migrating between schema versions.\n * Each migration has an `up` function to upgrade data and an optional `down` function\n * to downgrade data if needed.\n *\n * @example\n * ```ts\n * const addColorMigration: TLPropsMigration = {\n * id: 'com.myapp.shape.custom/1.0.0',\n * up: (props) => {\n * // Add a default color property\n * return { ...props, color: 'black' }\n * },\n * down: (props) => {\n * // Remove the color property\n * const { color, ...rest } = props\n * return rest\n * }\n * }\n * ```\n *\n * @public\n */\nexport interface TLPropsMigration {\n\treadonly id: MigrationId\n\treadonly dependsOn?: MigrationId[]\n\t// eslint-disable-next-line @typescript-eslint/method-signature-style\n\treadonly up: (props: any) => any\n\t/**\n\t * If a down migration was deployed more than a couple of months ago it should be safe to retire it.\n\t * We only really need them to smooth over the transition between versions, and some folks do keep\n\t * browser tabs open for months without refreshing, but at a certain point that kind of behavior is\n\t * on them. Plus anyway recently chrome has started to actually kill tabs that are open for too long\n\t * rather than just suspending them, so if other browsers follow suit maybe it's less of a concern.\n\t *\n\t * @public\n\t */\n\treadonly down?: 'none' | 'retired' | ((props: any) => any)\n}\n\n/**\n * A sequence of property migrations for a record type.\n *\n * Contains an ordered array of migrations that should be applied to transform\n * record properties from one version to another. Migrations can include both\n * property-specific migrations and standalone dependency declarations.\n *\n * @example\n * ```ts\n * const myShapeMigrations: TLPropsMigrations = {\n * sequence: [\n * {\n * id: 'com.myapp.shape.custom/1.0.0',\n * up: (props) => ({ ...props, version: 1 })\n * },\n * {\n * id: 'com.myapp.shape.custom/2.0.0',\n * up: (props) => ({ ...props, newFeature: true })\n * }\n * ]\n * }\n * ```\n *\n * @public\n */\nexport interface TLPropsMigrations {\n\treadonly sequence: Array<StandaloneDependsOn | TLPropsMigration>\n}\n\n/**\n * Processes property migrations for all record types in a schema.\n *\n * Takes a collection of record configurations and converts their migrations\n * into proper migration sequences that can be used by the store system.\n * Handles different migration formats including legacy migrations.\n *\n * @param typeName - The base type name for the records (e.g., 'shape', 'binding')\n * @param records - Record of type names to their schema configuration\n * @returns Array of processed migration sequences\n *\n * @example\n * ```ts\n * const shapeRecords = {\n * geo: { props: geoProps, migrations: geoMigrations },\n * arrow: { props: arrowProps, migrations: arrowMigrations }\n * }\n *\n * const sequences = processPropsMigrations('shape', shapeRecords)\n * ```\n *\n * @internal\n */\nexport function processPropsMigrations<R extends UnknownRecord & { type: string; props: object }>(\n\ttypeName: R['typeName'],\n\trecords: Record<string, SchemaPropsInfo>\n) {\n\tconst result: MigrationSequence[] = []\n\n\tfor (const [subType, { migrations }] of Object.entries(records)) {\n\t\tconst sequenceId = `com.tldraw.${typeName}.${subType}`\n\t\tif (!migrations) {\n\t\t\t// provide empty migrations sequence to allow for future migrations\n\t\t\tresult.push(\n\t\t\t\tcreateMigrationSequence({\n\t\t\t\t\tsequenceId,\n\t\t\t\t\tretroactive: true,\n\t\t\t\t\tsequence: [],\n\t\t\t\t})\n\t\t\t)\n\t\t} else if ('sequenceId' in migrations) {\n\t\t\tassert(\n\t\t\t\tsequenceId === migrations.sequenceId,\n\t\t\t\t`sequenceId mismatch for ${subType} ${RecordType} migrations. Expected '${sequenceId}', got '${migrations.sequenceId}'`\n\t\t\t)\n\t\t\tresult.push(migrations)\n\t\t} else if ('sequence' in migrations) {\n\t\t\tresult.push(\n\t\t\t\tcreateMigrationSequence({\n\t\t\t\t\tsequenceId,\n\t\t\t\t\tretroactive: true,\n\t\t\t\t\tsequence: migrations.sequence.map((m) =>\n\t\t\t\t\t\t'id' in m ? createPropsMigration(typeName, subType, m) : m\n\t\t\t\t\t),\n\t\t\t\t})\n\t\t\t)\n\t\t} else {\n\t\t\t// legacy migrations, will be removed in the future\n\t\t\tresult.push(\n\t\t\t\tcreateMigrationSequence({\n\t\t\t\t\tsequenceId,\n\t\t\t\t\tretroactive: true,\n\t\t\t\t\tsequence: Object.keys(migrations.migrators)\n\t\t\t\t\t\t.map((k) => Number(k))\n\t\t\t\t\t\t.sort((a: number, b: number) => a - b)\n\t\t\t\t\t\t.map(\n\t\t\t\t\t\t\t(version): Migration => ({\n\t\t\t\t\t\t\t\tid: `${sequenceId}/${version}`,\n\t\t\t\t\t\t\t\tscope: 'record',\n\t\t\t\t\t\t\t\tfilter: (r) => r.typeName === typeName && (r as R).type === subType,\n\t\t\t\t\t\t\t\tup: (record: any) => {\n\t\t\t\t\t\t\t\t\tconst result = migrations.migrators[version].up(record)\n\t\t\t\t\t\t\t\t\tif (result) {\n\t\t\t\t\t\t\t\t\t\treturn result\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\tdown: (record: any) => {\n\t\t\t\t\t\t\t\t\tconst result = migrations.migrators[version].down(record)\n\t\t\t\t\t\t\t\t\tif (result) {\n\t\t\t\t\t\t\t\t\t\treturn result\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t})\n\t\t\t\t\t\t),\n\t\t\t\t})\n\t\t\t)\n\t\t}\n\t}\n\n\treturn result\n}\n\n/**\n * Creates a store migration from a props migration definition.\n *\n * Converts a high-level property migration into a low-level store migration\n * that can be applied to records. The resulting migration will only affect\n * records of the specified type and subtype.\n *\n * @param typeName - The base type name (e.g., 'shape', 'binding')\n * @param subType - The specific subtype (e.g., 'geo', 'arrow')\n * @param m - The property migration definition\n * @returns A store migration that applies the property transformation\n *\n * @example\n * ```ts\n * const propsMigration: TLPropsMigration = {\n * id: 'com.myapp.shape.custom/1.0.0',\n * up: (props) => ({ ...props, color: 'blue' })\n * }\n *\n * const storeMigration = createPropsMigration('shape', 'custom', propsMigration)\n * ```\n *\n * @internal\n */\nexport function createPropsMigration<R extends UnknownRecord & { type: string; props: object }>(\n\ttypeName: R['typeName'],\n\tsubType: R['type'],\n\tm: TLPropsMigration\n): Migration {\n\treturn {\n\t\tid: m.id,\n\t\tdependsOn: m.dependsOn,\n\t\tscope: 'record',\n\t\tfilter: (r) => r.typeName === typeName && (r as R).type === subType,\n\t\tup: (record: any) => {\n\t\t\tconst result = m.up(record.props)\n\t\t\tif (result) {\n\t\t\t\trecord.props = result\n\t\t\t}\n\t\t},\n\t\tdown:\n\t\t\ttypeof m.down === 'function'\n\t\t\t\t? (record: any) => {\n\t\t\t\t\t\tconst result = (m.down as (props: any) => any)(record.props)\n\t\t\t\t\t\tif (result) {\n\t\t\t\t\t\t\trecord.props = result\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t: undefined,\n\t}\n}\n"],
4
+ "sourcesContent": ["import {\n\tMigration,\n\tMigrationId,\n\tMigrationSequence,\n\tRecordType,\n\tStandaloneDependsOn,\n\tUnknownRecord,\n\tcreateMigrationSequence,\n} from '@tldraw/store'\nimport { MakeUndefinedOptional, assert } from '@tldraw/utils'\nimport { T } from '@tldraw/validate'\nimport { SchemaPropsInfo } from './createTLSchema'\n\n/**\n * Maps a record's property types to their corresponding validators.\n *\n * This utility type takes a record type with a `props` object and creates\n * a mapping where each property key maps to a validator for that property's type.\n * This is used to define validation schemas for record properties.\n *\n * @example\n * ```ts\n * interface MyShape extends TLBaseShape<'custom', { width: number; color: string }> {}\n *\n * // Define validators for the shape properties\n * const myShapeProps: RecordProps<MyShape> = {\n * width: T.number,\n * color: T.string\n * }\n * ```\n *\n * @public\n */\nexport type RecordProps<R extends UnknownRecord & { props: object }> = {\n\t[K in keyof R['props']]: T.Validatable<R['props'][K]>\n}\n\n/**\n * Extracts the TypeScript types from a record properties configuration.\n *\n * Takes a configuration object where values are validators and returns the\n * corresponding TypeScript types, with undefined values made optional.\n *\n * @example\n * ```ts\n * const shapePropsConfig = {\n * width: T.number,\n * height: T.number,\n * color: T.optional(T.string)\n * }\n *\n * type ShapeProps = RecordPropsType<typeof shapePropsConfig>\n * // Result: { width: number; height: number; color?: string }\n * ```\n *\n * @public\n */\nexport type RecordPropsType<Config extends Record<string, T.Validatable<any>>> =\n\tMakeUndefinedOptional<{\n\t\t[K in keyof Config]: T.TypeOf<Config[K]>\n\t}>\n\n/**\n * A migration definition for shape or record properties.\n *\n * Defines how to transform record properties when migrating between schema versions.\n * Each migration has an `up` function to upgrade data and an optional `down` function\n * to downgrade data if needed.\n *\n * @example\n * ```ts\n * const addColorMigration: TLPropsMigration = {\n * id: 'com.myapp.shape.custom/1.0.0',\n * up: (props) => {\n * // Add a default color property\n * return { ...props, color: 'black' }\n * },\n * down: (props) => {\n * // Remove the color property\n * const { color, ...rest } = props\n * return rest\n * }\n * }\n * ```\n *\n * @public\n */\nexport interface TLPropsMigration {\n\treadonly id: MigrationId\n\treadonly dependsOn?: MigrationId[]\n\t// eslint-disable-next-line tldraw/method-signature-style\n\treadonly up: (props: any) => any\n\t/**\n\t * If a down migration was deployed more than a couple of months ago it should be safe to retire it.\n\t * We only really need them to smooth over the transition between versions, and some folks do keep\n\t * browser tabs open for months without refreshing, but at a certain point that kind of behavior is\n\t * on them. Plus anyway recently chrome has started to actually kill tabs that are open for too long\n\t * rather than just suspending them, so if other browsers follow suit maybe it's less of a concern.\n\t *\n\t * @public\n\t */\n\treadonly down?: 'none' | 'retired' | ((props: any) => any)\n}\n\n/**\n * A sequence of property migrations for a record type.\n *\n * Contains an ordered array of migrations that should be applied to transform\n * record properties from one version to another. Migrations can include both\n * property-specific migrations and standalone dependency declarations.\n *\n * @example\n * ```ts\n * const myShapeMigrations: TLPropsMigrations = {\n * sequence: [\n * {\n * id: 'com.myapp.shape.custom/1.0.0',\n * up: (props) => ({ ...props, version: 1 })\n * },\n * {\n * id: 'com.myapp.shape.custom/2.0.0',\n * up: (props) => ({ ...props, newFeature: true })\n * }\n * ]\n * }\n * ```\n *\n * @public\n */\nexport interface TLPropsMigrations {\n\treadonly sequence: Array<StandaloneDependsOn | TLPropsMigration>\n}\n\n/**\n * Processes property migrations for all record types in a schema.\n *\n * Takes a collection of record configurations and converts their migrations\n * into proper migration sequences that can be used by the store system.\n * Handles different migration formats including legacy migrations.\n *\n * @param typeName - The base type name for the records (e.g., 'shape', 'binding')\n * @param records - Record of type names to their schema configuration\n * @returns Array of processed migration sequences\n *\n * @example\n * ```ts\n * const shapeRecords = {\n * geo: { props: geoProps, migrations: geoMigrations },\n * arrow: { props: arrowProps, migrations: arrowMigrations }\n * }\n *\n * const sequences = processPropsMigrations('shape', shapeRecords)\n * ```\n *\n * @internal\n */\nexport function processPropsMigrations<R extends UnknownRecord & { type: string; props: object }>(\n\ttypeName: R['typeName'],\n\trecords: Record<string, SchemaPropsInfo>\n) {\n\tconst result: MigrationSequence[] = []\n\n\tfor (const [subType, { migrations }] of Object.entries(records)) {\n\t\tconst sequenceId = `com.tldraw.${typeName}.${subType}`\n\t\tif (!migrations) {\n\t\t\t// provide empty migrations sequence to allow for future migrations\n\t\t\tresult.push(\n\t\t\t\tcreateMigrationSequence({\n\t\t\t\t\tsequenceId,\n\t\t\t\t\tretroactive: true,\n\t\t\t\t\tsequence: [],\n\t\t\t\t})\n\t\t\t)\n\t\t} else if ('sequenceId' in migrations) {\n\t\t\tassert(\n\t\t\t\tsequenceId === migrations.sequenceId,\n\t\t\t\t`sequenceId mismatch for ${subType} ${RecordType} migrations. Expected '${sequenceId}', got '${migrations.sequenceId}'`\n\t\t\t)\n\t\t\tresult.push(migrations)\n\t\t} else if ('sequence' in migrations) {\n\t\t\tresult.push(\n\t\t\t\tcreateMigrationSequence({\n\t\t\t\t\tsequenceId,\n\t\t\t\t\tretroactive: true,\n\t\t\t\t\tsequence: migrations.sequence.map((m) =>\n\t\t\t\t\t\t'id' in m ? createPropsMigration(typeName, subType, m) : m\n\t\t\t\t\t),\n\t\t\t\t})\n\t\t\t)\n\t\t} else {\n\t\t\t// legacy migrations, will be removed in the future\n\t\t\tresult.push(\n\t\t\t\tcreateMigrationSequence({\n\t\t\t\t\tsequenceId,\n\t\t\t\t\tretroactive: true,\n\t\t\t\t\tsequence: Object.keys(migrations.migrators)\n\t\t\t\t\t\t.map((k) => Number(k))\n\t\t\t\t\t\t.sort((a: number, b: number) => a - b)\n\t\t\t\t\t\t.map(\n\t\t\t\t\t\t\t(version): Migration => ({\n\t\t\t\t\t\t\t\tid: `${sequenceId}/${version}`,\n\t\t\t\t\t\t\t\tscope: 'record',\n\t\t\t\t\t\t\t\tfilter: (r) => r.typeName === typeName && (r as R).type === subType,\n\t\t\t\t\t\t\t\tup: (record: any) => {\n\t\t\t\t\t\t\t\t\tconst result = migrations.migrators[version].up(record)\n\t\t\t\t\t\t\t\t\tif (result) {\n\t\t\t\t\t\t\t\t\t\treturn result\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\tdown: (record: any) => {\n\t\t\t\t\t\t\t\t\tconst result = migrations.migrators[version].down(record)\n\t\t\t\t\t\t\t\t\tif (result) {\n\t\t\t\t\t\t\t\t\t\treturn result\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t})\n\t\t\t\t\t\t),\n\t\t\t\t})\n\t\t\t)\n\t\t}\n\t}\n\n\treturn result\n}\n\n/**\n * Creates a store migration from a props migration definition.\n *\n * Converts a high-level property migration into a low-level store migration\n * that can be applied to records. The resulting migration will only affect\n * records of the specified type and subtype.\n *\n * @param typeName - The base type name (e.g., 'shape', 'binding')\n * @param subType - The specific subtype (e.g., 'geo', 'arrow')\n * @param m - The property migration definition\n * @returns A store migration that applies the property transformation\n *\n * @example\n * ```ts\n * const propsMigration: TLPropsMigration = {\n * id: 'com.myapp.shape.custom/1.0.0',\n * up: (props) => ({ ...props, color: 'blue' })\n * }\n *\n * const storeMigration = createPropsMigration('shape', 'custom', propsMigration)\n * ```\n *\n * @internal\n */\nexport function createPropsMigration<R extends UnknownRecord & { type: string; props: object }>(\n\ttypeName: R['typeName'],\n\tsubType: R['type'],\n\tm: TLPropsMigration\n): Migration {\n\treturn {\n\t\tid: m.id,\n\t\tdependsOn: m.dependsOn,\n\t\tscope: 'record',\n\t\tfilter: (r) => r.typeName === typeName && (r as R).type === subType,\n\t\tup: (record: any) => {\n\t\t\tconst result = m.up(record.props)\n\t\t\tif (result) {\n\t\t\t\trecord.props = result\n\t\t\t}\n\t\t},\n\t\tdown:\n\t\t\ttypeof m.down === 'function'\n\t\t\t\t? (record: any) => {\n\t\t\t\t\t\tconst result = (m.down as (props: any) => any)(record.props)\n\t\t\t\t\t\tif (result) {\n\t\t\t\t\t\t\trecord.props = result\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t: undefined,\n\t}\n}\n"],
5
5
  "mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,mBAQO;AACP,mBAA8C;AAmJvC,SAAS,uBACf,UACA,SACC;AACD,QAAM,SAA8B,CAAC;AAErC,aAAW,CAAC,SAAS,EAAE,WAAW,CAAC,KAAK,OAAO,QAAQ,OAAO,GAAG;AAChE,UAAM,aAAa,cAAc,QAAQ,IAAI,OAAO;AACpD,QAAI,CAAC,YAAY;AAEhB,aAAO;AAAA,YACN,sCAAwB;AAAA,UACvB;AAAA,UACA,aAAa;AAAA,UACb,UAAU,CAAC;AAAA,QACZ,CAAC;AAAA,MACF;AAAA,IACD,WAAW,gBAAgB,YAAY;AACtC;AAAA,QACC,eAAe,WAAW;AAAA,QAC1B,2BAA2B,OAAO,IAAI,uBAAU,0BAA0B,UAAU,WAAW,WAAW,UAAU;AAAA,MACrH;AACA,aAAO,KAAK,UAAU;AAAA,IACvB,WAAW,cAAc,YAAY;AACpC,aAAO;AAAA,YACN,sCAAwB;AAAA,UACvB;AAAA,UACA,aAAa;AAAA,UACb,UAAU,WAAW,SAAS;AAAA,YAAI,CAAC,MAClC,QAAQ,IAAI,qBAAqB,UAAU,SAAS,CAAC,IAAI;AAAA,UAC1D;AAAA,QACD,CAAC;AAAA,MACF;AAAA,IACD,OAAO;AAEN,aAAO;AAAA,YACN,sCAAwB;AAAA,UACvB;AAAA,UACA,aAAa;AAAA,UACb,UAAU,OAAO,KAAK,WAAW,SAAS,EACxC,IAAI,CAAC,MAAM,OAAO,CAAC,CAAC,EACpB,KAAK,CAAC,GAAW,MAAc,IAAI,CAAC,EACpC;AAAA,YACA,CAAC,aAAwB;AAAA,cACxB,IAAI,GAAG,UAAU,IAAI,OAAO;AAAA,cAC5B,OAAO;AAAA,cACP,QAAQ,CAAC,MAAM,EAAE,aAAa,YAAa,EAAQ,SAAS;AAAA,cAC5D,IAAI,CAAC,WAAgB;AACpB,sBAAMA,UAAS,WAAW,UAAU,OAAO,EAAE,GAAG,MAAM;AACtD,oBAAIA,SAAQ;AACX,yBAAOA;AAAA,gBACR;AAAA,cACD;AAAA,cACA,MAAM,CAAC,WAAgB;AACtB,sBAAMA,UAAS,WAAW,UAAU,OAAO,EAAE,KAAK,MAAM;AACxD,oBAAIA,SAAQ;AACX,yBAAOA;AAAA,gBACR;AAAA,cACD;AAAA,YACD;AAAA,UACD;AAAA,QACF,CAAC;AAAA,MACF;AAAA,IACD;AAAA,EACD;AAEA,SAAO;AACR;AA0BO,SAAS,qBACf,UACA,SACA,GACY;AACZ,SAAO;AAAA,IACN,IAAI,EAAE;AAAA,IACN,WAAW,EAAE;AAAA,IACb,OAAO;AAAA,IACP,QAAQ,CAAC,MAAM,EAAE,aAAa,YAAa,EAAQ,SAAS;AAAA,IAC5D,IAAI,CAAC,WAAgB;AACpB,YAAM,SAAS,EAAE,GAAG,OAAO,KAAK;AAChC,UAAI,QAAQ;AACX,eAAO,QAAQ;AAAA,MAChB;AAAA,IACD;AAAA,IACA,MACC,OAAO,EAAE,SAAS,aACf,CAAC,WAAgB;AACjB,YAAM,SAAU,EAAE,KAA6B,OAAO,KAAK;AAC3D,UAAI,QAAQ;AACX,eAAO,QAAQ;AAAA,MAChB;AAAA,IACD,IACC;AAAA,EACL;AACD;",
6
6
  "names": ["result"]
7
7
  }
@@ -181,7 +181,7 @@ import {
181
181
  } from "./translations/translations.mjs";
182
182
  registerTldrawLibraryVersion(
183
183
  "@tldraw/tlschema",
184
- "4.6.0-internal.c7df3c92455a",
184
+ "4.6.0-internal.e29318c66fb0",
185
185
  "esm"
186
186
  );
187
187
  import { b64Vecs } from "./misc/b64Vecs.mjs";
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/records/TLCustomRecord.ts"],
4
- "sourcesContent": ["import {\n\tMigrationSequence,\n\tRecordId,\n\tRecordScope,\n\tUnknownRecord,\n\tcreateMigrationSequence,\n\tcreateRecordType,\n} from '@tldraw/store'\nimport { assert, mapObjectMapValues, uniqueId } from '@tldraw/utils'\nimport { T } from '@tldraw/validate'\nimport { TLPropsMigrations } from '../recordsWithProps'\n\n/**\n * Configuration for a custom record type in the schema.\n *\n * Custom record types allow you to add entirely new data types to the tldraw store\n * that don't fit into the existing shape, binding, or asset categories. This is useful\n * for storing domain-specific data like comments, annotations, or application state\n * that needs to participate in persistence and synchronization.\n *\n * @example\n * ```ts\n * const commentRecordConfig: CustomRecordInfo = {\n * scope: 'document',\n * validator: T.object({\n * id: T.string,\n * typeName: T.literal('comment'),\n * text: T.string,\n * shapeId: T.string,\n * authorId: T.string,\n * createdAt: T.number,\n * }),\n * migrations: createRecordMigrationSequence({\n * sequenceId: 'com.myapp.comment',\n * recordType: 'comment',\n * sequence: [],\n * }),\n * }\n * ```\n *\n * @public\n */\nexport interface CustomRecordInfo {\n\t/**\n\t * The scope determines how records of this type are persisted and synchronized:\n\t * - **document**: Persisted and synced across all clients\n\t * - **session**: Local to current session, not synced\n\t * - **presence**: Ephemeral presence data, may be synced but not persisted\n\t */\n\tscope: RecordScope\n\n\t/**\n\t * Validator for the complete record structure.\n\t *\n\t * Should validate the entire record including `id` and `typeName` fields.\n\t * Use validators like T.object, T.string, etc.\n\t */\n\tvalidator: T.Validatable<any>\n\n\t/**\n\t * Optional migration sequence for handling schema evolution over time.\n\t *\n\t * Can be a full MigrationSequence or a simplified TLPropsMigrations format.\n\t * If not provided, an empty migration sequence will be created automatically.\n\t */\n\tmigrations?: MigrationSequence | TLPropsMigrations\n\n\t/**\n\t * Optional factory function that returns default property values for new records.\n\t *\n\t * Called when creating new records to provide initial values for any properties\n\t * not explicitly provided during creation.\n\t */\n\t// eslint-disable-next-line @typescript-eslint/method-signature-style\n\tcreateDefaultProperties?: () => Record<string, unknown>\n}\n\n/**\n * Creates a RecordType for a custom record based on its configuration.\n *\n * @param typeName - The unique type name for this record type\n * @param config - Configuration for the custom record type\n * @returns A RecordType instance that can be used to create and manage records\n *\n * @internal\n */\nexport function createCustomRecordType(typeName: string, config: CustomRecordInfo) {\n\treturn createRecordType<UnknownRecord>(typeName, {\n\t\tscope: config.scope,\n\t\tvalidator: config.validator,\n\t}).withDefaultProperties(config.createDefaultProperties ?? (() => ({})))\n}\n\n/**\n * Processes migrations for custom record types.\n *\n * Converts the migration configuration from CustomRecordInfo into proper\n * MigrationSequence objects that can be used by the store system.\n *\n * @param records - Record of type names to their configuration\n * @returns Array of migration sequences for the custom record types\n *\n * @internal\n */\nexport function processCustomRecordMigrations(\n\trecords: Record<string, CustomRecordInfo>\n): MigrationSequence[] {\n\tconst result: MigrationSequence[] = []\n\n\tfor (const [typeName, config] of Object.entries(records)) {\n\t\tconst sequenceId = `com.tldraw.${typeName}`\n\t\tconst { migrations } = config\n\n\t\tif (!migrations) {\n\t\t\t// Provide empty migration sequence to allow for future migrations\n\t\t\tresult.push(\n\t\t\t\tcreateMigrationSequence({\n\t\t\t\t\tsequenceId,\n\t\t\t\t\tretroactive: true,\n\t\t\t\t\tsequence: [],\n\t\t\t\t})\n\t\t\t)\n\t\t} else if ('sequenceId' in migrations) {\n\t\t\t// Full MigrationSequence provided\n\t\t\tassert(\n\t\t\t\tsequenceId === migrations.sequenceId,\n\t\t\t\t`sequenceId mismatch for ${typeName} custom record migrations. Expected '${sequenceId}', got '${migrations.sequenceId}'`\n\t\t\t)\n\t\t\tresult.push(migrations)\n\t\t} else if ('sequence' in migrations) {\n\t\t\t// TLPropsMigrations format - convert to full MigrationSequence\n\t\t\tresult.push(\n\t\t\t\tcreateMigrationSequence({\n\t\t\t\t\tsequenceId,\n\t\t\t\t\tretroactive: true,\n\t\t\t\t\tsequence: migrations.sequence.map((m) => {\n\t\t\t\t\t\tif (!('id' in m)) return m\n\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\tid: m.id,\n\t\t\t\t\t\t\tdependsOn: m.dependsOn,\n\t\t\t\t\t\t\tscope: 'record' as const,\n\t\t\t\t\t\t\tfilter: (r: UnknownRecord) => r.typeName === typeName,\n\t\t\t\t\t\t\tup: (record: any) => {\n\t\t\t\t\t\t\t\tconst result = m.up(record)\n\t\t\t\t\t\t\t\tif (result) return result\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tdown:\n\t\t\t\t\t\t\t\ttypeof m.down === 'function'\n\t\t\t\t\t\t\t\t\t? (record: any) => {\n\t\t\t\t\t\t\t\t\t\t\tconst result = (m.down as (r: any) => any)(record)\n\t\t\t\t\t\t\t\t\t\t\tif (result) return result\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t: undefined,\n\t\t\t\t\t\t}\n\t\t\t\t\t}),\n\t\t\t\t})\n\t\t\t)\n\t\t}\n\t}\n\n\treturn result\n}\n\n/**\n * Creates properly formatted migration IDs for custom record migrations.\n *\n * Generates standardized migration IDs following the convention:\n * `com.tldraw.{recordType}/{version}`\n *\n * @param recordType - The type name of the custom record\n * @param ids - Record mapping migration names to version numbers\n * @returns Record with the same keys but formatted migration ID values\n *\n * @example\n * ```ts\n * const commentVersions = createCustomRecordMigrationIds('comment', {\n * AddAuthorId: 1,\n * AddCreatedAt: 2,\n * RefactorReactions: 3\n * })\n * // Result: {\n * // AddAuthorId: 'com.tldraw.comment/1',\n * // AddCreatedAt: 'com.tldraw.comment/2',\n * // RefactorReactions: 'com.tldraw.comment/3'\n * // }\n * ```\n *\n * @public\n */\nexport function createCustomRecordMigrationIds<\n\tconst S extends string,\n\tconst T extends Record<string, number>,\n>(recordType: S, ids: T): { [k in keyof T]: `com.tldraw.${S}/${T[k]}` } {\n\treturn mapObjectMapValues(ids, (_k, v) => `com.tldraw.${recordType}/${v}`) as any\n}\n\n/**\n * Creates a migration sequence for custom record types.\n *\n * This is a pass-through function that maintains the same structure as the input.\n * It's used for consistency and to provide a clear API for defining custom record migrations.\n *\n * @param migrations - The migration sequence to create\n * @returns The same migration sequence (pass-through)\n *\n * @example\n * ```ts\n * const commentMigrations = createCustomRecordMigrationSequence({\n * sequence: [\n * {\n * id: 'com.myapp.comment/1',\n * up: (record) => ({ ...record, authorId: record.authorId ?? 'unknown' }),\n * down: ({ authorId, ...record }) => record\n * }\n * ]\n * })\n * ```\n *\n * @public\n */\nexport function createCustomRecordMigrationSequence(\n\tmigrations: TLPropsMigrations\n): TLPropsMigrations {\n\treturn migrations\n}\n\n/**\n * Creates a unique ID for a custom record type.\n *\n * @param typeName - The type name of the custom record\n * @param id - Optional custom ID suffix. If not provided, a unique ID will be generated\n * @returns A properly formatted record ID\n *\n * @example\n * ```ts\n * // Create with auto-generated ID\n * const commentId = createCustomRecordId('comment') // 'comment:abc123'\n *\n * // Create with custom ID\n * const customId = createCustomRecordId('comment', 'my-comment') // 'comment:my-comment'\n * ```\n *\n * @public\n */\nexport function createCustomRecordId<T extends string>(\n\ttypeName: T,\n\tid?: string\n): RecordId<UnknownRecord> & `${T}:${string}` {\n\treturn `${typeName}:${id ?? uniqueId()}` as RecordId<UnknownRecord> & `${T}:${string}`\n}\n\n/**\n * Type guard to check if a string is a valid ID for a specific custom record type.\n *\n * @param typeName - The type name to check against\n * @param id - The string to check\n * @returns True if the string is a valid ID for the specified record type\n *\n * @example\n * ```ts\n * const id = 'comment:abc123'\n * if (isCustomRecordId('comment', id)) {\n * // id is now typed as a comment record ID\n * const comment = store.get(id)\n * }\n * ```\n *\n * @public\n */\nexport function isCustomRecordId(typeName: string, id?: string): boolean {\n\tif (!id) return false\n\treturn id.startsWith(`${typeName}:`)\n}\n\n/**\n * Type guard to check if a record is of a specific custom type.\n *\n * @param typeName - The type name to check against\n * @param record - The record to check\n * @returns True if the record is of the specified type\n *\n * @example\n * ```ts\n * function handleRecord(record: TLRecord) {\n * if (isCustomRecord('comment', record)) {\n * // Handle comment record\n * console.log(`Comment: ${record.text}`)\n * }\n * }\n * ```\n *\n * @public\n */\nexport function isCustomRecord(typeName: string, record?: UnknownRecord): boolean {\n\tif (!record) return false\n\treturn record.typeName === typeName\n}\n"],
4
+ "sourcesContent": ["import {\n\tMigrationSequence,\n\tRecordId,\n\tRecordScope,\n\tUnknownRecord,\n\tcreateMigrationSequence,\n\tcreateRecordType,\n} from '@tldraw/store'\nimport { assert, mapObjectMapValues, uniqueId } from '@tldraw/utils'\nimport { T } from '@tldraw/validate'\nimport { TLPropsMigrations } from '../recordsWithProps'\n\n/**\n * Configuration for a custom record type in the schema.\n *\n * Custom record types allow you to add entirely new data types to the tldraw store\n * that don't fit into the existing shape, binding, or asset categories. This is useful\n * for storing domain-specific data like comments, annotations, or application state\n * that needs to participate in persistence and synchronization.\n *\n * @example\n * ```ts\n * const commentRecordConfig: CustomRecordInfo = {\n * scope: 'document',\n * validator: T.object({\n * id: T.string,\n * typeName: T.literal('comment'),\n * text: T.string,\n * shapeId: T.string,\n * authorId: T.string,\n * createdAt: T.number,\n * }),\n * migrations: createRecordMigrationSequence({\n * sequenceId: 'com.myapp.comment',\n * recordType: 'comment',\n * sequence: [],\n * }),\n * }\n * ```\n *\n * @public\n */\nexport interface CustomRecordInfo {\n\t/**\n\t * The scope determines how records of this type are persisted and synchronized:\n\t * - **document**: Persisted and synced across all clients\n\t * - **session**: Local to current session, not synced\n\t * - **presence**: Ephemeral presence data, may be synced but not persisted\n\t */\n\tscope: RecordScope\n\n\t/**\n\t * Validator for the complete record structure.\n\t *\n\t * Should validate the entire record including `id` and `typeName` fields.\n\t * Use validators like T.object, T.string, etc.\n\t */\n\tvalidator: T.Validatable<any>\n\n\t/**\n\t * Optional migration sequence for handling schema evolution over time.\n\t *\n\t * Can be a full MigrationSequence or a simplified TLPropsMigrations format.\n\t * If not provided, an empty migration sequence will be created automatically.\n\t */\n\tmigrations?: MigrationSequence | TLPropsMigrations\n\n\t/**\n\t * Optional factory function that returns default property values for new records.\n\t *\n\t * Called when creating new records to provide initial values for any properties\n\t * not explicitly provided during creation.\n\t */\n\t// eslint-disable-next-line tldraw/method-signature-style\n\tcreateDefaultProperties?: () => Record<string, unknown>\n}\n\n/**\n * Creates a RecordType for a custom record based on its configuration.\n *\n * @param typeName - The unique type name for this record type\n * @param config - Configuration for the custom record type\n * @returns A RecordType instance that can be used to create and manage records\n *\n * @internal\n */\nexport function createCustomRecordType(typeName: string, config: CustomRecordInfo) {\n\treturn createRecordType<UnknownRecord>(typeName, {\n\t\tscope: config.scope,\n\t\tvalidator: config.validator,\n\t}).withDefaultProperties(config.createDefaultProperties ?? (() => ({})))\n}\n\n/**\n * Processes migrations for custom record types.\n *\n * Converts the migration configuration from CustomRecordInfo into proper\n * MigrationSequence objects that can be used by the store system.\n *\n * @param records - Record of type names to their configuration\n * @returns Array of migration sequences for the custom record types\n *\n * @internal\n */\nexport function processCustomRecordMigrations(\n\trecords: Record<string, CustomRecordInfo>\n): MigrationSequence[] {\n\tconst result: MigrationSequence[] = []\n\n\tfor (const [typeName, config] of Object.entries(records)) {\n\t\tconst sequenceId = `com.tldraw.${typeName}`\n\t\tconst { migrations } = config\n\n\t\tif (!migrations) {\n\t\t\t// Provide empty migration sequence to allow for future migrations\n\t\t\tresult.push(\n\t\t\t\tcreateMigrationSequence({\n\t\t\t\t\tsequenceId,\n\t\t\t\t\tretroactive: true,\n\t\t\t\t\tsequence: [],\n\t\t\t\t})\n\t\t\t)\n\t\t} else if ('sequenceId' in migrations) {\n\t\t\t// Full MigrationSequence provided\n\t\t\tassert(\n\t\t\t\tsequenceId === migrations.sequenceId,\n\t\t\t\t`sequenceId mismatch for ${typeName} custom record migrations. Expected '${sequenceId}', got '${migrations.sequenceId}'`\n\t\t\t)\n\t\t\tresult.push(migrations)\n\t\t} else if ('sequence' in migrations) {\n\t\t\t// TLPropsMigrations format - convert to full MigrationSequence\n\t\t\tresult.push(\n\t\t\t\tcreateMigrationSequence({\n\t\t\t\t\tsequenceId,\n\t\t\t\t\tretroactive: true,\n\t\t\t\t\tsequence: migrations.sequence.map((m) => {\n\t\t\t\t\t\tif (!('id' in m)) return m\n\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\tid: m.id,\n\t\t\t\t\t\t\tdependsOn: m.dependsOn,\n\t\t\t\t\t\t\tscope: 'record' as const,\n\t\t\t\t\t\t\tfilter: (r: UnknownRecord) => r.typeName === typeName,\n\t\t\t\t\t\t\tup: (record: any) => {\n\t\t\t\t\t\t\t\tconst result = m.up(record)\n\t\t\t\t\t\t\t\tif (result) return result\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tdown:\n\t\t\t\t\t\t\t\ttypeof m.down === 'function'\n\t\t\t\t\t\t\t\t\t? (record: any) => {\n\t\t\t\t\t\t\t\t\t\t\tconst result = (m.down as (r: any) => any)(record)\n\t\t\t\t\t\t\t\t\t\t\tif (result) return result\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t: undefined,\n\t\t\t\t\t\t}\n\t\t\t\t\t}),\n\t\t\t\t})\n\t\t\t)\n\t\t}\n\t}\n\n\treturn result\n}\n\n/**\n * Creates properly formatted migration IDs for custom record migrations.\n *\n * Generates standardized migration IDs following the convention:\n * `com.tldraw.{recordType}/{version}`\n *\n * @param recordType - The type name of the custom record\n * @param ids - Record mapping migration names to version numbers\n * @returns Record with the same keys but formatted migration ID values\n *\n * @example\n * ```ts\n * const commentVersions = createCustomRecordMigrationIds('comment', {\n * AddAuthorId: 1,\n * AddCreatedAt: 2,\n * RefactorReactions: 3\n * })\n * // Result: {\n * // AddAuthorId: 'com.tldraw.comment/1',\n * // AddCreatedAt: 'com.tldraw.comment/2',\n * // RefactorReactions: 'com.tldraw.comment/3'\n * // }\n * ```\n *\n * @public\n */\nexport function createCustomRecordMigrationIds<\n\tconst S extends string,\n\tconst T extends Record<string, number>,\n>(recordType: S, ids: T): { [k in keyof T]: `com.tldraw.${S}/${T[k]}` } {\n\treturn mapObjectMapValues(ids, (_k, v) => `com.tldraw.${recordType}/${v}`) as any\n}\n\n/**\n * Creates a migration sequence for custom record types.\n *\n * This is a pass-through function that maintains the same structure as the input.\n * It's used for consistency and to provide a clear API for defining custom record migrations.\n *\n * @param migrations - The migration sequence to create\n * @returns The same migration sequence (pass-through)\n *\n * @example\n * ```ts\n * const commentMigrations = createCustomRecordMigrationSequence({\n * sequence: [\n * {\n * id: 'com.myapp.comment/1',\n * up: (record) => ({ ...record, authorId: record.authorId ?? 'unknown' }),\n * down: ({ authorId, ...record }) => record\n * }\n * ]\n * })\n * ```\n *\n * @public\n */\nexport function createCustomRecordMigrationSequence(\n\tmigrations: TLPropsMigrations\n): TLPropsMigrations {\n\treturn migrations\n}\n\n/**\n * Creates a unique ID for a custom record type.\n *\n * @param typeName - The type name of the custom record\n * @param id - Optional custom ID suffix. If not provided, a unique ID will be generated\n * @returns A properly formatted record ID\n *\n * @example\n * ```ts\n * // Create with auto-generated ID\n * const commentId = createCustomRecordId('comment') // 'comment:abc123'\n *\n * // Create with custom ID\n * const customId = createCustomRecordId('comment', 'my-comment') // 'comment:my-comment'\n * ```\n *\n * @public\n */\nexport function createCustomRecordId<T extends string>(\n\ttypeName: T,\n\tid?: string\n): RecordId<UnknownRecord> & `${T}:${string}` {\n\treturn `${typeName}:${id ?? uniqueId()}` as RecordId<UnknownRecord> & `${T}:${string}`\n}\n\n/**\n * Type guard to check if a string is a valid ID for a specific custom record type.\n *\n * @param typeName - The type name to check against\n * @param id - The string to check\n * @returns True if the string is a valid ID for the specified record type\n *\n * @example\n * ```ts\n * const id = 'comment:abc123'\n * if (isCustomRecordId('comment', id)) {\n * // id is now typed as a comment record ID\n * const comment = store.get(id)\n * }\n * ```\n *\n * @public\n */\nexport function isCustomRecordId(typeName: string, id?: string): boolean {\n\tif (!id) return false\n\treturn id.startsWith(`${typeName}:`)\n}\n\n/**\n * Type guard to check if a record is of a specific custom type.\n *\n * @param typeName - The type name to check against\n * @param record - The record to check\n * @returns True if the record is of the specified type\n *\n * @example\n * ```ts\n * function handleRecord(record: TLRecord) {\n * if (isCustomRecord('comment', record)) {\n * // Handle comment record\n * console.log(`Comment: ${record.text}`)\n * }\n * }\n * ```\n *\n * @public\n */\nexport function isCustomRecord(typeName: string, record?: UnknownRecord): boolean {\n\tif (!record) return false\n\treturn record.typeName === typeName\n}\n"],
5
5
  "mappings": "AAAA;AAAA,EAKC;AAAA,EACA;AAAA,OACM;AACP,SAAS,QAAQ,oBAAoB,gBAAgB;AA8E9C,SAAS,uBAAuB,UAAkB,QAA0B;AAClF,SAAO,iBAAgC,UAAU;AAAA,IAChD,OAAO,OAAO;AAAA,IACd,WAAW,OAAO;AAAA,EACnB,CAAC,EAAE,sBAAsB,OAAO,4BAA4B,OAAO,CAAC,GAAG;AACxE;AAaO,SAAS,8BACf,SACsB;AACtB,QAAM,SAA8B,CAAC;AAErC,aAAW,CAAC,UAAU,MAAM,KAAK,OAAO,QAAQ,OAAO,GAAG;AACzD,UAAM,aAAa,cAAc,QAAQ;AACzC,UAAM,EAAE,WAAW,IAAI;AAEvB,QAAI,CAAC,YAAY;AAEhB,aAAO;AAAA,QACN,wBAAwB;AAAA,UACvB;AAAA,UACA,aAAa;AAAA,UACb,UAAU,CAAC;AAAA,QACZ,CAAC;AAAA,MACF;AAAA,IACD,WAAW,gBAAgB,YAAY;AAEtC;AAAA,QACC,eAAe,WAAW;AAAA,QAC1B,2BAA2B,QAAQ,wCAAwC,UAAU,WAAW,WAAW,UAAU;AAAA,MACtH;AACA,aAAO,KAAK,UAAU;AAAA,IACvB,WAAW,cAAc,YAAY;AAEpC,aAAO;AAAA,QACN,wBAAwB;AAAA,UACvB;AAAA,UACA,aAAa;AAAA,UACb,UAAU,WAAW,SAAS,IAAI,CAAC,MAAM;AACxC,gBAAI,EAAE,QAAQ,GAAI,QAAO;AACzB,mBAAO;AAAA,cACN,IAAI,EAAE;AAAA,cACN,WAAW,EAAE;AAAA,cACb,OAAO;AAAA,cACP,QAAQ,CAAC,MAAqB,EAAE,aAAa;AAAA,cAC7C,IAAI,CAAC,WAAgB;AACpB,sBAAMA,UAAS,EAAE,GAAG,MAAM;AAC1B,oBAAIA,QAAQ,QAAOA;AAAA,cACpB;AAAA,cACA,MACC,OAAO,EAAE,SAAS,aACf,CAAC,WAAgB;AACjB,sBAAMA,UAAU,EAAE,KAAyB,MAAM;AACjD,oBAAIA,QAAQ,QAAOA;AAAA,cACpB,IACC;AAAA,YACL;AAAA,UACD,CAAC;AAAA,QACF,CAAC;AAAA,MACF;AAAA,IACD;AAAA,EACD;AAEA,SAAO;AACR;AA4BO,SAAS,+BAGd,YAAe,KAAuD;AACvE,SAAO,mBAAmB,KAAK,CAAC,IAAI,MAAM,cAAc,UAAU,IAAI,CAAC,EAAE;AAC1E;AA0BO,SAAS,oCACf,YACoB;AACpB,SAAO;AACR;AAoBO,SAAS,qBACf,UACA,IAC6C;AAC7C,SAAO,GAAG,QAAQ,IAAI,MAAM,SAAS,CAAC;AACvC;AAoBO,SAAS,iBAAiB,UAAkB,IAAsB;AACxE,MAAI,CAAC,GAAI,QAAO;AAChB,SAAO,GAAG,WAAW,GAAG,QAAQ,GAAG;AACpC;AAqBO,SAAS,eAAe,UAAkB,QAAiC;AACjF,MAAI,CAAC,OAAQ,QAAO;AACpB,SAAO,OAAO,aAAa;AAC5B;",
6
6
  "names": ["result"]
7
7
  }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/records/TLPageState.ts"],
4
- "sourcesContent": ["import {\n\tBaseRecord,\n\tcreateMigrationIds,\n\tcreateRecordMigrationSequence,\n\tcreateRecordType,\n\tRecordId,\n} from '@tldraw/store'\nimport { JsonObject } from '@tldraw/utils'\nimport { T } from '@tldraw/validate'\nimport { idValidator } from '../misc/id-validator'\nimport { shapeIdValidator } from '../shapes/TLBaseShape'\nimport { pageIdValidator, TLPage } from './TLPage'\nimport { TLShapeId } from './TLShape'\n\n/**\n * State that is unique to a particular page within a particular browser tab.\n * This record tracks all page-specific interaction state including selected shapes,\n * editing state, hover state, and other transient UI state that is tied to\n * both a specific page and a specific browser session.\n *\n * Each combination of page and browser tab has its own TLInstancePageState record.\n *\n * @example\n * ```ts\n * const pageState: TLInstancePageState = {\n * id: 'instance_page_state:page1',\n * typeName: 'instance_page_state',\n * pageId: 'page:page1',\n * selectedShapeIds: ['shape:rect1', 'shape:circle2'],\n * hoveredShapeId: 'shape:text3',\n * editingShapeId: null,\n * focusedGroupId: null\n * }\n * ```\n *\n * @public\n */\nexport interface TLInstancePageState\n\textends BaseRecord<'instance_page_state', TLInstancePageStateId> {\n\tpageId: RecordId<TLPage>\n\tselectedShapeIds: TLShapeId[]\n\thintingShapeIds: TLShapeId[]\n\terasingShapeIds: TLShapeId[]\n\thoveredShapeId: TLShapeId | null\n\teditingShapeId: TLShapeId | null\n\tcroppingShapeId: TLShapeId | null\n\tfocusedGroupId: TLShapeId | null\n\tmeta: JsonObject\n}\n\n/**\n * Runtime validator for TLInstancePageState records. Validates the structure\n * and types of all instance page state properties to ensure data integrity.\n *\n * @example\n * ```ts\n * const pageState = {\n * id: 'instance_page_state:page1',\n * typeName: 'instance_page_state',\n * pageId: 'page:page1',\n * selectedShapeIds: ['shape:rect1'],\n * // ... other properties\n * }\n * const isValid = instancePageStateValidator.isValid(pageState) // true\n * ```\n *\n * @public\n */\nexport const instancePageStateValidator: T.Validator<TLInstancePageState> = T.model(\n\t'instance_page_state',\n\tT.object({\n\t\ttypeName: T.literal('instance_page_state'),\n\t\tid: idValidator<TLInstancePageStateId>('instance_page_state'),\n\t\tpageId: pageIdValidator,\n\t\tselectedShapeIds: T.arrayOf(shapeIdValidator),\n\t\thintingShapeIds: T.arrayOf(shapeIdValidator),\n\t\terasingShapeIds: T.arrayOf(shapeIdValidator),\n\t\thoveredShapeId: shapeIdValidator.nullable(),\n\t\teditingShapeId: shapeIdValidator.nullable(),\n\t\tcroppingShapeId: shapeIdValidator.nullable(),\n\t\tfocusedGroupId: shapeIdValidator.nullable(),\n\t\tmeta: T.jsonValue as T.ObjectValidator<JsonObject>,\n\t})\n)\n\n/**\n * Migration version identifiers for TLInstancePageState records. Each version\n * represents a schema change that requires data transformation when loading\n * older documents.\n *\n * @public\n */\nexport const instancePageStateVersions = createMigrationIds('com.tldraw.instance_page_state', {\n\tAddCroppingId: 1,\n\tRemoveInstanceIdAndCameraId: 2,\n\tAddMeta: 3,\n\tRenameProperties: 4,\n\tRenamePropertiesAgain: 5,\n} as const)\n\n/**\n * Migration sequence for TLInstancePageState records. Defines how to transform\n * instance page state records between different schema versions, ensuring data\n * compatibility when loading documents created with different versions.\n *\n * @example\n * ```ts\n * // Migrations are applied automatically when loading documents\n * const migrated = instancePageStateMigrations.migrate(oldState, targetVersion)\n * ```\n *\n * @public\n */\nexport const instancePageStateMigrations = createRecordMigrationSequence({\n\tsequenceId: 'com.tldraw.instance_page_state',\n\trecordType: 'instance_page_state',\n\tsequence: [\n\t\t{\n\t\t\tid: instancePageStateVersions.AddCroppingId,\n\t\t\tup(instance: any) {\n\t\t\t\tinstance.croppingShapeId = null\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tid: instancePageStateVersions.RemoveInstanceIdAndCameraId,\n\t\t\tup(instance: any) {\n\t\t\t\tdelete instance.instanceId\n\t\t\t\tdelete instance.cameraId\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tid: instancePageStateVersions.AddMeta,\n\t\t\tup: (record: any) => {\n\t\t\t\trecord.meta = {}\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tid: instancePageStateVersions.RenameProperties,\n\t\t\t// this migration is cursed: it was written wrong and doesn't do anything.\n\t\t\t// rather than replace it, I've added another migration below that fixes it.\n\t\t\tup: (_record) => {\n\t\t\t\t// noop\n\t\t\t},\n\t\t\tdown: (_record) => {\n\t\t\t\t// noop\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tid: instancePageStateVersions.RenamePropertiesAgain,\n\t\t\tup: (record: any) => {\n\t\t\t\trecord.selectedShapeIds = record.selectedIds\n\t\t\t\tdelete record.selectedIds\n\t\t\t\trecord.hintingShapeIds = record.hintingIds\n\t\t\t\tdelete record.hintingIds\n\t\t\t\trecord.erasingShapeIds = record.erasingIds\n\t\t\t\tdelete record.erasingIds\n\t\t\t\trecord.hoveredShapeId = record.hoveredId\n\t\t\t\tdelete record.hoveredId\n\t\t\t\trecord.editingShapeId = record.editingId\n\t\t\t\tdelete record.editingId\n\t\t\t\trecord.croppingShapeId = record.croppingShapeId ?? record.croppingId ?? null\n\t\t\t\tdelete record.croppingId\n\t\t\t\trecord.focusedGroupId = record.focusLayerId\n\t\t\t\tdelete record.focusLayerId\n\t\t\t},\n\t\t\tdown: (record: any) => {\n\t\t\t\trecord.selectedIds = record.selectedShapeIds\n\t\t\t\tdelete record.selectedShapeIds\n\t\t\t\trecord.hintingIds = record.hintingShapeIds\n\t\t\t\tdelete record.hintingShapeIds\n\t\t\t\trecord.erasingIds = record.erasingShapeIds\n\t\t\t\tdelete record.erasingShapeIds\n\t\t\t\trecord.hoveredId = record.hoveredShapeId\n\t\t\t\tdelete record.hoveredShapeId\n\t\t\t\trecord.editingId = record.editingShapeId\n\t\t\t\tdelete record.editingShapeId\n\t\t\t\trecord.croppingId = record.croppingShapeId\n\t\t\t\tdelete record.croppingShapeId\n\t\t\t\trecord.focusLayerId = record.focusedGroupId\n\t\t\t\tdelete record.focusedGroupId\n\t\t\t},\n\t\t},\n\t],\n})\n\n/**\n * The RecordType definition for TLInstancePageState records. Defines validation,\n * scope, and default properties for instance page state records.\n *\n * Instance page states are scoped to the session level, meaning they are\n * specific to a browser tab and don't persist across sessions or sync\n * in collaborative environments.\n *\n * @example\n * ```ts\n * const pageState = InstancePageStateRecordType.create({\n * id: 'instance_page_state:page1',\n * pageId: 'page:page1',\n * selectedShapeIds: ['shape:rect1']\n * })\n * ```\n *\n * @public\n */\nexport const InstancePageStateRecordType = createRecordType<TLInstancePageState>(\n\t'instance_page_state',\n\t{\n\t\tvalidator: instancePageStateValidator,\n\t\tscope: 'session',\n\t\tephemeralKeys: {\n\t\t\tpageId: false,\n\t\t\tselectedShapeIds: false,\n\t\t\teditingShapeId: false,\n\t\t\tcroppingShapeId: false,\n\t\t\tmeta: false,\n\n\t\t\thintingShapeIds: true,\n\t\t\terasingShapeIds: true,\n\t\t\thoveredShapeId: true,\n\t\t\tfocusedGroupId: true,\n\t\t},\n\t}\n).withDefaultProperties(\n\t(): Omit<TLInstancePageState, 'id' | 'typeName' | 'pageId'> => ({\n\t\teditingShapeId: null,\n\t\tcroppingShapeId: null,\n\t\tselectedShapeIds: [],\n\t\thoveredShapeId: null,\n\t\terasingShapeIds: [],\n\t\thintingShapeIds: [],\n\t\tfocusedGroupId: null,\n\t\tmeta: {},\n\t})\n)\n\n/**\n * A unique identifier for TLInstancePageState records.\n *\n * Instance page state IDs follow the format 'instance_page_state:' followed\n * by a unique identifier, typically related to the page ID.\n *\n * @example\n * ```ts\n * const stateId: TLInstancePageStateId = 'instance_page_state:page1'\n * ```\n *\n * @public\n */\nexport type TLInstancePageStateId = RecordId<TLInstancePageState>\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import {\n\tBaseRecord,\n\tcreateMigrationIds,\n\tcreateRecordMigrationSequence,\n\tcreateRecordType,\n\tRecordId,\n} from '@tldraw/store'\nimport { JsonObject } from '@tldraw/utils'\nimport { T } from '@tldraw/validate'\nimport { idValidator } from '../misc/id-validator'\nimport { shapeIdValidator } from '../shapes/TLBaseShape'\nimport { pageIdValidator, TLPage } from './TLPage'\nimport { TLShapeId } from './TLShape'\n\n/**\n * State that is unique to a particular page within a particular browser tab.\n * This record tracks all page-specific interaction state including selected shapes,\n * editing state, hover state, and other transient UI state that is tied to\n * both a specific page and a specific browser session.\n *\n * Each combination of page and browser tab has its own TLInstancePageState record.\n *\n * @example\n * ```ts\n * const pageState: TLInstancePageState = {\n * id: 'instance_page_state:page1',\n * typeName: 'instance_page_state',\n * pageId: 'page:page1',\n * selectedShapeIds: ['shape:rect1', 'shape:circle2'],\n * hoveredShapeId: 'shape:text3',\n * editingShapeId: null,\n * focusedGroupId: null\n * }\n * ```\n *\n * @public\n */\nexport interface TLInstancePageState extends BaseRecord<\n\t'instance_page_state',\n\tTLInstancePageStateId\n> {\n\tpageId: RecordId<TLPage>\n\tselectedShapeIds: TLShapeId[]\n\thintingShapeIds: TLShapeId[]\n\terasingShapeIds: TLShapeId[]\n\thoveredShapeId: TLShapeId | null\n\teditingShapeId: TLShapeId | null\n\tcroppingShapeId: TLShapeId | null\n\tfocusedGroupId: TLShapeId | null\n\tmeta: JsonObject\n}\n\n/**\n * Runtime validator for TLInstancePageState records. Validates the structure\n * and types of all instance page state properties to ensure data integrity.\n *\n * @example\n * ```ts\n * const pageState = {\n * id: 'instance_page_state:page1',\n * typeName: 'instance_page_state',\n * pageId: 'page:page1',\n * selectedShapeIds: ['shape:rect1'],\n * // ... other properties\n * }\n * const isValid = instancePageStateValidator.isValid(pageState) // true\n * ```\n *\n * @public\n */\nexport const instancePageStateValidator: T.Validator<TLInstancePageState> = T.model(\n\t'instance_page_state',\n\tT.object({\n\t\ttypeName: T.literal('instance_page_state'),\n\t\tid: idValidator<TLInstancePageStateId>('instance_page_state'),\n\t\tpageId: pageIdValidator,\n\t\tselectedShapeIds: T.arrayOf(shapeIdValidator),\n\t\thintingShapeIds: T.arrayOf(shapeIdValidator),\n\t\terasingShapeIds: T.arrayOf(shapeIdValidator),\n\t\thoveredShapeId: shapeIdValidator.nullable(),\n\t\teditingShapeId: shapeIdValidator.nullable(),\n\t\tcroppingShapeId: shapeIdValidator.nullable(),\n\t\tfocusedGroupId: shapeIdValidator.nullable(),\n\t\tmeta: T.jsonValue as T.ObjectValidator<JsonObject>,\n\t})\n)\n\n/**\n * Migration version identifiers for TLInstancePageState records. Each version\n * represents a schema change that requires data transformation when loading\n * older documents.\n *\n * @public\n */\nexport const instancePageStateVersions = createMigrationIds('com.tldraw.instance_page_state', {\n\tAddCroppingId: 1,\n\tRemoveInstanceIdAndCameraId: 2,\n\tAddMeta: 3,\n\tRenameProperties: 4,\n\tRenamePropertiesAgain: 5,\n} as const)\n\n/**\n * Migration sequence for TLInstancePageState records. Defines how to transform\n * instance page state records between different schema versions, ensuring data\n * compatibility when loading documents created with different versions.\n *\n * @example\n * ```ts\n * // Migrations are applied automatically when loading documents\n * const migrated = instancePageStateMigrations.migrate(oldState, targetVersion)\n * ```\n *\n * @public\n */\nexport const instancePageStateMigrations = createRecordMigrationSequence({\n\tsequenceId: 'com.tldraw.instance_page_state',\n\trecordType: 'instance_page_state',\n\tsequence: [\n\t\t{\n\t\t\tid: instancePageStateVersions.AddCroppingId,\n\t\t\tup(instance: any) {\n\t\t\t\tinstance.croppingShapeId = null\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tid: instancePageStateVersions.RemoveInstanceIdAndCameraId,\n\t\t\tup(instance: any) {\n\t\t\t\tdelete instance.instanceId\n\t\t\t\tdelete instance.cameraId\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tid: instancePageStateVersions.AddMeta,\n\t\t\tup: (record: any) => {\n\t\t\t\trecord.meta = {}\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tid: instancePageStateVersions.RenameProperties,\n\t\t\t// this migration is cursed: it was written wrong and doesn't do anything.\n\t\t\t// rather than replace it, I've added another migration below that fixes it.\n\t\t\tup: (_record) => {\n\t\t\t\t// noop\n\t\t\t},\n\t\t\tdown: (_record) => {\n\t\t\t\t// noop\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tid: instancePageStateVersions.RenamePropertiesAgain,\n\t\t\tup: (record: any) => {\n\t\t\t\trecord.selectedShapeIds = record.selectedIds\n\t\t\t\tdelete record.selectedIds\n\t\t\t\trecord.hintingShapeIds = record.hintingIds\n\t\t\t\tdelete record.hintingIds\n\t\t\t\trecord.erasingShapeIds = record.erasingIds\n\t\t\t\tdelete record.erasingIds\n\t\t\t\trecord.hoveredShapeId = record.hoveredId\n\t\t\t\tdelete record.hoveredId\n\t\t\t\trecord.editingShapeId = record.editingId\n\t\t\t\tdelete record.editingId\n\t\t\t\trecord.croppingShapeId = record.croppingShapeId ?? record.croppingId ?? null\n\t\t\t\tdelete record.croppingId\n\t\t\t\trecord.focusedGroupId = record.focusLayerId\n\t\t\t\tdelete record.focusLayerId\n\t\t\t},\n\t\t\tdown: (record: any) => {\n\t\t\t\trecord.selectedIds = record.selectedShapeIds\n\t\t\t\tdelete record.selectedShapeIds\n\t\t\t\trecord.hintingIds = record.hintingShapeIds\n\t\t\t\tdelete record.hintingShapeIds\n\t\t\t\trecord.erasingIds = record.erasingShapeIds\n\t\t\t\tdelete record.erasingShapeIds\n\t\t\t\trecord.hoveredId = record.hoveredShapeId\n\t\t\t\tdelete record.hoveredShapeId\n\t\t\t\trecord.editingId = record.editingShapeId\n\t\t\t\tdelete record.editingShapeId\n\t\t\t\trecord.croppingId = record.croppingShapeId\n\t\t\t\tdelete record.croppingShapeId\n\t\t\t\trecord.focusLayerId = record.focusedGroupId\n\t\t\t\tdelete record.focusedGroupId\n\t\t\t},\n\t\t},\n\t],\n})\n\n/**\n * The RecordType definition for TLInstancePageState records. Defines validation,\n * scope, and default properties for instance page state records.\n *\n * Instance page states are scoped to the session level, meaning they are\n * specific to a browser tab and don't persist across sessions or sync\n * in collaborative environments.\n *\n * @example\n * ```ts\n * const pageState = InstancePageStateRecordType.create({\n * id: 'instance_page_state:page1',\n * pageId: 'page:page1',\n * selectedShapeIds: ['shape:rect1']\n * })\n * ```\n *\n * @public\n */\nexport const InstancePageStateRecordType = createRecordType<TLInstancePageState>(\n\t'instance_page_state',\n\t{\n\t\tvalidator: instancePageStateValidator,\n\t\tscope: 'session',\n\t\tephemeralKeys: {\n\t\t\tpageId: false,\n\t\t\tselectedShapeIds: false,\n\t\t\teditingShapeId: false,\n\t\t\tcroppingShapeId: false,\n\t\t\tmeta: false,\n\n\t\t\thintingShapeIds: true,\n\t\t\terasingShapeIds: true,\n\t\t\thoveredShapeId: true,\n\t\t\tfocusedGroupId: true,\n\t\t},\n\t}\n).withDefaultProperties(\n\t(): Omit<TLInstancePageState, 'id' | 'typeName' | 'pageId'> => ({\n\t\teditingShapeId: null,\n\t\tcroppingShapeId: null,\n\t\tselectedShapeIds: [],\n\t\thoveredShapeId: null,\n\t\terasingShapeIds: [],\n\t\thintingShapeIds: [],\n\t\tfocusedGroupId: null,\n\t\tmeta: {},\n\t})\n)\n\n/**\n * A unique identifier for TLInstancePageState records.\n *\n * Instance page state IDs follow the format 'instance_page_state:' followed\n * by a unique identifier, typically related to the page ID.\n *\n * @example\n * ```ts\n * const stateId: TLInstancePageStateId = 'instance_page_state:page1'\n * ```\n *\n * @public\n */\nexport type TLInstancePageStateId = RecordId<TLInstancePageState>\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../src/recordsWithProps.ts"],
4
- "sourcesContent": ["import {\n\tMigration,\n\tMigrationId,\n\tMigrationSequence,\n\tRecordType,\n\tStandaloneDependsOn,\n\tUnknownRecord,\n\tcreateMigrationSequence,\n} from '@tldraw/store'\nimport { MakeUndefinedOptional, assert } from '@tldraw/utils'\nimport { T } from '@tldraw/validate'\nimport { SchemaPropsInfo } from './createTLSchema'\n\n/**\n * Maps a record's property types to their corresponding validators.\n *\n * This utility type takes a record type with a `props` object and creates\n * a mapping where each property key maps to a validator for that property's type.\n * This is used to define validation schemas for record properties.\n *\n * @example\n * ```ts\n * interface MyShape extends TLBaseShape<'custom', { width: number; color: string }> {}\n *\n * // Define validators for the shape properties\n * const myShapeProps: RecordProps<MyShape> = {\n * width: T.number,\n * color: T.string\n * }\n * ```\n *\n * @public\n */\nexport type RecordProps<R extends UnknownRecord & { props: object }> = {\n\t[K in keyof R['props']]: T.Validatable<R['props'][K]>\n}\n\n/**\n * Extracts the TypeScript types from a record properties configuration.\n *\n * Takes a configuration object where values are validators and returns the\n * corresponding TypeScript types, with undefined values made optional.\n *\n * @example\n * ```ts\n * const shapePropsConfig = {\n * width: T.number,\n * height: T.number,\n * color: T.optional(T.string)\n * }\n *\n * type ShapeProps = RecordPropsType<typeof shapePropsConfig>\n * // Result: { width: number; height: number; color?: string }\n * ```\n *\n * @public\n */\nexport type RecordPropsType<Config extends Record<string, T.Validatable<any>>> =\n\tMakeUndefinedOptional<{\n\t\t[K in keyof Config]: T.TypeOf<Config[K]>\n\t}>\n\n/**\n * A migration definition for shape or record properties.\n *\n * Defines how to transform record properties when migrating between schema versions.\n * Each migration has an `up` function to upgrade data and an optional `down` function\n * to downgrade data if needed.\n *\n * @example\n * ```ts\n * const addColorMigration: TLPropsMigration = {\n * id: 'com.myapp.shape.custom/1.0.0',\n * up: (props) => {\n * // Add a default color property\n * return { ...props, color: 'black' }\n * },\n * down: (props) => {\n * // Remove the color property\n * const { color, ...rest } = props\n * return rest\n * }\n * }\n * ```\n *\n * @public\n */\nexport interface TLPropsMigration {\n\treadonly id: MigrationId\n\treadonly dependsOn?: MigrationId[]\n\t// eslint-disable-next-line @typescript-eslint/method-signature-style\n\treadonly up: (props: any) => any\n\t/**\n\t * If a down migration was deployed more than a couple of months ago it should be safe to retire it.\n\t * We only really need them to smooth over the transition between versions, and some folks do keep\n\t * browser tabs open for months without refreshing, but at a certain point that kind of behavior is\n\t * on them. Plus anyway recently chrome has started to actually kill tabs that are open for too long\n\t * rather than just suspending them, so if other browsers follow suit maybe it's less of a concern.\n\t *\n\t * @public\n\t */\n\treadonly down?: 'none' | 'retired' | ((props: any) => any)\n}\n\n/**\n * A sequence of property migrations for a record type.\n *\n * Contains an ordered array of migrations that should be applied to transform\n * record properties from one version to another. Migrations can include both\n * property-specific migrations and standalone dependency declarations.\n *\n * @example\n * ```ts\n * const myShapeMigrations: TLPropsMigrations = {\n * sequence: [\n * {\n * id: 'com.myapp.shape.custom/1.0.0',\n * up: (props) => ({ ...props, version: 1 })\n * },\n * {\n * id: 'com.myapp.shape.custom/2.0.0',\n * up: (props) => ({ ...props, newFeature: true })\n * }\n * ]\n * }\n * ```\n *\n * @public\n */\nexport interface TLPropsMigrations {\n\treadonly sequence: Array<StandaloneDependsOn | TLPropsMigration>\n}\n\n/**\n * Processes property migrations for all record types in a schema.\n *\n * Takes a collection of record configurations and converts their migrations\n * into proper migration sequences that can be used by the store system.\n * Handles different migration formats including legacy migrations.\n *\n * @param typeName - The base type name for the records (e.g., 'shape', 'binding')\n * @param records - Record of type names to their schema configuration\n * @returns Array of processed migration sequences\n *\n * @example\n * ```ts\n * const shapeRecords = {\n * geo: { props: geoProps, migrations: geoMigrations },\n * arrow: { props: arrowProps, migrations: arrowMigrations }\n * }\n *\n * const sequences = processPropsMigrations('shape', shapeRecords)\n * ```\n *\n * @internal\n */\nexport function processPropsMigrations<R extends UnknownRecord & { type: string; props: object }>(\n\ttypeName: R['typeName'],\n\trecords: Record<string, SchemaPropsInfo>\n) {\n\tconst result: MigrationSequence[] = []\n\n\tfor (const [subType, { migrations }] of Object.entries(records)) {\n\t\tconst sequenceId = `com.tldraw.${typeName}.${subType}`\n\t\tif (!migrations) {\n\t\t\t// provide empty migrations sequence to allow for future migrations\n\t\t\tresult.push(\n\t\t\t\tcreateMigrationSequence({\n\t\t\t\t\tsequenceId,\n\t\t\t\t\tretroactive: true,\n\t\t\t\t\tsequence: [],\n\t\t\t\t})\n\t\t\t)\n\t\t} else if ('sequenceId' in migrations) {\n\t\t\tassert(\n\t\t\t\tsequenceId === migrations.sequenceId,\n\t\t\t\t`sequenceId mismatch for ${subType} ${RecordType} migrations. Expected '${sequenceId}', got '${migrations.sequenceId}'`\n\t\t\t)\n\t\t\tresult.push(migrations)\n\t\t} else if ('sequence' in migrations) {\n\t\t\tresult.push(\n\t\t\t\tcreateMigrationSequence({\n\t\t\t\t\tsequenceId,\n\t\t\t\t\tretroactive: true,\n\t\t\t\t\tsequence: migrations.sequence.map((m) =>\n\t\t\t\t\t\t'id' in m ? createPropsMigration(typeName, subType, m) : m\n\t\t\t\t\t),\n\t\t\t\t})\n\t\t\t)\n\t\t} else {\n\t\t\t// legacy migrations, will be removed in the future\n\t\t\tresult.push(\n\t\t\t\tcreateMigrationSequence({\n\t\t\t\t\tsequenceId,\n\t\t\t\t\tretroactive: true,\n\t\t\t\t\tsequence: Object.keys(migrations.migrators)\n\t\t\t\t\t\t.map((k) => Number(k))\n\t\t\t\t\t\t.sort((a: number, b: number) => a - b)\n\t\t\t\t\t\t.map(\n\t\t\t\t\t\t\t(version): Migration => ({\n\t\t\t\t\t\t\t\tid: `${sequenceId}/${version}`,\n\t\t\t\t\t\t\t\tscope: 'record',\n\t\t\t\t\t\t\t\tfilter: (r) => r.typeName === typeName && (r as R).type === subType,\n\t\t\t\t\t\t\t\tup: (record: any) => {\n\t\t\t\t\t\t\t\t\tconst result = migrations.migrators[version].up(record)\n\t\t\t\t\t\t\t\t\tif (result) {\n\t\t\t\t\t\t\t\t\t\treturn result\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\tdown: (record: any) => {\n\t\t\t\t\t\t\t\t\tconst result = migrations.migrators[version].down(record)\n\t\t\t\t\t\t\t\t\tif (result) {\n\t\t\t\t\t\t\t\t\t\treturn result\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t})\n\t\t\t\t\t\t),\n\t\t\t\t})\n\t\t\t)\n\t\t}\n\t}\n\n\treturn result\n}\n\n/**\n * Creates a store migration from a props migration definition.\n *\n * Converts a high-level property migration into a low-level store migration\n * that can be applied to records. The resulting migration will only affect\n * records of the specified type and subtype.\n *\n * @param typeName - The base type name (e.g., 'shape', 'binding')\n * @param subType - The specific subtype (e.g., 'geo', 'arrow')\n * @param m - The property migration definition\n * @returns A store migration that applies the property transformation\n *\n * @example\n * ```ts\n * const propsMigration: TLPropsMigration = {\n * id: 'com.myapp.shape.custom/1.0.0',\n * up: (props) => ({ ...props, color: 'blue' })\n * }\n *\n * const storeMigration = createPropsMigration('shape', 'custom', propsMigration)\n * ```\n *\n * @internal\n */\nexport function createPropsMigration<R extends UnknownRecord & { type: string; props: object }>(\n\ttypeName: R['typeName'],\n\tsubType: R['type'],\n\tm: TLPropsMigration\n): Migration {\n\treturn {\n\t\tid: m.id,\n\t\tdependsOn: m.dependsOn,\n\t\tscope: 'record',\n\t\tfilter: (r) => r.typeName === typeName && (r as R).type === subType,\n\t\tup: (record: any) => {\n\t\t\tconst result = m.up(record.props)\n\t\t\tif (result) {\n\t\t\t\trecord.props = result\n\t\t\t}\n\t\t},\n\t\tdown:\n\t\t\ttypeof m.down === 'function'\n\t\t\t\t? (record: any) => {\n\t\t\t\t\t\tconst result = (m.down as (props: any) => any)(record.props)\n\t\t\t\t\t\tif (result) {\n\t\t\t\t\t\t\trecord.props = result\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t: undefined,\n\t}\n}\n"],
4
+ "sourcesContent": ["import {\n\tMigration,\n\tMigrationId,\n\tMigrationSequence,\n\tRecordType,\n\tStandaloneDependsOn,\n\tUnknownRecord,\n\tcreateMigrationSequence,\n} from '@tldraw/store'\nimport { MakeUndefinedOptional, assert } from '@tldraw/utils'\nimport { T } from '@tldraw/validate'\nimport { SchemaPropsInfo } from './createTLSchema'\n\n/**\n * Maps a record's property types to their corresponding validators.\n *\n * This utility type takes a record type with a `props` object and creates\n * a mapping where each property key maps to a validator for that property's type.\n * This is used to define validation schemas for record properties.\n *\n * @example\n * ```ts\n * interface MyShape extends TLBaseShape<'custom', { width: number; color: string }> {}\n *\n * // Define validators for the shape properties\n * const myShapeProps: RecordProps<MyShape> = {\n * width: T.number,\n * color: T.string\n * }\n * ```\n *\n * @public\n */\nexport type RecordProps<R extends UnknownRecord & { props: object }> = {\n\t[K in keyof R['props']]: T.Validatable<R['props'][K]>\n}\n\n/**\n * Extracts the TypeScript types from a record properties configuration.\n *\n * Takes a configuration object where values are validators and returns the\n * corresponding TypeScript types, with undefined values made optional.\n *\n * @example\n * ```ts\n * const shapePropsConfig = {\n * width: T.number,\n * height: T.number,\n * color: T.optional(T.string)\n * }\n *\n * type ShapeProps = RecordPropsType<typeof shapePropsConfig>\n * // Result: { width: number; height: number; color?: string }\n * ```\n *\n * @public\n */\nexport type RecordPropsType<Config extends Record<string, T.Validatable<any>>> =\n\tMakeUndefinedOptional<{\n\t\t[K in keyof Config]: T.TypeOf<Config[K]>\n\t}>\n\n/**\n * A migration definition for shape or record properties.\n *\n * Defines how to transform record properties when migrating between schema versions.\n * Each migration has an `up` function to upgrade data and an optional `down` function\n * to downgrade data if needed.\n *\n * @example\n * ```ts\n * const addColorMigration: TLPropsMigration = {\n * id: 'com.myapp.shape.custom/1.0.0',\n * up: (props) => {\n * // Add a default color property\n * return { ...props, color: 'black' }\n * },\n * down: (props) => {\n * // Remove the color property\n * const { color, ...rest } = props\n * return rest\n * }\n * }\n * ```\n *\n * @public\n */\nexport interface TLPropsMigration {\n\treadonly id: MigrationId\n\treadonly dependsOn?: MigrationId[]\n\t// eslint-disable-next-line tldraw/method-signature-style\n\treadonly up: (props: any) => any\n\t/**\n\t * If a down migration was deployed more than a couple of months ago it should be safe to retire it.\n\t * We only really need them to smooth over the transition between versions, and some folks do keep\n\t * browser tabs open for months without refreshing, but at a certain point that kind of behavior is\n\t * on them. Plus anyway recently chrome has started to actually kill tabs that are open for too long\n\t * rather than just suspending them, so if other browsers follow suit maybe it's less of a concern.\n\t *\n\t * @public\n\t */\n\treadonly down?: 'none' | 'retired' | ((props: any) => any)\n}\n\n/**\n * A sequence of property migrations for a record type.\n *\n * Contains an ordered array of migrations that should be applied to transform\n * record properties from one version to another. Migrations can include both\n * property-specific migrations and standalone dependency declarations.\n *\n * @example\n * ```ts\n * const myShapeMigrations: TLPropsMigrations = {\n * sequence: [\n * {\n * id: 'com.myapp.shape.custom/1.0.0',\n * up: (props) => ({ ...props, version: 1 })\n * },\n * {\n * id: 'com.myapp.shape.custom/2.0.0',\n * up: (props) => ({ ...props, newFeature: true })\n * }\n * ]\n * }\n * ```\n *\n * @public\n */\nexport interface TLPropsMigrations {\n\treadonly sequence: Array<StandaloneDependsOn | TLPropsMigration>\n}\n\n/**\n * Processes property migrations for all record types in a schema.\n *\n * Takes a collection of record configurations and converts their migrations\n * into proper migration sequences that can be used by the store system.\n * Handles different migration formats including legacy migrations.\n *\n * @param typeName - The base type name for the records (e.g., 'shape', 'binding')\n * @param records - Record of type names to their schema configuration\n * @returns Array of processed migration sequences\n *\n * @example\n * ```ts\n * const shapeRecords = {\n * geo: { props: geoProps, migrations: geoMigrations },\n * arrow: { props: arrowProps, migrations: arrowMigrations }\n * }\n *\n * const sequences = processPropsMigrations('shape', shapeRecords)\n * ```\n *\n * @internal\n */\nexport function processPropsMigrations<R extends UnknownRecord & { type: string; props: object }>(\n\ttypeName: R['typeName'],\n\trecords: Record<string, SchemaPropsInfo>\n) {\n\tconst result: MigrationSequence[] = []\n\n\tfor (const [subType, { migrations }] of Object.entries(records)) {\n\t\tconst sequenceId = `com.tldraw.${typeName}.${subType}`\n\t\tif (!migrations) {\n\t\t\t// provide empty migrations sequence to allow for future migrations\n\t\t\tresult.push(\n\t\t\t\tcreateMigrationSequence({\n\t\t\t\t\tsequenceId,\n\t\t\t\t\tretroactive: true,\n\t\t\t\t\tsequence: [],\n\t\t\t\t})\n\t\t\t)\n\t\t} else if ('sequenceId' in migrations) {\n\t\t\tassert(\n\t\t\t\tsequenceId === migrations.sequenceId,\n\t\t\t\t`sequenceId mismatch for ${subType} ${RecordType} migrations. Expected '${sequenceId}', got '${migrations.sequenceId}'`\n\t\t\t)\n\t\t\tresult.push(migrations)\n\t\t} else if ('sequence' in migrations) {\n\t\t\tresult.push(\n\t\t\t\tcreateMigrationSequence({\n\t\t\t\t\tsequenceId,\n\t\t\t\t\tretroactive: true,\n\t\t\t\t\tsequence: migrations.sequence.map((m) =>\n\t\t\t\t\t\t'id' in m ? createPropsMigration(typeName, subType, m) : m\n\t\t\t\t\t),\n\t\t\t\t})\n\t\t\t)\n\t\t} else {\n\t\t\t// legacy migrations, will be removed in the future\n\t\t\tresult.push(\n\t\t\t\tcreateMigrationSequence({\n\t\t\t\t\tsequenceId,\n\t\t\t\t\tretroactive: true,\n\t\t\t\t\tsequence: Object.keys(migrations.migrators)\n\t\t\t\t\t\t.map((k) => Number(k))\n\t\t\t\t\t\t.sort((a: number, b: number) => a - b)\n\t\t\t\t\t\t.map(\n\t\t\t\t\t\t\t(version): Migration => ({\n\t\t\t\t\t\t\t\tid: `${sequenceId}/${version}`,\n\t\t\t\t\t\t\t\tscope: 'record',\n\t\t\t\t\t\t\t\tfilter: (r) => r.typeName === typeName && (r as R).type === subType,\n\t\t\t\t\t\t\t\tup: (record: any) => {\n\t\t\t\t\t\t\t\t\tconst result = migrations.migrators[version].up(record)\n\t\t\t\t\t\t\t\t\tif (result) {\n\t\t\t\t\t\t\t\t\t\treturn result\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\tdown: (record: any) => {\n\t\t\t\t\t\t\t\t\tconst result = migrations.migrators[version].down(record)\n\t\t\t\t\t\t\t\t\tif (result) {\n\t\t\t\t\t\t\t\t\t\treturn result\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t})\n\t\t\t\t\t\t),\n\t\t\t\t})\n\t\t\t)\n\t\t}\n\t}\n\n\treturn result\n}\n\n/**\n * Creates a store migration from a props migration definition.\n *\n * Converts a high-level property migration into a low-level store migration\n * that can be applied to records. The resulting migration will only affect\n * records of the specified type and subtype.\n *\n * @param typeName - The base type name (e.g., 'shape', 'binding')\n * @param subType - The specific subtype (e.g., 'geo', 'arrow')\n * @param m - The property migration definition\n * @returns A store migration that applies the property transformation\n *\n * @example\n * ```ts\n * const propsMigration: TLPropsMigration = {\n * id: 'com.myapp.shape.custom/1.0.0',\n * up: (props) => ({ ...props, color: 'blue' })\n * }\n *\n * const storeMigration = createPropsMigration('shape', 'custom', propsMigration)\n * ```\n *\n * @internal\n */\nexport function createPropsMigration<R extends UnknownRecord & { type: string; props: object }>(\n\ttypeName: R['typeName'],\n\tsubType: R['type'],\n\tm: TLPropsMigration\n): Migration {\n\treturn {\n\t\tid: m.id,\n\t\tdependsOn: m.dependsOn,\n\t\tscope: 'record',\n\t\tfilter: (r) => r.typeName === typeName && (r as R).type === subType,\n\t\tup: (record: any) => {\n\t\t\tconst result = m.up(record.props)\n\t\t\tif (result) {\n\t\t\t\trecord.props = result\n\t\t\t}\n\t\t},\n\t\tdown:\n\t\t\ttypeof m.down === 'function'\n\t\t\t\t? (record: any) => {\n\t\t\t\t\t\tconst result = (m.down as (props: any) => any)(record.props)\n\t\t\t\t\t\tif (result) {\n\t\t\t\t\t\t\trecord.props = result\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t: undefined,\n\t}\n}\n"],
5
5
  "mappings": "AAAA;AAAA,EAIC;AAAA,EAGA;AAAA,OACM;AACP,SAAgC,cAAc;AAmJvC,SAAS,uBACf,UACA,SACC;AACD,QAAM,SAA8B,CAAC;AAErC,aAAW,CAAC,SAAS,EAAE,WAAW,CAAC,KAAK,OAAO,QAAQ,OAAO,GAAG;AAChE,UAAM,aAAa,cAAc,QAAQ,IAAI,OAAO;AACpD,QAAI,CAAC,YAAY;AAEhB,aAAO;AAAA,QACN,wBAAwB;AAAA,UACvB;AAAA,UACA,aAAa;AAAA,UACb,UAAU,CAAC;AAAA,QACZ,CAAC;AAAA,MACF;AAAA,IACD,WAAW,gBAAgB,YAAY;AACtC;AAAA,QACC,eAAe,WAAW;AAAA,QAC1B,2BAA2B,OAAO,IAAI,UAAU,0BAA0B,UAAU,WAAW,WAAW,UAAU;AAAA,MACrH;AACA,aAAO,KAAK,UAAU;AAAA,IACvB,WAAW,cAAc,YAAY;AACpC,aAAO;AAAA,QACN,wBAAwB;AAAA,UACvB;AAAA,UACA,aAAa;AAAA,UACb,UAAU,WAAW,SAAS;AAAA,YAAI,CAAC,MAClC,QAAQ,IAAI,qBAAqB,UAAU,SAAS,CAAC,IAAI;AAAA,UAC1D;AAAA,QACD,CAAC;AAAA,MACF;AAAA,IACD,OAAO;AAEN,aAAO;AAAA,QACN,wBAAwB;AAAA,UACvB;AAAA,UACA,aAAa;AAAA,UACb,UAAU,OAAO,KAAK,WAAW,SAAS,EACxC,IAAI,CAAC,MAAM,OAAO,CAAC,CAAC,EACpB,KAAK,CAAC,GAAW,MAAc,IAAI,CAAC,EACpC;AAAA,YACA,CAAC,aAAwB;AAAA,cACxB,IAAI,GAAG,UAAU,IAAI,OAAO;AAAA,cAC5B,OAAO;AAAA,cACP,QAAQ,CAAC,MAAM,EAAE,aAAa,YAAa,EAAQ,SAAS;AAAA,cAC5D,IAAI,CAAC,WAAgB;AACpB,sBAAMA,UAAS,WAAW,UAAU,OAAO,EAAE,GAAG,MAAM;AACtD,oBAAIA,SAAQ;AACX,yBAAOA;AAAA,gBACR;AAAA,cACD;AAAA,cACA,MAAM,CAAC,WAAgB;AACtB,sBAAMA,UAAS,WAAW,UAAU,OAAO,EAAE,KAAK,MAAM;AACxD,oBAAIA,SAAQ;AACX,yBAAOA;AAAA,gBACR;AAAA,cACD;AAAA,YACD;AAAA,UACD;AAAA,QACF,CAAC;AAAA,MACF;AAAA,IACD;AAAA,EACD;AAEA,SAAO;AACR;AA0BO,SAAS,qBACf,UACA,SACA,GACY;AACZ,SAAO;AAAA,IACN,IAAI,EAAE;AAAA,IACN,WAAW,EAAE;AAAA,IACb,OAAO;AAAA,IACP,QAAQ,CAAC,MAAM,EAAE,aAAa,YAAa,EAAQ,SAAS;AAAA,IAC5D,IAAI,CAAC,WAAgB;AACpB,YAAM,SAAS,EAAE,GAAG,OAAO,KAAK;AAChC,UAAI,QAAQ;AACX,eAAO,QAAQ;AAAA,MAChB;AAAA,IACD;AAAA,IACA,MACC,OAAO,EAAE,SAAS,aACf,CAAC,WAAgB;AACjB,YAAM,SAAU,EAAE,KAA6B,OAAO,KAAK;AAC3D,UAAI,QAAQ;AACX,eAAO,QAAQ;AAAA,MAChB;AAAA,IACD,IACC;AAAA,EACL;AACD;",
6
6
  "names": ["result"]
7
7
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@tldraw/tlschema",
3
3
  "description": "tldraw infinite canvas SDK (schema).",
4
- "version": "4.6.0-internal.c7df3c92455a",
4
+ "version": "4.6.0-internal.e29318c66fb0",
5
5
  "author": {
6
6
  "name": "tldraw Inc.",
7
7
  "email": "hello@tldraw.com"
@@ -35,13 +35,13 @@
35
35
  "test-ci": "yarn run -T vitest run --passWithNoTests",
36
36
  "test": "yarn run -T vitest --passWithNoTests",
37
37
  "test-coverage": "yarn run -T vitest run --coverage --passWithNoTests",
38
- "format": "yarn run -T prettier --write --cache \"src/**/*.{ts,tsx,js,jsx,json,md}\"",
38
+ "format": "yarn run -T oxfmt \"src/**/*.{ts,tsx,js,jsx,json,md}\"",
39
39
  "build": "yarn run -T tsx ../../internal/scripts/build-package.ts",
40
40
  "build-api": "yarn run -T tsx ../../internal/scripts/build-api.ts",
41
41
  "prepack": "yarn run -T tsx ../../internal/scripts/prepack.ts",
42
42
  "postpack": "../../internal/scripts/postpack.sh",
43
43
  "pack-tarball": "yarn pack",
44
- "lint": "yarn run -T tsx ../../internal/scripts/lint.ts"
44
+ "lint": "cd ../.. && yarn run -T oxlint packages/tlschema"
45
45
  },
46
46
  "devDependencies": {
47
47
  "kleur": "^4.1.5",
@@ -50,10 +50,10 @@
50
50
  "vitest": "^3.2.4"
51
51
  },
52
52
  "dependencies": {
53
- "@tldraw/state": "4.6.0-internal.c7df3c92455a",
54
- "@tldraw/store": "4.6.0-internal.c7df3c92455a",
55
- "@tldraw/utils": "4.6.0-internal.c7df3c92455a",
56
- "@tldraw/validate": "4.6.0-internal.c7df3c92455a"
53
+ "@tldraw/state": "4.6.0-internal.e29318c66fb0",
54
+ "@tldraw/store": "4.6.0-internal.e29318c66fb0",
55
+ "@tldraw/utils": "4.6.0-internal.e29318c66fb0",
56
+ "@tldraw/validate": "4.6.0-internal.e29318c66fb0"
57
57
  },
58
58
  "peerDependencies": {
59
59
  "react": "^18.2.0 || ^19.2.1",
@@ -71,7 +71,7 @@ export interface CustomRecordInfo {
71
71
  * Called when creating new records to provide initial values for any properties
72
72
  * not explicitly provided during creation.
73
73
  */
74
- // eslint-disable-next-line @typescript-eslint/method-signature-style
74
+ // eslint-disable-next-line tldraw/method-signature-style
75
75
  createDefaultProperties?: () => Record<string, unknown>
76
76
  }
77
77
 
@@ -35,8 +35,10 @@ import { TLShapeId } from './TLShape'
35
35
  *
36
36
  * @public
37
37
  */
38
- export interface TLInstancePageState
39
- extends BaseRecord<'instance_page_state', TLInstancePageStateId> {
38
+ export interface TLInstancePageState extends BaseRecord<
39
+ 'instance_page_state',
40
+ TLInstancePageStateId
41
+ > {
40
42
  pageId: RecordId<TLPage>
41
43
  selectedShapeIds: TLShapeId[]
42
44
  hintingShapeIds: TLShapeId[]
@@ -88,7 +88,7 @@ export type RecordPropsType<Config extends Record<string, T.Validatable<any>>> =
88
88
  export interface TLPropsMigration {
89
89
  readonly id: MigrationId
90
90
  readonly dependsOn?: MigrationId[]
91
- // eslint-disable-next-line @typescript-eslint/method-signature-style
91
+ // eslint-disable-next-line tldraw/method-signature-style
92
92
  readonly up: (props: any) => any
93
93
  /**
94
94
  * If a down migration was deployed more than a couple of months ago it should be safe to retire it.