@pattern-stack/codegen 0.10.0 → 0.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (307) hide show
  1. package/CHANGELOG.md +135 -0
  2. package/README.md +5 -5
  3. package/consumer-skills/codegen/SKILL.md +2 -2
  4. package/consumer-skills/events/typed-bus-and-outbox.md +1 -1
  5. package/consumer-skills/{sync → integration}/SKILL.md +29 -29
  6. package/consumer-skills/{sync → integration}/audit-and-detection.md +22 -22
  7. package/consumer-skills/{sync → integration}/change-sources-and-sinks.md +60 -60
  8. package/consumer-skills/subsystems/SKILL.md +64 -8
  9. package/consumer-skills/subsystems/wiring-and-order.md +7 -7
  10. package/dist/runtime/base-classes/index.d.ts +4 -4
  11. package/dist/runtime/base-classes/index.js +35 -35
  12. package/dist/runtime/base-classes/index.js.map +1 -1
  13. package/dist/runtime/base-classes/{synced-entity-repository.d.ts → integrated-entity-repository.d.ts} +15 -15
  14. package/dist/runtime/base-classes/{synced-entity-repository.js → integrated-entity-repository.js} +21 -21
  15. package/dist/runtime/base-classes/integrated-entity-repository.js.map +1 -0
  16. package/dist/runtime/base-classes/{synced-entity-service.d.ts → integrated-entity-service.d.ts} +6 -6
  17. package/dist/runtime/base-classes/{synced-entity-service.js → integrated-entity-service.js} +4 -4
  18. package/dist/runtime/base-classes/integrated-entity-service.js.map +1 -0
  19. package/dist/runtime/base-classes/{sync-upsert-config.d.ts → integration-upsert-config.d.ts} +13 -13
  20. package/dist/runtime/base-classes/integration-upsert-config.js +1 -0
  21. package/dist/runtime/base-classes/{junction-sync-repository.d.ts → junction-integration-repository.d.ts} +11 -11
  22. package/dist/runtime/base-classes/{junction-sync-repository.js → junction-integration-repository.js} +15 -15
  23. package/dist/runtime/base-classes/junction-integration-repository.js.map +1 -0
  24. package/dist/runtime/subsystems/auth/auth-oauth-state.schema.js.map +1 -1
  25. package/dist/runtime/subsystems/auth/auth.module.d.ts +4 -4
  26. package/dist/runtime/subsystems/auth/auth.module.js +3 -3
  27. package/dist/runtime/subsystems/auth/auth.module.js.map +1 -1
  28. package/dist/runtime/subsystems/auth/auth.tokens.d.ts +8 -8
  29. package/dist/runtime/subsystems/auth/auth.tokens.js +6 -6
  30. package/dist/runtime/subsystems/auth/auth.tokens.js.map +1 -1
  31. package/dist/runtime/subsystems/auth/backends/state-store.drizzle-backend.js.map +1 -1
  32. package/dist/runtime/subsystems/auth/controllers/auth.controller.d.ts +2 -2
  33. package/dist/runtime/subsystems/auth/controllers/auth.controller.js +3 -3
  34. package/dist/runtime/subsystems/auth/controllers/auth.controller.js.map +1 -1
  35. package/dist/runtime/subsystems/auth/index.d.ts +3 -3
  36. package/dist/runtime/subsystems/auth/index.js +40 -40
  37. package/dist/runtime/subsystems/auth/index.js.map +1 -1
  38. package/dist/runtime/subsystems/auth/middleware/requester-context.js.map +1 -1
  39. package/dist/runtime/subsystems/auth/protocols/auth-strategy.d.ts +3 -3
  40. package/dist/runtime/subsystems/auth/protocols/{integration-store.d.ts → connection-store.d.ts} +20 -20
  41. package/dist/runtime/subsystems/auth/protocols/connection-store.js +1 -0
  42. package/dist/runtime/subsystems/auth/protocols/provider-strategy.d.ts +3 -3
  43. package/dist/runtime/subsystems/auth/runtime/{integration-broken.error.d.ts → connection-broken.error.d.ts} +5 -5
  44. package/dist/runtime/subsystems/auth/runtime/connection-broken.error.js +19 -0
  45. package/dist/runtime/subsystems/auth/runtime/connection-broken.error.js.map +1 -0
  46. package/dist/runtime/subsystems/auth/runtime/oauth2-refresh.strategy.d.ts +10 -10
  47. package/dist/runtime/subsystems/auth/runtime/oauth2-refresh.strategy.js +28 -28
  48. package/dist/runtime/subsystems/auth/runtime/oauth2-refresh.strategy.js.map +1 -1
  49. package/dist/runtime/subsystems/auth/runtime/with-auth-retry.d.ts +1 -1
  50. package/dist/runtime/subsystems/auth/runtime/with-auth-retry.js +3 -3
  51. package/dist/runtime/subsystems/auth/runtime/with-auth-retry.js.map +1 -1
  52. package/dist/runtime/subsystems/bridge/bridge.module.d.ts +0 -1
  53. package/dist/runtime/subsystems/bridge/bridge.module.js +294 -710
  54. package/dist/runtime/subsystems/bridge/bridge.module.js.map +1 -1
  55. package/dist/runtime/subsystems/bridge/index.d.ts +0 -1
  56. package/dist/runtime/subsystems/bridge/index.js +248 -664
  57. package/dist/runtime/subsystems/bridge/index.js.map +1 -1
  58. package/dist/runtime/subsystems/events/event-bus.drizzle-backend.js +18 -10
  59. package/dist/runtime/subsystems/events/event-bus.drizzle-backend.js.map +1 -1
  60. package/dist/runtime/subsystems/events/events.module.js +43 -244
  61. package/dist/runtime/subsystems/events/events.module.js.map +1 -1
  62. package/dist/runtime/subsystems/events/index.d.ts +0 -1
  63. package/dist/runtime/subsystems/events/index.js +39 -241
  64. package/dist/runtime/subsystems/events/index.js.map +1 -1
  65. package/dist/runtime/subsystems/index.d.ts +7 -7
  66. package/dist/runtime/subsystems/index.js +222 -839
  67. package/dist/runtime/subsystems/index.js.map +1 -1
  68. package/dist/runtime/subsystems/{sync → integration}/build-change-source.d.ts +3 -3
  69. package/dist/runtime/subsystems/{sync → integration}/build-change-source.js +3 -3
  70. package/dist/runtime/subsystems/integration/build-change-source.js.map +1 -0
  71. package/dist/runtime/subsystems/{sync → integration}/deep-equal.differ.d.ts +2 -2
  72. package/dist/runtime/subsystems/{sync → integration}/deep-equal.differ.js +1 -1
  73. package/dist/runtime/subsystems/integration/deep-equal.differ.js.map +1 -0
  74. package/dist/runtime/subsystems/{sync → integration}/detection-config.schema.d.ts +3 -3
  75. package/dist/runtime/subsystems/{sync → integration}/detection-config.schema.js +1 -1
  76. package/dist/runtime/subsystems/integration/detection-config.schema.js.map +1 -0
  77. package/dist/runtime/subsystems/{sync/execute-sync.use-case.d.ts → integration/execute-integration.use-case.d.ts} +13 -13
  78. package/dist/runtime/subsystems/{sync/execute-sync.use-case.js → integration/execute-integration.use-case.js} +30 -30
  79. package/dist/runtime/subsystems/integration/execute-integration.use-case.js.map +1 -0
  80. package/dist/runtime/subsystems/integration/index.d.ts +28 -0
  81. package/dist/runtime/subsystems/{sync → integration}/index.js +171 -171
  82. package/dist/runtime/subsystems/integration/index.js.map +1 -0
  83. package/dist/runtime/subsystems/{sync/sync-audit.schema.d.ts → integration/integration-audit.schema.d.ts} +64 -64
  84. package/dist/runtime/subsystems/{sync/sync-audit.schema.js → integration/integration-audit.schema.js} +47 -47
  85. package/dist/runtime/subsystems/integration/integration-audit.schema.js.map +1 -0
  86. package/dist/runtime/subsystems/{sync/sync-change-source.protocol.d.ts → integration/integration-change-source.protocol.d.ts} +10 -10
  87. package/dist/runtime/subsystems/integration/integration-change-source.protocol.js +1 -0
  88. package/dist/runtime/subsystems/{sync/sync-cursor-store.drizzle-backend.d.ts → integration/integration-cursor-store.drizzle-backend.d.ts} +1 -1
  89. package/dist/runtime/subsystems/{sync/sync-cursor-store.drizzle-backend.js → integration/integration-cursor-store.drizzle-backend.js} +65 -65
  90. package/dist/runtime/subsystems/integration/integration-cursor-store.drizzle-backend.js.map +1 -0
  91. package/dist/runtime/subsystems/{sync/sync-cursor-store.memory-backend.d.ts → integration/integration-cursor-store.memory-backend.d.ts} +6 -6
  92. package/dist/runtime/subsystems/{sync/sync-cursor-store.memory-backend.js → integration/integration-cursor-store.memory-backend.js} +5 -5
  93. package/dist/runtime/subsystems/integration/integration-cursor-store.memory-backend.js.map +1 -0
  94. package/dist/runtime/subsystems/{sync/sync-cursor-store.protocol.d.ts → integration/integration-cursor-store.protocol.d.ts} +13 -13
  95. package/dist/runtime/subsystems/integration/integration-cursor-store.protocol.js +1 -0
  96. package/dist/runtime/subsystems/{sync/sync-errors.d.ts → integration/integration-errors.d.ts} +2 -2
  97. package/dist/runtime/subsystems/{sync/sync-errors.js → integration/integration-errors.js} +3 -3
  98. package/dist/runtime/subsystems/integration/integration-errors.js.map +1 -0
  99. package/dist/runtime/subsystems/{sync/sync-field-diff.protocol.d.ts → integration/integration-field-diff.protocol.d.ts} +2 -2
  100. package/dist/runtime/subsystems/{sync/sync-field-diff.protocol.js → integration/integration-field-diff.protocol.js} +2 -2
  101. package/dist/runtime/subsystems/integration/integration-field-diff.protocol.js.map +1 -0
  102. package/dist/runtime/subsystems/{sync/sync-loopback.protocol.d.ts → integration/integration-loopback.protocol.d.ts} +2 -2
  103. package/dist/runtime/subsystems/integration/integration-loopback.protocol.js +1 -0
  104. package/dist/runtime/subsystems/{sync/sync-middleware.protocol.d.ts → integration/integration-middleware.protocol.d.ts} +5 -5
  105. package/dist/runtime/subsystems/integration/integration-middleware.protocol.js +1 -0
  106. package/dist/runtime/subsystems/{sync/sync-run-recorder.drizzle-backend.d.ts → integration/integration-run-recorder.drizzle-backend.d.ts} +5 -5
  107. package/dist/runtime/subsystems/{sync/sync-run-recorder.drizzle-backend.js → integration/integration-run-recorder.drizzle-backend.js} +73 -73
  108. package/dist/runtime/subsystems/integration/integration-run-recorder.drizzle-backend.js.map +1 -0
  109. package/dist/runtime/subsystems/{sync/sync-run-recorder.memory-backend.d.ts → integration/integration-run-recorder.memory-backend.d.ts} +15 -15
  110. package/dist/runtime/subsystems/{sync/sync-run-recorder.memory-backend.js → integration/integration-run-recorder.memory-backend.js} +11 -11
  111. package/dist/runtime/subsystems/integration/integration-run-recorder.memory-backend.js.map +1 -0
  112. package/dist/runtime/subsystems/{sync/sync-run-recorder.protocol.d.ts → integration/integration-run-recorder.protocol.d.ts} +25 -25
  113. package/dist/runtime/subsystems/integration/integration-run-recorder.protocol.js +1 -0
  114. package/dist/runtime/subsystems/{sync/sync-sink.protocol.d.ts → integration/integration-sink.protocol.d.ts} +5 -5
  115. package/dist/runtime/subsystems/integration/integration-sink.protocol.js +1 -0
  116. package/dist/runtime/subsystems/{sync/sync.module.d.ts → integration/integration.module.d.ts} +24 -24
  117. package/dist/runtime/subsystems/{sync/sync.module.js → integration/integration.module.js} +132 -132
  118. package/dist/runtime/subsystems/integration/integration.module.js.map +1 -0
  119. package/dist/runtime/subsystems/integration/integration.tokens.d.ts +47 -0
  120. package/dist/runtime/subsystems/integration/integration.tokens.js +18 -0
  121. package/dist/runtime/subsystems/integration/integration.tokens.js.map +1 -0
  122. package/dist/runtime/subsystems/{sync → integration}/loopback.middleware.d.ts +5 -5
  123. package/dist/runtime/subsystems/{sync → integration}/loopback.middleware.js +1 -1
  124. package/dist/runtime/subsystems/integration/loopback.middleware.js.map +1 -0
  125. package/dist/runtime/subsystems/{sync → integration}/poll-change-source.d.ts +5 -5
  126. package/dist/runtime/subsystems/{sync → integration}/poll-change-source.js +1 -1
  127. package/dist/runtime/subsystems/integration/poll-change-source.js.map +1 -0
  128. package/dist/runtime/subsystems/{sync → integration}/webhook-change-source.d.ts +5 -5
  129. package/dist/runtime/subsystems/{sync → integration}/webhook-change-source.js +1 -1
  130. package/dist/runtime/subsystems/integration/webhook-change-source.js.map +1 -0
  131. package/dist/runtime/subsystems/jobs/bullmq.config.d.ts +22 -3
  132. package/dist/runtime/subsystems/jobs/bullmq.config.js.map +1 -1
  133. package/dist/runtime/subsystems/jobs/index.d.ts +1 -4
  134. package/dist/runtime/subsystems/jobs/index.js +87 -506
  135. package/dist/runtime/subsystems/jobs/index.js.map +1 -1
  136. package/dist/runtime/subsystems/jobs/job-orchestrator.bullmq-backend.js.map +1 -1
  137. package/dist/runtime/subsystems/jobs/job-worker.bullmq-backend.js +3 -0
  138. package/dist/runtime/subsystems/jobs/job-worker.bullmq-backend.js.map +1 -1
  139. package/dist/runtime/subsystems/jobs/job-worker.module.d.ts +10 -3
  140. package/dist/runtime/subsystems/jobs/job-worker.module.js +248 -664
  141. package/dist/runtime/subsystems/jobs/job-worker.module.js.map +1 -1
  142. package/dist/runtime/subsystems/jobs/jobs-domain.module.d.ts +0 -1
  143. package/dist/runtime/subsystems/jobs/jobs-domain.module.js +89 -391
  144. package/dist/runtime/subsystems/jobs/jobs-domain.module.js.map +1 -1
  145. package/dist/runtime/subsystems/observability/index.d.ts +4 -4
  146. package/dist/runtime/subsystems/observability/index.js +11 -11
  147. package/dist/runtime/subsystems/observability/index.js.map +1 -1
  148. package/dist/runtime/subsystems/observability/observability.module.d.ts +2 -2
  149. package/dist/runtime/subsystems/observability/observability.module.js +11 -11
  150. package/dist/runtime/subsystems/observability/observability.module.js.map +1 -1
  151. package/dist/runtime/subsystems/observability/observability.protocol.d.ts +11 -11
  152. package/dist/runtime/subsystems/observability/observability.service.d.ts +6 -6
  153. package/dist/runtime/subsystems/observability/observability.service.js +11 -11
  154. package/dist/runtime/subsystems/observability/observability.service.js.map +1 -1
  155. package/dist/runtime/subsystems/observability/observability.tokens.d.ts +1 -1
  156. package/dist/runtime/subsystems/observability/observability.tokens.js.map +1 -1
  157. package/dist/runtime/subsystems/observability/reporters/bridge-metrics.reporter.d.ts +3 -3
  158. package/dist/runtime/subsystems/observability/reporters/bridge-metrics.reporter.js.map +1 -1
  159. package/dist/runtime/subsystems/observability/reporters/index.d.ts +3 -3
  160. package/dist/runtime/subsystems/observability/reporters/index.js.map +1 -1
  161. package/dist/src/cli/index.js +412 -302
  162. package/dist/src/cli/index.js.map +1 -1
  163. package/dist/src/index.d.ts +22 -22
  164. package/dist/src/index.js +191 -191
  165. package/dist/src/index.js.map +1 -1
  166. package/examples/auth-integrations/README.md +32 -32
  167. package/examples/auth-integrations/definitions/entities/{integration.yaml → connection.yaml} +10 -10
  168. package/examples/auth-integrations/runtime/{integrations/adapters/integration-grant-sink.adapter.ts → connections/adapters/connection-grant-sink.adapter.ts} +7 -7
  169. package/examples/auth-integrations/runtime/{integrations/adapters/integration-reader.adapter.ts → connections/adapters/connection-reader.adapter.ts} +10 -10
  170. package/examples/auth-integrations/runtime/{integrations/adapters/integration-token-writer.adapter.ts → connections/adapters/connection-token-writer.adapter.ts} +11 -11
  171. package/examples/auth-integrations/runtime/connections/connections-auth.module.ts +81 -0
  172. package/examples/auth-integrations/runtime/{integrations/facade/integrations.service.ts → connections/facade/connections.service.ts} +35 -35
  173. package/examples/auth-integrations/runtime/{integrations → connections}/oauth/use-cases/create-or-update-from-oauth-grant.use-case.ts +11 -11
  174. package/examples/auth-integrations/runtime/{integrations/oauth/use-cases/disconnect-integration.use-case.ts → connections/oauth/use-cases/disconnect-connection.use-case.ts} +6 -6
  175. package/examples/auth-integrations/runtime/connections/oauth/use-cases/list-user-connections.use-case.ts +21 -0
  176. package/examples/auth-integrations/runtime/connections/oauth/use-cases/mark-connection-requires-reauth.use-case.ts +21 -0
  177. package/package.json +1 -1
  178. package/runtime/base-classes/index.ts +8 -8
  179. package/runtime/base-classes/{synced-entity-repository.ts → integrated-entity-repository.ts} +36 -36
  180. package/runtime/base-classes/{synced-entity-service.ts → integrated-entity-service.ts} +6 -6
  181. package/runtime/base-classes/{sync-upsert-config.ts → integration-upsert-config.ts} +12 -12
  182. package/runtime/base-classes/{junction-sync-repository.ts → junction-integration-repository.ts} +28 -28
  183. package/runtime/subsystems/auth/auth-oauth-state.schema.ts +1 -1
  184. package/runtime/subsystems/auth/auth.module.ts +4 -4
  185. package/runtime/subsystems/auth/auth.tokens.ts +7 -7
  186. package/runtime/subsystems/auth/controllers/auth.controller.ts +7 -7
  187. package/runtime/subsystems/auth/index.ts +19 -19
  188. package/runtime/subsystems/auth/protocols/auth-strategy.ts +3 -3
  189. package/runtime/subsystems/auth/protocols/{integration-store.ts → connection-store.ts} +19 -19
  190. package/runtime/subsystems/auth/protocols/provider-strategy.ts +2 -2
  191. package/runtime/subsystems/auth/runtime/{integration-broken.error.ts → connection-broken.error.ts} +5 -5
  192. package/runtime/subsystems/auth/runtime/oauth2-refresh.strategy.ts +35 -35
  193. package/runtime/subsystems/auth/runtime/with-auth-retry.ts +3 -3
  194. package/runtime/subsystems/events/event-bus.drizzle-backend.ts +32 -10
  195. package/runtime/subsystems/events/events.module.ts +38 -6
  196. package/runtime/subsystems/events/index.ts +7 -1
  197. package/runtime/subsystems/index.ts +11 -11
  198. package/runtime/subsystems/{sync → integration}/build-change-source.ts +3 -3
  199. package/runtime/subsystems/{sync → integration}/deep-equal.differ.ts +7 -7
  200. package/runtime/subsystems/{sync → integration}/detection-config.schema.ts +3 -3
  201. package/runtime/subsystems/{sync/execute-sync.use-case.ts → integration/execute-integration.use-case.ts} +40 -40
  202. package/runtime/subsystems/{sync → integration}/index.ts +47 -47
  203. package/runtime/subsystems/{sync/sync-audit.schema.ts → integration/integration-audit.schema.ts} +61 -61
  204. package/runtime/subsystems/{sync/sync-change-source.protocol.ts → integration/integration-change-source.protocol.ts} +9 -9
  205. package/runtime/subsystems/{sync/sync-cursor-store.drizzle-backend.ts → integration/integration-cursor-store.drizzle-backend.ts} +30 -30
  206. package/runtime/subsystems/{sync/sync-cursor-store.memory-backend.ts → integration/integration-cursor-store.memory-backend.ts} +9 -9
  207. package/runtime/subsystems/{sync/sync-cursor-store.protocol.ts → integration/integration-cursor-store.protocol.ts} +13 -13
  208. package/runtime/subsystems/{sync/sync-errors.ts → integration/integration-errors.ts} +3 -3
  209. package/runtime/subsystems/{sync/sync-field-diff.protocol.ts → integration/integration-field-diff.protocol.ts} +2 -2
  210. package/runtime/subsystems/{sync/sync-loopback.protocol.ts → integration/integration-loopback.protocol.ts} +2 -2
  211. package/runtime/subsystems/{sync/sync-middleware.protocol.ts → integration/integration-middleware.protocol.ts} +6 -6
  212. package/runtime/subsystems/{sync/sync-run-recorder.drizzle-backend.ts → integration/integration-run-recorder.drizzle-backend.ts} +39 -39
  213. package/runtime/subsystems/{sync/sync-run-recorder.memory-backend.ts → integration/integration-run-recorder.memory-backend.ts} +23 -23
  214. package/runtime/subsystems/{sync/sync-run-recorder.protocol.ts → integration/integration-run-recorder.protocol.ts} +25 -25
  215. package/runtime/subsystems/{sync/sync-sink.protocol.ts → integration/integration-sink.protocol.ts} +4 -4
  216. package/runtime/subsystems/{sync/sync.module.ts → integration/integration.module.ts} +48 -48
  217. package/runtime/subsystems/integration/integration.tokens.ts +49 -0
  218. package/runtime/subsystems/{sync → integration}/loopback.middleware.ts +5 -5
  219. package/runtime/subsystems/{sync → integration}/poll-change-source.ts +7 -7
  220. package/runtime/subsystems/{sync → integration}/webhook-change-source.ts +7 -7
  221. package/runtime/subsystems/jobs/bullmq.config.ts +23 -3
  222. package/runtime/subsystems/jobs/index.ts +13 -8
  223. package/runtime/subsystems/jobs/job-worker.bullmq-backend.ts +5 -2
  224. package/runtime/subsystems/jobs/job-worker.module.ts +27 -7
  225. package/runtime/subsystems/jobs/jobs-domain.module.ts +27 -2
  226. package/runtime/subsystems/observability/index.ts +1 -1
  227. package/runtime/subsystems/observability/observability.module.ts +2 -2
  228. package/runtime/subsystems/observability/observability.protocol.ts +11 -11
  229. package/runtime/subsystems/observability/observability.service.ts +13 -13
  230. package/runtime/subsystems/observability/observability.tokens.ts +1 -1
  231. package/src/patterns/library/index.ts +4 -4
  232. package/src/patterns/library/{synced.pattern.ts → integrated.pattern.ts} +12 -12
  233. package/src/patterns/library/junction.pattern.ts +1 -1
  234. package/src/patterns/pattern-definition.ts +3 -3
  235. package/templates/entity/new/backend/modules/core/{sync-source.ejs.t → integration-source.ejs.t} +6 -6
  236. package/templates/entity/new/backend/modules/core/{sync-source.providers.ejs.t → integration-source.providers.ejs.t} +2 -2
  237. package/templates/entity/new/clean-lite-ps/entity.ejs.t +1 -1
  238. package/templates/entity/new/clean-lite-ps/module.ejs.t +1 -1
  239. package/templates/entity/new/clean-lite-ps/prompt-extension.js +33 -33
  240. package/templates/entity/new/clean-lite-ps/repository.ejs.t +27 -27
  241. package/templates/entity/new/frontend/collections/collection.ejs.t +26 -1
  242. package/templates/entity/new/frontend/collections/collections-base.ejs.t +11 -0
  243. package/templates/entity/new/frontend/entity/combined.ejs.t +31 -1
  244. package/templates/entity/new/prompt.js +27 -15
  245. package/templates/junction/new/entity.ejs.t +1 -1
  246. package/templates/junction/new/prompt.js +24 -24
  247. package/templates/junction/new/repository.ejs.t +19 -19
  248. package/templates/subsystem/auth/auth-oauth-state.schema.ejs.t +2 -2
  249. package/templates/subsystem/auth-config/prompt.js +1 -1
  250. package/templates/subsystem/auth-integrations/app-module-hook.ejs.t +5 -5
  251. package/templates/subsystem/bridge/prompt.js +1 -1
  252. package/templates/subsystem/events/domain-events.schema.ejs.t +43 -2
  253. package/templates/subsystem/integration/integration-audit.schema.ejs.t +192 -0
  254. package/templates/subsystem/{sync → integration}/prompt.js +12 -12
  255. package/templates/subsystem/{sync-config/codegen-config-sync-block.ejs.t → integration-config/codegen-config-integration-block.ejs.t} +7 -7
  256. package/templates/subsystem/integration-config/prompt.js +22 -0
  257. package/templates/subsystem/jobs/worker.ejs.t +2 -2
  258. package/templates/subsystem/observability/main-hook.ejs.t +1 -1
  259. package/templates/subsystem/observability/prompt.js +1 -1
  260. package/templates/subsystem/openapi-config/prompt.js +1 -1
  261. package/dist/runtime/base-classes/junction-sync-repository.js.map +0 -1
  262. package/dist/runtime/base-classes/sync-upsert-config.js +0 -1
  263. package/dist/runtime/base-classes/synced-entity-repository.js.map +0 -1
  264. package/dist/runtime/base-classes/synced-entity-service.js.map +0 -1
  265. package/dist/runtime/subsystems/auth/protocols/integration-store.js +0 -1
  266. package/dist/runtime/subsystems/auth/runtime/integration-broken.error.js +0 -19
  267. package/dist/runtime/subsystems/auth/runtime/integration-broken.error.js.map +0 -1
  268. package/dist/runtime/subsystems/sync/build-change-source.js.map +0 -1
  269. package/dist/runtime/subsystems/sync/deep-equal.differ.js.map +0 -1
  270. package/dist/runtime/subsystems/sync/detection-config.schema.js.map +0 -1
  271. package/dist/runtime/subsystems/sync/execute-sync.use-case.js.map +0 -1
  272. package/dist/runtime/subsystems/sync/index.d.ts +0 -28
  273. package/dist/runtime/subsystems/sync/index.js.map +0 -1
  274. package/dist/runtime/subsystems/sync/loopback.middleware.js.map +0 -1
  275. package/dist/runtime/subsystems/sync/poll-change-source.js.map +0 -1
  276. package/dist/runtime/subsystems/sync/sync-audit.schema.js.map +0 -1
  277. package/dist/runtime/subsystems/sync/sync-change-source.protocol.js +0 -1
  278. package/dist/runtime/subsystems/sync/sync-cursor-store.drizzle-backend.js.map +0 -1
  279. package/dist/runtime/subsystems/sync/sync-cursor-store.memory-backend.js.map +0 -1
  280. package/dist/runtime/subsystems/sync/sync-cursor-store.protocol.js +0 -1
  281. package/dist/runtime/subsystems/sync/sync-errors.js.map +0 -1
  282. package/dist/runtime/subsystems/sync/sync-field-diff.protocol.js.map +0 -1
  283. package/dist/runtime/subsystems/sync/sync-loopback.protocol.js +0 -1
  284. package/dist/runtime/subsystems/sync/sync-middleware.protocol.js +0 -1
  285. package/dist/runtime/subsystems/sync/sync-run-recorder.drizzle-backend.js.map +0 -1
  286. package/dist/runtime/subsystems/sync/sync-run-recorder.memory-backend.js.map +0 -1
  287. package/dist/runtime/subsystems/sync/sync-run-recorder.protocol.js +0 -1
  288. package/dist/runtime/subsystems/sync/sync-sink.protocol.js +0 -1
  289. package/dist/runtime/subsystems/sync/sync.module.js.map +0 -1
  290. package/dist/runtime/subsystems/sync/sync.tokens.d.ts +0 -47
  291. package/dist/runtime/subsystems/sync/sync.tokens.js +0 -18
  292. package/dist/runtime/subsystems/sync/sync.tokens.js.map +0 -1
  293. package/dist/runtime/subsystems/sync/webhook-change-source.js.map +0 -1
  294. package/examples/auth-integrations/runtime/integrations/integrations-auth.module.ts +0 -81
  295. package/examples/auth-integrations/runtime/integrations/oauth/use-cases/list-user-integrations.use-case.ts +0 -21
  296. package/examples/auth-integrations/runtime/integrations/oauth/use-cases/mark-integration-requires-reauth.use-case.ts +0 -21
  297. package/runtime/subsystems/sync/sync.tokens.ts +0 -49
  298. package/templates/subsystem/sync/sync-audit.schema.ejs.t +0 -192
  299. package/templates/subsystem/sync-config/prompt.js +0 -22
  300. /package/dist/runtime/base-classes/{sync-upsert-config.js.map → integration-upsert-config.js.map} +0 -0
  301. /package/dist/runtime/subsystems/auth/protocols/{integration-store.js.map → connection-store.js.map} +0 -0
  302. /package/dist/runtime/subsystems/{sync/sync-change-source.protocol.js.map → integration/integration-change-source.protocol.js.map} +0 -0
  303. /package/dist/runtime/subsystems/{sync/sync-cursor-store.protocol.js.map → integration/integration-cursor-store.protocol.js.map} +0 -0
  304. /package/dist/runtime/subsystems/{sync/sync-loopback.protocol.js.map → integration/integration-loopback.protocol.js.map} +0 -0
  305. /package/dist/runtime/subsystems/{sync/sync-middleware.protocol.js.map → integration/integration-middleware.protocol.js.map} +0 -0
  306. /package/dist/runtime/subsystems/{sync/sync-run-recorder.protocol.js.map → integration/integration-run-recorder.protocol.js.map} +0 -0
  307. /package/dist/runtime/subsystems/{sync/sync-sink.protocol.js.map → integration/integration-sink.protocol.js.map} +0 -0
