@@ -19,7 +19,7 @@ public actor Datastore<
1919 let key : DatastoreKey
2020 let version : Version
2121 let encoder : ( _ instance: CodedType ) async throws -> Data
22- let decoders : [ Version : ( _ data: Data ) async throws -> CodedType ]
22+ let decoders : [ Version : ( _ data: Data ) async throws -> ( id : IdentifierType , instance : CodedType ) ]
2323 let directIndexes : [ IndexPath < CodedType , _AnyIndexed > ]
2424 let computedIndexes : [ IndexPath < CodedType , _AnyIndexed > ]
2525
@@ -41,7 +41,7 @@ public actor Datastore<
4141 codedType: CodedType . Type = CodedType . self,
4242 identifierType: IdentifierType . Type ,
4343 encoder: @escaping ( _ instance: CodedType ) async throws -> Data ,
44- decoders: [ Version : ( _ data: Data ) async throws -> CodedType ] ,
44+ decoders: [ Version : ( _ data: Data ) async throws -> ( id : IdentifierType , instance : CodedType ) ] ,
4545 directIndexes: [ IndexPath < CodedType , _AnyIndexed > ] = [ ] ,
4646 computedIndexes: [ IndexPath < CodedType , _AnyIndexed > ] = [ ] ,
4747 configuration: Configuration = . init( )
@@ -53,6 +53,11 @@ public actor Datastore<
5353 self . decoders = decoders
5454 self . directIndexes = directIndexes
5555 self . computedIndexes = computedIndexes
56+
57+ for decoderVersion in Version . allCases {
58+ guard decoders [ decoderVersion] == nil else { continue }
59+ assertionFailure ( " Decoders missing case for \( decoderVersion) . Please make sure you have a decoder configured for this version or you may encounter errors at runtime. " )
60+ }
5661 }
5762
5863 public init (
@@ -61,7 +66,7 @@ public actor Datastore<
6166 version: Version ,
6267 codedType: CodedType . Type = CodedType . self,
6368 identifierType: IdentifierType . Type ,
64- decoders: [ Version : ( _ data: Data ) async throws -> CodedType ] ,
69+ decoders: [ Version : ( _ data: Data ) async throws -> ( id : IdentifierType , instance : CodedType ) ] ,
6570 directIndexes: [ IndexPath < CodedType , _AnyIndexed > ] = [ ] ,
6671 computedIndexes: [ IndexPath < CodedType , _AnyIndexed > ] = [ ] ,
6772 configuration: Configuration = . init( )
@@ -95,7 +100,7 @@ extension Datastore {
95100 return descriptor
96101 }
97102
98- func decoder( for version: Version ) throws -> ( _ data: Data ) async throws -> CodedType {
103+ func decoder( for version: Version ) throws -> ( _ data: Data ) async throws -> ( id : IdentifierType , instance : CodedType ) {
99104 guard let decoder = decoders [ version] else {
100105 throw DatastoreError . missingDecoder ( version: String ( describing: version) )
101106 }
@@ -272,7 +277,7 @@ extension Datastore {
272277
273278 let entryVersion = try Version ( persistedEntry. versionData)
274279 let decoder = try await self . decoder ( for: entryVersion)
275- let instance = try await decoder ( persistedEntry. instanceData)
280+ let instance = try await decoder ( persistedEntry. instanceData) . instance
276281
277282 return instance
278283 } catch DatastoreInterfaceError . instanceNotFound {
@@ -297,7 +302,7 @@ extension Datastore {
297302 try await transaction. primaryIndexScan ( range: range. applying ( order) , datastoreKey: self . key) { versionData, instanceData in
298303 let entryVersion = try Version ( versionData)
299304 let decoder = try await self . decoder ( for: entryVersion)
300- let instance = try await decoder ( instanceData)
305+ let instance = try await decoder ( instanceData) . instance
301306
302307 try await provider. yield ( instance)
303308 }
@@ -342,7 +347,7 @@ extension Datastore {
342347 ) { versionData, instanceData in
343348 let entryVersion = try Version ( versionData)
344349 let decoder = try await self . decoder ( for: entryVersion)
345- let instance = try await decoder ( instanceData)
350+ let instance = try await decoder ( instanceData) . instance
346351
347352 try await provider. yield ( instance)
348353 }
@@ -356,7 +361,7 @@ extension Datastore {
356361
357362 let entryVersion = try Version ( persistedEntry. versionData)
358363 let decoder = try await self . decoder ( for: entryVersion)
359- let instance = try await decoder ( persistedEntry. instanceData)
364+ let instance = try await decoder ( persistedEntry. instanceData) . instance
360365
361366 try await provider. yield ( instance)
362367 }
@@ -416,7 +421,7 @@ extension Datastore {
416421 try ? await event. mapEntries { entry in
417422 let version = try Version ( entry. versionData)
418423 let decoder = try await self . decoder ( for: version)
419- let instance = try await decoder ( entry. instanceData)
424+ let instance = try await decoder ( entry. instanceData) . instance
420425 return instance
421426 }
422427 }
@@ -453,7 +458,7 @@ extension Datastore where AccessMode == ReadWrite {
453458
454459 let existingVersion = try Version ( existingEntry. versionData)
455460 let decoder = try await self . decoder ( for: existingVersion)
456- let existingInstance = try await decoder ( existingEntry. instanceData)
461+ let existingInstance = try await decoder ( existingEntry. instanceData) . instance
457462
458463 return (
459464 cursor: existingEntry. cursor,
@@ -664,7 +669,7 @@ extension Datastore where AccessMode == ReadWrite {
664669 @discardableResult
665670 public func delete( _ idenfifier: IdentifierType ) async throws -> CodedType {
666671 try await warmupIfNeeded ( )
667-
672+
668673 return try await persistence. _withTransaction (
669674 actionName: " Delete Entry " ,
670675 options: [ . idempotent]
@@ -678,7 +683,7 @@ extension Datastore where AccessMode == ReadWrite {
678683 /// Load the instance completely so we can delete the entry within the direct and secondary indexes too.
679684 let existingVersion = try Version ( existingEntry. versionData)
680685 let decoder = try await self . decoder ( for: existingVersion)
681- let existingInstance = try await decoder ( existingEntry. instanceData)
686+ let existingInstance = try await decoder ( existingEntry. instanceData) . instance
682687
683688 try await transaction. emit (
684689 event: . deleted(
@@ -805,7 +810,7 @@ extension Datastore where AccessMode == ReadWrite {
805810 identifierType: IdentifierType . Type ,
806811 encoder: JSONEncoder = JSONEncoder ( ) ,
807812 decoder: JSONDecoder = JSONDecoder ( ) ,
808- migrations: [ Version : ( _ data: Data , _ decoder: JSONDecoder ) async throws -> CodedType ] ,
813+ migrations: [ Version : ( _ data: Data , _ decoder: JSONDecoder ) async throws -> ( id : IdentifierType , instance : CodedType ) ] ,
809814 directIndexes: [ IndexPath < CodedType , _AnyIndexed > ] = [ ] ,
810815 computedIndexes: [ IndexPath < CodedType , _AnyIndexed > ] = [ ] ,
811816 configuration: Configuration = . init( )
@@ -817,11 +822,9 @@ extension Datastore where AccessMode == ReadWrite {
817822 codedType: codedType,
818823 identifierType: identifierType,
819824 encoder: { try encoder. encode ( $0) } ,
820- decoders: migrations. mapValues ( { migration in
821- return { data in
822- return try await migration ( data, decoder)
823- }
824- } ) ,
825+ decoders: migrations. mapValues { migration in
826+ { data in try await migration ( data, decoder) }
827+ } ,
825828 directIndexes: directIndexes,
826829 computedIndexes: computedIndexes,
827830 configuration: configuration
@@ -835,7 +838,7 @@ extension Datastore where AccessMode == ReadWrite {
835838 codedType: CodedType . Type = CodedType . self,
836839 identifierType: IdentifierType . Type ,
837840 outputFormat: PropertyListSerialization . PropertyListFormat = . binary,
838- migrations: [ Version : ( _ data: Data , _ decoder: PropertyListDecoder ) async throws -> CodedType ] ,
841+ migrations: [ Version : ( _ data: Data , _ decoder: PropertyListDecoder ) async throws -> ( id : IdentifierType , instance : CodedType ) ] ,
839842 directIndexes: [ IndexPath < CodedType , _AnyIndexed > ] = [ ] ,
840843 computedIndexes: [ IndexPath < CodedType , _AnyIndexed > ] = [ ] ,
841844 configuration: Configuration = . init( )
@@ -852,11 +855,9 @@ extension Datastore where AccessMode == ReadWrite {
852855 codedType: codedType,
853856 identifierType: identifierType,
854857 encoder: { try encoder. encode ( $0) } ,
855- decoders: migrations. mapValues ( { migration in
856- return { data in
857- return try await migration ( data, decoder)
858- }
859- } ) ,
858+ decoders: migrations. mapValues { migration in
859+ { data in try await migration ( data, decoder) }
860+ } ,
860861 directIndexes: directIndexes,
861862 computedIndexes: computedIndexes,
862863 configuration: configuration
@@ -872,7 +873,7 @@ extension Datastore where AccessMode == ReadOnly {
872873 codedType: CodedType . Type = CodedType . self,
873874 identifierType: IdentifierType . Type ,
874875 decoder: JSONDecoder = JSONDecoder ( ) ,
875- migrations: [ Version : ( _ data: Data , _ decoder: JSONDecoder ) async throws -> CodedType ] ,
876+ migrations: [ Version : ( _ data: Data , _ decoder: JSONDecoder ) async throws -> ( id : IdentifierType , instance : CodedType ) ] ,
876877 directIndexes: [ IndexPath < CodedType , _AnyIndexed > ] = [ ] ,
877878 computedIndexes: [ IndexPath < CodedType , _AnyIndexed > ] = [ ] ,
878879 configuration: Configuration = . init( )
@@ -883,11 +884,9 @@ extension Datastore where AccessMode == ReadOnly {
883884 version: version,
884885 codedType: codedType,
885886 identifierType: identifierType,
886- decoders: migrations. mapValues ( { migration in
887- return { data in
888- return try await migration ( data, decoder)
889- }
890- } ) ,
887+ decoders: migrations. mapValues { migration in
888+ { data in try await migration ( data, decoder) }
889+ } ,
891890 directIndexes: directIndexes,
892891 computedIndexes: computedIndexes,
893892 configuration: configuration
@@ -900,7 +899,7 @@ extension Datastore where AccessMode == ReadOnly {
900899 version: Version ,
901900 codedType: CodedType . Type = CodedType . self,
902901 identifierType: IdentifierType . Type ,
903- migrations: [ Version : ( _ data: Data , _ decoder: PropertyListDecoder ) async throws -> CodedType ] ,
902+ migrations: [ Version : ( _ data: Data , _ decoder: PropertyListDecoder ) async throws -> ( id : IdentifierType , instance : CodedType ) ] ,
904903 directIndexes: [ IndexPath < CodedType , _AnyIndexed > ] = [ ] ,
905904 computedIndexes: [ IndexPath < CodedType , _AnyIndexed > ] = [ ] ,
906905 configuration: Configuration = . init( )
@@ -913,11 +912,9 @@ extension Datastore where AccessMode == ReadOnly {
913912 version: version,
914913 codedType: codedType,
915914 identifierType: identifierType,
916- decoders: migrations. mapValues ( { migration in
917- return { data in
918- return try await migration ( data, decoder)
919- }
920- } ) ,
915+ decoders: migrations. mapValues { migration in
916+ { data in try await migration ( data, decoder) }
917+ } ,
921918 directIndexes: directIndexes,
922919 computedIndexes: computedIndexes,
923920 configuration: configuration
@@ -946,7 +943,12 @@ extension Datastore where CodedType: Identifiable, IdentifierType == CodedType.I
946943 codedType: codedType,
947944 identifierType: codedType. ID. self,
948945 encoder: encoder,
949- decoders: decoders,
946+ decoders: decoders. mapValues { decoder in
947+ { data in
948+ let instance = try await decoder ( data)
949+ return ( id: instance. id, instance: instance)
950+ }
951+ } ,
950952 directIndexes: directIndexes,
951953 computedIndexes: computedIndexes,
952954 configuration: configuration
@@ -973,7 +975,12 @@ extension Datastore where CodedType: Identifiable, IdentifierType == CodedType.I
973975 identifierType: codedType. ID. self,
974976 encoder: encoder,
975977 decoder: decoder,
976- migrations: migrations,
978+ migrations: migrations. mapValues { migration in
979+ { data, decoder in
980+ let instance = try await migration ( data, decoder)
981+ return ( id: instance. id, instance: instance)
982+ }
983+ } ,
977984 directIndexes: directIndexes,
978985 computedIndexes: computedIndexes,
979986 configuration: configuration
@@ -998,7 +1005,12 @@ extension Datastore where CodedType: Identifiable, IdentifierType == CodedType.I
9981005 codedType: codedType,
9991006 identifierType: codedType. ID. self,
10001007 outputFormat: outputFormat,
1001- migrations: migrations,
1008+ migrations: migrations. mapValues { migration in
1009+ { data, decoder in
1010+ let instance = try await migration ( data, decoder)
1011+ return ( id: instance. id, instance: instance)
1012+ }
1013+ } ,
10021014 directIndexes: directIndexes,
10031015 computedIndexes: computedIndexes,
10041016 configuration: configuration
@@ -1023,7 +1035,12 @@ extension Datastore where CodedType: Identifiable, IdentifierType == CodedType.I
10231035 version: version,
10241036 codedType: codedType,
10251037 identifierType: codedType. ID. self,
1026- decoders: decoders,
1038+ decoders: decoders. mapValues { decoder in
1039+ { data in
1040+ let instance = try await decoder ( data)
1041+ return ( id: instance. id, instance: instance)
1042+ }
1043+ } ,
10271044 directIndexes: directIndexes,
10281045 computedIndexes: computedIndexes,
10291046 configuration: configuration
@@ -1048,7 +1065,12 @@ extension Datastore where CodedType: Identifiable, IdentifierType == CodedType.I
10481065 codedType: codedType,
10491066 identifierType: codedType. ID. self,
10501067 decoder: decoder,
1051- migrations: migrations,
1068+ migrations: migrations. mapValues { migration in
1069+ { data, decoder in
1070+ let instance = try await migration ( data, decoder)
1071+ return ( id: instance. id, instance: instance)
1072+ }
1073+ } ,
10521074 directIndexes: directIndexes,
10531075 computedIndexes: computedIndexes,
10541076 configuration: configuration
@@ -1071,7 +1093,12 @@ extension Datastore where CodedType: Identifiable, IdentifierType == CodedType.I
10711093 version: version,
10721094 codedType: codedType,
10731095 identifierType: codedType. ID. self,
1074- migrations: migrations,
1096+ migrations: migrations. mapValues { migration in
1097+ { data, decoder in
1098+ let instance = try await migration ( data, decoder)
1099+ return ( id: instance. id, instance: instance)
1100+ }
1101+ } ,
10751102 directIndexes: directIndexes,
10761103 computedIndexes: computedIndexes,
10771104 configuration: configuration
0 commit comments