@@ -59,9 +59,9 @@ function buildS3Key(contentHash: string): string {
5959 * metaschema query needed.
6060 */
6161async function resolveDatabaseId ( pgClient : any ) : Promise < string | null > {
62- const result = await pgClient . query (
63- `SELECT jwt_private.current_database_id() AS id` ,
64- ) ;
62+ const result = await pgClient . query ( {
63+ text : `SELECT jwt_private.current_database_id() AS id` ,
64+ } ) ;
6565 return result . rows [ 0 ] ?. id ?? null ;
6666}
6767
@@ -235,15 +235,14 @@ export function createPresignedUrlPlugin(
235235 }
236236
237237 return withPgClient ( pgSettings , async ( pgClient : any ) => {
238- await pgClient . query ( 'BEGIN' ) ;
239- try {
238+ return pgClient . withTransaction ( async ( txClient : any ) => {
240239 // --- Resolve storage module config (all limits come from here) ---
241- const databaseId = await resolveDatabaseId ( pgClient ) ;
240+ const databaseId = await resolveDatabaseId ( txClient ) ;
242241 if ( ! databaseId ) {
243242 throw new Error ( 'DATABASE_NOT_FOUND' ) ;
244243 }
245244
246- const storageConfig = await getStorageModuleConfig ( pgClient , databaseId ) ;
245+ const storageConfig = await getStorageModuleConfig ( txClient , databaseId ) ;
247246 if ( ! storageConfig ) {
248247 throw new Error ( 'STORAGE_MODULE_NOT_PROVISIONED' ) ;
249248 }
@@ -259,7 +258,7 @@ export function createPresignedUrlPlugin(
259258 }
260259
261260 // --- Look up the bucket (cached; first miss queries via RLS) ---
262- const bucket = await getBucketConfig ( pgClient , storageConfig , databaseId , bucketKey ) ;
261+ const bucket = await getBucketConfig ( txClient , storageConfig , databaseId , bucketKey ) ;
263262 if ( ! bucket ) {
264263 throw new Error ( 'BUCKET_NOT_FOUND' ) ;
265264 }
@@ -288,29 +287,28 @@ export function createPresignedUrlPlugin(
288287 const s3Key = buildS3Key ( contentHash ) ;
289288
290289 // --- Dedup check: look for existing file with same content_hash in this bucket ---
291- const dedupResult = await pgClient . query (
292- `SELECT id, status
290+ const dedupResult = await txClient . query ( {
291+ text : `SELECT id, status
293292 FROM ${ storageConfig . filesQualifiedName }
294293 WHERE content_hash = $1
295294 AND bucket_id = $2
296295 AND status IN ('ready', 'processed')
297296 LIMIT 1` ,
298- [ contentHash , bucket . id ] ,
299- ) ;
297+ values : [ contentHash , bucket . id ] ,
298+ } ) ;
300299
301300 if ( dedupResult . rows . length > 0 ) {
302301 const existingFile = dedupResult . rows [ 0 ] ;
303302 log . info ( `Dedup hit: file ${ existingFile . id } for hash ${ contentHash } ` ) ;
304303
305304 // Track the dedup request
306- await pgClient . query (
307- `INSERT INTO ${ storageConfig . uploadRequestsQualifiedName }
305+ await txClient . query ( {
306+ text : `INSERT INTO ${ storageConfig . uploadRequestsQualifiedName }
308307 (file_id, bucket_id, key, content_type, content_hash, size, status, expires_at)
309308 VALUES ($1, $2, $3, $4, $5, $6, 'confirmed', NOW())` ,
310- [ existingFile . id , bucket . id , s3Key , contentType , contentHash , size ] ,
311- ) ;
309+ values : [ existingFile . id , bucket . id , s3Key , contentType , contentHash , size ] ,
310+ } ) ;
312311
313- await pgClient . query ( 'COMMIT' ) ;
314312 return {
315313 uploadUrl : null ,
316314 fileId : existingFile . id ,
@@ -321,12 +319,12 @@ export function createPresignedUrlPlugin(
321319 }
322320
323321 // --- Create file record (status=pending) ---
324- const fileResult = await pgClient . query (
325- `INSERT INTO ${ storageConfig . filesQualifiedName }
322+ const fileResult = await txClient . query ( {
323+ text : `INSERT INTO ${ storageConfig . filesQualifiedName }
326324 (bucket_id, key, content_type, content_hash, size, filename, owner_id, is_public, status)
327325 VALUES ($1, $2, $3, $4, $5, $6, $7, $8, 'pending')
328326 RETURNING id` ,
329- [
327+ values : [
330328 bucket . id ,
331329 s3Key ,
332330 contentType ,
@@ -336,7 +334,7 @@ export function createPresignedUrlPlugin(
336334 bucket . owner_id ,
337335 bucket . is_public ,
338336 ] ,
339- ) ;
337+ } ) ;
340338
341339 const fileId = fileResult . rows [ 0 ] . id ;
342340
@@ -356,25 +354,21 @@ export function createPresignedUrlPlugin(
356354 const expiresAt = new Date ( Date . now ( ) + storageConfig . uploadUrlExpirySeconds * 1000 ) . toISOString ( ) ;
357355
358356 // --- Track the upload request ---
359- await pgClient . query (
360- `INSERT INTO ${ storageConfig . uploadRequestsQualifiedName }
357+ await txClient . query ( {
358+ text : `INSERT INTO ${ storageConfig . uploadRequestsQualifiedName }
361359 (file_id, bucket_id, key, content_type, content_hash, size, status, expires_at)
362360 VALUES ($1, $2, $3, $4, $5, $6, 'issued', $7)` ,
363- [ fileId , bucket . id , s3Key , contentType , contentHash , size , expiresAt ] ,
364- ) ;
361+ values : [ fileId , bucket . id , s3Key , contentType , contentHash , size , expiresAt ] ,
362+ } ) ;
365363
366- await pgClient . query ( 'COMMIT' ) ;
367364 return {
368365 uploadUrl,
369366 fileId,
370367 key : s3Key ,
371368 deduplicated : false ,
372369 expiresAt,
373370 } ;
374- } catch ( err ) {
375- await pgClient . query ( 'ROLLBACK' ) ;
376- throw err ;
377- }
371+ } ) ;
378372 } ) ;
379373 } ) ;
380374 } ,
@@ -397,27 +391,26 @@ export function createPresignedUrlPlugin(
397391 }
398392
399393 return withPgClient ( pgSettings , async ( pgClient : any ) => {
400- await pgClient . query ( 'BEGIN' ) ;
401- try {
394+ return pgClient . withTransaction ( async ( txClient : any ) => {
402395 // --- Resolve storage module config ---
403- const databaseId = await resolveDatabaseId ( pgClient ) ;
396+ const databaseId = await resolveDatabaseId ( txClient ) ;
404397 if ( ! databaseId ) {
405398 throw new Error ( 'DATABASE_NOT_FOUND' ) ;
406399 }
407400
408- const storageConfig = await getStorageModuleConfig ( pgClient , databaseId ) ;
401+ const storageConfig = await getStorageModuleConfig ( txClient , databaseId ) ;
409402 if ( ! storageConfig ) {
410403 throw new Error ( 'STORAGE_MODULE_NOT_PROVISIONED' ) ;
411404 }
412405
413406 // --- Look up the file (RLS enforced) ---
414- const fileResult = await pgClient . query (
415- `SELECT id, key, content_type, status, bucket_id
407+ const fileResult = await txClient . query ( {
408+ text : `SELECT id, key, content_type, status, bucket_id
416409 FROM ${ storageConfig . filesQualifiedName }
417410 WHERE id = $1
418411 LIMIT 1` ,
419- [ fileId ] ,
420- ) ;
412+ values : [ fileId ] ,
413+ } ) ;
421414
422415 if ( fileResult . rows . length === 0 ) {
423416 throw new Error ( 'FILE_NOT_FOUND' ) ;
@@ -427,7 +420,6 @@ export function createPresignedUrlPlugin(
427420
428421 if ( file . status !== 'pending' ) {
429422 // File is already confirmed or processed — idempotent success
430- await pgClient . query ( 'COMMIT' ) ;
431423 return {
432424 fileId : file . id ,
433425 status : file . status ,
@@ -446,45 +438,40 @@ export function createPresignedUrlPlugin(
446438 // --- Content-type verification ---
447439 if ( s3Head . contentType && s3Head . contentType !== file . content_type ) {
448440 // Mark upload_request as rejected
449- await pgClient . query (
450- `UPDATE ${ storageConfig . uploadRequestsQualifiedName }
441+ await txClient . query ( {
442+ text : `UPDATE ${ storageConfig . uploadRequestsQualifiedName }
451443 SET status = 'rejected'
452444 WHERE file_id = $1 AND status = 'issued'` ,
453- [ fileId ] ,
454- ) ;
445+ values : [ fileId ] ,
446+ } ) ;
455447
456- await pgClient . query ( 'COMMIT' ) ;
457448 throw new Error (
458449 `CONTENT_TYPE_MISMATCH: expected ${ file . content_type } , got ${ s3Head . contentType } ` ,
459450 ) ;
460451 }
461452
462453 // --- Transition file to 'ready' ---
463- await pgClient . query (
464- `UPDATE ${ storageConfig . filesQualifiedName }
454+ await txClient . query ( {
455+ text : `UPDATE ${ storageConfig . filesQualifiedName }
465456 SET status = 'ready'
466457 WHERE id = $1` ,
467- [ fileId ] ,
468- ) ;
458+ values : [ fileId ] ,
459+ } ) ;
469460
470461 // --- Update upload_request to 'confirmed' ---
471- await pgClient . query (
472- `UPDATE ${ storageConfig . uploadRequestsQualifiedName }
462+ await txClient . query ( {
463+ text : `UPDATE ${ storageConfig . uploadRequestsQualifiedName }
473464 SET status = 'confirmed', confirmed_at = NOW()
474465 WHERE file_id = $1 AND status = 'issued'` ,
475- [ fileId ] ,
476- ) ;
466+ values : [ fileId ] ,
467+ } ) ;
477468
478- await pgClient . query ( 'COMMIT' ) ;
479469 return {
480470 fileId : file . id ,
481471 status : 'ready' ,
482472 success : true ,
483473 } ;
484- } catch ( err ) {
485- await pgClient . query ( 'ROLLBACK' ) ;
486- throw err ;
487- }
474+ } ) ;
488475 } ) ;
489476 } ) ;
490477 } ,
0 commit comments