@burdenoff/be-sdk 2026.825.7 → 2026.825.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (120) hide show
  1. package/dist/EventQueueFactory-J2XXPYXH.js +7 -0
  2. package/dist/{EventQueueFactory-ELT7NDXK.js.map → EventQueueFactory-J2XXPYXH.js.map} +1 -1
  3. package/dist/auth/index.js +2 -2
  4. package/dist/cache/index.js +3 -3
  5. package/dist/{chunk-AW6JUXCU.js → chunk-3UQMAUX4.js} +4 -4
  6. package/dist/{chunk-AW6JUXCU.js.map → chunk-3UQMAUX4.js.map} +1 -1
  7. package/dist/{chunk-N3YN6ZII.js → chunk-5JNHVKHG.js} +3 -3
  8. package/dist/{chunk-N3YN6ZII.js.map → chunk-5JNHVKHG.js.map} +1 -1
  9. package/dist/{chunk-7UJXIX4I.js → chunk-5NT2OEDQ.js} +3 -3
  10. package/dist/{chunk-7UJXIX4I.js.map → chunk-5NT2OEDQ.js.map} +1 -1
  11. package/dist/{chunk-OQLDXOZ3.js → chunk-6GL4SLU7.js} +3 -3
  12. package/dist/{chunk-OQLDXOZ3.js.map → chunk-6GL4SLU7.js.map} +1 -1
  13. package/dist/{chunk-L3QCRJOA.js → chunk-74Y5YD3U.js} +7 -7
  14. package/dist/{chunk-L3QCRJOA.js.map → chunk-74Y5YD3U.js.map} +1 -1
  15. package/dist/{chunk-NVVWSOY7.js → chunk-AX3UF33H.js} +3 -3
  16. package/dist/{chunk-NVVWSOY7.js.map → chunk-AX3UF33H.js.map} +1 -1
  17. package/dist/{chunk-Z3O32BW6.js → chunk-CPLFP5JK.js} +3 -3
  18. package/dist/{chunk-Z3O32BW6.js.map → chunk-CPLFP5JK.js.map} +1 -1
  19. package/dist/{chunk-XD5ZK727.js → chunk-DS3YMJ4X.js} +3 -3
  20. package/dist/{chunk-XD5ZK727.js.map → chunk-DS3YMJ4X.js.map} +1 -1
  21. package/dist/{chunk-2HANKZZM.js → chunk-ELU7VL3E.js} +3 -3
  22. package/dist/{chunk-2HANKZZM.js.map → chunk-ELU7VL3E.js.map} +1 -1
  23. package/dist/{chunk-KESVEZB2.js → chunk-FA5ROGTS.js} +3 -3
  24. package/dist/{chunk-KESVEZB2.js.map → chunk-FA5ROGTS.js.map} +1 -1
  25. package/dist/{chunk-WFVLQELZ.js → chunk-FYH5IAPR.js} +6 -6
  26. package/dist/{chunk-WFVLQELZ.js.map → chunk-FYH5IAPR.js.map} +1 -1
  27. package/dist/{chunk-RXMOV3YE.js → chunk-GJWQK3IU.js} +3 -3
  28. package/dist/{chunk-RXMOV3YE.js.map → chunk-GJWQK3IU.js.map} +1 -1
  29. package/dist/{chunk-TORD32GS.js → chunk-INAZ3PKF.js} +3 -3
  30. package/dist/{chunk-TORD32GS.js.map → chunk-INAZ3PKF.js.map} +1 -1
  31. package/dist/{chunk-UJG32VIP.js → chunk-IUJSIXMM.js} +3 -3
  32. package/dist/{chunk-UJG32VIP.js.map → chunk-IUJSIXMM.js.map} +1 -1
  33. package/dist/{chunk-VI4VSNTI.js → chunk-KJOSPVB2.js} +3 -3
  34. package/dist/{chunk-VI4VSNTI.js.map → chunk-KJOSPVB2.js.map} +1 -1
  35. package/dist/{chunk-UM32ZA3G.js → chunk-KMNSVLDS.js} +5 -5
  36. package/dist/{chunk-UM32ZA3G.js.map → chunk-KMNSVLDS.js.map} +1 -1
  37. package/dist/{chunk-VBXPFYZ5.js → chunk-KO2ZXZ7W.js} +3 -3
  38. package/dist/{chunk-VBXPFYZ5.js.map → chunk-KO2ZXZ7W.js.map} +1 -1
  39. package/dist/{chunk-VDYBUTFI.js → chunk-KW55Q6TA.js} +5 -5
  40. package/dist/{chunk-VDYBUTFI.js.map → chunk-KW55Q6TA.js.map} +1 -1
  41. package/dist/{chunk-OCYZEBOL.js → chunk-L5TDUAFN.js} +3 -3
  42. package/dist/{chunk-OCYZEBOL.js.map → chunk-L5TDUAFN.js.map} +1 -1
  43. package/dist/{chunk-S7LWYERE.js → chunk-LKCBI6B2.js} +3 -3
  44. package/dist/{chunk-S7LWYERE.js.map → chunk-LKCBI6B2.js.map} +1 -1
  45. package/dist/{chunk-LGTQ26Z2.js → chunk-MEA4BQNA.js} +3 -3
  46. package/dist/{chunk-LGTQ26Z2.js.map → chunk-MEA4BQNA.js.map} +1 -1
  47. package/dist/{chunk-QLVKMWFA.js → chunk-MWPYA2HD.js} +3 -3
  48. package/dist/{chunk-QLVKMWFA.js.map → chunk-MWPYA2HD.js.map} +1 -1
  49. package/dist/{chunk-XWVP4MC6.js → chunk-MZCBEJ67.js} +3 -3
  50. package/dist/{chunk-XWVP4MC6.js.map → chunk-MZCBEJ67.js.map} +1 -1
  51. package/dist/{chunk-URDYOM2L.js → chunk-QJN4K7LD.js} +4 -4
  52. package/dist/{chunk-URDYOM2L.js.map → chunk-QJN4K7LD.js.map} +1 -1
  53. package/dist/{chunk-CBZNP6RF.js → chunk-RU266375.js} +48 -7
  54. package/dist/chunk-RU266375.js.map +1 -0
  55. package/dist/{chunk-A6DGEZJ4.js → chunk-UD5PPGVU.js} +3 -3
  56. package/dist/{chunk-A6DGEZJ4.js.map → chunk-UD5PPGVU.js.map} +1 -1
  57. package/dist/{chunk-JNJSSBKO.js → chunk-UFXHLQ2T.js} +5 -5
  58. package/dist/{chunk-JNJSSBKO.js.map → chunk-UFXHLQ2T.js.map} +1 -1
  59. package/dist/{chunk-F5SGJ6VS.js → chunk-UNASM5VJ.js} +3 -3
  60. package/dist/{chunk-F5SGJ6VS.js.map → chunk-UNASM5VJ.js.map} +1 -1
  61. package/dist/{chunk-5LXDPGDH.js → chunk-VAT66FJA.js} +3 -3
  62. package/dist/{chunk-5LXDPGDH.js.map → chunk-VAT66FJA.js.map} +1 -1
  63. package/dist/{chunk-7E76FL2C.js → chunk-XCQN6GH7.js} +18 -10
  64. package/dist/chunk-XCQN6GH7.js.map +1 -0
  65. package/dist/{chunk-4X5WL6I3.js → chunk-XYWLCNJH.js} +5 -5
  66. package/dist/{chunk-4X5WL6I3.js.map → chunk-XYWLCNJH.js.map} +1 -1
  67. package/dist/{chunk-MX4AHK3E.js → chunk-YAQ7GNAC.js} +6 -6
  68. package/dist/{chunk-MX4AHK3E.js.map → chunk-YAQ7GNAC.js.map} +1 -1
  69. package/dist/{chunk-RNR45JQH.js → chunk-YK7C5DU6.js} +3 -3
  70. package/dist/{chunk-RNR45JQH.js.map → chunk-YK7C5DU6.js.map} +1 -1
  71. package/dist/{chunk-IC7YDBGE.js → chunk-YNDJQRI3.js} +3 -3
  72. package/dist/{chunk-IC7YDBGE.js.map → chunk-YNDJQRI3.js.map} +1 -1
  73. package/dist/{chunk-WCJIZR5Q.js → chunk-Z5BURBFZ.js} +3 -3
  74. package/dist/{chunk-WCJIZR5Q.js.map → chunk-Z5BURBFZ.js.map} +1 -1
  75. package/dist/client/internal-client.js +2 -2
  76. package/dist/database/index.js +2 -2
  77. package/dist/event-queue/index.js +6 -6
  78. package/dist/export/index.js +5 -5
  79. package/dist/feature-flags/index.js +2 -2
  80. package/dist/gateway/index.js +4 -4
  81. package/dist/gateway/security/index.js +2 -2
  82. package/dist/graph/index.js +8 -8
  83. package/dist/graphql/index.js +4 -4
  84. package/dist/graphql/services/index.js +2 -2
  85. package/dist/i18n/index.js +2 -2
  86. package/dist/{index-BtpoFSLa.d.ts → index-BLWIKXin.d.ts} +1 -1
  87. package/dist/{index-C0qWSC_Q.d.ts → index-hWpL68Vx.d.ts} +4 -2
  88. package/dist/index.d.ts +3 -3
  89. package/dist/index.js +44 -44
  90. package/dist/init/index.js +6 -6
  91. package/dist/instrumentation/index.d.ts +2 -2
  92. package/dist/instrumentation/index.js +2 -2
  93. package/dist/layer/index.js +2 -2
  94. package/dist/lifecycle/index.js +2 -2
  95. package/dist/logger/index.d.ts +1 -1
  96. package/dist/logger/index.js +1 -1
  97. package/dist/middleware/index.js +2 -2
  98. package/dist/notifications/index.js +2 -2
  99. package/dist/observability/index.js +2 -2
  100. package/dist/pino-logger-GJ2CYLD5.js +5 -0
  101. package/dist/{pino-logger-XF275Y5C.js.map → pino-logger-GJ2CYLD5.js.map} +1 -1
  102. package/dist/platform/index.js +2 -2
  103. package/dist/prisma/index.js +8 -8
  104. package/dist/rbac/index.js +2 -2
  105. package/dist/resource-caps/index.js +2 -2
  106. package/dist/server/index.js +6 -6
  107. package/dist/sharding/index.js +1 -1
  108. package/dist/sharing/index.js +2 -2
  109. package/dist/telemetry/index.d.ts +3 -3
  110. package/dist/telemetry/index.js +5 -5
  111. package/dist/temporal/index.js +2 -2
  112. package/dist/tracker/index.js +4 -4
  113. package/dist/workspace-guard-7PEZT3ZJ.js +5 -0
  114. package/dist/{workspace-guard-4BUG4ZP2.js.map → workspace-guard-7PEZT3ZJ.js.map} +1 -1
  115. package/package.json +1 -1
  116. package/dist/EventQueueFactory-ELT7NDXK.js +0 -7
  117. package/dist/chunk-7E76FL2C.js.map +0 -1
  118. package/dist/chunk-CBZNP6RF.js.map +0 -1
  119. package/dist/pino-logger-XF275Y5C.js +0 -5
  120. package/dist/workspace-guard-4BUG4ZP2.js +0 -5
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/graph/utils/registry.ts","../src/graph/utils/helpers.ts","../src/prisma/client.ts","../src/graph/middleware/prisma-extension.ts"],"names":["GraphRegistry","entityMappings","Map","relationshipMappings","registeredModules","Set","resolveFields","entityType","config","Array","isArray","fields","logger","warn","registerModule","moduleName","entities","relationships","has","info","entityCount","entityConfig","Object","entries","enabled","resolvedFields","resolvedConfig","set","relationshipCount","relationshipType","relationshipConfig","add","getEntityConfig","get","getRelationshipConfig","getAllEntityTypes","from","keys","getAllRelationshipTypes","getRegisteredModules","isEntityRegistered","isRelationshipRegistered","getOrganizationId","data","getOrgId","undefined","getWorkspaceId","getRbacConfig","rbac","resolveRbacMetadata","entityData","rbacConfig","name","extractName","identifier","extractIdentifier","parentResourceIdentifier","parentResourceField","resourceTypeName","createResource","getStats","collections","edgeTypes","values","collection","label","modules","size","clear","getRelationshipsForEntity","result","key","push","printStatus","stats","join","uuidv4","crypto","randomUUID","createEntityEvent","eventType","organizationId","entity","metadata","productSource","eventId","process","env","timestamp","Date","toISOString","userId","correlationId","createRelationshipEvent","relationship","id","to","type","extractMinimalFields","modelName","minimal","field","parseRelationship","String","fromField","extractMetadata","getCollectionForEntity","extractEntityTitle","extractTitle","shouldSyncEntity","shouldSyncRelationship","createConnectionPool","idleTimeoutMillis","poolConfig","connectionString","databaseUrl","max","maxConnections","connectionTimeoutMillis","keepAlive","keepAliveInitialDelayMillis","applicationName","application_name","queryTimeoutMillis","query_timeout","statementTimeoutMillis","statement_timeout","idleInTransactionTimeoutMillis","idle_in_transaction_session_timeout","lockTimeoutMillis","lock_timeout","pool","Pool","on","error","message","installAcquireRetry","acquireRetries","acquireRetryDelayMillis","startPoolWarmer","isTransientAcquireError","Error","toLowerCase","includes","retries","baseDelayMillis","originalConnect","connect","bind","acquireWithRetry","attempt","delayMillis","Promise","resolve","setTimeout","patchedConnect","callback","then","client","release","keepWarm","intervalMs","warmupIntervalMillis","WARM_FAILURE_LOG_INTERVAL_MS","consecutiveWarmFailures","lastWarmFailureLogAt","timer","setInterval","query","failedAttempts","now","unref","originalEnd","end","args","clearInterval","ensureServiceApplicationName","productName","createPrismaAdapter","PrismaPg","configurePrismaLogging","isDevelopment","slowQueryThreshold","enableQueryLogging","$on","e","duration","substring","length","params","debug","target","PrismaClientWrapper","connectionState","isConnected","attempts","isDisconnecting","getClient","getPool","getConnectionState","delay","$connect","lastConnectedAt","lastError","errorMessage","waitTime","Math","pow","disconnect","$disconnect","registerShutdownHandlers","shutdownHandler","signal","exit","createPrismaClient","PrismaClientConstructor","adapter","logLevels","emit","level","log","defaultConfig","monitoredOperations","extractEntityInfo","model","record","extractContext","actorId","workspaceId","emitEntityEvent","entityInfo","entityTypes","context","minimalData","orgId","rbacMetadata","hasName","eventEmitter","publishEntityEvent","catch","emitRelationshipEvents","fromId","relationshipKey","foreignKeyValue","targetType","polymorphicTypeField","description","relationType","addGraphExtension","baseClient","fullConfig","prismaClient","$extends","$allModels","create","update","delete","updateMany","deleteMany"],"mappings":";;;;;;AA+BO,IAAMA,gBAAN,MAAMA;EA/Bb;;;EAgCE,OAAeC,cAAAA,uBAA6DC,GAAAA,EAAAA;EAC5E,OAAeC,oBAAAA,uBAAiED,GAAAA,EAAAA;EAChF,OAAeE,iBAAAA,uBAAqCC,GAAAA,EAAAA;;;;;;;;EASpD,OAAeC,aAAAA,CAAcC,YAAoBC,MAAAA,EAAqC;AACpF,IAAA,IAAIC,KAAAA,CAAMC,OAAAA,CAAQF,MAAAA,CAAOG,MAAM,CAAA,EAAG;AAChC,MAAA,OAAOH,MAAAA,CAAOG,MAAAA;AAChB,IAAA;AAGAC,IAAAA,MAAAA,CAAOC,IAAAA,CAAK,CAAA,4CAAA,EAA+CN,UAAAA,CAAAA,mBAAAA,CAA+B,CAAA;AAC1F,IAAA,OAAO,EAAA;AACT,EAAA;;;;;AAMA,EAAA,OAAOO,eAAeN,MAAAA,EAAiC;AACrD,IAAA,MAAM,EAAEO,UAAAA,EAAYC,QAAAA,EAAUC,aAAAA,EAAa,GAAKT,MAAAA;AAEhD,IAAA,IAAI,IAAA,CAAKJ,iBAAAA,CAAkBc,GAAAA,CAAIH,UAAAA,CAAAA,EAAa;AAC1CH,MAAAA,MAAAA,CAAOC,IAAAA,CAAK,CAAA,wBAAA,EAA2BE,UAAAA,CAAAA,8BAAAA,CAA0C,CAAA;AACjF,MAAA;AACF,IAAA;AAEAH,IAAAA,MAAAA,CAAOO,IAAAA,CAAK,CAAA,oCAAA,EAAuCJ,UAAAA,CAAAA,CAAY,CAAA;AAG/D,IAAA,IAAIK,WAAAA,GAAc,CAAA;AAClB,IAAA,KAAA,MAAW,CAACb,UAAAA,EAAYc,YAAAA,KAAiBC,MAAAA,CAAOC,OAAAA,CAAQP,QAAAA,CAAAA,EAAW;AACjE,MAAA,IAAIK,YAAAA,CAAaG,YAAY,KAAA,EAAO;AAElC,QAAA,MAAMC,cAAAA,GAAiB,IAAA,CAAKnB,aAAAA,CAAcC,UAAAA,EAAYc,YAAAA,CAAAA;AAGtD,QAAA,MAAMK,cAAAA,GAA4C;UAChD,GAAGL,YAAAA;UACHV,MAAAA,EAAQc;AACV,SAAA;AAEA,QAAA,IAAA,CAAKxB,cAAAA,CAAe0B,GAAAA,CAAIpB,UAAAA,EAAYmB,cAAAA,CAAAA;AACpCN,QAAAA,WAAAA,EAAAA;AACF,MAAA;AACF,IAAA;AAGA,IAAA,IAAIQ,iBAAAA,GAAoB,CAAA;AACxB,IAAA,IAAIX,aAAAA,EAAe;AACjB,MAAA,KAAA,MAAW,CAACY,gBAAAA,EAAkBC,kBAAAA,KAAuBR,MAAAA,CAAOC,OAAAA,CAAQN,aAAAA,CAAAA,EAAgB;AAClF,QAAA,IAAIa,kBAAAA,CAAmBN,YAAY,KAAA,EAAO;AACxC,UAAA,IAAA,CAAKrB,oBAAAA,CAAqBwB,GAAAA,CAAIE,gBAAAA,EAAkBC,kBAAAA,CAAAA;AAChDF,UAAAA,iBAAAA,EAAAA;AACF,QAAA;AACF,MAAA;AACF,IAAA;AAEA,IAAA,IAAA,CAAKxB,iBAAAA,CAAkB2B,IAAIhB,UAAAA,CAAAA;AAC3BH,IAAAA,MAAAA,CAAOO,KACL,CAAA,kCAAA,EAAgCJ,UAAAA,KAAeK,WAAAA,CAAAA,WAAAA,EAAyBQ,iBAAAA,CAAAA,cAAAA,CAAiC,CAAA;AAE7G,EAAA;;;;;;AAOA,EAAA,OAAOI,gBAAgBzB,UAAAA,EAA2D;AAChF,IAAA,OAAO,IAAA,CAAKN,cAAAA,CAAegC,GAAAA,CAAI1B,UAAAA,CAAAA;AACjC,EAAA;;;;;;AAOA,EAAA,OAAO2B,sBAAsBL,gBAAAA,EAA+D;AAC1F,IAAA,OAAO,IAAA,CAAK1B,oBAAAA,CAAqB8B,GAAAA,CAAIJ,gBAAAA,CAAAA;AACvC,EAAA;;;;;AAMA,EAAA,OAAOM,iBAAAA,GAA8B;AACnC,IAAA,OAAO1B,KAAAA,CAAM2B,IAAAA,CAAK,IAAA,CAAKnC,cAAAA,CAAeoC,MAAI,CAAA;AAC5C,EAAA;;;;;AAMA,EAAA,OAAOC,uBAAAA,GAAoC;AACzC,IAAA,OAAO7B,KAAAA,CAAM2B,IAAAA,CAAK,IAAA,CAAKjC,oBAAAA,CAAqBkC,MAAI,CAAA;AAClD,EAAA;;;;;AAMA,EAAA,OAAOE,oBAAAA,GAAiC;AACtC,IAAA,OAAO9B,KAAAA,CAAM2B,IAAAA,CAAK,IAAA,CAAKhC,iBAAiB,CAAA;AAC1C,EAAA;;;;;;AAOA,EAAA,OAAOoC,mBAAmBjC,UAAAA,EAA6B;AACrD,IAAA,OAAO,IAAA,CAAKN,cAAAA,CAAeiB,GAAAA,CAAIX,UAAAA,CAAAA;AACjC,EAAA;;;;;;AAOA,EAAA,OAAOkC,yBAAyBZ,gBAAAA,EAAmC;AACjE,IAAA,OAAO,IAAA,CAAK1B,oBAAAA,CAAqBe,GAAAA,CAAIW,gBAAAA,CAAAA;AACvC,EAAA;;;;;;;EAQA,OAAOa,iBAAAA,CAAkBnC,YAAoBoC,IAAAA,EAAmD;AAC9F,IAAA,MAAMnC,MAAAA,GAAS,IAAA,CAAKP,cAAAA,CAAegC,GAAAA,CAAI1B,UAAAA,CAAAA;AACvC,IAAA,IAAI,CAACC,MAAAA,IAAU,CAACA,MAAAA,CAAOoC,QAAAA,EAAU;AAC/B,MAAA,OAAOC,MAAAA;AACT,IAAA;AACA,IAAA,OAAOrC,MAAAA,CAAOoC,SAASD,IAAAA,CAAAA;AACzB,EAAA;;;;;;;EAQA,OAAOG,cAAAA,CAAevC,YAAoBoC,IAAAA,EAAmD;AAC3F,IAAA,MAAMnC,MAAAA,GAAS,IAAA,CAAKP,cAAAA,CAAegC,GAAAA,CAAI1B,UAAAA,CAAAA;AACvC,IAAA,IAAI,CAACC,MAAAA,IAAU,CAACA,MAAAA,CAAOsC,cAAAA,EAAgB;AACrC,MAAA,OAAOD,MAAAA;AACT,IAAA;AACA,IAAA,OAAOrC,MAAAA,CAAOsC,eAAeH,IAAAA,CAAAA;AAC/B,EAAA;;;;;;;AAQA,EAAA,OAAOI,cAAcxC,UAAAA,EAA0D;AAC7E,IAAA,MAAMC,MAAAA,GAAS,IAAA,CAAKP,cAAAA,CAAegC,GAAAA,CAAI1B,UAAAA,CAAAA;AACvC,IAAA,OAAOC,MAAAA,EAAQwC,IAAAA;AACjB,EAAA;;;;;;;;;EAUA,OAAOC,mBAAAA,CACL1C,YACA2C,UAAAA,EASY;AACZ,IAAA,MAAMC,UAAAA,GAAa,IAAA,CAAKJ,aAAAA,CAAcxC,UAAAA,CAAAA;AACtC,IAAA,IAAI,CAAC4C,UAAAA,EAAY;AACf,MAAA,OAAON,MAAAA;AACT,IAAA;AAEA,IAAA,MAAMO,OAAOD,UAAAA,CAAWE,WAAAA,GAAcF,UAAAA,CAAWE,WAAAA,CAAYH,UAAAA,CAAAA,GAAcL,MAAAA;AAC3E,IAAA,MAAMS,aAAaH,UAAAA,CAAWI,iBAAAA,GAAoBJ,UAAAA,CAAWI,iBAAAA,CAAkBL,UAAAA,CAAAA,GAAcL,MAAAA;AAC7F,IAAA,MAAMW,2BAA2BL,UAAAA,CAAWM,mBAAAA,GACvCP,UAAAA,CAAWC,UAAAA,CAAWM,mBAAmB,CAAA,GAC1CZ,MAAAA;AAEJ,IAAA,OAAO;AACLa,MAAAA,gBAAAA,EAAkBP,UAAAA,CAAWO,gBAAAA;AAC7B,MAAA,GAAIN,IAAAA,IAAQ;AAAEA,QAAAA;AAAK,OAAA;AACnB,MAAA,GAAIE,UAAAA,IAAc;AAAEA,QAAAA;AAAW,OAAA;AAC/B,MAAA,GAAIE,wBAAAA,IAA4B;AAAEA,QAAAA;AAAyB,OAAA;MAC3D,GAAIL,UAAAA,CAAWQ,mBAAmBd,MAAAA,IAAa;AAAEc,QAAAA,cAAAA,EAAgBR,UAAAA,CAAWQ;AAAe;AAC7F,KAAA;AACF,EAAA;;;;;AAMA,EAAA,OAAOC,QAAAA,GAML;AACA,IAAA,MAAMC,WAAAA,uBAAkBxD,GAAAA,EAAAA;AACxB,IAAA,MAAMyD,SAAAA,uBAAgBzD,GAAAA,EAAAA;AAEtB,IAAA,KAAA,MAAWG,MAAAA,IAAU,IAAA,CAAKP,cAAAA,CAAe8D,MAAAA,EAAM,EAAI;AACjDF,MAAAA,WAAAA,CAAY9B,GAAAA,CAAIvB,MAAAA,CAAOwD,UAAAA,IAAc,kBAAA,CAAA;AACvC,IAAA;AAEA,IAAA,KAAA,MAAWxD,MAAAA,IAAU,IAAA,CAAKL,oBAAAA,CAAqB4D,MAAAA,EAAM,EAAI;AACvD,MAAA,IAAIvD,OAAOyD,KAAAA,EAAO;AAChBH,QAAAA,SAAAA,CAAU/B,GAAAA,CAAIvB,OAAOyD,KAAK,CAAA;AAC5B,MAAA;AACF,IAAA;AAEA,IAAA,OAAO;AACLC,MAAAA,OAAAA,EAAS,KAAK9D,iBAAAA,CAAkB+D,IAAAA;AAChCnD,MAAAA,QAAAA,EAAU,KAAKf,cAAAA,CAAekE,IAAAA;AAC9BlD,MAAAA,aAAAA,EAAe,KAAKd,oBAAAA,CAAqBgE,IAAAA;AACzCN,MAAAA,WAAAA;AACAC,MAAAA;AACF,KAAA;AACF,EAAA;;;;AAKA,EAAA,OAAOM,KAAAA,GAAc;AACnB,IAAA,IAAA,CAAKnE,eAAemE,KAAAA,EAAK;AACzB,IAAA,IAAA,CAAKjE,qBAAqBiE,KAAAA,EAAK;AAC/B,IAAA,IAAA,CAAKhE,kBAAkBgE,KAAAA,EAAK;AAC5BxD,IAAAA,MAAAA,CAAOO,KAAK,2CAAA,CAAA;AACd,EAAA;;;;;;;AAQA,EAAA,OAAOkD,0BAA0B9D,UAAAA,EAA8D;AAC7F,IAAA,MAAM+D,SAAmD,EAAA;AAEzD,IAAA,KAAA,MAAW,CAACC,GAAAA,EAAK/D,MAAAA,KAAW,IAAA,CAAKL,oBAAAA,CAAqBoB,SAAO,EAAI;AAC/D,MAAA,IAAIf,MAAAA,CAAO4B,SAAS7B,UAAAA,EAAY;AAC9B+D,QAAAA,MAAAA,CAAOE,IAAAA,CAAK;AAACD,UAAAA,GAAAA;AAAK/D,UAAAA;AAAO,SAAA,CAAA;AAC3B,MAAA;AACF,IAAA;AAEA,IAAA,OAAO8D,MAAAA;AACT,EAAA;;;;AAKA,EAAA,OAAOG,WAAAA,GAAoB;AACzB,IAAA,MAAMC,KAAAA,GAAQ,KAAKd,QAAAA,EAAQ;AAC3BhD,IAAAA,MAAAA,CAAOO,KAAK,EAAA,CAAA;AACZP,IAAAA,MAAAA,CAAOO,KAAK,iCAAA,CAAA;AACZP,IAAAA,MAAAA,CAAOO,KAAK,0BAAA,CAAA;AACZP,IAAAA,MAAAA,CAAOO,IAAAA,CAAK,CAAA,oBAAA,EAAuBuD,KAAAA,CAAMR,OAAO,CAAA,CAAE,CAAA;AAClDtD,IAAAA,MAAAA,CAAOO,IAAAA,CAAK,CAAA,gBAAA,EAAmBuD,KAAAA,CAAM1D,QAAQ,CAAA,CAAE,CAAA;AAC/CJ,IAAAA,MAAAA,CAAOO,IAAAA,CAAK,CAAA,qBAAA,EAAwBuD,KAAAA,CAAMzD,aAAa,CAAA,CAAE,CAAA;AACzDL,IAAAA,MAAAA,CAAOO,IAAAA,CAAK,CAAA,oBAAA,EAAuBuD,KAAAA,CAAMb,WAAAA,CAAYM,IAAI,CAAA,CAAE,CAAA;AAC3DvD,IAAAA,MAAAA,CAAOO,IAAAA,CAAK,CAAA,YAAA,EAAeuD,KAAAA,CAAMZ,SAAAA,CAAUK,IAAI,CAAA,CAAE,CAAA;AACjDvD,IAAAA,MAAAA,CAAOO,KAAK,EAAA,CAAA;AACZP,IAAAA,MAAAA,CAAOO,KAAK,qBAAA,EAAuB,IAAA,CAAKoB,sBAAoB,CAAGoC,IAAAA,CAAK,IAAA,CAAA,CAAA;AACpE/D,IAAAA,MAAAA,CAAOO,KAAK,EAAA,CAAA;AACd,EAAA;AACF;;;AClTA,IAAMyD,MAAAA,mBAAS,MAAA,CAAA,MAAcC,MAAAA,CAAOC,UAAAA,EAAU,EAA/B,QAAA,CAAA;AAKR,SAASC,iBAAAA,CACdC,SAAAA,EACAC,cAAAA,EACAC,MAAAA,EAKAC,UAMAC,aAAAA,EAAsB;AAEtB,EAAA,OAAO;IACLC,OAAAA,EAAS,CAAA,IAAA,EAAOT,QAAAA,CAAAA,CAAAA;AAChBI,IAAAA,SAAAA;AACAC,IAAAA,cAAAA;AACAG,IAAAA,aAAAA,EAAeA,aAAAA,IAAiBE,OAAAA,CAAQC,GAAAA,CAAI,gBAAA,CAAA,IAAqB,SAAA;IACjEC,SAAAA,EAAAA,iBAAW,IAAIC,IAAAA,EAAAA,EAAOC,WAAAA,EAAW;AACjCR,IAAAA,MAAAA;IACAC,QAAAA,EAAU;AACRQ,MAAAA,MAAAA,EAAQR,QAAAA,EAAUQ,MAAAA;AAClBC,MAAAA,aAAAA,EAAeT,QAAAA,EAAUS,aAAAA,IAAiB,CAAA,IAAA,EAAOhB,MAAAA,EAAAA,CAAAA;AACnD;AACF,GAAA;AACF;AA5BgBG,MAAAA,CAAAA,iBAAAA,EAAAA,mBAAAA,CAAAA;AAiCT,SAASc,uBAAAA,CACdb,SAAAA,EACAC,cAAAA,EACAa,YAAAA,EAMAX,UAIAC,aAAAA,EAAsB;AAEtB,EAAA,OAAO;IACLC,OAAAA,EAAS,CAAA,IAAA,EAAOT,QAAAA,CAAAA,CAAAA;AAChBI,IAAAA,SAAAA;AACAC,IAAAA,cAAAA;AACAG,IAAAA,aAAAA,EAAeA,aAAAA,IAAiBE,OAAAA,CAAQC,GAAAA,CAAI,gBAAA,CAAA,IAAqB,SAAA;IACjEC,SAAAA,EAAAA,iBAAW,IAAIC,IAAAA,EAAAA,EAAOC,WAAAA,EAAW;IACjCR,MAAAA,EAAQ;AACNa,MAAAA,EAAAA,EAAI,GAAGD,YAAAA,CAAa1D,IAAAA,CAAK2D,EAAE,CAAA,CAAA,EAAID,YAAAA,CAAaE,GAAGD,EAAE,CAAA,CAAA;AACjDE,MAAAA,IAAAA,EAAMH,YAAAA,CAAaG,IAAAA;AACnBtD,MAAAA,IAAAA,EAAM;AACR,KAAA;AACAmD,IAAAA,YAAAA;IACAX,QAAAA,EAAU;AACRQ,MAAAA,MAAAA,EAAQR,QAAAA,EAAUQ,MAAAA;AAClBC,MAAAA,aAAAA,EAAeT,QAAAA,EAAUS,aAAAA,IAAiB,CAAA,IAAA,EAAOhB,MAAAA,EAAAA,CAAAA;AACnD;AACF,GAAA;AACF;AAhCgBiB,MAAAA,CAAAA,uBAAAA,EAAAA,yBAAAA,CAAAA;AAyCT,SAASK,oBAAAA,CAAqBC,WAAmBjB,MAAAA,EAA+B;AAErF,EAAA,MAAM1E,MAAAA,GAASR,aAAAA,CAAcgC,eAAAA,CAAgBmE,SAAAA,CAAAA;AAE7C,EAAA,IAAI,CAAC3F,MAAAA,EAAQ;AAEXI,IAAAA,MAAAA,CAAOC,IAAAA,CAAK,CAAA,sDAAA,EAAyDsF,SAAAA,CAAAA,gBAAAA,CAA2B,CAAA;AAChG,IAAA,MAAMC,WAAmC,EAAC;AAE1C,IAAA,IAAIlB,MAAAA,CAAO,IAAA,CAAA,EAAOkB,SAAQ,IAAA,CAAA,GAAQlB,OAAO,IAAA,CAAA;AACzC,IAAA,IAAIA,MAAAA,CAAO,aAAA,CAAA,EAAgBkB,SAAQ,aAAA,CAAA,GAAiBlB,OAAO,aAAA,CAAA;AAC3D,IAAA,IAAIA,MAAAA,CAAO,aAAA,CAAA,EAAgBkB,SAAQ,aAAA,CAAA,GAAiBlB,OAAO,aAAA,CAAA;AAE3D,IAAA,OAAOkB,QAAAA;AACT,EAAA;AAGA,EAAA,MAAMA,UAAmC,EAAC;AAE1C,EAAA,KAAA,MAAWC,KAAAA,IAAS7F,OAAOG,MAAAA,EAAQ;AACjC,IAAA,IAAIuE,MAAAA,CAAOmB,KAAAA,CAAAA,KAAWxD,MAAAA,EAAW;AAC/BuD,MAAAA,OAAAA,CAAQC,KAAAA,CAAAA,GAASnB,MAAAA,CAAOmB,KAAAA,CAAAA;AAC1B,IAAA;AACF,EAAA;AAEA,EAAA,OAAOD,OAAAA;AACT;AA1BgBF,MAAAA,CAAAA,oBAAAA,EAAAA,sBAAAA,CAAAA;AAmCT,SAASI,iBAAAA,CACdH,WACAL,YAAAA,EAAqC;AAQrC,EAAA,MAAMtF,MAAAA,GAASR,aAAAA,CAAckC,qBAAAA,CAAsBiE,SAAAA,CAAAA;AAEnD,EAAA,IAAI,CAAC3F,MAAAA,EAAQ;AACXI,IAAAA,MAAAA,CAAOC,IAAAA,CAAK,CAAA,4DAAA,EAA+DsF,SAAAA,CAAAA,gBAAAA,CAA2B,CAAA;AACtG,IAAA,OAAO;MACL/D,IAAAA,EAAM;QAAE2D,EAAAA,EAAI,SAAA;QAAWE,IAAAA,EAAM;AAAU,OAAA;MACvCD,EAAAA,EAAI;QAAED,EAAAA,EAAI,SAAA;QAAWE,IAAAA,EAAM;AAAU,OAAA;MACrCpE,gBAAAA,EAAkB,YAAA;AAClBsD,MAAAA,QAAAA,EAAU;AACZ,KAAA;AACF,EAAA;AAGA,EAAA,OAAO;IACL/C,IAAAA,EAAM;AACJ2D,MAAAA,EAAAA,EAAIQ,MAAAA,CAAOT,YAAAA,CAAatF,MAAAA,CAAOgG,SAAS,KAAK,SAAA,CAAA;AAC7CP,MAAAA,IAAAA,EAAMzF,MAAAA,CAAO4B;AACf,KAAA;IACA4D,EAAAA,EAAI;AACFD,MAAAA,EAAAA,EAAIQ,MAAAA,CAAOT,YAAAA,CAAatF,MAAAA,CAAOwF,EAAE,KAAK,SAAA,CAAA;AACtCC,MAAAA,IAAAA,EAAMzF,MAAAA,CAAOwF;AACf,KAAA;AACAnE,IAAAA,gBAAAA,EAAkBrB,OAAOyD,KAAAA,IAAS,YAAA;AAClCkB,IAAAA,QAAAA,EAAU3E,MAAAA,CAAOiG,eAAAA,GAAkBX,YAAAA,CAAAA,IAAiB;AACtD,GAAA;AACF;AAnCgBQ,MAAAA,CAAAA,iBAAAA,EAAAA,mBAAAA,CAAAA;AA2CT,SAASI,uBAAuBnG,UAAAA,EAAkB;AACvD,EAAA,MAAMC,MAAAA,GAASR,aAAAA,CAAcgC,eAAAA,CAAgBzB,UAAAA,CAAAA;AAE7C,EAAA,IAAI,CAACC,MAAAA,EAAQ;AAEX,IAAA,OAAO,QAAA;AACT,EAAA;AAEA,EAAA,OAAOA,OAAOwD,UAAAA,IAAc,QAAA;AAC9B;AATgB0C,MAAAA,CAAAA,sBAAAA,EAAAA,wBAAAA,CAAAA;AAkBT,SAASC,kBAAAA,CAAmBpG,YAAoB2E,MAAAA,EAA+B;AACpF,EAAA,MAAM1E,MAAAA,GAASR,aAAAA,CAAcgC,eAAAA,CAAgBzB,UAAAA,CAAAA;AAG7C,EAAA,IAAIC,QAAQoG,YAAAA,EAAc;AACxB,IAAA,OAAOpG,MAAAA,CAAOoG,aAAa1B,MAAAA,CAAAA;AAC7B,EAAA;AAGA,EAAA,OAAOqB,MAAAA,CAAOrB,MAAAA,CAAO,MAAA,CAAA,IAAWA,MAAAA,CAAO,OAAA,CAAA,IAAYA,MAAAA,CAAO,OAAA,CAAA,IAAYA,MAAAA,CAAO,IAAA,KAAS,UAAA,CAAA;AACxF;AAVgByB,MAAAA,CAAAA,kBAAAA,EAAAA,oBAAAA,CAAAA;AAkBT,SAASE,iBAAiBtG,UAAAA,EAAkB;AACjD,EAAA,MAAMC,MAAAA,GAASR,aAAAA,CAAcgC,eAAAA,CAAgBzB,UAAAA,CAAAA;AAE7C,EAAA,IAAI,CAACC,MAAAA,EAAQ;AAEX,IAAA,OAAO,KAAA;AACT,EAAA;AAGA,EAAA,OAAOA,OAAOgB,OAAAA,KAAY,KAAA;AAC5B;AAVgBqF,MAAAA,CAAAA,gBAAAA,EAAAA,kBAAAA,CAAAA;AAkBT,SAASC,uBAAuBjF,gBAAAA,EAAwB;AAC7D,EAAA,MAAMrB,MAAAA,GAASR,aAAAA,CAAckC,qBAAAA,CAAsBL,gBAAAA,CAAAA;AAEnD,EAAA,IAAI,CAACrB,MAAAA,EAAQ;AAEX,IAAA,OAAO,KAAA;AACT,EAAA;AAGA,EAAA,OAAOA,OAAOgB,OAAAA,KAAY,KAAA;AAC5B;AAVgBsF,MAAAA,CAAAA,sBAAAA,EAAAA,wBAAAA,CAAAA;AC9GT,SAASC,qBAAqBvG,MAAAA,EAA0B;AAC7D,EAAA,MAAMwG,iBAAAA,GAAoBxG,OAAOwG,iBAAAA,IAAqB,GAAA;AACtD,EAAA,MAAMC,UAAAA,GAAyB;AAC7BC,IAAAA,gBAAAA,EAAkB1G,MAAAA,CAAO2G,WAAAA;AACzBC,IAAAA,GAAAA,EAAK5G,OAAO6G,cAAAA,IAAkB,EAAA;AAC9BL,IAAAA,iBAAAA;AACAM,IAAAA,uBAAAA,EAAyB9G,OAAO8G,uBAAAA,IAA2B,GAAA;;;;;;;IAO3DC,SAAAA,EAAW,IAAA;IACXC,2BAAAA,EAA6B;AAC/B,GAAA;AAGA,EAAA,IAAIhH,OAAOiH,eAAAA,EAAiB;AAC1BR,IAAAA,UAAAA,CAAWS,mBAAmBlH,MAAAA,CAAOiH,eAAAA;AACvC,EAAA;AAUA,EAAA,IAAIjH,MAAAA,CAAOmH,kBAAAA,IAAsB,IAAA,IAAQnH,MAAAA,CAAOmH,qBAAqB,CAAA,EAAG;AACtEV,IAAAA,UAAAA,CAAWW,gBAAgBpH,MAAAA,CAAOmH,kBAAAA;AACpC,EAAA;AAIA,EAAA,IAAInH,MAAAA,CAAOqH,sBAAAA,IAA0B,IAAA,IAAQrH,MAAAA,CAAOqH,yBAAyB,CAAA,EAAG;AAC9EZ,IAAAA,UAAAA,CAAWa,oBAAoBtH,MAAAA,CAAOqH,sBAAAA;AACxC,EAAA;AACA,EAAA,IAAIrH,MAAAA,CAAOuH,8BAAAA,IAAkC,IAAA,IAAQvH,MAAAA,CAAOuH,iCAAiC,CAAA,EAAG;AAC9Fd,IAAAA,UAAAA,CAAWe,sCAAsCxH,MAAAA,CAAOuH,8BAAAA;AAC1D,EAAA;AACA,EAAA,IAAIvH,MAAAA,CAAOyH,iBAAAA,IAAqB,IAAA,IAAQzH,MAAAA,CAAOyH,oBAAoB,CAAA,EAAG;AACpEhB,IAAAA,UAAAA,CAAWiB,eAAe1H,MAAAA,CAAOyH,iBAAAA;AACnC,EAAA;AAEA,EAAA,MAAME,IAAAA,GAAO,IAAIC,IAAAA,CAAKnB,UAAAA,CAAAA;AAQtBkB,EAAAA,IAAAA,CAAKE,EAAAA,CAAG,OAAA,EAAS,CAACC,KAAAA,KAAAA;AAChB1H,IAAAA,MAAAA,CAAOC,KACL,2GAAA,EACA;AAAEyH,MAAAA,KAAAA,EAAOA,KAAAA,CAAMC;KAAQ,CAAA;EAE3B,CAAA,CAAA;AAEAC,EAAAA,mBAAAA,CAAoBL,MAAM3H,MAAAA,CAAOiI,cAAAA,IAAkB,CAAA,EAAGjI,MAAAA,CAAOkI,2BAA2B,GAAA,CAAA;AACxFC,EAAAA,eAAAA,CAAgBR,IAAAA,EAAM3H,QAAQwG,iBAAAA,CAAAA;AAC9B,EAAA,OAAOmB,IAAAA;AACT;AAhEgBpB,MAAAA,CAAAA,oBAAAA,EAAAA,sBAAAA,CAAAA;AAyET,SAAS6B,wBAAwBN,KAAAA,EAAc;AACpD,EAAA,IAAI,EAAEA,KAAAA,YAAiBO,KAAAA,CAAAA,EAAQ,OAAO,KAAA;AACtC,EAAA,MAAMN,OAAAA,GAAUD,KAAAA,CAAMC,OAAAA,CAAQO,WAAAA,EAAW;AACzC,EAAA,OACEP,OAAAA,CAAQQ,SAAS,iDAAA,CAAA,IACjBR,QAAQQ,QAAAA,CAAS,yCAAA,CAAA,IACjBR,OAAAA,CAAQQ,QAAAA,CAAS,oCAAA,KACjBR,OAAAA,CAAQQ,QAAAA,CAAS,YAAA,CAAA,IACjBR,OAAAA,CAAQQ,SAAS,cAAA,CAAA,IACjBR,OAAAA,CAAQQ,QAAAA,CAAS,WAAA,CAAA;AAErB;AAXgBH,MAAAA,CAAAA,uBAAAA,EAAAA,yBAAAA,CAAAA;AAkCT,SAASJ,mBAAAA,CAAoBL,IAAAA,EAAYa,OAAAA,EAAiBC,eAAAA,EAAuB;AACtF,EAAA,IAAID,WAAW,CAAA,EAAG;AAClB,EAAA,MAAME,eAAAA,GAAkBf,IAAAA,CAAKgB,OAAAA,CAAQC,IAAAA,CAAKjB,IAAAA,CAAAA;AAE1C,EAAA,MAAMkB,mCAAmB,MAAA,CAAA,YAAA;AACvB,IAAA,IAAIC,OAAAA,GAAU,CAAA;AACd,IAAA,WAAS;AACP,MAAA,IAAI;AACF,QAAA,OAAO,MAAMJ,eAAAA,EAAAA;AACf,MAAA,CAAA,CAAA,OAASZ,KAAAA,EAAO;AACd,QAAA,IAAIgB,OAAAA,IAAWN,OAAAA,IAAW,CAACJ,uBAAAA,CAAwBN,KAAAA,CAAAA,EAAQ;AACzD,UAAA,MAAMA,KAAAA;AACR,QAAA;AACAgB,QAAAA,OAAAA,IAAW,CAAA;AACX,QAAA,MAAMC,WAAAA,GAAcN,eAAAA,GAAkB,CAAA,KAAMK,OAAAA,GAAU,CAAA,CAAA;AACtD1I,QAAAA,MAAAA,CAAOC,IAAAA,CACL,CAAA,wDAAA,EAA2D0F,MAAAA,CAAO+C,OAAAA,CAAAA,CAAAA,CAAAA,EAAY/C,MAAAA,CAAOyC,OAAAA,CAAAA,CAAAA,eAAAA,EACpEzC,MAAAA,CAAOgD,WAAAA,CAAAA,CAAAA,EAAAA,CAAAA,EACxB;AAAEjB,UAAAA,KAAAA,EAAOA,KAAAA,YAAiBO,KAAAA,GAAQP,KAAAA,CAAMC,OAAAA,GAAUhC,OAAO+B,KAAAA;SAAO,CAAA;AAElE,QAAA,MAAM,IAAIkB,OAAAA,CAAQ,CAACC,YAAYC,UAAAA,CAAWD,OAAAA,EAASF,WAAAA,CAAAA,CAAAA;AACrD,MAAA;AACF,IAAA;EACF,CAAA,EAnByB,kBAAA,CAAA;AAqBzB,EAAA,MAAMI,cAAAA,2BAAkBC,QAAAA,KAAAA;AACtB,IAAA,IAAI,OAAOA,aAAa,UAAA,EAAY;AAClCP,MAAAA,gBAAAA,EAAAA,CAAmBQ,IAAAA,CACjB,CAACC,MAAAA,KAAAA;AACCF,QAAAA,QAAAA,CAAS/G,QAAWiH,MAAAA,EAAQA,MAAAA,CAAOC,OAAAA,CAAQX,IAAAA,CAAKU,MAAAA,CAAAA,CAAAA;AAClD,MAAA,CAAA,EACA,CAACxB,KAAAA,KAAAA;AACCsB,QAAAA,QAAAA,CAAStB,KAAAA,YAAiBO,KAAAA,GAAQP,KAAAA,GAAQ,IAAIO,KAAAA,CAAMtC,MAAAA,CAAO+B,KAAAA,CAAAA,CAAAA,EAASzF,MAAAA,EAAW,MAAMA,MAAAA,CAAAA;MACvF,CAAA,CAAA;AAEF,MAAA;AACF,IAAA;AACA,IAAA,OAAOwG,gBAAAA,EAAAA;EACT,CAAA,EAbuB,gBAAA,CAAA;AAevBlB,EAAAA,IAAAA,CAAKgB,OAAAA,GAAUQ,cAAAA;AACjB;AAzCgBnB,MAAAA,CAAAA,mBAAAA,EAAAA,qBAAAA,CAAAA;AAuDhB,SAASG,eAAAA,CAAgBR,IAAAA,EAAY3H,MAAAA,EAA4BwG,iBAAAA,EAAyB;AACxF,EAAA,IAAIxG,MAAAA,CAAOwJ,aAAa,KAAA,EAAO;AAC/B,EAAA,MAAMC,UAAAA,GAAazJ,OAAO0J,oBAAAA,IAAwB,GAAA;AAElD,EAAA,IAAID,UAAAA,IAAc,CAAA,IAAMjD,iBAAAA,GAAoB,CAAA,IAAKiD,cAAcjD,iBAAAA,EAAoB;AAOnF,EAAA,MAAMmD,4BAAAA,GAA+B,GAAA;AACrC,EAAA,IAAIC,uBAAAA,GAA0B,CAAA;AAC9B,EAAA,IAAIC,oBAAAA,GAAuB,CAAA;AAC3B,EAAA,MAAMC,KAAAA,GAAQC,YAAY,MAAA;AACxBpC,IAAAA,IAAAA,CAAKqC,KAAAA,CAAM,UAAA,CAAA,CAAYX,IAAAA,CACrB,MAAA;AACE,MAAA,IAAIO,0BAA0B,CAAA,EAAG;AAC/BxJ,QAAAA,MAAAA,CAAOO,KAAK,mCAAA,EAAqC;UAAEsJ,cAAAA,EAAgBL;SAAwB,CAAA;AAC3FA,QAAAA,uBAAAA,GAA0B,CAAA;AAC5B,MAAA;AACF,IAAA,CAAA,EACA,CAAC9B,KAAAA,KAAAA;AACC8B,MAAAA,uBAAAA,IAA2B,CAAA;AAC3B,MAAA,MAAMM,GAAAA,GAAMjF,KAAKiF,GAAAA,EAAG;AACpB,MAAA,IAAIA,GAAAA,GAAML,wBAAwBF,4BAAAA,EAA8B;AAC9DE,QAAAA,oBAAAA,GAAuBK,GAAAA;AACvB9J,QAAAA,MAAAA,CAAOC,KAAK,oGAAA,EAAiG;AAC3GuJ,UAAAA,uBAAAA;AACA9B,UAAAA,KAAAA,EAAOA,KAAAA,YAAiBO,KAAAA,GAAQP,KAAAA,CAAMC,OAAAA,GAAUhC,OAAO+B,KAAAA;SACzD,CAAA;AACF,MAAA;IACF,CAAA,CAAA;AAEJ,EAAA,CAAA,EAAG2B,UAAAA,CAAAA;AACH,EAAA,IAAI,OAAOK,KAAAA,CAAMK,KAAAA,KAAU,UAAA,QAAkBA,KAAAA,EAAK;AAGlD,EAAA,MAAMC,WAAAA,GAAczC,IAAAA,CAAK0C,GAAAA,CAAIzB,IAAAA,CAAKjB,IAAAA,CAAAA;AAClCA,EAAAA,IAAAA,CAAK0C,GAAAA,GAAO,IAAIC,IAAAA,KAAAA;AACdC,IAAAA,aAAAA,CAAcT,KAAAA,CAAAA;AACd,IAAA,OAAOM,WAAAA,CAAAA,GAAeE,IAAAA,CAAAA;AACxB,EAAA,CAAA;AACF;AA3CSnC,MAAAA,CAAAA,eAAAA,EAAAA,iBAAAA,CAAAA;AA4DF,SAASqC,6BAA6BC,WAAAA,EAA+B;AAC1E,EAAA,IAAIA,WAAAA,IAAe,CAAC3F,OAAAA,CAAQC,GAAAA,CAAI,WAAA,CAAA,EAAc;AAC5CD,IAAAA,OAAAA,CAAQC,GAAAA,CAAI,WAAA,CAAA,GAAe,CAAA,IAAA,EAAO0F,WAAAA,CAAAA,CAAAA;AACpC,EAAA;AACF;AAJgBD,MAAAA,CAAAA,4BAAAA,EAAAA,8BAAAA,CAAAA;AAST,SAASE,oBAAoB/C,IAAAA,EAAU;AAC5C,EAAA,OAAO,IAAIgD,SAAShD,IAAAA,CAAAA;AACtB;AAFgB+C,MAAAA,CAAAA,mBAAAA,EAAAA,qBAAAA,CAAAA;AAOT,SAASE,sBAAAA,CAAmDtB,QAAWtJ,MAAAA,EAA0B;AACtG,EAAA,MAAM6K,aAAAA,GAAgB/F,OAAAA,CAAQC,GAAAA,CAAI,UAAA,CAAA,KAAgB,aAAA;AAClD,EAAA,MAAM+F,kBAAAA,GAAqB9K,MAAAA,CAAO8K,kBAAAA,KAAuBD,aAAAA,GAAgB,GAAA,GAAM,GAAA,CAAA;AAG/E,EAAA,IAAI7K,MAAAA,CAAO+K,sBAAsBF,aAAAA,EAAe;AAC9CvB,IAAAA,MAAAA,CAAO0B,GAAAA,CAAI,OAAA,EAAS,CAACC,CAAAA,KAAAA;AACnB,MAAA,IAAI,OAAA,IAAWA,CAAAA,IAAK,UAAA,IAAcA,CAAAA,EAAG;AACnC,QAAA,IAAIA,CAAAA,CAAEC,WAAWJ,kBAAAA,EAAoB;AACnC1K,UAAAA,MAAAA,CAAOC,KAAK,8BAAA,EAAgC;YAC1C2J,KAAAA,EAAOiB,CAAAA,CAAEjB,KAAAA,CAAMmB,SAAAA,CAAU,CAAA,EAAG,GAAA,KAAQF,CAAAA,CAAEjB,KAAAA,CAAMoB,MAAAA,GAAS,GAAA,GAAM,KAAA,GAAQ,EAAA,CAAA;AACnEC,YAAAA,MAAAA,EAAQJ,CAAAA,CAAEI,MAAAA;YACVH,QAAAA,EAAU,CAAA,EAAGD,EAAEC,QAAQ,CAAA,EAAA;WACzB,CAAA;QACF,CAAA,MAAO;AACL9K,UAAAA,MAAAA,CAAOkL,MAAM,gBAAA,EAAkB;YAC7BtB,KAAAA,EAAOiB,CAAAA,CAAEjB,KAAAA,CAAMmB,SAAAA,CAAU,CAAA,EAAG,GAAA,KAAQF,CAAAA,CAAEjB,KAAAA,CAAMoB,MAAAA,GAAS,GAAA,GAAM,KAAA,GAAQ,EAAA,CAAA;YACnEF,QAAAA,EAAU,CAAA,EAAGD,EAAEC,QAAQ,CAAA,EAAA;WACzB,CAAA;AACF,QAAA;AACF,MAAA;IACF,CAAA,CAAA;AACF,EAAA;AAGA5B,EAAAA,MAAAA,CAAO0B,GAAAA,CAAI,OAAA,EAAS,CAACC,CAAAA,KAAAA;AACnB,IAAA,IAAI,aAAaA,CAAAA,EAAG;AAClB7K,MAAAA,MAAAA,CAAO0H,MAAM,yBAAA,EAA2B;AACtCC,QAAAA,OAAAA,EAASkD,CAAAA,CAAElD,OAAAA;AACXwD,QAAAA,MAAAA,EAAQN,CAAAA,CAAEM;OACZ,CAAA;AACF,IAAA;EACF,CAAA,CAAA;AAGAjC,EAAAA,MAAAA,CAAO0B,GAAAA,CAAI,MAAA,EAAQ,CAACC,CAAAA,KAAAA;AAClB,IAAA,IAAI,aAAaA,CAAAA,EAAG;AAClB7K,MAAAA,MAAAA,CAAOC,KAAK,2BAAA,EAA6B;AACvC0H,QAAAA,OAAAA,EAASkD,CAAAA,CAAElD,OAAAA;AACXwD,QAAAA,MAAAA,EAAQN,CAAAA,CAAEM;OACZ,CAAA;AACF,IAAA;EACF,CAAA,CAAA;AAEA,EAAA,OAAOjC,MAAAA;AACT;AA7CgBsB,MAAAA,CAAAA,sBAAAA,EAAAA,wBAAAA,CAAAA;AAkDT,IAAMY,sBAAN,MAAMA;EAlZb;;;AAmZUlC,EAAAA,MAAAA;AACA3B,EAAAA,IAAAA;EACA8D,eAAAA,GAAmC;IACzCC,WAAAA,EAAa,KAAA;IACbC,QAAAA,EAAU;AACZ,GAAA;EACQC,eAAAA,GAAkB,KAAA;EAE1B,WAAA,CAAYtC,MAAAA,EAAW3B,MAAY3H,MAAAA,EAA4B;AAC7D,IAAA,IAAA,CAAKsJ,MAAAA,GAASA,MAAAA;AACd,IAAA,IAAA,CAAK3B,IAAAA,GAAOA,IAAAA;AAGZiD,IAAAA,sBAAAA,CAAuB,IAAA,CAAKtB,QAAQtJ,MAAAA,CAAAA;AACtC,EAAA;;;;EAKO6L,SAAAA,GAAe;AACpB,IAAA,OAAO,IAAA,CAAKvC,MAAAA;AACd,EAAA;;;;EAKOwC,OAAAA,GAAgB;AACrB,IAAA,OAAO,IAAA,CAAKnE,IAAAA;AACd,EAAA;;;;EAKOoE,kBAAAA,GAAsC;AAC3C,IAAA,OAAO;AAAE,MAAA,GAAG,IAAA,CAAKN;AAAgB,KAAA;AACnC,EAAA;;;;AAKA,EAAA,MAAa9C,OAAAA,CAAQH,OAAAA,GAAU,CAAA,EAAGwD,KAAAA,GAAQ,GAAA,EAAqB;AAC7D,IAAA,IAAI,IAAA,CAAKP,gBAAgBC,WAAAA,EAAa;AACpCtL,MAAAA,MAAAA,CAAOO,KAAK,wCAAA,CAAA;AACZ,MAAA;AACF,IAAA;AAEA,IAAA,KAAA,IAASmI,OAAAA,GAAU,CAAA,EAAGA,OAAAA,IAAWN,OAAAA,EAASM,OAAAA,EAAAA,EAAW;AACnD,MAAA,IAAA,CAAK2C,gBAAgBE,QAAAA,GAAW7C,OAAAA;AAEhC,MAAA,IAAI;AACF,QAAA,MAAM,IAAA,CAAKQ,OAAO2C,QAAAA,EAAQ;AAC1B,QAAA,IAAA,CAAKR,gBAAgBC,WAAAA,GAAc,IAAA;AACnC,QAAA,IAAA,CAAKD,eAAAA,CAAgBS,eAAAA,mBAAkB,IAAIjH,IAAAA,EAAAA;AAC3C,QAAA,IAAA,CAAKwG,gBAAgBU,SAAAA,GAAY9J,KAAAA,CAAAA;AAEjCjC,QAAAA,MAAAA,CAAOO,KAAK,6CAAA,CAAA;AACZ,QAAA;AACF,MAAA,CAAA,CAAA,OAASmH,KAAAA,EAAO;AACd,QAAA,MAAMsE,eAAetE,KAAAA,YAAiBO,KAAAA,GAAQP,KAAAA,CAAMC,OAAAA,GAAUhC,OAAO+B,KAAAA,CAAAA;AACrE,QAAA,IAAA,CAAK2D,gBAAgBU,SAAAA,GAAYC,YAAAA;AAEjChM,QAAAA,MAAAA,CAAO0H,KAAAA,CAAM,CAAA,4BAAA,EAA+BgB,OAAAA,CAAAA,CAAAA,EAAWN,OAAAA,CAAAA,OAAAA,CAAAA,EAAkB;UACvEV,KAAAA,EAAOsE;SACT,CAAA;AAEA,QAAA,IAAItD,YAAYN,OAAAA,EAAS;AACvBpI,UAAAA,MAAAA,CAAO0H,MAAM,yCAAA,CAAA;AACb,UAAA,MAAMA,KAAAA;AACR,QAAA;AAGA,QAAA,MAAMuE,WAAWL,KAAAA,GAAQM,IAAAA,CAAKC,GAAAA,CAAI,CAAA,EAAGzD,UAAU,CAAA,CAAA;AAC/C1I,QAAAA,MAAAA,CAAOO,IAAAA,CAAK,CAAA,qBAAA,EAAwB0L,QAAAA,CAAAA,KAAAA,CAAe,CAAA;AACnD,QAAA,MAAM,IAAIrD,OAAAA,CAAQ,CAACC,YAAYC,UAAAA,CAAWD,OAAAA,EAASoD,QAAAA,CAAAA,CAAAA;AACrD,MAAA;AACF,IAAA;AACF,EAAA;;;;AAKA,EAAA,MAAaG,UAAAA,GAA4B;AAEvC,IAAA,IAAI,KAAKZ,eAAAA,EAAiB;AACxBxL,MAAAA,MAAAA,CAAOkL,MAAM,mDAAA,CAAA;AACb,MAAA;AACF,IAAA;AAEA,IAAA,IAAI,CAAC,IAAA,CAAKG,eAAAA,CAAgBC,WAAAA,EAAa;AACrCtL,MAAAA,MAAAA,CAAOO,KAAK,wCAAA,CAAA;AACZ,MAAA;AACF,IAAA;AAGA,IAAA,IAAA,CAAKiL,eAAAA,GAAkB,IAAA;AAEvB,IAAA,IAAI;AACF,MAAA,MAAM,IAAA,CAAKtC,OAAOmD,WAAAA,EAAW;AAC7B,MAAA,MAAM,IAAA,CAAK9E,KAAK0C,GAAAA,EAAG;AACnB,MAAA,IAAA,CAAKoB,gBAAgBC,WAAAA,GAAc,KAAA;AAEnCtL,MAAAA,MAAAA,CAAOO,KAAK,kDAAA,CAAA;AACd,IAAA,CAAA,CAAA,OAASmH,KAAAA,EAAO;AACd,MAAA,MAAMsE,eAAetE,KAAAA,YAAiBO,KAAAA,GAAQP,KAAAA,CAAMC,OAAAA,GAAUhC,OAAO+B,KAAAA,CAAAA;AAGrE,MAAA,IAAIsE,YAAAA,CAAa7D,QAAAA,CAAS,mCAAA,CAAA,EAAsC;AAC9DnI,QAAAA,MAAAA,CAAOkL,MAAM,0DAAA,CAAA;AACb,QAAA,IAAA,CAAKG,gBAAgBC,WAAAA,GAAc,KAAA;AACnC,QAAA;AACF,MAAA;AAEAtL,MAAAA,MAAAA,CAAO0H,MAAM,4CAAA,EAA8C;QACzDA,KAAAA,EAAOsE;OACT,CAAA;AACA,MAAA,MAAMtE,KAAAA;IACR,CAAA,SAAA;AACE,MAAA,IAAA,CAAK8D,eAAAA,GAAkB,KAAA;AACzB,IAAA;AACF,EAAA;;;;EAKOc,wBAAAA,GAAiC;AACtC,IAAA,MAAMC,eAAAA,iCAAyBC,MAAAA,KAAAA;AAC7BxM,MAAAA,MAAAA,CAAOO,IAAAA,CAAK,CAAA,kBAAA,EAAqBiM,MAAAA,CAAAA,+BAAAA,CAAuC,CAAA;AAExE,MAAA,IAAI;AACF,QAAA,MAAM,KAAKJ,UAAAA,EAAU;AACrB1H,QAAAA,OAAAA,CAAQ+H,KAAK,CAAA,CAAA;AACf,MAAA,CAAA,CAAA,OAAS/E,KAAAA,EAAO;AACd1H,QAAAA,MAAAA,CAAO0H,MAAM,yCAAA,EAA2C;AACtDA,UAAAA,KAAAA,EAAOA,KAAAA,YAAiBO,KAAAA,GAAQP,KAAAA,CAAMC,OAAAA,GAAUhC,OAAO+B,KAAAA;SACzD,CAAA;AACAhD,QAAAA,OAAAA,CAAQ+H,KAAK,CAAA,CAAA;AACf,MAAA;IACF,CAAA,EAZwB,iBAAA,CAAA;AAexB/H,IAAAA,OAAAA,CAAQ+C,GAAG,QAAA,EAAU,MAAM,KAAK8E,eAAAA,CAAgB,QAAA,CAAA,CAAA;AAChD7H,IAAAA,OAAAA,CAAQ+C,GAAG,SAAA,EAAW,MAAM,KAAK8E,eAAAA,CAAgB,SAAA,CAAA,CAAA;AACjD7H,IAAAA,OAAAA,CAAQ+C,GAAG,YAAA,EAAc,MAAM,KAAK,IAAA,CAAK2E,YAAU,CAAA;AACrD,EAAA;AACF;AA0CO,SAASM,kBAAAA,CACdC,yBACA/M,MAAAA,EAA0B;AAE1B,EAAA,MAAM6K,aAAAA,GAAgB/F,OAAAA,CAAQC,GAAAA,CAAI,UAAA,CAAA,KAAgB,aAAA;AAGlD,EAAA,MAAM4C,IAAAA,GAAOpB,qBAAqBvG,MAAAA,CAAAA;AAGlC,EAAA,MAAMgN,OAAAA,GAAUtC,oBAAoB/C,IAAAA,CAAAA;AAGpC,EAAA,MAAMsF,SAAAA,GACHjN,MAAAA,CAAOiN,SAAAA,KACPpC,aAAAA,GACG;AACE,IAAA;MAAEqC,IAAAA,EAAM,OAAA;MAASC,KAAAA,EAAO;AAAQ,KAAA;AAChC,IAAA;MAAED,IAAAA,EAAM,OAAA;MAASC,KAAAA,EAAO;AAAO,KAAA;AAC/B,IAAA;MAAED,IAAAA,EAAM,OAAA;MAASC,KAAAA,EAAO;AAAO,KAAA;AAC/B,IAAA;MAAED,IAAAA,EAAM,OAAA;MAASC,KAAAA,EAAO;AAAQ;AAElC,GAAA,GAAA;AACE,IAAA;MAAED,IAAAA,EAAM,OAAA;MAASC,KAAAA,EAAO;AAAO,KAAA;AAC/B,IAAA;MAAED,IAAAA,EAAM,OAAA;MAASC,KAAAA,EAAO;AAAQ;;AAIxC,EAAA,MAAM7D,MAAAA,GAAS,IAAIyD,uBAAAA,CAAwB;AACzCC,IAAAA,OAAAA;IACAI,GAAAA,EAAKH;GACP,CAAA;AAGA,EAAA,OAAO,IAAIzB,mBAAAA,CAAoBlC,MAAAA,EAAQ3B,IAAAA,EAAM3H,MAAAA,CAAAA;AAC/C;AAnCgB8M,MAAAA,CAAAA,kBAAAA,EAAAA,oBAAAA,CAAAA;;;ACjgBhB,IAAMO,aAAAA,GAGF;EACFrM,OAAAA,EAAS,IAAA;EACTsM,mBAAAA,EAAqB;AAAC,IAAA,QAAA;AAAU,IAAA,QAAA;AAAU,IAAA,QAAA;AAAU,IAAA,YAAA;AAAc,IAAA;;AACpE,CAAA;AAKA,SAASC,iBAAAA,CACPC,OACA1J,MAAAA,EAAe;AAEf,EAAA,IAAI,CAACA,MAAAA,IAAU,OAAOA,MAAAA,KAAW,QAAA,EAAU;AACzC,IAAA,OAAO,IAAA;AACT,EAAA;AAEA,EAAA,MAAM2J,MAAAA,GAAS3J,MAAAA;AACf,EAAA,MAAMyB,EAAAA,GAAKkI,OAAO,IAAA,CAAA;AAElB,EAAA,IAAI,CAAClI,EAAAA,EAAI;AACP,IAAA,OAAO,IAAA;AACT,EAAA;AAEA,EAAA,OAAO;AACLA,IAAAA,EAAAA;IACAE,IAAAA,EAAM+H,KAAAA;IACNrL,IAAAA,EAAMsL;AACR,GAAA;AACF;AApBSF,MAAAA,CAAAA,iBAAAA,EAAAA,mBAAAA,CAAAA;AAyBT,SAASG,eAAepD,IAAAA,EAAa;AAKnC,EAAA,IAAI,CAACA,IAAAA,IAAQ,OAAOA,IAAAA,KAAS,QAAA,EAAU;AACrC,IAAA,OAAO,EAAC;AACV,EAAA;AAEA,EAAA,MAAMnI,IAAAA,GACHmI,IAAAA,CAA6E,MAAA,CAAA,IAC7EA,KAA6C,OAAA,CAAA;AAEhD,EAAA,IAAI,CAACnI,IAAAA,IAAQ,OAAOA,IAAAA,KAAS,QAAA,EAAU;AACrC,IAAA,OAAO,EAAC;AACV,EAAA;AAEA,EAAA,OAAO;AACLsC,IAAAA,cAAAA,EAAgBtC,KAAK,gBAAA,CAAA;IACrBwL,OAAAA,EACGxL,IAAAA,CAAK,SAAA,CAAA,IACLA,IAAAA,CAAK,WAAA,KACLA,IAAAA,CAAK,WAAA,CAAA,IACLA,IAAAA,CAAK,QAAA,CAAA;AACRyL,IAAAA,WAAAA,EAAczL,IAAAA,CAAK,aAAA,CAAA,IAA0CA,IAAAA,CAAK,aAAA;AACpE,GAAA;AACF;AA1BSuL,MAAAA,CAAAA,cAAAA,EAAAA,gBAAAA,CAAAA;AA+BT,SAASG,eAAAA,CACPrJ,SAAAA,EACAgJ,KAAAA,EACA1J,MAAAA,EACAwG,MACAtK,MAAAA,EAA6B;AAE7B,EAAA,MAAM8N,UAAAA,GAAaP,iBAAAA,CAAkBC,KAAAA,EAAO1J,MAAAA,CAAAA;AAC5C,EAAA,IAAI,CAACgK,UAAAA,EAAY;AACf,IAAA;AACF,EAAA;AAGA,EAAA,IAAI,CAACtO,aAAAA,CAAcwC,kBAAAA,CAAmBwL,KAAAA,CAAAA,EAAQ;AAC5C,IAAA;AACF,EAAA;AAGA,EAAA,IAAIxN,MAAAA,CAAO+N,WAAAA,IAAe/N,MAAAA,CAAO+N,WAAAA,CAAY3C,MAAAA,GAAS,CAAA,IAAK,CAACpL,MAAAA,CAAO+N,WAAAA,CAAYxF,QAAAA,CAASiF,KAAAA,CAAAA,EAAQ;AAC9F,IAAA;AACF,EAAA;AAEA,EAAA,MAAMQ,OAAAA,GAAUN,eAAepD,IAAAA,CAAAA;AAC/B,EAAA,MAAM2D,WAAAA,GAAcvI,oBAAAA,CAAqB8H,KAAAA,EAAOM,UAAAA,CAAW3L,IAAI,CAAA;AAI/D,EAAA,MAAM+L,KAAAA,GAAQ1O,cAAc0C,iBAAAA,CAAkBsL,KAAAA,EAAOM,WAAW3L,IAAI,CAAA,IAAK6L,QAAQvJ,cAAAA,IAAkB,SAAA;AACnG,EAAA,MAAMmJ,cAAcpO,aAAAA,CAAc8C,cAAAA,CAAekL,OAAOM,UAAAA,CAAW3L,IAAI,KAAK6L,OAAAA,CAAQJ,WAAAA;AACpF,EAAA,MAAMD,OAAAA,GAAUK,QAAQL,OAAAA,IAAW,SAAA;AAGnC,EAAA,MAAMQ,YAAAA,GAAe3O,aAAAA,CAAciD,mBAAAA,CAAoB+K,KAAAA,EAAOM,WAAW3L,IAAI,CAAA;AAE7E,EAAA,IAAIgM,YAAAA,EAAc;AAChB/N,IAAAA,MAAAA,CAAOkL,KAAAA,CAAM,CAAA,8CAAA,EAAiDkC,KAAAA,CAAAA,CAAAA,EAAS;AACrEtK,MAAAA,gBAAAA,EAAkBiL,YAAAA,CAAajL,gBAAAA;MAC/BkL,OAAAA,EAAS,CAAC,CAACD,YAAAA,CAAavL;KAC1B,CAAA;AACF,EAAA;AAGA5C,EAAAA,MAAAA,CAAOqO,YAAAA,CACJC,mBACC9J,SAAAA,EACA;AACEe,IAAAA,EAAAA,EAAIuI,UAAAA,CAAWvI,EAAAA;AACfE,IAAAA,IAAAA,EAAMqI,UAAAA,CAAWrI,IAAAA;IACjBtD,IAAAA,EAAM8L;GACR,EACA;AACExD,IAAAA,WAAAA,EAAazK,MAAAA,CAAOyK,WAAAA;IACpBhG,cAAAA,EAAgByJ,KAAAA;AAChBP,IAAAA,OAAAA;AACAC,IAAAA;AACF,GAAA,EACAO,YAAAA,CAAAA,CAEDI,KAAAA,CAAM,CAACzG,KAAAA,KAAAA;AACN1H,IAAAA,MAAAA,CAAO0H,KAAAA,CAAM,2CAA2CA,KAAAA,CAAAA;EAC1D,CAAA,CAAA;AAIF,EAAA,IAAItD,SAAAA,KAAc,gBAAA,IAAoBA,SAAAA,KAAc,gBAAA,EAAkB;AACpEgK,IAAAA,sBAAAA,CAAuBhB,KAAAA,EAAOM,UAAAA,CAAW3L,IAAAA,EAAM+L,KAAAA,EAAOlO,MAAAA,CAAAA;AACxD,EAAA;AACF;AAnES6N,MAAAA,CAAAA,eAAAA,EAAAA,iBAAAA,CAAAA;AAyET,SAASW,sBAAAA,CACPzO,UAAAA,EACA2C,UAAAA,EACA+B,cAAAA,EACAzE,MAAAA,EAA6B;AAG7B,EAAA,MAAMS,aAAAA,GAAgBjB,aAAAA,CAAcqE,yBAAAA,CAA0B9D,UAAAA,CAAAA;AAE9D,EAAA,IAAIU,aAAAA,CAAc2K,WAAW,CAAA,EAAG;AAC9B,IAAA;AACF,EAAA;AAEA,EAAA,MAAMqD,MAAAA,GAAS/L,WAAW,IAAA,CAAA;AAC1B,EAAA,IAAI,CAAC+L,MAAAA,EAAQ;AACX,IAAA;AACF,EAAA;AAGA,EAAA,KAAA,MAAW,CAACC,eAAAA,EAAiBpN,kBAAAA,CAAAA,IAAuBb,aAAAA,EAAe;AACjE,IAAA,MAAMkO,eAAAA,GAAkBjM,UAAAA,CAAWpB,kBAAAA,CAAmB0E,SAAS,CAAA;AAG/D,IAAA,IAAI,CAAC2I,eAAAA,EAAiB;AACpB,MAAA;AACF,IAAA;AAGA,IAAA,IAAIC,aAAatN,kBAAAA,CAAmBkE,EAAAA;AACpC,IAAA,IAAIlE,kBAAAA,CAAmBkE,OAAO,GAAA,EAAK;AACjC,MAAA,IAAIlE,mBAAmBuN,oBAAAA,EAAsB;AAC3CD,QAAAA,UAAAA,GAAalM,UAAAA,CAAWpB,mBAAmBuN,oBAAoB,CAAA;AAC/D,QAAA,IAAI,CAACD,UAAAA,EAAY;AACfxO,UAAAA,MAAAA,CAAOC,IAAAA,CAAK,CAAA,2CAAA,EAA8CqO,eAAAA,CAAAA,wBAAAA,CAAyC,CAAA;AACnG,UAAA;AACF,QAAA;MACF,CAAA,MAAO;AACLtO,QAAAA,MAAAA,CAAOkL,KAAAA,CAAM,CAAA,wEAAA,EAA2EoD,eAAAA,CAAAA,CAAiB,CAAA;AACzG,QAAA;AACF,MAAA;AACF,IAAA;AAGA,IAAA,MAAM/J,WAAWrD,kBAAAA,CAAmB2E,eAAAA,GAChC3E,kBAAAA,CAAmB2E,eAAAA,CAAgBvD,UAAAA,CAAAA,GACnC;AAAEoM,MAAAA,WAAAA,EAAaxN,kBAAAA,CAAmBwN;AAAY,KAAA;AAGlD9O,IAAAA,MAAAA,CAAOqO,YAAAA,CACJC,mBACC,sBAAA,EACA;MACE/I,EAAAA,EAAI,CAAA,EAAGkJ,MAAAA,CAAAA,CAAAA,EAAUE,eAAAA,CAAAA,CAAAA;AACjBlJ,MAAAA,IAAAA,EAAMnE,kBAAAA,CAAmBmC,KAAAA;MACzBtB,IAAAA,EAAM;QACJP,IAAAA,EAAM;UACJ2D,EAAAA,EAAIkJ,MAAAA;UACJhJ,IAAAA,EAAM1F;AACR,SAAA;QACAyF,EAAAA,EAAI;UACFD,EAAAA,EAAIoJ,eAAAA;UACJlJ,IAAAA,EAAMmJ;AACR,SAAA;AACAG,QAAAA,YAAAA,EAAczN,kBAAAA,CAAmBmC,KAAAA;AACjCkB,QAAAA;AACF;KACF,EACA;AACE8F,MAAAA,WAAAA,EAAazK,MAAAA,CAAOyK,WAAAA;AACpBhG,MAAAA;KACF,CAAA,CAED8J,KAAAA,CAAM,CAACzG,KAAAA,KAAAA;AACN1H,MAAAA,MAAAA,CAAO0H,KAAAA,CAAM,CAAA,wDAAA,EAA2D4G,eAAAA,CAAAA,CAAAA,CAAAA,EAAoB5G,KAAAA,CAAAA;IAC9F,CAAA,CAAA;AAEF1H,IAAAA,MAAAA,CAAOkL,KAAAA,CACL,CAAA,gDAAA,EAAmDhK,kBAAAA,CAAmBmC,KAAK,CAAA,EAAA,EAAK1D,UAAAA,CAAAA,CAAAA,EAAc0O,MAAAA,CAAAA,IAAAA,EAAaG,UAAAA,CAAAA,CAAAA,EAAcD,eAAAA,CAAAA,CAAAA,CAAkB,CAAA;AAE/I,EAAA;AACF;AAhFSH,MAAAA,CAAAA,sBAAAA,EAAAA,wBAAAA,CAAAA;AA2GF,SAASQ,iBAAAA,CAAqBC,YAAejP,MAAAA,EAA6B;AAC/E,EAAA,MAAMkP,UAAAA,GAAa;IAAE,GAAG7B,aAAAA;IAAe,GAAGrN;AAAO,GAAA;AAEjD,EAAA,IAAI,CAACkP,WAAWlO,OAAAA,EAAS;AACvBZ,IAAAA,MAAAA,CAAOO,KAAK,uDAAA,CAAA;AACZ,IAAA,OAAOsO,UAAAA;AACT,EAAA;AAGA,EAAA,MAAME,YAAAA,GAAeF,UAAAA;AAErB,EAAA,OAAOE,aAAaC,QAAAA,CAAS;IAC3BpF,KAAAA,EAAO;MACLqF,UAAAA,EAAY;AACV,QAAA,MAAMC,MAAAA,CAAO,EACX9B,KAAAA,EACAlD,IAAAA,EACAN,OAAK,EAKN;AACC,UAAA,MAAMlG,MAAAA,GAAS,MAAMkG,KAAAA,CAAMM,IAAAA,CAAAA;AAE3B,UAAA,IAAI4E,UAAAA,CAAW5B,mBAAAA,EAAqB/E,QAAAA,CAAS,QAAA,CAAA,EAAW;AACtDsF,YAAAA,eAAAA,CAAgB,gBAAA,EAAkBL,KAAAA,EAAO1J,MAAAA,EAAQwG,IAAAA,EAAM4E,UAAAA,CAAAA;AACzD,UAAA;AAEA,UAAA,OAAOpL,MAAAA;AACT,QAAA,CAAA;AAEA,QAAA,MAAMyL,MAAAA,CAAO,EACX/B,KAAAA,EACAlD,IAAAA,EACAN,OAAK,EAKN;AACC,UAAA,MAAMlG,MAAAA,GAAS,MAAMkG,KAAAA,CAAMM,IAAAA,CAAAA;AAE3B,UAAA,IAAI4E,UAAAA,CAAW5B,mBAAAA,EAAqB/E,QAAAA,CAAS,QAAA,CAAA,EAAW;AACtDsF,YAAAA,eAAAA,CAAgB,gBAAA,EAAkBL,KAAAA,EAAO1J,MAAAA,EAAQwG,IAAAA,EAAM4E,UAAAA,CAAAA;AACzD,UAAA;AAEA,UAAA,OAAOpL,MAAAA;AACT,QAAA,CAAA;AAEA,QAAA,MAAM0L,MAAAA,CAAO,EACXhC,KAAAA,EACAlD,IAAAA,EACAN,OAAK,EAKN;AACC,UAAA,MAAMlG,MAAAA,GAAS,MAAMkG,KAAAA,CAAMM,IAAAA,CAAAA;AAE3B,UAAA,IAAI4E,UAAAA,CAAW5B,mBAAAA,EAAqB/E,QAAAA,CAAS,QAAA,CAAA,EAAW;AACtDsF,YAAAA,eAAAA,CAAgB,gBAAA,EAAkBL,KAAAA,EAAO1J,MAAAA,EAAQwG,IAAAA,EAAM4E,UAAAA,CAAAA;AACzD,UAAA;AAEA,UAAA,OAAOpL,MAAAA;AACT,QAAA,CAAA;AAEA,QAAA,MAAM2L,UAAAA,CAAW,EACfjC,KAAAA,EACAlD,IAAAA,EACAN,OAAK,EAKN;AACC,UAAA,MAAMlG,MAAAA,GAAS,MAAMkG,KAAAA,CAAMM,IAAAA,CAAAA;AAE3B,UAAA,IAAI4E,UAAAA,CAAW5B,mBAAAA,EAAqB/E,QAAAA,CAAS,YAAA,CAAA,EAAe;AAC1DnI,YAAAA,MAAAA,CAAOO,IAAAA,CAAK,CAAA,iCAAA,EAAoC6M,KAAAA,CAAAA,0CAAAA,CAAiD,CAAA;AACnG,UAAA;AAEA,UAAA,OAAO1J,MAAAA;AACT,QAAA,CAAA;AAEA,QAAA,MAAM4L,UAAAA,CAAW,EACflC,KAAAA,EACAlD,IAAAA,EACAN,OAAK,EAKN;AACC,UAAA,MAAMlG,MAAAA,GAAS,MAAMkG,KAAAA,CAAMM,IAAAA,CAAAA;AAE3B,UAAA,IAAI4E,UAAAA,CAAW5B,mBAAAA,EAAqB/E,QAAAA,CAAS,YAAA,CAAA,EAAe;AAC1DnI,YAAAA,MAAAA,CAAOO,IAAAA,CAAK,CAAA,iCAAA,EAAoC6M,KAAAA,CAAAA,0CAAAA,CAAiD,CAAA;AACnG,UAAA;AAEA,UAAA,OAAO1J,MAAAA;AACT,QAAA;AACF;AACF;GACF,CAAA;AACF;AA1GgBkL,MAAAA,CAAAA,iBAAAA,EAAAA,mBAAAA,CAAAA","file":"chunk-OCYZEBOL.js","sourcesContent":["/**\n * Graph Registry - Decentralized Graph Configuration System\n *\n * This registry allows each module to define its own graph configuration\n * without touching the central graph module. Modules register their entity\n * and relationship mappings, which are then used by the graph sync service.\n *\n * @module graph-registry\n * @category Graph\n */\nimport { logger } from '../../logger/index.js';\nimport type {\n EntityGraphConfig,\n ModuleGraphConfig,\n RelationshipGraphConfig,\n RegistryEntityRbacConfig,\n} from '../types.js';\n\n/**\n * Internal representation of entity config with resolved fields\n */\ninterface ResolvedEntityGraphConfig extends Omit<EntityGraphConfig, 'fields'> {\n fields: string[];\n getOrgId?: (data: Record<string, unknown>) => string | undefined;\n getWorkspaceId?: (data: Record<string, unknown>) => string | undefined;\n rbac?: RegistryEntityRbacConfig;\n}\n\n/**\n * Central registry for all graph configurations\n */\nexport class GraphRegistry {\n private static entityMappings: Map<string, ResolvedEntityGraphConfig> = new Map();\n private static relationshipMappings: Map<string, RelationshipGraphConfig> = new Map();\n private static registeredModules: Set<string> = new Set();\n\n /**\n * Resolve fields from entity configuration\n *\n * @param entityType - Name of the entity type\n * @param config - Entity configuration\n * @returns Resolved array of field names\n */\n private static resolveFields(entityType: string, config: EntityGraphConfig): string[] {\n if (Array.isArray(config.fields)) {\n return config.fields;\n }\n\n // Fallback: empty array if fields not configured\n logger.warn(`[GraphRegistry] No fields configuration for ${entityType}, using empty array`);\n return [];\n }\n\n /**\n * Register a module's graph configuration\n * @param config - Module graph configuration\n */\n static registerModule(config: ModuleGraphConfig): void {\n const { moduleName, entities, relationships } = config;\n\n if (this.registeredModules.has(moduleName)) {\n logger.warn(`[GraphRegistry] Module '${moduleName}' already registered, skipping`);\n return;\n }\n\n logger.info(`[GraphRegistry] Registering module: ${moduleName}`);\n\n // Register entities\n let entityCount = 0;\n for (const [entityType, entityConfig] of Object.entries(entities)) {\n if (entityConfig.enabled !== false) {\n // Resolve fields\n const resolvedFields = this.resolveFields(entityType, entityConfig);\n\n // Store resolved configuration\n const resolvedConfig: ResolvedEntityGraphConfig = {\n ...entityConfig,\n fields: resolvedFields,\n };\n\n this.entityMappings.set(entityType, resolvedConfig);\n entityCount++;\n }\n }\n\n // Register relationships\n let relationshipCount = 0;\n if (relationships) {\n for (const [relationshipType, relationshipConfig] of Object.entries(relationships)) {\n if (relationshipConfig.enabled !== false) {\n this.relationshipMappings.set(relationshipType, relationshipConfig);\n relationshipCount++;\n }\n }\n }\n\n this.registeredModules.add(moduleName);\n logger.info(\n `[GraphRegistry] ✅ Registered ${moduleName}: ${entityCount} entities, ${relationshipCount} relationships`\n );\n }\n\n /**\n * Get entity configuration by entity type\n * @param entityType - Entity type name (e.g., 'Calendar', 'Group')\n * @returns Entity configuration or undefined (with resolved fields)\n */\n static getEntityConfig(entityType: string): ResolvedEntityGraphConfig | undefined {\n return this.entityMappings.get(entityType);\n }\n\n /**\n * Get relationship configuration by relationship type\n * @param relationshipType - Relationship type name (e.g., 'EventAttendee', 'GroupMembership')\n * @returns Relationship configuration or undefined\n */\n static getRelationshipConfig(relationshipType: string): RelationshipGraphConfig | undefined {\n return this.relationshipMappings.get(relationshipType);\n }\n\n /**\n * Get all registered entity types\n * @returns Array of entity type names\n */\n static getAllEntityTypes(): string[] {\n return Array.from(this.entityMappings.keys());\n }\n\n /**\n * Get all registered relationship types\n * @returns Array of relationship type names\n */\n static getAllRelationshipTypes(): string[] {\n return Array.from(this.relationshipMappings.keys());\n }\n\n /**\n * Get all registered module names\n * @returns Array of module names\n */\n static getRegisteredModules(): string[] {\n return Array.from(this.registeredModules);\n }\n\n /**\n * Check if an entity type is registered\n * @param entityType - Entity type to check\n * @returns True if registered\n */\n static isEntityRegistered(entityType: string): boolean {\n return this.entityMappings.has(entityType);\n }\n\n /**\n * Check if a relationship type is registered\n * @param relationshipType - Relationship type to check\n * @returns True if registered\n */\n static isRelationshipRegistered(relationshipType: string): boolean {\n return this.relationshipMappings.has(relationshipType);\n }\n\n /**\n * Extract organization ID from entity data using configured mapping function\n * @param entityType - Entity type name\n * @param data - Entity data record\n * @returns Organization ID or undefined\n */\n static getOrganizationId(entityType: string, data: Record<string, unknown>): string | undefined {\n const config = this.entityMappings.get(entityType);\n if (!config || !config.getOrgId) {\n return undefined;\n }\n return config.getOrgId(data);\n }\n\n /**\n * Extract workspace ID from entity data using configured mapping function\n * @param entityType - Entity type name\n * @param data - Entity data record\n * @returns Workspace ID or undefined\n */\n static getWorkspaceId(entityType: string, data: Record<string, unknown>): string | undefined {\n const config = this.entityMappings.get(entityType);\n if (!config || !config.getWorkspaceId) {\n return undefined;\n }\n return config.getWorkspaceId(data);\n }\n\n /**\n * Get RBAC configuration for an entity type\n * Used by the Prisma graph extension to include RBAC metadata in entity events\n * @param entityType - Entity type name (e.g., 'Conversation', 'Agent')\n * @returns RBAC config or undefined if no RBAC is configured for this entity\n */\n static getRbacConfig(entityType: string): RegistryEntityRbacConfig | undefined {\n const config = this.entityMappings.get(entityType);\n return config?.rbac;\n }\n\n /**\n * Resolve RBAC event metadata from entity data\n * Converts the registry's function-based RBAC config into the flat metadata\n * structure expected by the RBAC consumer in the NATS event payload.\n * @param entityType - Entity type name\n * @param entityData - The entity data record\n * @returns RBAC metadata for the event or undefined\n */\n static resolveRbacMetadata(\n entityType: string,\n entityData: Record<string, unknown>\n ):\n | {\n resourceTypeName: string;\n name?: string;\n identifier?: string;\n parentResourceIdentifier?: string;\n createResource?: boolean;\n }\n | undefined {\n const rbacConfig = this.getRbacConfig(entityType);\n if (!rbacConfig) {\n return undefined;\n }\n\n const name = rbacConfig.extractName ? rbacConfig.extractName(entityData) : undefined;\n const identifier = rbacConfig.extractIdentifier ? rbacConfig.extractIdentifier(entityData) : undefined;\n const parentResourceIdentifier = rbacConfig.parentResourceField\n ? (entityData[rbacConfig.parentResourceField] as string | undefined)\n : undefined;\n\n return {\n resourceTypeName: rbacConfig.resourceTypeName,\n ...(name && { name }),\n ...(identifier && { identifier }),\n ...(parentResourceIdentifier && { parentResourceIdentifier }),\n ...(rbacConfig.createResource !== undefined && { createResource: rbacConfig.createResource }),\n };\n }\n\n /**\n * Get statistics about registered configurations\n * @returns Statistics object\n */\n static getStats(): {\n modules: number;\n entities: number;\n relationships: number;\n collections: Set<string>;\n edgeTypes: Set<string>;\n } {\n const collections = new Set<string>();\n const edgeTypes = new Set<string>();\n\n for (const config of this.entityMappings.values()) {\n collections.add(config.collection || 'product_entities');\n }\n\n for (const config of this.relationshipMappings.values()) {\n if (config.label) {\n edgeTypes.add(config.label);\n }\n }\n\n return {\n modules: this.registeredModules.size,\n entities: this.entityMappings.size,\n relationships: this.relationshipMappings.size,\n collections,\n edgeTypes,\n };\n }\n\n /**\n * Clear all registrations (for testing)\n */\n static clear(): void {\n this.entityMappings.clear();\n this.relationshipMappings.clear();\n this.registeredModules.clear();\n logger.info('[GraphRegistry] Cleared all registrations');\n }\n\n /**\n * Get all relationships where the given entity type is the \"from\" side\n * This is used for automatic relationship event emission when entities are created/updated\n * @param entityType - Entity type name (e.g., 'UniversalTag')\n * @returns Array of [relationshipKey, config] tuples\n */\n static getRelationshipsForEntity(entityType: string): Array<[string, RelationshipGraphConfig]> {\n const result: Array<[string, RelationshipGraphConfig]> = [];\n\n for (const [key, config] of this.relationshipMappings.entries()) {\n if (config.from === entityType) {\n result.push([key, config]);\n }\n }\n\n return result;\n }\n\n /**\n * Print registry status to console\n */\n static printStatus(): void {\n const stats = this.getStats();\n logger.info('');\n logger.info('📊 Graph Registry Status');\n logger.info('========================');\n logger.info(`Registered Modules: ${stats.modules}`);\n logger.info(`Total Entities: ${stats.entities}`);\n logger.info(`Total Relationships: ${stats.relationships}`);\n logger.info(`Vertex Collections: ${stats.collections.size}`);\n logger.info(`Edge Types: ${stats.edgeTypes.size}`);\n logger.info('');\n logger.info('Registered Modules:', this.getRegisteredModules().join(', '));\n logger.info('');\n }\n}\n","/**\n * Event Helpers - Registry-Based Graph Event Utilities\n *\n * This version uses the GraphRegistry to dynamically load entity and relationship\n * configurations from module-level graph.config.ts files.\n *\n * @module graph-helpers\n * @category Graph\n */\nimport { logger } from '../../logger/index.js';\nimport type { GraphEvent, GraphEventType } from '../types.js';\nimport { GraphRegistry } from './registry.js';\n\nconst uuidv4 = (): string => crypto.randomUUID();\n\n/**\n * Create an entity event for the graph\n */\nexport function createEntityEvent(\n eventType: GraphEventType,\n organizationId: string,\n entity: {\n id: string;\n type: string;\n data: Record<string, unknown>;\n },\n metadata?: {\n userId?: string;\n correlationId?: string;\n workspaceId?: string;\n projectId?: string;\n },\n productSource?: string\n): GraphEvent {\n return {\n eventId: `evt_${uuidv4()}`,\n eventType,\n organizationId,\n productSource: productSource || process.env['PRODUCT_SOURCE'] || 'default',\n timestamp: new Date().toISOString(),\n entity,\n metadata: {\n userId: metadata?.userId,\n correlationId: metadata?.correlationId || `req_${uuidv4()}`,\n },\n };\n}\n\n/**\n * Create a relationship event for the graph\n */\nexport function createRelationshipEvent(\n eventType: GraphEventType,\n organizationId: string,\n relationship: {\n from: { id: string; type: string };\n to: { id: string; type: string };\n type: string;\n metadata: Record<string, unknown>;\n },\n metadata?: {\n userId?: string;\n correlationId?: string;\n },\n productSource?: string\n): GraphEvent {\n return {\n eventId: `evt_${uuidv4()}`,\n eventType,\n organizationId,\n productSource: productSource || process.env['PRODUCT_SOURCE'] || 'default',\n timestamp: new Date().toISOString(),\n entity: {\n id: `${relationship.from.id}_${relationship.to.id}`,\n type: relationship.type,\n data: {},\n },\n relationship,\n metadata: {\n userId: metadata?.userId,\n correlationId: metadata?.correlationId || `req_${uuidv4()}`,\n },\n };\n}\n\n/**\n * Extract minimal fields for syncing to graph (uses registry)\n *\n * @param modelName - Prisma model name (e.g., 'Calendar', 'Group')\n * @param entity - Full entity data from Prisma\n * @returns Minimal entity data for graph sync\n */\nexport function extractMinimalFields(modelName: string, entity: Record<string, unknown>): Record<string, unknown> {\n // Get entity config from registry\n const config = GraphRegistry.getEntityConfig(modelName);\n\n if (!config) {\n // Fallback: if entity not registered, just use id and workspaceID\n logger.warn(`[GraphHelpers] No graph config found for entity type: ${modelName}, using fallback`);\n const minimal: Record<string, unknown> = {};\n\n if (entity['id']) minimal['id'] = entity['id'];\n if (entity['workspaceID']) minimal['workspaceID'] = entity['workspaceID'];\n if (entity['workspaceId']) minimal['workspaceId'] = entity['workspaceId'];\n\n return minimal;\n }\n\n // Extract configured fields\n const minimal: Record<string, unknown> = {};\n\n for (const field of config.fields) {\n if (entity[field] !== undefined) {\n minimal[field] = entity[field];\n }\n }\n\n return minimal;\n}\n\n/**\n * Parse relationship from join table models (uses registry)\n *\n * @param modelName - Relationship model name (e.g., 'EventAttendee', 'GroupMembership')\n * @param relationship - Full relationship data from Prisma\n * @returns Parsed relationship with from/to/type/metadata\n */\nexport function parseRelationship(\n modelName: string,\n relationship: Record<string, unknown>\n): {\n from: { id: string; type: string };\n to: { id: string; type: string };\n relationshipType: string;\n metadata: Record<string, unknown>;\n} {\n // Get relationship config from registry\n const config = GraphRegistry.getRelationshipConfig(modelName);\n\n if (!config) {\n logger.warn(`[GraphHelpers] No graph config found for relationship type: ${modelName}, using fallback`);\n return {\n from: { id: 'unknown', type: 'Unknown' },\n to: { id: 'unknown', type: 'Unknown' },\n relationshipType: 'relates_to',\n metadata: {},\n };\n }\n\n // Extract relationship data using config\n return {\n from: {\n id: String(relationship[config.fromField] || 'unknown'),\n type: config.from,\n },\n to: {\n id: String(relationship[config.to] || 'unknown'),\n type: config.to,\n },\n relationshipType: config.label || 'relates_to',\n metadata: config.extractMetadata?.(relationship) ?? {},\n };\n}\n\n/**\n * Get the graph vertex label for an entity type (uses registry)\n *\n * @param entityType - Entity type name\n * @returns Collection name\n */\nexport function getCollectionForEntity(entityType: string): string {\n const config = GraphRegistry.getEntityConfig(entityType);\n\n if (!config) {\n // Default to product_entities if not registered\n return 'entity';\n }\n\n return config.collection || 'entity';\n}\n\n/**\n * Extract title from entity (uses registry or fallback)\n *\n * @param entityType - Entity type name\n * @param entity - Entity data\n * @returns Title string\n */\nexport function extractEntityTitle(entityType: string, entity: Record<string, unknown>): string {\n const config = GraphRegistry.getEntityConfig(entityType);\n\n // Use custom title extractor if provided\n if (config?.extractTitle) {\n return config.extractTitle(entity);\n }\n\n // Fallback: try common title fields\n return String(entity['name'] || entity['title'] || entity['email'] || entity['id'] || 'Untitled');\n}\n\n/**\n * Check if an entity type should be synced to the graph\n *\n * @param entityType - Entity type name\n * @returns True if entity should be synced\n */\nexport function shouldSyncEntity(entityType: string): boolean {\n const config = GraphRegistry.getEntityConfig(entityType);\n\n if (!config) {\n // If not registered, don't sync\n return false;\n }\n\n // Check if explicitly disabled\n return config.enabled !== false;\n}\n\n/**\n * Check if a relationship type should be synced to the graph\n *\n * @param relationshipType - Relationship type name\n * @returns True if relationship should be synced\n */\nexport function shouldSyncRelationship(relationshipType: string): boolean {\n const config = GraphRegistry.getRelationshipConfig(relationshipType);\n\n if (!config) {\n // If not registered, don't sync\n return false;\n }\n\n // Check if explicitly disabled\n return config.enabled !== false;\n}\n","/**\n * Prisma 7 Client Factory with PostgreSQL Adapter\n *\n * This module provides a generic factory for creating Prisma clients\n * configured with the PostgreSQL driver adapter as required by Prisma 7.\n *\n * Breaking Changes in Prisma 7:\n * - Must use database driver adapter (@prisma/adapter-pg for PostgreSQL)\n * - Datasource URL moved from schema.prisma to prisma.config.ts\n * - DMMF no longer available at runtime (use generator for build-time access)\n *\n * @module prisma/client\n */\n\nimport { PrismaPg } from '@prisma/adapter-pg';\nimport { Pool, type PoolClient, type PoolConfig } from 'pg';\nimport { logger } from '../logger/index.js';\nimport type { PrismaClientConfig, ConnectionState } from './types.js';\n\n/**\n * Prisma event object types\n */\nexport interface PrismaQueryEvent {\n query: string;\n params: string;\n duration: number;\n target?: string;\n}\n\nexport interface PrismaLogEvent {\n message: string;\n target?: string;\n}\n\nexport type PrismaEvent = PrismaQueryEvent | PrismaLogEvent;\n\n/**\n * Transaction options for Prisma $transaction method\n */\nexport interface PrismaTransactionOptions {\n maxWait?: number;\n timeout?: number;\n isolationLevel?: string;\n}\n\n/**\n * Base Prisma client interface with required methods\n *\n * This interface defines the MINIMUM contract required for server bootstrapping.\n * It only includes methods actually used by the SDK's server module.\n *\n * Note: Service-specific model properties (e.g., universalTag, user, workspace, etc.)\n * and full method signatures should be accessed by casting to the service's\n * generated Prisma client type.\n *\n * @example\n * ```typescript\n * // In your service's context type:\n * import type { PrismaClient } from './generated/prisma/client.js';\n * import type { GraphQLContext } from '@burdenoff/be-sdk';\n *\n * export interface Context extends GraphQLContext {\n * db: PrismaClient;\n * }\n * ```\n */\nexport interface PrismaClientBase {\n /** Connect to the database */\n $connect(): Promise<void>;\n /** Disconnect from the database */\n $disconnect(): Promise<void>;\n /** Register event handlers for logging */\n $on(event: string, callback: (e: PrismaEvent) => void): void;\n /** Execute a raw SQL query */\n $queryRaw<T = unknown>(query: TemplateStringsArray, ...values: unknown[]): Promise<T>;\n}\n\n/**\n * Database client return type for getDb()\n *\n * Returns the service's PrismaClient type (T) with a `client` property\n * for backwards compatibility. All model access and typing comes from\n * the service's own generated Prisma types.\n *\n * @example\n * ```typescript\n * // In your service - import YOUR generated PrismaClient\n * import { PrismaClient } from './generated/prisma/client.js';\n * import { getDb } from '@burdenoff/be-sdk/prisma';\n *\n * // Pass your PrismaClient type for full type safety\n * const db = getDb<PrismaClient>();\n * const tags = await db.client.universalTag.findMany(); // Fully typed!\n * ```\n */\nexport type DatabaseReturnType<T extends PrismaClientBase = PrismaClientBase> = T & {\n /**\n * Client property for explicit model access.\n * This is the same as the db object itself, provided for API consistency.\n */\n client: T;\n};\n\n/**\n * Create a PostgreSQL connection pool.\n *\n * The base pool sizing (max / idle / connection timeout) is unchanged. The\n * optional tuning fields (`applicationName`, `statementTimeoutMillis`,\n * `idleInTransactionTimeoutMillis`, `lockTimeoutMillis`) are only attached to\n * the pool config when explicitly provided — when they are all unset, the\n * resulting pool is byte-for-byte identical to the previous behavior. This keeps\n * the change safe to roll out fleet-wide: `application_name` is pure diagnostic\n * metadata, and every DB-enforced timeout defaults to OFF (pg default).\n */\nexport function createConnectionPool(config: PrismaClientConfig): Pool {\n const idleTimeoutMillis = config.idleTimeoutMillis ?? 30000;\n const poolConfig: PoolConfig = {\n connectionString: config.databaseUrl,\n max: config.maxConnections ?? 20,\n idleTimeoutMillis,\n connectionTimeoutMillis: config.connectionTimeoutMillis ?? 10000,\n // Keep pooled TCP sockets alive so Azure's load balancer / Postgres does not\n // silently drop an idle connection out from under the pool. Without this the\n // first query after a quiet window re-establishes a socket — the slow cold\n // TLS handshake that intermittently exceeds connectionTimeoutMillis and 500s\n // the request (context-switcher bootstrap after ~30s idle). Pure transport\n // hygiene; no effect on query behavior.\n keepAlive: true,\n keepAliveInitialDelayMillis: 10000,\n };\n\n // Diagnostic metadata only — no effect on query behavior.\n if (config.applicationName) {\n poolConfig.application_name = config.applicationName;\n }\n\n // Client-side query timeout — the pooler-safe query bound. node-postgres\n // applies this as a per-query timer inside the driver (NOT a startup\n // parameter and NOT a server GUC), so it works transparently through Azure's\n // built-in PgBouncer transaction pooling (the :6432 runtime endpoint) where\n // the server-side `statement_timeout` startup parameter cannot be used. When\n // it fires, pg destroys the connection and the pool replaces it on the next\n // acquire, so a runaway/hung query can no longer permanently pin a pool slot.\n // Only applied when explicitly opted in, so the default is unchanged.\n if (config.queryTimeoutMillis != null && config.queryTimeoutMillis > 0) {\n poolConfig.query_timeout = config.queryTimeoutMillis;\n }\n\n // DB-enforced safety timeouts — only applied when explicitly opted in, so the\n // default (unset) preserves the current no-server-timeout behavior exactly.\n if (config.statementTimeoutMillis != null && config.statementTimeoutMillis > 0) {\n poolConfig.statement_timeout = config.statementTimeoutMillis;\n }\n if (config.idleInTransactionTimeoutMillis != null && config.idleInTransactionTimeoutMillis > 0) {\n poolConfig.idle_in_transaction_session_timeout = config.idleInTransactionTimeoutMillis;\n }\n if (config.lockTimeoutMillis != null && config.lockTimeoutMillis > 0) {\n poolConfig.lock_timeout = config.lockTimeoutMillis;\n }\n\n const pool = new Pool(poolConfig);\n\n // node-postgres emits 'error' on the Pool when an IDLE pooled client is\n // dropped by the server or network (e.g. a Postgres restart, a PgBouncer\n // server_lifetime recycle, an Azure LB reset). With no listener that is an\n // unhandled 'error' event — which CRASHES the process. The pool discards the\n // dead client and replaces it on the next acquire, so this is log-worthy but\n // never fatal.\n pool.on('error', (error: Error) => {\n logger.warn(\n '[pg-pool] Idle pooled connection errored (dropped by server/network); it will be replaced on next acquire',\n { error: error.message }\n );\n });\n\n installAcquireRetry(pool, config.acquireRetries ?? 2, config.acquireRetryDelayMillis ?? 250);\n startPoolWarmer(pool, config, idleTimeoutMillis);\n return pool;\n}\n\n/**\n * True for errors that occur while ESTABLISHING a connection and are worth one\n * more attempt: the cold-connect stall past `connectionTimeoutMillis` observed\n * on Azure ACA, a checkout-queue timeout, a reset/refused during handshake, or\n * transient DNS. Anything else (auth failure, TLS misconfig, \"pool after end\")\n * fails immediately.\n */\nexport function isTransientAcquireError(error: unknown): boolean {\n if (!(error instanceof Error)) return false;\n const message = error.message.toLowerCase();\n return (\n message.includes('connection terminated due to connection timeout') ||\n message.includes('timeout exceeded when trying to connect') ||\n message.includes('connection terminated unexpectedly') ||\n message.includes('econnreset') ||\n message.includes('econnrefused') ||\n message.includes('eai_again')\n );\n}\n\ntype PoolConnectCallback = (\n err: Error | undefined,\n client: PoolClient | undefined,\n done: (release?: Error | boolean) => void\n) => void;\n\n/**\n * Retry transient connect-phase failures when acquiring a pooled connection.\n *\n * The acquire phase (pool checkout / physical connect) happens BEFORE any query\n * is dispatched, so retrying it is always safe — it can never double-execute a\n * statement. This is the piece the keep-warm ping cannot cover: the warmer keeps\n * one connection live, but a concurrent burst after an idle window still\n * cold-connects clients 2..N, and any of those stalling past\n * `connectionTimeoutMillis` used to surface directly as a resolver 500\n * (\"Connection terminated due to connection timeout\").\n *\n * Patches `pool.connect` in place (both the promise and callback forms —\n * `pool.query` funnels through the callback form internally, and the Prisma\n * pg adapter uses both), so every consumer of the pool gets the retry.\n */\nexport function installAcquireRetry(pool: Pool, retries: number, baseDelayMillis: number): void {\n if (retries <= 0) return;\n const originalConnect = pool.connect.bind(pool) as () => Promise<PoolClient>;\n\n const acquireWithRetry = async (): Promise<PoolClient> => {\n let attempt = 0;\n for (;;) {\n try {\n return await originalConnect();\n } catch (error) {\n if (attempt >= retries || !isTransientAcquireError(error)) {\n throw error;\n }\n attempt += 1;\n const delayMillis = baseDelayMillis * 2 ** (attempt - 1);\n logger.warn(\n `[pg-pool] Transient connection-acquire failure (attempt ${String(attempt)}/${String(retries)}); ` +\n `retrying in ${String(delayMillis)}ms`,\n { error: error instanceof Error ? error.message : String(error) }\n );\n await new Promise((resolve) => setTimeout(resolve, delayMillis));\n }\n }\n };\n\n const patchedConnect = (callback?: PoolConnectCallback): Promise<PoolClient> | void => {\n if (typeof callback === 'function') {\n acquireWithRetry().then(\n (client) => {\n callback(undefined, client, client.release.bind(client));\n },\n (error: unknown) => {\n callback(error instanceof Error ? error : new Error(String(error)), undefined, () => undefined);\n }\n );\n return;\n }\n return acquireWithRetry();\n };\n\n pool.connect = patchedConnect as typeof pool.connect;\n}\n\n/**\n * Keep at least one pooled connection live during quiet periods.\n *\n * `pg.Pool` closes every idle client after `idleTimeoutMillis`, so a service\n * that goes quiet for that long drains to zero connections and the next request\n * pays a full cold connect. On Azure ACA that cold TLS handshake occasionally\n * stalls past `connectionTimeoutMillis`, 500ing the request. A lightweight\n * `SELECT 1` on an interval shorter than the idle timeout keeps one connection\n * checked-out-and-released just often enough that its idle timer never expires,\n * so post-idle requests reuse a warm socket. The timer is `unref`'d (never keeps\n * the process alive) and cleared when the pool ends.\n */\nfunction startPoolWarmer(pool: Pool, config: PrismaClientConfig, idleTimeoutMillis: number): void {\n if (config.keepWarm === false) return;\n const intervalMs = config.warmupIntervalMillis ?? 20000;\n // A warmer at/above the idle timeout can't keep anything warm — skip it.\n if (intervalMs <= 0 || (idleTimeoutMillis > 0 && intervalMs >= idleTimeoutMillis)) return;\n\n // Surface persistent warm-up failures (throttled) instead of swallowing them:\n // if the warmer itself cannot reach Postgres the pool is silently unable to\n // establish connections, and previously operators only found out from\n // user-facing 500s. One warn per minute is enough signal without noise; a\n // recovery logs once so the window is visible in retrospect.\n const WARM_FAILURE_LOG_INTERVAL_MS = 60000;\n let consecutiveWarmFailures = 0;\n let lastWarmFailureLogAt = 0;\n const timer = setInterval(() => {\n pool.query('SELECT 1').then(\n () => {\n if (consecutiveWarmFailures > 0) {\n logger.info('[pg-pool] Warm-up query recovered', { failedAttempts: consecutiveWarmFailures });\n consecutiveWarmFailures = 0;\n }\n },\n (error: unknown) => {\n consecutiveWarmFailures += 1;\n const now = Date.now();\n if (now - lastWarmFailureLogAt >= WARM_FAILURE_LOG_INTERVAL_MS) {\n lastWarmFailureLogAt = now;\n logger.warn('[pg-pool] Warm-up query failing — the pool cannot establish connections to Postgres right now', {\n consecutiveWarmFailures,\n error: error instanceof Error ? error.message : String(error),\n });\n }\n }\n );\n }, intervalMs);\n if (typeof timer.unref === 'function') timer.unref();\n\n // Stop warming once the pool is torn down (graceful shutdown / disconnect).\n const originalEnd = pool.end.bind(pool);\n pool.end = ((...args: Parameters<typeof originalEnd>) => {\n clearInterval(timer);\n return originalEnd(...args);\n }) as typeof pool.end;\n}\n\n/**\n * Ensure a per-service Postgres `application_name` is set process-wide.\n *\n * node-postgres reads the libpq `PGAPPNAME` environment variable as the\n * `application_name` fallback for every Client/Pool it creates. Setting it here\n * guarantees per-service attribution in pg_stat_activity / pg_stat_statements for\n * ALL pools a service opens — including pools a service constructs itself (e.g.\n * via `createPrismaGraphIntegration`'s `createPrismaClient` closure) that bypass\n * `createConnectionPool`.\n *\n * Behavior-preserving: this is pure diagnostic metadata, it is only applied when\n * `PGAPPNAME` is not already set (so an explicit operator/env value wins), and an\n * explicit `application_name` in a pool config still takes precedence over the\n * env fallback.\n */\nexport function ensureServiceApplicationName(productName: string | undefined): void {\n if (productName && !process.env['PGAPPNAME']) {\n process.env['PGAPPNAME'] = `svc=${productName}`;\n }\n}\n\n/**\n * Create a Prisma PostgreSQL adapter\n */\nexport function createPrismaAdapter(pool: Pool): PrismaPg {\n return new PrismaPg(pool);\n}\n\n/**\n * Configure Prisma client logging\n */\nexport function configurePrismaLogging<T extends PrismaClientBase>(client: T, config: PrismaClientConfig): T {\n const isDevelopment = process.env['NODE_ENV'] === 'development';\n const slowQueryThreshold = config.slowQueryThreshold ?? (isDevelopment ? 100 : 500);\n\n // Query logging\n if (config.enableQueryLogging ?? isDevelopment) {\n client.$on('query', (e: PrismaEvent) => {\n if ('query' in e && 'duration' in e) {\n if (e.duration > slowQueryThreshold) {\n logger.warn('[Prisma] Slow query detected', {\n query: e.query.substring(0, 200) + (e.query.length > 200 ? '...' : ''),\n params: e.params,\n duration: `${e.duration}ms`,\n });\n } else {\n logger.debug('[Prisma] Query', {\n query: e.query.substring(0, 100) + (e.query.length > 100 ? '...' : ''),\n duration: `${e.duration}ms`,\n });\n }\n }\n });\n }\n\n // Error logging\n client.$on('error', (e: PrismaEvent) => {\n if ('message' in e) {\n logger.error('[Prisma] Database error', {\n message: e.message,\n target: e.target,\n });\n }\n });\n\n // Warning logging\n client.$on('warn', (e: PrismaEvent) => {\n if ('message' in e) {\n logger.warn('[Prisma] Database warning', {\n message: e.message,\n target: e.target,\n });\n }\n });\n\n return client;\n}\n\n/**\n * Prisma Client Wrapper with connection management\n */\nexport class PrismaClientWrapper<T extends PrismaClientBase> {\n private client: T;\n private pool: Pool;\n private connectionState: ConnectionState = {\n isConnected: false,\n attempts: 0,\n };\n private isDisconnecting = false;\n\n constructor(client: T, pool: Pool, config: PrismaClientConfig) {\n this.client = client;\n this.pool = pool;\n\n // Configure logging\n configurePrismaLogging(this.client, config);\n }\n\n /**\n * Get the Prisma client instance\n */\n public getClient(): T {\n return this.client;\n }\n\n /**\n * Get the connection pool\n */\n public getPool(): Pool {\n return this.pool;\n }\n\n /**\n * Get connection state\n */\n public getConnectionState(): ConnectionState {\n return { ...this.connectionState };\n }\n\n /**\n * Connect to database with retry logic\n */\n public async connect(retries = 5, delay = 1000): Promise<void> {\n if (this.connectionState.isConnected) {\n logger.info('[Prisma] Already connected to database');\n return;\n }\n\n for (let attempt = 1; attempt <= retries; attempt++) {\n this.connectionState.attempts = attempt;\n\n try {\n await this.client.$connect();\n this.connectionState.isConnected = true;\n this.connectionState.lastConnectedAt = new Date();\n this.connectionState.lastError = undefined;\n\n logger.info('[Prisma] Successfully connected to database');\n return;\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error);\n this.connectionState.lastError = errorMessage;\n\n logger.error(`[Prisma] Connection attempt ${attempt}/${retries} failed`, {\n error: errorMessage,\n });\n\n if (attempt === retries) {\n logger.error('[Prisma] Max connection retries reached');\n throw error;\n }\n\n // Exponential backoff\n const waitTime = delay * Math.pow(2, attempt - 1);\n logger.info(`[Prisma] Retrying in ${waitTime}ms...`);\n await new Promise((resolve) => setTimeout(resolve, waitTime));\n }\n }\n }\n\n /**\n * Gracefully disconnect from database\n */\n public async disconnect(): Promise<void> {\n // Guard against multiple disconnect calls\n if (this.isDisconnecting) {\n logger.debug('[Prisma] Disconnect already in progress, skipping');\n return;\n }\n\n if (!this.connectionState.isConnected) {\n logger.info('[Prisma] Database already disconnected');\n return;\n }\n\n // Mark as disconnecting to prevent concurrent disconnect calls\n this.isDisconnecting = true;\n\n try {\n await this.client.$disconnect();\n await this.pool.end();\n this.connectionState.isConnected = false;\n\n logger.info('[Prisma] Successfully disconnected from database');\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error);\n\n // Ignore \"Called end on pool more than once\" errors\n if (errorMessage.includes('Called end on pool more than once')) {\n logger.debug('[Prisma] Pool already ended, ignoring duplicate end call');\n this.connectionState.isConnected = false;\n return;\n }\n\n logger.error('[Prisma] Error disconnecting from database', {\n error: errorMessage,\n });\n throw error;\n } finally {\n this.isDisconnecting = false;\n }\n }\n\n /**\n * Register graceful shutdown handlers\n */\n public registerShutdownHandlers(): void {\n const shutdownHandler = async (signal: string): Promise<void> => {\n logger.info(`[Prisma] Received ${signal}, starting graceful shutdown...`);\n\n try {\n await this.disconnect();\n process.exit(0);\n } catch (error) {\n logger.error('[Prisma] Error during graceful shutdown', {\n error: error instanceof Error ? error.message : String(error),\n });\n process.exit(1);\n }\n };\n\n // Register shutdown handlers\n process.on('SIGINT', () => void shutdownHandler('SIGINT'));\n process.on('SIGTERM', () => void shutdownHandler('SIGTERM'));\n process.on('beforeExit', () => void this.disconnect());\n }\n}\n\n/**\n * Create a configured Prisma client wrapper\n *\n * @example\n * ```typescript\n * import { PrismaClient } from './generated/prisma/client.js';\n * import { createPrismaClient } from '@burdenoff/be-sdk';\n *\n * const wrapper = createPrismaClient(PrismaClient, {\n * databaseUrl: process.env.DATABASE_URL!,\n * });\n *\n * await wrapper.connect();\n * const prisma = wrapper.getClient();\n *\n * // Use prisma client\n * const users = await prisma.user.findMany();\n * ```\n */\n/**\n * Prisma log level options\n */\nexport type PrismaLogLevel = 'info' | 'query' | 'warn' | 'error';\n\n/**\n * Prisma log definition\n */\nexport interface PrismaLogDefinition {\n level: PrismaLogLevel;\n emit: 'stdout' | 'event';\n}\n\n/**\n * Prisma client constructor options\n */\nexport interface PrismaClientConstructorOptions {\n adapter: PrismaPg;\n log?: (PrismaLogLevel | PrismaLogDefinition)[];\n}\n\nexport function createPrismaClient<T extends PrismaClientBase>(\n PrismaClientConstructor: new (options: PrismaClientConstructorOptions) => T,\n config: PrismaClientConfig\n): PrismaClientWrapper<T> {\n const isDevelopment = process.env['NODE_ENV'] === 'development';\n\n // Create connection pool\n const pool = createConnectionPool(config);\n\n // Create adapter\n const adapter = createPrismaAdapter(pool);\n\n // Determine log levels\n const logLevels: PrismaLogDefinition[] =\n (config.logLevels as PrismaLogDefinition[] | undefined) ??\n (isDevelopment\n ? [\n { emit: 'event', level: 'query' },\n { emit: 'event', level: 'info' },\n { emit: 'event', level: 'warn' },\n { emit: 'event', level: 'error' },\n ]\n : [\n { emit: 'event', level: 'warn' },\n { emit: 'event', level: 'error' },\n ]);\n\n // Create Prisma client\n const client = new PrismaClientConstructor({\n adapter,\n log: logLevels,\n });\n\n // Create and return wrapper\n return new PrismaClientWrapper(client, pool, config);\n}\n","/**\n * Prisma Middleware for Graph Event Emission\n *\n * Automatically emits events to the graph event queue when entities are\n * created, updated, or deleted in PostgreSQL.\n *\n * This is a product-agnostic Prisma extension that can be used by any Burdenoff product.\n *\n * @module prisma-graph-extension\n * @category Graph\n */\nimport { logger } from '../../logger/index.js';\nimport { extractMinimalFields } from '../utils/helpers.js';\nimport { GraphRegistry } from '../utils/registry.js';\n\n/**\n * Event types for entity operations\n */\nexport type EntityEventType =\n | 'entity.created'\n | 'entity.updated'\n | 'entity.deleted'\n | 'relationship.created'\n | 'relationship.deleted';\n\n/**\n * RBAC metadata for entity events (resolved from graph config)\n */\nexport interface EntityEventRbacMetadata {\n resourceTypeName: string;\n name?: string;\n identifier?: string;\n parentResourceIdentifier?: string;\n createResource?: boolean;\n}\n\n/**\n * Event emitter interface - products must provide their own implementation\n */\nexport interface GraphEventEmitter {\n publishEntityEvent(\n eventType: EntityEventType,\n entity: {\n id: string;\n type: string;\n data: Record<string, unknown>;\n },\n context: {\n productName: string;\n organizationId: string;\n actorId?: string;\n workspaceId?: string;\n },\n rbac?: EntityEventRbacMetadata\n ): Promise<void>;\n}\n\n/**\n * Configuration for graph middleware\n */\nexport interface GraphMiddlewareConfig {\n /** Whether middleware is enabled */\n enabled: boolean;\n /** Product name for event metadata */\n productName: string;\n /** Event emitter implementation */\n eventEmitter: GraphEventEmitter;\n /** Entity types to monitor (if empty, monitors all registered types) */\n entityTypes?: string[];\n /** Operations to monitor */\n monitoredOperations?: Array<'create' | 'update' | 'delete' | 'deleteMany' | 'updateMany'>;\n}\n\n/**\n * Default configuration\n */\nconst defaultConfig: {\n enabled: boolean;\n monitoredOperations: Array<'create' | 'update' | 'delete' | 'deleteMany' | 'updateMany'>;\n} = {\n enabled: true,\n monitoredOperations: ['create', 'update', 'delete', 'deleteMany', 'updateMany'],\n};\n\n/**\n * Extract entity information from Prisma result\n */\nfunction extractEntityInfo(\n model: string,\n result: unknown\n): { id: string; type: string; data: Record<string, unknown> } | null {\n if (!result || typeof result !== 'object') {\n return null;\n }\n\n const record = result as Record<string, unknown>;\n const id = record['id'] as string;\n\n if (!id) {\n return null;\n }\n\n return {\n id,\n type: model,\n data: record,\n };\n}\n\n/**\n * Extract organization and user context from Prisma arguments\n */\nfunction extractContext(args: unknown): {\n organizationId?: string;\n actorId?: string;\n workspaceId?: string;\n} {\n if (!args || typeof args !== 'object') {\n return {};\n }\n\n const data =\n (args as { data?: Record<string, unknown>; where?: Record<string, unknown> })['data'] ||\n (args as { where?: Record<string, unknown> })['where'];\n\n if (!data || typeof data !== 'object') {\n return {};\n }\n\n return {\n organizationId: data['organizationId'] as string | undefined,\n actorId:\n (data['actorId'] as string | undefined) ||\n (data['createdBy'] as string | undefined) ||\n (data['updatedBy'] as string | undefined) ||\n (data['userId'] as string | undefined),\n workspaceId: (data['workspaceId'] as string | undefined) || (data['workspaceID'] as string | undefined),\n };\n}\n\n/**\n * Emit event for entity operation\n */\nfunction emitEntityEvent(\n eventType: EntityEventType,\n model: string,\n result: unknown,\n args: unknown,\n config: GraphMiddlewareConfig\n): void {\n const entityInfo = extractEntityInfo(model, result);\n if (!entityInfo) {\n return;\n }\n\n // Check if this entity type is registered in the graph registry\n if (!GraphRegistry.isEntityRegistered(model)) {\n return;\n }\n\n // Check if we should monitor this entity type\n if (config.entityTypes && config.entityTypes.length > 0 && !config.entityTypes.includes(model)) {\n return;\n }\n\n const context = extractContext(args);\n const minimalData = extractMinimalFields(model, entityInfo.data);\n\n // Use GraphRegistry to extract organization and workspace IDs from entity data\n // This allows entity-specific field mappings (e.g., tenantId → organizationId)\n const orgId = GraphRegistry.getOrganizationId(model, entityInfo.data) || context.organizationId || 'unknown';\n const workspaceId = GraphRegistry.getWorkspaceId(model, entityInfo.data) || context.workspaceId;\n const actorId = context.actorId || 'unknown';\n\n // Resolve RBAC metadata from GraphRegistry (if entity has rbac config)\n const rbacMetadata = GraphRegistry.resolveRbacMetadata(model, entityInfo.data);\n\n if (rbacMetadata) {\n logger.debug(`[GraphMiddleware] Including RBAC metadata for ${model}`, {\n resourceTypeName: rbacMetadata.resourceTypeName,\n hasName: !!rbacMetadata.name,\n });\n }\n\n // Emit event (non-blocking) — includes RBAC metadata when configured\n config.eventEmitter\n .publishEntityEvent(\n eventType,\n {\n id: entityInfo.id,\n type: entityInfo.type,\n data: minimalData,\n },\n {\n productName: config.productName,\n organizationId: orgId,\n actorId,\n workspaceId,\n },\n rbacMetadata\n )\n .catch((error: unknown) => {\n logger.error('[GraphMiddleware] Failed to emit event:', error);\n });\n\n // After emitting entity event, check for relationship events\n // Only for create/update operations\n if (eventType === 'entity.created' || eventType === 'entity.updated') {\n emitRelationshipEvents(model, entityInfo.data, orgId, config);\n }\n}\n\n/**\n * Emit relationship events based on foreign key values\n * This automatically creates edges in the graph when entities with foreign keys are created/updated\n */\nfunction emitRelationshipEvents(\n entityType: string,\n entityData: Record<string, unknown>,\n organizationId: string,\n config: GraphMiddlewareConfig\n): void {\n // Get all relationships where this entity type is the \"from\" side\n const relationships = GraphRegistry.getRelationshipsForEntity(entityType);\n\n if (relationships.length === 0) {\n return;\n }\n\n const fromId = entityData['id'] as string;\n if (!fromId) {\n return;\n }\n\n // For each relationship, check if the foreign key field has a value\n for (const [relationshipKey, relationshipConfig] of relationships) {\n const foreignKeyValue = entityData[relationshipConfig.fromField] as string | null | undefined;\n\n // Skip if foreign key is null/undefined (no relationship)\n if (!foreignKeyValue) {\n continue;\n }\n\n // Handle polymorphic relationships\n let targetType = relationshipConfig.to;\n if (relationshipConfig.to === '*') {\n if (relationshipConfig.polymorphicTypeField) {\n targetType = entityData[relationshipConfig.polymorphicTypeField] as string;\n if (!targetType) {\n logger.warn(`[GraphMiddleware] Polymorphic relationship ${relationshipKey} has no type field value`);\n continue;\n }\n } else {\n logger.debug(`[GraphMiddleware] Skipping polymorphic relationship without type field: ${relationshipKey}`);\n continue;\n }\n }\n\n // Extract metadata if configured\n const metadata = relationshipConfig.extractMetadata\n ? relationshipConfig.extractMetadata(entityData)\n : { description: relationshipConfig.description };\n\n // Emit relationship.created event\n config.eventEmitter\n .publishEntityEvent(\n 'relationship.created',\n {\n id: `${fromId}_${foreignKeyValue}`,\n type: relationshipConfig.label,\n data: {\n from: {\n id: fromId,\n type: entityType,\n },\n to: {\n id: foreignKeyValue,\n type: targetType,\n },\n relationType: relationshipConfig.label,\n metadata,\n },\n },\n {\n productName: config.productName,\n organizationId,\n }\n )\n .catch((error: unknown) => {\n logger.error(`[GraphMiddleware] Failed to emit relationship event for ${relationshipKey}:`, error);\n });\n\n logger.debug(\n `[GraphMiddleware] Emitted relationship.created: ${relationshipConfig.label} (${entityType}:${fromId} -> ${targetType}:${foreignKeyValue})`\n );\n }\n}\n\n/**\n * Add graph extension to Prisma client for automatic event emission\n *\n * This function uses Prisma Client Extensions (Prisma 6+) to intercept\n * database operations and emit events to the graph event queue.\n *\n * @param baseClient - Base Prisma client instance\n * @param config - Configuration for the middleware\n * @returns Extended Prisma client with graph event emission\n *\n * @example\n * ```typescript\n * import { PrismaClient } from '@prisma/client';\n * import { addGraphExtension } from '@burdenoff/be-sdk/graph';\n * import { eventQueue } from './event-queue';\n *\n * const baseClient = new PrismaClient();\n * const client = addGraphExtension(baseClient, {\n * enabled: true,\n * productName: 'workspaces',\n * eventEmitter: eventQueue,\n * entityTypes: ['Project', 'Group', 'Workspace'], // Optional: monitor specific types\n * });\n * ```\n */\nexport function addGraphExtension<T>(baseClient: T, config: GraphMiddlewareConfig): T {\n const fullConfig = { ...defaultConfig, ...config };\n\n if (!fullConfig.enabled) {\n logger.info('[GraphMiddleware] Extension disabled by configuration');\n return baseClient;\n }\n\n // Type assertion for Prisma client\n const prismaClient = baseClient as { $extends: (args: unknown) => T };\n\n return prismaClient.$extends({\n query: {\n $allModels: {\n async create({\n model,\n args,\n query,\n }: {\n model: string;\n args: unknown;\n query: (args: unknown) => Promise<unknown>;\n }) {\n const result = await query(args);\n\n if (fullConfig.monitoredOperations?.includes('create')) {\n emitEntityEvent('entity.created', model, result, args, fullConfig);\n }\n\n return result;\n },\n\n async update({\n model,\n args,\n query,\n }: {\n model: string;\n args: unknown;\n query: (args: unknown) => Promise<unknown>;\n }) {\n const result = await query(args);\n\n if (fullConfig.monitoredOperations?.includes('update')) {\n emitEntityEvent('entity.updated', model, result, args, fullConfig);\n }\n\n return result;\n },\n\n async delete({\n model,\n args,\n query,\n }: {\n model: string;\n args: unknown;\n query: (args: unknown) => Promise<unknown>;\n }) {\n const result = await query(args);\n\n if (fullConfig.monitoredOperations?.includes('delete')) {\n emitEntityEvent('entity.deleted', model, result, args, fullConfig);\n }\n\n return result;\n },\n\n async updateMany({\n model,\n args,\n query,\n }: {\n model: string;\n args: unknown;\n query: (args: unknown) => Promise<unknown>;\n }) {\n const result = await query(args);\n\n if (fullConfig.monitoredOperations?.includes('updateMany')) {\n logger.info(`[GraphMiddleware] updateMany for ${model} (bulk operation not tracked individually)`);\n }\n\n return result;\n },\n\n async deleteMany({\n model,\n args,\n query,\n }: {\n model: string;\n args: unknown;\n query: (args: unknown) => Promise<unknown>;\n }) {\n const result = await query(args);\n\n if (fullConfig.monitoredOperations?.includes('deleteMany')) {\n logger.info(`[GraphMiddleware] deleteMany for ${model} (bulk operation not tracked individually)`);\n }\n\n return result;\n },\n },\n },\n });\n}\n"]}
1
+ {"version":3,"sources":["../src/graph/utils/registry.ts","../src/graph/utils/helpers.ts","../src/prisma/client.ts","../src/graph/middleware/prisma-extension.ts"],"names":["GraphRegistry","entityMappings","Map","relationshipMappings","registeredModules","Set","resolveFields","entityType","config","Array","isArray","fields","logger","warn","registerModule","moduleName","entities","relationships","has","info","entityCount","entityConfig","Object","entries","enabled","resolvedFields","resolvedConfig","set","relationshipCount","relationshipType","relationshipConfig","add","getEntityConfig","get","getRelationshipConfig","getAllEntityTypes","from","keys","getAllRelationshipTypes","getRegisteredModules","isEntityRegistered","isRelationshipRegistered","getOrganizationId","data","getOrgId","undefined","getWorkspaceId","getRbacConfig","rbac","resolveRbacMetadata","entityData","rbacConfig","name","extractName","identifier","extractIdentifier","parentResourceIdentifier","parentResourceField","resourceTypeName","createResource","getStats","collections","edgeTypes","values","collection","label","modules","size","clear","getRelationshipsForEntity","result","key","push","printStatus","stats","join","uuidv4","crypto","randomUUID","createEntityEvent","eventType","organizationId","entity","metadata","productSource","eventId","process","env","timestamp","Date","toISOString","userId","correlationId","createRelationshipEvent","relationship","id","to","type","extractMinimalFields","modelName","minimal","field","parseRelationship","String","fromField","extractMetadata","getCollectionForEntity","extractEntityTitle","extractTitle","shouldSyncEntity","shouldSyncRelationship","createConnectionPool","idleTimeoutMillis","poolConfig","connectionString","databaseUrl","max","maxConnections","connectionTimeoutMillis","keepAlive","keepAliveInitialDelayMillis","applicationName","application_name","queryTimeoutMillis","query_timeout","statementTimeoutMillis","statement_timeout","idleInTransactionTimeoutMillis","idle_in_transaction_session_timeout","lockTimeoutMillis","lock_timeout","pool","Pool","on","error","message","installAcquireRetry","acquireRetries","acquireRetryDelayMillis","startPoolWarmer","isTransientAcquireError","Error","toLowerCase","includes","retries","baseDelayMillis","originalConnect","connect","bind","acquireWithRetry","attempt","delayMillis","Promise","resolve","setTimeout","patchedConnect","callback","then","client","release","keepWarm","intervalMs","warmupIntervalMillis","WARM_FAILURE_LOG_INTERVAL_MS","consecutiveWarmFailures","lastWarmFailureLogAt","timer","setInterval","query","failedAttempts","now","unref","originalEnd","end","args","clearInterval","ensureServiceApplicationName","productName","createPrismaAdapter","PrismaPg","configurePrismaLogging","isDevelopment","slowQueryThreshold","enableQueryLogging","$on","e","duration","substring","length","params","debug","target","PrismaClientWrapper","connectionState","isConnected","attempts","isDisconnecting","getClient","getPool","getConnectionState","delay","$connect","lastConnectedAt","lastError","errorMessage","waitTime","Math","pow","disconnect","$disconnect","registerShutdownHandlers","shutdownHandler","signal","exit","createPrismaClient","PrismaClientConstructor","adapter","logLevels","emit","level","log","defaultConfig","monitoredOperations","extractEntityInfo","model","record","extractContext","actorId","workspaceId","emitEntityEvent","entityInfo","entityTypes","context","minimalData","orgId","rbacMetadata","hasName","eventEmitter","publishEntityEvent","catch","emitRelationshipEvents","fromId","relationshipKey","foreignKeyValue","targetType","polymorphicTypeField","description","relationType","addGraphExtension","baseClient","fullConfig","prismaClient","$extends","$allModels","create","update","delete","updateMany","deleteMany"],"mappings":"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","file":"chunk-L5TDUAFN.js","sourcesContent":["/**\n * Graph Registry - Decentralized Graph Configuration System\n *\n * This registry allows each module to define its own graph configuration\n * without touching the central graph module. Modules register their entity\n * and relationship mappings, which are then used by the graph sync service.\n *\n * @module graph-registry\n * @category Graph\n */\nimport { logger } from '../../logger/index.js';\nimport type {\n EntityGraphConfig,\n ModuleGraphConfig,\n RelationshipGraphConfig,\n RegistryEntityRbacConfig,\n} from '../types.js';\n\n/**\n * Internal representation of entity config with resolved fields\n */\ninterface ResolvedEntityGraphConfig extends Omit<EntityGraphConfig, 'fields'> {\n fields: string[];\n getOrgId?: (data: Record<string, unknown>) => string | undefined;\n getWorkspaceId?: (data: Record<string, unknown>) => string | undefined;\n rbac?: RegistryEntityRbacConfig;\n}\n\n/**\n * Central registry for all graph configurations\n */\nexport class GraphRegistry {\n private static entityMappings: Map<string, ResolvedEntityGraphConfig> = new Map();\n private static relationshipMappings: Map<string, RelationshipGraphConfig> = new Map();\n private static registeredModules: Set<string> = new Set();\n\n /**\n * Resolve fields from entity configuration\n *\n * @param entityType - Name of the entity type\n * @param config - Entity configuration\n * @returns Resolved array of field names\n */\n private static resolveFields(entityType: string, config: EntityGraphConfig): string[] {\n if (Array.isArray(config.fields)) {\n return config.fields;\n }\n\n // Fallback: empty array if fields not configured\n logger.warn(`[GraphRegistry] No fields configuration for ${entityType}, using empty array`);\n return [];\n }\n\n /**\n * Register a module's graph configuration\n * @param config - Module graph configuration\n */\n static registerModule(config: ModuleGraphConfig): void {\n const { moduleName, entities, relationships } = config;\n\n if (this.registeredModules.has(moduleName)) {\n logger.warn(`[GraphRegistry] Module '${moduleName}' already registered, skipping`);\n return;\n }\n\n logger.info(`[GraphRegistry] Registering module: ${moduleName}`);\n\n // Register entities\n let entityCount = 0;\n for (const [entityType, entityConfig] of Object.entries(entities)) {\n if (entityConfig.enabled !== false) {\n // Resolve fields\n const resolvedFields = this.resolveFields(entityType, entityConfig);\n\n // Store resolved configuration\n const resolvedConfig: ResolvedEntityGraphConfig = {\n ...entityConfig,\n fields: resolvedFields,\n };\n\n this.entityMappings.set(entityType, resolvedConfig);\n entityCount++;\n }\n }\n\n // Register relationships\n let relationshipCount = 0;\n if (relationships) {\n for (const [relationshipType, relationshipConfig] of Object.entries(relationships)) {\n if (relationshipConfig.enabled !== false) {\n this.relationshipMappings.set(relationshipType, relationshipConfig);\n relationshipCount++;\n }\n }\n }\n\n this.registeredModules.add(moduleName);\n logger.info(\n `[GraphRegistry] ✅ Registered ${moduleName}: ${entityCount} entities, ${relationshipCount} relationships`\n );\n }\n\n /**\n * Get entity configuration by entity type\n * @param entityType - Entity type name (e.g., 'Calendar', 'Group')\n * @returns Entity configuration or undefined (with resolved fields)\n */\n static getEntityConfig(entityType: string): ResolvedEntityGraphConfig | undefined {\n return this.entityMappings.get(entityType);\n }\n\n /**\n * Get relationship configuration by relationship type\n * @param relationshipType - Relationship type name (e.g., 'EventAttendee', 'GroupMembership')\n * @returns Relationship configuration or undefined\n */\n static getRelationshipConfig(relationshipType: string): RelationshipGraphConfig | undefined {\n return this.relationshipMappings.get(relationshipType);\n }\n\n /**\n * Get all registered entity types\n * @returns Array of entity type names\n */\n static getAllEntityTypes(): string[] {\n return Array.from(this.entityMappings.keys());\n }\n\n /**\n * Get all registered relationship types\n * @returns Array of relationship type names\n */\n static getAllRelationshipTypes(): string[] {\n return Array.from(this.relationshipMappings.keys());\n }\n\n /**\n * Get all registered module names\n * @returns Array of module names\n */\n static getRegisteredModules(): string[] {\n return Array.from(this.registeredModules);\n }\n\n /**\n * Check if an entity type is registered\n * @param entityType - Entity type to check\n * @returns True if registered\n */\n static isEntityRegistered(entityType: string): boolean {\n return this.entityMappings.has(entityType);\n }\n\n /**\n * Check if a relationship type is registered\n * @param relationshipType - Relationship type to check\n * @returns True if registered\n */\n static isRelationshipRegistered(relationshipType: string): boolean {\n return this.relationshipMappings.has(relationshipType);\n }\n\n /**\n * Extract organization ID from entity data using configured mapping function\n * @param entityType - Entity type name\n * @param data - Entity data record\n * @returns Organization ID or undefined\n */\n static getOrganizationId(entityType: string, data: Record<string, unknown>): string | undefined {\n const config = this.entityMappings.get(entityType);\n if (!config || !config.getOrgId) {\n return undefined;\n }\n return config.getOrgId(data);\n }\n\n /**\n * Extract workspace ID from entity data using configured mapping function\n * @param entityType - Entity type name\n * @param data - Entity data record\n * @returns Workspace ID or undefined\n */\n static getWorkspaceId(entityType: string, data: Record<string, unknown>): string | undefined {\n const config = this.entityMappings.get(entityType);\n if (!config || !config.getWorkspaceId) {\n return undefined;\n }\n return config.getWorkspaceId(data);\n }\n\n /**\n * Get RBAC configuration for an entity type\n * Used by the Prisma graph extension to include RBAC metadata in entity events\n * @param entityType - Entity type name (e.g., 'Conversation', 'Agent')\n * @returns RBAC config or undefined if no RBAC is configured for this entity\n */\n static getRbacConfig(entityType: string): RegistryEntityRbacConfig | undefined {\n const config = this.entityMappings.get(entityType);\n return config?.rbac;\n }\n\n /**\n * Resolve RBAC event metadata from entity data\n * Converts the registry's function-based RBAC config into the flat metadata\n * structure expected by the RBAC consumer in the NATS event payload.\n * @param entityType - Entity type name\n * @param entityData - The entity data record\n * @returns RBAC metadata for the event or undefined\n */\n static resolveRbacMetadata(\n entityType: string,\n entityData: Record<string, unknown>\n ):\n | {\n resourceTypeName: string;\n name?: string;\n identifier?: string;\n parentResourceIdentifier?: string;\n createResource?: boolean;\n }\n | undefined {\n const rbacConfig = this.getRbacConfig(entityType);\n if (!rbacConfig) {\n return undefined;\n }\n\n const name = rbacConfig.extractName ? rbacConfig.extractName(entityData) : undefined;\n const identifier = rbacConfig.extractIdentifier ? rbacConfig.extractIdentifier(entityData) : undefined;\n const parentResourceIdentifier = rbacConfig.parentResourceField\n ? (entityData[rbacConfig.parentResourceField] as string | undefined)\n : undefined;\n\n return {\n resourceTypeName: rbacConfig.resourceTypeName,\n ...(name && { name }),\n ...(identifier && { identifier }),\n ...(parentResourceIdentifier && { parentResourceIdentifier }),\n ...(rbacConfig.createResource !== undefined && { createResource: rbacConfig.createResource }),\n };\n }\n\n /**\n * Get statistics about registered configurations\n * @returns Statistics object\n */\n static getStats(): {\n modules: number;\n entities: number;\n relationships: number;\n collections: Set<string>;\n edgeTypes: Set<string>;\n } {\n const collections = new Set<string>();\n const edgeTypes = new Set<string>();\n\n for (const config of this.entityMappings.values()) {\n collections.add(config.collection || 'product_entities');\n }\n\n for (const config of this.relationshipMappings.values()) {\n if (config.label) {\n edgeTypes.add(config.label);\n }\n }\n\n return {\n modules: this.registeredModules.size,\n entities: this.entityMappings.size,\n relationships: this.relationshipMappings.size,\n collections,\n edgeTypes,\n };\n }\n\n /**\n * Clear all registrations (for testing)\n */\n static clear(): void {\n this.entityMappings.clear();\n this.relationshipMappings.clear();\n this.registeredModules.clear();\n logger.info('[GraphRegistry] Cleared all registrations');\n }\n\n /**\n * Get all relationships where the given entity type is the \"from\" side\n * This is used for automatic relationship event emission when entities are created/updated\n * @param entityType - Entity type name (e.g., 'UniversalTag')\n * @returns Array of [relationshipKey, config] tuples\n */\n static getRelationshipsForEntity(entityType: string): Array<[string, RelationshipGraphConfig]> {\n const result: Array<[string, RelationshipGraphConfig]> = [];\n\n for (const [key, config] of this.relationshipMappings.entries()) {\n if (config.from === entityType) {\n result.push([key, config]);\n }\n }\n\n return result;\n }\n\n /**\n * Print registry status to console\n */\n static printStatus(): void {\n const stats = this.getStats();\n logger.info('');\n logger.info('📊 Graph Registry Status');\n logger.info('========================');\n logger.info(`Registered Modules: ${stats.modules}`);\n logger.info(`Total Entities: ${stats.entities}`);\n logger.info(`Total Relationships: ${stats.relationships}`);\n logger.info(`Vertex Collections: ${stats.collections.size}`);\n logger.info(`Edge Types: ${stats.edgeTypes.size}`);\n logger.info('');\n logger.info('Registered Modules:', this.getRegisteredModules().join(', '));\n logger.info('');\n }\n}\n","/**\n * Event Helpers - Registry-Based Graph Event Utilities\n *\n * This version uses the GraphRegistry to dynamically load entity and relationship\n * configurations from module-level graph.config.ts files.\n *\n * @module graph-helpers\n * @category Graph\n */\nimport { logger } from '../../logger/index.js';\nimport type { GraphEvent, GraphEventType } from '../types.js';\nimport { GraphRegistry } from './registry.js';\n\nconst uuidv4 = (): string => crypto.randomUUID();\n\n/**\n * Create an entity event for the graph\n */\nexport function createEntityEvent(\n eventType: GraphEventType,\n organizationId: string,\n entity: {\n id: string;\n type: string;\n data: Record<string, unknown>;\n },\n metadata?: {\n userId?: string;\n correlationId?: string;\n workspaceId?: string;\n projectId?: string;\n },\n productSource?: string\n): GraphEvent {\n return {\n eventId: `evt_${uuidv4()}`,\n eventType,\n organizationId,\n productSource: productSource || process.env['PRODUCT_SOURCE'] || 'default',\n timestamp: new Date().toISOString(),\n entity,\n metadata: {\n userId: metadata?.userId,\n correlationId: metadata?.correlationId || `req_${uuidv4()}`,\n },\n };\n}\n\n/**\n * Create a relationship event for the graph\n */\nexport function createRelationshipEvent(\n eventType: GraphEventType,\n organizationId: string,\n relationship: {\n from: { id: string; type: string };\n to: { id: string; type: string };\n type: string;\n metadata: Record<string, unknown>;\n },\n metadata?: {\n userId?: string;\n correlationId?: string;\n },\n productSource?: string\n): GraphEvent {\n return {\n eventId: `evt_${uuidv4()}`,\n eventType,\n organizationId,\n productSource: productSource || process.env['PRODUCT_SOURCE'] || 'default',\n timestamp: new Date().toISOString(),\n entity: {\n id: `${relationship.from.id}_${relationship.to.id}`,\n type: relationship.type,\n data: {},\n },\n relationship,\n metadata: {\n userId: metadata?.userId,\n correlationId: metadata?.correlationId || `req_${uuidv4()}`,\n },\n };\n}\n\n/**\n * Extract minimal fields for syncing to graph (uses registry)\n *\n * @param modelName - Prisma model name (e.g., 'Calendar', 'Group')\n * @param entity - Full entity data from Prisma\n * @returns Minimal entity data for graph sync\n */\nexport function extractMinimalFields(modelName: string, entity: Record<string, unknown>): Record<string, unknown> {\n // Get entity config from registry\n const config = GraphRegistry.getEntityConfig(modelName);\n\n if (!config) {\n // Fallback: if entity not registered, just use id and workspaceID\n logger.warn(`[GraphHelpers] No graph config found for entity type: ${modelName}, using fallback`);\n const minimal: Record<string, unknown> = {};\n\n if (entity['id']) minimal['id'] = entity['id'];\n if (entity['workspaceID']) minimal['workspaceID'] = entity['workspaceID'];\n if (entity['workspaceId']) minimal['workspaceId'] = entity['workspaceId'];\n\n return minimal;\n }\n\n // Extract configured fields\n const minimal: Record<string, unknown> = {};\n\n for (const field of config.fields) {\n if (entity[field] !== undefined) {\n minimal[field] = entity[field];\n }\n }\n\n return minimal;\n}\n\n/**\n * Parse relationship from join table models (uses registry)\n *\n * @param modelName - Relationship model name (e.g., 'EventAttendee', 'GroupMembership')\n * @param relationship - Full relationship data from Prisma\n * @returns Parsed relationship with from/to/type/metadata\n */\nexport function parseRelationship(\n modelName: string,\n relationship: Record<string, unknown>\n): {\n from: { id: string; type: string };\n to: { id: string; type: string };\n relationshipType: string;\n metadata: Record<string, unknown>;\n} {\n // Get relationship config from registry\n const config = GraphRegistry.getRelationshipConfig(modelName);\n\n if (!config) {\n logger.warn(`[GraphHelpers] No graph config found for relationship type: ${modelName}, using fallback`);\n return {\n from: { id: 'unknown', type: 'Unknown' },\n to: { id: 'unknown', type: 'Unknown' },\n relationshipType: 'relates_to',\n metadata: {},\n };\n }\n\n // Extract relationship data using config\n return {\n from: {\n id: String(relationship[config.fromField] || 'unknown'),\n type: config.from,\n },\n to: {\n id: String(relationship[config.to] || 'unknown'),\n type: config.to,\n },\n relationshipType: config.label || 'relates_to',\n metadata: config.extractMetadata?.(relationship) ?? {},\n };\n}\n\n/**\n * Get the graph vertex label for an entity type (uses registry)\n *\n * @param entityType - Entity type name\n * @returns Collection name\n */\nexport function getCollectionForEntity(entityType: string): string {\n const config = GraphRegistry.getEntityConfig(entityType);\n\n if (!config) {\n // Default to product_entities if not registered\n return 'entity';\n }\n\n return config.collection || 'entity';\n}\n\n/**\n * Extract title from entity (uses registry or fallback)\n *\n * @param entityType - Entity type name\n * @param entity - Entity data\n * @returns Title string\n */\nexport function extractEntityTitle(entityType: string, entity: Record<string, unknown>): string {\n const config = GraphRegistry.getEntityConfig(entityType);\n\n // Use custom title extractor if provided\n if (config?.extractTitle) {\n return config.extractTitle(entity);\n }\n\n // Fallback: try common title fields\n return String(entity['name'] || entity['title'] || entity['email'] || entity['id'] || 'Untitled');\n}\n\n/**\n * Check if an entity type should be synced to the graph\n *\n * @param entityType - Entity type name\n * @returns True if entity should be synced\n */\nexport function shouldSyncEntity(entityType: string): boolean {\n const config = GraphRegistry.getEntityConfig(entityType);\n\n if (!config) {\n // If not registered, don't sync\n return false;\n }\n\n // Check if explicitly disabled\n return config.enabled !== false;\n}\n\n/**\n * Check if a relationship type should be synced to the graph\n *\n * @param relationshipType - Relationship type name\n * @returns True if relationship should be synced\n */\nexport function shouldSyncRelationship(relationshipType: string): boolean {\n const config = GraphRegistry.getRelationshipConfig(relationshipType);\n\n if (!config) {\n // If not registered, don't sync\n return false;\n }\n\n // Check if explicitly disabled\n return config.enabled !== false;\n}\n","/**\n * Prisma 7 Client Factory with PostgreSQL Adapter\n *\n * This module provides a generic factory for creating Prisma clients\n * configured with the PostgreSQL driver adapter as required by Prisma 7.\n *\n * Breaking Changes in Prisma 7:\n * - Must use database driver adapter (@prisma/adapter-pg for PostgreSQL)\n * - Datasource URL moved from schema.prisma to prisma.config.ts\n * - DMMF no longer available at runtime (use generator for build-time access)\n *\n * @module prisma/client\n */\n\nimport { PrismaPg } from '@prisma/adapter-pg';\nimport { Pool, type PoolClient, type PoolConfig } from 'pg';\nimport { logger } from '../logger/index.js';\nimport type { PrismaClientConfig, ConnectionState } from './types.js';\n\n/**\n * Prisma event object types\n */\nexport interface PrismaQueryEvent {\n query: string;\n params: string;\n duration: number;\n target?: string;\n}\n\nexport interface PrismaLogEvent {\n message: string;\n target?: string;\n}\n\nexport type PrismaEvent = PrismaQueryEvent | PrismaLogEvent;\n\n/**\n * Transaction options for Prisma $transaction method\n */\nexport interface PrismaTransactionOptions {\n maxWait?: number;\n timeout?: number;\n isolationLevel?: string;\n}\n\n/**\n * Base Prisma client interface with required methods\n *\n * This interface defines the MINIMUM contract required for server bootstrapping.\n * It only includes methods actually used by the SDK's server module.\n *\n * Note: Service-specific model properties (e.g., universalTag, user, workspace, etc.)\n * and full method signatures should be accessed by casting to the service's\n * generated Prisma client type.\n *\n * @example\n * ```typescript\n * // In your service's context type:\n * import type { PrismaClient } from './generated/prisma/client.js';\n * import type { GraphQLContext } from '@burdenoff/be-sdk';\n *\n * export interface Context extends GraphQLContext {\n * db: PrismaClient;\n * }\n * ```\n */\nexport interface PrismaClientBase {\n /** Connect to the database */\n $connect(): Promise<void>;\n /** Disconnect from the database */\n $disconnect(): Promise<void>;\n /** Register event handlers for logging */\n $on(event: string, callback: (e: PrismaEvent) => void): void;\n /** Execute a raw SQL query */\n $queryRaw<T = unknown>(query: TemplateStringsArray, ...values: unknown[]): Promise<T>;\n}\n\n/**\n * Database client return type for getDb()\n *\n * Returns the service's PrismaClient type (T) with a `client` property\n * for backwards compatibility. All model access and typing comes from\n * the service's own generated Prisma types.\n *\n * @example\n * ```typescript\n * // In your service - import YOUR generated PrismaClient\n * import { PrismaClient } from './generated/prisma/client.js';\n * import { getDb } from '@burdenoff/be-sdk/prisma';\n *\n * // Pass your PrismaClient type for full type safety\n * const db = getDb<PrismaClient>();\n * const tags = await db.client.universalTag.findMany(); // Fully typed!\n * ```\n */\nexport type DatabaseReturnType<T extends PrismaClientBase = PrismaClientBase> = T & {\n /**\n * Client property for explicit model access.\n * This is the same as the db object itself, provided for API consistency.\n */\n client: T;\n};\n\n/**\n * Create a PostgreSQL connection pool.\n *\n * The base pool sizing (max / idle / connection timeout) is unchanged. The\n * optional tuning fields (`applicationName`, `statementTimeoutMillis`,\n * `idleInTransactionTimeoutMillis`, `lockTimeoutMillis`) are only attached to\n * the pool config when explicitly provided — when they are all unset, the\n * resulting pool is byte-for-byte identical to the previous behavior. This keeps\n * the change safe to roll out fleet-wide: `application_name` is pure diagnostic\n * metadata, and every DB-enforced timeout defaults to OFF (pg default).\n */\nexport function createConnectionPool(config: PrismaClientConfig): Pool {\n const idleTimeoutMillis = config.idleTimeoutMillis ?? 30000;\n const poolConfig: PoolConfig = {\n connectionString: config.databaseUrl,\n max: config.maxConnections ?? 20,\n idleTimeoutMillis,\n connectionTimeoutMillis: config.connectionTimeoutMillis ?? 10000,\n // Keep pooled TCP sockets alive so Azure's load balancer / Postgres does not\n // silently drop an idle connection out from under the pool. Without this the\n // first query after a quiet window re-establishes a socket — the slow cold\n // TLS handshake that intermittently exceeds connectionTimeoutMillis and 500s\n // the request (context-switcher bootstrap after ~30s idle). Pure transport\n // hygiene; no effect on query behavior.\n keepAlive: true,\n keepAliveInitialDelayMillis: 10000,\n };\n\n // Diagnostic metadata only — no effect on query behavior.\n if (config.applicationName) {\n poolConfig.application_name = config.applicationName;\n }\n\n // Client-side query timeout — the pooler-safe query bound. node-postgres\n // applies this as a per-query timer inside the driver (NOT a startup\n // parameter and NOT a server GUC), so it works transparently through Azure's\n // built-in PgBouncer transaction pooling (the :6432 runtime endpoint) where\n // the server-side `statement_timeout` startup parameter cannot be used. When\n // it fires, pg destroys the connection and the pool replaces it on the next\n // acquire, so a runaway/hung query can no longer permanently pin a pool slot.\n // Only applied when explicitly opted in, so the default is unchanged.\n if (config.queryTimeoutMillis != null && config.queryTimeoutMillis > 0) {\n poolConfig.query_timeout = config.queryTimeoutMillis;\n }\n\n // DB-enforced safety timeouts — only applied when explicitly opted in, so the\n // default (unset) preserves the current no-server-timeout behavior exactly.\n if (config.statementTimeoutMillis != null && config.statementTimeoutMillis > 0) {\n poolConfig.statement_timeout = config.statementTimeoutMillis;\n }\n if (config.idleInTransactionTimeoutMillis != null && config.idleInTransactionTimeoutMillis > 0) {\n poolConfig.idle_in_transaction_session_timeout = config.idleInTransactionTimeoutMillis;\n }\n if (config.lockTimeoutMillis != null && config.lockTimeoutMillis > 0) {\n poolConfig.lock_timeout = config.lockTimeoutMillis;\n }\n\n const pool = new Pool(poolConfig);\n\n // node-postgres emits 'error' on the Pool when an IDLE pooled client is\n // dropped by the server or network (e.g. a Postgres restart, a PgBouncer\n // server_lifetime recycle, an Azure LB reset). With no listener that is an\n // unhandled 'error' event — which CRASHES the process. The pool discards the\n // dead client and replaces it on the next acquire, so this is log-worthy but\n // never fatal.\n pool.on('error', (error: Error) => {\n logger.warn(\n '[pg-pool] Idle pooled connection errored (dropped by server/network); it will be replaced on next acquire',\n { error: error.message }\n );\n });\n\n installAcquireRetry(pool, config.acquireRetries ?? 2, config.acquireRetryDelayMillis ?? 250);\n startPoolWarmer(pool, config, idleTimeoutMillis);\n return pool;\n}\n\n/**\n * True for errors that occur while ESTABLISHING a connection and are worth one\n * more attempt: the cold-connect stall past `connectionTimeoutMillis` observed\n * on Azure ACA, a checkout-queue timeout, a reset/refused during handshake, or\n * transient DNS. Anything else (auth failure, TLS misconfig, \"pool after end\")\n * fails immediately.\n */\nexport function isTransientAcquireError(error: unknown): boolean {\n if (!(error instanceof Error)) return false;\n const message = error.message.toLowerCase();\n return (\n message.includes('connection terminated due to connection timeout') ||\n message.includes('timeout exceeded when trying to connect') ||\n message.includes('connection terminated unexpectedly') ||\n message.includes('econnreset') ||\n message.includes('econnrefused') ||\n message.includes('eai_again')\n );\n}\n\ntype PoolConnectCallback = (\n err: Error | undefined,\n client: PoolClient | undefined,\n done: (release?: Error | boolean) => void\n) => void;\n\n/**\n * Retry transient connect-phase failures when acquiring a pooled connection.\n *\n * The acquire phase (pool checkout / physical connect) happens BEFORE any query\n * is dispatched, so retrying it is always safe — it can never double-execute a\n * statement. This is the piece the keep-warm ping cannot cover: the warmer keeps\n * one connection live, but a concurrent burst after an idle window still\n * cold-connects clients 2..N, and any of those stalling past\n * `connectionTimeoutMillis` used to surface directly as a resolver 500\n * (\"Connection terminated due to connection timeout\").\n *\n * Patches `pool.connect` in place (both the promise and callback forms —\n * `pool.query` funnels through the callback form internally, and the Prisma\n * pg adapter uses both), so every consumer of the pool gets the retry.\n */\nexport function installAcquireRetry(pool: Pool, retries: number, baseDelayMillis: number): void {\n if (retries <= 0) return;\n const originalConnect = pool.connect.bind(pool) as () => Promise<PoolClient>;\n\n const acquireWithRetry = async (): Promise<PoolClient> => {\n let attempt = 0;\n for (;;) {\n try {\n return await originalConnect();\n } catch (error) {\n if (attempt >= retries || !isTransientAcquireError(error)) {\n throw error;\n }\n attempt += 1;\n const delayMillis = baseDelayMillis * 2 ** (attempt - 1);\n logger.warn(\n `[pg-pool] Transient connection-acquire failure (attempt ${String(attempt)}/${String(retries)}); ` +\n `retrying in ${String(delayMillis)}ms`,\n { error: error instanceof Error ? error.message : String(error) }\n );\n await new Promise((resolve) => setTimeout(resolve, delayMillis));\n }\n }\n };\n\n const patchedConnect = (callback?: PoolConnectCallback): Promise<PoolClient> | void => {\n if (typeof callback === 'function') {\n acquireWithRetry().then(\n (client) => {\n callback(undefined, client, client.release.bind(client));\n },\n (error: unknown) => {\n callback(error instanceof Error ? error : new Error(String(error)), undefined, () => undefined);\n }\n );\n return;\n }\n return acquireWithRetry();\n };\n\n pool.connect = patchedConnect as typeof pool.connect;\n}\n\n/**\n * Keep at least one pooled connection live during quiet periods.\n *\n * `pg.Pool` closes every idle client after `idleTimeoutMillis`, so a service\n * that goes quiet for that long drains to zero connections and the next request\n * pays a full cold connect. On Azure ACA that cold TLS handshake occasionally\n * stalls past `connectionTimeoutMillis`, 500ing the request. A lightweight\n * `SELECT 1` on an interval shorter than the idle timeout keeps one connection\n * checked-out-and-released just often enough that its idle timer never expires,\n * so post-idle requests reuse a warm socket. The timer is `unref`'d (never keeps\n * the process alive) and cleared when the pool ends.\n */\nfunction startPoolWarmer(pool: Pool, config: PrismaClientConfig, idleTimeoutMillis: number): void {\n if (config.keepWarm === false) return;\n const intervalMs = config.warmupIntervalMillis ?? 20000;\n // A warmer at/above the idle timeout can't keep anything warm — skip it.\n if (intervalMs <= 0 || (idleTimeoutMillis > 0 && intervalMs >= idleTimeoutMillis)) return;\n\n // Surface persistent warm-up failures (throttled) instead of swallowing them:\n // if the warmer itself cannot reach Postgres the pool is silently unable to\n // establish connections, and previously operators only found out from\n // user-facing 500s. One warn per minute is enough signal without noise; a\n // recovery logs once so the window is visible in retrospect.\n const WARM_FAILURE_LOG_INTERVAL_MS = 60000;\n let consecutiveWarmFailures = 0;\n let lastWarmFailureLogAt = 0;\n const timer = setInterval(() => {\n pool.query('SELECT 1').then(\n () => {\n if (consecutiveWarmFailures > 0) {\n logger.info('[pg-pool] Warm-up query recovered', { failedAttempts: consecutiveWarmFailures });\n consecutiveWarmFailures = 0;\n }\n },\n (error: unknown) => {\n consecutiveWarmFailures += 1;\n const now = Date.now();\n if (now - lastWarmFailureLogAt >= WARM_FAILURE_LOG_INTERVAL_MS) {\n lastWarmFailureLogAt = now;\n logger.warn('[pg-pool] Warm-up query failing — the pool cannot establish connections to Postgres right now', {\n consecutiveWarmFailures,\n error: error instanceof Error ? error.message : String(error),\n });\n }\n }\n );\n }, intervalMs);\n if (typeof timer.unref === 'function') timer.unref();\n\n // Stop warming once the pool is torn down (graceful shutdown / disconnect).\n const originalEnd = pool.end.bind(pool);\n pool.end = ((...args: Parameters<typeof originalEnd>) => {\n clearInterval(timer);\n return originalEnd(...args);\n }) as typeof pool.end;\n}\n\n/**\n * Ensure a per-service Postgres `application_name` is set process-wide.\n *\n * node-postgres reads the libpq `PGAPPNAME` environment variable as the\n * `application_name` fallback for every Client/Pool it creates. Setting it here\n * guarantees per-service attribution in pg_stat_activity / pg_stat_statements for\n * ALL pools a service opens — including pools a service constructs itself (e.g.\n * via `createPrismaGraphIntegration`'s `createPrismaClient` closure) that bypass\n * `createConnectionPool`.\n *\n * Behavior-preserving: this is pure diagnostic metadata, it is only applied when\n * `PGAPPNAME` is not already set (so an explicit operator/env value wins), and an\n * explicit `application_name` in a pool config still takes precedence over the\n * env fallback.\n */\nexport function ensureServiceApplicationName(productName: string | undefined): void {\n if (productName && !process.env['PGAPPNAME']) {\n process.env['PGAPPNAME'] = `svc=${productName}`;\n }\n}\n\n/**\n * Create a Prisma PostgreSQL adapter\n */\nexport function createPrismaAdapter(pool: Pool): PrismaPg {\n return new PrismaPg(pool);\n}\n\n/**\n * Configure Prisma client logging\n */\nexport function configurePrismaLogging<T extends PrismaClientBase>(client: T, config: PrismaClientConfig): T {\n const isDevelopment = process.env['NODE_ENV'] === 'development';\n const slowQueryThreshold = config.slowQueryThreshold ?? (isDevelopment ? 100 : 500);\n\n // Query logging\n if (config.enableQueryLogging ?? isDevelopment) {\n client.$on('query', (e: PrismaEvent) => {\n if ('query' in e && 'duration' in e) {\n if (e.duration > slowQueryThreshold) {\n logger.warn('[Prisma] Slow query detected', {\n query: e.query.substring(0, 200) + (e.query.length > 200 ? '...' : ''),\n params: e.params,\n duration: `${e.duration}ms`,\n });\n } else {\n logger.debug('[Prisma] Query', {\n query: e.query.substring(0, 100) + (e.query.length > 100 ? '...' : ''),\n duration: `${e.duration}ms`,\n });\n }\n }\n });\n }\n\n // Error logging\n client.$on('error', (e: PrismaEvent) => {\n if ('message' in e) {\n logger.error('[Prisma] Database error', {\n message: e.message,\n target: e.target,\n });\n }\n });\n\n // Warning logging\n client.$on('warn', (e: PrismaEvent) => {\n if ('message' in e) {\n logger.warn('[Prisma] Database warning', {\n message: e.message,\n target: e.target,\n });\n }\n });\n\n return client;\n}\n\n/**\n * Prisma Client Wrapper with connection management\n */\nexport class PrismaClientWrapper<T extends PrismaClientBase> {\n private client: T;\n private pool: Pool;\n private connectionState: ConnectionState = {\n isConnected: false,\n attempts: 0,\n };\n private isDisconnecting = false;\n\n constructor(client: T, pool: Pool, config: PrismaClientConfig) {\n this.client = client;\n this.pool = pool;\n\n // Configure logging\n configurePrismaLogging(this.client, config);\n }\n\n /**\n * Get the Prisma client instance\n */\n public getClient(): T {\n return this.client;\n }\n\n /**\n * Get the connection pool\n */\n public getPool(): Pool {\n return this.pool;\n }\n\n /**\n * Get connection state\n */\n public getConnectionState(): ConnectionState {\n return { ...this.connectionState };\n }\n\n /**\n * Connect to database with retry logic\n */\n public async connect(retries = 5, delay = 1000): Promise<void> {\n if (this.connectionState.isConnected) {\n logger.info('[Prisma] Already connected to database');\n return;\n }\n\n for (let attempt = 1; attempt <= retries; attempt++) {\n this.connectionState.attempts = attempt;\n\n try {\n await this.client.$connect();\n this.connectionState.isConnected = true;\n this.connectionState.lastConnectedAt = new Date();\n this.connectionState.lastError = undefined;\n\n logger.info('[Prisma] Successfully connected to database');\n return;\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error);\n this.connectionState.lastError = errorMessage;\n\n logger.error(`[Prisma] Connection attempt ${attempt}/${retries} failed`, {\n error: errorMessage,\n });\n\n if (attempt === retries) {\n logger.error('[Prisma] Max connection retries reached');\n throw error;\n }\n\n // Exponential backoff\n const waitTime = delay * Math.pow(2, attempt - 1);\n logger.info(`[Prisma] Retrying in ${waitTime}ms...`);\n await new Promise((resolve) => setTimeout(resolve, waitTime));\n }\n }\n }\n\n /**\n * Gracefully disconnect from database\n */\n public async disconnect(): Promise<void> {\n // Guard against multiple disconnect calls\n if (this.isDisconnecting) {\n logger.debug('[Prisma] Disconnect already in progress, skipping');\n return;\n }\n\n if (!this.connectionState.isConnected) {\n logger.info('[Prisma] Database already disconnected');\n return;\n }\n\n // Mark as disconnecting to prevent concurrent disconnect calls\n this.isDisconnecting = true;\n\n try {\n await this.client.$disconnect();\n await this.pool.end();\n this.connectionState.isConnected = false;\n\n logger.info('[Prisma] Successfully disconnected from database');\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error);\n\n // Ignore \"Called end on pool more than once\" errors\n if (errorMessage.includes('Called end on pool more than once')) {\n logger.debug('[Prisma] Pool already ended, ignoring duplicate end call');\n this.connectionState.isConnected = false;\n return;\n }\n\n logger.error('[Prisma] Error disconnecting from database', {\n error: errorMessage,\n });\n throw error;\n } finally {\n this.isDisconnecting = false;\n }\n }\n\n /**\n * Register graceful shutdown handlers\n */\n public registerShutdownHandlers(): void {\n const shutdownHandler = async (signal: string): Promise<void> => {\n logger.info(`[Prisma] Received ${signal}, starting graceful shutdown...`);\n\n try {\n await this.disconnect();\n process.exit(0);\n } catch (error) {\n logger.error('[Prisma] Error during graceful shutdown', {\n error: error instanceof Error ? error.message : String(error),\n });\n process.exit(1);\n }\n };\n\n // Register shutdown handlers\n process.on('SIGINT', () => void shutdownHandler('SIGINT'));\n process.on('SIGTERM', () => void shutdownHandler('SIGTERM'));\n process.on('beforeExit', () => void this.disconnect());\n }\n}\n\n/**\n * Create a configured Prisma client wrapper\n *\n * @example\n * ```typescript\n * import { PrismaClient } from './generated/prisma/client.js';\n * import { createPrismaClient } from '@burdenoff/be-sdk';\n *\n * const wrapper = createPrismaClient(PrismaClient, {\n * databaseUrl: process.env.DATABASE_URL!,\n * });\n *\n * await wrapper.connect();\n * const prisma = wrapper.getClient();\n *\n * // Use prisma client\n * const users = await prisma.user.findMany();\n * ```\n */\n/**\n * Prisma log level options\n */\nexport type PrismaLogLevel = 'info' | 'query' | 'warn' | 'error';\n\n/**\n * Prisma log definition\n */\nexport interface PrismaLogDefinition {\n level: PrismaLogLevel;\n emit: 'stdout' | 'event';\n}\n\n/**\n * Prisma client constructor options\n */\nexport interface PrismaClientConstructorOptions {\n adapter: PrismaPg;\n log?: (PrismaLogLevel | PrismaLogDefinition)[];\n}\n\nexport function createPrismaClient<T extends PrismaClientBase>(\n PrismaClientConstructor: new (options: PrismaClientConstructorOptions) => T,\n config: PrismaClientConfig\n): PrismaClientWrapper<T> {\n const isDevelopment = process.env['NODE_ENV'] === 'development';\n\n // Create connection pool\n const pool = createConnectionPool(config);\n\n // Create adapter\n const adapter = createPrismaAdapter(pool);\n\n // Determine log levels\n const logLevels: PrismaLogDefinition[] =\n (config.logLevels as PrismaLogDefinition[] | undefined) ??\n (isDevelopment\n ? [\n { emit: 'event', level: 'query' },\n { emit: 'event', level: 'info' },\n { emit: 'event', level: 'warn' },\n { emit: 'event', level: 'error' },\n ]\n : [\n { emit: 'event', level: 'warn' },\n { emit: 'event', level: 'error' },\n ]);\n\n // Create Prisma client\n const client = new PrismaClientConstructor({\n adapter,\n log: logLevels,\n });\n\n // Create and return wrapper\n return new PrismaClientWrapper(client, pool, config);\n}\n","/**\n * Prisma Middleware for Graph Event Emission\n *\n * Automatically emits events to the graph event queue when entities are\n * created, updated, or deleted in PostgreSQL.\n *\n * This is a product-agnostic Prisma extension that can be used by any Burdenoff product.\n *\n * @module prisma-graph-extension\n * @category Graph\n */\nimport { logger } from '../../logger/index.js';\nimport { extractMinimalFields } from '../utils/helpers.js';\nimport { GraphRegistry } from '../utils/registry.js';\n\n/**\n * Event types for entity operations\n */\nexport type EntityEventType =\n | 'entity.created'\n | 'entity.updated'\n | 'entity.deleted'\n | 'relationship.created'\n | 'relationship.deleted';\n\n/**\n * RBAC metadata for entity events (resolved from graph config)\n */\nexport interface EntityEventRbacMetadata {\n resourceTypeName: string;\n name?: string;\n identifier?: string;\n parentResourceIdentifier?: string;\n createResource?: boolean;\n}\n\n/**\n * Event emitter interface - products must provide their own implementation\n */\nexport interface GraphEventEmitter {\n publishEntityEvent(\n eventType: EntityEventType,\n entity: {\n id: string;\n type: string;\n data: Record<string, unknown>;\n },\n context: {\n productName: string;\n organizationId: string;\n actorId?: string;\n workspaceId?: string;\n },\n rbac?: EntityEventRbacMetadata\n ): Promise<void>;\n}\n\n/**\n * Configuration for graph middleware\n */\nexport interface GraphMiddlewareConfig {\n /** Whether middleware is enabled */\n enabled: boolean;\n /** Product name for event metadata */\n productName: string;\n /** Event emitter implementation */\n eventEmitter: GraphEventEmitter;\n /** Entity types to monitor (if empty, monitors all registered types) */\n entityTypes?: string[];\n /** Operations to monitor */\n monitoredOperations?: Array<'create' | 'update' | 'delete' | 'deleteMany' | 'updateMany'>;\n}\n\n/**\n * Default configuration\n */\nconst defaultConfig: {\n enabled: boolean;\n monitoredOperations: Array<'create' | 'update' | 'delete' | 'deleteMany' | 'updateMany'>;\n} = {\n enabled: true,\n monitoredOperations: ['create', 'update', 'delete', 'deleteMany', 'updateMany'],\n};\n\n/**\n * Extract entity information from Prisma result\n */\nfunction extractEntityInfo(\n model: string,\n result: unknown\n): { id: string; type: string; data: Record<string, unknown> } | null {\n if (!result || typeof result !== 'object') {\n return null;\n }\n\n const record = result as Record<string, unknown>;\n const id = record['id'] as string;\n\n if (!id) {\n return null;\n }\n\n return {\n id,\n type: model,\n data: record,\n };\n}\n\n/**\n * Extract organization and user context from Prisma arguments\n */\nfunction extractContext(args: unknown): {\n organizationId?: string;\n actorId?: string;\n workspaceId?: string;\n} {\n if (!args || typeof args !== 'object') {\n return {};\n }\n\n const data =\n (args as { data?: Record<string, unknown>; where?: Record<string, unknown> })['data'] ||\n (args as { where?: Record<string, unknown> })['where'];\n\n if (!data || typeof data !== 'object') {\n return {};\n }\n\n return {\n organizationId: data['organizationId'] as string | undefined,\n actorId:\n (data['actorId'] as string | undefined) ||\n (data['createdBy'] as string | undefined) ||\n (data['updatedBy'] as string | undefined) ||\n (data['userId'] as string | undefined),\n workspaceId: (data['workspaceId'] as string | undefined) || (data['workspaceID'] as string | undefined),\n };\n}\n\n/**\n * Emit event for entity operation\n */\nfunction emitEntityEvent(\n eventType: EntityEventType,\n model: string,\n result: unknown,\n args: unknown,\n config: GraphMiddlewareConfig\n): void {\n const entityInfo = extractEntityInfo(model, result);\n if (!entityInfo) {\n return;\n }\n\n // Check if this entity type is registered in the graph registry\n if (!GraphRegistry.isEntityRegistered(model)) {\n return;\n }\n\n // Check if we should monitor this entity type\n if (config.entityTypes && config.entityTypes.length > 0 && !config.entityTypes.includes(model)) {\n return;\n }\n\n const context = extractContext(args);\n const minimalData = extractMinimalFields(model, entityInfo.data);\n\n // Use GraphRegistry to extract organization and workspace IDs from entity data\n // This allows entity-specific field mappings (e.g., tenantId → organizationId)\n const orgId = GraphRegistry.getOrganizationId(model, entityInfo.data) || context.organizationId || 'unknown';\n const workspaceId = GraphRegistry.getWorkspaceId(model, entityInfo.data) || context.workspaceId;\n const actorId = context.actorId || 'unknown';\n\n // Resolve RBAC metadata from GraphRegistry (if entity has rbac config)\n const rbacMetadata = GraphRegistry.resolveRbacMetadata(model, entityInfo.data);\n\n if (rbacMetadata) {\n logger.debug(`[GraphMiddleware] Including RBAC metadata for ${model}`, {\n resourceTypeName: rbacMetadata.resourceTypeName,\n hasName: !!rbacMetadata.name,\n });\n }\n\n // Emit event (non-blocking) — includes RBAC metadata when configured\n config.eventEmitter\n .publishEntityEvent(\n eventType,\n {\n id: entityInfo.id,\n type: entityInfo.type,\n data: minimalData,\n },\n {\n productName: config.productName,\n organizationId: orgId,\n actorId,\n workspaceId,\n },\n rbacMetadata\n )\n .catch((error: unknown) => {\n logger.error('[GraphMiddleware] Failed to emit event:', error);\n });\n\n // After emitting entity event, check for relationship events\n // Only for create/update operations\n if (eventType === 'entity.created' || eventType === 'entity.updated') {\n emitRelationshipEvents(model, entityInfo.data, orgId, config);\n }\n}\n\n/**\n * Emit relationship events based on foreign key values\n * This automatically creates edges in the graph when entities with foreign keys are created/updated\n */\nfunction emitRelationshipEvents(\n entityType: string,\n entityData: Record<string, unknown>,\n organizationId: string,\n config: GraphMiddlewareConfig\n): void {\n // Get all relationships where this entity type is the \"from\" side\n const relationships = GraphRegistry.getRelationshipsForEntity(entityType);\n\n if (relationships.length === 0) {\n return;\n }\n\n const fromId = entityData['id'] as string;\n if (!fromId) {\n return;\n }\n\n // For each relationship, check if the foreign key field has a value\n for (const [relationshipKey, relationshipConfig] of relationships) {\n const foreignKeyValue = entityData[relationshipConfig.fromField] as string | null | undefined;\n\n // Skip if foreign key is null/undefined (no relationship)\n if (!foreignKeyValue) {\n continue;\n }\n\n // Handle polymorphic relationships\n let targetType = relationshipConfig.to;\n if (relationshipConfig.to === '*') {\n if (relationshipConfig.polymorphicTypeField) {\n targetType = entityData[relationshipConfig.polymorphicTypeField] as string;\n if (!targetType) {\n logger.warn(`[GraphMiddleware] Polymorphic relationship ${relationshipKey} has no type field value`);\n continue;\n }\n } else {\n logger.debug(`[GraphMiddleware] Skipping polymorphic relationship without type field: ${relationshipKey}`);\n continue;\n }\n }\n\n // Extract metadata if configured\n const metadata = relationshipConfig.extractMetadata\n ? relationshipConfig.extractMetadata(entityData)\n : { description: relationshipConfig.description };\n\n // Emit relationship.created event\n config.eventEmitter\n .publishEntityEvent(\n 'relationship.created',\n {\n id: `${fromId}_${foreignKeyValue}`,\n type: relationshipConfig.label,\n data: {\n from: {\n id: fromId,\n type: entityType,\n },\n to: {\n id: foreignKeyValue,\n type: targetType,\n },\n relationType: relationshipConfig.label,\n metadata,\n },\n },\n {\n productName: config.productName,\n organizationId,\n }\n )\n .catch((error: unknown) => {\n logger.error(`[GraphMiddleware] Failed to emit relationship event for ${relationshipKey}:`, error);\n });\n\n logger.debug(\n `[GraphMiddleware] Emitted relationship.created: ${relationshipConfig.label} (${entityType}:${fromId} -> ${targetType}:${foreignKeyValue})`\n );\n }\n}\n\n/**\n * Add graph extension to Prisma client for automatic event emission\n *\n * This function uses Prisma Client Extensions (Prisma 6+) to intercept\n * database operations and emit events to the graph event queue.\n *\n * @param baseClient - Base Prisma client instance\n * @param config - Configuration for the middleware\n * @returns Extended Prisma client with graph event emission\n *\n * @example\n * ```typescript\n * import { PrismaClient } from '@prisma/client';\n * import { addGraphExtension } from '@burdenoff/be-sdk/graph';\n * import { eventQueue } from './event-queue';\n *\n * const baseClient = new PrismaClient();\n * const client = addGraphExtension(baseClient, {\n * enabled: true,\n * productName: 'workspaces',\n * eventEmitter: eventQueue,\n * entityTypes: ['Project', 'Group', 'Workspace'], // Optional: monitor specific types\n * });\n * ```\n */\nexport function addGraphExtension<T>(baseClient: T, config: GraphMiddlewareConfig): T {\n const fullConfig = { ...defaultConfig, ...config };\n\n if (!fullConfig.enabled) {\n logger.info('[GraphMiddleware] Extension disabled by configuration');\n return baseClient;\n }\n\n // Type assertion for Prisma client\n const prismaClient = baseClient as { $extends: (args: unknown) => T };\n\n return prismaClient.$extends({\n query: {\n $allModels: {\n async create({\n model,\n args,\n query,\n }: {\n model: string;\n args: unknown;\n query: (args: unknown) => Promise<unknown>;\n }) {\n const result = await query(args);\n\n if (fullConfig.monitoredOperations?.includes('create')) {\n emitEntityEvent('entity.created', model, result, args, fullConfig);\n }\n\n return result;\n },\n\n async update({\n model,\n args,\n query,\n }: {\n model: string;\n args: unknown;\n query: (args: unknown) => Promise<unknown>;\n }) {\n const result = await query(args);\n\n if (fullConfig.monitoredOperations?.includes('update')) {\n emitEntityEvent('entity.updated', model, result, args, fullConfig);\n }\n\n return result;\n },\n\n async delete({\n model,\n args,\n query,\n }: {\n model: string;\n args: unknown;\n query: (args: unknown) => Promise<unknown>;\n }) {\n const result = await query(args);\n\n if (fullConfig.monitoredOperations?.includes('delete')) {\n emitEntityEvent('entity.deleted', model, result, args, fullConfig);\n }\n\n return result;\n },\n\n async updateMany({\n model,\n args,\n query,\n }: {\n model: string;\n args: unknown;\n query: (args: unknown) => Promise<unknown>;\n }) {\n const result = await query(args);\n\n if (fullConfig.monitoredOperations?.includes('updateMany')) {\n logger.info(`[GraphMiddleware] updateMany for ${model} (bulk operation not tracked individually)`);\n }\n\n return result;\n },\n\n async deleteMany({\n model,\n args,\n query,\n }: {\n model: string;\n args: unknown;\n query: (args: unknown) => Promise<unknown>;\n }) {\n const result = await query(args);\n\n if (fullConfig.monitoredOperations?.includes('deleteMany')) {\n logger.info(`[GraphMiddleware] deleteMany for ${model} (bulk operation not tracked individually)`);\n }\n\n return result;\n },\n },\n },\n });\n}\n"]}
@@ -1,4 +1,4 @@
1
- import { logger } from './chunk-CBZNP6RF.js';
1
+ import { logger } from './chunk-RU266375.js';
2
2
  import { __name } from './chunk-XE4OXN2W.js';
3
3
 
4
4
  // src/event-queue/implementations/redis-streams/keyspace.ts
@@ -245,5 +245,5 @@ var RedisStreamsConnection = class {
245
245
  };
246
246
 
247
247
  export { RedisStreamsConnection, boundaryOf, dedupKey, delayLockKey, delayQueueKey, dlqKey, isWildcard, matchSubject, registryKey, replyKey, streamKey };
248
- //# sourceMappingURL=chunk-S7LWYERE.js.map
249
- //# sourceMappingURL=chunk-S7LWYERE.js.map
248
+ //# sourceMappingURL=chunk-LKCBI6B2.js.map
249
+ //# sourceMappingURL=chunk-LKCBI6B2.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/event-queue/implementations/redis-streams/keyspace.ts","../src/event-queue/implementations/redis-streams/RedisStreamsConnection.ts"],"names":["DEFAULT_PREFIX","REGISTRY_PREFIX","DELAYQ_PREFIX","DELAYQ_LOCK_PREFIX","DLQ_PREFIX","DEDUP_PREFIX","REPLY_PREFIX","currentScope","setKeyScope","scope","scoped","prefix","subjectToKey","subject","replace","streamKey","opts","registryKey","boundary","boundaryOf","first","split","delayQueueKey","stream","delayLockKey","dlqKey","dedupKey","msgId","replyKey","correlationId","matchSubject","pattern","pParts","sParts","last","length","i","isWildcard","includes","ioredisModulePromise","loadIoRedis","mod","default","Redis","err","logger","error","Error","message","String","ctor","normaliseUrl","rawUrl","url","tls","test","host","dbIndex","parsed","URL","hostname","pathDb","pathname","parseInt","toString","RedisStreamsConnection","client","connecting","normalisedUrl","config","process","env","isConnected","status","connect","doConnect","finally","keepAlive","lazyConnect","maxRetriesPerRequest","enableReadyCheck","connectTimeout","connectionTimeout","reconnectOnError","retryStrategy","times","Math","min","Number","isFinite","password","user","servername","on","args","warn","info","keyScope","disconnect","quit","getClient","makeBlockingClient","dup","duplicate","ping"],"mappings":"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","file":"chunk-S7LWYERE.js","sourcesContent":["/**\n * Redis Streams key namespace helpers.\n *\n * All keys are prefixed with `boff:` because DB 0 of Azure Managed Redis is\n * shared with the be-sdk cache provider.\n */\n\nexport interface KeyspaceOptions {\n /** Top-level prefix for event streams. Defaults to `boff:events`. */\n prefix?: string;\n}\n\nconst DEFAULT_PREFIX = 'boff:events';\nconst REGISTRY_PREFIX = 'boff:registry:subjects';\nconst DELAYQ_PREFIX = 'boff:delayq';\nconst DELAYQ_LOCK_PREFIX = 'boff:lock:delayq';\nconst DLQ_PREFIX = 'boff:dlq';\nconst DEDUP_PREFIX = 'boff:dedup';\nconst REPLY_PREFIX = 'boff:replies';\n\n// ── Process-wide key scope (DB-as-prefix) ────────────────────────────────\n//\n// Azure Managed Redis Balanced/B0 only exposes DB 0. Services that used to\n// rely on a non-zero DB index in their REDIS_URL (e.g. `…/4`) for namespace\n// isolation now share DB 0 — RedisStreamsConnection strips the path, pins\n// the connection to DB 0, and calls `setKeyScope(\"db4:\")` so every key that\n// flows through this module is automatically prefixed with `db4:`. That\n// preserves the per-service isolation the DB number used to give us without\n// any of the callers having to change.\n//\n// Default scope is empty (back-compat for services on classic Redis or\n// already using DB 0). Set once at connection time; reads are O(1).\nlet currentScope = '';\n\nexport function setKeyScope(scope: string): void {\n currentScope = scope ?? '';\n}\n\nexport function getKeyScope(): string {\n return currentScope;\n}\n\nfunction scoped(prefix: string): string {\n return currentScope ? `${currentScope}${prefix}` : prefix;\n}\n\n/** Convert a NATS-style subject to a Redis key segment (`.` → `:`). */\nexport function subjectToKey(subject: string): string {\n return subject.replace(/\\./g, ':');\n}\n\n/** Build the stream key for a given subject. */\nexport function streamKey(subject: string, opts: KeyspaceOptions = {}): string {\n const prefix = opts.prefix ?? DEFAULT_PREFIX;\n return `${scoped(prefix)}:${subjectToKey(subject)}`;\n}\n\n/** Stream key from a NATS-style wildcard prefix (e.g. `wspace`). */\nexport function registryKey(boundary: string): string {\n return `${scoped(REGISTRY_PREFIX)}:${boundary}`;\n}\n\n/** Extract the leading boundary (`x` in `x.y.z`). */\nexport function boundaryOf(subject: string): string {\n const first = subject.split('.')[0];\n return first ?? subject;\n}\n\n/** Sorted-set key for delayed-NAK re-delivery, scoped per stream. */\nexport function delayQueueKey(stream: string): string {\n return `${scoped(DELAYQ_PREFIX)}:${stream}`;\n}\n\n/** Lock key the delay-queue worker uses to serialise across replicas. */\nexport function delayLockKey(stream: string): string {\n return `${scoped(DELAYQ_LOCK_PREFIX)}:${stream}`;\n}\n\n/** Per-stream dead-letter queue. */\nexport function dlqKey(stream: string): string {\n return `${scoped(DLQ_PREFIX)}:${stream}`;\n}\n\n/** Per-message dedup marker key. */\nexport function dedupKey(stream: string, msgId: string): string {\n return `${scoped(DEDUP_PREFIX)}:${stream}:${msgId}`;\n}\n\n/** Reply-stream key for request/response emulation. */\nexport function replyKey(correlationId: string): string {\n return `${scoped(REPLY_PREFIX)}:${correlationId}`;\n}\n\n/**\n * Resolve a NATS-style subject pattern to a concrete list of stream keys, using\n * a registry of known subjects.\n *\n * Patterns supported:\n * - `x.y.z` — exact subject, returns single stream\n * - `x.>` — all subjects starting with `x.`\n * - `x.*` — all subjects with exactly one more segment after `x.`\n * - `x.*.z` — single-segment wildcard at position\n */\nexport function matchSubject(pattern: string, subject: string): boolean {\n if (pattern === subject) return true;\n const pParts = pattern.split('.');\n const sParts = subject.split('.');\n const last = pParts[pParts.length - 1];\n if (last === '>') {\n if (sParts.length < pParts.length) return false;\n for (let i = 0; i < pParts.length - 1; i++) {\n if (pParts[i] !== sParts[i]) return false;\n }\n return true;\n }\n if (pParts.length !== sParts.length) return false;\n for (let i = 0; i < pParts.length; i++) {\n if (pParts[i] !== '*' && pParts[i] !== sParts[i]) return false;\n }\n return true;\n}\n\n/** True if subject pattern contains a wildcard token. */\nexport function isWildcard(pattern: string): boolean {\n return pattern.includes('*') || pattern.includes('>');\n}\n","/**\n * Manages a single ioredis client (or cluster) for the Redis Streams backend.\n *\n * Connection URL conventions:\n * - `redis://host:port` — plaintext\n * - `rediss://host:port` — TLS (Azure Managed Redis uses port 10000)\n * - `valkey://`/`valkeys://` — accepted as aliases, normalised internally\n *\n * Hostname → SNI is set automatically for TLS endpoints so Azure-managed certs\n * validate.\n */\nimport { logger } from '../../../logger/index.js';\nimport type { BaseQueueConfig } from '../../types/config.js';\nimport { setKeyScope } from './keyspace.js';\n\ntype IoRedis = {\n status: string;\n connect: () => Promise<void>;\n disconnect: () => void;\n quit: () => Promise<unknown>;\n ping: () => Promise<string>;\n on: (event: string, handler: (...args: unknown[]) => void) => void;\n duplicate: () => IoRedis;\n // Stream + key commands used by publisher/consumer/sweeper\n xadd: (...args: unknown[]) => Promise<string>;\n xack: (...args: unknown[]) => Promise<number>;\n xreadgroup: (...args: unknown[]) => Promise<unknown>;\n xgroup: (...args: unknown[]) => Promise<unknown>;\n xautoclaim: (...args: unknown[]) => Promise<unknown>;\n xpending: (...args: unknown[]) => Promise<unknown>;\n xlen: (key: string) => Promise<number>;\n xinfo: (...args: unknown[]) => Promise<unknown>;\n xrevrange: (...args: unknown[]) => Promise<unknown>;\n xrange: (...args: unknown[]) => Promise<unknown>;\n xdel: (key: string, ...ids: string[]) => Promise<number>;\n set: (...args: unknown[]) => Promise<string | null>;\n expire: (key: string, seconds: number) => Promise<number>;\n del: (...keys: string[]) => Promise<number>;\n sadd: (key: string, ...members: string[]) => Promise<number>;\n smembers: (key: string) => Promise<string[]>;\n zadd: (...args: unknown[]) => Promise<number>;\n zrangebyscore: (...args: unknown[]) => Promise<string[]>;\n zrem: (key: string, ...members: string[]) => Promise<number>;\n pipeline: () => { xadd: (...args: unknown[]) => unknown; exec: () => Promise<Array<[Error | null, unknown]>> };\n};\n\ntype IoRedisCtor = new (url: string, opts: Record<string, unknown>) => IoRedis;\n\nlet ioredisModulePromise: Promise<IoRedisCtor | null> | null = null;\n\nasync function loadIoRedis(): Promise<IoRedisCtor> {\n if (!ioredisModulePromise) {\n ioredisModulePromise = (async () => {\n try {\n const mod = (await import('ioredis')) as unknown as { default?: IoRedisCtor; Redis?: IoRedisCtor };\n return mod.default ?? mod.Redis ?? null;\n } catch (err) {\n logger.error('[RedisStreamsConnection] ioredis not installed', {\n error: err instanceof Error ? err.message : String(err),\n });\n return null;\n }\n })();\n }\n const ctor = await ioredisModulePromise;\n if (!ctor) {\n throw new Error(\n '[RedisStreamsConnection] ioredis is required for the redis-streams event-queue backend. ' +\n 'Install it with: bun add ioredis (or npm i ioredis)'\n );\n }\n return ctor;\n}\n\nfunction normaliseUrl(rawUrl: string): { url: string; tls: boolean; host: string; dbIndex: number } {\n let url = rawUrl;\n let tls = false;\n if (/^valkeys:\\/\\//.test(url)) {\n tls = true;\n url = url.replace(/^valkeys:\\/\\//, 'rediss://');\n } else if (/^valkey:\\/\\//.test(url)) {\n url = url.replace(/^valkey:\\/\\//, 'redis://');\n } else if (/^rediss:\\/\\//.test(url)) {\n tls = true;\n }\n let host = 'localhost';\n let dbIndex = 0;\n try {\n const parsed = new URL(url);\n host = parsed.hostname || host;\n // Azure Managed Redis Balanced/B0 only exposes DB 0. If the URL pins a\n // non-zero DB in its path (e.g. `…/4`), ioredis would issue `SELECT 4`\n // on every reconnect and the server returns `ERR DB index is out of\n // range` in a tight loop that pegs the event loop. Strip the path here\n // so the connection lands on DB 0, then surface the original index to\n // the caller — we use it as a key-prefix scope so the per-service\n // isolation the DB number used to give us is preserved.\n const pathDb = parsed.pathname.replace(/^\\//, '');\n if (pathDb && /^\\d+$/.test(pathDb)) {\n dbIndex = parseInt(pathDb, 10);\n parsed.pathname = '';\n url = parsed.toString();\n }\n } catch {\n /* keep defaults */\n }\n return { url, tls, host, dbIndex };\n}\n\nexport class RedisStreamsConnection {\n private client: IoRedis | null = null;\n private connecting: Promise<void> | null = null;\n private readonly tls: boolean;\n private readonly host: string;\n private readonly normalisedUrl: string;\n private readonly dbIndex: number;\n\n constructor(private readonly config: BaseQueueConfig) {\n const { url, tls, host, dbIndex } = normaliseUrl(config.url);\n this.normalisedUrl = url;\n this.tls = tls || process.env['REDIS_TLS'] === 'true';\n this.host = host;\n this.dbIndex = dbIndex;\n // Install the DB-as-prefix scope before the first publish/consume runs.\n // Safe to call at construction: keyspace.setKeyScope is process-wide and\n // every key produced after this point will be prefixed with `db{N}:`.\n if (dbIndex > 0) {\n setKeyScope(`db${String(dbIndex)}:`);\n }\n }\n\n /** True once `connect()` has resolved and ioredis is in `ready` state. */\n isConnected(): boolean {\n return this.client !== null && this.client.status === 'ready';\n }\n\n /** Connect lazily; subsequent calls await the in-flight promise. */\n async connect(): Promise<void> {\n if (this.isConnected()) return;\n if (this.connecting) {\n await this.connecting;\n return;\n }\n this.connecting = this.doConnect().finally(() => {\n this.connecting = null;\n });\n await this.connecting;\n }\n\n private async doConnect(): Promise<void> {\n const Redis = await loadIoRedis();\n // Enable TCP keep-alive so half-open / stale sockets are detected and reclaimed\n // promptly instead of lingering server-side. Blocking XREAD connections (one per\n // subscribed stream) sit idle for long periods; without keep-alive, a connection\n // orphaned by a proxy failover, network drop, or Redis reprovision (e.g. a tier\n // scale) is not noticed until the next command, so stale sockets accumulate against\n // the server's connection cap during churn. 30s default; set REDIS_STREAMS_KEEPALIVE=0\n // to disable. ioredis passes this to socket.setKeepAlive(true, <ms>).\n const keepAlive = parseInt(process.env['REDIS_STREAMS_KEEPALIVE'] ?? '30000', 10);\n const opts: Record<string, unknown> = {\n lazyConnect: true,\n maxRetriesPerRequest: null,\n enableReadyCheck: true,\n connectTimeout: this.config.connectionTimeout ?? 15000,\n reconnectOnError: () => true,\n retryStrategy: (times: number): number => Math.min(times * 200, 2000),\n };\n if (Number.isFinite(keepAlive) && keepAlive > 0) opts['keepAlive'] = keepAlive;\n if (this.config.password) opts['password'] = this.config.password;\n if (this.config.user) opts['username'] = this.config.user;\n if (this.tls) {\n opts['tls'] = { servername: this.host };\n }\n this.client = new Redis(this.normalisedUrl, opts);\n this.client.on('error', (...args: unknown[]) => {\n const err = args[0] as Error | undefined;\n logger.warn('[RedisStreamsConnection] redis error', {\n error: err?.message ?? 'unknown',\n });\n });\n this.client.on('reconnecting', () => {\n logger.info('[RedisStreamsConnection] reconnecting');\n });\n await this.client.connect();\n logger.info('[RedisStreamsConnection] connected', {\n url: this.normalisedUrl.replace(/:[^:@/]*@/, ':***@'),\n tls: this.tls,\n dbIndex: this.dbIndex,\n keyScope: this.dbIndex > 0 ? `db${String(this.dbIndex)}:` : '',\n });\n }\n\n async disconnect(): Promise<void> {\n if (!this.client) return;\n try {\n await this.client.quit();\n } catch {\n this.client.disconnect();\n }\n this.client = null;\n }\n\n /** The shared command client. Throws if not connected. */\n getClient(): IoRedis {\n if (!this.client) {\n throw new Error('[RedisStreamsConnection] not connected — call connect() first');\n }\n return this.client;\n }\n\n /** Make a dedicated client (e.g. for a blocking XREADGROUP loop). */\n async makeBlockingClient(): Promise<IoRedis> {\n await this.connect();\n const dup = this.getClient().duplicate();\n if ('connect' in dup && typeof dup.connect === 'function') {\n try {\n await dup.connect();\n } catch {\n /* ioredis auto-connects in some versions */\n }\n }\n return dup;\n }\n\n async ping(): Promise<string> {\n await this.connect();\n return this.getClient().ping();\n }\n}\n\nexport type { IoRedis };\n"]}
1
+ {"version":3,"sources":["../src/event-queue/implementations/redis-streams/keyspace.ts","../src/event-queue/implementations/redis-streams/RedisStreamsConnection.ts"],"names":["DEFAULT_PREFIX","REGISTRY_PREFIX","DELAYQ_PREFIX","DELAYQ_LOCK_PREFIX","DLQ_PREFIX","DEDUP_PREFIX","REPLY_PREFIX","currentScope","setKeyScope","scope","scoped","prefix","subjectToKey","subject","replace","streamKey","opts","registryKey","boundary","boundaryOf","first","split","delayQueueKey","stream","delayLockKey","dlqKey","dedupKey","msgId","replyKey","correlationId","matchSubject","pattern","pParts","sParts","last","length","i","isWildcard","includes","ioredisModulePromise","loadIoRedis","mod","default","Redis","err","logger","error","Error","message","String","ctor","normaliseUrl","rawUrl","url","tls","test","host","dbIndex","parsed","URL","hostname","pathDb","pathname","parseInt","toString","RedisStreamsConnection","client","connecting","normalisedUrl","config","process","env","isConnected","status","connect","doConnect","finally","keepAlive","lazyConnect","maxRetriesPerRequest","enableReadyCheck","connectTimeout","connectionTimeout","reconnectOnError","retryStrategy","times","Math","min","Number","isFinite","password","user","servername","on","args","warn","info","keyScope","disconnect","quit","getClient","makeBlockingClient","dup","duplicate","ping"],"mappings":"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","file":"chunk-LKCBI6B2.js","sourcesContent":["/**\n * Redis Streams key namespace helpers.\n *\n * All keys are prefixed with `boff:` because DB 0 of Azure Managed Redis is\n * shared with the be-sdk cache provider.\n */\n\nexport interface KeyspaceOptions {\n /** Top-level prefix for event streams. Defaults to `boff:events`. */\n prefix?: string;\n}\n\nconst DEFAULT_PREFIX = 'boff:events';\nconst REGISTRY_PREFIX = 'boff:registry:subjects';\nconst DELAYQ_PREFIX = 'boff:delayq';\nconst DELAYQ_LOCK_PREFIX = 'boff:lock:delayq';\nconst DLQ_PREFIX = 'boff:dlq';\nconst DEDUP_PREFIX = 'boff:dedup';\nconst REPLY_PREFIX = 'boff:replies';\n\n// ── Process-wide key scope (DB-as-prefix) ────────────────────────────────\n//\n// Azure Managed Redis Balanced/B0 only exposes DB 0. Services that used to\n// rely on a non-zero DB index in their REDIS_URL (e.g. `…/4`) for namespace\n// isolation now share DB 0 — RedisStreamsConnection strips the path, pins\n// the connection to DB 0, and calls `setKeyScope(\"db4:\")` so every key that\n// flows through this module is automatically prefixed with `db4:`. That\n// preserves the per-service isolation the DB number used to give us without\n// any of the callers having to change.\n//\n// Default scope is empty (back-compat for services on classic Redis or\n// already using DB 0). Set once at connection time; reads are O(1).\nlet currentScope = '';\n\nexport function setKeyScope(scope: string): void {\n currentScope = scope ?? '';\n}\n\nexport function getKeyScope(): string {\n return currentScope;\n}\n\nfunction scoped(prefix: string): string {\n return currentScope ? `${currentScope}${prefix}` : prefix;\n}\n\n/** Convert a NATS-style subject to a Redis key segment (`.` → `:`). */\nexport function subjectToKey(subject: string): string {\n return subject.replace(/\\./g, ':');\n}\n\n/** Build the stream key for a given subject. */\nexport function streamKey(subject: string, opts: KeyspaceOptions = {}): string {\n const prefix = opts.prefix ?? DEFAULT_PREFIX;\n return `${scoped(prefix)}:${subjectToKey(subject)}`;\n}\n\n/** Stream key from a NATS-style wildcard prefix (e.g. `wspace`). */\nexport function registryKey(boundary: string): string {\n return `${scoped(REGISTRY_PREFIX)}:${boundary}`;\n}\n\n/** Extract the leading boundary (`x` in `x.y.z`). */\nexport function boundaryOf(subject: string): string {\n const first = subject.split('.')[0];\n return first ?? subject;\n}\n\n/** Sorted-set key for delayed-NAK re-delivery, scoped per stream. */\nexport function delayQueueKey(stream: string): string {\n return `${scoped(DELAYQ_PREFIX)}:${stream}`;\n}\n\n/** Lock key the delay-queue worker uses to serialise across replicas. */\nexport function delayLockKey(stream: string): string {\n return `${scoped(DELAYQ_LOCK_PREFIX)}:${stream}`;\n}\n\n/** Per-stream dead-letter queue. */\nexport function dlqKey(stream: string): string {\n return `${scoped(DLQ_PREFIX)}:${stream}`;\n}\n\n/** Per-message dedup marker key. */\nexport function dedupKey(stream: string, msgId: string): string {\n return `${scoped(DEDUP_PREFIX)}:${stream}:${msgId}`;\n}\n\n/** Reply-stream key for request/response emulation. */\nexport function replyKey(correlationId: string): string {\n return `${scoped(REPLY_PREFIX)}:${correlationId}`;\n}\n\n/**\n * Resolve a NATS-style subject pattern to a concrete list of stream keys, using\n * a registry of known subjects.\n *\n * Patterns supported:\n * - `x.y.z` — exact subject, returns single stream\n * - `x.>` — all subjects starting with `x.`\n * - `x.*` — all subjects with exactly one more segment after `x.`\n * - `x.*.z` — single-segment wildcard at position\n */\nexport function matchSubject(pattern: string, subject: string): boolean {\n if (pattern === subject) return true;\n const pParts = pattern.split('.');\n const sParts = subject.split('.');\n const last = pParts[pParts.length - 1];\n if (last === '>') {\n if (sParts.length < pParts.length) return false;\n for (let i = 0; i < pParts.length - 1; i++) {\n if (pParts[i] !== sParts[i]) return false;\n }\n return true;\n }\n if (pParts.length !== sParts.length) return false;\n for (let i = 0; i < pParts.length; i++) {\n if (pParts[i] !== '*' && pParts[i] !== sParts[i]) return false;\n }\n return true;\n}\n\n/** True if subject pattern contains a wildcard token. */\nexport function isWildcard(pattern: string): boolean {\n return pattern.includes('*') || pattern.includes('>');\n}\n","/**\n * Manages a single ioredis client (or cluster) for the Redis Streams backend.\n *\n * Connection URL conventions:\n * - `redis://host:port` — plaintext\n * - `rediss://host:port` — TLS (Azure Managed Redis uses port 10000)\n * - `valkey://`/`valkeys://` — accepted as aliases, normalised internally\n *\n * Hostname → SNI is set automatically for TLS endpoints so Azure-managed certs\n * validate.\n */\nimport { logger } from '../../../logger/index.js';\nimport type { BaseQueueConfig } from '../../types/config.js';\nimport { setKeyScope } from './keyspace.js';\n\ntype IoRedis = {\n status: string;\n connect: () => Promise<void>;\n disconnect: () => void;\n quit: () => Promise<unknown>;\n ping: () => Promise<string>;\n on: (event: string, handler: (...args: unknown[]) => void) => void;\n duplicate: () => IoRedis;\n // Stream + key commands used by publisher/consumer/sweeper\n xadd: (...args: unknown[]) => Promise<string>;\n xack: (...args: unknown[]) => Promise<number>;\n xreadgroup: (...args: unknown[]) => Promise<unknown>;\n xgroup: (...args: unknown[]) => Promise<unknown>;\n xautoclaim: (...args: unknown[]) => Promise<unknown>;\n xpending: (...args: unknown[]) => Promise<unknown>;\n xlen: (key: string) => Promise<number>;\n xinfo: (...args: unknown[]) => Promise<unknown>;\n xrevrange: (...args: unknown[]) => Promise<unknown>;\n xrange: (...args: unknown[]) => Promise<unknown>;\n xdel: (key: string, ...ids: string[]) => Promise<number>;\n set: (...args: unknown[]) => Promise<string | null>;\n expire: (key: string, seconds: number) => Promise<number>;\n del: (...keys: string[]) => Promise<number>;\n sadd: (key: string, ...members: string[]) => Promise<number>;\n smembers: (key: string) => Promise<string[]>;\n zadd: (...args: unknown[]) => Promise<number>;\n zrangebyscore: (...args: unknown[]) => Promise<string[]>;\n zrem: (key: string, ...members: string[]) => Promise<number>;\n pipeline: () => { xadd: (...args: unknown[]) => unknown; exec: () => Promise<Array<[Error | null, unknown]>> };\n};\n\ntype IoRedisCtor = new (url: string, opts: Record<string, unknown>) => IoRedis;\n\nlet ioredisModulePromise: Promise<IoRedisCtor | null> | null = null;\n\nasync function loadIoRedis(): Promise<IoRedisCtor> {\n if (!ioredisModulePromise) {\n ioredisModulePromise = (async () => {\n try {\n const mod = (await import('ioredis')) as unknown as { default?: IoRedisCtor; Redis?: IoRedisCtor };\n return mod.default ?? mod.Redis ?? null;\n } catch (err) {\n logger.error('[RedisStreamsConnection] ioredis not installed', {\n error: err instanceof Error ? err.message : String(err),\n });\n return null;\n }\n })();\n }\n const ctor = await ioredisModulePromise;\n if (!ctor) {\n throw new Error(\n '[RedisStreamsConnection] ioredis is required for the redis-streams event-queue backend. ' +\n 'Install it with: bun add ioredis (or npm i ioredis)'\n );\n }\n return ctor;\n}\n\nfunction normaliseUrl(rawUrl: string): { url: string; tls: boolean; host: string; dbIndex: number } {\n let url = rawUrl;\n let tls = false;\n if (/^valkeys:\\/\\//.test(url)) {\n tls = true;\n url = url.replace(/^valkeys:\\/\\//, 'rediss://');\n } else if (/^valkey:\\/\\//.test(url)) {\n url = url.replace(/^valkey:\\/\\//, 'redis://');\n } else if (/^rediss:\\/\\//.test(url)) {\n tls = true;\n }\n let host = 'localhost';\n let dbIndex = 0;\n try {\n const parsed = new URL(url);\n host = parsed.hostname || host;\n // Azure Managed Redis Balanced/B0 only exposes DB 0. If the URL pins a\n // non-zero DB in its path (e.g. `…/4`), ioredis would issue `SELECT 4`\n // on every reconnect and the server returns `ERR DB index is out of\n // range` in a tight loop that pegs the event loop. Strip the path here\n // so the connection lands on DB 0, then surface the original index to\n // the caller — we use it as a key-prefix scope so the per-service\n // isolation the DB number used to give us is preserved.\n const pathDb = parsed.pathname.replace(/^\\//, '');\n if (pathDb && /^\\d+$/.test(pathDb)) {\n dbIndex = parseInt(pathDb, 10);\n parsed.pathname = '';\n url = parsed.toString();\n }\n } catch {\n /* keep defaults */\n }\n return { url, tls, host, dbIndex };\n}\n\nexport class RedisStreamsConnection {\n private client: IoRedis | null = null;\n private connecting: Promise<void> | null = null;\n private readonly tls: boolean;\n private readonly host: string;\n private readonly normalisedUrl: string;\n private readonly dbIndex: number;\n\n constructor(private readonly config: BaseQueueConfig) {\n const { url, tls, host, dbIndex } = normaliseUrl(config.url);\n this.normalisedUrl = url;\n this.tls = tls || process.env['REDIS_TLS'] === 'true';\n this.host = host;\n this.dbIndex = dbIndex;\n // Install the DB-as-prefix scope before the first publish/consume runs.\n // Safe to call at construction: keyspace.setKeyScope is process-wide and\n // every key produced after this point will be prefixed with `db{N}:`.\n if (dbIndex > 0) {\n setKeyScope(`db${String(dbIndex)}:`);\n }\n }\n\n /** True once `connect()` has resolved and ioredis is in `ready` state. */\n isConnected(): boolean {\n return this.client !== null && this.client.status === 'ready';\n }\n\n /** Connect lazily; subsequent calls await the in-flight promise. */\n async connect(): Promise<void> {\n if (this.isConnected()) return;\n if (this.connecting) {\n await this.connecting;\n return;\n }\n this.connecting = this.doConnect().finally(() => {\n this.connecting = null;\n });\n await this.connecting;\n }\n\n private async doConnect(): Promise<void> {\n const Redis = await loadIoRedis();\n // Enable TCP keep-alive so half-open / stale sockets are detected and reclaimed\n // promptly instead of lingering server-side. Blocking XREAD connections (one per\n // subscribed stream) sit idle for long periods; without keep-alive, a connection\n // orphaned by a proxy failover, network drop, or Redis reprovision (e.g. a tier\n // scale) is not noticed until the next command, so stale sockets accumulate against\n // the server's connection cap during churn. 30s default; set REDIS_STREAMS_KEEPALIVE=0\n // to disable. ioredis passes this to socket.setKeepAlive(true, <ms>).\n const keepAlive = parseInt(process.env['REDIS_STREAMS_KEEPALIVE'] ?? '30000', 10);\n const opts: Record<string, unknown> = {\n lazyConnect: true,\n maxRetriesPerRequest: null,\n enableReadyCheck: true,\n connectTimeout: this.config.connectionTimeout ?? 15000,\n reconnectOnError: () => true,\n retryStrategy: (times: number): number => Math.min(times * 200, 2000),\n };\n if (Number.isFinite(keepAlive) && keepAlive > 0) opts['keepAlive'] = keepAlive;\n if (this.config.password) opts['password'] = this.config.password;\n if (this.config.user) opts['username'] = this.config.user;\n if (this.tls) {\n opts['tls'] = { servername: this.host };\n }\n this.client = new Redis(this.normalisedUrl, opts);\n this.client.on('error', (...args: unknown[]) => {\n const err = args[0] as Error | undefined;\n logger.warn('[RedisStreamsConnection] redis error', {\n error: err?.message ?? 'unknown',\n });\n });\n this.client.on('reconnecting', () => {\n logger.info('[RedisStreamsConnection] reconnecting');\n });\n await this.client.connect();\n logger.info('[RedisStreamsConnection] connected', {\n url: this.normalisedUrl.replace(/:[^:@/]*@/, ':***@'),\n tls: this.tls,\n dbIndex: this.dbIndex,\n keyScope: this.dbIndex > 0 ? `db${String(this.dbIndex)}:` : '',\n });\n }\n\n async disconnect(): Promise<void> {\n if (!this.client) return;\n try {\n await this.client.quit();\n } catch {\n this.client.disconnect();\n }\n this.client = null;\n }\n\n /** The shared command client. Throws if not connected. */\n getClient(): IoRedis {\n if (!this.client) {\n throw new Error('[RedisStreamsConnection] not connected — call connect() first');\n }\n return this.client;\n }\n\n /** Make a dedicated client (e.g. for a blocking XREADGROUP loop). */\n async makeBlockingClient(): Promise<IoRedis> {\n await this.connect();\n const dup = this.getClient().duplicate();\n if ('connect' in dup && typeof dup.connect === 'function') {\n try {\n await dup.connect();\n } catch {\n /* ioredis auto-connects in some versions */\n }\n }\n return dup;\n }\n\n async ping(): Promise<string> {\n await this.connect();\n return this.getClient().ping();\n }\n}\n\nexport type { IoRedis };\n"]}
@@ -1,4 +1,4 @@
1
- import { GatewayClient } from './chunk-4X5WL6I3.js';
1
+ import { GatewayClient } from './chunk-XYWLCNJH.js';
2
2
  import { __export, __name } from './chunk-XE4OXN2W.js';
3
3
 
4
4
  // src/export/index.ts
@@ -624,5 +624,5 @@ async function triggerExportJob(params) {
624
624
  __name(triggerExportJob, "triggerExportJob");
625
625
 
626
626
  export { BaseModuleExporter, PaginationService, convertToCSV, csvToJSON, estimateCSVSize, export_exports, getCSVHeaders, parseCSV, triggerExportJob };
627
- //# sourceMappingURL=chunk-LGTQ26Z2.js.map
628
- //# sourceMappingURL=chunk-LGTQ26Z2.js.map
627
+ //# sourceMappingURL=chunk-MEA4BQNA.js.map
628
+ //# sourceMappingURL=chunk-MEA4BQNA.js.map