66 DeleteCommandInput ,
77 GetCommandInput ,
88 GetCommandOutput ,
9+ NativeAttributeValue ,
910 PutCommandInput ,
1011 QueryCommandInput ,
1112 QueryCommandOutput ,
@@ -19,7 +20,6 @@ import {
1920 UpdateCommandOutput
2021} from '@aws-sdk/lib-dynamodb'
2122import { DynamoDBInterface } from '@symphoniacloud/dynamodb-entity-store'
22- import { FakeTable } from './fakeDynamoDBTable.js'
2323
2424export const METADATA = { $metadata : { } }
2525
@@ -132,10 +132,87 @@ export class FakeDynamoDBInterface implements DynamoDBInterface {
132132 return this . getTable ( withTableName . TableName )
133133 }
134134
135- public getTable ( tableName : string | undefined ) {
135+ private getTable ( tableName : string | undefined ) {
136136 if ( ! tableName ) throw new Error ( 'Table name is required' )
137137 const table = this . tables [ tableName ]
138138 if ( ! table ) throw new Error ( `Table ${ tableName } not configured` )
139139 return table
140140 }
141+
142+ // Convenience functions
143+ public putToTable ( tableName : string , item : Record < string , NativeAttributeValue > ) {
144+ this . getTable ( tableName ) . putItem ( item )
145+ }
146+
147+ public getFromTable ( tableName : string , key : Record < string , NativeAttributeValue > ) {
148+ return this . getTable ( tableName ) . get ( key )
149+ }
150+
151+ public getAllFromTable ( tableName : string ) {
152+ return this . getTable ( tableName ) . allItems ( )
153+ }
154+ }
155+
156+ interface TableKey {
157+ PK : NativeAttributeValue
158+ SK ?: NativeAttributeValue
159+ }
160+
161+ class FakeTable {
162+ private readonly pkName : string
163+ private readonly skName : string | undefined
164+ private readonly items : Map < TableKey , Record < string , NativeAttributeValue > > = new Map <
165+ TableKey ,
166+ Record < string , NativeAttributeValue >
167+ > ( )
168+
169+ constructor ( pkName : string , skName : string | undefined ) {
170+ this . pkName = pkName
171+ this . skName = skName
172+ }
173+
174+ putItem ( item : Record < string , NativeAttributeValue > | undefined ) {
175+ if ( ! item ) return
176+ const itemKey = this . keyFromItem ( item )
177+ // Required because complex key type on items, and otherwise we'd get "duplicate" items
178+ this . items . set ( this . findMatchingKey ( itemKey ) ?? itemKey , item )
179+ }
180+
181+ get ( key : Record < string , NativeAttributeValue > | undefined ) {
182+ const matchingKey = this . findMatchingKey ( this . keyFromItem ( key ) )
183+ return matchingKey ? this . items . get ( matchingKey ) : undefined
184+ }
185+
186+ deleteItem ( key : Record < string , NativeAttributeValue > | undefined ) {
187+ const matchingKey = this . findMatchingKey ( this . keyFromItem ( key ) )
188+ if ( matchingKey ) {
189+ this . items . delete ( matchingKey )
190+ }
191+ }
192+
193+ allItems ( ) {
194+ return Array . from ( this . items . values ( ) )
195+ }
196+
197+ private keyFromItem ( item : Record < string , NativeAttributeValue > | undefined ) : TableKey {
198+ if ( ! item ) throw new Error ( 'Item is undefined' )
199+ const pkValue = item [ this . pkName ]
200+ if ( ! pkValue ) throw new Error ( `PK field [${ this . pkName } ] is not found` )
201+ if ( this . skName ) {
202+ const skValue = item [ this . skName ]
203+ if ( ! skValue ) throw new Error ( `SK field [${ this . skName } ] is not found` )
204+ return { PK : pkValue , SK : skValue }
205+ } else {
206+ return { PK : pkValue }
207+ }
208+ }
209+
210+ // Required because we have a complex key on items (a Map), and Map only matches object
211+ // complex keys if they are the same instance
212+ private findMatchingKey ( key : TableKey ) {
213+ for ( const tableKey of this . items . keys ( ) ) {
214+ if ( tableKey . PK === key . PK && tableKey . SK === key . SK ) return tableKey
215+ }
216+ return undefined
217+ }
141218}
0 commit comments