@tldraw/store 3.16.0-next.fe14f1b4181f → 4.0.1
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/README.md +11 -11
- package/dist-cjs/index.d.ts +2 -40
- package/dist-cjs/index.js +1 -2
- package/dist-cjs/index.js.map +2 -2
- package/dist-cjs/lib/RecordType.js +0 -16
- package/dist-cjs/lib/RecordType.js.map +2 -2
- package/dist-cjs/lib/Store.js +1 -20
- package/dist-cjs/lib/Store.js.map +2 -2
- package/dist-cjs/lib/StoreSchema.js +1 -0
- package/dist-cjs/lib/StoreSchema.js.map +2 -2
- package/dist-cjs/lib/migrate.js +57 -43
- package/dist-cjs/lib/migrate.js.map +2 -2
- package/dist-esm/index.d.mts +2 -40
- package/dist-esm/index.mjs +1 -3
- package/dist-esm/index.mjs.map +2 -2
- package/dist-esm/lib/RecordType.mjs +0 -16
- package/dist-esm/lib/RecordType.mjs.map +2 -2
- package/dist-esm/lib/Store.mjs +1 -20
- package/dist-esm/lib/Store.mjs.map +2 -2
- package/dist-esm/lib/StoreSchema.mjs +1 -0
- package/dist-esm/lib/StoreSchema.mjs.map +2 -2
- package/dist-esm/lib/migrate.mjs +57 -43
- package/dist-esm/lib/migrate.mjs.map +2 -2
- package/package.json +3 -3
- package/src/index.ts +0 -1
- package/src/lib/RecordType.ts +0 -17
- package/src/lib/Store.ts +1 -22
- package/src/lib/StoreSchema.ts +1 -0
- package/src/lib/migrate.ts +106 -57
- package/src/lib/test/sortMigrations.test.ts +32 -0
- package/src/lib/test/defineMigrations.test.ts +0 -232
package/src/lib/Store.ts
CHANGED
|
@@ -501,21 +501,11 @@ export class Store<R extends UnknownRecord = UnknownRecord, Props = unknown> {
|
|
|
501
501
|
}
|
|
502
502
|
}
|
|
503
503
|
|
|
504
|
-
/**
|
|
505
|
-
* @deprecated use `getSnapshot` from the 'tldraw' package instead.
|
|
506
|
-
*/
|
|
507
|
-
getSnapshot(scope: RecordScope | 'all' = 'document') {
|
|
508
|
-
console.warn(
|
|
509
|
-
'[tldraw] `Store.getSnapshot` is deprecated and will be removed in a future release. Use `getSnapshot` from the `tldraw` package instead.'
|
|
510
|
-
)
|
|
511
|
-
return this.getStoreSnapshot(scope)
|
|
512
|
-
}
|
|
513
|
-
|
|
514
504
|
/**
|
|
515
505
|
* Migrate a serialized snapshot of the store and its schema.
|
|
516
506
|
*
|
|
517
507
|
* ```ts
|
|
518
|
-
* const snapshot = store.
|
|
508
|
+
* const snapshot = store.getStoreSnapshot()
|
|
519
509
|
* store.migrateSnapshot(snapshot)
|
|
520
510
|
* ```
|
|
521
511
|
*
|
|
@@ -566,17 +556,6 @@ export class Store<R extends UnknownRecord = UnknownRecord, Props = unknown> {
|
|
|
566
556
|
}
|
|
567
557
|
}
|
|
568
558
|
|
|
569
|
-
/**
|
|
570
|
-
* @public
|
|
571
|
-
* @deprecated use `loadSnapshot` from the 'tldraw' package instead.
|
|
572
|
-
*/
|
|
573
|
-
loadSnapshot(snapshot: StoreSnapshot<R>) {
|
|
574
|
-
console.warn(
|
|
575
|
-
"[tldraw] `Store.loadSnapshot` is deprecated and will be removed in a future release. Use `loadSnapshot` from the 'tldraw' package instead."
|
|
576
|
-
)
|
|
577
|
-
this.loadStoreSnapshot(snapshot)
|
|
578
|
-
}
|
|
579
|
-
|
|
580
559
|
/**
|
|
581
560
|
* Get an array of all values in the store.
|
|
582
561
|
*
|
package/src/lib/StoreSchema.ts
CHANGED
|
@@ -349,6 +349,7 @@ export class StoreSchema<R extends UnknownRecord, P = unknown> {
|
|
|
349
349
|
|
|
350
350
|
/**
|
|
351
351
|
* @deprecated This is only here for legacy reasons, don't use it unless you have david's blessing!
|
|
352
|
+
* @internal
|
|
352
353
|
*/
|
|
353
354
|
serializeEarliestVersion(): SerializedSchema {
|
|
354
355
|
return {
|
package/src/lib/migrate.ts
CHANGED
|
@@ -2,45 +2,6 @@ import { assert, objectMapEntries } from '@tldraw/utils'
|
|
|
2
2
|
import { UnknownRecord } from './BaseRecord'
|
|
3
3
|
import { SerializedStore } from './Store'
|
|
4
4
|
|
|
5
|
-
let didWarn = false
|
|
6
|
-
|
|
7
|
-
/**
|
|
8
|
-
* @public
|
|
9
|
-
* @deprecated use `createShapePropsMigrationSequence` instead. See [the docs](https://tldraw.dev/docs/persistence#Updating-legacy-shape-migrations-defineMigrations) for how to migrate.
|
|
10
|
-
*/
|
|
11
|
-
export function defineMigrations(opts: {
|
|
12
|
-
firstVersion?: number
|
|
13
|
-
currentVersion?: number
|
|
14
|
-
migrators?: Record<number, LegacyMigration>
|
|
15
|
-
subTypeKey?: string
|
|
16
|
-
subTypeMigrations?: Record<string, LegacyBaseMigrationsInfo>
|
|
17
|
-
}): LegacyMigrations {
|
|
18
|
-
const { currentVersion, firstVersion, migrators = {}, subTypeKey, subTypeMigrations } = opts
|
|
19
|
-
if (!didWarn) {
|
|
20
|
-
console.warn(
|
|
21
|
-
`The 'defineMigrations' function is deprecated and will be removed in a future release. Use the new migrations API instead. See the migration guide for more info: https://tldraw.dev/docs/persistence#Updating-legacy-shape-migrations-defineMigrations`
|
|
22
|
-
)
|
|
23
|
-
didWarn = true
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
// Some basic guards against impossible version combinations, some of which will be caught by TypeScript
|
|
27
|
-
if (typeof currentVersion === 'number' && typeof firstVersion === 'number') {
|
|
28
|
-
if ((currentVersion as number) === (firstVersion as number)) {
|
|
29
|
-
throw Error(`Current version is equal to initial version.`)
|
|
30
|
-
} else if (currentVersion < firstVersion) {
|
|
31
|
-
throw Error(`Current version is lower than initial version.`)
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
return {
|
|
36
|
-
firstVersion: (firstVersion as number) ?? 0, // defaults
|
|
37
|
-
currentVersion: (currentVersion as number) ?? 0, // defaults
|
|
38
|
-
migrators,
|
|
39
|
-
subTypeKey,
|
|
40
|
-
subTypeMigrations,
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
|
|
44
5
|
function squashDependsOn(sequence: Array<Migration | StandaloneDependsOn>): Migration[] {
|
|
45
6
|
const result: Migration[] = []
|
|
46
7
|
for (let i = sequence.length - 1; i >= 0; i--) {
|
|
@@ -199,38 +160,126 @@ export interface MigrationSequence {
|
|
|
199
160
|
sequence: Migration[]
|
|
200
161
|
}
|
|
201
162
|
|
|
163
|
+
/**
|
|
164
|
+
* Sorts migrations using a distance-minimizing topological sort.
|
|
165
|
+
*
|
|
166
|
+
* This function respects two types of dependencies:
|
|
167
|
+
* 1. Implicit sequence dependencies (foo/1 must come before foo/2)
|
|
168
|
+
* 2. Explicit dependencies via `dependsOn` property
|
|
169
|
+
*
|
|
170
|
+
* The algorithm minimizes the total distance between migrations and their explicit
|
|
171
|
+
* dependencies in the final ordering, while maintaining topological correctness.
|
|
172
|
+
* This means when migration A depends on migration B, A will be scheduled as close
|
|
173
|
+
* as possible to B (while respecting all constraints).
|
|
174
|
+
*
|
|
175
|
+
* Implementation uses Kahn's algorithm with priority scoring:
|
|
176
|
+
* - Builds dependency graph and calculates in-degrees
|
|
177
|
+
* - Uses priority queue that prioritizes migrations which unblock explicit dependencies
|
|
178
|
+
* - Processes migrations in urgency order while maintaining topological constraints
|
|
179
|
+
* - Detects cycles by ensuring all migrations are processed
|
|
180
|
+
*
|
|
181
|
+
* @param migrations - Array of migrations to sort
|
|
182
|
+
* @returns Sorted array of migrations in execution order
|
|
183
|
+
*/
|
|
202
184
|
export function sortMigrations(migrations: Migration[]): Migration[] {
|
|
203
|
-
|
|
204
|
-
const byId = new Map(migrations.map((m) => [m.id, m]))
|
|
205
|
-
const isProcessing = new Set<MigrationId>()
|
|
185
|
+
if (migrations.length === 0) return []
|
|
206
186
|
|
|
207
|
-
|
|
187
|
+
// Build dependency graph and calculate in-degrees
|
|
188
|
+
const byId = new Map(migrations.map((m) => [m.id, m]))
|
|
189
|
+
const dependents = new Map<MigrationId, Set<MigrationId>>() // who depends on this
|
|
190
|
+
const inDegree = new Map<MigrationId, number>()
|
|
191
|
+
const explicitDeps = new Map<MigrationId, Set<MigrationId>>() // explicit dependsOn relationships
|
|
208
192
|
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
193
|
+
// Initialize
|
|
194
|
+
for (const m of migrations) {
|
|
195
|
+
inDegree.set(m.id, 0)
|
|
196
|
+
dependents.set(m.id, new Set())
|
|
197
|
+
explicitDeps.set(m.id, new Set())
|
|
198
|
+
}
|
|
212
199
|
|
|
200
|
+
// Add implicit sequence dependencies and explicit dependencies
|
|
201
|
+
for (const m of migrations) {
|
|
213
202
|
const { version, sequenceId } = parseMigrationId(m.id)
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
203
|
+
|
|
204
|
+
// Implicit dependency on previous in sequence
|
|
205
|
+
const prevId = `${sequenceId}/${version - 1}` as MigrationId
|
|
206
|
+
if (byId.has(prevId)) {
|
|
207
|
+
dependents.get(prevId)!.add(m.id)
|
|
208
|
+
inDegree.set(m.id, inDegree.get(m.id)! + 1)
|
|
217
209
|
}
|
|
218
210
|
|
|
211
|
+
// Explicit dependencies
|
|
219
212
|
if (m.dependsOn) {
|
|
220
|
-
for (const
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
213
|
+
for (const depId of m.dependsOn) {
|
|
214
|
+
if (byId.has(depId)) {
|
|
215
|
+
dependents.get(depId)!.add(m.id)
|
|
216
|
+
explicitDeps.get(m.id)!.add(depId)
|
|
217
|
+
inDegree.set(m.id, inDegree.get(m.id)! + 1)
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
// Priority queue: migrations ready to process (in-degree 0)
|
|
224
|
+
const ready = migrations.filter((m) => inDegree.get(m.id) === 0)
|
|
225
|
+
const result: Migration[] = []
|
|
226
|
+
const processed = new Set<MigrationId>()
|
|
227
|
+
|
|
228
|
+
while (ready.length > 0) {
|
|
229
|
+
// Calculate urgency scores for ready migrations and pick the best one
|
|
230
|
+
let bestCandidate: Migration | undefined
|
|
231
|
+
let bestCandidateScore = -Infinity
|
|
232
|
+
|
|
233
|
+
for (const m of ready) {
|
|
234
|
+
let urgencyScore = 0
|
|
235
|
+
|
|
236
|
+
for (const depId of dependents.get(m.id) || []) {
|
|
237
|
+
if (!processed.has(depId)) {
|
|
238
|
+
// Priority 1: Count all unprocessed dependents (to break ties)
|
|
239
|
+
urgencyScore += 1
|
|
240
|
+
|
|
241
|
+
// Priority 2: If this migration is explicitly depended on by others, boost priority
|
|
242
|
+
if (explicitDeps.get(depId)!.has(m.id)) {
|
|
243
|
+
urgencyScore += 100
|
|
244
|
+
}
|
|
224
245
|
}
|
|
225
246
|
}
|
|
247
|
+
|
|
248
|
+
if (
|
|
249
|
+
urgencyScore > bestCandidateScore ||
|
|
250
|
+
// Tiebreaker: prefer lower sequence/version
|
|
251
|
+
(urgencyScore === bestCandidateScore && m.id.localeCompare(bestCandidate?.id ?? '') < 0)
|
|
252
|
+
) {
|
|
253
|
+
bestCandidate = m
|
|
254
|
+
bestCandidateScore = urgencyScore
|
|
255
|
+
}
|
|
226
256
|
}
|
|
227
257
|
|
|
228
|
-
|
|
229
|
-
|
|
258
|
+
const nextMigration = bestCandidate!
|
|
259
|
+
ready.splice(ready.indexOf(nextMigration), 1)
|
|
260
|
+
|
|
261
|
+
// Cycle detection - if we have processed everything and still have items left, there's a cycle
|
|
262
|
+
// This is handled by Kahn's algorithm naturally - if we finish with items unprocessed, there's a cycle
|
|
263
|
+
|
|
264
|
+
// Process this migration
|
|
265
|
+
result.push(nextMigration)
|
|
266
|
+
processed.add(nextMigration.id)
|
|
267
|
+
|
|
268
|
+
// Update in-degrees and add newly ready migrations
|
|
269
|
+
for (const depId of dependents.get(nextMigration.id) || []) {
|
|
270
|
+
if (!processed.has(depId)) {
|
|
271
|
+
inDegree.set(depId, inDegree.get(depId)! - 1)
|
|
272
|
+
if (inDegree.get(depId) === 0) {
|
|
273
|
+
ready.push(byId.get(depId)!)
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
}
|
|
230
277
|
}
|
|
231
278
|
|
|
232
|
-
for
|
|
233
|
-
|
|
279
|
+
// Check for cycles - if we didn't process all migrations, there's a cycle
|
|
280
|
+
if (result.length !== migrations.length) {
|
|
281
|
+
const unprocessed = migrations.filter((m) => !processed.has(m.id))
|
|
282
|
+
assert(false, `Circular dependency in migrations: ${unprocessed[0].id}`)
|
|
234
283
|
}
|
|
235
284
|
|
|
236
285
|
return result
|
|
@@ -31,6 +31,38 @@ describe(sortMigrations, () => {
|
|
|
31
31
|
).toEqual(['bar/1', 'bar/2', 'foo/1', 'foo/2'])
|
|
32
32
|
})
|
|
33
33
|
|
|
34
|
+
it('should minimize distance between dependencies and dependents', () => {
|
|
35
|
+
// bar/3 depends on foo/1 - should process bar sequence immediately after foo/1
|
|
36
|
+
expect(
|
|
37
|
+
sort([m('foo/2'), m('bar/3', { dependsOn: ['foo/1'] }), m('foo/1'), m('bar/1'), m('bar/2')])
|
|
38
|
+
).toEqual(['foo/1', 'bar/1', 'bar/2', 'bar/3', 'foo/2'])
|
|
39
|
+
})
|
|
40
|
+
|
|
41
|
+
it('should minimize total distance for multiple explicit dependencies', () => {
|
|
42
|
+
// Both bar/2 and baz/1 depend on foo/1 - minimize total distance
|
|
43
|
+
expect(
|
|
44
|
+
sort([
|
|
45
|
+
m('foo/2'),
|
|
46
|
+
m('bar/2', { dependsOn: ['foo/1'] }),
|
|
47
|
+
m('foo/1'),
|
|
48
|
+
m('bar/1'),
|
|
49
|
+
m('baz/1', { dependsOn: ['foo/1'] }),
|
|
50
|
+
])
|
|
51
|
+
).toEqual(['foo/1', 'bar/1', 'bar/2', 'baz/1', 'foo/2'])
|
|
52
|
+
})
|
|
53
|
+
|
|
54
|
+
it('should handle chain of explicit dependencies optimally', () => {
|
|
55
|
+
// foo/1 -> bar/1 -> baz/1 chain should be consecutive
|
|
56
|
+
expect(
|
|
57
|
+
sort([
|
|
58
|
+
m('foo/2'),
|
|
59
|
+
m('bar/1', { dependsOn: ['foo/1'] }),
|
|
60
|
+
m('foo/1'),
|
|
61
|
+
m('baz/1', { dependsOn: ['bar/1'] }),
|
|
62
|
+
])
|
|
63
|
+
).toEqual(['foo/1', 'bar/1', 'baz/1', 'foo/2'])
|
|
64
|
+
})
|
|
65
|
+
|
|
34
66
|
it('should fail if a cycle is created', () => {
|
|
35
67
|
expect(() => {
|
|
36
68
|
sort([m('foo/1', { dependsOn: ['foo/1'] })])
|
|
@@ -1,232 +0,0 @@
|
|
|
1
|
-
import { defineMigrations } from '../migrate'
|
|
2
|
-
|
|
3
|
-
const Versions = {
|
|
4
|
-
Initial: 0,
|
|
5
|
-
January: 1,
|
|
6
|
-
February: 2,
|
|
7
|
-
March: 3,
|
|
8
|
-
} as const
|
|
9
|
-
|
|
10
|
-
describe('define migrations tests', () => {
|
|
11
|
-
it('defines migrations', () => {
|
|
12
|
-
expect(() => {
|
|
13
|
-
// no versions
|
|
14
|
-
// eslint-disable-next-line @typescript-eslint/no-deprecated
|
|
15
|
-
defineMigrations({
|
|
16
|
-
firstVersion: Versions.Initial,
|
|
17
|
-
})
|
|
18
|
-
}).not.toThrow()
|
|
19
|
-
|
|
20
|
-
expect(() => {
|
|
21
|
-
// no versions
|
|
22
|
-
// eslint-disable-next-line @typescript-eslint/no-deprecated
|
|
23
|
-
defineMigrations({
|
|
24
|
-
firstVersion: Versions.February,
|
|
25
|
-
})
|
|
26
|
-
}).not.toThrow()
|
|
27
|
-
|
|
28
|
-
expect(() => {
|
|
29
|
-
// empty migrators
|
|
30
|
-
// eslint-disable-next-line @typescript-eslint/no-deprecated
|
|
31
|
-
defineMigrations({
|
|
32
|
-
migrators: {},
|
|
33
|
-
})
|
|
34
|
-
}).not.toThrow()
|
|
35
|
-
|
|
36
|
-
expect(() => {
|
|
37
|
-
// no versions!
|
|
38
|
-
// eslint-disable-next-line @typescript-eslint/no-deprecated
|
|
39
|
-
defineMigrations({
|
|
40
|
-
migrators: {
|
|
41
|
-
[Versions.February]: {
|
|
42
|
-
up: (rec: any) => rec,
|
|
43
|
-
down: (rec: any) => rec,
|
|
44
|
-
},
|
|
45
|
-
},
|
|
46
|
-
})
|
|
47
|
-
}).not.toThrow()
|
|
48
|
-
|
|
49
|
-
expect(() => {
|
|
50
|
-
// wrong current version!
|
|
51
|
-
// eslint-disable-next-line @typescript-eslint/no-deprecated
|
|
52
|
-
defineMigrations({
|
|
53
|
-
currentVersion: Versions.January,
|
|
54
|
-
migrators: {
|
|
55
|
-
[Versions.February]: {
|
|
56
|
-
up: (rec: any) => rec,
|
|
57
|
-
down: (rec: any) => rec,
|
|
58
|
-
},
|
|
59
|
-
},
|
|
60
|
-
})
|
|
61
|
-
}).not.toThrow()
|
|
62
|
-
|
|
63
|
-
expect(() => {
|
|
64
|
-
// eslint-disable-next-line @typescript-eslint/no-deprecated
|
|
65
|
-
defineMigrations({
|
|
66
|
-
currentVersion: Versions.February,
|
|
67
|
-
migrators: {
|
|
68
|
-
// has a default zero version
|
|
69
|
-
[Versions.January]: {
|
|
70
|
-
up: (rec: any) => rec,
|
|
71
|
-
down: (rec: any) => rec,
|
|
72
|
-
},
|
|
73
|
-
// has a current version
|
|
74
|
-
[Versions.February]: {
|
|
75
|
-
up: (rec: any) => rec,
|
|
76
|
-
down: (rec: any) => rec,
|
|
77
|
-
},
|
|
78
|
-
},
|
|
79
|
-
})
|
|
80
|
-
}).not.toThrow()
|
|
81
|
-
|
|
82
|
-
expect(() => {
|
|
83
|
-
// can't provide only first version
|
|
84
|
-
// eslint-disable-next-line @typescript-eslint/no-deprecated
|
|
85
|
-
defineMigrations({
|
|
86
|
-
firstVersion: Versions.January,
|
|
87
|
-
migrators: {},
|
|
88
|
-
})
|
|
89
|
-
}).not.toThrow()
|
|
90
|
-
|
|
91
|
-
expect(() => {
|
|
92
|
-
// same version
|
|
93
|
-
// eslint-disable-next-line @typescript-eslint/no-deprecated
|
|
94
|
-
defineMigrations({
|
|
95
|
-
firstVersion: Versions.Initial,
|
|
96
|
-
currentVersion: Versions.Initial,
|
|
97
|
-
migrators: {},
|
|
98
|
-
})
|
|
99
|
-
}).toThrow()
|
|
100
|
-
|
|
101
|
-
expect(() => {
|
|
102
|
-
// only first version
|
|
103
|
-
// eslint-disable-next-line @typescript-eslint/no-deprecated
|
|
104
|
-
defineMigrations({
|
|
105
|
-
firstVersion: Versions.January,
|
|
106
|
-
migrators: {},
|
|
107
|
-
})
|
|
108
|
-
}).not.toThrow()
|
|
109
|
-
|
|
110
|
-
expect(() => {
|
|
111
|
-
// missing only version
|
|
112
|
-
// eslint-disable-next-line @typescript-eslint/no-deprecated
|
|
113
|
-
defineMigrations({
|
|
114
|
-
firstVersion: Versions.January,
|
|
115
|
-
currentVersion: Versions.January,
|
|
116
|
-
migrators: {},
|
|
117
|
-
})
|
|
118
|
-
}).toThrow()
|
|
119
|
-
|
|
120
|
-
expect(() => {
|
|
121
|
-
// only version, explicit start and current
|
|
122
|
-
// eslint-disable-next-line @typescript-eslint/no-deprecated
|
|
123
|
-
defineMigrations({
|
|
124
|
-
firstVersion: Versions.January,
|
|
125
|
-
currentVersion: Versions.January,
|
|
126
|
-
migrators: {
|
|
127
|
-
[Versions.January]: {
|
|
128
|
-
up: (rec: any) => rec,
|
|
129
|
-
down: (rec: any) => rec,
|
|
130
|
-
},
|
|
131
|
-
},
|
|
132
|
-
})
|
|
133
|
-
}).toThrow()
|
|
134
|
-
|
|
135
|
-
expect(() => {
|
|
136
|
-
// missing later versions
|
|
137
|
-
// eslint-disable-next-line @typescript-eslint/no-deprecated
|
|
138
|
-
defineMigrations({
|
|
139
|
-
firstVersion: Versions.January,
|
|
140
|
-
currentVersion: Versions.February,
|
|
141
|
-
migrators: {},
|
|
142
|
-
})
|
|
143
|
-
}).not.toThrow()
|
|
144
|
-
|
|
145
|
-
expect(() => {
|
|
146
|
-
// missing later versions
|
|
147
|
-
// eslint-disable-next-line @typescript-eslint/no-deprecated
|
|
148
|
-
defineMigrations({
|
|
149
|
-
firstVersion: Versions.Initial,
|
|
150
|
-
currentVersion: Versions.February,
|
|
151
|
-
migrators: {
|
|
152
|
-
[Versions.January]: {
|
|
153
|
-
up: (rec: any) => rec,
|
|
154
|
-
down: (rec: any) => rec,
|
|
155
|
-
},
|
|
156
|
-
},
|
|
157
|
-
})
|
|
158
|
-
}).not.toThrow()
|
|
159
|
-
|
|
160
|
-
expect(() => {
|
|
161
|
-
// missing earlier versions
|
|
162
|
-
// eslint-disable-next-line @typescript-eslint/no-deprecated
|
|
163
|
-
defineMigrations({
|
|
164
|
-
firstVersion: Versions.Initial,
|
|
165
|
-
currentVersion: Versions.February,
|
|
166
|
-
migrators: {
|
|
167
|
-
[Versions.February]: {
|
|
168
|
-
up: (rec: any) => rec,
|
|
169
|
-
down: (rec: any) => rec,
|
|
170
|
-
},
|
|
171
|
-
},
|
|
172
|
-
})
|
|
173
|
-
}).not.toThrow()
|
|
174
|
-
|
|
175
|
-
expect(() => {
|
|
176
|
-
// got em all
|
|
177
|
-
// eslint-disable-next-line @typescript-eslint/no-deprecated
|
|
178
|
-
defineMigrations({
|
|
179
|
-
firstVersion: Versions.Initial,
|
|
180
|
-
currentVersion: Versions.February,
|
|
181
|
-
migrators: {
|
|
182
|
-
[Versions.January]: {
|
|
183
|
-
up: (rec: any) => rec,
|
|
184
|
-
down: (rec: any) => rec,
|
|
185
|
-
},
|
|
186
|
-
[Versions.February]: {
|
|
187
|
-
up: (rec: any) => rec,
|
|
188
|
-
down: (rec: any) => rec,
|
|
189
|
-
},
|
|
190
|
-
},
|
|
191
|
-
})
|
|
192
|
-
}).not.toThrow()
|
|
193
|
-
|
|
194
|
-
expect(() => {
|
|
195
|
-
// got em all starting later
|
|
196
|
-
// eslint-disable-next-line @typescript-eslint/no-deprecated
|
|
197
|
-
defineMigrations({
|
|
198
|
-
firstVersion: Versions.January,
|
|
199
|
-
currentVersion: Versions.March,
|
|
200
|
-
migrators: {
|
|
201
|
-
[Versions.February]: {
|
|
202
|
-
up: (rec: any) => rec,
|
|
203
|
-
down: (rec: any) => rec,
|
|
204
|
-
},
|
|
205
|
-
[Versions.March]: {
|
|
206
|
-
up: (rec: any) => rec,
|
|
207
|
-
down: (rec: any) => rec,
|
|
208
|
-
},
|
|
209
|
-
},
|
|
210
|
-
})
|
|
211
|
-
}).not.toThrow()
|
|
212
|
-
|
|
213
|
-
expect(() => {
|
|
214
|
-
// first migration should be first version + 1
|
|
215
|
-
// eslint-disable-next-line @typescript-eslint/no-deprecated
|
|
216
|
-
defineMigrations({
|
|
217
|
-
firstVersion: Versions.February,
|
|
218
|
-
currentVersion: Versions.March,
|
|
219
|
-
migrators: {
|
|
220
|
-
[Versions.February]: {
|
|
221
|
-
up: (rec: any) => rec,
|
|
222
|
-
down: (rec: any) => rec,
|
|
223
|
-
},
|
|
224
|
-
[Versions.March]: {
|
|
225
|
-
up: (rec: any) => rec,
|
|
226
|
-
down: (rec: any) => rec,
|
|
227
|
-
},
|
|
228
|
-
},
|
|
229
|
-
})
|
|
230
|
-
}).not.toThrow()
|
|
231
|
-
})
|
|
232
|
-
})
|