@@ -12,44 +12,38 @@ import {
1212 DeleteCommand ,
1313 QueryCommand ,
1414 ScanCommand ,
15+ DynamoDBDocumentClient ,
1516} from "@aws-sdk/lib-dynamodb" ;
1617import type { User } from "../routes/users/users.js" ;
1718import DynamoDBService from "@sparta/utils/dynamo-db.js" ;
1819
19- // Type for extended DynamoDB with user methods
20- interface ExtendedDynamoDB {
21- getUser ( discordUserId : string ) : Promise < User | null > ;
22- getUserByVerificationId ( verificationId : string ) : Promise < User | null > ;
23- getUserByWalletAddress ( walletAddress : string ) : Promise < User | null > ;
24- getAllUsers ( ) : Promise < User [ ] > ;
25- createUser ( user : User ) : Promise < User | null > ;
26- updateUser ( discordUserId : string , updates : Partial < User > ) : Promise < boolean > ;
27- deleteUser ( discordUserId : string ) : Promise < boolean > ;
28- getClient ( ) : any ;
29- }
30-
3120const USERS_TABLE_NAME = process . env . USERS_TABLE_NAME || "users" ;
3221
3322// Instantiate the shared service for the users table
34- const dynamoDB = new DynamoDBService ( USERS_TABLE_NAME ) ;
23+ const dynamoDBService = new DynamoDBService ( USERS_TABLE_NAME ) ;
3524
36- const extendedDynamoDB = dynamoDB as unknown as ExtendedDynamoDB ;
25+ export class UserRepository {
26+ private client : DynamoDBDocumentClient ;
27+ private tableName : string ;
3728
38- logger . info ( "dynamoDB config" , dynamoDB . getClient ( ) . config ) ;
29+ constructor ( ) {
30+ this . tableName = USERS_TABLE_NAME ;
31+ // Get the client instance from the shared service
32+ this . client = dynamoDBService . getClient ( ) ;
33+ logger . info (
34+ `UserRepository initialized using shared DynamoDBService for table: ${ this . tableName } `
35+ ) ;
36+ }
3937
40- // Extend the DynamoDB service with user operations
41- export function extendDynamoDBWithUserMethods ( ) : void {
4238 // Get user by Discord ID
43- extendedDynamoDB . getUser = async (
44- discordUserId : string
45- ) : Promise < User | null > => {
39+ async getUser ( discordUserId : string ) : Promise < User | null > {
4640 try {
4741 const command = new GetCommand ( {
48- TableName : process . env . USERS_TABLE_NAME || "users" ,
42+ TableName : this . tableName ,
4943 Key : { discordUserId } ,
5044 } ) ;
5145
52- const response = await dynamoDB . getClient ( ) . send ( command ) ;
46+ const response = await this . client . send ( command ) ;
5347 return ( response . Item as User ) || null ;
5448 } catch ( error : any ) {
5549 logger . error (
@@ -58,23 +52,23 @@ export function extendDynamoDBWithUserMethods(): void {
5852 ) ;
5953 return null ;
6054 }
61- } ;
55+ }
6256
6357 // Get user by verification ID - uses the flattened verificationId index
64- extendedDynamoDB . getUserByVerificationId = async (
58+ async getUserByVerificationId (
6559 verificationId : string
66- ) : Promise < User | null > => {
60+ ) : Promise < User | null > {
6761 try {
6862 const command = new QueryCommand ( {
69- TableName : process . env . USERS_TABLE_NAME || "users" ,
63+ TableName : this . tableName ,
7064 IndexName : "verificationId-index" ,
7165 KeyConditionExpression : "verificationId = :verificationId" ,
7266 ExpressionAttributeValues : {
7367 ":verificationId" : verificationId ,
7468 } ,
7569 } ) ;
7670
77- const response = await dynamoDB . getClient ( ) . send ( command ) ;
71+ const response = await this . client . send ( command ) ;
7872
7973 if ( ! response . Items || response . Items . length === 0 ) {
8074 return null ;
@@ -92,26 +86,24 @@ export function extendDynamoDBWithUserMethods(): void {
9286 ) ;
9387 return null ;
9488 }
95- } ;
89+ }
9690
9791 // Get user by wallet address
98- extendedDynamoDB . getUserByWalletAddress = async (
99- walletAddress : string
100- ) : Promise < User | null > => {
92+ async getUserByWalletAddress ( walletAddress : string ) : Promise < User | null > {
10193 try {
10294 // Normalize wallet address (lowercase)
10395 const normalizedAddress = walletAddress . toLowerCase ( ) ;
10496
10597 const command = new QueryCommand ( {
106- TableName : process . env . USERS_TABLE_NAME || "users" ,
98+ TableName : this . tableName ,
10799 IndexName : "walletAddress-index" , // This assumes a GSI on walletAddress
108100 KeyConditionExpression : "walletAddress = :walletAddress" ,
109101 ExpressionAttributeValues : {
110102 ":walletAddress" : normalizedAddress ,
111103 } ,
112104 } ) ;
113105
114- const response = await dynamoDB . getClient ( ) . send ( command ) ;
106+ const response = await this . client . send ( command ) ;
115107
116108 if ( response . Items && response . Items . length > 0 ) {
117109 return response . Items [ 0 ] as User ;
@@ -125,25 +117,25 @@ export function extendDynamoDBWithUserMethods(): void {
125117 ) ;
126118 return null ;
127119 }
128- } ;
120+ }
129121
130122 // Get all users
131- extendedDynamoDB . getAllUsers = async ( ) : Promise < User [ ] > = > {
123+ async getAllUsers ( ) : Promise < User [ ] > {
132124 try {
133125 const command = new ScanCommand ( {
134- TableName : process . env . USERS_TABLE_NAME || "users" ,
126+ TableName : this . tableName ,
135127 } ) ;
136128
137- const response = await dynamoDB . getClient ( ) . send ( command ) ;
129+ const response = await this . client . send ( command ) ;
138130 return ( response . Items as User [ ] ) || [ ] ;
139131 } catch ( error : any ) {
140132 logger . error ( { error : error . message } , "Error getting all users" ) ;
141133 return [ ] ;
142134 }
143- } ;
135+ }
144136
145137 // Create a new user
146- extendedDynamoDB . createUser = async ( user : User ) : Promise < User | null > = > {
138+ async createUser ( user : User ) : Promise < User | null > {
147139 try {
148140 // Create a clean version of the user object for DynamoDB
149141 const dynamoUser : any = { ...user } ;
@@ -159,6 +151,12 @@ export function extendDynamoDBWithUserMethods(): void {
159151
160152 // Handle humanPassport fields - remove any null values to ensure proper indexing
161153 if ( dynamoUser . humanPassport ) {
154+ logger . debug (
155+ {
156+ dynamoUser : dynamoUser . humanPassport ,
157+ } ,
158+ "Human passport in createUser"
159+ ) ;
162160 const cleanHumanPassport : Record < string , any > = { } ;
163161
164162 // Only keep non-null values
@@ -186,26 +184,24 @@ export function extendDynamoDBWithUserMethods(): void {
186184 }
187185
188186 const command = new PutCommand ( {
189- TableName : process . env . USERS_TABLE_NAME || "users" ,
187+ TableName : this . tableName ,
190188 Item : dynamoUser ,
191189 ConditionExpression : "attribute_not_exists(discordUserId)" ,
192190 } ) ;
193191
194- logger . debug ( { command } , "Creating user in repository" ) ;
195-
196- await dynamoDB . getClient ( ) . send ( command ) ;
192+ await this . client . send ( command ) ;
197193 return user ;
198194 } catch ( error : any ) {
199195 logger . error ( { error : error . message , user } , "Error creating user" ) ;
200196 return null ;
201197 }
202- } ;
198+ }
203199
204200 // Update a user
205- extendedDynamoDB . updateUser = async (
201+ async updateUser (
206202 discordUserId : string ,
207203 updates : Partial < User >
208- ) : Promise < boolean > => {
204+ ) : Promise < boolean > {
209205 try {
210206 // Build update and remove expressions
211207 const updateExpressions : string [ ] = [ ] ;
@@ -289,15 +285,15 @@ export function extendDynamoDBWithUserMethods(): void {
289285 }
290286
291287 const command = new UpdateCommand ( {
292- TableName : process . env . USERS_TABLE_NAME || "users" ,
288+ TableName : this . tableName ,
293289 Key : { discordUserId } ,
294290 UpdateExpression : updateExpression ,
295291 ExpressionAttributeNames : expressionAttributeNames ,
296292 ExpressionAttributeValues : expressionAttributeValues ,
297293 ReturnValues : "UPDATED_NEW" ,
298294 } ) ;
299295
300- await dynamoDB . getClient ( ) . send ( command ) ;
296+ await this . client . send ( command ) ;
301297 return true ;
302298 } catch ( error : any ) {
303299 logger . error (
@@ -306,19 +302,17 @@ export function extendDynamoDBWithUserMethods(): void {
306302 ) ;
307303 return false ;
308304 }
309- } ;
305+ }
310306
311307 // Delete a user
312- extendedDynamoDB . deleteUser = async (
313- discordUserId : string
314- ) : Promise < boolean > => {
308+ async deleteUser ( discordUserId : string ) : Promise < boolean > {
315309 try {
316310 const command = new DeleteCommand ( {
317- TableName : process . env . USERS_TABLE_NAME || "users" ,
311+ TableName : this . tableName ,
318312 Key : { discordUserId } ,
319313 } ) ;
320314
321- await dynamoDB . getClient ( ) . send ( command ) ;
315+ await this . client . send ( command ) ;
322316 return true ;
323317 } catch ( error : any ) {
324318 logger . error (
@@ -327,14 +321,8 @@ export function extendDynamoDBWithUserMethods(): void {
327321 ) ;
328322 return false ;
329323 }
330- } ;
324+ }
331325}
332326
333- // Export the extended dynamoDB for use in other modules
334- export { extendedDynamoDB } ;
335-
336- // Export function to initialize - this will be called during app startup
337- export function initializeUserRepository ( ) : void {
338- extendDynamoDBWithUserMethods ( ) ;
339- logger . info ( "User repository initialized" ) ;
340- }
327+ // Export a singleton instance of the repository
328+ export const userRepository = new UserRepository ( ) ;
0 commit comments