@pattern-stack/codegen 0.15.0 → 0.15.2
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.
- package/CHANGELOG.md +111 -0
- package/dist/chunk-24CWKBK5.js +94 -0
- package/dist/chunk-24CWKBK5.js.map +1 -0
- package/dist/chunk-2E224ZSN.js +20 -0
- package/dist/chunk-2E224ZSN.js.map +1 -0
- package/dist/chunk-2FTZLDBP.js +179 -0
- package/dist/chunk-2FTZLDBP.js.map +1 -0
- package/dist/chunk-2N4UG4VD.js +20 -0
- package/dist/chunk-2N4UG4VD.js.map +1 -0
- package/dist/chunk-2TVVBC53.js +92 -0
- package/dist/chunk-2TVVBC53.js.map +1 -0
- package/dist/chunk-2VHZ7EKC.js +37 -0
- package/dist/chunk-2VHZ7EKC.js.map +1 -0
- package/dist/chunk-32BMMV4H.js +109 -0
- package/dist/chunk-32BMMV4H.js.map +1 -0
- package/dist/chunk-32DOFN3T.js +4042 -0
- package/dist/chunk-32DOFN3T.js.map +1 -0
- package/dist/chunk-36U5UGIO.js +107 -0
- package/dist/chunk-36U5UGIO.js.map +1 -0
- package/dist/chunk-3CJFPU6Q.js +14 -0
- package/dist/chunk-3CJFPU6Q.js.map +1 -0
- package/dist/chunk-3NMCDN7L.js +90 -0
- package/dist/chunk-3NMCDN7L.js.map +1 -0
- package/dist/chunk-3SZFUTXE.js +62 -0
- package/dist/chunk-3SZFUTXE.js.map +1 -0
- package/dist/chunk-4DOJBQTP.js +117 -0
- package/dist/chunk-4DOJBQTP.js.map +1 -0
- package/dist/chunk-4JLJYWJC.js +308 -0
- package/dist/chunk-4JLJYWJC.js.map +1 -0
- package/dist/chunk-4KNXX6TI.js +29 -0
- package/dist/chunk-4KNXX6TI.js.map +1 -0
- package/dist/chunk-4LH67P4U.js +17 -0
- package/dist/chunk-4LH67P4U.js.map +1 -0
- package/dist/chunk-4MVGAMUA.js +40 -0
- package/dist/chunk-4MVGAMUA.js.map +1 -0
- package/dist/chunk-4OMHBMZJ.js +75 -0
- package/dist/chunk-4OMHBMZJ.js.map +1 -0
- package/dist/chunk-4RFHUZXU.js +635 -0
- package/dist/chunk-4RFHUZXU.js.map +1 -0
- package/dist/chunk-5A432NZJ.js +7 -0
- package/dist/chunk-5A432NZJ.js.map +1 -0
- package/dist/chunk-5Y7W3XR6.js +356 -0
- package/dist/chunk-5Y7W3XR6.js.map +1 -0
- package/dist/chunk-6DWFJNIK.js +15 -0
- package/dist/chunk-6DWFJNIK.js.map +1 -0
- package/dist/chunk-6I7ULIN6.js +15 -0
- package/dist/chunk-6I7ULIN6.js.map +1 -0
- package/dist/chunk-6XY6ZMMD.js +25 -0
- package/dist/chunk-6XY6ZMMD.js.map +1 -0
- package/dist/chunk-7B3RYX45.js +63 -0
- package/dist/chunk-7B3RYX45.js.map +1 -0
- package/dist/chunk-7C3FOSDI.js +1 -0
- package/dist/chunk-7C3FOSDI.js.map +1 -0
- package/dist/chunk-7KOW6PU6.js +59 -0
- package/dist/chunk-7KOW6PU6.js.map +1 -0
- package/dist/chunk-7LKAMLV4.js +92 -0
- package/dist/chunk-7LKAMLV4.js.map +1 -0
- package/dist/chunk-7RELQJIN.js +22 -0
- package/dist/chunk-7RELQJIN.js.map +1 -0
- package/dist/chunk-AHV4GDYM.js +63 -0
- package/dist/chunk-AHV4GDYM.js.map +1 -0
- package/dist/chunk-AQFQ4BYM.js +81 -0
- package/dist/chunk-AQFQ4BYM.js.map +1 -0
- package/dist/chunk-AS3NAZB6.js +14 -0
- package/dist/chunk-AS3NAZB6.js.map +1 -0
- package/dist/chunk-BGULBWKJ.js +88 -0
- package/dist/chunk-BGULBWKJ.js.map +1 -0
- package/dist/chunk-BIO6F7YI.js +17 -0
- package/dist/chunk-BIO6F7YI.js.map +1 -0
- package/dist/chunk-BOPZWRJK.js +36 -0
- package/dist/chunk-BOPZWRJK.js.map +1 -0
- package/dist/chunk-BPARRK6F.js +14 -0
- package/dist/chunk-BPARRK6F.js.map +1 -0
- package/dist/chunk-CO6LUM72.js +59 -0
- package/dist/chunk-CO6LUM72.js.map +1 -0
- package/dist/chunk-COGHTKXY.js +84 -0
- package/dist/chunk-COGHTKXY.js.map +1 -0
- package/dist/chunk-DCCZB4UC.js +100 -0
- package/dist/chunk-DCCZB4UC.js.map +1 -0
- package/dist/chunk-DKKFTHHI.js +53 -0
- package/dist/chunk-DKKFTHHI.js.map +1 -0
- package/dist/chunk-DV4RV2DC.js +59 -0
- package/dist/chunk-DV4RV2DC.js.map +1 -0
- package/dist/chunk-EDKJU5BO.js +11 -0
- package/dist/chunk-EDKJU5BO.js.map +1 -0
- package/dist/chunk-EO2QPOKH.js +116 -0
- package/dist/chunk-EO2QPOKH.js.map +1 -0
- package/dist/chunk-EOLLMEAH.js +155 -0
- package/dist/chunk-EOLLMEAH.js.map +1 -0
- package/dist/chunk-EWYCWP4H.js +14 -0
- package/dist/chunk-EWYCWP4H.js.map +1 -0
- package/dist/chunk-EXVDJMIY.js +33 -0
- package/dist/chunk-EXVDJMIY.js.map +1 -0
- package/dist/chunk-FASRXRX5.js +19 -0
- package/dist/chunk-FASRXRX5.js.map +1 -0
- package/dist/chunk-FI34KYZ5.js +1 -0
- package/dist/chunk-FI34KYZ5.js.map +1 -0
- package/dist/chunk-FN2PYDPP.js +1 -0
- package/dist/chunk-FN2PYDPP.js.map +1 -0
- package/dist/chunk-GM3RMJIJ.js +92 -0
- package/dist/chunk-GM3RMJIJ.js.map +1 -0
- package/dist/chunk-GYGNEQSC.js +9 -0
- package/dist/chunk-GYGNEQSC.js.map +1 -0
- package/dist/chunk-H5NH7KPE.js +21 -0
- package/dist/chunk-H5NH7KPE.js.map +1 -0
- package/dist/chunk-HNWZFNKP.js +168 -0
- package/dist/chunk-HNWZFNKP.js.map +1 -0
- package/dist/chunk-HUH73XGI.js +1 -0
- package/dist/chunk-HUH73XGI.js.map +1 -0
- package/dist/chunk-I6MG4M3F.js +201 -0
- package/dist/chunk-I6MG4M3F.js.map +1 -0
- package/dist/chunk-I6MVCB5A.js +39 -0
- package/dist/chunk-I6MVCB5A.js.map +1 -0
- package/dist/chunk-IBGER4YK.js +12 -0
- package/dist/chunk-IBGER4YK.js.map +1 -0
- package/dist/chunk-IF5I3DAA.js +92 -0
- package/dist/chunk-IF5I3DAA.js.map +1 -0
- package/dist/chunk-IP4OO26U.js +54 -0
- package/dist/chunk-IP4OO26U.js.map +1 -0
- package/dist/chunk-IWAOY6KC.js +1 -0
- package/dist/chunk-IWAOY6KC.js.map +1 -0
- package/dist/chunk-J37YWU7Y.js +19 -0
- package/dist/chunk-J37YWU7Y.js.map +1 -0
- package/dist/chunk-J6KZS54B.js +269 -0
- package/dist/chunk-J6KZS54B.js.map +1 -0
- package/dist/chunk-J6MN42LG.js +19 -0
- package/dist/chunk-J6MN42LG.js.map +1 -0
- package/dist/chunk-JRQO2IOF.js +65 -0
- package/dist/chunk-JRQO2IOF.js.map +1 -0
- package/dist/chunk-JRVNVKN6.js +212 -0
- package/dist/chunk-JRVNVKN6.js.map +1 -0
- package/dist/chunk-JWNHNUYL.js +96 -0
- package/dist/chunk-JWNHNUYL.js.map +1 -0
- package/dist/chunk-K2I6XIK5.js +122 -0
- package/dist/chunk-K2I6XIK5.js.map +1 -0
- package/dist/chunk-KMZCQASO.js +111 -0
- package/dist/chunk-KMZCQASO.js.map +1 -0
- package/dist/chunk-KVOWSC5S.js +1 -0
- package/dist/chunk-KVOWSC5S.js.map +1 -0
- package/dist/chunk-KYR3B3OW.js +79 -0
- package/dist/chunk-KYR3B3OW.js.map +1 -0
- package/dist/chunk-L3LZWWSX.js +61 -0
- package/dist/chunk-L3LZWWSX.js.map +1 -0
- package/dist/chunk-L4SDDEEU.js +1 -0
- package/dist/chunk-L4SDDEEU.js.map +1 -0
- package/dist/chunk-L6FTY45T.js +13 -0
- package/dist/chunk-L6FTY45T.js.map +1 -0
- package/dist/chunk-L7BNNRGI.js +134 -0
- package/dist/chunk-L7BNNRGI.js.map +1 -0
- package/dist/chunk-LG57S2SC.js +150 -0
- package/dist/chunk-LG57S2SC.js.map +1 -0
- package/dist/chunk-M6QLSLPO.js +97 -0
- package/dist/chunk-M6QLSLPO.js.map +1 -0
- package/dist/chunk-MZ6GV4YF.js +21 -0
- package/dist/chunk-MZ6GV4YF.js.map +1 -0
- package/dist/chunk-N5OTOWTP.js +55 -0
- package/dist/chunk-N5OTOWTP.js.map +1 -0
- package/dist/chunk-NN7XZEGF.js +14 -0
- package/dist/chunk-NN7XZEGF.js.map +1 -0
- package/dist/chunk-NPFPZ2HO.js +13 -0
- package/dist/chunk-NPFPZ2HO.js.map +1 -0
- package/dist/chunk-NXXDZ6ZF.js +42 -0
- package/dist/chunk-NXXDZ6ZF.js.map +1 -0
- package/dist/chunk-NYBCQZC7.js +11 -0
- package/dist/chunk-NYBCQZC7.js.map +1 -0
- package/dist/chunk-OFRRBC7M.js +78 -0
- package/dist/chunk-OFRRBC7M.js.map +1 -0
- package/dist/chunk-OGIZXGPY.js +222 -0
- package/dist/chunk-OGIZXGPY.js.map +1 -0
- package/dist/chunk-OKXZ63IA.js +168 -0
- package/dist/chunk-OKXZ63IA.js.map +1 -0
- package/dist/chunk-OSQRXVG2.js +58 -0
- package/dist/chunk-OSQRXVG2.js.map +1 -0
- package/dist/chunk-OTDN3OUQ.js +215 -0
- package/dist/chunk-OTDN3OUQ.js.map +1 -0
- package/dist/chunk-OZZJDRGW.js +122 -0
- package/dist/chunk-OZZJDRGW.js.map +1 -0
- package/dist/chunk-PNZSGAB2.js +114 -0
- package/dist/chunk-PNZSGAB2.js.map +1 -0
- package/dist/chunk-PRWIX6UW.js +21 -0
- package/dist/chunk-PRWIX6UW.js.map +1 -0
- package/dist/chunk-PSXUNOVU.js +7 -0
- package/dist/chunk-PSXUNOVU.js.map +1 -0
- package/dist/chunk-QLTJSCE6.js +44 -0
- package/dist/chunk-QLTJSCE6.js.map +1 -0
- package/dist/chunk-RC23QROE.js +447 -0
- package/dist/chunk-RC23QROE.js.map +1 -0
- package/dist/chunk-RFH7N6EP.js +36 -0
- package/dist/chunk-RFH7N6EP.js.map +1 -0
- package/dist/chunk-RHVN6NA7.js +134 -0
- package/dist/chunk-RHVN6NA7.js.map +1 -0
- package/dist/chunk-S7C6TIIF.js +21 -0
- package/dist/chunk-S7C6TIIF.js.map +1 -0
- package/dist/chunk-SNQ3TOWP.js +20 -0
- package/dist/chunk-SNQ3TOWP.js.map +1 -0
- package/dist/chunk-SOVM2VEK.js +14 -0
- package/dist/chunk-SOVM2VEK.js.map +1 -0
- package/dist/chunk-SQDOBLBP.js +13 -0
- package/dist/chunk-SQDOBLBP.js.map +1 -0
- package/dist/chunk-SR7F3TJY.js +130 -0
- package/dist/chunk-SR7F3TJY.js.map +1 -0
- package/dist/chunk-SZVPIHWE.js +129 -0
- package/dist/chunk-SZVPIHWE.js.map +1 -0
- package/dist/chunk-T4BIIU5E.js +89 -0
- package/dist/chunk-T4BIIU5E.js.map +1 -0
- package/dist/chunk-T6C4LFLC.js +112 -0
- package/dist/chunk-T6C4LFLC.js.map +1 -0
- package/dist/chunk-TNXH7BJS.js +48 -0
- package/dist/chunk-TNXH7BJS.js.map +1 -0
- package/dist/chunk-U64T4YZE.js +9 -0
- package/dist/chunk-U64T4YZE.js.map +1 -0
- package/dist/chunk-UQ5EHOH2.js +39 -0
- package/dist/chunk-UQ5EHOH2.js.map +1 -0
- package/dist/chunk-UTN4GBPQ.js +1 -0
- package/dist/chunk-UTN4GBPQ.js.map +1 -0
- package/dist/chunk-V4AF6DI4.js +16 -0
- package/dist/chunk-V4AF6DI4.js.map +1 -0
- package/dist/chunk-W72PRNJY.js +126 -0
- package/dist/chunk-W72PRNJY.js.map +1 -0
- package/dist/chunk-WEVWJKOW.js +81 -0
- package/dist/chunk-WEVWJKOW.js.map +1 -0
- package/dist/chunk-WL67FZGF.js +21 -0
- package/dist/chunk-WL67FZGF.js.map +1 -0
- package/dist/chunk-WPXNN6QS.js +290 -0
- package/dist/chunk-WPXNN6QS.js.map +1 -0
- package/dist/chunk-WRUUSZDJ.js +29 -0
- package/dist/chunk-WRUUSZDJ.js.map +1 -0
- package/dist/chunk-X2GMTYPA.js +50 -0
- package/dist/chunk-X2GMTYPA.js.map +1 -0
- package/dist/chunk-XCEI7NUH.js +41 -0
- package/dist/chunk-XCEI7NUH.js.map +1 -0
- package/dist/chunk-Y7GDG744.js +88 -0
- package/dist/chunk-Y7GDG744.js.map +1 -0
- package/dist/chunk-Y7RRSEOC.js +9 -0
- package/dist/chunk-Y7RRSEOC.js.map +1 -0
- package/dist/chunk-YPWODKD5.js +184 -0
- package/dist/chunk-YPWODKD5.js.map +1 -0
- package/dist/chunk-YSLTTQLC.js +25 -0
- package/dist/chunk-YSLTTQLC.js.map +1 -0
- package/dist/chunk-YTN6BKWA.js +121 -0
- package/dist/chunk-YTN6BKWA.js.map +1 -0
- package/dist/chunk-Z7PQCAVK.js +200 -0
- package/dist/chunk-Z7PQCAVK.js.map +1 -0
- package/dist/chunk-ZUKFQL6E.js +47 -0
- package/dist/chunk-ZUKFQL6E.js.map +1 -0
- package/dist/chunk-ZUMULSEQ.js +1 -0
- package/dist/chunk-ZUMULSEQ.js.map +1 -0
- package/dist/{job-orchestrator.protocol-CARhMLCO.d.ts → job-orchestrator.protocol-DubMVbm9.d.ts} +1 -1
- package/dist/runtime/analytics/index.js +8 -41
- package/dist/runtime/analytics/index.js.map +1 -1
- package/dist/runtime/analytics/types.js +8 -41
- package/dist/runtime/analytics/types.js.map +1 -1
- package/dist/runtime/base-classes/activity-entity-repository.js +6 -312
- package/dist/runtime/base-classes/activity-entity-repository.js.map +1 -1
- package/dist/runtime/base-classes/activity-entity-service.js +6 -212
- package/dist/runtime/base-classes/activity-entity-service.js.map +1 -1
- package/dist/runtime/base-classes/base-read-use-cases.js +5 -27
- package/dist/runtime/base-classes/base-read-use-cases.js.map +1 -1
- package/dist/runtime/base-classes/base-repository.js +5 -277
- package/dist/runtime/base-classes/base-repository.js.map +1 -1
- package/dist/runtime/base-classes/base-service.js +5 -184
- package/dist/runtime/base-classes/base-service.js.map +1 -1
- package/dist/runtime/base-classes/index.js +59 -1076
- package/dist/runtime/base-classes/index.js.map +1 -1
- package/dist/runtime/base-classes/integrated-entity-repository.js +6 -486
- package/dist/runtime/base-classes/integrated-entity-repository.js.map +1 -1
- package/dist/runtime/base-classes/integrated-entity-service.js +6 -213
- package/dist/runtime/base-classes/integrated-entity-service.js.map +1 -1
- package/dist/runtime/base-classes/junction-integration-repository.js +8 -448
- package/dist/runtime/base-classes/junction-integration-repository.js.map +1 -1
- package/dist/runtime/base-classes/knowledge-entity-repository.js +6 -283
- package/dist/runtime/base-classes/knowledge-entity-repository.js.map +1 -1
- package/dist/runtime/base-classes/knowledge-entity-service.js +6 -190
- package/dist/runtime/base-classes/knowledge-entity-service.js.map +1 -1
- package/dist/runtime/base-classes/lifecycle-events.js +8 -70
- package/dist/runtime/base-classes/lifecycle-events.js.map +1 -1
- package/dist/runtime/base-classes/metadata-entity-repository.js +6 -330
- package/dist/runtime/base-classes/metadata-entity-repository.js.map +1 -1
- package/dist/runtime/base-classes/metadata-entity-service.js +6 -212
- package/dist/runtime/base-classes/metadata-entity-service.js.map +1 -1
- package/dist/runtime/base-classes/tenant-context.js +10 -36
- package/dist/runtime/base-classes/tenant-context.js.map +1 -1
- package/dist/runtime/base-classes/with-analytics.js +4 -7
- package/dist/runtime/base-classes/with-analytics.js.map +1 -1
- package/dist/runtime/constants/tokens.js +5 -3
- package/dist/runtime/constants/tokens.js.map +1 -1
- package/dist/runtime/eav-helpers.js +2 -0
- package/dist/runtime/eav-helpers.js.map +1 -1
- package/dist/runtime/pipes/zod-validation.pipe.js +3 -10
- package/dist/runtime/pipes/zod-validation.pipe.js.map +1 -1
- package/dist/runtime/shared/openapi/error-response.dto.js +5 -8
- package/dist/runtime/shared/openapi/error-response.dto.js.map +1 -1
- package/dist/runtime/shared/openapi/errors.js +5 -19
- package/dist/runtime/shared/openapi/errors.js.map +1 -1
- package/dist/runtime/shared/openapi/index.js +15 -106
- package/dist/runtime/shared/openapi/index.js.map +1 -1
- package/dist/runtime/shared/openapi/registry.js +6 -103
- package/dist/runtime/shared/openapi/registry.js.map +1 -1
- package/dist/runtime/shared/openapi/registry.tokens.js +4 -2
- package/dist/runtime/shared/openapi/registry.tokens.js.map +1 -1
- package/dist/runtime/subsystems/analytics/analytics.module.js +8 -117
- package/dist/runtime/subsystems/analytics/analytics.module.js.map +1 -1
- package/dist/runtime/subsystems/analytics/analytics.tokens.js +7 -8
- package/dist/runtime/subsystems/analytics/analytics.tokens.js.map +1 -1
- package/dist/runtime/subsystems/analytics/cube-backend.js +6 -71
- package/dist/runtime/subsystems/analytics/cube-backend.js.map +1 -1
- package/dist/runtime/subsystems/analytics/index.js +16 -117
- package/dist/runtime/subsystems/analytics/index.js.map +1 -1
- package/dist/runtime/subsystems/analytics/noop-backend.js +4 -21
- package/dist/runtime/subsystems/analytics/noop-backend.js.map +1 -1
- package/dist/runtime/subsystems/auth/auth-oauth-state.schema.js +4 -8
- package/dist/runtime/subsystems/auth/auth-oauth-state.schema.js.map +1 -1
- package/dist/runtime/subsystems/auth/auth.module.js +12 -359
- package/dist/runtime/subsystems/auth/auth.module.js.map +1 -1
- package/dist/runtime/subsystems/auth/auth.tokens.js +12 -13
- package/dist/runtime/subsystems/auth/auth.tokens.js.map +1 -1
- package/dist/runtime/subsystems/auth/backends/encryption-key/env.js +4 -49
- package/dist/runtime/subsystems/auth/backends/encryption-key/env.js.map +1 -1
- package/dist/runtime/subsystems/auth/backends/state-store.drizzle-backend.js +6 -64
- package/dist/runtime/subsystems/auth/backends/state-store.drizzle-backend.js.map +1 -1
- package/dist/runtime/subsystems/auth/backends/state-store.memory-backend.js +5 -47
- package/dist/runtime/subsystems/auth/backends/state-store.memory-backend.js.map +1 -1
- package/dist/runtime/subsystems/auth/controllers/auth.controller.js +5 -139
- package/dist/runtime/subsystems/auth/controllers/auth.controller.js.map +1 -1
- package/dist/runtime/subsystems/auth/index.js +53 -542
- package/dist/runtime/subsystems/auth/index.js.map +1 -1
- package/dist/runtime/subsystems/auth/middleware/requester-context.js +9 -65
- package/dist/runtime/subsystems/auth/middleware/requester-context.js.map +1 -1
- package/dist/runtime/subsystems/auth/protocols/oauth-state-store.js +4 -9
- package/dist/runtime/subsystems/auth/protocols/oauth-state-store.js.map +1 -1
- package/dist/runtime/subsystems/auth/runtime/connection-broken.error.js +4 -15
- package/dist/runtime/subsystems/auth/runtime/connection-broken.error.js.map +1 -1
- package/dist/runtime/subsystems/auth/runtime/oauth2-refresh.strategy.js +5 -104
- package/dist/runtime/subsystems/auth/runtime/oauth2-refresh.strategy.js.map +1 -1
- package/dist/runtime/subsystems/auth/runtime/session-expired.error.js +5 -16
- package/dist/runtime/subsystems/auth/runtime/session-expired.error.js.map +1 -1
- package/dist/runtime/subsystems/auth/runtime/with-auth-retry.js +5 -29
- package/dist/runtime/subsystems/auth/runtime/with-auth-retry.js.map +1 -1
- package/dist/runtime/subsystems/bridge/assert-tenant-id.js +5 -18
- package/dist/runtime/subsystems/bridge/assert-tenant-id.js.map +1 -1
- package/dist/runtime/subsystems/bridge/bridge-delivery-handler.d.ts +2 -2
- package/dist/runtime/subsystems/bridge/bridge-delivery-handler.js +12 -184
- package/dist/runtime/subsystems/bridge/bridge-delivery-handler.js.map +1 -1
- package/dist/runtime/subsystems/bridge/bridge-delivery.drizzle-backend.d.ts +1 -1
- package/dist/runtime/subsystems/bridge/bridge-delivery.drizzle-backend.js +10 -448
- package/dist/runtime/subsystems/bridge/bridge-delivery.drizzle-backend.js.map +1 -1
- package/dist/runtime/subsystems/bridge/bridge-delivery.memory-backend.d.ts +1 -1
- package/dist/runtime/subsystems/bridge/bridge-delivery.memory-backend.js +5 -126
- package/dist/runtime/subsystems/bridge/bridge-delivery.memory-backend.js.map +1 -1
- package/dist/runtime/subsystems/bridge/bridge-delivery.schema.js +6 -308
- package/dist/runtime/subsystems/bridge/bridge-delivery.schema.js.map +1 -1
- package/dist/runtime/subsystems/bridge/bridge-errors.js +6 -35
- package/dist/runtime/subsystems/bridge/bridge-errors.js.map +1 -1
- package/dist/runtime/subsystems/bridge/bridge-outbox-drain-hook.d.ts +1 -1
- package/dist/runtime/subsystems/bridge/bridge-outbox-drain-hook.js +14 -606
- package/dist/runtime/subsystems/bridge/bridge-outbox-drain-hook.js.map +1 -1
- package/dist/runtime/subsystems/bridge/bridge.module.d.ts +2 -2
- package/dist/runtime/subsystems/bridge/bridge.module.js +35 -3476
- package/dist/runtime/subsystems/bridge/bridge.module.js.map +1 -1
- package/dist/runtime/subsystems/bridge/bridge.protocol.d.ts +1 -1
- package/dist/runtime/subsystems/bridge/bridge.tokens.js +9 -7
- package/dist/runtime/subsystems/bridge/bridge.tokens.js.map +1 -1
- package/dist/runtime/subsystems/bridge/event-flow.service.d.ts +2 -2
- package/dist/runtime/subsystems/bridge/event-flow.service.js +11 -137
- package/dist/runtime/subsystems/bridge/event-flow.service.js.map +1 -1
- package/dist/runtime/subsystems/bridge/generated/registry.d.ts +1 -1
- package/dist/runtime/subsystems/bridge/generated/registry.js +4 -2
- package/dist/runtime/subsystems/bridge/generated/registry.js.map +1 -1
- package/dist/runtime/subsystems/bridge/index.d.ts +2 -2
- package/dist/runtime/subsystems/bridge/index.js +60 -3470
- package/dist/runtime/subsystems/bridge/index.js.map +1 -1
- package/dist/runtime/subsystems/bridge/reserved-pools.js +4 -6
- package/dist/runtime/subsystems/bridge/reserved-pools.js.map +1 -1
- package/dist/runtime/subsystems/cache/cache.drizzle-backend.js +10 -133
- package/dist/runtime/subsystems/cache/cache.drizzle-backend.js.map +1 -1
- package/dist/runtime/subsystems/cache/cache.memory-backend.js +6 -101
- package/dist/runtime/subsystems/cache/cache.memory-backend.js.map +1 -1
- package/dist/runtime/subsystems/cache/cache.module.js +10 -278
- package/dist/runtime/subsystems/cache/cache.module.js.map +1 -1
- package/dist/runtime/subsystems/cache/cache.schema.js +4 -14
- package/dist/runtime/subsystems/cache/cache.schema.js.map +1 -1
- package/dist/runtime/subsystems/cache/cache.tokens.js +6 -7
- package/dist/runtime/subsystems/cache/cache.tokens.js.map +1 -1
- package/dist/runtime/subsystems/cache/index.js +20 -278
- package/dist/runtime/subsystems/cache/index.js.map +1 -1
- package/dist/runtime/subsystems/events/domain-events.schema.js +3 -72
- package/dist/runtime/subsystems/events/domain-events.schema.js.map +1 -1
- package/dist/runtime/subsystems/events/event-bus.drizzle-backend.d.ts +1 -1
- package/dist/runtime/subsystems/events/event-bus.drizzle-backend.js +9 -413
- package/dist/runtime/subsystems/events/event-bus.drizzle-backend.js.map +1 -1
- package/dist/runtime/subsystems/events/event-bus.memory-backend.js +7 -235
- package/dist/runtime/subsystems/events/event-bus.memory-backend.js.map +1 -1
- package/dist/runtime/subsystems/events/event-bus.redis-backend.js +8 -20
- package/dist/runtime/subsystems/events/event-bus.redis-backend.js.map +1 -1
- package/dist/runtime/subsystems/events/event-keyset-cursor.js +8 -30
- package/dist/runtime/subsystems/events/event-keyset-cursor.js.map +1 -1
- package/dist/runtime/subsystems/events/event-read.protocol.js +2 -0
- package/dist/runtime/subsystems/events/event-read.protocol.js.map +1 -1
- package/dist/runtime/subsystems/events/event-registry.d.ts +77 -0
- package/dist/runtime/subsystems/events/event-registry.js +1 -0
- package/dist/runtime/subsystems/events/event-registry.js.map +1 -0
- package/dist/runtime/subsystems/events/events-errors.js +4 -11
- package/dist/runtime/subsystems/events/events-errors.js.map +1 -1
- package/dist/runtime/subsystems/events/events.module.js +15 -949
- package/dist/runtime/subsystems/events/events.module.js.map +1 -1
- package/dist/runtime/subsystems/events/events.tokens.js +10 -11
- package/dist/runtime/subsystems/events/events.tokens.js.map +1 -1
- package/dist/runtime/subsystems/events/generated/bus.js +9 -240
- package/dist/runtime/subsystems/events/generated/bus.js.map +1 -1
- package/dist/runtime/subsystems/events/generated/index.js +23 -240
- package/dist/runtime/subsystems/events/generated/index.js.map +1 -1
- package/dist/runtime/subsystems/events/generated/registry.js +5 -82
- package/dist/runtime/subsystems/events/generated/registry.js.map +1 -1
- package/dist/runtime/subsystems/events/generated/schemas.js +12 -52
- package/dist/runtime/subsystems/events/generated/schemas.js.map +1 -1
- package/dist/runtime/subsystems/events/generated/types.js +1 -0
- package/dist/runtime/subsystems/events/index.d.ts +1 -0
- package/dist/runtime/subsystems/events/index.js +32 -949
- package/dist/runtime/subsystems/events/index.js.map +1 -1
- package/dist/runtime/subsystems/index.d.ts +2 -2
- package/dist/runtime/subsystems/index.js +171 -5912
- package/dist/runtime/subsystems/index.js.map +1 -1
- package/dist/runtime/subsystems/integration/build-change-source.js +6 -178
- package/dist/runtime/subsystems/integration/build-change-source.js.map +1 -1
- package/dist/runtime/subsystems/integration/deep-equal.differ.js +4 -109
- package/dist/runtime/subsystems/integration/deep-equal.differ.js.map +1 -1
- package/dist/runtime/subsystems/integration/detection-config.schema.js +11 -78
- package/dist/runtime/subsystems/integration/detection-config.schema.js.map +1 -1
- package/dist/runtime/subsystems/integration/entity-change-source-registry.memory.js +5 -30
- package/dist/runtime/subsystems/integration/entity-change-source-registry.memory.js.map +1 -1
- package/dist/runtime/subsystems/integration/entity-change-source-registry.protocol.js +4 -9
- package/dist/runtime/subsystems/integration/entity-change-source-registry.protocol.js.map +1 -1
- package/dist/runtime/subsystems/integration/execute-integration.use-case.js +6 -239
- package/dist/runtime/subsystems/integration/execute-integration.use-case.js.map +1 -1
- package/dist/runtime/subsystems/integration/incremental-read.js +5 -144
- package/dist/runtime/subsystems/integration/incremental-read.js.map +1 -1
- package/dist/runtime/subsystems/integration/index.js +83 -1352
- package/dist/runtime/subsystems/integration/index.js.map +1 -1
- package/dist/runtime/subsystems/integration/integration-audit.schema.js +10 -155
- package/dist/runtime/subsystems/integration/integration-audit.schema.js.map +1 -1
- package/dist/runtime/subsystems/integration/integration-cursor-store.drizzle-backend.js +7 -270
- package/dist/runtime/subsystems/integration/integration-cursor-store.drizzle-backend.js.map +1 -1
- package/dist/runtime/subsystems/integration/integration-cursor-store.memory-backend.js +4 -65
- package/dist/runtime/subsystems/integration/integration-cursor-store.memory-backend.js.map +1 -1
- package/dist/runtime/subsystems/integration/integration-errors.js +5 -15
- package/dist/runtime/subsystems/integration/integration-errors.js.map +1 -1
- package/dist/runtime/subsystems/integration/integration-field-diff.protocol.js +5 -7
- package/dist/runtime/subsystems/integration/integration-field-diff.protocol.js.map +1 -1
- package/dist/runtime/subsystems/integration/integration-run-recorder.drizzle-backend.js +8 -303
- package/dist/runtime/subsystems/integration/integration-run-recorder.drizzle-backend.js.map +1 -1
- package/dist/runtime/subsystems/integration/integration-run-recorder.memory-backend.js +5 -125
- package/dist/runtime/subsystems/integration/integration-run-recorder.memory-backend.js.map +1 -1
- package/dist/runtime/subsystems/integration/integration.module.js +13 -700
- package/dist/runtime/subsystems/integration/integration.module.js.map +1 -1
- package/dist/runtime/subsystems/integration/integration.tokens.js +11 -9
- package/dist/runtime/subsystems/integration/integration.tokens.js.map +1 -1
- package/dist/runtime/subsystems/integration/loopback.middleware.js +4 -16
- package/dist/runtime/subsystems/integration/loopback.middleware.js.map +1 -1
- package/dist/runtime/subsystems/integration/poll-change-source.js +4 -89
- package/dist/runtime/subsystems/integration/poll-change-source.js.map +1 -1
- package/dist/runtime/subsystems/integration/webhook-change-source.js +4 -70
- package/dist/runtime/subsystems/integration/webhook-change-source.js.map +1 -1
- package/dist/runtime/subsystems/jobs/bullmq.config.js +9 -140
- package/dist/runtime/subsystems/jobs/bullmq.config.js.map +1 -1
- package/dist/runtime/subsystems/jobs/index.d.ts +2 -2
- package/dist/runtime/subsystems/jobs/index.js +88 -2691
- package/dist/runtime/subsystems/jobs/index.js.map +1 -1
- package/dist/runtime/subsystems/jobs/job-handler.base.d.ts +2 -2
- package/dist/runtime/subsystems/jobs/job-handler.base.js +10 -49
- package/dist/runtime/subsystems/jobs/job-handler.base.js.map +1 -1
- package/dist/runtime/subsystems/jobs/job-orchestration.schema.js +13 -152
- package/dist/runtime/subsystems/jobs/job-orchestration.schema.js.map +1 -1
- package/dist/runtime/subsystems/jobs/job-orchestrator.bullmq-backend.d.ts +2 -2
- package/dist/runtime/subsystems/jobs/job-orchestrator.bullmq-backend.js +36 -699
- package/dist/runtime/subsystems/jobs/job-orchestrator.bullmq-backend.js.map +1 -1
- package/dist/runtime/subsystems/jobs/job-orchestrator.drizzle-backend.d.ts +2 -2
- package/dist/runtime/subsystems/jobs/job-orchestrator.drizzle-backend.js +10 -564
- package/dist/runtime/subsystems/jobs/job-orchestrator.drizzle-backend.js.map +1 -1
- package/dist/runtime/subsystems/jobs/job-orchestrator.memory-backend.d.ts +2 -2
- package/dist/runtime/subsystems/jobs/job-orchestrator.memory-backend.js +10 -824
- package/dist/runtime/subsystems/jobs/job-orchestrator.memory-backend.js.map +1 -1
- package/dist/runtime/subsystems/jobs/job-orchestrator.protocol.d.ts +2 -2
- package/dist/runtime/subsystems/jobs/job-run-keyset-cursor.d.ts +2 -2
- package/dist/runtime/subsystems/jobs/job-run-keyset-cursor.js +9 -51
- package/dist/runtime/subsystems/jobs/job-run-keyset-cursor.js.map +1 -1
- package/dist/runtime/subsystems/jobs/job-run-service.drizzle-backend.d.ts +2 -2
- package/dist/runtime/subsystems/jobs/job-run-service.drizzle-backend.js +9 -416
- package/dist/runtime/subsystems/jobs/job-run-service.drizzle-backend.js.map +1 -1
- package/dist/runtime/subsystems/jobs/job-run-service.memory-backend.d.ts +2 -2
- package/dist/runtime/subsystems/jobs/job-run-service.memory-backend.js +9 -290
- package/dist/runtime/subsystems/jobs/job-run-service.memory-backend.js.map +1 -1
- package/dist/runtime/subsystems/jobs/job-run-service.protocol.d.ts +2 -2
- package/dist/runtime/subsystems/jobs/job-step-service.drizzle-backend.js +5 -213
- package/dist/runtime/subsystems/jobs/job-step-service.drizzle-backend.js.map +1 -1
- package/dist/runtime/subsystems/jobs/job-step-service.memory-backend.js +5 -131
- package/dist/runtime/subsystems/jobs/job-step-service.memory-backend.js.map +1 -1
- package/dist/runtime/subsystems/jobs/job-worker.bullmq-backend.d.ts +2 -2
- package/dist/runtime/subsystems/jobs/job-worker.bullmq-backend.js +9 -175
- package/dist/runtime/subsystems/jobs/job-worker.bullmq-backend.js.map +1 -1
- package/dist/runtime/subsystems/jobs/job-worker.d.ts +2 -2
- package/dist/runtime/subsystems/jobs/job-worker.js +14 -613
- package/dist/runtime/subsystems/jobs/job-worker.js.map +1 -1
- package/dist/runtime/subsystems/jobs/job-worker.module.d.ts +2 -2
- package/dist/runtime/subsystems/jobs/job-worker.module.js +23 -2647
- package/dist/runtime/subsystems/jobs/job-worker.module.js.map +1 -1
- package/dist/runtime/subsystems/jobs/jobs-domain.module.js +19 -1897
- package/dist/runtime/subsystems/jobs/jobs-domain.module.js.map +1 -1
- package/dist/runtime/subsystems/jobs/jobs-domain.tokens.js +8 -9
- package/dist/runtime/subsystems/jobs/jobs-domain.tokens.js.map +1 -1
- package/dist/runtime/subsystems/jobs/jobs-errors.d.ts +2 -2
- package/dist/runtime/subsystems/jobs/jobs-errors.js +10 -78
- package/dist/runtime/subsystems/jobs/jobs-errors.js.map +1 -1
- package/dist/runtime/subsystems/jobs/memory-job-store.js +4 -15
- package/dist/runtime/subsystems/jobs/memory-job-store.js.map +1 -1
- package/dist/runtime/subsystems/jobs/pool-config.loader.js +9 -124
- package/dist/runtime/subsystems/jobs/pool-config.loader.js.map +1 -1
- package/dist/runtime/subsystems/observability/index.d.ts +2 -2
- package/dist/runtime/subsystems/observability/index.js +21 -310
- package/dist/runtime/subsystems/observability/index.js.map +1 -1
- package/dist/runtime/subsystems/observability/observability-errors.js +4 -9
- package/dist/runtime/subsystems/observability/observability-errors.js.map +1 -1
- package/dist/runtime/subsystems/observability/observability.module.js +11 -300
- package/dist/runtime/subsystems/observability/observability.module.js.map +1 -1
- package/dist/runtime/subsystems/observability/observability.protocol.d.ts +2 -2
- package/dist/runtime/subsystems/observability/observability.service.d.ts +2 -2
- package/dist/runtime/subsystems/observability/observability.service.js +9 -197
- package/dist/runtime/subsystems/observability/observability.service.js.map +1 -1
- package/dist/runtime/subsystems/observability/observability.tokens.js +5 -3
- package/dist/runtime/subsystems/observability/observability.tokens.js.map +1 -1
- package/dist/runtime/subsystems/observability/reporters/bridge-metrics.reporter.d.ts +2 -2
- package/dist/runtime/subsystems/observability/reporters/bridge-metrics.reporter.js +4 -84
- package/dist/runtime/subsystems/observability/reporters/bridge-metrics.reporter.js.map +1 -1
- package/dist/runtime/subsystems/observability/reporters/index.d.ts +2 -2
- package/dist/runtime/subsystems/observability/reporters/index.js +5 -84
- package/dist/runtime/subsystems/observability/reporters/index.js.map +1 -1
- package/dist/runtime/subsystems/storage/index.js +15 -200
- package/dist/runtime/subsystems/storage/index.js.map +1 -1
- package/dist/runtime/subsystems/storage/storage.local-backend.js +4 -103
- package/dist/runtime/subsystems/storage/storage.local-backend.js.map +1 -1
- package/dist/runtime/subsystems/storage/storage.memory-backend.js +5 -68
- package/dist/runtime/subsystems/storage/storage.memory-backend.js.map +1 -1
- package/dist/runtime/subsystems/storage/storage.module.js +8 -200
- package/dist/runtime/subsystems/storage/storage.module.js.map +1 -1
- package/dist/runtime/subsystems/storage/storage.tokens.js +5 -6
- package/dist/runtime/subsystems/storage/storage.tokens.js.map +1 -1
- package/dist/runtime/subsystems/storage/storage.utils.js +4 -14
- package/dist/runtime/subsystems/storage/storage.utils.js.map +1 -1
- package/dist/runtime/subsystems/token-key.js +5 -3
- package/dist/runtime/subsystems/token-key.js.map +1 -1
- package/dist/src/cli/index.js +653 -5444
- package/dist/src/cli/index.js.map +1 -1
- package/dist/src/index.js +68 -4170
- package/dist/src/index.js.map +1 -1
- package/package.json +1 -1
- package/runtime/subsystems/bridge/bridge-delivery-handler.ts +1 -1
- package/runtime/subsystems/bridge/bridge-outbox-drain-hook.ts +45 -22
- package/runtime/subsystems/bridge/bridge.protocol.ts +1 -1
- package/runtime/subsystems/bridge/event-flow.service.ts +1 -1
- package/runtime/subsystems/events/event-registry.ts +77 -0
- package/runtime/subsystems/events/index.ts +12 -0
- package/runtime/subsystems/jobs/job-handler.base.ts +1 -1
- package/runtime/subsystems/jobs/job-worker.ts +17 -11
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../runtime/subsystems/auth/middleware/requester-context.ts"],"sourcesContent":["/**\n * RequesterContext boundary install — bridges authentication to ambient\n * tenant scoping.\n *\n * This is the missing link that makes `BaseRepository`'s ambient scoping\n * (see `base-classes/tenant-context.ts`) actually engage on HTTP requests:\n * it reads the requester off each request (via the consumer-bound\n * `IUserContext`) and runs the rest of the request inside `withRequester(...)`,\n * so every downstream repository read/write is automatically scoped — no\n * threaded `userId`.\n *\n * ## Wiring (one line in your bootstrap)\n *\n * In `main.ts`, after `NestFactory.create`:\n *\n * ```ts\n * import { installRequesterContext } from './shared/subsystems/auth/middleware/requester-context';\n * const app = await NestFactory.create(AppModule);\n * installRequesterContext(app); // no-op + warn if AUTH_USER_CONTEXT is unbound\n * ```\n *\n * `installRequesterContext` resolves `AUTH_USER_CONTEXT` from the root DI\n * container (so it sees the binding the consumer provides in AppModule) and\n * registers a global Express middleware. Pairs with Swagger's `@ApiBearerAuth`\n * \"Authorize\" button: paste a token there and every request it sends now flows\n * through this boundary into a scoped repository call.\n *\n * ## Trust + failure model\n *\n * - The middleware TRUSTS whatever `IUserContext` returns — authentication and\n * authorization (validating the token, deciding which scope a requester may\n * claim) are the `IUserContext` implementation's job, exactly as for a\n * hand-threaded `userId`.\n * - When the requester cannot be resolved (no/invalid credentials — e.g. a\n * public route, or the OAuth callback itself), the request proceeds WITHOUT\n * an ambient context (`onUnresolved: 'unscoped'`, the default). A\n * `userTracking` repo in lenient mode then runs unscoped; in strict mode it\n * throws downstream — which is correct: unauthenticated callers must not\n * reach scoped data. Set `onUnresolved: 'reject'` to fail the request at the\n * boundary instead.\n */\nimport type { INestApplication } from '@nestjs/common';\nimport {\n withRequester,\n type RequesterContext,\n} from '../../../base-classes/tenant-context';\nimport { AUTH_USER_CONTEXT } from '../auth.tokens';\nimport type { IUserContext } from '../protocols/user-context';\n\n/** Minimal Express-style middleware signature (avoids an `express` dep). */\ntype NextFn = (err?: unknown) => void;\ntype RequestHandler = (req: unknown, res: unknown, next: NextFn) => void;\n\nexport interface RequesterContextOptions {\n /**\n * What to do when `IUserContext` cannot resolve a requester (throws, or\n * returns no `userId`).\n * - `'unscoped'` (default): proceed without a context — public routes work;\n * scoped repos run unscoped (lenient) or throw downstream (strict).\n * - `'reject'`: fail the request at the boundary (`next(error)`).\n */\n onUnresolved?: 'unscoped' | 'reject';\n}\n\n/**\n * Resolve the ambient context for a request: prefer the richer\n * `resolveRequester` (org/superuser), else derive plain `'user'` scope from\n * `getCurrentUserId`. Returns `undefined` when no requester can be determined.\n */\nexport async function resolveRequesterContext(\n userContext: IUserContext,\n req: unknown,\n): Promise<RequesterContext | undefined> {\n if (typeof userContext.resolveRequester === 'function') {\n const ctx = await userContext.resolveRequester(req);\n return ctx?.userId ? ctx : undefined;\n }\n const userId = await userContext.getCurrentUserId(req);\n return userId ? { userId, organizationId: null } : undefined;\n}\n\n/**\n * Build the global middleware. Runs the remainder of the request inside\n * `withRequester(...)` so the ambient context propagates through every `await`\n * to downstream repositories.\n */\nexport function makeRequesterContextMiddleware(\n userContext: IUserContext,\n options: RequesterContextOptions = {},\n): RequestHandler {\n const onUnresolved = options.onUnresolved ?? 'unscoped';\n return (req, _res, next) => {\n resolveRequesterContext(userContext, req).then(\n (ctx) => {\n if (!ctx) {\n next();\n return;\n }\n // als.run executes its callback synchronously; Express dispatches the\n // rest of the pipeline inside next(), so all downstream handlers (and\n // their awaits) inherit this context.\n withRequester(ctx, async () => {\n next();\n });\n },\n (err) => {\n if (onUnresolved === 'reject') {\n next(err);\n return;\n }\n next();\n },\n );\n };\n}\n\n/**\n * Register the requester-context boundary on a Nest app. Resolves\n * `AUTH_USER_CONTEXT` from the root container (so it sees the consumer's\n * AppModule binding) and installs the global middleware. No-ops with a warning\n * when `AUTH_USER_CONTEXT` is not bound, so calling it unconditionally in\n * bootstrap is safe.\n */\nexport function installRequesterContext(\n app: INestApplication,\n options: RequesterContextOptions = {},\n): void {\n const userContext = app.get<IUserContext>(AUTH_USER_CONTEXT, {\n strict: false,\n });\n if (!userContext) {\n // eslint-disable-next-line no-console\n console.warn(\n '[auth] installRequesterContext: AUTH_USER_CONTEXT is not bound — ' +\n 'request scoping NOT installed. Provide an IUserContext under ' +\n 'AUTH_USER_CONTEXT in your AppModule to enable ambient tenant scoping.',\n );\n return;\n }\n app.use(makeRequesterContextMiddleware(userContext, options));\n}\n"],"mappings":";;;;;;;;AAqEA,eAAsB,wBACpB,aACA,KACuC;AACvC,MAAI,OAAO,YAAY,qBAAqB,YAAY;AACtD,UAAM,MAAM,MAAM,YAAY,iBAAiB,GAAG;AAClD,WAAO,KAAK,SAAS,MAAM;AAAA,EAC7B;AACA,QAAM,SAAS,MAAM,YAAY,iBAAiB,GAAG;AACrD,SAAO,SAAS,EAAE,QAAQ,gBAAgB,KAAK,IAAI;AACrD;AAOO,SAAS,+BACd,aACA,UAAmC,CAAC,GACpB;AAChB,QAAM,eAAe,QAAQ,gBAAgB;AAC7C,SAAO,CAAC,KAAK,MAAM,SAAS;AAC1B,4BAAwB,aAAa,GAAG,EAAE;AAAA,MACxC,CAAC,QAAQ;AACP,YAAI,CAAC,KAAK;AACR,eAAK;AACL;AAAA,QACF;AAIA,sBAAc,KAAK,YAAY;AAC7B,eAAK;AAAA,QACP,CAAC;AAAA,MACH;AAAA,MACA,CAAC,QAAQ;AACP,YAAI,iBAAiB,UAAU;AAC7B,eAAK,GAAG;AACR;AAAA,QACF;AACA,aAAK;AAAA,MACP;AAAA,IACF;AAAA,EACF;AACF;AASO,SAAS,wBACd,KACA,UAAmC,CAAC,GAC9B;AACN,QAAM,cAAc,IAAI,IAAkB,mBAAmB;AAAA,IAC3D,QAAQ;AAAA,EACV,CAAC;AACD,MAAI,CAAC,aAAa;AAEhB,YAAQ;AAAA,MACN;AAAA,IAGF;AACA;AAAA,EACF;AACA,MAAI,IAAI,+BAA+B,aAAa,OAAO,CAAC;AAC9D;","names":[]}
|
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
import {
|
|
2
|
+
BaseRepository
|
|
3
|
+
} from "./chunk-J6KZS54B.js";
|
|
4
|
+
|
|
5
|
+
// runtime/base-classes/integrated-entity-repository.ts
|
|
6
|
+
import { and, eq, inArray } from "drizzle-orm";
|
|
7
|
+
var IntegratedEntityRepository = class extends BaseRepository {
|
|
8
|
+
/**
|
|
9
|
+
* Find a single entity by its external CRM identifier.
|
|
10
|
+
*/
|
|
11
|
+
async findByExternalId(externalId) {
|
|
12
|
+
const rows = await this.baseQuery().where(eq(this.table["externalId"], externalId)).limit(1);
|
|
13
|
+
return rows[0] ?? null;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Find multiple entities by external CRM identifiers.
|
|
17
|
+
*/
|
|
18
|
+
async findManyByExternalIds(externalIds) {
|
|
19
|
+
if (externalIds.length === 0) return [];
|
|
20
|
+
const rows = await this.baseQuery().where(inArray(this.table["externalId"], externalIds));
|
|
21
|
+
return rows;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Find all entities owned by a specific user.
|
|
25
|
+
*/
|
|
26
|
+
async findAllByUserId(userId) {
|
|
27
|
+
const rows = await this.baseQuery().where(eq(this.table["userId"], userId));
|
|
28
|
+
return rows;
|
|
29
|
+
}
|
|
30
|
+
// ==========================================================================
|
|
31
|
+
// Inbound integration (#374) — canonical→Drizzle write + provider-scoped FK
|
|
32
|
+
// resolution + EAV dual-write seam, all inside a SINGLE transaction.
|
|
33
|
+
// Driven entirely by `this.integrationConfig`; the per-entity shape lives there.
|
|
34
|
+
// ==========================================================================
|
|
35
|
+
/**
|
|
36
|
+
* Upsert ONE entity by its `(provider, externalId)` identity, in a single
|
|
37
|
+
* transaction:
|
|
38
|
+
* 1. resolve each `integrationConfig.fkResolvers` FK (provider-scoped). Strict
|
|
39
|
+
* resolvers throw on unresolved; non-strict leave the column null.
|
|
40
|
+
* 2. insert-or-update the canonical columns via `onConflictDoUpdate` on the
|
|
41
|
+
* `conflictTarget`. Resolved FKs are only written into `set` when
|
|
42
|
+
* non-null this run (no-clobber).
|
|
43
|
+
* 3. EAV dual-write of `write.fields` via `writeCustomFields` when
|
|
44
|
+
* `integrationConfig.eav` and the bag is non-empty (same tx).
|
|
45
|
+
*
|
|
46
|
+
* Idempotent: a second call with the same identity updates in place. Returns
|
|
47
|
+
* the canonical projection (so the orchestrator records `local_id`).
|
|
48
|
+
*
|
|
49
|
+
* @param write canonical fields + parent external ids + custom-field bag
|
|
50
|
+
* @param provider adapter/provider label persisted + used to scope lookups
|
|
51
|
+
* @param tx optional outer transaction; when omitted we open our own
|
|
52
|
+
*/
|
|
53
|
+
async integrationUpsertOne(write, provider, tx) {
|
|
54
|
+
const cfg = this.integrationConfig;
|
|
55
|
+
const w = write;
|
|
56
|
+
const run = async (db) => {
|
|
57
|
+
const resolvedFks = {};
|
|
58
|
+
for (const fk of cfg.fkResolvers) {
|
|
59
|
+
resolvedFks[fk.column] = await this.resolveFk(db, fk, w[fk.writeKey], provider);
|
|
60
|
+
}
|
|
61
|
+
const now = /* @__PURE__ */ new Date();
|
|
62
|
+
const copyThrough = {};
|
|
63
|
+
for (const col of cfg.writeColumns) copyThrough[col] = w[col];
|
|
64
|
+
const values = {
|
|
65
|
+
externalId: w["externalId"],
|
|
66
|
+
provider,
|
|
67
|
+
...copyThrough,
|
|
68
|
+
...resolvedFks,
|
|
69
|
+
...this.behaviors.timestamps ? { updatedAt: now } : {}
|
|
70
|
+
};
|
|
71
|
+
const set = {
|
|
72
|
+
...copyThrough,
|
|
73
|
+
...this.behaviors.timestamps ? { updatedAt: now } : {}
|
|
74
|
+
};
|
|
75
|
+
for (const fk of cfg.fkResolvers) {
|
|
76
|
+
if (resolvedFks[fk.column] !== null) set[fk.column] = resolvedFks[fk.column];
|
|
77
|
+
}
|
|
78
|
+
const rows = await db.insert(this.table).values(values).onConflictDoUpdate({
|
|
79
|
+
target: cfg.conflictTarget.map((c) => this.table[c]),
|
|
80
|
+
set
|
|
81
|
+
}).returning();
|
|
82
|
+
const saved = rows[0];
|
|
83
|
+
const fields = w["fields"];
|
|
84
|
+
if (cfg.eav && fields && Object.keys(fields).length > 0) {
|
|
85
|
+
await this.writeCustomFields(
|
|
86
|
+
db,
|
|
87
|
+
saved["id"],
|
|
88
|
+
w["userId"],
|
|
89
|
+
fields
|
|
90
|
+
);
|
|
91
|
+
}
|
|
92
|
+
return this.toProjection(saved);
|
|
93
|
+
};
|
|
94
|
+
return tx ? run(tx) : this.db.transaction((t) => run(t));
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Canonical-projected lookup by external id (differ-ready). Returns `null`
|
|
98
|
+
* when no local row exists. Provider-scoped so a HubSpot id can't match a
|
|
99
|
+
* Salesforce row.
|
|
100
|
+
*/
|
|
101
|
+
async findByExternalIdProjected(externalId, provider) {
|
|
102
|
+
const rows = await this.db.select().from(this.table).where(
|
|
103
|
+
and(
|
|
104
|
+
eq(this.table["provider"], provider),
|
|
105
|
+
eq(this.table["externalId"], externalId)
|
|
106
|
+
)
|
|
107
|
+
).limit(1);
|
|
108
|
+
const row = rows[0];
|
|
109
|
+
return row ? this.toProjection(row) : null;
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Integration "delete" by external id, provider-scoped. When `softDelete: true`,
|
|
113
|
+
* sets `deletedAt`. When `softDelete: false`, tombstone-by-clearing: null out
|
|
114
|
+
* `external_id`/`provider` so the row no longer matches future inbound
|
|
115
|
+
* changes while preserving local-id references. Returns `{ id }` or `null`.
|
|
116
|
+
*/
|
|
117
|
+
async softDeleteByExternalId(externalId, provider, tx) {
|
|
118
|
+
const db = this.runner(tx);
|
|
119
|
+
const set = this.integrationConfig.softDelete ? { deletedAt: /* @__PURE__ */ new Date(), updatedAt: /* @__PURE__ */ new Date() } : { externalId: null, provider: null, updatedAt: /* @__PURE__ */ new Date() };
|
|
120
|
+
const rows = await db.update(this.table).set(set).where(
|
|
121
|
+
and(
|
|
122
|
+
eq(this.table["provider"], provider),
|
|
123
|
+
eq(this.table["externalId"], externalId)
|
|
124
|
+
)
|
|
125
|
+
).returning({ id: this.table["id"] });
|
|
126
|
+
return rows[0] ? { id: rows[0].id } : null;
|
|
127
|
+
}
|
|
128
|
+
/**
|
|
129
|
+
* Batch integration upsert — concretizes the former abstract stub. Delegates to
|
|
130
|
+
* `integrationUpsertOne` per input inside one transaction. Inputs are raw partial
|
|
131
|
+
* rows: provider is read from each input's own `provider` column; rows
|
|
132
|
+
* missing `externalId`/`provider` are skipped.
|
|
133
|
+
*/
|
|
134
|
+
async integrationUpsert(inputs) {
|
|
135
|
+
if (inputs.length === 0) return [];
|
|
136
|
+
return this.db.transaction(async (tx) => {
|
|
137
|
+
const out = [];
|
|
138
|
+
for (const input of inputs) {
|
|
139
|
+
const rec = input;
|
|
140
|
+
if (!rec["externalId"] || !rec["provider"]) continue;
|
|
141
|
+
const proj = await this.integrationUpsertOne(
|
|
142
|
+
input,
|
|
143
|
+
rec["provider"],
|
|
144
|
+
tx
|
|
145
|
+
);
|
|
146
|
+
const id = proj["id"];
|
|
147
|
+
const row = await tx.select().from(this.table).where(eq(this.table["id"], id)).limit(1);
|
|
148
|
+
out.push(row[0]);
|
|
149
|
+
}
|
|
150
|
+
return out;
|
|
151
|
+
});
|
|
152
|
+
}
|
|
153
|
+
/**
|
|
154
|
+
* Project a raw row to the canonical differ shape — a generic pick over
|
|
155
|
+
* `integrationConfig.projectionColumns`. Override only for synthesized projections
|
|
156
|
+
* (e.g. junctions); entities use this verbatim.
|
|
157
|
+
*/
|
|
158
|
+
toProjection(row) {
|
|
159
|
+
const r = row;
|
|
160
|
+
const out = {};
|
|
161
|
+
for (const col of this.integrationConfig.projectionColumns) out[col] = r[col];
|
|
162
|
+
return out;
|
|
163
|
+
}
|
|
164
|
+
/**
|
|
165
|
+
* EAV dual-write seam (#374, live path lands in #124). No-op by default;
|
|
166
|
+
* `eav: true` entities emit a concrete override that injects
|
|
167
|
+
* `FieldValueService` and delegates to `upsertFieldsTransactional` so the
|
|
168
|
+
* dual-write joins the same tx (`db`). Kept as an explicit hook so the base
|
|
169
|
+
* stays portable (the FieldValueService dependency is eav-only).
|
|
170
|
+
*/
|
|
171
|
+
async writeCustomFields(_db, _entityId, _userId, _fields) {
|
|
172
|
+
}
|
|
173
|
+
/**
|
|
174
|
+
* Resolve one FK from a parent external id (provider-scoped). `self` resolves
|
|
175
|
+
* against `this.table`. Strict resolvers throw when unresolved; non-strict
|
|
176
|
+
* return null. A null/absent write value short-circuits to null.
|
|
177
|
+
*/
|
|
178
|
+
async resolveFk(db, fk, rawExternalId, provider) {
|
|
179
|
+
const parentExternalId = rawExternalId;
|
|
180
|
+
if (!parentExternalId) {
|
|
181
|
+
if (fk.strict) {
|
|
182
|
+
throw new Error(
|
|
183
|
+
`${this.constructor.name}.integrationUpsertOne: missing required parent external id for '${fk.column}' (writeKey '${fk.writeKey}')`
|
|
184
|
+
);
|
|
185
|
+
}
|
|
186
|
+
return null;
|
|
187
|
+
}
|
|
188
|
+
const refTable = fk.refTable === "self" ? this.table : fk.refTable;
|
|
189
|
+
const rows = await db.select({ id: refTable["id"] }).from(refTable).where(
|
|
190
|
+
and(
|
|
191
|
+
eq(refTable["provider"], provider),
|
|
192
|
+
eq(refTable["externalId"], parentExternalId)
|
|
193
|
+
)
|
|
194
|
+
).limit(1);
|
|
195
|
+
const id = rows[0]?.id ?? null;
|
|
196
|
+
if (id === null && fk.strict) {
|
|
197
|
+
throw new Error(
|
|
198
|
+
`${this.constructor.name}.integrationUpsertOne: unresolved parent '${parentExternalId}' (provider '${provider}') for '${fk.column}' \u2014 parent not integrated yet`
|
|
199
|
+
);
|
|
200
|
+
}
|
|
201
|
+
return id;
|
|
202
|
+
}
|
|
203
|
+
/**
|
|
204
|
+
* Find entities visible to a user (ownership + sharing rules).
|
|
205
|
+
* Concrete repositories must implement with visibility logic.
|
|
206
|
+
*/
|
|
207
|
+
async findVisibleByUserId(_userId) {
|
|
208
|
+
throw new Error("findVisibleByUserId not implemented \u2014 override in concrete repository");
|
|
209
|
+
}
|
|
210
|
+
};
|
|
211
|
+
|
|
212
|
+
export {
|
|
213
|
+
IntegratedEntityRepository
|
|
214
|
+
};
|
|
215
|
+
//# sourceMappingURL=chunk-OTDN3OUQ.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../runtime/base-classes/integrated-entity-repository.ts"],"sourcesContent":["/**\n * IntegratedEntityRepository<TEntity, TIntegrationWrite, TIntegrationProjection>\n *\n * Family-specific base for Integrated entities (contacts, accounts, opportunities).\n * Adds external ID lookups, user-scoped queries, and the generic inbound-integration\n * write surface (canonical→Drizzle upsert + provider-scoped FK resolution +\n * EAV dual-write seam), driven by the concrete repo's `integrationConfig`.\n *\n * The type params default so pre-existing single-param subclasses keep\n * compiling; `pattern: Integrated` repos declare all three plus `integrationConfig`.\n */\nimport { and, eq, inArray } from 'drizzle-orm';\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nimport type { PgTableWithColumns } from 'drizzle-orm/pg-core';\nimport type { DrizzleTx } from '../types/drizzle';\nimport { BaseRepository } from './base-repository';\nimport type { IntegrationUpsertConfig, IntegrationFkResolver } from './integration-upsert-config';\n\nexport abstract class IntegratedEntityRepository<\n TEntity,\n TIntegrationWrite = Partial<TEntity>,\n TIntegrationProjection = TEntity,\n> extends BaseRepository<TEntity> {\n /**\n * Declarative integration write surface. Concrete (`pattern: Integrated`) repositories\n * declare this — the template emits it from the entity's fields + FKs.\n */\n protected abstract readonly integrationConfig: IntegrationUpsertConfig;\n\n /**\n * Find a single entity by its external CRM identifier.\n */\n async findByExternalId(externalId: string): Promise<TEntity | null> {\n const rows = await this.baseQuery()\n .where(eq(this.table['externalId'], externalId))\n .limit(1);\n return (rows[0] as TEntity) ?? null;\n }\n\n /**\n * Find multiple entities by external CRM identifiers.\n */\n async findManyByExternalIds(externalIds: string[]): Promise<TEntity[]> {\n if (externalIds.length === 0) return [];\n const rows = await this.baseQuery()\n .where(inArray(this.table['externalId'], externalIds));\n return rows as TEntity[];\n }\n\n /**\n * Find all entities owned by a specific user.\n */\n async findAllByUserId(userId: string): Promise<TEntity[]> {\n const rows = await this.baseQuery()\n .where(eq(this.table['userId'], userId));\n return rows as TEntity[];\n }\n\n // ==========================================================================\n // Inbound integration (#374) — canonical→Drizzle write + provider-scoped FK\n // resolution + EAV dual-write seam, all inside a SINGLE transaction.\n // Driven entirely by `this.integrationConfig`; the per-entity shape lives there.\n // ==========================================================================\n\n /**\n * Upsert ONE entity by its `(provider, externalId)` identity, in a single\n * transaction:\n * 1. resolve each `integrationConfig.fkResolvers` FK (provider-scoped). Strict\n * resolvers throw on unresolved; non-strict leave the column null.\n * 2. insert-or-update the canonical columns via `onConflictDoUpdate` on the\n * `conflictTarget`. Resolved FKs are only written into `set` when\n * non-null this run (no-clobber).\n * 3. EAV dual-write of `write.fields` via `writeCustomFields` when\n * `integrationConfig.eav` and the bag is non-empty (same tx).\n *\n * Idempotent: a second call with the same identity updates in place. Returns\n * the canonical projection (so the orchestrator records `local_id`).\n *\n * @param write canonical fields + parent external ids + custom-field bag\n * @param provider adapter/provider label persisted + used to scope lookups\n * @param tx optional outer transaction; when omitted we open our own\n */\n async integrationUpsertOne(\n write: TIntegrationWrite,\n provider: string,\n tx?: DrizzleTx,\n ): Promise<TIntegrationProjection> {\n const cfg = this.integrationConfig;\n const w = write as Record<string, unknown>;\n\n const run = async (db: DrizzleTx): Promise<TIntegrationProjection> => {\n // 1. FK resolution (provider-scoped). Strict → throw; else opportunistic null.\n const resolvedFks: Record<string, string | null> = {};\n for (const fk of cfg.fkResolvers) {\n resolvedFks[fk.column] = await this.resolveFk(db, fk, w[fk.writeKey], provider);\n }\n\n // 2. Canonical → Drizzle insert-or-update by the conflict target.\n const now = new Date();\n const copyThrough: Record<string, unknown> = {};\n for (const col of cfg.writeColumns) copyThrough[col] = w[col];\n\n const values: Record<string, unknown> = {\n externalId: w['externalId'],\n provider,\n ...copyThrough,\n ...resolvedFks,\n ...(this.behaviors.timestamps ? { updatedAt: now } : {}),\n };\n\n // `set` excludes the identity (externalId/provider). Resolved FKs are\n // only written when non-null this run — never clobber a previously\n // resolved parent with null on a later run that dropped the ref.\n const set: Record<string, unknown> = {\n ...copyThrough,\n ...(this.behaviors.timestamps ? { updatedAt: now } : {}),\n };\n for (const fk of cfg.fkResolvers) {\n if (resolvedFks[fk.column] !== null) set[fk.column] = resolvedFks[fk.column];\n }\n\n const rows = await db\n .insert(this.table)\n .values(values as never)\n .onConflictDoUpdate({\n target: cfg.conflictTarget.map((c: string) => this.table[c]),\n set: set as never,\n })\n .returning();\n\n const saved = rows[0] as Record<string, unknown>;\n\n // 3. EAV dual-write seam — same tx. No-op unless the entity opts in.\n const fields = w['fields'] as Record<string, unknown> | undefined;\n if (cfg.eav && fields && Object.keys(fields).length > 0) {\n await this.writeCustomFields(\n db,\n saved['id'] as string,\n w['userId'] as string,\n fields,\n );\n }\n\n return this.toProjection(saved as TEntity);\n };\n\n return tx ? run(tx) : this.db.transaction((t) => run(t));\n }\n\n /**\n * Canonical-projected lookup by external id (differ-ready). Returns `null`\n * when no local row exists. Provider-scoped so a HubSpot id can't match a\n * Salesforce row.\n */\n async findByExternalIdProjected(\n externalId: string,\n provider: string,\n ): Promise<TIntegrationProjection | null> {\n const rows = await this.db\n .select()\n .from(this.table)\n .where(\n and(\n eq(this.table['provider'], provider),\n eq(this.table['externalId'], externalId),\n ),\n )\n .limit(1);\n const row = rows[0] as TEntity | undefined;\n return row ? this.toProjection(row) : null;\n }\n\n /**\n * Integration \"delete\" by external id, provider-scoped. When `softDelete: true`,\n * sets `deletedAt`. When `softDelete: false`, tombstone-by-clearing: null out\n * `external_id`/`provider` so the row no longer matches future inbound\n * changes while preserving local-id references. Returns `{ id }` or `null`.\n */\n async softDeleteByExternalId(\n externalId: string,\n provider: string,\n tx?: DrizzleTx,\n ): Promise<{ id: string } | null> {\n const db = this.runner(tx);\n const set = this.integrationConfig.softDelete\n ? { deletedAt: new Date(), updatedAt: new Date() }\n : { externalId: null, provider: null, updatedAt: new Date() };\n const rows = await db\n .update(this.table)\n .set(set as never)\n .where(\n and(\n eq(this.table['provider'], provider),\n eq(this.table['externalId'], externalId),\n ),\n )\n .returning({ id: this.table['id'] });\n return rows[0] ? { id: rows[0].id as string } : null;\n }\n\n /**\n * Batch integration upsert — concretizes the former abstract stub. Delegates to\n * `integrationUpsertOne` per input inside one transaction. Inputs are raw partial\n * rows: provider is read from each input's own `provider` column; rows\n * missing `externalId`/`provider` are skipped.\n */\n async integrationUpsert(inputs: Array<Partial<TEntity>>): Promise<TEntity[]> {\n if (inputs.length === 0) return [];\n return this.db.transaction(async (tx) => {\n const out: TEntity[] = [];\n for (const input of inputs) {\n const rec = input as Record<string, unknown>;\n if (!rec['externalId'] || !rec['provider']) continue;\n const proj = await this.integrationUpsertOne(\n input as unknown as TIntegrationWrite,\n rec['provider'] as string,\n tx,\n );\n const id = (proj as Record<string, unknown>)['id'] as string;\n const row = await tx\n .select()\n .from(this.table)\n .where(eq(this.table['id'], id))\n .limit(1);\n out.push(row[0] as TEntity);\n }\n return out;\n });\n }\n\n /**\n * Project a raw row to the canonical differ shape — a generic pick over\n * `integrationConfig.projectionColumns`. Override only for synthesized projections\n * (e.g. junctions); entities use this verbatim.\n */\n protected toProjection(row: TEntity): TIntegrationProjection {\n const r = row as Record<string, unknown>;\n const out: Record<string, unknown> = {};\n for (const col of this.integrationConfig.projectionColumns) out[col] = r[col];\n return out as TIntegrationProjection;\n }\n\n /**\n * EAV dual-write seam (#374, live path lands in #124). No-op by default;\n * `eav: true` entities emit a concrete override that injects\n * `FieldValueService` and delegates to `upsertFieldsTransactional` so the\n * dual-write joins the same tx (`db`). Kept as an explicit hook so the base\n * stays portable (the FieldValueService dependency is eav-only).\n */\n protected async writeCustomFields(\n _db: DrizzleTx,\n _entityId: string,\n _userId: string,\n _fields: Record<string, unknown>,\n ): Promise<void> {\n // Intentionally empty until the entity opts into EAV.\n }\n\n /**\n * Resolve one FK from a parent external id (provider-scoped). `self` resolves\n * against `this.table`. Strict resolvers throw when unresolved; non-strict\n * return null. A null/absent write value short-circuits to null.\n */\n private async resolveFk(\n db: DrizzleTx,\n fk: IntegrationFkResolver,\n rawExternalId: unknown,\n provider: string,\n ): Promise<string | null> {\n const parentExternalId = rawExternalId as string | null | undefined;\n if (!parentExternalId) {\n if (fk.strict) {\n throw new Error(\n `${this.constructor.name}.integrationUpsertOne: missing required parent ` +\n `external id for '${fk.column}' (writeKey '${fk.writeKey}')`,\n );\n }\n return null;\n }\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const refTable: PgTableWithColumns<any> =\n fk.refTable === 'self' ? this.table : fk.refTable;\n const rows = await db\n .select({ id: refTable['id'] })\n .from(refTable)\n .where(\n and(\n eq(refTable['provider'], provider),\n eq(refTable['externalId'], parentExternalId),\n ),\n )\n .limit(1);\n const id = (rows[0]?.id as string | undefined) ?? null;\n if (id === null && fk.strict) {\n throw new Error(\n `${this.constructor.name}.integrationUpsertOne: unresolved parent ` +\n `'${parentExternalId}' (provider '${provider}') for '${fk.column}' — ` +\n `parent not integrated yet`,\n );\n }\n return id;\n }\n\n /**\n * Find entities visible to a user (ownership + sharing rules).\n * Concrete repositories must implement with visibility logic.\n */\n async findVisibleByUserId(_userId: string): Promise<TEntity[]> {\n throw new Error('findVisibleByUserId not implemented — override in concrete repository');\n }\n}\n"],"mappings":"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","names":[]}
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
import {
|
|
2
|
+
bridgeRegistry
|
|
3
|
+
} from "./chunk-5A432NZJ.js";
|
|
4
|
+
import {
|
|
5
|
+
BridgeOutboxDrainHook
|
|
6
|
+
} from "./chunk-L7BNNRGI.js";
|
|
7
|
+
import {
|
|
8
|
+
EventFlowService
|
|
9
|
+
} from "./chunk-32BMMV4H.js";
|
|
10
|
+
import {
|
|
11
|
+
BRIDGE_RESERVED_POOLS
|
|
12
|
+
} from "./chunk-EDKJU5BO.js";
|
|
13
|
+
import {
|
|
14
|
+
BridgeDeliveryHandler
|
|
15
|
+
} from "./chunk-YTN6BKWA.js";
|
|
16
|
+
import {
|
|
17
|
+
DrizzleBridgeDeliveryRepo
|
|
18
|
+
} from "./chunk-K2I6XIK5.js";
|
|
19
|
+
import {
|
|
20
|
+
MemoryBridgeDeliveryRepo
|
|
21
|
+
} from "./chunk-4DOJBQTP.js";
|
|
22
|
+
import {
|
|
23
|
+
BridgeReservedPoolsNotPolledError
|
|
24
|
+
} from "./chunk-NXXDZ6ZF.js";
|
|
25
|
+
import {
|
|
26
|
+
JOB_WORKER_MODULE_OPTIONS
|
|
27
|
+
} from "./chunk-WPXNN6QS.js";
|
|
28
|
+
import {
|
|
29
|
+
BRIDGE_DELIVERY_REPO,
|
|
30
|
+
BRIDGE_MODULE_OPTIONS,
|
|
31
|
+
BRIDGE_MULTI_TENANT,
|
|
32
|
+
BRIDGE_OUTBOX_DRAIN_HOOK,
|
|
33
|
+
BRIDGE_REGISTRY,
|
|
34
|
+
EVENT_FLOW
|
|
35
|
+
} from "./chunk-4LH67P4U.js";
|
|
36
|
+
import {
|
|
37
|
+
__decorateClass,
|
|
38
|
+
__decorateParam
|
|
39
|
+
} from "./chunk-2E224ZSN.js";
|
|
40
|
+
|
|
41
|
+
// runtime/subsystems/bridge/bridge.module.ts
|
|
42
|
+
import {
|
|
43
|
+
Inject,
|
|
44
|
+
Module,
|
|
45
|
+
Optional
|
|
46
|
+
} from "@nestjs/common";
|
|
47
|
+
var BridgeModule = class {
|
|
48
|
+
/**
|
|
49
|
+
* `JOB_WORKER_MODULE_OPTIONS` is declared `@Optional()` so unit tests
|
|
50
|
+
* that mount `BridgeModule` alone (no `JobWorkerModule`) boot
|
|
51
|
+
* cleanly — the boot-time check skips when the token is undefined.
|
|
52
|
+
*/
|
|
53
|
+
constructor(workerOpts) {
|
|
54
|
+
this.workerOpts = workerOpts;
|
|
55
|
+
}
|
|
56
|
+
workerOpts;
|
|
57
|
+
static forRoot(opts) {
|
|
58
|
+
const repoProvider = opts.backend === "memory" ? { provide: BRIDGE_DELIVERY_REPO, useClass: MemoryBridgeDeliveryRepo } : { provide: BRIDGE_DELIVERY_REPO, useClass: DrizzleBridgeDeliveryRepo };
|
|
59
|
+
return {
|
|
60
|
+
module: BridgeModule,
|
|
61
|
+
global: true,
|
|
62
|
+
// BridgeModule consumes EVENT_BUS / JOB_ORCHESTRATOR / DRIZZLE
|
|
63
|
+
// from sibling subsystems via DI; no `imports` needed here. The
|
|
64
|
+
// consumer is responsible for wiring EventsModule + JobsDomainModule
|
|
65
|
+
// (or JobWorkerModule, which transitively imports the latter)
|
|
66
|
+
// BEFORE BridgeModule.
|
|
67
|
+
providers: [
|
|
68
|
+
{ provide: BRIDGE_MODULE_OPTIONS, useValue: opts },
|
|
69
|
+
{ provide: BRIDGE_MULTI_TENANT, useValue: opts.multiTenant ?? false },
|
|
70
|
+
// Package mode threads the consumer's generated registry through
|
|
71
|
+
// `opts.registry`; vendored mode omits it and we fall back to the
|
|
72
|
+
// bundled `./generated/registry` (which IS the consumer's generated
|
|
73
|
+
// file in a vendored tree). See `BridgeModuleOptions.registry`.
|
|
74
|
+
{ provide: BRIDGE_REGISTRY, useValue: opts.registry ?? bridgeRegistry },
|
|
75
|
+
repoProvider,
|
|
76
|
+
// Drain hook — always wired; `DrizzleEventBus` consumes it via
|
|
77
|
+
// `@Optional()`, so non-bridge mounts simply see `undefined`.
|
|
78
|
+
{ provide: BRIDGE_OUTBOX_DRAIN_HOOK, useClass: BridgeOutboxDrainHook },
|
|
79
|
+
// Facade — class provider + token alias.
|
|
80
|
+
EventFlowService,
|
|
81
|
+
{ provide: EVENT_FLOW, useExisting: EventFlowService },
|
|
82
|
+
// Framework handler — provider so DI can construct it. The
|
|
83
|
+
// `@JobHandler` decorator already auto-registers it in
|
|
84
|
+
// `JOB_HANDLER_REGISTRY` at module-load time, and its `jobs`
|
|
85
|
+
// row is upserted at `JobWorkerModule.onModuleInit`. We just
|
|
86
|
+
// need the class instantiated as a Nest provider so its DI
|
|
87
|
+
// deps (BRIDGE_DELIVERY_REPO, JOB_ORCHESTRATOR, EVENT_BUS,
|
|
88
|
+
// BRIDGE_REGISTRY, BRIDGE_MULTI_TENANT) resolve.
|
|
89
|
+
BridgeDeliveryHandler
|
|
90
|
+
],
|
|
91
|
+
exports: [
|
|
92
|
+
EVENT_FLOW,
|
|
93
|
+
BRIDGE_DELIVERY_REPO,
|
|
94
|
+
BRIDGE_REGISTRY,
|
|
95
|
+
BRIDGE_MULTI_TENANT,
|
|
96
|
+
BRIDGE_MODULE_OPTIONS,
|
|
97
|
+
BRIDGE_OUTBOX_DRAIN_HOOK
|
|
98
|
+
]
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
async onModuleInit() {
|
|
102
|
+
if (!this.workerOpts) return;
|
|
103
|
+
if (this.workerOpts.allPools) return;
|
|
104
|
+
const activePools = this.workerOpts.pools ?? [];
|
|
105
|
+
const missing = BRIDGE_RESERVED_POOLS.filter(
|
|
106
|
+
(p) => !activePools.includes(p)
|
|
107
|
+
);
|
|
108
|
+
if (missing.length > 0) {
|
|
109
|
+
throw new BridgeReservedPoolsNotPolledError(missing);
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
};
|
|
113
|
+
BridgeModule = __decorateClass([
|
|
114
|
+
Module({}),
|
|
115
|
+
__decorateParam(0, Optional()),
|
|
116
|
+
__decorateParam(0, Inject(JOB_WORKER_MODULE_OPTIONS))
|
|
117
|
+
], BridgeModule);
|
|
118
|
+
|
|
119
|
+
export {
|
|
120
|
+
BridgeModule
|
|
121
|
+
};
|
|
122
|
+
//# sourceMappingURL=chunk-OZZJDRGW.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../runtime/subsystems/bridge/bridge.module.ts"],"sourcesContent":["/**\n * BridgeModule — `DynamicModule.forRoot({ backend, multiTenant })`\n * factory that wires the entire bridge subsystem (BRIDGE-8, ADR-023\n * Phase 2).\n *\n * The bridge is the formalized seam between events (ADR-024) and jobs\n * (ADR-022). It is owned by neither subsystem and consumes their tokens\n * via DI. `BridgeModule` is the *combiner* — neither `EventsModule` nor\n * `JobsDomainModule` know about it.\n *\n * Consumer wiring (must be imported AFTER `EventsModule`,\n * `JobsDomainModule`, and `JobWorkerModule`):\n * ```ts\n * @Module({\n * imports: [\n * EventsModule.forRoot({ backend: 'drizzle' }),\n * JobWorkerModule.forRoot({\n * mode: 'embedded',\n * backend: 'drizzle',\n * pools: ['interactive', 'batch', ...BRIDGE_RESERVED_POOLS],\n * }),\n * BridgeModule.forRoot({ backend: 'drizzle', multiTenant: false }),\n * ],\n * })\n * class AppModule {}\n * ```\n *\n * Boot-time check: `onModuleInit` inspects `JobWorkerModule`'s active\n * pools and throws `BridgeReservedPoolsNotPolledError` when any of the\n * three reserved bridge pools isn't being polled. Converts the\n * \"wrappers sit pending forever\" footgun into a fail-fast.\n *\n * Handler registration: ONE `@JobHandler('@framework/bridge_delivery',\n * ...)` decorator on `BridgeDeliveryHandler` auto-registers it in\n * `JOB_HANDLER_REGISTRY` at module-load time. We declare the class as a\n * Nest provider here so DI resolves its constructor deps; per-direction\n * routing happens via `job_run.pool='events_<direction>'` set by\n * `BridgeOutboxDrainHook` (BRIDGE-4) — workers polling each reserved\n * pool independently claim wrappers from their own pool and dispatch to\n * the same handler class. The reserved-pool validator exemption\n * (BRIDGE-5) lets the framework handler legitimately target a reserved\n * pool.\n */\nimport {\n Inject,\n Module,\n Optional,\n type DynamicModule,\n type OnModuleInit,\n type Provider,\n} from '@nestjs/common';\n\nimport {\n JOB_WORKER_MODULE_OPTIONS,\n type JobWorkerModuleOptions,\n} from '../jobs/job-worker.module';\n\nimport {\n BRIDGE_DELIVERY_REPO,\n BRIDGE_MODULE_OPTIONS,\n BRIDGE_MULTI_TENANT,\n BRIDGE_OUTBOX_DRAIN_HOOK,\n BRIDGE_REGISTRY,\n EVENT_FLOW,\n} from './bridge.tokens';\nimport { BridgeReservedPoolsNotPolledError } from './bridge-errors';\nimport { MemoryBridgeDeliveryRepo } from './bridge-delivery.memory-backend';\nimport { DrizzleBridgeDeliveryRepo } from './bridge-delivery.drizzle-backend';\nimport { BridgeOutboxDrainHook } from './bridge-outbox-drain-hook';\nimport { EventFlowService } from './event-flow.service';\nimport { BridgeDeliveryHandler } from './bridge-delivery-handler';\nimport { bridgeRegistry } from './generated/registry';\nimport type { BridgeRegistry } from './bridge.protocol';\nimport { BRIDGE_RESERVED_POOLS } from './reserved-pools';\n\nexport interface BridgeModuleOptions {\n /**\n * `'memory'` for unit tests (no Postgres), `'drizzle'` for production.\n * Switches `BRIDGE_DELIVERY_REPO` between\n * `MemoryBridgeDeliveryRepo` and `DrizzleBridgeDeliveryRepo`.\n */\n backend: 'memory' | 'drizzle';\n /**\n * Multi-tenancy opt-in. When `true`, the three enforcement sites\n * (`EventFlowService.publishAndStart`, `BridgeDeliveryHandler.run`,\n * `DrizzleBridgeDeliveryRepo.insertDelivery`) throw\n * `MissingTenantIdError` when `tenantId === undefined`. Explicit\n * `null` always passes (cross-tenant work). Defaults to `false`.\n */\n multiTenant?: boolean;\n /**\n * The codegen-emitted `Record<EventTypeName, BridgeTriggerEntry[]>` that\n * drives outbox-drain trigger lookup (BRIDGE-4) and the facade's Case B\n * dedup (BRIDGE-7).\n *\n * **Package mode (ADR-037).** When the runtime is imported from\n * `@pattern-stack/codegen` (not vendored), the bundled\n * `./generated/registry` is a frozen empty placeholder (`{}`) — a\n * consumer's `@JobHandler.triggers` are scanned into a registry that lives\n * in THEIR `src/generated/bridge-registry.ts`, which the package can't\n * import. The generated subsystem barrel therefore threads that registry in\n * here: `BridgeModule.forRoot({ ..., registry: bridgeRegistry })`. Omitted\n * (vendored mode / tests) ⇒ falls back to the bundled `./generated/registry`,\n * which in vendored mode IS the consumer's freshly-generated file.\n *\n * Without this, package-mode consumers' triggers never bind and the bridge\n * routes nothing (the \"wrappers sit pending\" footgun's silent twin —\n * nothing is ever enqueued in the first place).\n */\n registry?: BridgeRegistry;\n}\n\n@Module({})\nexport class BridgeModule implements OnModuleInit {\n static forRoot(opts: BridgeModuleOptions): DynamicModule {\n const repoProvider: Provider =\n opts.backend === 'memory'\n ? { provide: BRIDGE_DELIVERY_REPO, useClass: MemoryBridgeDeliveryRepo }\n : { provide: BRIDGE_DELIVERY_REPO, useClass: DrizzleBridgeDeliveryRepo };\n\n return {\n module: BridgeModule,\n global: true,\n // BridgeModule consumes EVENT_BUS / JOB_ORCHESTRATOR / DRIZZLE\n // from sibling subsystems via DI; no `imports` needed here. The\n // consumer is responsible for wiring EventsModule + JobsDomainModule\n // (or JobWorkerModule, which transitively imports the latter)\n // BEFORE BridgeModule.\n providers: [\n { provide: BRIDGE_MODULE_OPTIONS, useValue: opts },\n { provide: BRIDGE_MULTI_TENANT, useValue: opts.multiTenant ?? false },\n // Package mode threads the consumer's generated registry through\n // `opts.registry`; vendored mode omits it and we fall back to the\n // bundled `./generated/registry` (which IS the consumer's generated\n // file in a vendored tree). See `BridgeModuleOptions.registry`.\n { provide: BRIDGE_REGISTRY, useValue: opts.registry ?? bridgeRegistry },\n repoProvider,\n // Drain hook — always wired; `DrizzleEventBus` consumes it via\n // `@Optional()`, so non-bridge mounts simply see `undefined`.\n { provide: BRIDGE_OUTBOX_DRAIN_HOOK, useClass: BridgeOutboxDrainHook },\n // Facade — class provider + token alias.\n EventFlowService,\n { provide: EVENT_FLOW, useExisting: EventFlowService },\n // Framework handler — provider so DI can construct it. The\n // `@JobHandler` decorator already auto-registers it in\n // `JOB_HANDLER_REGISTRY` at module-load time, and its `jobs`\n // row is upserted at `JobWorkerModule.onModuleInit`. We just\n // need the class instantiated as a Nest provider so its DI\n // deps (BRIDGE_DELIVERY_REPO, JOB_ORCHESTRATOR, EVENT_BUS,\n // BRIDGE_REGISTRY, BRIDGE_MULTI_TENANT) resolve.\n BridgeDeliveryHandler,\n ],\n exports: [\n EVENT_FLOW,\n BRIDGE_DELIVERY_REPO,\n BRIDGE_REGISTRY,\n BRIDGE_MULTI_TENANT,\n BRIDGE_MODULE_OPTIONS,\n BRIDGE_OUTBOX_DRAIN_HOOK,\n ],\n };\n }\n\n /**\n * `JOB_WORKER_MODULE_OPTIONS` is declared `@Optional()` so unit tests\n * that mount `BridgeModule` alone (no `JobWorkerModule`) boot\n * cleanly — the boot-time check skips when the token is undefined.\n */\n constructor(\n @Optional()\n @Inject(JOB_WORKER_MODULE_OPTIONS)\n private readonly workerOpts?: JobWorkerModuleOptions,\n ) {}\n\n async onModuleInit(): Promise<void> {\n if (!this.workerOpts) return;\n // BULLMQ-1 Phase 1 — `allPools: true` activates every pool (reserved\n // `events_*` included), so the reserved-pool guarantee holds by\n // construction. Short-circuit pass without inspecting the (typically\n // omitted) explicit `pools` list.\n if (this.workerOpts.allPools) return;\n const activePools = this.workerOpts.pools ?? [];\n const missing = BRIDGE_RESERVED_POOLS.filter(\n (p) => !activePools.includes(p),\n );\n if (missing.length > 0) {\n throw new BridgeReservedPoolsNotPolledError(missing);\n }\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA2CA;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,OAIK;AA+DA,IAAM,eAAN,MAA2C;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAuDhD,YAGmB,YACjB;AADiB;AAAA,EAChB;AAAA,EADgB;AAAA,EAzDnB,OAAO,QAAQ,MAA0C;AACvD,UAAM,eACJ,KAAK,YAAY,WACb,EAAE,SAAS,sBAAsB,UAAU,yBAAyB,IACpE,EAAE,SAAS,sBAAsB,UAAU,0BAA0B;AAE3E,WAAO;AAAA,MACL,QAAQ;AAAA,MACR,QAAQ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAMR,WAAW;AAAA,QACT,EAAE,SAAS,uBAAuB,UAAU,KAAK;AAAA,QACjD,EAAE,SAAS,qBAAqB,UAAU,KAAK,eAAe,MAAM;AAAA;AAAA;AAAA;AAAA;AAAA,QAKpE,EAAE,SAAS,iBAAiB,UAAU,KAAK,YAAY,eAAe;AAAA,QACtE;AAAA;AAAA;AAAA,QAGA,EAAE,SAAS,0BAA0B,UAAU,sBAAsB;AAAA;AAAA,QAErE;AAAA,QACA,EAAE,SAAS,YAAY,aAAa,iBAAiB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,QAQrD;AAAA,MACF;AAAA,MACA,SAAS;AAAA,QACP;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAAA,EAaA,MAAM,eAA8B;AAClC,QAAI,CAAC,KAAK,WAAY;AAKtB,QAAI,KAAK,WAAW,SAAU;AAC9B,UAAM,cAAc,KAAK,WAAW,SAAS,CAAC;AAC9C,UAAM,UAAU,sBAAsB;AAAA,MACpC,CAAC,MAAM,CAAC,YAAY,SAAS,CAAC;AAAA,IAChC;AACA,QAAI,QAAQ,SAAS,GAAG;AACtB,YAAM,IAAI,kCAAkC,OAAO;AAAA,IACrD;AAAA,EACF;AACF;AA5Ea,eAAN;AAAA,EADN,OAAO,CAAC,CAAC;AAAA,EAyDL,4BAAS;AAAA,EACT,0BAAO,yBAAyB;AAAA,GAzDxB;","names":[]}
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
import {
|
|
2
|
+
MemoryJobStore
|
|
3
|
+
} from "./chunk-SNQ3TOWP.js";
|
|
4
|
+
import {
|
|
5
|
+
__decorateClass,
|
|
6
|
+
__decorateParam
|
|
7
|
+
} from "./chunk-2E224ZSN.js";
|
|
8
|
+
|
|
9
|
+
// runtime/subsystems/jobs/job-step-service.memory-backend.ts
|
|
10
|
+
import { randomUUID } from "crypto";
|
|
11
|
+
import { Inject, Injectable } from "@nestjs/common";
|
|
12
|
+
var MemoryJobStepService = class {
|
|
13
|
+
// ADR-037 (package-mode DI): explicit `@Inject(MemoryJobStore)` — the
|
|
14
|
+
// published bundle carries no `design:paramtypes`, so a by-type inject
|
|
15
|
+
// would resolve to `undefined` in package mode.
|
|
16
|
+
constructor(store) {
|
|
17
|
+
this.store = store;
|
|
18
|
+
}
|
|
19
|
+
store;
|
|
20
|
+
async findStep(runId, stepId) {
|
|
21
|
+
const rows = this.store.steps.get(runId);
|
|
22
|
+
if (!rows) return null;
|
|
23
|
+
const match = rows.find(
|
|
24
|
+
(r) => r.stepId === stepId && r.status === "completed"
|
|
25
|
+
);
|
|
26
|
+
return match ?? null;
|
|
27
|
+
}
|
|
28
|
+
async recordStep(input) {
|
|
29
|
+
const rows = this.getOrCreateRows(input.jobRunId);
|
|
30
|
+
const existingIdx = rows.findIndex((r) => r.stepId === input.stepId);
|
|
31
|
+
const normalisedInput = input.input ?? null;
|
|
32
|
+
const normalisedOutput = input.output ?? null;
|
|
33
|
+
if (existingIdx >= 0) {
|
|
34
|
+
const prev = rows[existingIdx];
|
|
35
|
+
const next = {
|
|
36
|
+
...prev,
|
|
37
|
+
status: input.status,
|
|
38
|
+
input: normalisedInput ?? prev.input,
|
|
39
|
+
output: normalisedOutput ?? prev.output,
|
|
40
|
+
error: input.error ?? prev.error,
|
|
41
|
+
attempts: input.attempts ?? prev.attempts,
|
|
42
|
+
startedAt: input.startedAt ?? prev.startedAt,
|
|
43
|
+
finishedAt: input.finishedAt ?? prev.finishedAt
|
|
44
|
+
};
|
|
45
|
+
rows[existingIdx] = next;
|
|
46
|
+
return next;
|
|
47
|
+
}
|
|
48
|
+
const seq = input.seq ?? this.nextSeq(rows);
|
|
49
|
+
const row = {
|
|
50
|
+
id: randomUUID(),
|
|
51
|
+
jobRunId: input.jobRunId,
|
|
52
|
+
stepId: input.stepId,
|
|
53
|
+
kind: input.kind,
|
|
54
|
+
seq,
|
|
55
|
+
status: input.status,
|
|
56
|
+
input: normalisedInput,
|
|
57
|
+
output: normalisedOutput,
|
|
58
|
+
error: input.error ?? null,
|
|
59
|
+
attempts: input.attempts ?? 0,
|
|
60
|
+
startedAt: input.startedAt ?? null,
|
|
61
|
+
finishedAt: input.finishedAt ?? null
|
|
62
|
+
};
|
|
63
|
+
rows.push(row);
|
|
64
|
+
return row;
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Replay helper — wipe every step row for a run. Mirrors the `scratch`
|
|
68
|
+
* replay mode of the Drizzle backend (`DELETE FROM job_step WHERE job_run_id = …`).
|
|
69
|
+
*/
|
|
70
|
+
clearStepsForRun(runId) {
|
|
71
|
+
this.store.steps.delete(runId);
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Remove every non-`completed` row for the run. Memoized (`completed`)
|
|
75
|
+
* rows are preserved — this is the `last_checkpoint` / `last_step`
|
|
76
|
+
* semantics the Drizzle backend implements via
|
|
77
|
+
* `DELETE … WHERE status != 'completed'`. Both replay modes route here
|
|
78
|
+
* (Phase 1 collapses `last_step` onto this behaviour; see JOB-3 notes).
|
|
79
|
+
*/
|
|
80
|
+
clearIncompleteSteps(runId) {
|
|
81
|
+
const rows = this.store.steps.get(runId);
|
|
82
|
+
if (!rows) return;
|
|
83
|
+
const kept = rows.filter((r) => r.status === "completed");
|
|
84
|
+
if (kept.length === 0) {
|
|
85
|
+
this.store.steps.delete(runId);
|
|
86
|
+
} else {
|
|
87
|
+
this.store.steps.set(runId, kept);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
getOrCreateRows(runId) {
|
|
91
|
+
let rows = this.store.steps.get(runId);
|
|
92
|
+
if (!rows) {
|
|
93
|
+
rows = [];
|
|
94
|
+
this.store.steps.set(runId, rows);
|
|
95
|
+
}
|
|
96
|
+
return rows;
|
|
97
|
+
}
|
|
98
|
+
nextSeq(rows) {
|
|
99
|
+
let max = 0;
|
|
100
|
+
for (const r of rows) {
|
|
101
|
+
if (r.seq > max) max = r.seq;
|
|
102
|
+
}
|
|
103
|
+
return max + 1;
|
|
104
|
+
}
|
|
105
|
+
};
|
|
106
|
+
MemoryJobStepService = __decorateClass([
|
|
107
|
+
Injectable(),
|
|
108
|
+
__decorateParam(0, Inject(MemoryJobStore))
|
|
109
|
+
], MemoryJobStepService);
|
|
110
|
+
|
|
111
|
+
export {
|
|
112
|
+
MemoryJobStepService
|
|
113
|
+
};
|
|
114
|
+
//# sourceMappingURL=chunk-PNZSGAB2.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../runtime/subsystems/jobs/job-step-service.memory-backend.ts"],"sourcesContent":["/**\n * MemoryJobStepService — in-memory implementation of `IJobStepService`\n * (ADR-022, JOB-4).\n *\n * Mirrors `DrizzleJobStepService` but against plain Maps. `findStep` only\n * returns `completed` rows (memoization cache hit); anything non-completed\n * is invisible so the ctx.step fn re-runs on replay / retry exactly like\n * the Drizzle backend (which deletes non-completed rows on replay).\n */\nimport { randomUUID } from 'node:crypto';\nimport { Inject, Injectable } from '@nestjs/common';\nimport type { JobStepRow } from './job-orchestration.schema';\nimport type {\n IJobStepService,\n JobStep,\n RecordStepInput,\n} from './job-step-service.protocol';\nimport { MemoryJobStore } from './memory-job-store';\n\n@Injectable()\nexport class MemoryJobStepService implements IJobStepService {\n // ADR-037 (package-mode DI): explicit `@Inject(MemoryJobStore)` — the\n // published bundle carries no `design:paramtypes`, so a by-type inject\n // would resolve to `undefined` in package mode.\n constructor(\n @Inject(MemoryJobStore) private readonly store: MemoryJobStore,\n ) {}\n\n async findStep(runId: string, stepId: string): Promise<JobStep | null> {\n const rows = this.store.steps.get(runId);\n if (!rows) return null;\n const match = rows.find(\n (r) => r.stepId === stepId && r.status === 'completed',\n );\n return (match ?? null) as JobStep | null;\n }\n\n async recordStep(input: RecordStepInput): Promise<JobStep> {\n const rows = this.getOrCreateRows(input.jobRunId);\n const existingIdx = rows.findIndex((r) => r.stepId === input.stepId);\n\n const normalisedInput =\n (input.input ?? null) as Record<string, unknown> | null;\n const normalisedOutput =\n (input.output ?? null) as Record<string, unknown> | null;\n\n if (existingIdx >= 0) {\n const prev = rows[existingIdx]!;\n const next: JobStepRow = {\n ...prev,\n status: input.status,\n input: normalisedInput ?? prev.input,\n output: normalisedOutput ?? prev.output,\n error: input.error ?? prev.error,\n attempts: input.attempts ?? prev.attempts,\n startedAt: input.startedAt ?? prev.startedAt,\n finishedAt: input.finishedAt ?? prev.finishedAt,\n };\n rows[existingIdx] = next;\n return next as JobStep;\n }\n\n const seq = input.seq ?? this.nextSeq(rows);\n const row: JobStepRow = {\n id: randomUUID(),\n jobRunId: input.jobRunId,\n stepId: input.stepId,\n kind: input.kind,\n seq,\n status: input.status,\n input: normalisedInput,\n output: normalisedOutput,\n error: input.error ?? null,\n attempts: input.attempts ?? 0,\n startedAt: input.startedAt ?? null,\n finishedAt: input.finishedAt ?? null,\n };\n rows.push(row);\n return row as JobStep;\n }\n\n /**\n * Replay helper — wipe every step row for a run. Mirrors the `scratch`\n * replay mode of the Drizzle backend (`DELETE FROM job_step WHERE job_run_id = …`).\n */\n clearStepsForRun(runId: string): void {\n this.store.steps.delete(runId);\n }\n\n /**\n * Remove every non-`completed` row for the run. Memoized (`completed`)\n * rows are preserved — this is the `last_checkpoint` / `last_step`\n * semantics the Drizzle backend implements via\n * `DELETE … WHERE status != 'completed'`. Both replay modes route here\n * (Phase 1 collapses `last_step` onto this behaviour; see JOB-3 notes).\n */\n clearIncompleteSteps(runId: string): void {\n const rows = this.store.steps.get(runId);\n if (!rows) return;\n const kept = rows.filter((r) => r.status === 'completed');\n if (kept.length === 0) {\n this.store.steps.delete(runId);\n } else {\n this.store.steps.set(runId, kept);\n }\n }\n\n private getOrCreateRows(runId: string): JobStepRow[] {\n let rows = this.store.steps.get(runId);\n if (!rows) {\n rows = [];\n this.store.steps.set(runId, rows);\n }\n return rows;\n }\n\n private nextSeq(rows: JobStepRow[]): number {\n let max = 0;\n for (const r of rows) {\n if (r.seq > max) max = r.seq;\n }\n return max + 1;\n }\n}\n"],"mappings":";;;;;;;;;AASA,SAAS,kBAAkB;AAC3B,SAAS,QAAQ,kBAAkB;AAU5B,IAAM,uBAAN,MAAsD;AAAA;AAAA;AAAA;AAAA,EAI3D,YAC2C,OACzC;AADyC;AAAA,EACxC;AAAA,EADwC;AAAA,EAG3C,MAAM,SAAS,OAAe,QAAyC;AACrE,UAAM,OAAO,KAAK,MAAM,MAAM,IAAI,KAAK;AACvC,QAAI,CAAC,KAAM,QAAO;AAClB,UAAM,QAAQ,KAAK;AAAA,MACjB,CAAC,MAAM,EAAE,WAAW,UAAU,EAAE,WAAW;AAAA,IAC7C;AACA,WAAQ,SAAS;AAAA,EACnB;AAAA,EAEA,MAAM,WAAW,OAA0C;AACzD,UAAM,OAAO,KAAK,gBAAgB,MAAM,QAAQ;AAChD,UAAM,cAAc,KAAK,UAAU,CAAC,MAAM,EAAE,WAAW,MAAM,MAAM;AAEnE,UAAM,kBACH,MAAM,SAAS;AAClB,UAAM,mBACH,MAAM,UAAU;AAEnB,QAAI,eAAe,GAAG;AACpB,YAAM,OAAO,KAAK,WAAW;AAC7B,YAAM,OAAmB;AAAA,QACvB,GAAG;AAAA,QACH,QAAQ,MAAM;AAAA,QACd,OAAO,mBAAmB,KAAK;AAAA,QAC/B,QAAQ,oBAAoB,KAAK;AAAA,QACjC,OAAO,MAAM,SAAS,KAAK;AAAA,QAC3B,UAAU,MAAM,YAAY,KAAK;AAAA,QACjC,WAAW,MAAM,aAAa,KAAK;AAAA,QACnC,YAAY,MAAM,cAAc,KAAK;AAAA,MACvC;AACA,WAAK,WAAW,IAAI;AACpB,aAAO;AAAA,IACT;AAEA,UAAM,MAAM,MAAM,OAAO,KAAK,QAAQ,IAAI;AAC1C,UAAM,MAAkB;AAAA,MACtB,IAAI,WAAW;AAAA,MACf,UAAU,MAAM;AAAA,MAChB,QAAQ,MAAM;AAAA,MACd,MAAM,MAAM;AAAA,MACZ;AAAA,MACA,QAAQ,MAAM;AAAA,MACd,OAAO;AAAA,MACP,QAAQ;AAAA,MACR,OAAO,MAAM,SAAS;AAAA,MACtB,UAAU,MAAM,YAAY;AAAA,MAC5B,WAAW,MAAM,aAAa;AAAA,MAC9B,YAAY,MAAM,cAAc;AAAA,IAClC;AACA,SAAK,KAAK,GAAG;AACb,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,iBAAiB,OAAqB;AACpC,SAAK,MAAM,MAAM,OAAO,KAAK;AAAA,EAC/B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,qBAAqB,OAAqB;AACxC,UAAM,OAAO,KAAK,MAAM,MAAM,IAAI,KAAK;AACvC,QAAI,CAAC,KAAM;AACX,UAAM,OAAO,KAAK,OAAO,CAAC,MAAM,EAAE,WAAW,WAAW;AACxD,QAAI,KAAK,WAAW,GAAG;AACrB,WAAK,MAAM,MAAM,OAAO,KAAK;AAAA,IAC/B,OAAO;AACL,WAAK,MAAM,MAAM,IAAI,OAAO,IAAI;AAAA,IAClC;AAAA,EACF;AAAA,EAEQ,gBAAgB,OAA6B;AACnD,QAAI,OAAO,KAAK,MAAM,MAAM,IAAI,KAAK;AACrC,QAAI,CAAC,MAAM;AACT,aAAO,CAAC;AACR,WAAK,MAAM,MAAM,IAAI,OAAO,IAAI;AAAA,IAClC;AACA,WAAO;AAAA,EACT;AAAA,EAEQ,QAAQ,MAA4B;AAC1C,QAAI,MAAM;AACV,eAAW,KAAK,MAAM;AACpB,UAAI,EAAE,MAAM,IAAK,OAAM,EAAE;AAAA,IAC3B;AACA,WAAO,MAAM;AAAA,EACf;AACF;AAvGa,uBAAN;AAAA,EADN,WAAW;AAAA,EAMP,0BAAO,cAAc;AAAA,GALb;","names":[]}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
// runtime/subsystems/integration/loopback.middleware.ts
|
|
2
|
+
function createLoopbackMiddleware(store) {
|
|
3
|
+
return (next) => {
|
|
4
|
+
return async function* (subscription, cursor) {
|
|
5
|
+
for await (const change of next(subscription, cursor)) {
|
|
6
|
+
const isEcho = await store.isEchoOfOwnWrite(
|
|
7
|
+
subscription.domain,
|
|
8
|
+
change.externalId,
|
|
9
|
+
change.record
|
|
10
|
+
);
|
|
11
|
+
if (isEcho) continue;
|
|
12
|
+
yield change;
|
|
13
|
+
}
|
|
14
|
+
};
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export {
|
|
19
|
+
createLoopbackMiddleware
|
|
20
|
+
};
|
|
21
|
+
//# sourceMappingURL=chunk-PRWIX6UW.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../runtime/subsystems/integration/loopback.middleware.ts"],"sourcesContent":["/**\n * Integration subsystem — loopback `ChangeMiddleware` factory (#226-5, ADR-033).\n *\n * Replaces the prior orchestrator-side `@Optional() INTEGRATION_LOOPBACK_FINGERPRINT_STORE`\n * branch. Consumers that need to suppress echoes of their own outbound\n * writes compose `createLoopbackMiddleware(store)` into a primitive's\n * middleware chain — typically alongside `PollChangeSource<T>` — instead\n * of injecting a store into the orchestrator.\n *\n * Why middleware, not orchestrator branch:\n * - keeps the orchestrator port-agnostic (no per-mode special cases);\n * - lets primitives compose loopback with redaction / throttling /\n * other cross-cutting wrappers in a single chain;\n * - lets consumers pick per-source whether loopback is wired (some\n * entities have outbound writeback, others don't) without DI gymnastics.\n *\n * Behavior:\n * - For every change yielded by the inner iterator, call\n * `store.isEchoOfOwnWrite(subscription.domain, change.externalId, change.record)`.\n * - If the store returns `true`, the change is dropped (not yielded).\n * - Otherwise the change is passed through untouched.\n *\n * The middleware does not record audit rows for suppressed changes —\n * the orchestrator no longer learns about them. This is the deliberate\n * trade: loopback echoes are noise, not signal; their prior `skipped+noop`\n * audit rows existed only because the orchestrator was the suppression\n * site. Consumers wanting visibility into suppression counts can wrap\n * their store or layer a counting middleware alongside this one.\n */\n\nimport type { Change } from './integration-change-source.protocol';\nimport type {\n ChangeIterator,\n ChangeMiddleware,\n} from './integration-middleware.protocol';\nimport type { ILoopbackFingerprintStore } from './integration-loopback.protocol';\n\n/**\n * Build a `ChangeMiddleware<T>` that suppresses changes whose fingerprint\n * matches a recent local write according to the supplied store.\n *\n * Composition — first middleware in the array is outermost. Consumers\n * typically place loopback as the outermost layer so suppressed changes\n * never reach downstream middleware (redaction, transforms, etc.).\n */\nexport function createLoopbackMiddleware<T>(\n store: ILoopbackFingerprintStore<T>,\n): ChangeMiddleware<T> {\n return (next: ChangeIterator<T>): ChangeIterator<T> => {\n return async function* (subscription, cursor): AsyncIterable<Change<T>> {\n for await (const change of next(subscription, cursor)) {\n const isEcho = await store.isEchoOfOwnWrite(\n subscription.domain,\n change.externalId,\n change.record,\n );\n if (isEcho) continue;\n yield change;\n }\n };\n };\n}\n"],"mappings":";AA6CO,SAAS,yBACd,OACqB;AACrB,SAAO,CAAC,SAA+C;AACrD,WAAO,iBAAiB,cAAc,QAAkC;AACtE,uBAAiB,UAAU,KAAK,cAAc,MAAM,GAAG;AACrD,cAAM,SAAS,MAAM,MAAM;AAAA,UACzB,aAAa;AAAA,UACb,OAAO;AAAA,UACP,OAAO;AAAA,QACT;AACA,YAAI,OAAQ;AACZ,cAAM;AAAA,MACR;AAAA,IACF;AAAA,EACF;AACF;","names":[]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../runtime/shared/openapi/registry.tokens.ts"],"sourcesContent":["/**\n * Injection token for the OpenAPI registry (OPENAPI-1).\n *\n * String constant (not a Symbol) so it matches by value across import\n * boundaries — same convention as `ANALYTICS_QUERY` in analytics and\n * `EVENT_BUS` / `BRIDGE_DELIVERY_REPO` in events / bridge. The OPENAPI-1\n * spec sketched a Symbol, but the repo-wide convention wins — codebase\n * consistency matters more than the spec's initial guess.\n *\n * Consumed by generated DTO providers (OPENAPI-2), controllers\n * (OPENAPI-3), and the Swagger bootstrap (OPENAPI-4).\n */\nexport const OPENAPI_REGISTRY = 'OPENAPI_REGISTRY' as const;\n"],"mappings":";AAYO,IAAM,mBAAmB;","names":[]}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import {
|
|
2
|
+
OAuthStateError
|
|
3
|
+
} from "./chunk-BPARRK6F.js";
|
|
4
|
+
|
|
5
|
+
// runtime/subsystems/auth/backends/state-store.memory-backend.ts
|
|
6
|
+
import { randomBytes } from "crypto";
|
|
7
|
+
var MemoryOAuthStateStore = class {
|
|
8
|
+
store = /* @__PURE__ */ new Map();
|
|
9
|
+
ttlMs;
|
|
10
|
+
now;
|
|
11
|
+
generateToken;
|
|
12
|
+
constructor(opts = {}) {
|
|
13
|
+
this.ttlMs = opts.ttlMs ?? 10 * 60 * 1e3;
|
|
14
|
+
this.now = opts.now ?? (() => Date.now());
|
|
15
|
+
this.generateToken = opts.generateToken ?? (() => randomBytes(32).toString("base64url"));
|
|
16
|
+
}
|
|
17
|
+
async generate(record) {
|
|
18
|
+
const state = this.generateToken();
|
|
19
|
+
this.store.set(state, {
|
|
20
|
+
record: { ...record },
|
|
21
|
+
expiresAt: this.now() + this.ttlMs
|
|
22
|
+
});
|
|
23
|
+
return state;
|
|
24
|
+
}
|
|
25
|
+
async consume(state) {
|
|
26
|
+
const slot = this.store.get(state);
|
|
27
|
+
if (!slot) {
|
|
28
|
+
throw new OAuthStateError(
|
|
29
|
+
`OAuth state token unknown or already consumed`,
|
|
30
|
+
"missing"
|
|
31
|
+
);
|
|
32
|
+
}
|
|
33
|
+
this.store.delete(state);
|
|
34
|
+
if (slot.expiresAt <= this.now()) {
|
|
35
|
+
throw new OAuthStateError(`OAuth state token expired`, "expired");
|
|
36
|
+
}
|
|
37
|
+
return slot.record;
|
|
38
|
+
}
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
export {
|
|
42
|
+
MemoryOAuthStateStore
|
|
43
|
+
};
|
|
44
|
+
//# sourceMappingURL=chunk-QLTJSCE6.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../runtime/subsystems/auth/backends/state-store.memory-backend.ts"],"sourcesContent":["/**\n * In-memory `IOAuthStateStore` backend.\n *\n * Single-process store — Map<state, { record, expiresAt }>. Suitable for\n * tests and single-worker dev. Production deployments select the drizzle\n * backend so state survives restarts and is shared across workers.\n *\n * Single-use semantics:\n * - `generate(record)` mints a 256-bit random token (base64url, opaque).\n * - `consume(state)` deletes the entry on read. A second call with the\n * same state throws `OAuthStateError('replay')`.\n * - Expired entries also throw (`'expired'`); the entry is deleted as a\n * side effect so a later replay still surfaces correctly.\n *\n * TTL defaults to 10 minutes — long enough for a user to complete the\n * provider's consent screen, short enough that abandoned states age out.\n */\nimport { randomBytes } from 'node:crypto';\nimport {\n type IOAuthStateStore,\n type OAuthStateRecord,\n OAuthStateError,\n} from '../protocols/oauth-state-store';\n\nexport interface MemoryOAuthStateStoreOptions {\n /** TTL in ms. Default 10 minutes. */\n ttlMs?: number;\n /** Injectable clock for tests. Default `Date.now`. */\n now?: () => number;\n /** Injectable token generator for tests. Default 32-byte base64url. */\n generateToken?: () => string;\n}\n\ninterface Slot {\n record: OAuthStateRecord;\n expiresAt: number;\n}\n\nexport class MemoryOAuthStateStore implements IOAuthStateStore {\n private readonly store = new Map<string, Slot>();\n private readonly ttlMs: number;\n private readonly now: () => number;\n private readonly generateToken: () => string;\n\n constructor(opts: MemoryOAuthStateStoreOptions = {}) {\n this.ttlMs = opts.ttlMs ?? 10 * 60 * 1000;\n this.now = opts.now ?? (() => Date.now());\n this.generateToken =\n opts.generateToken ?? (() => randomBytes(32).toString('base64url'));\n }\n\n async generate(record: OAuthStateRecord): Promise<string> {\n const state = this.generateToken();\n this.store.set(state, {\n record: { ...record },\n expiresAt: this.now() + this.ttlMs,\n });\n return state;\n }\n\n async consume(state: string): Promise<OAuthStateRecord> {\n const slot = this.store.get(state);\n if (!slot) {\n throw new OAuthStateError(\n `OAuth state token unknown or already consumed`,\n 'missing',\n );\n }\n // Delete first so a concurrent consume can't replay.\n this.store.delete(state);\n if (slot.expiresAt <= this.now()) {\n throw new OAuthStateError(`OAuth state token expired`, 'expired');\n }\n return slot.record;\n }\n}\n"],"mappings":";;;;;AAiBA,SAAS,mBAAmB;AAqBrB,IAAM,wBAAN,MAAwD;AAAA,EAC5C,QAAQ,oBAAI,IAAkB;AAAA,EAC9B;AAAA,EACA;AAAA,EACA;AAAA,EAEjB,YAAY,OAAqC,CAAC,GAAG;AACnD,SAAK,QAAQ,KAAK,SAAS,KAAK,KAAK;AACrC,SAAK,MAAM,KAAK,QAAQ,MAAM,KAAK,IAAI;AACvC,SAAK,gBACH,KAAK,kBAAkB,MAAM,YAAY,EAAE,EAAE,SAAS,WAAW;AAAA,EACrE;AAAA,EAEA,MAAM,SAAS,QAA2C;AACxD,UAAM,QAAQ,KAAK,cAAc;AACjC,SAAK,MAAM,IAAI,OAAO;AAAA,MACpB,QAAQ,EAAE,GAAG,OAAO;AAAA,MACpB,WAAW,KAAK,IAAI,IAAI,KAAK;AAAA,IAC/B,CAAC;AACD,WAAO;AAAA,EACT;AAAA,EAEA,MAAM,QAAQ,OAA0C;AACtD,UAAM,OAAO,KAAK,MAAM,IAAI,KAAK;AACjC,QAAI,CAAC,MAAM;AACT,YAAM,IAAI;AAAA,QACR;AAAA,QACA;AAAA,MACF;AAAA,IACF;AAEA,SAAK,MAAM,OAAO,KAAK;AACvB,QAAI,KAAK,aAAa,KAAK,IAAI,GAAG;AAChC,YAAM,IAAI,gBAAgB,6BAA6B,SAAS;AAAA,IAClE;AACA,WAAO,KAAK;AAAA,EACd;AACF;","names":[]}
|