22 * Auto-generate MSW handlers from ObjectStack configuration
33 *
44 * This helper creates all necessary MSW handlers based on your
5- * objectstack.config.ts without requiring the full runtime .
5+ * objectstack.config.ts using the in-memory driver .
66 */
77
88import { http , HttpResponse } from 'msw' ;
9+ import { InMemoryDriver } from '@objectstack/driver-memory' ;
910
10- // Simple in-memory store
11- const stores = new Map < string , Map < string , any > > ( ) ;
12-
13- let idCounters = new Map < string , number > ( ) ;
14-
15- function getStore ( objectName : string ) : Map < string , any > {
16- if ( ! stores . has ( objectName ) ) {
17- stores . set ( objectName , new Map ( ) ) ;
18- }
19- return stores . get ( objectName ) ! ;
20- }
21-
22- function getNextId ( objectName : string ) : string {
23- const current = idCounters . get ( objectName ) || 0 ;
24- const next = current + 1 ;
25- idCounters . set ( objectName , next ) ;
26- return String ( next ) ;
27- }
11+ // Shared driver instance
12+ const driver = new InMemoryDriver ( ) ;
13+ driver . connect ( ) ;
2814
2915/**
3016 * Seed initial data for an object
3117 */
32- export function seedData ( objectName : string , records : any [ ] ) {
33- const store = getStore ( objectName ) ;
34- records . forEach ( ( record ) => {
35- const id = record . id || getNextId ( objectName ) ;
36- store . set ( id , { ...record , id } ) ;
37- } ) ;
18+ export async function seedData ( objectName : string , records : any [ ] ) {
19+ // Ensure table exists
20+ await driver . syncSchema ( objectName , { } ) ;
3821
39- // Initialize ID counter
40- const maxId = Math . max (
41- 0 ,
42- ...Array . from ( store . values ( ) ) . map ( r => parseInt ( r . id ) || 0 )
43- ) ;
44- idCounters . set ( objectName , maxId ) ;
22+ // Get existing records to determine insert vs update
23+ const existing = await driver . find ( objectName , { object : objectName } ) ;
24+
25+ for ( const record of records ) {
26+ const id = record . id ;
27+ // Check if record exists by ID
28+ const found = id ? existing . find ( ( r : any ) => r . id === id ) : null ;
29+
30+ if ( found ) {
31+ await driver . update ( objectName , id , record ) ;
32+ } else {
33+ await driver . create ( objectName , record ) ;
34+ }
35+ }
4536}
4637
4738/**
@@ -64,9 +55,12 @@ export function createMockHandlers(baseUrl: string = '/api/v1', metadata: any =
6455 }
6556 } ;
6657
67- // Generate handlers for both correct paths and doubled paths (client compatibility)
68- const paths = [ baseUrl , `${ baseUrl } /api/v1` ] ;
69-
58+ // Generate handlers for both correct paths and potential variations
59+ const paths = [ baseUrl ] ;
60+ if ( ! baseUrl . endsWith ( '/api/v1' ) ) {
61+ paths . push ( `${ baseUrl } /api/v1` ) ; // fallback compatibility
62+ }
63+
7064 const handlers = [ ] ;
7165
7266 for ( const path of paths ) {
@@ -110,30 +104,34 @@ export function createMockHandlers(baseUrl: string = '/api/v1', metadata: any =
110104 } ) ,
111105
112106 // Data: Find/List
113- http . get ( `${ path } /data/:object` , ( { params, request } ) => {
107+ http . get ( `${ path } /data/:object` , async ( { params, request } ) => {
114108 const objectName = params . object as string ;
115- const store = getStore ( objectName ) ;
116109 const url = new URL ( request . url ) ;
117110
118111 const top = parseInt ( url . searchParams . get ( 'top' ) || '100' ) ;
119112 const skip = parseInt ( url . searchParams . get ( '$skip' ) || '0' ) ;
120113
121- const records = Array . from ( store . values ( ) ) ;
122- const paginatedRecords = records . slice ( skip , skip + top ) ;
114+ // Fetch all and slice manually since driver lacks skip/filtering
115+ await driver . syncSchema ( objectName , { } ) ;
116+ const allRecords = await driver . find ( objectName , { object : objectName } ) ;
117+
118+ const paginatedRecords = allRecords . slice ( skip , skip + top ) ;
123119
124120 return HttpResponse . json ( {
125121 '@odata.context' : `${ baseUrl } /data/$metadata#${ objectName } ` ,
126122 value : paginatedRecords ,
127- count : records . length
123+ count : allRecords . length
128124 } ) ;
129125 } ) ,
130126
131127 // Data: Get by ID
132- http . get ( `${ path } /data/:object/:id` , ( { params } ) => {
128+ http . get ( `${ path } /data/:object/:id` , async ( { params } ) => {
133129 const objectName = params . object as string ;
134130 const id = params . id as string ;
135- const store = getStore ( objectName ) ;
136- const record = store . get ( id ) ;
131+
132+ await driver . syncSchema ( objectName , { } ) ;
133+ const allRecords = await driver . find ( objectName , { object : objectName } ) ;
134+ const record = allRecords . find ( ( r : any ) => r . id === id ) ;
137135
138136 if ( ! record ) {
139137 return HttpResponse . json ( { error : 'Record not found' } , { status : 404 } ) ;
@@ -146,16 +144,9 @@ export function createMockHandlers(baseUrl: string = '/api/v1', metadata: any =
146144 http . post ( `${ path } /data/:object` , async ( { params, request } ) => {
147145 const objectName = params . object as string ;
148146 const body = await request . json ( ) as any ;
149- const store = getStore ( objectName ) ;
150147
151- const id = body . id || getNextId ( objectName ) ;
152- const newRecord = {
153- ...body ,
154- id,
155- createdAt : body . createdAt || new Date ( ) . toISOString ( )
156- } ;
157-
158- store . set ( id , newRecord ) ;
148+ await driver . syncSchema ( objectName , { } ) ;
149+ const newRecord = await driver . create ( objectName , body ) ;
159150
160151 return HttpResponse . json ( newRecord , { status : 201 } ) ;
161152 } ) ,
@@ -165,31 +156,28 @@ export function createMockHandlers(baseUrl: string = '/api/v1', metadata: any =
165156 const objectName = params . object as string ;
166157 const id = params . id as string ;
167158 const updates = await request . json ( ) as any ;
168- const store = getStore ( objectName ) ;
169- const record = store . get ( id ) ;
170159
171- if ( ! record ) {
172- return HttpResponse . json ( { error : 'Record not found' } , { status : 404 } ) ;
160+ try {
161+ await driver . syncSchema ( objectName , { } ) ;
162+ const updatedRecord = await driver . update ( objectName , id , updates ) ;
163+ return HttpResponse . json ( updatedRecord ) ;
164+ } catch ( e ) {
165+ return HttpResponse . json ( { error : 'Record not found' } , { status : 404 } ) ;
173166 }
174-
175- const updatedRecord = { ...record , ...updates } ;
176- store . set ( id , updatedRecord ) ;
177-
178- return HttpResponse . json ( updatedRecord ) ;
179167 } ) ,
180168
181169 // Data: Delete
182- http . delete ( `${ path } /data/:object/:id` , ( { params } ) => {
170+ http . delete ( `${ path } /data/:object/:id` , async ( { params } ) => {
183171 const objectName = params . object as string ;
184172 const id = params . id as string ;
185- const store = getStore ( objectName ) ;
186173
187- if ( ! store . has ( id ) ) {
174+ await driver . syncSchema ( objectName , { } ) ;
175+ const success = await driver . delete ( objectName , id ) ;
176+
177+ if ( ! success ) {
188178 return HttpResponse . json ( { error : 'Record not found' } , { status : 404 } ) ;
189179 }
190180
191- store . delete ( id ) ;
192-
193181 return HttpResponse . json ( { success : true } , { status : 204 } ) ;
194182 } )
195183 ) ;
0 commit comments