@@ -28,6 +28,14 @@ import { v4 as uuidv4 } from "uuid";
2828
2929import { Feedback , Publication , Purchase , Refund , Tester } from "../types/data" ;
3030
31+ /**
32+ * Interface for the OAuth ID to tester UUID mapping
33+ */
34+ interface IdMapping {
35+ id : string ; // OAuth ID (primary key)
36+ testerUuid : string ; // Reference to tester UUID
37+ }
38+
3139// Sample data collections
3240const testersData : Tester [ ] = [
3341 {
@@ -42,6 +50,20 @@ const testersData: Tester[] = [
4250 } ,
4351] ;
4452
53+ /**
54+ * ID mappings table - simulates a separate table for ID lookups
55+ */
56+ const idMappingsData : IdMapping [ ] = [
57+ {
58+ id : "auth0|1234567890" ,
59+ testerUuid : "45f9830a-309b-4cda-95ec-71e000b78f7d" ,
60+ } ,
61+ {
62+ id : "auth0|0987654321" ,
63+ testerUuid : "cc97a5cc-c4ba-4804-98b5-90532f09bd83" ,
64+ } ,
65+ ] ;
66+
4567const purchasesData : Purchase [ ] = [
4668 {
4769 id : "d5726cf2-36f6-41d8-bd37-f349314561b4" ,
@@ -126,6 +148,100 @@ const refundsData: Refund[] = [
126148 * Provides CRUD-like operations for all data types
127149 */
128150export const mockDb = {
151+ /**
152+ * ID mappings operations
153+ */
154+ idMappings : {
155+ /**
156+ * Check if an ID exists in the database
157+ * @param {string } id - The OAuth ID to check
158+ * @returns {boolean } True if the ID exists, false otherwise
159+ */
160+ exists : ( id : string ) : boolean => {
161+ return idMappingsData . some ( ( mapping ) => mapping . id === id ) ;
162+ } ,
163+
164+ /**
165+ * Check if multiple IDs exist in the database
166+ * @param {string[] } ids - Array of OAuth IDs to check
167+ * @returns {string[] } Array of IDs that already exist
168+ */
169+ existsMultiple : ( ids : string [ ] ) : string [ ] => {
170+ return ids . filter ( ( id ) =>
171+ idMappingsData . some ( ( mapping ) => mapping . id === id ) ,
172+ ) ;
173+ } ,
174+
175+ /**
176+ * Get the tester UUID associated with an ID
177+ * @param {string } id - The OAuth ID to look up
178+ * @returns {string|undefined } The associated tester UUID if found
179+ */
180+ getTesterUuid : ( id : string ) : string | undefined => {
181+ const mapping = idMappingsData . find ( ( mapping ) => mapping . id === id ) ;
182+
183+ return mapping ?. testerUuid ;
184+ } ,
185+
186+ /**
187+ * Add a new ID to tester mapping
188+ * @param {string } id - The OAuth ID
189+ * @param {string } testerUuid - The associated tester UUID
190+ * @returns {boolean } True if successful, false if ID already exists
191+ */
192+ put : ( id : string , testerUuid : string ) : boolean => {
193+ if ( idMappingsData . some ( ( mapping ) => mapping . id === id ) ) {
194+ return false ; // ID already exists
195+ }
196+
197+ idMappingsData . push ( { id, testerUuid } ) ;
198+
199+ return true ;
200+ } ,
201+
202+ /**
203+ * Add multiple ID to tester mappings
204+ * @param {string[] } ids - Array of OAuth IDs
205+ * @param {string } testerUuid - The associated tester UUID
206+ * @returns {string[] } Array of IDs that were successfully added
207+ */
208+ putMultiple : ( ids : string [ ] , testerUuid : string ) : string [ ] => {
209+ const addedIds : string [ ] = [ ] ;
210+
211+ for ( const id of ids ) {
212+ if ( ! idMappingsData . some ( ( mapping ) => mapping . id === id ) ) {
213+ idMappingsData . push ( { id, testerUuid } ) ;
214+ addedIds . push ( id ) ;
215+ }
216+ }
217+
218+ return addedIds ;
219+ } ,
220+
221+ /**
222+ * Delete an ID mapping
223+ * @param {string } id - The OAuth ID to delete
224+ * @returns {boolean } True if successful, false if ID not found
225+ */
226+ delete : ( id : string ) : boolean => {
227+ const index = idMappingsData . findIndex ( ( mapping ) => mapping . id === id ) ;
228+
229+ if ( index >= 0 ) {
230+ idMappingsData . splice ( index , 1 ) ;
231+
232+ return true ;
233+ }
234+
235+ return false ;
236+ } ,
237+
238+ /**
239+ * Get all ID mappings
240+ * @returns {IdMapping[] } Copy of all ID mappings
241+ */
242+ getAll : ( ) => [ ...idMappingsData ] ,
243+ } ,
244+
129245 /**
130246 * Tester-related database operations
131247 */
@@ -156,6 +272,24 @@ export const mockDb = {
156272
157273 if ( index >= 0 ) {
158274 // Update existing tester
275+ const oldIds = testersData [ index ] . ids ;
276+ const newIds = newTester . ids ;
277+
278+ // Remove old ID mappings that are no longer in the tester's ID list
279+ for ( const oldId of oldIds ) {
280+ if ( ! newIds . includes ( oldId ) ) {
281+ mockDb . idMappings . delete ( oldId ) ;
282+ }
283+ }
284+
285+ // Add new ID mappings
286+ for ( const newId of newIds ) {
287+ if ( ! oldIds . includes ( newId ) ) {
288+ mockDb . idMappings . put ( newId , newTester . uuid ) ;
289+ }
290+ }
291+
292+ // Update the tester
159293 testersData [ index ] = newTester ;
160294
161295 return newTester . ids ;
@@ -164,6 +298,11 @@ export const mockDb = {
164298 if ( ! newTester . uuid ) {
165299 newTester . uuid = uuidv4 ( ) ;
166300 }
301+
302+ // Add ID mappings for all IDs in the new tester
303+ mockDb . idMappings . putMultiple ( newTester . ids , newTester . uuid ) ;
304+
305+ // Add the tester
167306 testersData . push ( newTester ) ;
168307
169308 return newTester . ids ;
@@ -177,12 +316,17 @@ export const mockDb = {
177316 getAll : ( ) => [ ...testersData ] ,
178317
179318 /**
180- * Find a tester by their authentication ID
319+ * Find a tester by their authentication ID (efficient lookup using ID mappings)
181320 * @param {string } id - Authentication ID to search for
182321 * @returns {Tester|undefined } The matching tester or undefined if not found
183322 */
184- getTesterWithId : ( id : string ) =>
185- testersData . find ( ( tester ) => tester . ids . includes ( id ) ) ,
323+ getTesterWithId : ( id : string ) => {
324+ const testerUuid = mockDb . idMappings . getTesterUuid ( id ) ;
325+
326+ if ( ! testerUuid ) return undefined ;
327+
328+ return testersData . find ( ( tester ) => tester . uuid === testerUuid ) ;
329+ } ,
186330
187331 /**
188332 * Find a tester by their UUID
@@ -191,6 +335,33 @@ export const mockDb = {
191335 */
192336 getTesterWithUuid : ( uuid : string ) =>
193337 testersData . find ( ( tester ) => tester . uuid === uuid ) ,
338+
339+ /**
340+ * Add IDs to an existing tester
341+ * @param {string } uuid - UUID of the tester to update
342+ * @param {string[] } ids - IDs to add to the tester
343+ * @returns {string[]|undefined } Updated list of IDs if successful, undefined if tester not found
344+ */
345+ addIds : ( uuid : string , ids : string [ ] ) : string [ ] | undefined => {
346+ const index = testersData . findIndex ( ( tester ) => tester . uuid === uuid ) ;
347+
348+ if ( index < 0 ) return undefined ;
349+
350+ // Get existing IDs
351+ const existingIds = testersData [ index ] . ids ;
352+ // Check which IDs don't already exist in the mappings table
353+ const newIds = ids . filter ( ( id ) => ! mockDb . idMappings . exists ( id ) ) ;
354+
355+ // Add new ID mappings
356+ mockDb . idMappings . putMultiple ( newIds , uuid ) ;
357+
358+ // Update tester with all IDs (existing + new)
359+ const allIds = [ ...existingIds , ...newIds ] ;
360+
361+ testersData [ index ] . ids = allIds ;
362+
363+ return allIds ;
364+ } ,
194365 } ,
195366
196367 /**
0 commit comments