@@ -1,25 +1,25 @@
1
1
  /**
2
- * Auth subsystem — integration storage ports.
2
+ * Auth subsystem — connection storage ports.
3
3
  *
4
- * `OAuth2RefreshStrategy` reads decrypted integration rows and persists
4
+ * `OAuth2RefreshStrategy` reads decrypted connection rows and persists
5
5
  * refreshed tokens. The subsystem doesn't care what entity framework stores
6
6
  * those rows — consumers implement these narrow ports against whatever
7
- * `integrations` table their app uses.
7
+ * `connections` table their app uses.
8
8
  *
9
9
  * In the extraction-source app both ports are satisfied by a
10
- * pair of thin adapters over `IntegrationService` + `RefreshIntegrationUseCase`.
10
+ * pair of thin adapters over `ConnectionService` + `RefreshConnectionUseCase`.
11
11
  * The codegen-patterns `examples/auth-integrations/` starter (separate PR)
12
- * ships a canonical `integration.yaml` whose generated service + use case
12
+ * ships a canonical `connection.yaml` whose generated service + use case
13
13
  * satisfy the shape out of the box.
14
14
  */
15
15
  /**
16
- * An integration row with its secrets decrypted and ready to use.
16
+ * An connection row with its secrets decrypted and ready to use.
17
17
  *
18
18
  * Consumers produce this shape from their own storage by passing stored
19
19
  * ciphertexts through `IEncryptionKey.decrypt`. The subsystem never sees
20
20
  * the ciphertext form.
21
21
  */
