1- import { ParseResult , Schema } from "effect" ;
1+ import { Schema } from "effect" ;
22import { LoroDoc , LoroList , LoroMap } from "loro-crdt" ;
3- import { ActivitySchema , ActivityV1 , type ActivityV2 } from "./schema" ;
3+ import { ActivitySchema , AnyLoroDocSchema } from "./schema" ;
4+ import type { Version } from "./versioning" ;
45
5- /** 👇 Versioning management */
6-
7- const Version = [ 1 , 2 , 3 ] as const ;
8- export type Version = ( typeof Version ) [ number ] ;
96export const VERSION = 3 satisfies Version ;
107
11- /** 👆 Versioning management */
12-
13- const AnyLoroDocSchema = Schema . instanceOf ( LoroDoc ) ;
14-
158export const Metadata = Schema . Struct ( { version : Schema . Number } ) ;
169export const Activity = ActivitySchema [ VERSION ] ;
1710
1811export type LoroSchema = {
19- metadata : LoroMap < { version : number } > ;
12+ metadata : LoroMap < typeof Metadata . Encoded > ;
2013 activity : LoroList < LoroMap < typeof Activity . Encoded > > ;
2114} ;
2215
@@ -34,77 +27,6 @@ export class SnapshotSchema extends Schema.Class<SnapshotSchema>(
3427 } ;
3528}
3629
37- const migrations = {
38- 1 : ( doc ) => {
39- doc . getMap ( "metadata" ) . set ( "version" , VERSION ) ;
40- doc . getList ( "activity" ) ;
41- return doc ;
42- } ,
43- 2 : ( doc ) => {
44- doc . getMap ( "metadata" ) . set ( "version" , 2 ) ;
45-
46- const activity = doc . getList ( "activity" ) ;
47- for ( let i = 0 ; i < activity . length ; i ++ ) {
48- const item = activity . get ( i ) as LoroMap < typeof ActivityV1 . Encoded > ;
49- const map = new LoroMap ( ) ;
50- const [ firstName , lastName ] = item . get ( "name" ) . split ( " " ) ;
51- map . set ( "id" , item . get ( "id" ) ) ;
52- map . set ( "firstName" , firstName ) ;
53- map . set ( "lastName" , lastName ) ;
54- activity . insertContainer ( i , map ) ;
55- }
56-
57- return doc ;
58- } ,
59- 3 : ( doc ) => {
60- doc . getMap ( "metadata" ) . set ( "version" , 3 ) ;
61-
62- const activity = doc . getList ( "activity" ) ;
63- for ( let i = 0 ; i < activity . length ; i ++ ) {
64- const item = activity . get ( i ) as LoroMap < typeof ActivityV2 . Encoded > ;
65- const map = new LoroMap ( ) ;
66- map . set ( "id" , item . get ( "id" ) ) ;
67- map . set ( "firstName" , item . get ( "firstName" ) ) ;
68- map . set ( "lastName" , item . get ( "lastName" ) ) ;
69- map . set ( "age" , undefined ) ;
70- activity . insertContainer ( i , map ) ;
71- }
72-
73- return doc ;
74- } ,
75- } satisfies Record < Version , ( doc : LoroDoc ) => LoroDoc > ;
76-
77- export const LoroDocMigration = AnyLoroDocSchema . pipe (
78- Schema . transformOrFail ( AnyLoroDocSchema , {
79- decode : ( from , _ , ast ) => {
80- const doc = new LoroDoc ( ) ;
81- doc . import ( from . export ( { mode : "snapshot" } ) ) ;
82- const currentVersion = doc . getMap ( "metadata" ) . get ( "version" ) ;
83-
84- if ( typeof currentVersion === "number" ) {
85- Version . forEach ( ( version ) => {
86- doc . import ( migrations [ version ] ( doc ) . export ( { mode : "snapshot" } ) ) ;
87- } ) ;
88- } else {
89- return ParseResult . fail (
90- new ParseResult . Type ( ast , from , "Invalid version number in metadata" )
91- ) ;
92- }
93-
94- return ParseResult . succeed ( doc ) ;
95- } ,
96-
97- encode : ( to , _ , ast ) =>
98- ParseResult . fail (
99- new ParseResult . Forbidden (
100- ast ,
101- to ,
102- "Encoding LoroDoc migration is not allowed (should not happen...)"
103- )
104- ) ,
105- } )
106- ) ;
107-
10830export const SnapshotToLoroDoc = Schema . Uint8ArrayFromSelf . pipe (
10931 Schema . transform ( AnyLoroDocSchema , {
11032 decode : ( from ) => {
0 commit comments