@@ -6,12 +6,13 @@ import { BatchArgsHandler } from "./batch-args-handler";
66import {
77 FieldsToProject ,
88 toProjectionExpression ,
9- getDefaultFieldsToProject ,
9+ getAllProjectableFields ,
1010} from "./utils/ProjectFields" ;
1111import { createSTDError , isSingleTableDynamoError } from "./utils/errors" ;
1212import { z } from "zod" ;
13+ import { goTry } from "./utils/goTry" ;
1314
14- type ExtraQueryParams < T > = {
15+ type GetOptions < T > = {
1516 fieldsToProject : FieldsToProject < T > ;
1617} ;
1718
@@ -58,34 +59,64 @@ export class Repository<
5859 this . ddb = ddb ;
5960 }
6061
61- private doGet ( id : ID , extraParams : ExtraQueryParams < Output > ) {
62+ private async doGet (
63+ id : ID ,
64+ options : GetOptions < Output >
65+ ) : Promise < Output | null > {
6266 const args = {
6367 TableName : this . args . tableName ,
64- ...toProjectionExpression ( extraParams . fieldsToProject ) ,
68+ ...toProjectionExpression ( options . fieldsToProject ) ,
6569 Key : this . mapper . getKey ( id ) ,
6670 } ;
6771
68- return this . args . getDocument
72+ const res = await ( this . args . getDocument
6973 ? this . args . getDocument ( args )
70- : this . ddb . get ( args ) . promise ( ) ;
74+ : this . ddb . get ( args ) . promise ( ) ) ;
75+
76+ if ( ! res . Item ) {
77+ return null ;
78+ }
79+ const [ item , err ] = goTry ( ( ) =>
80+ this . mapper . pickedParse ( res . Item , options . fieldsToProject , "output" )
81+ ) ;
82+ // we got a parse error :O
83+ if ( err ) {
84+ if ( this . args . migrate ) {
85+ if ( this . isProjectingAllFields ( options . fieldsToProject ) ) {
86+ // if this is the full version that's in the db
87+ return this . args . migrate ( res . Item ) ;
88+ } else {
89+ const fullMigratedResult = await this . doGet ( id , {
90+ fieldsToProject : getAllProjectableFields ( this . args ) ,
91+ } ) ;
92+
93+ return this . mapper . pickedParse (
94+ fullMigratedResult ,
95+ options . fieldsToProject ,
96+ "output"
97+ ) as any ;
98+ }
99+ }
100+ throw err ;
101+ }
102+ return item as Output ;
103+ }
104+
105+ isProjectingAllFields ( fieldsToProject : FieldsToProject < Output > ) {
106+ const s = new Set ( fieldsToProject ) ;
107+ const allFields = getAllProjectableFields ( this . args ) ;
108+ return allFields . every ( ( f ) => s . has ( f ) ) ;
71109 }
72110
73111 async get (
74112 id : ID ,
75- extraParams : ExtraQueryParams < Output > = {
76- fieldsToProject : getDefaultFieldsToProject < Output > ( this . args as any ) ,
113+ extraParams : GetOptions < Output > = {
114+ fieldsToProject : getAllProjectableFields ( this . args ) ,
77115 }
78116 ) {
79117 try {
80- const res = await this . doGet ( id , extraParams ) ;
118+ const item : Output | null = await this . doGet ( id , extraParams ) ;
81119
82- let item : Output | null = res . Item
83- ? ( this . mapper . pickedParse (
84- res . Item ,
85- extraParams . fieldsToProject ,
86- "output"
87- ) as any )
88- : null ;
89120 this . args . on ?. get ?.(
90121 [ id , extraParams as any ] ,
91122 item ,
@@ -284,7 +315,7 @@ export class Repository<
284315 tableName : this . args . tableName ,
285316 index : this . getIndexByTag ( indexTag ) ,
286317 mapper : this . mapper as any ,
287- fieldsToProject : getDefaultFieldsToProject ( this . args ) ,
318+ fieldsToProject : getAllProjectableFields ( this . args ) ,
288319 ddb : this . ddb ,
289320 } ) ;
290321 return builder ;
0 commit comments