22
- interface DecryptedIntegration {
22
+ interface DecryptedConnection {
23
23
  id: string;
24
24
  /** Provider slug — must match the strategy's `provider`. */
25
25
  provider: string;
@@ -33,13 +33,13 @@ interface DecryptedIntegration {
33
33
  providerMetadata?: Record<string, unknown> | null;
34
34
  }
35
35
  /**
36
- * Read port — fetches a decrypted integration by id.
36
+ * Read port — fetches a decrypted connection by id.
37
37
  *
38
38
  * Adapters typically wrap a service/repo call that does the decryption
39
39
  * internally. `OAuth2RefreshStrategy.resolve()` calls this on every invocation.
40
40
  */
41
- interface IIntegrationReader {
42
- findByIdDecrypted(integrationId: string): Promise<DecryptedIntegration | null>;
41
+ interface IConnectionReader {
42
+ findByIdDecrypted(connectionId: string): Promise<DecryptedConnection | null>;
43
43
  }
44
44
  /**
45
45
  * Write port — persists a refreshed access token (and optionally rotated
@@ -51,14 +51,14 @@ interface IIntegrationReader {
51
51
  * `refreshToken` semantics: `undefined` means "provider did not rotate; keep
52
52
  * existing ciphertext". A rotated token comes through as a string.
53
53
  */
54
- interface IntegrationTokenUpdate {
55
- integrationId: string;
54
+ interface ConnectionTokenUpdate {
55
+ connectionId: string;
56
56
  accessToken: string;
57
57
  refreshToken?: string;
58
58
  expiresAt: Date;
59
59
  }
60
- interface IIntegrationTokenWriter {
61
- persistRefresh(update: IntegrationTokenUpdate): Promise<void>;
60
+ interface IConnectionTokenWriter {
61
+ persistRefresh(update: ConnectionTokenUpdate): Promise<void>;
62
62
  }
63
63
  /**
64
64
  * Grant-sink port — persists a freshly-minted OAuth2 grant from the
@@ -66,10 +66,10 @@ interface IIntegrationTokenWriter {
66
66
  * re-connected an existing one).
67
67
  *
68
68
  * `AuthController.callback` invokes this after `IProviderStrategy.exchangeCodeForTokens`.
69
- * The subsystem itself never imports a concrete `IntegrationsService` — the
69
+ * The subsystem itself never imports a concrete `ConnectionsService` — the
70
70
  * consumer's `auth-integrations` starter (or any equivalent) adapts this
71
71
  * port. Keeps the auth subsystem standalone: a non-codegen consumer can
72
- * satisfy the port against its own integrations storage.
72
+ * satisfy the port against its own connections storage.
73
73
  *
74
74
  * Semantics:
75
75
  * - Upserts on `(userId, provider)`. Repeated grants for the same pair
@@ -80,7 +80,7 @@ interface IIntegrationTokenWriter {
80
80
  * them (e.g. some providers omit `expires_in`; not every flow returns
81
81
  * a refresh token on first grant).
82
82
  */
83
- interface IntegrationGrantInput {
83
+ interface ConnectionGrantInput {
84
84
  userId: string;
85
85
  /** Provider slug — must match the strategy's `provider`. */
86
86
  provider: string;
@@ -92,8 +92,8 @@ interface IntegrationGrantInput {
92
92
  /** Provider-specific bag (SFDC `instance_url`, Google `sub`, …). */
93
93
  providerMetadata?: Record<string, unknown>;
94
94
  }
95
- interface IIntegrationGrantSink {
96
- createOrUpdateFromOAuthGrant(input: IntegrationGrantInput): Promise<void>;
95
+ interface IConnectionGrantSink {
96
+ createOrUpdateFromOAuthGrant(input: ConnectionGrantInput): Promise<void>;
97
97
  }
98
98
 
99
- export type { DecryptedIntegration, IIntegrationGrantSink, IIntegrationReader, IIntegrationTokenWriter, IntegrationGrantInput, IntegrationTokenUpdate };
99
+ export type { ConnectionGrantInput, ConnectionTokenUpdate, DecryptedConnection, IConnectionGrantSink, IConnectionReader, IConnectionTokenWriter };
@@ -0,0 +1 @@
1
+ //# sourceMappingURL=connection-store.js.map
@@ -1,6 +1,6 @@
1
1
  import { OAuth2RefreshStrategy } from '../runtime/oauth2-refresh.strategy.js';
2
2
  import './auth-strategy.js';
3
- import './integration-store.js';
3
+ import './connection-store.js';
4
4
 
5
5
  /**
6
6
  * Auth subsystem — `IProviderStrategy` contract.
@@ -22,9 +22,9 @@ import './integration-store.js';
22
22
  * and dispatches by slug.
23
23
  *
24
24
  * **Naming convention:** interfaces that describe behavioral ports use the
25
- * `I` prefix (`IProviderStrategy`, `IIntegrationReader`, `IUserContext`,
25
+ * `I` prefix (`IProviderStrategy`, `IConnectionReader`, `IUserContext`,
26
26
  * `IOAuthStateStore`, `IEncryptionKey`). Plain data types / DTOs (e.g.
27
- * `ExchangedTokens`, `DecryptedIntegration`, `IntegrationGrantInput`) do
27
+ * `ExchangedTokens`, `DecryptedConnection`, `ConnectionGrantInput`) do
28
28
  * not. Abstract template-method classes (e.g. `OAuth2RefreshStrategy`) also
29
29
  * do not — the `I` is for interfaces only.
30
30
  */
@@ -2,16 +2,16 @@
2
2
  * Thrown when an OAuth2 provider returns `400 invalid_grant`/`invalid_token`
3
3
  * on refresh — the refresh token itself is dead (user revoked, org
4
4
  * deactivated, token expired beyond the provider's rotation window). The
5
- * integration should be marked broken so background sync stops picking it
5
+ * connection should be marked broken so background sync stops picking it
6
6
  * up; the user re-initiates OAuth.
7
7
  *
8
8
  * Shared across every OAuth2 strategy.
9
9
  */
10
- declare class IntegrationBrokenError extends Error {
11
- readonly integrationId: string;
10
+ declare class ConnectionBrokenError extends Error {
11
+ readonly connectionId: string;
12
12
  readonly errorCode: string;
13
13
  readonly errorDescription: string;
14
- constructor(integrationId: string, errorCode: string, errorDescription: string);
14
+ constructor(connectionId: string, errorCode: string, errorDescription: string);
15
15
  }
16
16
 
17
- export { IntegrationBrokenError };
17
+ export { ConnectionBrokenError };
@@ -0,0 +1,19 @@
1
+ // runtime/subsystems/auth/runtime/connection-broken.error.ts
2
+ var ConnectionBrokenError = class extends Error {
3
+ constructor(connectionId, errorCode, errorDescription) {
4
+ super(
5
+ `Connection ${connectionId} broken: ${errorCode} - ${errorDescription}`
6
+ );
7
+ this.connectionId = connectionId;
8
+ this.errorCode = errorCode;
9
+ this.errorDescription = errorDescription;
10
+ this.name = "ConnectionBrokenError";
11
+ }
12
+ connectionId;
13
+ errorCode;
14
+ errorDescription;
15
+ };
16
+ export {
17
+ ConnectionBrokenError
18
+ };
19
+ //# sourceMappingURL=connection-broken.error.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../../runtime/subsystems/auth/runtime/connection-broken.error.ts"],"sourcesContent":["/**\n * Thrown when an OAuth2 provider returns `400 invalid_grant`/`invalid_token`\n * on refresh — the refresh token itself is dead (user revoked, org\n * deactivated, token expired beyond the provider's rotation window). The\n * connection should be marked broken so background sync stops picking it\n * up; the user re-initiates OAuth.\n *\n * Shared across every OAuth2 strategy.\n */\nexport class ConnectionBrokenError extends Error {\n constructor(\n readonly connectionId: string,\n readonly errorCode: string,\n readonly errorDescription: string,\n ) {\n super(\n `Connection ${connectionId} broken: ${errorCode} - ${errorDescription}`,\n );\n this.name = 'ConnectionBrokenError';\n }\n}\n"],"mappings":";AASO,IAAM,wBAAN,cAAoC,MAAM;AAAA,EAC/C,YACW,cACA,WACA,kBACT;AACA;AAAA,MACE,cAAc,YAAY,YAAY,SAAS,MAAM,gBAAgB;AAAA,IACvE;AANS;AACA;AACA;AAKT,SAAK,OAAO;AAAA,EACd;AAAA,EARW;AAAA,EACA;AAAA,EACA;AAOb;","names":[]}
@@ -1,5 +1,5 @@
1
1
  import { IAuthStrategy, AuthResolveOptions, AuthCredentials } from '../protocols/auth-strategy.js';
2
- import { IIntegrationReader, IIntegrationTokenWriter, DecryptedIntegration } from '../protocols/integration-store.js';
2
+ import { IConnectionReader, IConnectionTokenWriter, DecryptedConnection } from '../protocols/connection-store.js';
3
3
 
4
4
  /**
5
5
  * Abstract base class for OAuth2 refresh-token strategies.
@@ -11,25 +11,25 @@ import { IIntegrationReader, IIntegrationTokenWriter, DecryptedIntegration } fro
11
11
  * later" evidence.
12
12
  *
13
13
  * Subclass contract:
14
- * - `provider` — slug matched against `integrations.provider`
14
+ * - `provider` — slug matched against `connections.provider`
15
15
  * - `defaultExpiresInSec` — fallback when refresh response omits `expires_in`
16
16
  * - `tokenEndpoint()` — URL to POST the refresh grant
17
17
  * - `refreshBodyExtras()` — provider-specific body params
18
18
  * - `parseRefreshResponse()` — raw JSON → ParsedRefreshResponse
19
19
  * - `buildCredentials()` — stored or freshly-refreshed access token +
20
- * integration + optional raw refresh response
20
+ * connection + optional raw refresh response
21
21
  * → provider credentials
22
22
  *
23
23
  * Base handles: expiry check w/ 5-min safety window, `forceRefresh` escape
24
24
  * hatch, POST form-urlencoded body, OAuth2 error mapping to
25
- * `IntegrationBrokenError`, refresh-token rotation persistence, fetch +
25
+ * `ConnectionBrokenError`, refresh-token rotation persistence, fetch +
26
26
  * clock injection for tests.
27
27
  */
28
28
 
29
29
  type FetchLike = (input: string | URL | Request, init?: RequestInit) => Promise<Response>;
30
30
  interface OAuth2RefreshStrategyOptions {
31
- integrationReader: IIntegrationReader;
32
- tokenWriter: IIntegrationTokenWriter;
31
+ connectionReader: IConnectionReader;
32
+ tokenWriter: IConnectionTokenWriter;
33
33
  /** Injectable fetch for tests. Defaults to the global `fetch`. */
34
34
  fetch?: FetchLike;
35
35
  /** Injectable clock for tests. Defaults to `Date.now`. */
@@ -48,16 +48,16 @@ interface ParsedRefreshResponse {
48
48
  declare abstract class OAuth2RefreshStrategy implements IAuthStrategy {
49
49
  protected abstract readonly provider: string;
50
50
  protected abstract readonly defaultExpiresInSec: number;
51
- protected readonly integrationReader: IIntegrationReader;
52
- protected readonly tokenWriter: IIntegrationTokenWriter;
51
+ protected readonly connectionReader: IConnectionReader;
52
+ protected readonly tokenWriter: IConnectionTokenWriter;
53
53
  protected readonly fetchImpl: FetchLike;
54
54
  protected readonly now: () => number;
55
55
  constructor(opts: OAuth2RefreshStrategyOptions);
56
- resolve(integrationId: string, opts?: AuthResolveOptions): Promise<AuthCredentials>;
56
+ resolve(connectionId: string, opts?: AuthResolveOptions): Promise<AuthCredentials>;
57
57
  protected abstract tokenEndpoint(): string;
58
58
  protected abstract refreshBodyExtras(): Record<string, string>;
59
59
  protected abstract parseRefreshResponse(raw: unknown): ParsedRefreshResponse;
60
- protected abstract buildCredentials(accessToken: string, integration: DecryptedIntegration, refreshRaw?: unknown): AuthCredentials;
60
+ protected abstract buildCredentials(accessToken: string, connection: DecryptedConnection, refreshRaw?: unknown): AuthCredentials;
61
61
  private executeRefresh;
62
62
  private isExpiring;
63
63
  }
@@ -1,15 +1,15 @@
1
- // runtime/subsystems/auth/runtime/integration-broken.error.ts
2
- var IntegrationBrokenError = class extends Error {
3
- constructor(integrationId, errorCode, errorDescription) {
1
+ // runtime/subsystems/auth/runtime/connection-broken.error.ts
2
+ var ConnectionBrokenError = class extends Error {
3
+ constructor(connectionId, errorCode, errorDescription) {
4
4
  super(
5
- `Integration ${integrationId} broken: ${errorCode} - ${errorDescription}`
5
+ `Connection ${connectionId} broken: ${errorCode} - ${errorDescription}`
6
6
  );
7
- this.integrationId = integrationId;
7
+ this.connectionId = connectionId;
8
8
  this.errorCode = errorCode;
9
9
  this.errorDescription = errorDescription;
10
- this.name = "IntegrationBrokenError";
10
+ this.name = "ConnectionBrokenError";
11
11
  }
12
- integrationId;
12
+ connectionId;
13
13
  errorCode;
14
14
  errorDescription;
15
15
  };
@@ -17,53 +17,53 @@ var IntegrationBrokenError = class extends Error {
17
17
  // runtime/subsystems/auth/runtime/oauth2-refresh.strategy.ts
18
18
  var REFRESH_SAFETY_MS = 5 * 60 * 1e3;
19
19
  var OAuth2RefreshStrategy = class {
20
- integrationReader;
20
+ connectionReader;
21
21
  tokenWriter;
22
22
  fetchImpl;
23
23
  now;
24
24
  constructor(opts) {
25
- this.integrationReader = opts.integrationReader;
25
+ this.connectionReader = opts.connectionReader;
26
26
  this.tokenWriter = opts.tokenWriter;
27
27
  this.fetchImpl = opts.fetch ?? fetch;
28
28
  this.now = opts.now ?? Date.now;
29
29
  }
30
- async resolve(integrationId, opts = {}) {
31
- const integration = await this.integrationReader.findByIdDecrypted(integrationId);
32
- if (!integration) {
33
- throw new Error(`Integration ${integrationId} not found`);
30
+ async resolve(connectionId, opts = {}) {
31
+ const connection = await this.connectionReader.findByIdDecrypted(connectionId);
32
+ if (!connection) {
33
+ throw new Error(`Connection ${connectionId} not found`);
34
34
  }
35
- if (integration.provider !== this.provider) {
35
+ if (connection.provider !== this.provider) {
36
36
  throw new Error(
37
- `${this.constructor.name} called for non-${this.provider} integration ${integrationId} (provider=${integration.provider})`
37
+ `${this.constructor.name} called for non-${this.provider} connection ${connectionId} (provider=${connection.provider})`
38
38
  );
39
39
  }
40
- const needsRefresh = opts.forceRefresh || this.isExpiring(integration.expiresAt) || !integration.accessToken;
40
+ const needsRefresh = opts.forceRefresh || this.isExpiring(connection.expiresAt) || !connection.accessToken;
41
41
  if (!needsRefresh) {
42
- return this.buildCredentials(integration.accessToken, integration);
42
+ return this.buildCredentials(connection.accessToken, connection);
43
43
  }
44
- if (!integration.refreshToken) {
45
- throw new IntegrationBrokenError(
46
- integrationId,
44
+ if (!connection.refreshToken) {
45
+ throw new ConnectionBrokenError(
46
+ connectionId,
47
47
  "no_refresh_token",
48
- "Integration has no refresh token; user must reconnect"
48
+ "Connection has no refresh token; user must reconnect"
49
49
  );
50
50
  }
51
51
  const { parsed, raw } = await this.executeRefresh(
52
- integrationId,
53
- integration.refreshToken
52
+ connectionId,
53
+ connection.refreshToken
54
54
  );
55
55
  const newExpiresAt = new Date(
56
56
  this.now() + (parsed.expiresInSec ?? this.defaultExpiresInSec) * 1e3
57
57
  );
58
58
  await this.tokenWriter.persistRefresh({
59
- integrationId,
59
+ connectionId,
60
60
  accessToken: parsed.accessToken,
61
61
  refreshToken: parsed.refreshToken ?? void 0,
62
62
  expiresAt: newExpiresAt
63
63
  });
64
- return this.buildCredentials(parsed.accessToken, integration, raw);
64
+ return this.buildCredentials(parsed.accessToken, connection, raw);
65
65
  }
66
- async executeRefresh(integrationId, refreshToken) {
66
+ async executeRefresh(connectionId, refreshToken) {
67
67
  const body = new URLSearchParams({
68
68
  grant_type: "refresh_token",
69
69
  refresh_token: refreshToken,
@@ -77,8 +77,8 @@ var OAuth2RefreshStrategy = class {
77
77
  if (!response.ok) {
78
78
  const err = await safeJson(response);
79
79
  if (response.status === 400 && (err.error === "invalid_grant" || err.error === "invalid_token")) {
80
- throw new IntegrationBrokenError(
81
- integrationId,
80
+ throw new ConnectionBrokenError(
81
+ connectionId,
82
82
  err.error ?? "invalid_grant",
83
83
  err.error_description ?? err.message ?? "refresh token rejected"
84
84
  );
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../../runtime/subsystems/auth/runtime/integration-broken.error.ts","../../../../../runtime/subsystems/auth/runtime/oauth2-refresh.strategy.ts"],"sourcesContent":["/**\n * Thrown when an OAuth2 provider returns `400 invalid_grant`/`invalid_token`\n * on refresh — the refresh token itself is dead (user revoked, org\n * deactivated, token expired beyond the provider's rotation window). The\n * integration should be marked broken so background sync stops picking it\n * up; the user re-initiates OAuth.\n *\n * Shared across every OAuth2 strategy.\n */\nexport class IntegrationBrokenError extends Error {\n constructor(\n readonly integrationId: string,\n readonly errorCode: string,\n readonly errorDescription: string,\n ) {\n super(\n `Integration ${integrationId} broken: ${errorCode} - ${errorDescription}`,\n );\n this.name = 'IntegrationBrokenError';\n }\n}\n","/**\n * Abstract base class for OAuth2 refresh-token strategies.\n *\n * Template-method pattern: `resolve()` is concrete; four small hooks inject\n * provider specifics. Validated across two providers (Salesforce, HubSpot)\n * in the extraction-source app before being extracted here — see\n * `docs/gate-1-auth-extraction-findings.md` for the \"build first, extract\n * later\" evidence.\n *\n * Subclass contract:\n * - `provider` — slug matched against `integrations.provider`\n * - `defaultExpiresInSec` — fallback when refresh response omits `expires_in`\n * - `tokenEndpoint()` — URL to POST the refresh grant\n * - `refreshBodyExtras()` — provider-specific body params\n * - `parseRefreshResponse()` — raw JSON → ParsedRefreshResponse\n * - `buildCredentials()` — stored or freshly-refreshed access token +\n * integration + optional raw refresh response\n * → provider credentials\n *\n * Base handles: expiry check w/ 5-min safety window, `forceRefresh` escape\n * hatch, POST form-urlencoded body, OAuth2 error mapping to\n * `IntegrationBrokenError`, refresh-token rotation persistence, fetch +\n * clock injection for tests.\n */\nimport type {\n AuthCredentials,\n AuthResolveOptions,\n IAuthStrategy,\n} from '../protocols/auth-strategy';\nimport type {\n DecryptedIntegration,\n IIntegrationReader,\n IIntegrationTokenWriter,\n} from '../protocols/integration-store';\nimport { IntegrationBrokenError } from './integration-broken.error';\n\nexport type FetchLike = (\n input: string | URL | Request,\n init?: RequestInit,\n) => Promise<Response>;\n\n/** Safety window before expiry that triggers a refresh. */\nconst REFRESH_SAFETY_MS = 5 * 60 * 1000;\n\nexport interface OAuth2RefreshStrategyOptions {\n integrationReader: IIntegrationReader;\n tokenWriter: IIntegrationTokenWriter;\n /** Injectable fetch for tests. Defaults to the global `fetch`. */\n fetch?: FetchLike;\n /** Injectable clock for tests. Defaults to `Date.now`. */\n now?: () => number;\n}\n\nexport interface ParsedRefreshResponse {\n accessToken: string;\n /**\n * New refresh token if the provider rotated it (HubSpot: always, Salesforce:\n * sometimes). Omit when the provider reused the old refresh token.\n */\n refreshToken?: string;\n /** Seconds from now. If omitted, subclass `defaultExpiresInSec` applies. */\n expiresInSec?: number;\n}\n\nexport abstract class OAuth2RefreshStrategy implements IAuthStrategy {\n protected abstract readonly provider: string;\n protected abstract readonly defaultExpiresInSec: number;\n\n protected readonly integrationReader: IIntegrationReader;\n protected readonly tokenWriter: IIntegrationTokenWriter;\n protected readonly fetchImpl: FetchLike;\n protected readonly now: () => number;\n\n constructor(opts: OAuth2RefreshStrategyOptions) {\n this.integrationReader = opts.integrationReader;\n this.tokenWriter = opts.tokenWriter;\n this.fetchImpl = opts.fetch ?? fetch;\n this.now = opts.now ?? Date.now;\n }\n\n async resolve(\n integrationId: string,\n opts: AuthResolveOptions = {},\n ): Promise<AuthCredentials> {\n const integration =\n await this.integrationReader.findByIdDecrypted(integrationId);\n if (!integration) {\n throw new Error(`Integration ${integrationId} not found`);\n }\n if (integration.provider !== this.provider) {\n throw new Error(\n `${this.constructor.name} called for non-${this.provider} integration ${integrationId} (provider=${integration.provider})`,\n );\n }\n\n const needsRefresh =\n opts.forceRefresh ||\n this.isExpiring(integration.expiresAt) ||\n !integration.accessToken;\n\n if (!needsRefresh) {\n return this.buildCredentials(integration.accessToken, integration);\n }\n\n if (!integration.refreshToken) {\n throw new IntegrationBrokenError(\n integrationId,\n 'no_refresh_token',\n 'Integration has no refresh token; user must reconnect',\n );\n }\n\n const { parsed, raw } = await this.executeRefresh(\n integrationId,\n integration.refreshToken,\n );\n const newExpiresAt = new Date(\n this.now() + (parsed.expiresInSec ?? this.defaultExpiresInSec) * 1000,\n );\n await this.tokenWriter.persistRefresh({\n integrationId,\n accessToken: parsed.accessToken,\n refreshToken: parsed.refreshToken ?? undefined,\n expiresAt: newExpiresAt,\n });\n\n return this.buildCredentials(parsed.accessToken, integration, raw);\n }\n\n protected abstract tokenEndpoint(): string;\n protected abstract refreshBodyExtras(): Record<string, string>;\n protected abstract parseRefreshResponse(raw: unknown): ParsedRefreshResponse;\n protected abstract buildCredentials(\n accessToken: string,\n integration: DecryptedIntegration,\n refreshRaw?: unknown,\n ): AuthCredentials;\n\n private async executeRefresh(\n integrationId: string,\n refreshToken: string,\n ): Promise<{ parsed: ParsedRefreshResponse; raw: unknown }> {\n const body = new URLSearchParams({\n grant_type: 'refresh_token',\n refresh_token: refreshToken,\n ...this.refreshBodyExtras(),\n });\n const response = await this.fetchImpl(this.tokenEndpoint(), {\n method: 'POST',\n headers: { 'Content-Type': 'application/x-www-form-urlencoded' },\n body: body.toString(),\n });\n if (!response.ok) {\n const err = (await safeJson(response)) as Partial<{\n error: string;\n error_description: string;\n message: string;\n }>;\n if (\n response.status === 400 &&\n (err.error === 'invalid_grant' || err.error === 'invalid_token')\n ) {\n throw new IntegrationBrokenError(\n integrationId,\n err.error ?? 'invalid_grant',\n err.error_description ?? err.message ?? 'refresh token rejected',\n );\n }\n throw new Error(\n `${this.provider} token refresh failed: ${response.status} ${err.error ?? ''} ${err.error_description ?? err.message ?? ''}`.trim(),\n );\n }\n const raw = await response.json();\n return { parsed: this.parseRefreshResponse(raw), raw };\n }\n\n private isExpiring(expiresAt: Date | null): boolean {\n if (!expiresAt) return true;\n return expiresAt.getTime() - this.now() < REFRESH_SAFETY_MS;\n }\n}\n\nasync function safeJson(response: Response): Promise<unknown> {\n try {\n return await response.clone().json();\n } catch {\n return {};\n }\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../../../../runtime/subsystems/auth/runtime/connection-broken.error.ts","../../../../../runtime/subsystems/auth/runtime/oauth2-refresh.strategy.ts"],"sourcesContent":["/**\n * Thrown when an OAuth2 provider returns `400 invalid_grant`/`invalid_token`\n * on refresh — the refresh token itself is dead (user revoked, org\n * deactivated, token expired beyond the provider's rotation window). The\n * connection should be marked broken so background sync stops picking it\n * up; the user re-initiates OAuth.\n *\n * Shared across every OAuth2 strategy.\n */\nexport class ConnectionBrokenError extends Error {\n constructor(\n readonly connectionId: string,\n readonly errorCode: string,\n readonly errorDescription: string,\n ) {\n super(\n `Connection ${connectionId} broken: ${errorCode} - ${errorDescription}`,\n );\n this.name = 'ConnectionBrokenError';\n }\n}\n","/**\n * Abstract base class for OAuth2 refresh-token strategies.\n *\n * Template-method pattern: `resolve()` is concrete; four small hooks inject\n * provider specifics. Validated across two providers (Salesforce, HubSpot)\n * in the extraction-source app before being extracted here — see\n * `docs/gate-1-auth-extraction-findings.md` for the \"build first, extract\n * later\" evidence.\n *\n * Subclass contract:\n * - `provider` — slug matched against `connections.provider`\n * - `defaultExpiresInSec` — fallback when refresh response omits `expires_in`\n * - `tokenEndpoint()` — URL to POST the refresh grant\n * - `refreshBodyExtras()` — provider-specific body params\n * - `parseRefreshResponse()` — raw JSON → ParsedRefreshResponse\n * - `buildCredentials()` — stored or freshly-refreshed access token +\n * connection + optional raw refresh response\n * → provider credentials\n *\n * Base handles: expiry check w/ 5-min safety window, `forceRefresh` escape\n * hatch, POST form-urlencoded body, OAuth2 error mapping to\n * `ConnectionBrokenError`, refresh-token rotation persistence, fetch +\n * clock injection for tests.\n */\nimport type {\n AuthCredentials,\n AuthResolveOptions,\n IAuthStrategy,\n} from '../protocols/auth-strategy';\nimport type {\n DecryptedConnection,\n IConnectionReader,\n IConnectionTokenWriter,\n} from '../protocols/connection-store';\nimport { ConnectionBrokenError } from './connection-broken.error';\n\nexport type FetchLike = (\n input: string | URL | Request,\n init?: RequestInit,\n) => Promise<Response>;\n\n/** Safety window before expiry that triggers a refresh. */\nconst REFRESH_SAFETY_MS = 5 * 60 * 1000;\n\nexport interface OAuth2RefreshStrategyOptions {\n connectionReader: IConnectionReader;\n tokenWriter: IConnectionTokenWriter;\n /** Injectable fetch for tests. Defaults to the global `fetch`. */\n fetch?: FetchLike;\n /** Injectable clock for tests. Defaults to `Date.now`. */\n now?: () => number;\n}\n\nexport interface ParsedRefreshResponse {\n accessToken: string;\n /**\n * New refresh token if the provider rotated it (HubSpot: always, Salesforce:\n * sometimes). Omit when the provider reused the old refresh token.\n */\n refreshToken?: string;\n /** Seconds from now. If omitted, subclass `defaultExpiresInSec` applies. */\n expiresInSec?: number;\n}\n\nexport abstract class OAuth2RefreshStrategy implements IAuthStrategy {\n protected abstract readonly provider: string;\n protected abstract readonly defaultExpiresInSec: number;\n\n protected readonly connectionReader: IConnectionReader;\n protected readonly tokenWriter: IConnectionTokenWriter;\n protected readonly fetchImpl: FetchLike;\n protected readonly now: () => number;\n\n constructor(opts: OAuth2RefreshStrategyOptions) {\n this.connectionReader = opts.connectionReader;\n this.tokenWriter = opts.tokenWriter;\n this.fetchImpl = opts.fetch ?? fetch;\n this.now = opts.now ?? Date.now;\n }\n\n async resolve(\n connectionId: string,\n opts: AuthResolveOptions = {},\n ): Promise<AuthCredentials> {\n const connection =\n await this.connectionReader.findByIdDecrypted(connectionId);\n if (!connection) {\n throw new Error(`Connection ${connectionId} not found`);\n }\n if (connection.provider !== this.provider) {\n throw new Error(\n `${this.constructor.name} called for non-${this.provider} connection ${connectionId} (provider=${connection.provider})`,\n );\n }\n\n const needsRefresh =\n opts.forceRefresh ||\n this.isExpiring(connection.expiresAt) ||\n !connection.accessToken;\n\n if (!needsRefresh) {\n return this.buildCredentials(connection.accessToken, connection);\n }\n\n if (!connection.refreshToken) {\n throw new ConnectionBrokenError(\n connectionId,\n 'no_refresh_token',\n 'Connection has no refresh token; user must reconnect',\n );\n }\n\n const { parsed, raw } = await this.executeRefresh(\n connectionId,\n connection.refreshToken,\n );\n const newExpiresAt = new Date(\n this.now() + (parsed.expiresInSec ?? this.defaultExpiresInSec) * 1000,\n );\n await this.tokenWriter.persistRefresh({\n connectionId,\n accessToken: parsed.accessToken,\n refreshToken: parsed.refreshToken ?? undefined,\n expiresAt: newExpiresAt,\n });\n\n return this.buildCredentials(parsed.accessToken, connection, raw);\n }\n\n protected abstract tokenEndpoint(): string;\n protected abstract refreshBodyExtras(): Record<string, string>;\n protected abstract parseRefreshResponse(raw: unknown): ParsedRefreshResponse;\n protected abstract buildCredentials(\n accessToken: string,\n connection: DecryptedConnection,\n refreshRaw?: unknown,\n ): AuthCredentials;\n\n private async executeRefresh(\n connectionId: string,\n refreshToken: string,\n ): Promise<{ parsed: ParsedRefreshResponse; raw: unknown }> {\n const body = new URLSearchParams({\n grant_type: 'refresh_token',\n refresh_token: refreshToken,\n ...this.refreshBodyExtras(),\n });\n const response = await this.fetchImpl(this.tokenEndpoint(), {\n method: 'POST',\n headers: { 'Content-Type': 'application/x-www-form-urlencoded' },\n body: body.toString(),\n });\n if (!response.ok) {\n const err = (await safeJson(response)) as Partial<{\n error: string;\n error_description: string;\n message: string;\n }>;\n if (\n response.status === 400 &&\n (err.error === 'invalid_grant' || err.error === 'invalid_token')\n ) {\n throw new ConnectionBrokenError(\n connectionId,\n err.error ?? 'invalid_grant',\n err.error_description ?? err.message ?? 'refresh token rejected',\n );\n }\n throw new Error(\n `${this.provider} token refresh failed: ${response.status} ${err.error ?? ''} ${err.error_description ?? err.message ?? ''}`.trim(),\n );\n }\n const raw = await response.json();\n return { parsed: this.parseRefreshResponse(raw), raw };\n }\n\n private isExpiring(expiresAt: Date | null): boolean {\n if (!expiresAt) return true;\n return expiresAt.getTime() - this.now() < REFRESH_SAFETY_MS;\n }\n}\n\nasync function safeJson(response: Response): Promise<unknown> {\n try {\n return await response.clone().json();\n } catch {\n return {};\n }\n}\n"],"mappings":"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","names":[]}
@@ -27,6 +27,6 @@ interface WithAuthRetryOptions {
27
27
  */
28
28
  isSessionExpired?: (err: unknown) => boolean;
29
29
  }
30
- declare function withAuthRetry<T>(authStrategy: IAuthStrategy, integrationId: string, op: (credentials: AuthCredentials) => Promise<T>, options?: WithAuthRetryOptions): Promise<T>;
30
+ declare function withAuthRetry<T>(authStrategy: IAuthStrategy, connectionId: string, op: (credentials: AuthCredentials) => Promise<T>, options?: WithAuthRetryOptions): Promise<T>;
31
31
 
32
32
  export { type WithAuthRetryOptions, withAuthRetry };
@@ -16,14 +16,14 @@ function isSessionExpiredError(err) {
16
16
  }
17
17
 
18
18
  // runtime/subsystems/auth/runtime/with-auth-retry.ts
19
- async function withAuthRetry(authStrategy, integrationId, op, options = {}) {
19
+ async function withAuthRetry(authStrategy, connectionId, op, options = {}) {
20
20
  const classify = options.isSessionExpired ?? isSessionExpiredError;
21
- let creds = await authStrategy.resolve(integrationId);
21
+ let creds = await authStrategy.resolve(connectionId);
22
22
  try {
23
23
  return await op(creds);
24
24
  } catch (e) {
25
25
  if (!classify(e)) throw e;
26
- creds = await authStrategy.resolve(integrationId, { forceRefresh: true });
26
+ creds = await authStrategy.resolve(connectionId, { forceRefresh: true });
27
27
  return op(creds);
28
28
  }
29
29
  }
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../../runtime/subsystems/auth/runtime/session-expired.error.ts","../../../../../runtime/subsystems/auth/runtime/with-auth-retry.ts"],"sourcesContent":["/**\n * Provider-agnostic marker for \"the access token was rejected; a forced\n * refresh may recover.\"\n *\n * Concrete provider error classes (e.g. SalesforceSessionExpiredError,\n * HubSpotUnauthorizedError) either extend `SessionExpiredError` directly or\n * set `isSessionExpired === true` on their instances. `withAuthRetry` uses\n * the `isSessionExpiredError` predicate to decide whether to force-refresh\n * and retry once.\n *\n * This discriminator replaces the SFDC-only `instanceof` check from the\n * extraction-source app's original `withAuthRetry`. See\n * `docs/gate-1-auth-extraction-findings.md` (recommendation 4).\n */\nexport class SessionExpiredError extends Error {\n /** Duck-type marker — works across package boundaries where `instanceof` fails. */\n readonly isSessionExpired = true as const;\n\n constructor(message = 'Access token rejected by provider') {\n super(message);\n this.name = 'SessionExpiredError';\n }\n}\n\n/**\n * Predicate used by `withAuthRetry` by default.\n *\n * Matches any error that either `instanceof SessionExpiredError` or carries\n * the `isSessionExpired === true` marker property. Provider adapters that\n * want their existing error classes to participate can simply add the\n * marker property without touching the class hierarchy.\n */\nexport function isSessionExpiredError(err: unknown): boolean {\n if (err instanceof SessionExpiredError) return true;\n if (err !== null && typeof err === 'object' && 'isSessionExpired' in err) {\n return (err as { isSessionExpired?: unknown }).isSessionExpired === true;\n }\n return false;\n}\n","/**\n * Run `op` with auth-aware retry-once on session-expired errors.\n *\n * Pattern: resolve creds → run op → if `isSessionExpired(e)` → resolve with\n * `forceRefresh: true` → retry → propagate. A second session-expired error\n * on the refreshed token propagates rather than looping, so transient\n * adapter bugs can't hang the caller.\n *\n * Generalisation over the extraction source's SFDC-specific original: the\n * session-expired classifier is injected. Providers mark their session-\n * expired errors (via `instanceof` of a marker class, or by setting a known\n * property) and pass a classifier matching that shape.\n *\n * Default classifier recognises the marker interface `SessionExpiredError`\n * shipped in `session-expired.error.ts` — concrete provider errors that\n * extend it (or set `isSessionExpired === true`) get retried without any\n * further wiring.\n */\nimport type {\n AuthCredentials,\n IAuthStrategy,\n} from '../protocols/auth-strategy';\nimport { isSessionExpiredError } from './session-expired.error';\n\nexport interface WithAuthRetryOptions {\n /**\n * Classifier that decides whether a thrown error is a session-expired\n * signal worth retrying once with a fresh token. Defaults to the marker-\n * interface check in `session-expired.error.ts`.\n */\n isSessionExpired?: (err: unknown) => boolean;\n}\n\nexport async function withAuthRetry<T>(\n authStrategy: IAuthStrategy,\n integrationId: string,\n op: (credentials: AuthCredentials) => Promise<T>,\n options: WithAuthRetryOptions = {},\n): Promise<T> {\n const classify = options.isSessionExpired ?? isSessionExpiredError;\n\n let creds = await authStrategy.resolve(integrationId);\n try {\n return await op(creds);\n } catch (e) {\n if (!classify(e)) throw e;\n creds = await authStrategy.resolve(integrationId, { forceRefresh: true });\n return op(creds);\n }\n}\n"],"mappings":";AAcO,IAAM,sBAAN,cAAkC,MAAM;AAAA;AAAA,EAEpC,mBAAmB;AAAA,EAE5B,YAAY,UAAU,qCAAqC;AACzD,UAAM,OAAO;AACb,SAAK,OAAO;AAAA,EACd;AACF;AAUO,SAAS,sBAAsB,KAAuB;AAC3D,MAAI,eAAe,oBAAqB,QAAO;AAC/C,MAAI,QAAQ,QAAQ,OAAO,QAAQ,YAAY,sBAAsB,KAAK;AACxE,WAAQ,IAAuC,qBAAqB;AAAA,EACtE;AACA,SAAO;AACT;;;ACLA,eAAsB,cACpB,cACA,eACA,IACA,UAAgC,CAAC,GACrB;AACZ,QAAM,WAAW,QAAQ,oBAAoB;AAE7C,MAAI,QAAQ,MAAM,aAAa,QAAQ,aAAa;AACpD,MAAI;AACF,WAAO,MAAM,GAAG,KAAK;AAAA,EACvB,SAAS,GAAG;AACV,QAAI,CAAC,SAAS,CAAC,EAAG,OAAM;AACxB,YAAQ,MAAM,aAAa,QAAQ,eAAe,EAAE,cAAc,KAAK,CAAC;AACxE,WAAO,GAAG,KAAK;AAAA,EACjB;AACF;","names":[]}
1
+ {"version":3,"sources":["../../../../../runtime/subsystems/auth/runtime/session-expired.error.ts","../../../../../runtime/subsystems/auth/runtime/with-auth-retry.ts"],"sourcesContent":["/**\n * Provider-agnostic marker for \"the access token was rejected; a forced\n * refresh may recover.\"\n *\n * Concrete provider error classes (e.g. SalesforceSessionExpiredError,\n * HubSpotUnauthorizedError) either extend `SessionExpiredError` directly or\n * set `isSessionExpired === true` on their instances. `withAuthRetry` uses\n * the `isSessionExpiredError` predicate to decide whether to force-refresh\n * and retry once.\n *\n * This discriminator replaces the SFDC-only `instanceof` check from the\n * extraction-source app's original `withAuthRetry`. See\n * `docs/gate-1-auth-extraction-findings.md` (recommendation 4).\n */\nexport class SessionExpiredError extends Error {\n /** Duck-type marker — works across package boundaries where `instanceof` fails. */\n readonly isSessionExpired = true as const;\n\n constructor(message = 'Access token rejected by provider') {\n super(message);\n this.name = 'SessionExpiredError';\n }\n}\n\n/**\n * Predicate used by `withAuthRetry` by default.\n *\n * Matches any error that either `instanceof SessionExpiredError` or carries\n * the `isSessionExpired === true` marker property. Provider adapters that\n * want their existing error classes to participate can simply add the\n * marker property without touching the class hierarchy.\n */\nexport function isSessionExpiredError(err: unknown): boolean {\n if (err instanceof SessionExpiredError) return true;\n if (err !== null && typeof err === 'object' && 'isSessionExpired' in err) {\n return (err as { isSessionExpired?: unknown }).isSessionExpired === true;\n }\n return false;\n}\n","/**\n * Run `op` with auth-aware retry-once on session-expired errors.\n *\n * Pattern: resolve creds → run op → if `isSessionExpired(e)` → resolve with\n * `forceRefresh: true` → retry → propagate. A second session-expired error\n * on the refreshed token propagates rather than looping, so transient\n * adapter bugs can't hang the caller.\n *\n * Generalisation over the extraction source's SFDC-specific original: the\n * session-expired classifier is injected. Providers mark their session-\n * expired errors (via `instanceof` of a marker class, or by setting a known\n * property) and pass a classifier matching that shape.\n *\n * Default classifier recognises the marker interface `SessionExpiredError`\n * shipped in `session-expired.error.ts` — concrete provider errors that\n * extend it (or set `isSessionExpired === true`) get retried without any\n * further wiring.\n */\nimport type {\n AuthCredentials,\n IAuthStrategy,\n} from '../protocols/auth-strategy';\nimport { isSessionExpiredError } from './session-expired.error';\n\nexport interface WithAuthRetryOptions {\n /**\n * Classifier that decides whether a thrown error is a session-expired\n * signal worth retrying once with a fresh token. Defaults to the marker-\n * interface check in `session-expired.error.ts`.\n */\n isSessionExpired?: (err: unknown) => boolean;\n}\n\nexport async function withAuthRetry<T>(\n authStrategy: IAuthStrategy,\n connectionId: string,\n op: (credentials: AuthCredentials) => Promise<T>,\n options: WithAuthRetryOptions = {},\n): Promise<T> {\n const classify = options.isSessionExpired ?? isSessionExpiredError;\n\n let creds = await authStrategy.resolve(connectionId);\n try {\n return await op(creds);\n } catch (e) {\n if (!classify(e)) throw e;\n creds = await authStrategy.resolve(connectionId, { forceRefresh: true });\n return op(creds);\n }\n}\n"],"mappings":";AAcO,IAAM,sBAAN,cAAkC,MAAM;AAAA;AAAA,EAEpC,mBAAmB;AAAA,EAE5B,YAAY,UAAU,qCAAqC;AACzD,UAAM,OAAO;AACb,SAAK,OAAO;AAAA,EACd;AACF;AAUO,SAAS,sBAAsB,KAAuB;AAC3D,MAAI,eAAe,oBAAqB,QAAO;AAC/C,MAAI,QAAQ,QAAQ,OAAO,QAAQ,YAAY,sBAAsB,KAAK;AACxE,WAAQ,IAAuC,qBAAqB;AAAA,EACtE;AACA,SAAO;AACT;;;ACLA,eAAsB,cACpB,cACA,cACA,IACA,UAAgC,CAAC,GACrB;AACZ,QAAM,WAAW,QAAQ,oBAAoB;AAE7C,MAAI,QAAQ,MAAM,aAAa,QAAQ,YAAY;AACnD,MAAI;AACF,WAAO,MAAM,GAAG,KAAK;AAAA,EACvB,SAAS,GAAG;AACV,QAAI,CAAC,SAAS,CAAC,EAAG,OAAM;AACxB,YAAQ,MAAM,aAAa,QAAQ,cAAc,EAAE,cAAc,KAAK,CAAC;AACvE,WAAO,GAAG,KAAK;AAAA,EACjB;AACF;","names":[]}
@@ -5,7 +5,6 @@ import '../../types/drizzle.js';
5
5
  import 'drizzle-orm/node-postgres';
6
6
  import '../jobs/jobs-domain.module.js';
7
7
  import '../jobs/bullmq.config.js';
8
- import 'bullmq';
9
8
  import '../jobs/pool-config.loader.js';
10
9
  import '../../../job-orchestrator.protocol-CHOEqBDk.js';
11
10
  import '../events/event-bus.protocol.js';