@pattern-stack/codegen 0.15.1 → 0.15.3
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 +85 -0
- package/dist/chunk-27ETSJ2X.js +84 -0
- package/dist/chunk-27ETSJ2X.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-4H3PETLM.js +290 -0
- package/dist/chunk-4H3PETLM.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-4MF3HKJA.js +94 -0
- package/dist/chunk-4MF3HKJA.js.map +1 -0
- package/dist/chunk-4MVGAMUA.js +40 -0
- package/dist/chunk-4MVGAMUA.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-7RELQJIN.js +22 -0
- package/dist/chunk-7RELQJIN.js.map +1 -0
- package/dist/chunk-7YGORYZD.js +112 -0
- package/dist/chunk-7YGORYZD.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-DCCZB4UC.js +100 -0
- package/dist/chunk-DCCZB4UC.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-FBGHYQIZ.js +201 -0
- package/dist/chunk-FBGHYQIZ.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-GCYKMF22.js +81 -0
- package/dist/chunk-GCYKMF22.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-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-IYNSRIGR.js +122 -0
- package/dist/chunk-IYNSRIGR.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-J7JMVS2B.js +53 -0
- package/dist/chunk-J7JMVS2B.js.map +1 -0
- package/dist/chunk-JRQO2IOF.js +65 -0
- package/dist/chunk-JRQO2IOF.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-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-O37C3YE6.js +111 -0
- package/dist/chunk-O37C3YE6.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-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-RDVTWIYY.js +212 -0
- package/dist/chunk-RDVTWIYY.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-T6SCOJF4.js +92 -0
- package/dist/chunk-T6SCOJF4.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-WL67FZGF.js +21 -0
- package/dist/chunk-WL67FZGF.js.map +1 -0
- package/dist/chunk-WWGYCIJX.js +29 -0
- package/dist/chunk-WWGYCIJX.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-YLPAPPLW.js +75 -0
- package/dist/chunk-YLPAPPLW.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/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.js +12 -184
- package/dist/runtime/subsystems/bridge/bridge-delivery-handler.js.map +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.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.js +14 -606
- package/dist/runtime/subsystems/bridge/bridge-outbox-drain-hook.js.map +1 -1
- 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.tokens.js +9 -7
- package/dist/runtime/subsystems/bridge/bridge.tokens.js.map +1 -1
- 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.js +4 -2
- package/dist/runtime/subsystems/bridge/generated/registry.js.map +1 -1
- 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.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/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.js +32 -949
- package/dist/runtime/subsystems/events/index.js.map +1 -1
- package/dist/runtime/subsystems/index.d.ts +5 -1
- package/dist/runtime/subsystems/index.js +182 -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.d.ts +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.d.ts +4 -3
- 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.js +88 -2691
- package/dist/runtime/subsystems/jobs/index.js.map +1 -1
- 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.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.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.js +10 -824
- package/dist/runtime/subsystems/jobs/job-orchestrator.memory-backend.js.map +1 -1
- 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.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.js +9 -290
- package/dist/runtime/subsystems/jobs/job-run-service.memory-backend.js.map +1 -1
- 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.js +9 -175
- package/dist/runtime/subsystems/jobs/job-worker.bullmq-backend.js.map +1 -1
- 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.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.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.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.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.js +4 -84
- package/dist/runtime/subsystems/observability/reporters/bridge-metrics.reporter.js.map +1 -1
- 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 +637 -5454
- 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-outbox-drain-hook.ts +44 -21
- package/runtime/subsystems/index.ts +27 -0
- package/runtime/subsystems/integration/poll-change-source.ts +10 -7
- package/runtime/subsystems/integration/webhook-change-source.ts +12 -8
- package/runtime/subsystems/jobs/job-worker.ts +17 -11
|
@@ -1,307 +1,12 @@
|
|
|
1
|
-
var __defProp = Object.defineProperty;
|
|
2
|
-
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
3
|
-
var __decorateClass = (decorators, target, key, kind) => {
|
|
4
|
-
var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc(target, key) : target;
|
|
5
|
-
for (var i = decorators.length - 1, decorator; i >= 0; i--)
|
|
6
|
-
if (decorator = decorators[i])
|
|
7
|
-
result = (kind ? decorator(target, key, result) : decorator(result)) || result;
|
|
8
|
-
if (kind && result) __defProp(target, key, result);
|
|
9
|
-
return result;
|
|
10
|
-
};
|
|
11
|
-
var __decorateParam = (index2, decorator) => (target, key) => decorator(target, key, index2);
|
|
12
|
-
|
|
13
|
-
// runtime/subsystems/integration/integration-run-recorder.drizzle-backend.ts
|
|
14
|
-
import { Inject, Injectable, Optional } from "@nestjs/common";
|
|
15
|
-
import { and, desc, eq } from "drizzle-orm";
|
|
16
|
-
|
|
17
|
-
// runtime/constants/tokens.ts
|
|
18
|
-
var DRIZZLE = "DRIZZLE";
|
|
19
|
-
|
|
20
|
-
// runtime/subsystems/integration/integration-audit.schema.ts
|
|
21
1
|
import {
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
index,
|
|
31
|
-
uniqueIndex
|
|
32
|
-
} from "drizzle-orm/pg-core";
|
|
33
|
-
var integrationRunDirectionEnum = pgEnum("integration_run_direction", [
|
|
34
|
-
"inbound",
|
|
35
|
-
"outbound"
|
|
36
|
-
]);
|
|
37
|
-
var integrationRunActionEnum = pgEnum("integration_run_action", [
|
|
38
|
-
"poll",
|
|
39
|
-
"cdc",
|
|
40
|
-
"webhook",
|
|
41
|
-
"manual",
|
|
42
|
-
"writeback"
|
|
43
|
-
]);
|
|
44
|
-
var integrationRunStatusEnum = pgEnum("integration_run_status", [
|
|
45
|
-
"running",
|
|
46
|
-
"success",
|
|
47
|
-
"no_changes",
|
|
48
|
-
"failed"
|
|
49
|
-
]);
|
|
50
|
-
var integrationRunItemOperationEnum = pgEnum("integration_run_item_operation", [
|
|
51
|
-
"created",
|
|
52
|
-
"updated",
|
|
53
|
-
"deleted",
|
|
54
|
-
"noop"
|
|
55
|
-
]);
|
|
56
|
-
var integrationRunItemStatusEnum = pgEnum("integration_run_item_status", [
|
|
57
|
-
"success",
|
|
58
|
-
"failed",
|
|
59
|
-
"skipped"
|
|
60
|
-
]);
|
|
61
|
-
var integrationSubscriptions = pgTable(
|
|
62
|
-
"integration_subscriptions",
|
|
63
|
-
{
|
|
64
|
-
id: uuid("id").primaryKey().defaultRandom(),
|
|
65
|
-
connectionId: text("connection_id").notNull(),
|
|
66
|
-
adapter: text("adapter").notNull(),
|
|
67
|
-
domain: text("domain").notNull(),
|
|
68
|
-
externalRef: text("external_ref"),
|
|
69
|
-
enabled: boolean("enabled").notNull().default(true),
|
|
70
|
-
/**
|
|
71
|
-
* Per-subscription configuration bag. Strategies type it internally;
|
|
72
|
-
* e.g. polling strategies stash `{ batchSize, highWatermark }` here.
|
|
73
|
-
*/
|
|
74
|
-
config: jsonb("config").notNull().default({}).$type(),
|
|
75
|
-
/**
|
|
76
|
-
* Opaque cursor persisted by `ICursorStore.put()`. NULL until the first
|
|
77
|
-
* successful run advances it.
|
|
78
|
-
*/
|
|
79
|
-
cursor: jsonb("cursor").$type(),
|
|
80
|
-
lastIntegrationAt: timestamp("last_integration_at", { withTimezone: true }),
|
|
81
|
-
/** Runtime-enforced when `INTEGRATION_MULTI_TENANT` is true; see SYNC-6. */
|
|
82
|
-
tenantId: text("tenant_id"),
|
|
83
|
-
createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
|
|
84
|
-
updatedAt: timestamp("updated_at", { withTimezone: true }).notNull().defaultNow()
|
|
85
|
-
},
|
|
86
|
-
(t) => ({
|
|
87
|
-
/**
|
|
88
|
-
* Composite uniqueness per the epic shape. `external_ref` is nullable;
|
|
89
|
-
* Postgres treats NULLs as distinct in a UNIQUE constraint, which means
|
|
90
|
-
* two rows with the same `(connection_id, adapter, domain)` and NULL
|
|
91
|
-
* external_ref are allowed. That's intentional — a subscription with
|
|
92
|
-
* NULL external_ref covers the full domain, and duplicates there would
|
|
93
|
-
* be a consumer-layer modeling issue, not a schema concern.
|
|
94
|
-
*/
|
|
95
|
-
uqIntegrationSubscriptionTuple: uniqueIndex("uq_integration_subscriptions_tuple").on(
|
|
96
|
-
t.connectionId,
|
|
97
|
-
t.adapter,
|
|
98
|
-
t.domain,
|
|
99
|
-
t.externalRef
|
|
100
|
-
),
|
|
101
|
-
/** Scheduling query: list enabled subscriptions ordered by staleness. */
|
|
102
|
-
idxIntegrationSubscriptionsEnabledLastIntegration: index(
|
|
103
|
-
"idx_integration_subscriptions_enabled_last_integration"
|
|
104
|
-
).on(t.enabled, t.lastIntegrationAt)
|
|
105
|
-
})
|
|
106
|
-
);
|
|
107
|
-
var integrationRuns = pgTable(
|
|
108
|
-
"integration_runs",
|
|
109
|
-
{
|
|
110
|
-
id: uuid("id").primaryKey().defaultRandom(),
|
|
111
|
-
subscriptionId: uuid("subscription_id").notNull().references(() => integrationSubscriptions.id, { onDelete: "cascade" }),
|
|
112
|
-
direction: integrationRunDirectionEnum("direction").notNull(),
|
|
113
|
-
action: integrationRunActionEnum("action").notNull(),
|
|
114
|
-
status: integrationRunStatusEnum("status").notNull().default("running"),
|
|
115
|
-
recordsFound: integer("records_found").notNull().default(0),
|
|
116
|
-
recordsProcessed: integer("records_processed").notNull().default(0),
|
|
117
|
-
cursorBefore: jsonb("cursor_before").$type(),
|
|
118
|
-
cursorAfter: jsonb("cursor_after").$type(),
|
|
119
|
-
durationMs: integer("duration_ms"),
|
|
120
|
-
error: text("error"),
|
|
121
|
-
startedAt: timestamp("started_at", { withTimezone: true }).notNull().defaultNow(),
|
|
122
|
-
completedAt: timestamp("completed_at", { withTimezone: true }),
|
|
123
|
-
/** Runtime-enforced when `INTEGRATION_MULTI_TENANT` is true; see SYNC-6. */
|
|
124
|
-
tenantId: text("tenant_id")
|
|
125
|
-
},
|
|
126
|
-
(t) => ({
|
|
127
|
-
/** Timeline read: "most recent runs for this subscription". */
|
|
128
|
-
idxIntegrationRunsSubscriptionStartedAt: index(
|
|
129
|
-
"idx_integration_runs_subscription_started_at"
|
|
130
|
-
).on(t.subscriptionId, t.startedAt),
|
|
131
|
-
/** Stale-run sweeper: "runs that started > N minutes ago and are still running". */
|
|
132
|
-
idxIntegrationRunsStatusStartedAt: index("idx_integration_runs_status_started_at").on(
|
|
133
|
-
t.status,
|
|
134
|
-
t.startedAt
|
|
135
|
-
)
|
|
136
|
-
})
|
|
137
|
-
);
|
|
138
|
-
var integrationRunItems = pgTable(
|
|
139
|
-
"integration_run_items",
|
|
140
|
-
{
|
|
141
|
-
id: uuid("id").primaryKey().defaultRandom(),
|
|
142
|
-
integrationRunId: uuid("integration_run_id").notNull().references(() => integrationRuns.id, { onDelete: "cascade" }),
|
|
143
|
-
entityType: text("entity_type").notNull(),
|
|
144
|
-
externalId: text("external_id").notNull(),
|
|
145
|
-
localId: text("local_id"),
|
|
146
|
-
operation: integrationRunItemOperationEnum("operation").notNull(),
|
|
147
|
-
status: integrationRunItemStatusEnum("status").notNull(),
|
|
148
|
-
/**
|
|
149
|
-
* Structured per-field diff — ADR-0003 shape enforced by
|
|
150
|
-
* `FieldDiffSchema.parse` at the recorder service layer.
|
|
151
|
-
*
|
|
152
|
-
* Shape: `{ [fieldName]: { from: unknown, to: unknown } }`.
|
|
153
|
-
* Empty `{}` for `noop` items; `{ [field]: { from: null, to: <value> } }`
|
|
154
|
-
* for created items; `{ [field]: { from: <value>, to: null } }` for
|
|
155
|
-
* deleted items.
|
|
156
|
-
*/
|
|
157
|
-
changedFields: jsonb("changed_fields").notNull().default({}).$type(),
|
|
158
|
-
title: text("title"),
|
|
159
|
-
error: text("error"),
|
|
160
|
-
createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
|
|
161
|
-
/** Runtime-enforced when `INTEGRATION_MULTI_TENANT` is true; see SYNC-6. */
|
|
162
|
-
tenantId: text("tenant_id")
|
|
163
|
-
},
|
|
164
|
-
(t) => ({
|
|
165
|
-
/** Ordered timeline within a run. */
|
|
166
|
-
idxIntegrationRunItemsRunCreatedAt: index("idx_integration_run_items_run_created_at").on(
|
|
167
|
-
t.integrationRunId,
|
|
168
|
-
t.createdAt
|
|
169
|
-
),
|
|
170
|
-
/** Per-record history: "every integration that touched opportunity/$extId". */
|
|
171
|
-
idxIntegrationRunItemsEntityExternal: index(
|
|
172
|
-
"idx_integration_run_items_entity_external"
|
|
173
|
-
).on(t.entityType, t.externalId)
|
|
174
|
-
})
|
|
175
|
-
);
|
|
176
|
-
|
|
177
|
-
// runtime/subsystems/integration/integration-field-diff.protocol.ts
|
|
178
|
-
import { z } from "zod";
|
|
179
|
-
var FieldDiffValueSchema = z.object({
|
|
180
|
-
from: z.unknown(),
|
|
181
|
-
to: z.unknown()
|
|
182
|
-
});
|
|
183
|
-
var FieldDiffSchema = z.record(z.string(), FieldDiffValueSchema);
|
|
184
|
-
|
|
185
|
-
// runtime/subsystems/integration/integration.tokens.ts
|
|
186
|
-
var INTEGRATION_MULTI_TENANT = "INTEGRATION_MULTI_TENANT";
|
|
187
|
-
|
|
188
|
-
// runtime/subsystems/integration/integration-errors.ts
|
|
189
|
-
var MissingTenantIdError = class extends Error {
|
|
190
|
-
name = "MissingTenantIdError";
|
|
191
|
-
constructor(operation) {
|
|
192
|
-
super(
|
|
193
|
-
`Missing tenantId for integration operation '${operation}'. IntegrationModule is configured with multiTenant: true \u2014 every call must include a non-null tenantId. Either pass the tenantId or disable multi-tenancy on the module.`
|
|
194
|
-
);
|
|
195
|
-
}
|
|
196
|
-
};
|
|
197
|
-
function assertTenantId(tenantId, options) {
|
|
198
|
-
if (!options.multiTenant) return;
|
|
199
|
-
if (tenantId === void 0 || tenantId === null) {
|
|
200
|
-
throw new MissingTenantIdError(options.operation);
|
|
201
|
-
}
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
// runtime/subsystems/integration/integration-run-recorder.drizzle-backend.ts
|
|
205
|
-
var DrizzleIntegrationRunRecorder = class {
|
|
206
|
-
constructor(db, multiTenant) {
|
|
207
|
-
this.db = db;
|
|
208
|
-
this.multiTenant = multiTenant ?? false;
|
|
209
|
-
}
|
|
210
|
-
db;
|
|
211
|
-
multiTenant;
|
|
212
|
-
async startRun(input) {
|
|
213
|
-
assertTenantId(input.tenantId, {
|
|
214
|
-
multiTenant: this.multiTenant,
|
|
215
|
-
operation: "startRun"
|
|
216
|
-
});
|
|
217
|
-
const rows = await this.db.insert(integrationRuns).values({
|
|
218
|
-
subscriptionId: input.subscriptionId,
|
|
219
|
-
direction: input.direction,
|
|
220
|
-
action: input.action,
|
|
221
|
-
status: "running",
|
|
222
|
-
cursorBefore: input.cursorBefore ?? null,
|
|
223
|
-
tenantId: input.tenantId ?? null
|
|
224
|
-
}).returning({ id: integrationRuns.id });
|
|
225
|
-
const id = rows[0]?.id;
|
|
226
|
-
if (!id) {
|
|
227
|
-
throw new Error("DrizzleIntegrationRunRecorder: INSERT RETURNING produced no id");
|
|
228
|
-
}
|
|
229
|
-
return { id };
|
|
230
|
-
}
|
|
231
|
-
async recordItem(input) {
|
|
232
|
-
assertTenantId(input.tenantId, {
|
|
233
|
-
multiTenant: this.multiTenant,
|
|
234
|
-
operation: "recordItem"
|
|
235
|
-
});
|
|
236
|
-
FieldDiffSchema.parse(input.changedFields);
|
|
237
|
-
await this.db.insert(integrationRunItems).values({
|
|
238
|
-
integrationRunId: input.integrationRunId,
|
|
239
|
-
entityType: input.entityType,
|
|
240
|
-
externalId: input.externalId,
|
|
241
|
-
localId: input.localId ?? null,
|
|
242
|
-
operation: input.operation,
|
|
243
|
-
status: input.status,
|
|
244
|
-
changedFields: input.changedFields,
|
|
245
|
-
title: input.title ?? null,
|
|
246
|
-
error: input.error ?? null,
|
|
247
|
-
tenantId: input.tenantId ?? null
|
|
248
|
-
});
|
|
249
|
-
}
|
|
250
|
-
async listRecent(limit, subscriptionId, tenantId) {
|
|
251
|
-
assertTenantId(tenantId, {
|
|
252
|
-
multiTenant: this.multiTenant,
|
|
253
|
-
operation: "listRecent"
|
|
254
|
-
});
|
|
255
|
-
const conditions = [];
|
|
256
|
-
if (subscriptionId !== void 0) {
|
|
257
|
-
conditions.push(eq(integrationRuns.subscriptionId, subscriptionId));
|
|
258
|
-
}
|
|
259
|
-
if (this.multiTenant) {
|
|
260
|
-
conditions.push(eq(integrationRuns.tenantId, tenantId));
|
|
261
|
-
}
|
|
262
|
-
const where = conditions.length === 0 ? void 0 : conditions.length === 1 ? conditions[0] : and(...conditions);
|
|
263
|
-
const rows = await this.db.select({
|
|
264
|
-
id: integrationRuns.id,
|
|
265
|
-
subscriptionId: integrationRuns.subscriptionId,
|
|
266
|
-
connectionId: integrationSubscriptions.connectionId,
|
|
267
|
-
status: integrationRuns.status,
|
|
268
|
-
startedAt: integrationRuns.startedAt,
|
|
269
|
-
completedAt: integrationRuns.completedAt,
|
|
270
|
-
recordsProcessed: integrationRuns.recordsProcessed,
|
|
271
|
-
tenantId: integrationRuns.tenantId
|
|
272
|
-
}).from(integrationRuns).innerJoin(
|
|
273
|
-
integrationSubscriptions,
|
|
274
|
-
eq(integrationRuns.subscriptionId, integrationSubscriptions.id)
|
|
275
|
-
).where(where).orderBy(desc(integrationRuns.startedAt)).limit(limit);
|
|
276
|
-
return rows.map((row) => ({
|
|
277
|
-
id: row.id,
|
|
278
|
-
subscriptionId: row.subscriptionId,
|
|
279
|
-
connectionId: row.connectionId,
|
|
280
|
-
status: row.status,
|
|
281
|
-
startedAt: row.startedAt,
|
|
282
|
-
completedAt: row.completedAt,
|
|
283
|
-
recordsProcessed: row.recordsProcessed,
|
|
284
|
-
tenantId: row.tenantId
|
|
285
|
-
}));
|
|
286
|
-
}
|
|
287
|
-
async completeRun(runId, input) {
|
|
288
|
-
await this.db.update(integrationRuns).set({
|
|
289
|
-
status: input.status,
|
|
290
|
-
recordsFound: input.recordsFound,
|
|
291
|
-
recordsProcessed: input.recordsProcessed,
|
|
292
|
-
cursorAfter: input.cursorAfter ?? null,
|
|
293
|
-
durationMs: input.durationMs,
|
|
294
|
-
error: input.error ?? null,
|
|
295
|
-
completedAt: /* @__PURE__ */ new Date()
|
|
296
|
-
}).where(eq(integrationRuns.id, runId));
|
|
297
|
-
}
|
|
298
|
-
};
|
|
299
|
-
DrizzleIntegrationRunRecorder = __decorateClass([
|
|
300
|
-
Injectable(),
|
|
301
|
-
__decorateParam(0, Inject(DRIZZLE)),
|
|
302
|
-
__decorateParam(1, Optional()),
|
|
303
|
-
__decorateParam(1, Inject(INTEGRATION_MULTI_TENANT))
|
|
304
|
-
], DrizzleIntegrationRunRecorder);
|
|
2
|
+
DrizzleIntegrationRunRecorder
|
|
3
|
+
} from "../../../chunk-SR7F3TJY.js";
|
|
4
|
+
import "../../../chunk-SQDOBLBP.js";
|
|
5
|
+
import "../../../chunk-MZ6GV4YF.js";
|
|
6
|
+
import "../../../chunk-HNWZFNKP.js";
|
|
7
|
+
import "../../../chunk-S7C6TIIF.js";
|
|
8
|
+
import "../../../chunk-U64T4YZE.js";
|
|
9
|
+
import "../../../chunk-2E224ZSN.js";
|
|
305
10
|
export {
|
|
306
11
|
DrizzleIntegrationRunRecorder
|
|
307
12
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../runtime/subsystems/integration/integration-run-recorder.drizzle-backend.ts","../../../../runtime/constants/tokens.ts","../../../../runtime/subsystems/integration/integration-audit.schema.ts","../../../../runtime/subsystems/integration/integration-field-diff.protocol.ts","../../../../runtime/subsystems/integration/integration.tokens.ts","../../../../runtime/subsystems/integration/integration-errors.ts"],"sourcesContent":["/**\n * DrizzleIntegrationRunRecorder — Drizzle-backed `IIntegrationRunRecorder` (SYNC-4).\n *\n * Generic write path only — extracted from the source app's\n * `IntegrationRunRecorderService`, minus CRM-specific convenience methods. Those\n * stay consumer-owned; the subsystem ships the substrate.\n *\n * ## Responsibilities\n *\n * - `startRun` — INSERT integration_runs row in status='running', returns id.\n * - `recordItem` — validates `changedFields` via `FieldDiffSchema.parse`\n * BEFORE the INSERT; a malformed shape throws before\n * any DB call fires. Enforces the ADR-0003 contract at\n * the write boundary.\n * - `completeRun` — UPDATE integration_runs with terminal status, counts,\n * cursor_after, duration_ms, completed_at.\n *\n * ## Multi-tenancy\n *\n * When `INTEGRATION_MULTI_TENANT` is true (SYNC-6):\n * - `startRun` and `recordItem` require non-null `tenantId` on input.\n * Enforcement goes through the shared `assertTenantId` helper so the\n * error message shape matches the orchestrator entry point + the\n * cursor-store backends.\n * - `completeRun` does NOT re-check tenancy — the run id was returned\n * by `startRun` which already enforced it, and run ids are uuids that\n * aren't guessable cross-tenant. Matches JOB-3's pattern of trusting\n * the run-id for downstream mutations.\n */\nimport { Inject, Injectable, Optional } from '@nestjs/common';\nimport { and, desc, eq, type SQL } from 'drizzle-orm';\nimport type { DrizzleClient } from '../../types/drizzle';\nimport { DRIZZLE } from '../../constants/tokens';\nimport type {\n CompleteRunInput,\n IIntegrationRunRecorder,\n RecordItemInput,\n StartRunInput,\n IntegrationRunSummary,\n} from './integration-run-recorder.protocol';\nimport { integrationRuns, integrationRunItems, integrationSubscriptions } from './integration-audit.schema';\nimport { FieldDiffSchema } from './integration-field-diff.protocol';\nimport { INTEGRATION_MULTI_TENANT } from './integration.tokens';\nimport { assertTenantId } from './integration-errors';\n\n@Injectable()\nexport class DrizzleIntegrationRunRecorder implements IIntegrationRunRecorder {\n private readonly multiTenant: boolean;\n\n constructor(\n @Inject(DRIZZLE) private readonly db: DrizzleClient,\n @Optional() @Inject(INTEGRATION_MULTI_TENANT) multiTenant?: boolean,\n ) {\n this.multiTenant = multiTenant ?? false;\n }\n\n async startRun(input: StartRunInput): Promise<{ id: string }> {\n assertTenantId(input.tenantId, {\n multiTenant: this.multiTenant,\n operation: 'startRun',\n });\n\n const rows = await this.db\n .insert(integrationRuns)\n .values({\n subscriptionId: input.subscriptionId,\n direction: input.direction,\n action: input.action,\n status: 'running',\n cursorBefore: input.cursorBefore ?? null,\n tenantId: input.tenantId ?? null,\n })\n .returning({ id: integrationRuns.id });\n\n const id = rows[0]?.id;\n if (!id) {\n // Drizzle's insert().returning() contract: at least one row is\n // returned for every successful INSERT. A missing id would indicate\n // a driver misbehavior; throw loudly rather than return bogus data.\n throw new Error('DrizzleIntegrationRunRecorder: INSERT RETURNING produced no id');\n }\n return { id };\n }\n\n async recordItem(input: RecordItemInput): Promise<void> {\n assertTenantId(input.tenantId, {\n multiTenant: this.multiTenant,\n operation: 'recordItem',\n });\n\n // ADR-0003 contract enforcement — reject malformed changedFields\n // before the DB call fires. `parse` throws a ZodError; callers see\n // the validation failure, not a DB constraint error.\n FieldDiffSchema.parse(input.changedFields);\n\n await this.db.insert(integrationRunItems).values({\n integrationRunId: input.integrationRunId,\n entityType: input.entityType,\n externalId: input.externalId,\n localId: input.localId ?? null,\n operation: input.operation,\n status: input.status,\n changedFields: input.changedFields,\n title: input.title ?? null,\n error: input.error ?? null,\n tenantId: input.tenantId ?? null,\n });\n }\n\n async listRecent(\n limit: number,\n subscriptionId?: string,\n tenantId?: string | null,\n ): Promise<IntegrationRunSummary[]> {\n assertTenantId(tenantId, {\n multiTenant: this.multiTenant,\n operation: 'listRecent',\n });\n\n // JOIN against integration_subscriptions to resolve `connection_id` per run.\n // `integration_runs.subscription_id` is a non-null FK so INNER JOIN is correct;\n // there should be no orphaned runs.\n const conditions: SQL[] = [];\n if (subscriptionId !== undefined) {\n conditions.push(eq(integrationRuns.subscriptionId, subscriptionId));\n }\n if (this.multiTenant) {\n conditions.push(eq(integrationRuns.tenantId, tenantId as string));\n }\n const where =\n conditions.length === 0\n ? undefined\n : conditions.length === 1\n ? conditions[0]\n : and(...conditions);\n\n const rows = await this.db\n .select({\n id: integrationRuns.id,\n subscriptionId: integrationRuns.subscriptionId,\n connectionId: integrationSubscriptions.connectionId,\n status: integrationRuns.status,\n startedAt: integrationRuns.startedAt,\n completedAt: integrationRuns.completedAt,\n recordsProcessed: integrationRuns.recordsProcessed,\n tenantId: integrationRuns.tenantId,\n })\n .from(integrationRuns)\n .innerJoin(\n integrationSubscriptions,\n eq(integrationRuns.subscriptionId, integrationSubscriptions.id),\n )\n .where(where)\n .orderBy(desc(integrationRuns.startedAt))\n .limit(limit);\n\n return rows.map((row) => ({\n id: row.id,\n subscriptionId: row.subscriptionId,\n connectionId: row.connectionId,\n status: row.status,\n startedAt: row.startedAt,\n completedAt: row.completedAt,\n recordsProcessed: row.recordsProcessed,\n tenantId: row.tenantId,\n }));\n }\n\n async completeRun(runId: string, input: CompleteRunInput): Promise<void> {\n await this.db\n .update(integrationRuns)\n .set({\n status: input.status,\n recordsFound: input.recordsFound,\n recordsProcessed: input.recordsProcessed,\n cursorAfter: input.cursorAfter ?? null,\n durationMs: input.durationMs,\n error: input.error ?? null,\n completedAt: new Date(),\n })\n .where(eq(integrationRuns.id, runId));\n }\n}\n","/**\n * NestJS injection tokens\n *\n * Used with @Inject() decorator in concrete repository constructors.\n */\n\n/**\n * Injection token for the Drizzle ORM database client.\n *\n * Usage in concrete repositories:\n * ```typescript\n * constructor(@Inject(DRIZZLE) db: DrizzleClient) { super(db); }\n * ```\n */\nexport const DRIZZLE = 'DRIZZLE' as const;\n\n/**\n * Injection token for the event bus (IEventBus).\n *\n * Optional — only resolved when EventsModule.forRoot() is registered.\n * BaseService uses this with @Optional() to emit lifecycle events\n * without requiring the events subsystem to be installed.\n *\n * Usage in services/use cases:\n * ```typescript\n * @Optional() @Inject(EVENT_BUS) eventBus?: IEventBus\n * ```\n */\nexport const EVENT_BUS = 'EVENT_BUS' as const;\n","/**\n * Drizzle schema for the integration subsystem audit/observability tables (SYNC-1).\n *\n * Three tables model end-to-end integration observability, keyed by the single port\n * every integration adapter implements (`IChangeSource<T>` from SYNC-2):\n *\n * - `integration_subscriptions` — owns the cursor per\n * `(connection_id, adapter, domain, external_ref)` tuple. Addressed\n * by id by `ICursorStore` (SYNC-3/SYNC-4).\n * - `integration_runs` — per-run audit log: start/complete, status,\n * cursor before/after, counts, direction (inbound|outbound),\n * action (poll|cdc|webhook|manual|writeback).\n * - `integration_run_items` — per-record change log with structured\n * `changed_fields` jsonb enforced by the Zod `FieldDiffSchema`\n * contract (ADR-0003; protocol lives in SYNC-2's\n * integration-field-diff.protocol.ts).\n *\n * Design calls (vs. issue #126 open questions):\n *\n * - `integration_subscriptions` ships in the subsystem (not consumer-owned).\n * Rationale: SYNC-4's `PostgresCursorStore` needs to read/write this\n * table directly; making it consumer-owned would require consumers to\n * hand-wire a shape the backend already knows. The row is addressable\n * by id and scoped by the uniqueness tuple; consumers can still\n * query/list it freely. Same stance as `job_run` being subsystem-\n * owned while remaining consumer-queryable.\n *\n * - `tenant_id` is always emitted on the three tables as nullable text.\n * The `INTEGRATION_MULTI_TENANT` DI flag (SYNC-6) is what enforces the\n * non-null + cross-tenant-isolation contract at the service/orchestrator\n * boundary. This mirrors JOB-1/JOB-8's final shape — runtime guard, not\n * a scaffold-time conditional column. Keeps the schema file uniform\n * across single-tenant and multi-tenant deployments.\n *\n * - `changed_fields` on `integration_run_items` is typed via the Zod-inferred\n * `FieldDiff` shape from SYNC-2 (`{ [fieldName]: { from, to } }`). The\n * recorder service (SYNC-5) validates every write against\n * `FieldDiffSchema.parse` so consumers can rely on the shape.\n */\nimport {\n pgEnum,\n pgTable,\n uuid,\n text,\n jsonb,\n integer,\n boolean,\n timestamp,\n index,\n uniqueIndex,\n} from 'drizzle-orm/pg-core';\nimport type { InferSelectModel } from 'drizzle-orm';\n\nimport type { FieldDiff } from './integration-field-diff.protocol';\n\n// ─── Enums ──────────────────────────────────────────────────────────────────\n\n/**\n * Direction of a integration run relative to local state.\n *\n * - `inbound` — external → local (the common case: SFDC poll → local DB).\n * - `outbound` — local → external (writeback; deferred per epic but the\n * column shape is reserved so future writeback runs share the audit log).\n */\nexport const integrationRunDirectionEnum = pgEnum('integration_run_direction', [\n 'inbound',\n 'outbound',\n]);\n\n/**\n * How the run detected upstream changes. Maps 1:1 to the `Change.source`\n * provenance on inbound runs; `manual` captures operator-triggered re-integrations\n * and `writeback` captures outbound runs.\n */\nexport const integrationRunActionEnum = pgEnum('integration_run_action', [\n 'poll',\n 'cdc',\n 'webhook',\n 'manual',\n 'writeback',\n]);\n\n/**\n * Lifecycle status of a integration run.\n *\n * - `running` — in-flight; recorder has started but not completed.\n * - `success` — completed with at least one change processed.\n * - `no_changes` — completed cleanly, no upstream changes found.\n * - `failed` — errored before completion; `error` column carries the\n * message. `records_processed` may be non-zero (partial progress).\n */\nexport const integrationRunStatusEnum = pgEnum('integration_run_status', [\n 'running',\n 'success',\n 'no_changes',\n 'failed',\n]);\n\n/**\n * Operation applied per record. Mirrors `Change<T>.operation` from SYNC-2,\n * plus the recorder's own `'noop'` for changes that matched existing state.\n */\nexport const integrationRunItemOperationEnum = pgEnum('integration_run_item_operation', [\n 'created',\n 'updated',\n 'deleted',\n 'noop',\n]);\n\n/**\n * Per-record status within a run. `skipped` captures loopback-detected echoes\n * of the local system's own writes (see `ILoopbackFingerprintStore` in the\n * epic), which record the external_id but intentionally do not touch local\n * state.\n */\nexport const integrationRunItemStatusEnum = pgEnum('integration_run_item_status', [\n 'success',\n 'failed',\n 'skipped',\n]);\n\n// ─── integration_subscriptions ─────────────────────────────────────────────────────\n\n/**\n * One cursor owner per (integration, adapter, domain, external_ref).\n *\n * - `connection_id` — opaque id of the connected account/instance. E.g.\n * the SFDC org id for polling strategies, the GitHub installation id\n * for webhook strategies.\n * - `adapter` — short adapter label, e.g. `'salesforce'`, `'hubspot'`.\n * - `domain` — canonical entity domain this subscription tracks,\n * e.g. `'opportunity'`, `'contact'`.\n * - `external_ref` — optional upstream scope (e.g. a filter id, a\n * webhook subscription id). NULL when the subscription covers the\n * entire domain.\n *\n * The cursor shape is opaque jsonb — strategies type it internally (poll:\n * `{ systemModstamp }`, cdc: `{ replayId }`, webhook: `{ ts }`). Overwritten\n * by `ICursorStore.put(id, cursor)`.\n */\nexport const integrationSubscriptions = pgTable(\n 'integration_subscriptions',\n {\n id: uuid('id').primaryKey().defaultRandom(),\n connectionId: text('connection_id').notNull(),\n adapter: text('adapter').notNull(),\n domain: text('domain').notNull(),\n externalRef: text('external_ref'),\n enabled: boolean('enabled').notNull().default(true),\n /**\n * Per-subscription configuration bag. Strategies type it internally;\n * e.g. polling strategies stash `{ batchSize, highWatermark }` here.\n */\n config: jsonb('config').notNull().default({}).$type<Record<string, unknown>>(),\n /**\n * Opaque cursor persisted by `ICursorStore.put()`. NULL until the first\n * successful run advances it.\n */\n cursor: jsonb('cursor').$type<unknown>(),\n lastIntegrationAt: timestamp('last_integration_at', { withTimezone: true }),\n /** Runtime-enforced when `INTEGRATION_MULTI_TENANT` is true; see SYNC-6. */\n tenantId: text('tenant_id'),\n createdAt: timestamp('created_at', { withTimezone: true }).notNull().defaultNow(),\n updatedAt: timestamp('updated_at', { withTimezone: true }).notNull().defaultNow(),\n },\n (t) => ({\n /**\n * Composite uniqueness per the epic shape. `external_ref` is nullable;\n * Postgres treats NULLs as distinct in a UNIQUE constraint, which means\n * two rows with the same `(connection_id, adapter, domain)` and NULL\n * external_ref are allowed. That's intentional — a subscription with\n * NULL external_ref covers the full domain, and duplicates there would\n * be a consumer-layer modeling issue, not a schema concern.\n */\n uqIntegrationSubscriptionTuple: uniqueIndex('uq_integration_subscriptions_tuple').on(\n t.connectionId,\n t.adapter,\n t.domain,\n t.externalRef,\n ),\n /** Scheduling query: list enabled subscriptions ordered by staleness. */\n idxIntegrationSubscriptionsEnabledLastIntegration: index(\n 'idx_integration_subscriptions_enabled_last_integration',\n ).on(t.enabled, t.lastIntegrationAt),\n }),\n);\n\nexport type IntegrationSubscriptionRow = InferSelectModel<typeof integrationSubscriptions>;\n\n// ─── integration_runs ──────────────────────────────────────────────────────────────\n\n/**\n * One row per invocation of `ExecuteIntegrationUseCase`. `started_at` is set when\n * the recorder opens the run; `completed_at`, `status`, `records_*`,\n * `cursor_after`, and `duration_ms` are filled on completion.\n *\n * `cursor_before` / `cursor_after` carry the opaque cursor snapshots so the\n * run log is fully self-describing — given a run id, an operator can reason\n * about exactly what window was scanned without cross-referencing another\n * table.\n */\nexport const integrationRuns = pgTable(\n 'integration_runs',\n {\n id: uuid('id').primaryKey().defaultRandom(),\n subscriptionId: uuid('subscription_id')\n .notNull()\n .references(() => integrationSubscriptions.id, { onDelete: 'cascade' }),\n direction: integrationRunDirectionEnum('direction').notNull(),\n action: integrationRunActionEnum('action').notNull(),\n status: integrationRunStatusEnum('status').notNull().default('running'),\n recordsFound: integer('records_found').notNull().default(0),\n recordsProcessed: integer('records_processed').notNull().default(0),\n cursorBefore: jsonb('cursor_before').$type<unknown>(),\n cursorAfter: jsonb('cursor_after').$type<unknown>(),\n durationMs: integer('duration_ms'),\n error: text('error'),\n startedAt: timestamp('started_at', { withTimezone: true })\n .notNull()\n .defaultNow(),\n completedAt: timestamp('completed_at', { withTimezone: true }),\n /** Runtime-enforced when `INTEGRATION_MULTI_TENANT` is true; see SYNC-6. */\n tenantId: text('tenant_id'),\n },\n (t) => ({\n /** Timeline read: \"most recent runs for this subscription\". */\n idxIntegrationRunsSubscriptionStartedAt: index(\n 'idx_integration_runs_subscription_started_at',\n ).on(t.subscriptionId, t.startedAt),\n /** Stale-run sweeper: \"runs that started > N minutes ago and are still running\". */\n idxIntegrationRunsStatusStartedAt: index('idx_integration_runs_status_started_at').on(\n t.status,\n t.startedAt,\n ),\n }),\n);\n\nexport type IntegrationRunRow = InferSelectModel<typeof integrationRuns>;\n\n// ─── integration_run_items ─────────────────────────────────────────────────────────\n\n/**\n * One row per upstream change processed within a run. Captures the canonical\n * decision the orchestrator made (`operation` + `status`), the structured\n * per-field diff (`changed_fields`, ADR-0003), and the local row id\n * (`local_id`) for drill-down joins.\n *\n * `changed_fields` is validated at the recorder layer via `FieldDiffSchema`\n * (SYNC-2) — the $type<FieldDiff> annotation here only documents the shape\n * for Drizzle consumers. The runtime enforcement is non-negotiable: downstream\n * drift-detection queries rely on the `{from, to}` shape per field.\n *\n * `title` is an optional human-readable label captured at write time (e.g.\n * `\"Pinnacle opportunity\"`) so run-log UIs don't need to re-hydrate the\n * canonical record.\n */\nexport const integrationRunItems = pgTable(\n 'integration_run_items',\n {\n id: uuid('id').primaryKey().defaultRandom(),\n integrationRunId: uuid('integration_run_id')\n .notNull()\n .references(() => integrationRuns.id, { onDelete: 'cascade' }),\n entityType: text('entity_type').notNull(),\n externalId: text('external_id').notNull(),\n localId: text('local_id'),\n operation: integrationRunItemOperationEnum('operation').notNull(),\n status: integrationRunItemStatusEnum('status').notNull(),\n /**\n * Structured per-field diff — ADR-0003 shape enforced by\n * `FieldDiffSchema.parse` at the recorder service layer.\n *\n * Shape: `{ [fieldName]: { from: unknown, to: unknown } }`.\n * Empty `{}` for `noop` items; `{ [field]: { from: null, to: <value> } }`\n * for created items; `{ [field]: { from: <value>, to: null } }` for\n * deleted items.\n */\n changedFields: jsonb('changed_fields').notNull().default({}).$type<FieldDiff>(),\n title: text('title'),\n error: text('error'),\n createdAt: timestamp('created_at', { withTimezone: true })\n .notNull()\n .defaultNow(),\n /** Runtime-enforced when `INTEGRATION_MULTI_TENANT` is true; see SYNC-6. */\n tenantId: text('tenant_id'),\n },\n (t) => ({\n /** Ordered timeline within a run. */\n idxIntegrationRunItemsRunCreatedAt: index('idx_integration_run_items_run_created_at').on(\n t.integrationRunId,\n t.createdAt,\n ),\n /** Per-record history: \"every integration that touched opportunity/$extId\". */\n idxIntegrationRunItemsEntityExternal: index(\n 'idx_integration_run_items_entity_external',\n ).on(t.entityType, t.externalId),\n }),\n);\n\nexport type IntegrationRunItemRow = InferSelectModel<typeof integrationRunItems>;\n","/**\n * Integration subsystem — field-diff protocol (port)\n *\n * `IFieldDiffer<T>` is the pluggable differ seam. The default implementation\n * (`DeepEqualDiffer`, ships in SYNC-5) walks every field except an ignore\n * list; CDC-aware differs can skip comparison for fields the provider didn't\n * flag as changed.\n *\n * `FieldDiffSchema` is the structural enforcement of the `changed_fields`\n * column per ADR-0003 — enforced at write time by the recorder service so\n * consumers can rely on the shape in downstream queries.\n */\nimport { z } from 'zod';\n\n// ============================================================================\n// FieldDiff shape — the ADR-0003 contract\n// ============================================================================\n\n/**\n * Structured per-field change. Enforced shape for `integration_run_items.changed_fields`.\n *\n * `created` items set `from: null, to: <value>` for every non-null field.\n * `deleted` items set `from: <value>, to: null`.\n * `noop` items carry `{}`.\n */\nexport const FieldDiffValueSchema = z.object({\n from: z.unknown(),\n to: z.unknown(),\n});\n\nexport const FieldDiffSchema = z.record(z.string(), FieldDiffValueSchema);\n\nexport type FieldDiffValue = z.infer<typeof FieldDiffValueSchema>;\nexport type FieldDiff = z.infer<typeof FieldDiffSchema>;\n\n/** Result of comparing a new record against its existing local state. */\nexport type DiffResult = FieldDiff | 'noop';\n\n// ============================================================================\n// IFieldDiffer\n// ============================================================================\n\n/**\n * Pluggable differ. Default ships in SYNC-5 as `DeepEqualDiffer<T>` —\n * deep-equal over every field except an ignore list (`updated_at` and other\n * row metadata). CDC-aware differs restrict comparison to\n * `providerChangedFields` when supplied.\n */\nexport interface IFieldDiffer<T> {\n /**\n * @param existing — current local state, or `null` when the record is new\n * @param incoming — the canonical record coming from the adapter\n * @param providerChangedFields — optional hint from CDC-capable sources;\n * when present, differ may restrict the comparison to these fields\n */\n diff(\n existing: T | null,\n incoming: T,\n providerChangedFields?: string[],\n ): DiffResult;\n}\n","/**\n * Integration subsystem — DI tokens\n *\n * String constants (not Symbols) so they match by value across import\n * boundaries — same convention as the events subsystem (`EVENT_BUS`). The\n * jobs subsystem uses Symbols for its analogous tokens; events and integration\n * stay internally consistent with strings.\n *\n * Usage in use cases:\n * ```ts\n * constructor(\n * @Inject(INTEGRATION_CHANGE_SOURCE) private readonly source: IChangeSource<CanonicalOpportunity>,\n * @Inject(INTEGRATION_CURSOR_STORE) private readonly cursors: ICursorStore,\n * @Inject(INTEGRATION_FIELD_DIFFER) private readonly differ: IFieldDiffer<CanonicalOpportunity>,\n * @Inject(INTEGRATION_SINK) private readonly sink: IIntegrationSink<CanonicalOpportunity>,\n * @Inject(INTEGRATION_RUN_RECORDER) private readonly recorder: IIntegrationRunRecorder,\n * ) {}\n * ```\n *\n * Concrete bindings are registered by `IntegrationModule.forRoot(...)` (SYNC-6).\n */\n\nexport const INTEGRATION_CHANGE_SOURCE = 'INTEGRATION_CHANGE_SOURCE' as const;\nexport const INTEGRATION_CURSOR_STORE = 'INTEGRATION_CURSOR_STORE' as const;\nexport const INTEGRATION_FIELD_DIFFER = 'INTEGRATION_FIELD_DIFFER' as const;\nexport const INTEGRATION_SINK = 'INTEGRATION_SINK' as const;\n\n/**\n * Run-recorder token (SYNC-5). Backed by `IIntegrationRunRecorder`. Drizzle impl\n * lands in SYNC-4; tests provide inline fakes.\n */\nexport const INTEGRATION_RUN_RECORDER = 'INTEGRATION_RUN_RECORDER' as const;\n\n/**\n * Injection token for the resolved `IntegrationModuleOptions` object (SYNC-6).\n *\n * Backends that need to observe module configuration (e.g. `multiTenant`\n * flag, pool filters) inject via this token. Provided automatically by\n * `IntegrationModule.forRoot(...)` / `IntegrationModule.forRootAsync(...)`.\n */\nexport const INTEGRATION_MODULE_OPTIONS = 'INTEGRATION_MODULE_OPTIONS' as const;\n\n/**\n * Injection token for the resolved multi-tenancy flag (SYNC-6).\n *\n * Provided by `IntegrationModule.forRoot(...)` as `options.multiTenant ?? false`.\n * Consumed by `ExecuteIntegrationUseCase` to enforce the tenantId-is-required rule.\n */\nexport const INTEGRATION_MULTI_TENANT = 'INTEGRATION_MULTI_TENANT' as const;\n\n/**\n * Injection token for the entity-keyed `IEntityChangeSourceRegistry` (C7,\n * #336). Bound to the codegen-emitted aggregator that folds per-provider\n * adapter contributions into one registry (RFC-0001 §3, emitted by Track D\n * D3/D4).\n *\n * A string constant, not `Symbol.for(...)`, to match this subsystem's token\n * convention (see file header). The originating issue's code block proposed a\n * `Symbol.for('@pattern-stack/codegen.entity-change-source-registry')` key,\n * predating the sync→integration consolidation onto string tokens; kept as a\n * string here for internal consistency with the other INTEGRATION_* tokens.\n */\nexport const ENTITY_CHANGE_SOURCE_REGISTRY = 'ENTITY_CHANGE_SOURCE_REGISTRY' as const;\n","/**\n * Typed errors + shared boundary helpers for the integration subsystem.\n *\n * Classes (not bare Error) so consumers can `instanceof` them in catch\n * blocks and exception filters can map them to HTTP codes.\n *\n * Mirrors the shape of `events-errors.ts` and `jobs-errors.ts`.\n */\n\n/**\n * Thrown by the Drizzle cursor-store / run-recorder backends AND by the\n * orchestrator entry point when `INTEGRATION_MULTI_TENANT` is enabled but the\n * caller did not supply a non-null `tenantId`. Strict enforcement at the\n * boundary — explicit `null` still throws.\n *\n * Disable multi-tenancy on the module (`multiTenant: false`, the default)\n * to opt out of the requirement entirely.\n *\n * `operation` identifies the call site (e.g. `'cursor.put'`,\n * `'startRun'`, `'execute'`) so the stack-trace message points at the\n * specific boundary that rejected the input.\n */\nexport class MissingTenantIdError extends Error {\n override readonly name = 'MissingTenantIdError';\n constructor(operation: string) {\n super(\n `Missing tenantId for integration operation '${operation}'. IntegrationModule is ` +\n `configured with multiTenant: true — every call must include a ` +\n `non-null tenantId. Either pass the tenantId or disable multi-` +\n `tenancy on the module.`,\n );\n }\n}\n\n/**\n * Shared boundary guard — used at the orchestrator entry AND inside the\n * Drizzle backends. Keeping the check in one function guarantees every\n * `MissingTenantIdError` carries the same message shape regardless of the\n * site that raised it, which makes it easier for consumers to pattern-\n * match on the error in logs/metrics.\n *\n * When `multiTenant` is false, the function is a no-op — `tenantId` may\n * be anything (including `undefined`). When true, `undefined` or `null`\n * throws.\n */\nexport function assertTenantId(\n tenantId: string | null | undefined,\n options: { multiTenant: boolean; operation: string },\n): asserts tenantId is string {\n if (!options.multiTenant) return;\n if (tenantId === undefined || tenantId === null) {\n throw new MissingTenantIdError(options.operation);\n }\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
|
|
@@ -1,128 +1,8 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
if (decorator = decorators[i])
|
|
7
|
-
result = (kind ? decorator(target, key, result) : decorator(result)) || result;
|
|
8
|
-
if (kind && result) __defProp(target, key, result);
|
|
9
|
-
return result;
|
|
10
|
-
};
|
|
11
|
-
|
|
12
|
-
// runtime/subsystems/integration/integration-run-recorder.memory-backend.ts
|
|
13
|
-
import { Injectable } from "@nestjs/common";
|
|
14
|
-
|
|
15
|
-
// runtime/subsystems/integration/integration-field-diff.protocol.ts
|
|
16
|
-
import { z } from "zod";
|
|
17
|
-
var FieldDiffValueSchema = z.object({
|
|
18
|
-
from: z.unknown(),
|
|
19
|
-
to: z.unknown()
|
|
20
|
-
});
|
|
21
|
-
var FieldDiffSchema = z.record(z.string(), FieldDiffValueSchema);
|
|
22
|
-
|
|
23
|
-
// runtime/subsystems/integration/integration-run-recorder.memory-backend.ts
|
|
24
|
-
var MemoryRunRecorder = class {
|
|
25
|
-
/**
|
|
26
|
-
* All started runs keyed by id. Public so tests can inspect lifecycle
|
|
27
|
-
* transitions without poking through recording methods.
|
|
28
|
-
*/
|
|
29
|
-
runs = /* @__PURE__ */ new Map();
|
|
30
|
-
/**
|
|
31
|
-
* Items keyed by `integration_run_id`, array order matches insertion order —
|
|
32
|
-
* mirrors the timeline the `(integration_run_id, created_at)` index produces
|
|
33
|
-
* in Postgres.
|
|
34
|
-
*/
|
|
35
|
-
items = /* @__PURE__ */ new Map();
|
|
36
|
-
/**
|
|
37
|
-
* Seedable subscription metadata — tests populate this to make
|
|
38
|
-
* `listRecent` return meaningful `connectionId` values. The memory
|
|
39
|
-
* backend doesn't track subscriptions on its own (only runs + items), so
|
|
40
|
-
* this map is the intentional extension point: tests write entries for
|
|
41
|
-
* the subscription ids they use, production code never touches it.
|
|
42
|
-
*/
|
|
43
|
-
subscriptions = /* @__PURE__ */ new Map();
|
|
44
|
-
async startRun(input) {
|
|
45
|
-
const id = crypto.randomUUID();
|
|
46
|
-
this.runs.set(id, {
|
|
47
|
-
id,
|
|
48
|
-
subscriptionId: input.subscriptionId,
|
|
49
|
-
direction: input.direction,
|
|
50
|
-
action: input.action,
|
|
51
|
-
status: "running",
|
|
52
|
-
cursorBefore: input.cursorBefore ?? null,
|
|
53
|
-
cursorAfter: null,
|
|
54
|
-
recordsFound: 0,
|
|
55
|
-
recordsProcessed: 0,
|
|
56
|
-
durationMs: null,
|
|
57
|
-
error: null,
|
|
58
|
-
tenantId: input.tenantId ?? null,
|
|
59
|
-
startedAt: /* @__PURE__ */ new Date(),
|
|
60
|
-
completedAt: null
|
|
61
|
-
});
|
|
62
|
-
this.items.set(id, []);
|
|
63
|
-
return { id };
|
|
64
|
-
}
|
|
65
|
-
async recordItem(input) {
|
|
66
|
-
FieldDiffSchema.parse(input.changedFields);
|
|
67
|
-
const bucket = this.items.get(input.integrationRunId);
|
|
68
|
-
if (!bucket) {
|
|
69
|
-
throw new Error(
|
|
70
|
-
`MemoryRunRecorder.recordItem: no run started for id '${input.integrationRunId}'. Call startRun(...) first.`
|
|
71
|
-
);
|
|
72
|
-
}
|
|
73
|
-
bucket.push(input);
|
|
74
|
-
}
|
|
75
|
-
async completeRun(runId, input) {
|
|
76
|
-
const run = this.runs.get(runId);
|
|
77
|
-
if (!run) {
|
|
78
|
-
throw new Error(
|
|
79
|
-
`MemoryRunRecorder.completeRun: no run started for id '${runId}'.`
|
|
80
|
-
);
|
|
81
|
-
}
|
|
82
|
-
run.status = input.status;
|
|
83
|
-
run.recordsFound = input.recordsFound;
|
|
84
|
-
run.recordsProcessed = input.recordsProcessed;
|
|
85
|
-
run.cursorAfter = input.cursorAfter ?? null;
|
|
86
|
-
run.durationMs = input.durationMs;
|
|
87
|
-
run.error = input.error ?? null;
|
|
88
|
-
run.completedAt = /* @__PURE__ */ new Date();
|
|
89
|
-
}
|
|
90
|
-
async listRecent(limit, subscriptionId, _tenantId) {
|
|
91
|
-
const all = Array.from(this.runs.values());
|
|
92
|
-
const filtered = subscriptionId === void 0 ? all : all.filter((r) => r.subscriptionId === subscriptionId);
|
|
93
|
-
return filtered.sort((a, b) => b.startedAt.getTime() - a.startedAt.getTime()).slice(0, limit).map((r) => ({
|
|
94
|
-
id: r.id,
|
|
95
|
-
subscriptionId: r.subscriptionId,
|
|
96
|
-
// connectionId is only knowable if the test seeded subscriptions
|
|
97
|
-
// metadata; empty string otherwise. The Drizzle backend resolves
|
|
98
|
-
// it via JOIN, which is the production path.
|
|
99
|
-
connectionId: this.subscriptions.get(r.subscriptionId)?.connectionId ?? "",
|
|
100
|
-
status: r.status,
|
|
101
|
-
startedAt: r.startedAt,
|
|
102
|
-
completedAt: r.completedAt,
|
|
103
|
-
recordsProcessed: r.recordsProcessed,
|
|
104
|
-
tenantId: r.tenantId
|
|
105
|
-
}));
|
|
106
|
-
}
|
|
107
|
-
/** Reset state. Tests call this in `beforeEach`. */
|
|
108
|
-
clear() {
|
|
109
|
-
this.runs.clear();
|
|
110
|
-
this.items.clear();
|
|
111
|
-
this.subscriptions.clear();
|
|
112
|
-
}
|
|
113
|
-
// ─── test ergonomics ─────────────────────────────────────────────────
|
|
114
|
-
/** All runs for a subscription, newest first. Timeline reads. */
|
|
115
|
-
getRunsForSubscription(subscriptionId) {
|
|
116
|
-
return Array.from(this.runs.values()).filter((r) => r.subscriptionId === subscriptionId).sort((a, b) => b.startedAt.getTime() - a.startedAt.getTime());
|
|
117
|
-
}
|
|
118
|
-
/** All item rows for a run, insertion-ordered. */
|
|
119
|
-
getItemsForRun(runId) {
|
|
120
|
-
return this.items.get(runId) ?? [];
|
|
121
|
-
}
|
|
122
|
-
};
|
|
123
|
-
MemoryRunRecorder = __decorateClass([
|
|
124
|
-
Injectable()
|
|
125
|
-
], MemoryRunRecorder);
|
|
1
|
+
import {
|
|
2
|
+
MemoryRunRecorder
|
|
3
|
+
} from "../../../chunk-EO2QPOKH.js";
|
|
4
|
+
import "../../../chunk-SQDOBLBP.js";
|
|
5
|
+
import "../../../chunk-2E224ZSN.js";
|
|
126
6
|
export {
|
|
127
7
|
MemoryRunRecorder
|
|
128
8
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../runtime/subsystems/integration/integration-run-recorder.memory-backend.ts","../../../../runtime/subsystems/integration/integration-field-diff.protocol.ts"],"sourcesContent":["/**\n * MemoryRunRecorder — in-memory backend for `IIntegrationRunRecorder` (SYNC-6).\n *\n * Test double so `IntegrationModule.forRoot({ backend: 'memory' })` is genuinely\n * end-to-end runnable without Postgres. Mirrors the role of\n * `MemoryCursorStore`: plain keyed state, `clear()` helper for\n * `beforeEach` resets, public inspection surface so tests can assert on\n * the recorded run + item timeline without scraping logs.\n *\n * Validates `changedFields` through `FieldDiffSchema.parse` on every\n * `recordItem` call — same ADR-0003 contract as the Drizzle backend. An\n * in-memory recorder that skipped the validation would be a silently\n * weaker contract than production.\n *\n * `startRun` generates a uuid via `crypto.randomUUID()` (Node 19+ / Bun).\n * We don't import `uuid` because the subsystem has no other use for it.\n *\n * ## Multi-tenancy\n *\n * `tenantId` is accepted (and recorded on the in-memory row so tests can\n * assert it) but enforcement lives at the module boundary. The memory\n * backend intentionally does not throw on missing `tenantId` — that's\n * the orchestrator's job when `multiTenant=true` (SYNC-6). A permissive\n * memory recorder lets tests exercise error paths where the orchestrator\n * short-circuits before ever reaching the recorder.\n */\nimport { Injectable } from '@nestjs/common';\nimport type {\n CompleteRunInput,\n IIntegrationRunRecorder,\n RecordItemInput,\n StartRunInput,\n IntegrationRunSummary,\n} from './integration-run-recorder.protocol';\nimport { FieldDiffSchema } from './integration-field-diff.protocol';\n\n/**\n * Optional per-subscription metadata a test can seed on the memory backend\n * so `listRecent` can surface `connectionId`. The memory recorder's write\n * path never persists subscription rows (it only stores runs + items), so\n * `listRecent` has no way to derive `connectionId` on its own. Tests that\n * care about the field should populate `subscriptions` before calling\n * `listRecent`; calls that don't seed get an empty string and a stable\n * shape (see `listRecent` below).\n */\nexport interface MemoryIntegrationSubscription {\n connectionId: string;\n adapter: string;\n domain: string;\n externalRef: string | null;\n lastIntegrationAt?: Date | null;\n updatedAt: Date;\n}\n\n/**\n * Concrete run row as held in memory. Shape mirrors the interesting\n * columns on `integration_runs` so assertions read like DB queries.\n */\nexport interface MemoryRunRecord {\n id: string;\n subscriptionId: string;\n direction: 'inbound' | 'outbound';\n action: 'poll' | 'cdc' | 'webhook' | 'manual' | 'writeback';\n status: 'running' | 'success' | 'no_changes' | 'failed';\n cursorBefore: unknown | null;\n cursorAfter: unknown | null;\n recordsFound: number;\n recordsProcessed: number;\n durationMs: number | null;\n error: string | null;\n tenantId: string | null;\n startedAt: Date;\n completedAt: Date | null;\n}\n\n@Injectable()\nexport class MemoryRunRecorder implements IIntegrationRunRecorder {\n /**\n * All started runs keyed by id. Public so tests can inspect lifecycle\n * transitions without poking through recording methods.\n */\n readonly runs: Map<string, MemoryRunRecord> = new Map();\n\n /**\n * Items keyed by `integration_run_id`, array order matches insertion order —\n * mirrors the timeline the `(integration_run_id, created_at)` index produces\n * in Postgres.\n */\n readonly items: Map<string, RecordItemInput[]> = new Map();\n\n /**\n * Seedable subscription metadata — tests populate this to make\n * `listRecent` return meaningful `connectionId` values. The memory\n * backend doesn't track subscriptions on its own (only runs + items), so\n * this map is the intentional extension point: tests write entries for\n * the subscription ids they use, production code never touches it.\n */\n readonly subscriptions: Map<string, MemoryIntegrationSubscription> = new Map();\n\n async startRun(input: StartRunInput): Promise<{ id: string }> {\n const id = crypto.randomUUID();\n this.runs.set(id, {\n id,\n subscriptionId: input.subscriptionId,\n direction: input.direction,\n action: input.action,\n status: 'running',\n cursorBefore: input.cursorBefore ?? null,\n cursorAfter: null,\n recordsFound: 0,\n recordsProcessed: 0,\n durationMs: null,\n error: null,\n tenantId: input.tenantId ?? null,\n startedAt: new Date(),\n completedAt: null,\n });\n this.items.set(id, []);\n return { id };\n }\n\n async recordItem(input: RecordItemInput): Promise<void> {\n // Same ADR-0003 contract as the Drizzle backend.\n FieldDiffSchema.parse(input.changedFields);\n\n const bucket = this.items.get(input.integrationRunId);\n if (!bucket) {\n throw new Error(\n `MemoryRunRecorder.recordItem: no run started for id '${input.integrationRunId}'. ` +\n `Call startRun(...) first.`,\n );\n }\n bucket.push(input);\n }\n\n async completeRun(runId: string, input: CompleteRunInput): Promise<void> {\n const run = this.runs.get(runId);\n if (!run) {\n throw new Error(\n `MemoryRunRecorder.completeRun: no run started for id '${runId}'.`,\n );\n }\n run.status = input.status;\n run.recordsFound = input.recordsFound;\n run.recordsProcessed = input.recordsProcessed;\n run.cursorAfter = input.cursorAfter ?? null;\n run.durationMs = input.durationMs;\n run.error = input.error ?? null;\n run.completedAt = new Date();\n }\n\n async listRecent(\n limit: number,\n subscriptionId?: string,\n _tenantId?: string | null,\n ): Promise<IntegrationRunSummary[]> {\n // Memory backend accepts tenantId for contract symmetry but does not\n // filter on it — state is process-local and cross-tenant isolation is\n // not meaningful here (matches MemoryCursorStore behavior).\n const all = Array.from(this.runs.values());\n const filtered =\n subscriptionId === undefined\n ? all\n : all.filter((r) => r.subscriptionId === subscriptionId);\n return filtered\n .sort((a, b) => b.startedAt.getTime() - a.startedAt.getTime())\n .slice(0, limit)\n .map((r) => ({\n id: r.id,\n subscriptionId: r.subscriptionId,\n // connectionId is only knowable if the test seeded subscriptions\n // metadata; empty string otherwise. The Drizzle backend resolves\n // it via JOIN, which is the production path.\n connectionId:\n this.subscriptions.get(r.subscriptionId)?.connectionId ?? '',\n status: r.status,\n startedAt: r.startedAt,\n completedAt: r.completedAt,\n recordsProcessed: r.recordsProcessed,\n tenantId: r.tenantId,\n }));\n }\n\n /** Reset state. Tests call this in `beforeEach`. */\n clear(): void {\n this.runs.clear();\n this.items.clear();\n this.subscriptions.clear();\n }\n\n // ─── test ergonomics ─────────────────────────────────────────────────\n\n /** All runs for a subscription, newest first. Timeline reads. */\n getRunsForSubscription(subscriptionId: string): MemoryRunRecord[] {\n return Array.from(this.runs.values())\n .filter((r) => r.subscriptionId === subscriptionId)\n .sort((a, b) => b.startedAt.getTime() - a.startedAt.getTime());\n }\n\n /** All item rows for a run, insertion-ordered. */\n getItemsForRun(runId: string): RecordItemInput[] {\n return this.items.get(runId) ?? [];\n }\n}\n","/**\n * Integration subsystem — field-diff protocol (port)\n *\n * `IFieldDiffer<T>` is the pluggable differ seam. The default implementation\n * (`DeepEqualDiffer`, ships in SYNC-5) walks every field except an ignore\n * list; CDC-aware differs can skip comparison for fields the provider didn't\n * flag as changed.\n *\n * `FieldDiffSchema` is the structural enforcement of the `changed_fields`\n * column per ADR-0003 — enforced at write time by the recorder service so\n * consumers can rely on the shape in downstream queries.\n */\nimport { z } from 'zod';\n\n// ============================================================================\n// FieldDiff shape — the ADR-0003 contract\n// ============================================================================\n\n/**\n * Structured per-field change. Enforced shape for `integration_run_items.changed_fields`.\n *\n * `created` items set `from: null, to: <value>` for every non-null field.\n * `deleted` items set `from: <value>, to: null`.\n * `noop` items carry `{}`.\n */\nexport const FieldDiffValueSchema = z.object({\n from: z.unknown(),\n to: z.unknown(),\n});\n\nexport const FieldDiffSchema = z.record(z.string(), FieldDiffValueSchema);\n\nexport type FieldDiffValue = z.infer<typeof FieldDiffValueSchema>;\nexport type FieldDiff = z.infer<typeof FieldDiffSchema>;\n\n/** Result of comparing a new record against its existing local state. */\nexport type DiffResult = FieldDiff | 'noop';\n\n// ============================================================================\n// IFieldDiffer\n// ============================================================================\n\n/**\n * Pluggable differ. Default ships in SYNC-5 as `DeepEqualDiffer<T>` —\n * deep-equal over every field except an ignore list (`updated_at` and other\n * row metadata). CDC-aware differs restrict comparison to\n * `providerChangedFields` when supplied.\n */\nexport interface IFieldDiffer<T> {\n /**\n * @param existing — current local state, or `null` when the record is new\n * @param incoming — the canonical record coming from the adapter\n * @param providerChangedFields — optional hint from CDC-capable sources;\n * when present, differ may restrict the comparison to these fields\n */\n diff(\n existing: T | null,\n incoming: T,\n providerChangedFields?: string[],\n ): DiffResult;\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
|