@tldraw/tlschema 4.5.2 → 4.6.0-canary.4ec045c286e1
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/createTLSchema.js +27 -1
- package/dist-cjs/createTLSchema.js.map +2 -2
- package/dist-cjs/index.d.ts +265 -11
- package/dist-cjs/index.js +7 -1
- package/dist-cjs/index.js.map +2 -2
- package/dist-cjs/records/TLCustomRecord.js +102 -0
- package/dist-cjs/records/TLCustomRecord.js.map +7 -0
- package/dist-cjs/records/TLRecord.js.map +1 -1
- package/dist-esm/createTLSchema.mjs +30 -1
- package/dist-esm/createTLSchema.mjs.map +2 -2
- package/dist-esm/index.d.mts +265 -11
- package/dist-esm/index.mjs +13 -1
- package/dist-esm/index.mjs.map +2 -2
- package/dist-esm/records/TLCustomRecord.mjs +85 -0
- package/dist-esm/records/TLCustomRecord.mjs.map +7 -0
- package/package.json +5 -5
- package/src/createTLSchema.ts +49 -8
- package/src/index.ts +15 -1
- package/src/records/TLCustomRecord.ts +297 -0
- package/src/records/TLRecord.ts +81 -12
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
var TLCustomRecord_exports = {};
|
|
20
|
+
__export(TLCustomRecord_exports, {
|
|
21
|
+
createCustomRecordId: () => createCustomRecordId,
|
|
22
|
+
createCustomRecordMigrationIds: () => createCustomRecordMigrationIds,
|
|
23
|
+
createCustomRecordMigrationSequence: () => createCustomRecordMigrationSequence,
|
|
24
|
+
createCustomRecordType: () => createCustomRecordType,
|
|
25
|
+
isCustomRecord: () => isCustomRecord,
|
|
26
|
+
isCustomRecordId: () => isCustomRecordId,
|
|
27
|
+
processCustomRecordMigrations: () => processCustomRecordMigrations
|
|
28
|
+
});
|
|
29
|
+
module.exports = __toCommonJS(TLCustomRecord_exports);
|
|
30
|
+
var import_store = require("@tldraw/store");
|
|
31
|
+
var import_utils = require("@tldraw/utils");
|
|
32
|
+
function createCustomRecordType(typeName, config) {
|
|
33
|
+
return (0, import_store.createRecordType)(typeName, {
|
|
34
|
+
scope: config.scope,
|
|
35
|
+
validator: config.validator
|
|
36
|
+
}).withDefaultProperties(config.createDefaultProperties ?? (() => ({})));
|
|
37
|
+
}
|
|
38
|
+
function processCustomRecordMigrations(records) {
|
|
39
|
+
const result = [];
|
|
40
|
+
for (const [typeName, config] of Object.entries(records)) {
|
|
41
|
+
const sequenceId = `com.tldraw.${typeName}`;
|
|
42
|
+
const { migrations } = config;
|
|
43
|
+
if (!migrations) {
|
|
44
|
+
result.push(
|
|
45
|
+
(0, import_store.createMigrationSequence)({
|
|
46
|
+
sequenceId,
|
|
47
|
+
retroactive: true,
|
|
48
|
+
sequence: []
|
|
49
|
+
})
|
|
50
|
+
);
|
|
51
|
+
} else if ("sequenceId" in migrations) {
|
|
52
|
+
(0, import_utils.assert)(
|
|
53
|
+
sequenceId === migrations.sequenceId,
|
|
54
|
+
`sequenceId mismatch for ${typeName} custom record migrations. Expected '${sequenceId}', got '${migrations.sequenceId}'`
|
|
55
|
+
);
|
|
56
|
+
result.push(migrations);
|
|
57
|
+
} else if ("sequence" in migrations) {
|
|
58
|
+
result.push(
|
|
59
|
+
(0, import_store.createMigrationSequence)({
|
|
60
|
+
sequenceId,
|
|
61
|
+
retroactive: true,
|
|
62
|
+
sequence: migrations.sequence.map((m) => {
|
|
63
|
+
if (!("id" in m)) return m;
|
|
64
|
+
return {
|
|
65
|
+
id: m.id,
|
|
66
|
+
dependsOn: m.dependsOn,
|
|
67
|
+
scope: "record",
|
|
68
|
+
filter: (r) => r.typeName === typeName,
|
|
69
|
+
up: (record) => {
|
|
70
|
+
const result2 = m.up(record);
|
|
71
|
+
if (result2) return result2;
|
|
72
|
+
},
|
|
73
|
+
down: typeof m.down === "function" ? (record) => {
|
|
74
|
+
const result2 = m.down(record);
|
|
75
|
+
if (result2) return result2;
|
|
76
|
+
} : void 0
|
|
77
|
+
};
|
|
78
|
+
})
|
|
79
|
+
})
|
|
80
|
+
);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
return result;
|
|
84
|
+
}
|
|
85
|
+
function createCustomRecordMigrationIds(recordType, ids) {
|
|
86
|
+
return (0, import_utils.mapObjectMapValues)(ids, (_k, v) => `com.tldraw.${recordType}/${v}`);
|
|
87
|
+
}
|
|
88
|
+
function createCustomRecordMigrationSequence(migrations) {
|
|
89
|
+
return migrations;
|
|
90
|
+
}
|
|
91
|
+
function createCustomRecordId(typeName, id) {
|
|
92
|
+
return `${typeName}:${id ?? (0, import_utils.uniqueId)()}`;
|
|
93
|
+
}
|
|
94
|
+
function isCustomRecordId(typeName, id) {
|
|
95
|
+
if (!id) return false;
|
|
96
|
+
return id.startsWith(`${typeName}:`);
|
|
97
|
+
}
|
|
98
|
+
function isCustomRecord(typeName, record) {
|
|
99
|
+
if (!record) return false;
|
|
100
|
+
return record.typeName === typeName;
|
|
101
|
+
}
|
|
102
|
+
//# sourceMappingURL=TLCustomRecord.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 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"],
|
|
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
|
+
"names": ["result"]
|
|
7
|
+
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/records/TLRecord.ts"],
|
|
4
|
-
"sourcesContent": ["import { TLAsset } from './TLAsset'\nimport { TLBinding } from './TLBinding'\nimport { TLCamera } from './TLCamera'\nimport { TLDocument } from './TLDocument'\nimport { TLInstance } from './TLInstance'\nimport { TLPage } from './TLPage'\nimport { TLInstancePageState } from './TLPageState'\nimport { TLPointer } from './TLPointer'\nimport { TLInstancePresence } from './TLPresence'\nimport { TLShape } from './TLShape'\n\n/**\n * Union type representing all possible record types in a tldraw store.\n * This includes both persistent records (documents, pages, shapes, assets, bindings)\n * and session/presence records (cameras, instances, pointers, page states).\n *\n * Records are organized by scope:\n * - **document**: Persisted across sessions (shapes, pages, assets, bindings, documents)\n * - **session**: Local to current session (cameras, instances, page states)\n * - **presence**: Ephemeral user presence data (pointers, instance presence)\n *\n * @example\n * ```ts\n * // Function that works with any record type\n * function processRecord(record: TLRecord) {\n * switch (record.typeName) {\n * case 'shape':\n * console.log(`Shape: ${record.type} at (${record.x}, ${record.y})`)\n * break\n * case 'page':\n * console.log(`Page: ${record.name}`)\n * break\n * case 'asset':\n * console.log(`Asset: ${record.type}`)\n * break\n * case 'camera':\n * console.log(`Camera at (${record.x}, ${record.y}) zoom: ${record.z}`)\n * break\n * // ... handle other record types\n * }\n * }\n *\n * // Get all records from store\n * const allRecords: TLRecord[] = store.allRecords()\n *\n * // Filter by record type using type guards\n * import { isShape, isPage, isAsset } from '@tldraw/tlschema'\n * const shapes = allRecords.filter(isShape)\n * const pages = allRecords.filter(isPage)\n * const assets = allRecords.filter(isAsset)\n * ```\n *\n * @public\n */\nexport type TLRecord
|
|
4
|
+
"sourcesContent": ["import { TLAsset } from './TLAsset'\nimport { TLBinding } from './TLBinding'\nimport { TLCamera } from './TLCamera'\nimport { TLDocument } from './TLDocument'\nimport { TLInstance } from './TLInstance'\nimport { TLPage } from './TLPage'\nimport { TLInstancePageState } from './TLPageState'\nimport { TLPointer } from './TLPointer'\nimport { TLInstancePresence } from './TLPresence'\nimport { TLShape } from './TLShape'\n\n/**\n * Interface for extending tldraw with custom record types via TypeScript module augmentation.\n *\n * Custom record types allow you to add entirely new data types to the tldraw store that\n * don't fit into the existing shape, binding, or asset categories. Each key in this\n * interface becomes a new record type name, and the value should be your full record type.\n *\n * @example\n * ```ts\n * import { BaseRecord, RecordId } from '@tldraw/store'\n *\n * // Define your custom record type\n * interface TLComment extends BaseRecord<'comment', RecordId<TLComment>> {\n * text: string\n * shapeId: TLShapeId\n * authorId: string\n * createdAt: number\n * }\n *\n * // Augment the global record props map\n * declare module '@tldraw/tlschema' {\n * interface TLGlobalRecordPropsMap {\n * comment: TLComment\n * }\n * }\n *\n * // Now TLRecord includes your custom comment type\n * // and you can use it with createTLSchema()\n * ```\n *\n * @public\n */\n// eslint-disable-next-line @typescript-eslint/no-empty-object-type\nexport interface TLGlobalRecordPropsMap {}\n\n/**\n * Union type of all built-in tldraw record types.\n *\n * This includes persistent records (documents, pages, shapes, assets, bindings)\n * and session/presence records (cameras, instances, pointers, page states).\n *\n * @public\n */\nexport type TLDefaultRecord =\n\t| TLAsset\n\t| TLBinding\n\t| TLCamera\n\t| TLDocument\n\t| TLInstance\n\t| TLInstancePageState\n\t| TLPage\n\t| TLShape\n\t| TLInstancePresence\n\t| TLPointer\n\n/**\n * Index type that maps custom record type names to their record types.\n *\n * Similar to TLIndexedShapes and TLIndexedBindings, this type creates a mapping\n * from type name keys to their corresponding record types, filtering out any\n * disabled types (those set to null or undefined in TLGlobalRecordPropsMap).\n *\n * @public\n */\n// prettier-ignore\nexport type TLIndexedRecords = {\n\t[K in keyof TLGlobalRecordPropsMap as TLGlobalRecordPropsMap[K] extends null | undefined\n\t\t? never\n\t\t: K]: TLGlobalRecordPropsMap[K]\n}\n\n/**\n * Union type representing a custom record from the TLGlobalRecordPropsMap.\n *\n * @public\n */\nexport type TLCustomRecord = TLIndexedRecords[keyof TLIndexedRecords]\n\n/**\n * Union type representing all possible record types in a tldraw store.\n * This includes both persistent records (documents, pages, shapes, assets, bindings)\n * and session/presence records (cameras, instances, pointers, page states),\n * as well as any custom record types added via TLGlobalRecordPropsMap augmentation.\n *\n * Records are organized by scope:\n * - **document**: Persisted across sessions (shapes, pages, assets, bindings, documents)\n * - **session**: Local to current session (cameras, instances, page states)\n * - **presence**: Ephemeral user presence data (pointers, instance presence)\n *\n * @example\n * ```ts\n * // Function that works with any record type\n * function processRecord(record: TLRecord) {\n * switch (record.typeName) {\n * case 'shape':\n * console.log(`Shape: ${record.type} at (${record.x}, ${record.y})`)\n * break\n * case 'page':\n * console.log(`Page: ${record.name}`)\n * break\n * case 'asset':\n * console.log(`Asset: ${record.type}`)\n * break\n * case 'camera':\n * console.log(`Camera at (${record.x}, ${record.y}) zoom: ${record.z}`)\n * break\n * // ... handle other record types\n * }\n * }\n *\n * // Get all records from store\n * const allRecords: TLRecord[] = store.allRecords()\n *\n * // Filter by record type using type guards\n * import { isShape, isPage, isAsset } from '@tldraw/tlschema'\n * const shapes = allRecords.filter(isShape)\n * const pages = allRecords.filter(isPage)\n * const assets = allRecords.filter(isAsset)\n * ```\n *\n * @public\n */\nexport type TLRecord = TLDefaultRecord | TLCustomRecord\n"],
|
|
5
5
|
"mappings": ";;;;;;;;;;;;;;AAAA;AAAA;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -8,6 +8,10 @@ import { arrowBindingMigrations, arrowBindingProps } from "./bindings/TLArrowBin
|
|
|
8
8
|
import { AssetRecordType, assetMigrations } from "./records/TLAsset.mjs";
|
|
9
9
|
import { createBindingRecordType } from "./records/TLBinding.mjs";
|
|
10
10
|
import { CameraRecordType, cameraMigrations } from "./records/TLCamera.mjs";
|
|
11
|
+
import {
|
|
12
|
+
createCustomRecordType,
|
|
13
|
+
processCustomRecordMigrations
|
|
14
|
+
} from "./records/TLCustomRecord.mjs";
|
|
11
15
|
import { DocumentRecordType, documentMigrations } from "./records/TLDocument.mjs";
|
|
12
16
|
import { createInstanceRecordType, instanceMigrations } from "./records/TLInstance.mjs";
|
|
13
17
|
import { PageRecordType, pageMigrations } from "./records/TLPage.mjs";
|
|
@@ -55,6 +59,7 @@ const defaultBindingSchemas = {
|
|
|
55
59
|
function createTLSchema({
|
|
56
60
|
shapes = defaultShapeSchemas,
|
|
57
61
|
bindings = defaultBindingSchemas,
|
|
62
|
+
records = {},
|
|
58
63
|
migrations
|
|
59
64
|
} = {}) {
|
|
60
65
|
const stylesById = /* @__PURE__ */ new Map();
|
|
@@ -69,6 +74,28 @@ function createTLSchema({
|
|
|
69
74
|
const ShapeRecordType = createShapeRecordType(shapes);
|
|
70
75
|
const BindingRecordType = createBindingRecordType(bindings);
|
|
71
76
|
const InstanceRecordType = createInstanceRecordType(stylesById);
|
|
77
|
+
const builtInTypeNames = /* @__PURE__ */ new Set([
|
|
78
|
+
"asset",
|
|
79
|
+
"binding",
|
|
80
|
+
"camera",
|
|
81
|
+
"document",
|
|
82
|
+
"instance",
|
|
83
|
+
"instance_page_state",
|
|
84
|
+
"page",
|
|
85
|
+
"instance_presence",
|
|
86
|
+
"pointer",
|
|
87
|
+
"shape",
|
|
88
|
+
"store"
|
|
89
|
+
]);
|
|
90
|
+
const customRecordTypes = {};
|
|
91
|
+
for (const [typeName, config] of Object.entries(records)) {
|
|
92
|
+
if (builtInTypeNames.has(typeName)) {
|
|
93
|
+
throw new Error(
|
|
94
|
+
`Custom record type name '${typeName}' conflicts with tldraw's built-in record type of that name. Choose a different name instead.`
|
|
95
|
+
);
|
|
96
|
+
}
|
|
97
|
+
customRecordTypes[typeName] = createCustomRecordType(typeName, config);
|
|
98
|
+
}
|
|
72
99
|
return StoreSchema.create(
|
|
73
100
|
{
|
|
74
101
|
asset: AssetRecordType,
|
|
@@ -80,7 +107,8 @@ function createTLSchema({
|
|
|
80
107
|
page: PageRecordType,
|
|
81
108
|
instance_presence: InstancePresenceRecordType,
|
|
82
109
|
pointer: PointerRecordType,
|
|
83
|
-
shape: ShapeRecordType
|
|
110
|
+
shape: ShapeRecordType,
|
|
111
|
+
...customRecordTypes
|
|
84
112
|
},
|
|
85
113
|
{
|
|
86
114
|
migrations: [
|
|
@@ -99,6 +127,7 @@ function createTLSchema({
|
|
|
99
127
|
videoAssetMigrations,
|
|
100
128
|
...processPropsMigrations("shape", shapes),
|
|
101
129
|
...processPropsMigrations("binding", bindings),
|
|
130
|
+
...processCustomRecordMigrations(records),
|
|
102
131
|
...(migrations ?? [])
|
|
103
132
|
],
|
|
104
133
|
onValidationFailure,
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../src/createTLSchema.ts"],
|
|
4
|
-
"sourcesContent": ["import { LegacyMigrations, MigrationSequence, StoreSchema, StoreValidator } from '@tldraw/store'\nimport { objectMapValues } from '@tldraw/utils'\nimport { TLStoreProps, createIntegrityChecker, onValidationFailure } from './TLStore'\nimport { bookmarkAssetMigrations } from './assets/TLBookmarkAsset'\nimport { imageAssetMigrations } from './assets/TLImageAsset'\nimport { videoAssetMigrations } from './assets/TLVideoAsset'\nimport { arrowBindingMigrations, arrowBindingProps } from './bindings/TLArrowBinding'\nimport { AssetRecordType, assetMigrations } from './records/TLAsset'\nimport { TLBinding, TLDefaultBinding, createBindingRecordType } from './records/TLBinding'\nimport { CameraRecordType, cameraMigrations } from './records/TLCamera'\nimport { DocumentRecordType, documentMigrations } from './records/TLDocument'\nimport { createInstanceRecordType, instanceMigrations } from './records/TLInstance'\nimport { PageRecordType, pageMigrations } from './records/TLPage'\nimport { InstancePageStateRecordType, instancePageStateMigrations } from './records/TLPageState'\nimport { PointerRecordType, pointerMigrations } from './records/TLPointer'\nimport { InstancePresenceRecordType, instancePresenceMigrations } from './records/TLPresence'\nimport { TLRecord } from './records/TLRecord'\nimport {\n\tTLDefaultShape,\n\tTLShape,\n\tcreateShapeRecordType,\n\tgetShapePropKeysByStyle,\n\trootShapeMigrations,\n} from './records/TLShape'\nimport { RecordProps, TLPropsMigrations, processPropsMigrations } from './recordsWithProps'\nimport { arrowShapeMigrations, arrowShapeProps } from './shapes/TLArrowShape'\nimport { TLBaseShape } from './shapes/TLBaseShape'\nimport { bookmarkShapeMigrations, bookmarkShapeProps } from './shapes/TLBookmarkShape'\nimport { drawShapeMigrations, drawShapeProps } from './shapes/TLDrawShape'\nimport { embedShapeMigrations, embedShapeProps } from './shapes/TLEmbedShape'\nimport { frameShapeMigrations, frameShapeProps } from './shapes/TLFrameShape'\nimport { geoShapeMigrations, geoShapeProps } from './shapes/TLGeoShape'\nimport { groupShapeMigrations, groupShapeProps } from './shapes/TLGroupShape'\nimport { highlightShapeMigrations, highlightShapeProps } from './shapes/TLHighlightShape'\nimport { imageShapeMigrations, imageShapeProps } from './shapes/TLImageShape'\nimport { lineShapeMigrations, lineShapeProps } from './shapes/TLLineShape'\nimport { noteShapeMigrations, noteShapeProps } from './shapes/TLNoteShape'\nimport { textShapeMigrations, textShapeProps } from './shapes/TLTextShape'\nimport { videoShapeMigrations, videoShapeProps } from './shapes/TLVideoShape'\nimport { storeMigrations } from './store-migrations'\nimport { StyleProp } from './styles/StyleProp'\n\n/**\n * Configuration information for a schema type (shape or binding), including its properties,\n * metadata, and migration sequences for data evolution over time.\n *\n * @public\n * @example\n * ```ts\n * import { arrowShapeMigrations, arrowShapeProps } from './shapes/TLArrowShape'\n *\n * const myShapeSchema: SchemaPropsInfo = {\n * migrations: arrowShapeMigrations,\n * props: arrowShapeProps,\n * meta: {\n * customField: T.string,\n * },\n * }\n * ```\n */\nexport interface SchemaPropsInfo {\n\t/**\n\t * Migration sequences for handling data evolution over time. Can be legacy migrations,\n\t * props-specific migrations, or general migration sequences.\n\t */\n\tmigrations?: LegacyMigrations | TLPropsMigrations | MigrationSequence\n\n\t/**\n\t * Validation schema for the shape or binding properties. Maps property names to their validators.\n\t */\n\tprops?: Record<string, StoreValidator<any>>\n\n\t/**\n\t * Validation schema for metadata fields. Maps metadata field names to their validators.\n\t */\n\tmeta?: Record<string, StoreValidator<any>>\n}\n\n/**\n * The complete schema definition for a tldraw store, encompassing all record types,\n * validation rules, and migration sequences. This schema defines the structure of\n * the persistent data model used by tldraw.\n *\n * @public\n * @example\n * ```ts\n * import { createTLSchema, defaultShapeSchemas } from '@tldraw/tlschema'\n * import { Store } from '@tldraw/store'\n *\n * const schema: TLSchema = createTLSchema({\n * shapes: defaultShapeSchemas,\n * })\n *\n * const store = new Store({ schema })\n * ```\n */\nexport type TLSchema = StoreSchema<TLRecord, TLStoreProps>\n\n/**\n * Default shape schema configurations for all built-in tldraw shape types.\n * Each shape type includes its validation props and migration sequences.\n *\n * This object contains schema information for:\n * - arrow: Directional lines that can bind to other shapes\n * - bookmark: Website bookmark cards with preview information\n * - draw: Freehand drawing paths created with drawing tools\n * - embed: Embedded content from external services (YouTube, Figma, etc.)\n * - frame: Container shapes for organizing content\n * - geo: Geometric shapes (rectangles, ellipses, triangles, etc.)\n * - group: Logical groupings of multiple shapes\n * - highlight: Highlighting strokes from the highlighter tool\n * - image: Raster image shapes referencing image assets\n * - line: Multi-point lines and splines\n * - note: Sticky note shapes with text content\n * - text: Rich text shapes with formatting support\n * - video: Video shapes referencing video assets\n *\n * @public\n * @example\n * ```ts\n * import { createTLSchema, defaultShapeSchemas } from '@tldraw/tlschema'\n *\n * // Use all default shapes\n * const schema = createTLSchema({\n * shapes: defaultShapeSchemas,\n * })\n *\n * // Use only specific default shapes\n * const minimalSchema = createTLSchema({\n * shapes: {\n * geo: defaultShapeSchemas.geo,\n * text: defaultShapeSchemas.text,\n * },\n * })\n * ```\n */\nexport const defaultShapeSchemas = {\n\tarrow: { migrations: arrowShapeMigrations, props: arrowShapeProps },\n\tbookmark: { migrations: bookmarkShapeMigrations, props: bookmarkShapeProps },\n\tdraw: { migrations: drawShapeMigrations, props: drawShapeProps },\n\tembed: { migrations: embedShapeMigrations, props: embedShapeProps },\n\tframe: { migrations: frameShapeMigrations, props: frameShapeProps },\n\tgeo: { migrations: geoShapeMigrations, props: geoShapeProps },\n\tgroup: { migrations: groupShapeMigrations, props: groupShapeProps },\n\thighlight: { migrations: highlightShapeMigrations, props: highlightShapeProps },\n\timage: { migrations: imageShapeMigrations, props: imageShapeProps },\n\tline: { migrations: lineShapeMigrations, props: lineShapeProps },\n\tnote: { migrations: noteShapeMigrations, props: noteShapeProps },\n\ttext: { migrations: textShapeMigrations, props: textShapeProps },\n\tvideo: { migrations: videoShapeMigrations, props: videoShapeProps },\n} satisfies {\n\t[T in TLDefaultShape['type']]: {\n\t\tmigrations: SchemaPropsInfo['migrations']\n\t\tprops: RecordProps<TLBaseShape<T, Extract<TLDefaultShape, { type: T }>['props']>>\n\t}\n}\n\n/**\n * Default binding schema configurations for all built-in tldraw binding types.\n * Bindings represent relationships between shapes, such as arrows connected to shapes.\n *\n * Currently includes:\n * - arrow: Bindings that connect arrow shapes to other shapes at specific anchor points\n *\n * @public\n * @example\n * ```ts\n * import { createTLSchema, defaultBindingSchemas } from '@tldraw/tlschema'\n *\n * // Use default bindings\n * const schema = createTLSchema({\n * bindings: defaultBindingSchemas,\n * })\n *\n * // Add custom binding alongside defaults\n * const customSchema = createTLSchema({\n * bindings: {\n * ...defaultBindingSchemas,\n * myCustomBinding: {\n * props: myCustomBindingProps,\n * migrations: myCustomBindingMigrations,\n * },\n * },\n * })\n * ```\n */\nexport const defaultBindingSchemas = {\n\tarrow: { migrations: arrowBindingMigrations, props: arrowBindingProps },\n} satisfies { [T in TLDefaultBinding['type']]: SchemaPropsInfo }\n\n/**\n * Creates a complete TLSchema for use with tldraw stores. This schema defines the structure,\n * validation, and migration sequences for all record types in a tldraw application.\n *\n * The schema includes all core record types (pages, cameras, instances, etc.) plus the\n * shape and binding types you specify. Style properties are automatically collected from\n * all shapes to ensure consistency across the application.\n *\n * @param options - Configuration options for the schema\n * - shapes - Shape schema configurations. Defaults to defaultShapeSchemas if not provided\n * - bindings - Binding schema configurations. Defaults to defaultBindingSchemas if not provided\n * - migrations - Additional migration sequences to include in the schema\n * @returns A complete TLSchema ready for use with Store creation\n *\n * @public\n * @example\n * ```ts\n * import { createTLSchema, defaultShapeSchemas, defaultBindingSchemas } from '@tldraw/tlschema'\n * import { Store } from '@tldraw/store'\n *\n * // Create schema with all default shapes and bindings\n * const schema = createTLSchema()\n *\n * // Create schema with custom shapes added\n * const customSchema = createTLSchema({\n * shapes: {\n * ...defaultShapeSchemas,\n * myCustomShape: {\n * props: myCustomShapeProps,\n * migrations: myCustomShapeMigrations,\n * },\n * },\n * })\n *\n * // Create schema with only specific shapes\n * const minimalSchema = createTLSchema({\n * shapes: {\n * geo: defaultShapeSchemas.geo,\n * text: defaultShapeSchemas.text,\n * },\n * bindings: defaultBindingSchemas,\n * })\n *\n * // Use the schema with a store\n * const store = new Store({\n * schema: customSchema,\n * props: {\n * defaultName: 'My Drawing',\n * },\n * })\n * ```\n */\nexport function createTLSchema({\n\tshapes = defaultShapeSchemas,\n\tbindings = defaultBindingSchemas,\n\tmigrations,\n}: {\n\tshapes?: Record<string, SchemaPropsInfo>\n\tbindings?: Record<string, SchemaPropsInfo>\n\tmigrations?: readonly MigrationSequence[]\n} = {}): TLSchema {\n\tconst stylesById = new Map<string, StyleProp<unknown>>()\n\tfor (const shape of objectMapValues(shapes)) {\n\t\tfor (const style of getShapePropKeysByStyle(shape.props ?? {}).keys()) {\n\t\t\tif (stylesById.has(style.id) && stylesById.get(style.id) !== style) {\n\t\t\t\tthrow new Error(`Multiple StyleProp instances with the same id: ${style.id}`)\n\t\t\t}\n\t\t\tstylesById.set(style.id, style)\n\t\t}\n\t}\n\n\tconst ShapeRecordType = createShapeRecordType(shapes)\n\tconst BindingRecordType = createBindingRecordType(bindings)\n\tconst InstanceRecordType = createInstanceRecordType(stylesById)\n\n\treturn StoreSchema.create(\n\t\t{\n\t\t\tasset: AssetRecordType,\n\t\t\tbinding: BindingRecordType,\n\t\t\tcamera: CameraRecordType,\n\t\t\tdocument: DocumentRecordType,\n\t\t\tinstance: InstanceRecordType,\n\t\t\tinstance_page_state: InstancePageStateRecordType,\n\t\t\tpage: PageRecordType,\n\t\t\tinstance_presence: InstancePresenceRecordType,\n\t\t\tpointer: PointerRecordType,\n\t\t\tshape: ShapeRecordType,\n\t\t},\n\t\t{\n\t\t\tmigrations: [\n\t\t\t\tstoreMigrations,\n\t\t\t\tassetMigrations,\n\t\t\t\tcameraMigrations,\n\t\t\t\tdocumentMigrations,\n\t\t\t\tinstanceMigrations,\n\t\t\t\tinstancePageStateMigrations,\n\t\t\t\tpageMigrations,\n\t\t\t\tinstancePresenceMigrations,\n\t\t\t\tpointerMigrations,\n\t\t\t\trootShapeMigrations,\n\n\t\t\t\tbookmarkAssetMigrations,\n\t\t\t\timageAssetMigrations,\n\t\t\t\tvideoAssetMigrations,\n\n\t\t\t\t...processPropsMigrations<TLShape>('shape', shapes),\n\t\t\t\t...processPropsMigrations<TLBinding>('binding', bindings),\n\n\t\t\t\t...(migrations ?? []),\n\t\t\t],\n\t\t\tonValidationFailure,\n\t\t\tcreateIntegrityChecker,\n\t\t}\n\t)\n}\n"],
|
|
5
|
-
"mappings": "AAAA,SAA8C,mBAAmC;AACjF,SAAS,uBAAuB;AAChC,SAAuB,wBAAwB,2BAA2B;AAC1E,SAAS,+BAA+B;AACxC,SAAS,4BAA4B;AACrC,SAAS,4BAA4B;AACrC,SAAS,wBAAwB,yBAAyB;AAC1D,SAAS,iBAAiB,uBAAuB;AACjD,SAAsC,+BAA+B;AACrE,SAAS,kBAAkB,wBAAwB;AACnD,SAAS,oBAAoB,0BAA0B;AACvD,SAAS,0BAA0B,0BAA0B;AAC7D,SAAS,gBAAgB,sBAAsB;AAC/C,SAAS,6BAA6B,mCAAmC;AACzE,SAAS,mBAAmB,yBAAyB;AACrD,SAAS,4BAA4B,kCAAkC;AAEvE;AAAA,EAGC;AAAA,EACA;AAAA,EACA;AAAA,OACM;AACP,SAAyC,8BAA8B;AACvE,SAAS,sBAAsB,uBAAuB;AAEtD,SAAS,yBAAyB,0BAA0B;AAC5D,SAAS,qBAAqB,sBAAsB;AACpD,SAAS,sBAAsB,uBAAuB;AACtD,SAAS,sBAAsB,uBAAuB;AACtD,SAAS,oBAAoB,qBAAqB;AAClD,SAAS,sBAAsB,uBAAuB;AACtD,SAAS,0BAA0B,2BAA2B;AAC9D,SAAS,sBAAsB,uBAAuB;AACtD,SAAS,qBAAqB,sBAAsB;AACpD,SAAS,qBAAqB,sBAAsB;AACpD,SAAS,qBAAqB,sBAAsB;AACpD,SAAS,sBAAsB,uBAAuB;AACtD,SAAS,uBAAuB;AAiGzB,MAAM,sBAAsB;AAAA,EAClC,OAAO,EAAE,YAAY,sBAAsB,OAAO,gBAAgB;AAAA,EAClE,UAAU,EAAE,YAAY,yBAAyB,OAAO,mBAAmB;AAAA,EAC3E,MAAM,EAAE,YAAY,qBAAqB,OAAO,eAAe;AAAA,EAC/D,OAAO,EAAE,YAAY,sBAAsB,OAAO,gBAAgB;AAAA,EAClE,OAAO,EAAE,YAAY,sBAAsB,OAAO,gBAAgB;AAAA,EAClE,KAAK,EAAE,YAAY,oBAAoB,OAAO,cAAc;AAAA,EAC5D,OAAO,EAAE,YAAY,sBAAsB,OAAO,gBAAgB;AAAA,EAClE,WAAW,EAAE,YAAY,0BAA0B,OAAO,oBAAoB;AAAA,EAC9E,OAAO,EAAE,YAAY,sBAAsB,OAAO,gBAAgB;AAAA,EAClE,MAAM,EAAE,YAAY,qBAAqB,OAAO,eAAe;AAAA,EAC/D,MAAM,EAAE,YAAY,qBAAqB,OAAO,eAAe;AAAA,EAC/D,MAAM,EAAE,YAAY,qBAAqB,OAAO,eAAe;AAAA,EAC/D,OAAO,EAAE,YAAY,sBAAsB,OAAO,gBAAgB;AACnE;AAoCO,MAAM,wBAAwB;AAAA,EACpC,OAAO,EAAE,YAAY,wBAAwB,OAAO,kBAAkB;AACvE;
|
|
4
|
+
"sourcesContent": ["import { LegacyMigrations, MigrationSequence, StoreSchema, StoreValidator } from '@tldraw/store'\nimport { objectMapValues } from '@tldraw/utils'\nimport { TLStoreProps, createIntegrityChecker, onValidationFailure } from './TLStore'\nimport { bookmarkAssetMigrations } from './assets/TLBookmarkAsset'\nimport { imageAssetMigrations } from './assets/TLImageAsset'\nimport { videoAssetMigrations } from './assets/TLVideoAsset'\nimport { arrowBindingMigrations, arrowBindingProps } from './bindings/TLArrowBinding'\nimport { AssetRecordType, assetMigrations } from './records/TLAsset'\nimport { TLBinding, TLDefaultBinding, createBindingRecordType } from './records/TLBinding'\nimport { CameraRecordType, cameraMigrations } from './records/TLCamera'\nimport {\n\tCustomRecordInfo,\n\tcreateCustomRecordType,\n\tprocessCustomRecordMigrations,\n} from './records/TLCustomRecord'\nimport { DocumentRecordType, documentMigrations } from './records/TLDocument'\nimport { createInstanceRecordType, instanceMigrations } from './records/TLInstance'\nimport { PageRecordType, pageMigrations } from './records/TLPage'\nimport { InstancePageStateRecordType, instancePageStateMigrations } from './records/TLPageState'\nimport { PointerRecordType, pointerMigrations } from './records/TLPointer'\nimport { InstancePresenceRecordType, instancePresenceMigrations } from './records/TLPresence'\nimport { TLRecord } from './records/TLRecord'\nimport {\n\tTLDefaultShape,\n\tTLShape,\n\tcreateShapeRecordType,\n\tgetShapePropKeysByStyle,\n\trootShapeMigrations,\n} from './records/TLShape'\nimport { RecordProps, TLPropsMigrations, processPropsMigrations } from './recordsWithProps'\nimport { arrowShapeMigrations, arrowShapeProps } from './shapes/TLArrowShape'\nimport { TLBaseShape } from './shapes/TLBaseShape'\nimport { bookmarkShapeMigrations, bookmarkShapeProps } from './shapes/TLBookmarkShape'\nimport { drawShapeMigrations, drawShapeProps } from './shapes/TLDrawShape'\nimport { embedShapeMigrations, embedShapeProps } from './shapes/TLEmbedShape'\nimport { frameShapeMigrations, frameShapeProps } from './shapes/TLFrameShape'\nimport { geoShapeMigrations, geoShapeProps } from './shapes/TLGeoShape'\nimport { groupShapeMigrations, groupShapeProps } from './shapes/TLGroupShape'\nimport { highlightShapeMigrations, highlightShapeProps } from './shapes/TLHighlightShape'\nimport { imageShapeMigrations, imageShapeProps } from './shapes/TLImageShape'\nimport { lineShapeMigrations, lineShapeProps } from './shapes/TLLineShape'\nimport { noteShapeMigrations, noteShapeProps } from './shapes/TLNoteShape'\nimport { textShapeMigrations, textShapeProps } from './shapes/TLTextShape'\nimport { videoShapeMigrations, videoShapeProps } from './shapes/TLVideoShape'\nimport { storeMigrations } from './store-migrations'\nimport { StyleProp } from './styles/StyleProp'\n\n/**\n * Configuration information for a schema type (shape or binding), including its properties,\n * metadata, and migration sequences for data evolution over time.\n *\n * @public\n * @example\n * ```ts\n * import { arrowShapeMigrations, arrowShapeProps } from './shapes/TLArrowShape'\n *\n * const myShapeSchema: SchemaPropsInfo = {\n * migrations: arrowShapeMigrations,\n * props: arrowShapeProps,\n * meta: {\n * customField: T.string,\n * },\n * }\n * ```\n */\nexport interface SchemaPropsInfo {\n\t/**\n\t * Migration sequences for handling data evolution over time. Can be legacy migrations,\n\t * props-specific migrations, or general migration sequences.\n\t */\n\tmigrations?: LegacyMigrations | TLPropsMigrations | MigrationSequence\n\n\t/**\n\t * Validation schema for the shape or binding properties. Maps property names to their validators.\n\t */\n\tprops?: Record<string, StoreValidator<any>>\n\n\t/**\n\t * Validation schema for metadata fields. Maps metadata field names to their validators.\n\t */\n\tmeta?: Record<string, StoreValidator<any>>\n}\n\n/**\n * The complete schema definition for a tldraw store, encompassing all record types,\n * validation rules, and migration sequences. This schema defines the structure of\n * the persistent data model used by tldraw.\n *\n * @public\n * @example\n * ```ts\n * import { createTLSchema, defaultShapeSchemas } from '@tldraw/tlschema'\n * import { Store } from '@tldraw/store'\n *\n * const schema: TLSchema = createTLSchema({\n * shapes: defaultShapeSchemas,\n * })\n *\n * const store = new Store({ schema })\n * ```\n */\nexport type TLSchema = StoreSchema<TLRecord, TLStoreProps>\n\n/**\n * Default shape schema configurations for all built-in tldraw shape types.\n * Each shape type includes its validation props and migration sequences.\n *\n * This object contains schema information for:\n * - arrow: Directional lines that can bind to other shapes\n * - bookmark: Website bookmark cards with preview information\n * - draw: Freehand drawing paths created with drawing tools\n * - embed: Embedded content from external services (YouTube, Figma, etc.)\n * - frame: Container shapes for organizing content\n * - geo: Geometric shapes (rectangles, ellipses, triangles, etc.)\n * - group: Logical groupings of multiple shapes\n * - highlight: Highlighting strokes from the highlighter tool\n * - image: Raster image shapes referencing image assets\n * - line: Multi-point lines and splines\n * - note: Sticky note shapes with text content\n * - text: Rich text shapes with formatting support\n * - video: Video shapes referencing video assets\n *\n * @public\n * @example\n * ```ts\n * import { createTLSchema, defaultShapeSchemas } from '@tldraw/tlschema'\n *\n * // Use all default shapes\n * const schema = createTLSchema({\n * shapes: defaultShapeSchemas,\n * })\n *\n * // Use only specific default shapes\n * const minimalSchema = createTLSchema({\n * shapes: {\n * geo: defaultShapeSchemas.geo,\n * text: defaultShapeSchemas.text,\n * },\n * })\n * ```\n */\nexport const defaultShapeSchemas = {\n\tarrow: { migrations: arrowShapeMigrations, props: arrowShapeProps },\n\tbookmark: { migrations: bookmarkShapeMigrations, props: bookmarkShapeProps },\n\tdraw: { migrations: drawShapeMigrations, props: drawShapeProps },\n\tembed: { migrations: embedShapeMigrations, props: embedShapeProps },\n\tframe: { migrations: frameShapeMigrations, props: frameShapeProps },\n\tgeo: { migrations: geoShapeMigrations, props: geoShapeProps },\n\tgroup: { migrations: groupShapeMigrations, props: groupShapeProps },\n\thighlight: { migrations: highlightShapeMigrations, props: highlightShapeProps },\n\timage: { migrations: imageShapeMigrations, props: imageShapeProps },\n\tline: { migrations: lineShapeMigrations, props: lineShapeProps },\n\tnote: { migrations: noteShapeMigrations, props: noteShapeProps },\n\ttext: { migrations: textShapeMigrations, props: textShapeProps },\n\tvideo: { migrations: videoShapeMigrations, props: videoShapeProps },\n} satisfies {\n\t[T in TLDefaultShape['type']]: {\n\t\tmigrations: SchemaPropsInfo['migrations']\n\t\tprops: RecordProps<TLBaseShape<T, Extract<TLDefaultShape, { type: T }>['props']>>\n\t}\n}\n\n/**\n * Default binding schema configurations for all built-in tldraw binding types.\n * Bindings represent relationships between shapes, such as arrows connected to shapes.\n *\n * Currently includes:\n * - arrow: Bindings that connect arrow shapes to other shapes at specific anchor points\n *\n * @public\n * @example\n * ```ts\n * import { createTLSchema, defaultBindingSchemas } from '@tldraw/tlschema'\n *\n * // Use default bindings\n * const schema = createTLSchema({\n * bindings: defaultBindingSchemas,\n * })\n *\n * // Add custom binding alongside defaults\n * const customSchema = createTLSchema({\n * bindings: {\n * ...defaultBindingSchemas,\n * myCustomBinding: {\n * props: myCustomBindingProps,\n * migrations: myCustomBindingMigrations,\n * },\n * },\n * })\n * ```\n */\nexport const defaultBindingSchemas = {\n\tarrow: { migrations: arrowBindingMigrations, props: arrowBindingProps },\n} satisfies { [T in TLDefaultBinding['type']]: SchemaPropsInfo }\n\n/**\n * Creates a complete TLSchema for use with tldraw stores. This schema defines the structure,\n * validation, and migration sequences for all record types in a tldraw application.\n *\n * The schema includes all core record types (pages, cameras, instances, etc.) plus the\n * shape, binding, and custom record types you specify. Style properties are automatically\n * collected from all shapes to ensure consistency across the application.\n *\n * @param options - Configuration options for the schema\n * - shapes - Shape schema configurations. Defaults to defaultShapeSchemas if not provided\n * - bindings - Binding schema configurations. Defaults to defaultBindingSchemas if not provided\n * - records - Custom record type configurations. These are additional record types beyond\n * the built-in shapes, bindings, assets, etc.\n * - migrations - Additional migration sequences to include in the schema\n * @returns A complete TLSchema ready for use with Store creation\n *\n * @public\n * @example\n * ```ts\n * import { createTLSchema, defaultShapeSchemas, defaultBindingSchemas } from '@tldraw/tlschema'\n * import { Store } from '@tldraw/store'\n *\n * // Create schema with all default shapes and bindings\n * const schema = createTLSchema()\n *\n * // Create schema with custom shapes added\n * const customSchema = createTLSchema({\n * shapes: {\n * ...defaultShapeSchemas,\n * myCustomShape: {\n * props: myCustomShapeProps,\n * migrations: myCustomShapeMigrations,\n * },\n * },\n * })\n *\n * // Create schema with custom record types\n * const schemaWithCustomRecords = createTLSchema({\n * records: {\n * comment: {\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 * }),\n * },\n * },\n * })\n *\n * // Use the schema with a store\n * const store = new Store({\n * schema: customSchema,\n * props: {\n * defaultName: 'My Drawing',\n * },\n * })\n * ```\n */\nexport function createTLSchema({\n\tshapes = defaultShapeSchemas,\n\tbindings = defaultBindingSchemas,\n\trecords = {},\n\tmigrations,\n}: {\n\tshapes?: Record<string, SchemaPropsInfo>\n\tbindings?: Record<string, SchemaPropsInfo>\n\trecords?: Record<string, CustomRecordInfo>\n\tmigrations?: readonly MigrationSequence[]\n} = {}): TLSchema {\n\tconst stylesById = new Map<string, StyleProp<unknown>>()\n\tfor (const shape of objectMapValues(shapes)) {\n\t\tfor (const style of getShapePropKeysByStyle(shape.props ?? {}).keys()) {\n\t\t\tif (stylesById.has(style.id) && stylesById.get(style.id) !== style) {\n\t\t\t\tthrow new Error(`Multiple StyleProp instances with the same id: ${style.id}`)\n\t\t\t}\n\t\t\tstylesById.set(style.id, style)\n\t\t}\n\t}\n\n\tconst ShapeRecordType = createShapeRecordType(shapes)\n\tconst BindingRecordType = createBindingRecordType(bindings)\n\tconst InstanceRecordType = createInstanceRecordType(stylesById)\n\n\t// Create RecordTypes for custom records\n\tconst builtInTypeNames = new Set([\n\t\t'asset',\n\t\t'binding',\n\t\t'camera',\n\t\t'document',\n\t\t'instance',\n\t\t'instance_page_state',\n\t\t'page',\n\t\t'instance_presence',\n\t\t'pointer',\n\t\t'shape',\n\t\t'store',\n\t])\n\tconst customRecordTypes: Record<string, { createId: any }> = {}\n\tfor (const [typeName, config] of Object.entries(records)) {\n\t\tif (builtInTypeNames.has(typeName)) {\n\t\t\tthrow new Error(\n\t\t\t\t`Custom record type name '${typeName}' conflicts with tldraw's built-in record type of that name. Choose a different name instead.`\n\t\t\t)\n\t\t}\n\t\tcustomRecordTypes[typeName] = createCustomRecordType(typeName, config)\n\t}\n\n\treturn StoreSchema.create(\n\t\t{\n\t\t\tasset: AssetRecordType,\n\t\t\tbinding: BindingRecordType,\n\t\t\tcamera: CameraRecordType,\n\t\t\tdocument: DocumentRecordType,\n\t\t\tinstance: InstanceRecordType,\n\t\t\tinstance_page_state: InstancePageStateRecordType,\n\t\t\tpage: PageRecordType,\n\t\t\tinstance_presence: InstancePresenceRecordType,\n\t\t\tpointer: PointerRecordType,\n\t\t\tshape: ShapeRecordType,\n\t\t\t...customRecordTypes,\n\t\t},\n\t\t{\n\t\t\tmigrations: [\n\t\t\t\tstoreMigrations,\n\t\t\t\tassetMigrations,\n\t\t\t\tcameraMigrations,\n\t\t\t\tdocumentMigrations,\n\t\t\t\tinstanceMigrations,\n\t\t\t\tinstancePageStateMigrations,\n\t\t\t\tpageMigrations,\n\t\t\t\tinstancePresenceMigrations,\n\t\t\t\tpointerMigrations,\n\t\t\t\trootShapeMigrations,\n\n\t\t\t\tbookmarkAssetMigrations,\n\t\t\t\timageAssetMigrations,\n\t\t\t\tvideoAssetMigrations,\n\n\t\t\t\t...processPropsMigrations<TLShape>('shape', shapes),\n\t\t\t\t...processPropsMigrations<TLBinding>('binding', bindings),\n\t\t\t\t...processCustomRecordMigrations(records),\n\n\t\t\t\t...(migrations ?? []),\n\t\t\t],\n\t\t\tonValidationFailure,\n\t\t\tcreateIntegrityChecker,\n\t\t}\n\t)\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|