@tldraw/store
Advanced tools
Comparing version 2.0.0-canary.7b03ef9d0c62 to 2.0.0-canary.7fd0ab75edc8
@@ -1,3 +0,3 @@ | ||
import { Atom } from 'signia'; | ||
import { Computed } from 'signia'; | ||
import { Atom } from '@tldraw/state'; | ||
import { Computed } from '@tldraw/state'; | ||
@@ -395,2 +395,9 @@ /** | ||
/** | ||
* A serialized snapshot of the record store's values. | ||
* | ||
* @public | ||
*/ | ||
export declare type SerializedStore<R extends UnknownRecord> = Record<IdOf<R>, R>; | ||
/** | ||
* Squash a collection of diffs into a single diff. | ||
@@ -439,3 +446,3 @@ * | ||
/** The store's initial data. */ | ||
initialData?: StoreSnapshot<R>; | ||
initialData?: SerializedStore<R>; | ||
/** | ||
@@ -527,3 +534,3 @@ * A map of validators for each record type. A record's validator will be called when the record | ||
*/ | ||
serialize: (scope?: 'all' | RecordScope) => StoreSnapshot<R>; | ||
serialize: (scope?: 'all' | RecordScope) => SerializedStore<R>; | ||
/** | ||
@@ -540,6 +547,3 @@ * Get a serialized snapshot of the store and its schema. | ||
*/ | ||
getSnapshot(scope?: 'all' | RecordScope): { | ||
store: StoreSnapshot<R>; | ||
schema: SerializedSchema; | ||
}; | ||
getSnapshot(scope?: 'all' | RecordScope): StoreSnapshot<R>; | ||
/** | ||
@@ -557,6 +561,3 @@ * Load a serialized snapshot. | ||
*/ | ||
loadSnapshot(snapshot: { | ||
store: StoreSnapshot<R>; | ||
schema: SerializedSchema; | ||
}): void; | ||
loadSnapshot(snapshot: StoreSnapshot<R>): void; | ||
/** | ||
@@ -748,3 +749,3 @@ * Get an array of all values in the store. | ||
migratePersistedRecord(record: R, persistedSchema: SerializedSchema, direction?: 'down' | 'up'): MigrationResult<R>; | ||
migrateStoreSnapshot(storeSnapshot: StoreSnapshot<R>, persistedSchema: SerializedSchema): MigrationResult<StoreSnapshot<R>>; | ||
migrateStoreSnapshot(snapshot: StoreSnapshot<R>): MigrationResult<SerializedStore<R>>; | ||
/* Excluded from this release type: createIntegrityChecker */ | ||
@@ -770,8 +771,7 @@ serialize(): SerializedSchema; | ||
/** | ||
* A serialized snapshot of the record store's values. | ||
* | ||
* @public | ||
*/ | ||
export declare type StoreSnapshot<R extends UnknownRecord> = Record<IdOf<R>, R>; | ||
/** @public */ | ||
export declare type StoreSnapshot<R extends UnknownRecord> = { | ||
store: SerializedStore<R>; | ||
schema: SerializedSchema; | ||
}; | ||
@@ -778,0 +778,0 @@ /** @public */ |
@@ -26,5 +26,5 @@ "use strict"; | ||
module.exports = __toCommonJS(Store_exports); | ||
var import_state = require("@tldraw/state"); | ||
var import_utils = require("@tldraw/utils"); | ||
var import_nanoid = require("nanoid"); | ||
var import_signia = require("signia"); | ||
var import_Cache = require("./Cache"); | ||
@@ -44,3 +44,3 @@ var import_StoreQueries = require("./StoreQueries"); | ||
*/ | ||
atoms = (0, import_signia.atom)("store_atoms", {}); | ||
atoms = (0, import_state.atom)("store_atoms", {}); | ||
/** | ||
@@ -52,3 +52,3 @@ * An atom containing the store's history. | ||
*/ | ||
history = (0, import_signia.atom)("history", 0, { | ||
history = (0, import_state.atom)("history", 0, { | ||
historyLength: 1e3 | ||
@@ -94,3 +94,3 @@ }); | ||
id, | ||
(0, import_signia.atom)("atom:" + id, this.schema.validateRecord(this, record, "initialize", null)) | ||
(0, import_state.atom)("atom:" + id, this.schema.validateRecord(this, record, "initialize", null)) | ||
]) | ||
@@ -100,3 +100,3 @@ ) | ||
} | ||
this.historyReactor = (0, import_signia.reactor)( | ||
this.historyReactor = (0, import_state.reactor)( | ||
"Store.historyReactor", | ||
@@ -225,3 +225,3 @@ () => { | ||
put = (records, phaseOverride) => { | ||
(0, import_signia.transact)(() => { | ||
(0, import_state.transact)(() => { | ||
const updates = {}; | ||
@@ -262,3 +262,3 @@ const additions = {}; | ||
} | ||
map[record.id] = (0, import_signia.atom)("atom:" + record.id, record); | ||
map[record.id] = (0, import_state.atom)("atom:" + record.id, record); | ||
} | ||
@@ -296,3 +296,3 @@ } | ||
remove = (ids) => { | ||
(0, import_signia.transact)(() => { | ||
(0, import_state.transact)(() => { | ||
if (this.onBeforeDelete && this._runCallbacks) { | ||
@@ -395,7 +395,7 @@ for (const id of ids) { | ||
loadSnapshot(snapshot) { | ||
const migrationResult = this.schema.migrateStoreSnapshot(snapshot.store, snapshot.schema); | ||
const migrationResult = this.schema.migrateStoreSnapshot(snapshot); | ||
if (migrationResult.type === "error") { | ||
throw new Error(`Failed to migrate snapshot: ${migrationResult.reason}`); | ||
} | ||
(0, import_signia.transact)(() => { | ||
(0, import_state.transact)(() => { | ||
this.clear(); | ||
@@ -487,3 +487,3 @@ this.put(Object.values(migrationResult.value)); | ||
this.isMergingRemoteChanges = true; | ||
(0, import_signia.transact)(fn); | ||
(0, import_state.transact)(fn); | ||
} finally { | ||
@@ -497,3 +497,3 @@ this.isMergingRemoteChanges = false; | ||
try { | ||
(0, import_signia.transact)(fn); | ||
(0, import_state.transact)(fn); | ||
return squashRecordDiffs(changes); | ||
@@ -508,3 +508,3 @@ } finally { | ||
this._runCallbacks = runCallbacks; | ||
(0, import_signia.transact)(() => { | ||
(0, import_state.transact)(() => { | ||
const toPut = (0, import_utils.objectMapValues)(diff.added).concat( | ||
@@ -542,3 +542,3 @@ (0, import_utils.objectMapValues)(diff.updated).map(([_from, to]) => to) | ||
atom2, | ||
() => (0, import_signia.computed)(name + ":" + id, () => derive(atom2.value)) | ||
() => (0, import_state.computed)(name + ":" + id, () => derive(atom2.value)) | ||
).value; | ||
@@ -564,3 +564,3 @@ } | ||
} | ||
const d = (0, import_signia.computed)( | ||
const d = (0, import_state.computed)( | ||
name + ":" + id + ":selector", | ||
@@ -571,3 +571,3 @@ () => selector(atom2.value) | ||
atom2, | ||
() => (0, import_signia.computed)(name + ":" + id, () => derive(d.value)) | ||
() => (0, import_state.computed)(name + ":" + id, () => derive(d.value)) | ||
).value; | ||
@@ -574,0 +574,0 @@ } |
@@ -34,5 +34,5 @@ "use strict"; | ||
module.exports = __toCommonJS(StoreQueries_exports); | ||
var import_state = require("@tldraw/state"); | ||
var import_utils = require("@tldraw/utils"); | ||
var import_lodash = __toESM(require("lodash.isequal")); | ||
var import_signia = require("signia"); | ||
var import_executeQuery = require("./executeQuery"); | ||
@@ -69,10 +69,10 @@ var import_IncrementalSetConstructor = require("./IncrementalSetConstructor"); | ||
} | ||
const filtered = (0, import_signia.computed)( | ||
const filtered = (0, import_state.computed)( | ||
"filterHistory:" + typeName, | ||
(lastValue, lastComputedEpoch) => { | ||
if ((0, import_signia.isUninitialized)(lastValue)) { | ||
if ((0, import_state.isUninitialized)(lastValue)) { | ||
return this.history.value; | ||
} | ||
const diff = this.history.getDiffSince(lastComputedEpoch); | ||
if (diff === import_signia.RESET_VALUE) | ||
if (diff === import_state.RESET_VALUE) | ||
return this.history.value; | ||
@@ -130,3 +130,3 @@ const res = { added: {}, removed: {}, updated: {} }; | ||
if (numAdded || numRemoved || numUpdated) { | ||
return (0, import_signia.withDiff)(this.history.value, res); | ||
return (0, import_state.withDiff)(this.history.value, res); | ||
} else { | ||
@@ -181,9 +181,9 @@ return lastValue; | ||
}; | ||
return (0, import_signia.computed)( | ||
return (0, import_state.computed)( | ||
"index:" + typeName + ":" + property, | ||
(prevValue, lastComputedEpoch) => { | ||
if ((0, import_signia.isUninitialized)(prevValue)) | ||
if ((0, import_state.isUninitialized)(prevValue)) | ||
return fromScratch(); | ||
const history = typeHistory.getDiffSince(lastComputedEpoch); | ||
if (history === import_signia.RESET_VALUE) { | ||
if (history === import_state.RESET_VALUE) { | ||
return fromScratch(); | ||
@@ -250,3 +250,3 @@ } | ||
if (nextValue && nextDiff) { | ||
return (0, import_signia.withDiff)(nextValue, nextDiff); | ||
return (0, import_state.withDiff)(nextValue, nextDiff); | ||
} | ||
@@ -269,3 +269,3 @@ return prevValue; | ||
const ids = this.ids(typeName, queryCreator, name); | ||
return (0, import_signia.computed)(name, () => { | ||
return (0, import_state.computed)(name, () => { | ||
for (const id of ids.value) { | ||
@@ -286,3 +286,3 @@ return this.atoms.value[id]?.value; | ||
const ids = this.ids(typeName, queryCreator, "ids:" + name); | ||
return (0, import_signia.computed)(name, () => { | ||
return (0, import_state.computed)(name, () => { | ||
return [...ids.value].map((id) => { | ||
@@ -327,3 +327,3 @@ const atom = this.atoms.value[id]; | ||
if (diff) { | ||
return (0, import_signia.withDiff)(nextValue, diff); | ||
return (0, import_state.withDiff)(nextValue, diff); | ||
} else { | ||
@@ -333,10 +333,10 @@ return prevValue; | ||
}; | ||
const cachedQuery = (0, import_signia.computed)("ids_query:" + name, queryCreator, { | ||
const cachedQuery = (0, import_state.computed)("ids_query:" + name, queryCreator, { | ||
isEqual: import_lodash.default | ||
}); | ||
return (0, import_signia.computed)( | ||
return (0, import_state.computed)( | ||
"query:" + name, | ||
(prevValue, lastComputedEpoch) => { | ||
const query = cachedQuery.value; | ||
if ((0, import_signia.isUninitialized)(prevValue)) { | ||
if ((0, import_state.isUninitialized)(prevValue)) { | ||
return fromScratch(); | ||
@@ -348,3 +348,3 @@ } | ||
const history = typeHistory.getDiffSince(lastComputedEpoch); | ||
if (history === import_signia.RESET_VALUE) { | ||
if (history === import_state.RESET_VALUE) { | ||
return fromScratchWithDiff(prevValue); | ||
@@ -380,3 +380,3 @@ } | ||
} | ||
return (0, import_signia.withDiff)(result.value, result.diff); | ||
return (0, import_state.withDiff)(result.value, result.diff); | ||
}, | ||
@@ -389,3 +389,3 @@ { historyLength: 50 } | ||
if (ids.size === 0) { | ||
return import_signia.EMPTY_ARRAY; | ||
return import_state.EMPTY_ARRAY; | ||
} | ||
@@ -392,0 +392,0 @@ const atoms = this.atoms.value; |
@@ -110,9 +110,9 @@ "use strict"; | ||
} | ||
migrateStoreSnapshot(storeSnapshot, persistedSchema) { | ||
migrateStoreSnapshot(snapshot) { | ||
const migrations = this.options.snapshotMigrations; | ||
if (!migrations) { | ||
return { type: "success", value: storeSnapshot }; | ||
return { type: "success", value: snapshot.store }; | ||
} | ||
const ourStoreVersion = migrations.currentVersion; | ||
const persistedStoreVersion = persistedSchema.storeVersion ?? 0; | ||
const persistedStoreVersion = snapshot.schema.storeVersion ?? 0; | ||
if (ourStoreVersion < persistedStoreVersion) { | ||
@@ -123,3 +123,3 @@ return { type: "error", reason: import_migrate.MigrationFailureReason.TargetVersionTooOld }; | ||
const result = (0, import_migrate.migrate)({ | ||
value: storeSnapshot, | ||
value: snapshot.store, | ||
migrations, | ||
@@ -132,7 +132,7 @@ fromVersion: persistedStoreVersion, | ||
} | ||
storeSnapshot = result.value; | ||
snapshot.store = result.value; | ||
} | ||
const updated = []; | ||
for (const r of (0, import_utils.objectMapValues)(storeSnapshot)) { | ||
const result = this.migratePersistedRecord(r, persistedSchema); | ||
for (const r of (0, import_utils.objectMapValues)(snapshot.store)) { | ||
const result = this.migratePersistedRecord(r, snapshot.schema); | ||
if (result.type === "error") { | ||
@@ -145,8 +145,8 @@ return result; | ||
if (updated.length) { | ||
storeSnapshot = { ...storeSnapshot }; | ||
snapshot.store = { ...snapshot.store }; | ||
for (const r of updated) { | ||
storeSnapshot[r.id] = r; | ||
snapshot.store[r.id] = r; | ||
} | ||
} | ||
return { type: "success", value: storeSnapshot }; | ||
return { type: "success", value: snapshot.store }; | ||
} | ||
@@ -153,0 +153,0 @@ /** @internal */ |
{ | ||
"name": "@tldraw/store", | ||
"description": "A tiny little drawing app (store).", | ||
"version": "2.0.0-canary.7b03ef9d0c62", | ||
"version": "2.0.0-canary.7fd0ab75edc8", | ||
"packageManager": "yarn@3.5.0", | ||
@@ -45,9 +45,7 @@ "author": { | ||
"dependencies": { | ||
"@tldraw/utils": "2.0.0-canary.7b03ef9d0c62", | ||
"@tldraw/state": "2.0.0-canary.7fd0ab75edc8", | ||
"@tldraw/utils": "2.0.0-canary.7fd0ab75edc8", | ||
"lodash.isequal": "^4.5.0", | ||
"nanoid": "4.0.2" | ||
}, | ||
"peerDependencies": { | ||
"signia": "*" | ||
}, | ||
"devDependencies": { | ||
@@ -54,0 +52,0 @@ "@peculiar/webcrypto": "^1.4.0", |
@@ -10,2 +10,3 @@ export type { BaseRecord, IdOf, RecordId, UnknownRecord } from './lib/BaseRecord' | ||
RecordsDiff, | ||
SerializedStore, | ||
StoreError, | ||
@@ -12,0 +13,0 @@ StoreListener, |
@@ -0,1 +1,2 @@ | ||
import { Atom, Computed, Reactor, atom, computed, reactor, transact } from '@tldraw/state' | ||
import { | ||
@@ -10,3 +11,2 @@ filterEntries, | ||
import { nanoid } from 'nanoid' | ||
import { Atom, Computed, Reactor, atom, computed, reactor, transact } from 'signia' | ||
import { IdOf, RecordId, UnknownRecord } from './BaseRecord' | ||
@@ -77,5 +77,11 @@ import { Cache } from './Cache' | ||
*/ | ||
export type StoreSnapshot<R extends UnknownRecord> = Record<IdOf<R>, R> | ||
export type SerializedStore<R extends UnknownRecord> = Record<IdOf<R>, R> | ||
/** @public */ | ||
export type StoreSnapshot<R extends UnknownRecord> = { | ||
store: SerializedStore<R> | ||
schema: SerializedSchema | ||
} | ||
/** @public */ | ||
export type StoreValidator<R extends UnknownRecord> = { | ||
@@ -168,3 +174,3 @@ validate: (record: unknown) => R | ||
/** The store's initial data. */ | ||
initialData?: StoreSnapshot<R> | ||
initialData?: SerializedStore<R> | ||
/** | ||
@@ -509,4 +515,4 @@ * A map of validators for each record type. A record's validator will be called when the record | ||
*/ | ||
serialize = (scope: RecordScope | 'all' = 'document'): StoreSnapshot<R> => { | ||
const result = {} as StoreSnapshot<R> | ||
serialize = (scope: RecordScope | 'all' = 'document'): SerializedStore<R> => { | ||
const result = {} as SerializedStore<R> | ||
for (const [id, atom] of objectMapEntries(this.atoms.value)) { | ||
@@ -532,3 +538,3 @@ const record = atom.value | ||
*/ | ||
getSnapshot(scope: RecordScope | 'all' = 'document') { | ||
getSnapshot(scope: RecordScope | 'all' = 'document'): StoreSnapshot<R> { | ||
return { | ||
@@ -552,4 +558,4 @@ store: this.serialize(scope), | ||
*/ | ||
loadSnapshot(snapshot: { store: StoreSnapshot<R>; schema: SerializedSchema }): void { | ||
const migrationResult = this.schema.migrateStoreSnapshot(snapshot.store, snapshot.schema) | ||
loadSnapshot(snapshot: StoreSnapshot<R>): void { | ||
const migrationResult = this.schema.migrateStoreSnapshot(snapshot) | ||
@@ -556,0 +562,0 @@ if (migrationResult.type === 'error') { |
@@ -1,3 +0,1 @@ | ||
import { objectMapValues } from '@tldraw/utils' | ||
import isEqual from 'lodash.isequal' | ||
import { | ||
@@ -11,3 +9,5 @@ Atom, | ||
withDiff, | ||
} from 'signia' | ||
} from '@tldraw/state' | ||
import { objectMapValues } from '@tldraw/utils' | ||
import isEqual from 'lodash.isequal' | ||
import { IdOf, UnknownRecord } from './BaseRecord' | ||
@@ -14,0 +14,0 @@ import { executeQuery, objectMatchesQuery, QueryExpression } from './executeQuery' |
import { getOwnProperty, objectMapValues } from '@tldraw/utils' | ||
import { IdOf, UnknownRecord } from './BaseRecord' | ||
import { RecordType } from './RecordType' | ||
import { Store, StoreSnapshot } from './Store' | ||
import { SerializedStore, Store, StoreSnapshot } from './Store' | ||
import { | ||
@@ -191,13 +191,10 @@ MigrationFailureReason, | ||
migrateStoreSnapshot( | ||
storeSnapshot: StoreSnapshot<R>, | ||
persistedSchema: SerializedSchema | ||
): MigrationResult<StoreSnapshot<R>> { | ||
migrateStoreSnapshot(snapshot: StoreSnapshot<R>): MigrationResult<SerializedStore<R>> { | ||
const migrations = this.options.snapshotMigrations | ||
if (!migrations) { | ||
return { type: 'success', value: storeSnapshot } | ||
return { type: 'success', value: snapshot.store } | ||
} | ||
// apply store migrations first | ||
const ourStoreVersion = migrations.currentVersion | ||
const persistedStoreVersion = persistedSchema.storeVersion ?? 0 | ||
const persistedStoreVersion = snapshot.schema.storeVersion ?? 0 | ||
@@ -209,4 +206,4 @@ if (ourStoreVersion < persistedStoreVersion) { | ||
if (ourStoreVersion > persistedStoreVersion) { | ||
const result = migrate<StoreSnapshot<R>>({ | ||
value: storeSnapshot, | ||
const result = migrate<SerializedStore<R>>({ | ||
value: snapshot.store, | ||
migrations, | ||
@@ -220,8 +217,8 @@ fromVersion: persistedStoreVersion, | ||
} | ||
storeSnapshot = result.value | ||
snapshot.store = result.value | ||
} | ||
const updated: R[] = [] | ||
for (const r of objectMapValues(storeSnapshot)) { | ||
const result = this.migratePersistedRecord(r, persistedSchema) | ||
for (const r of objectMapValues(snapshot.store)) { | ||
const result = this.migratePersistedRecord(r, snapshot.schema) | ||
if (result.type === 'error') { | ||
@@ -234,8 +231,8 @@ return result | ||
if (updated.length) { | ||
storeSnapshot = { ...storeSnapshot } | ||
snapshot.store = { ...snapshot.store } | ||
for (const r of updated) { | ||
storeSnapshot[r.id as IdOf<R>] = r | ||
snapshot.store[r.id as IdOf<R>] = r | ||
} | ||
} | ||
return { type: 'success', value: storeSnapshot } | ||
return { type: 'success', value: snapshot.store } | ||
} | ||
@@ -242,0 +239,0 @@ |
import { MigrationFailureReason } from '../migrate' | ||
import { StoreSnapshot } from '../Store' | ||
import { SerializedStore } from '../Store' | ||
import { testSchemaV0 } from './testSchema.v0' | ||
@@ -308,3 +308,3 @@ import { testSchemaV1 } from './testSchema.v1' | ||
test('migrating a whole store snapshot works', () => { | ||
const snapshot: StoreSnapshot<any> = { | ||
const serializedStore: SerializedStore<any> = { | ||
'user-1': { | ||
@@ -333,3 +333,6 @@ id: 'user-1', | ||
const result = testSchemaV1.migrateStoreSnapshot(snapshot, serializedV0Schenma) | ||
const result = testSchemaV1.migrateStoreSnapshot({ | ||
store: serializedStore, | ||
schema: serializedV0Schenma, | ||
}) | ||
@@ -336,0 +339,0 @@ if (result.type !== 'success') { |
@@ -1,2 +0,2 @@ | ||
import { Computed, react, RESET_VALUE, transact } from 'signia' | ||
import { Computed, react, RESET_VALUE, transact } from '@tldraw/state' | ||
import { BaseRecord, RecordId } from '../BaseRecord' | ||
@@ -3,0 +3,0 @@ import { createRecordType } from '../RecordType' |
@@ -1,2 +0,2 @@ | ||
import { atom, EffectScheduler, RESET_VALUE } from 'signia' | ||
import { atom, EffectScheduler, RESET_VALUE } from '@tldraw/state' | ||
import { BaseRecord, IdOf, RecordId, UnknownRecord } from '../BaseRecord' | ||
@@ -3,0 +3,0 @@ import { executeQuery } from '../executeQuery' |
@@ -1,2 +0,2 @@ | ||
import { atom, RESET_VALUE } from 'signia' | ||
import { atom, RESET_VALUE } from '@tldraw/state' | ||
import { BaseRecord, RecordId } from '../BaseRecord' | ||
@@ -3,0 +3,0 @@ import { createRecordType } from '../RecordType' |
import { assert } from '@tldraw/utils' | ||
import { BaseRecord, RecordId } from '../BaseRecord' | ||
import { createRecordType } from '../RecordType' | ||
import { StoreSnapshot } from '../Store' | ||
import { SerializedStore } from '../Store' | ||
import { StoreSchema } from '../StoreSchema' | ||
@@ -206,6 +206,6 @@ import { defineMigrations } from '../migrate' | ||
[StoreVersions.RemoveOrg]: { | ||
up: (store: StoreSnapshot<any>) => { | ||
up: (store: SerializedStore<any>) => { | ||
return Object.fromEntries(Object.entries(store).filter(([_, r]) => r.typeName !== 'org')) | ||
}, | ||
down: (store: StoreSnapshot<any>) => { | ||
down: (store: SerializedStore<any>) => { | ||
// noop | ||
@@ -212,0 +212,0 @@ return store |
import { BaseRecord, IdOf, RecordId } from '../BaseRecord' | ||
import { createRecordType } from '../RecordType' | ||
import { Store, StoreSnapshot } from '../Store' | ||
import { SerializedStore, Store } from '../Store' | ||
import { StoreSchema } from '../StoreSchema' | ||
@@ -93,3 +93,3 @@ | ||
describe('Validating initial data', () => { | ||
let snapshot: StoreSnapshot<Book | Author> | ||
let snapshot: SerializedStore<Book | Author> | ||
@@ -96,0 +96,0 @@ beforeEach(() => { |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
578713
10069
+ Added@tldraw/state@2.0.0-canary.7fd0ab75edc8(transitive)
+ Added@tldraw/utils@2.0.0-canary.7fd0ab75edc8(transitive)
+ Addedjs-tokens@4.0.0(transitive)
+ Addedloose-envify@1.4.0(transitive)
+ Addedreact@18.3.1(transitive)
- Removed@tldraw/utils@2.0.0-canary.7b03ef9d0c62(transitive)
- Removedsignia@0.1.5(transitive)