@shipfox/api-integration-jira 12.2.0 → 12.3.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 (91) hide show
  1. package/.turbo/turbo-build.log +8 -7
  2. package/.turbo/turbo-type$colon$emit.log +0 -1
  3. package/CHANGELOG.md +11 -0
  4. package/README.md +5 -1
  5. package/dist/api/client.d.ts +10 -0
  6. package/dist/api/client.d.ts.map +1 -1
  7. package/dist/api/client.js +55 -11
  8. package/dist/api/client.js.map +1 -1
  9. package/dist/core/disconnect.d.ts +12 -0
  10. package/dist/core/disconnect.d.ts.map +1 -1
  11. package/dist/core/disconnect.js +45 -1
  12. package/dist/core/disconnect.js.map +1 -1
  13. package/dist/core/install.d.ts +1 -0
  14. package/dist/core/install.d.ts.map +1 -1
  15. package/dist/core/install.js +2 -1
  16. package/dist/core/install.js.map +1 -1
  17. package/dist/core/tokens.d.ts +2 -0
  18. package/dist/core/tokens.d.ts.map +1 -1
  19. package/dist/core/tokens.js +2 -2
  20. package/dist/core/tokens.js.map +1 -1
  21. package/dist/core/webhook-registration.d.ts +1 -0
  22. package/dist/core/webhook-registration.d.ts.map +1 -1
  23. package/dist/core/webhook-registration.js +3 -1
  24. package/dist/core/webhook-registration.js.map +1 -1
  25. package/dist/core/webhook-url.d.ts +3 -0
  26. package/dist/core/webhook-url.d.ts.map +1 -0
  27. package/dist/core/webhook-url.js +8 -0
  28. package/dist/core/webhook-url.js.map +1 -0
  29. package/dist/db/installations.d.ts +13 -0
  30. package/dist/db/installations.d.ts.map +1 -1
  31. package/dist/db/installations.js +18 -1
  32. package/dist/db/installations.js.map +1 -1
  33. package/dist/index.d.ts +17 -4
  34. package/dist/index.d.ts.map +1 -1
  35. package/dist/index.js +5 -7
  36. package/dist/index.js.map +1 -1
  37. package/dist/presentation/routes/webhooks.d.ts +2 -1
  38. package/dist/presentation/routes/webhooks.d.ts.map +1 -1
  39. package/dist/presentation/routes/webhooks.js +2 -1
  40. package/dist/presentation/routes/webhooks.js.map +1 -1
  41. package/dist/temporal/activities/index.d.ts +8 -1
  42. package/dist/temporal/activities/index.d.ts.map +1 -1
  43. package/dist/temporal/activities/index.js +8 -1
  44. package/dist/temporal/activities/index.js.map +1 -1
  45. package/dist/temporal/activities/renew-jira-webhooks.d.ts +26 -0
  46. package/dist/temporal/activities/renew-jira-webhooks.d.ts.map +1 -0
  47. package/dist/temporal/activities/renew-jira-webhooks.js +96 -0
  48. package/dist/temporal/activities/renew-jira-webhooks.js.map +1 -0
  49. package/dist/temporal/constants.d.ts +2 -0
  50. package/dist/temporal/constants.d.ts.map +1 -1
  51. package/dist/temporal/constants.js +2 -0
  52. package/dist/temporal/constants.js.map +1 -1
  53. package/dist/temporal/worker.d.ts +3 -0
  54. package/dist/temporal/worker.d.ts.map +1 -1
  55. package/dist/temporal/worker.js +5 -0
  56. package/dist/temporal/worker.js.map +1 -1
  57. package/dist/temporal/workflows/index.bundle.js +38 -2
  58. package/dist/temporal/workflows/index.d.ts +1 -0
  59. package/dist/temporal/workflows/index.d.ts.map +1 -1
  60. package/dist/temporal/workflows/index.js +1 -0
  61. package/dist/temporal/workflows/index.js.map +1 -1
  62. package/dist/temporal/workflows/renew-jira-webhooks-cron.d.ts +2 -0
  63. package/dist/temporal/workflows/renew-jira-webhooks-cron.d.ts.map +1 -0
  64. package/dist/temporal/workflows/renew-jira-webhooks-cron.js +18 -0
  65. package/dist/temporal/workflows/renew-jira-webhooks-cron.js.map +1 -0
  66. package/dist/tsconfig.test.tsbuildinfo +1 -1
  67. package/package.json +2 -2
  68. package/src/api/client.test.ts +81 -2
  69. package/src/api/client.ts +68 -7
  70. package/src/core/disconnect.test.ts +107 -1
  71. package/src/core/disconnect.ts +64 -1
  72. package/src/core/install.test.ts +23 -0
  73. package/src/core/install.ts +5 -2
  74. package/src/core/tokens-refresh.test.ts +39 -0
  75. package/src/core/tokens.ts +4 -2
  76. package/src/core/webhook-registration.test.ts +32 -0
  77. package/src/core/webhook-registration.ts +4 -1
  78. package/src/core/webhook-url.ts +9 -0
  79. package/src/db/installations.test.ts +82 -0
  80. package/src/db/installations.ts +54 -1
  81. package/src/index.test.ts +21 -1
  82. package/src/index.ts +21 -9
  83. package/src/presentation/routes/webhooks.ts +3 -1
  84. package/src/temporal/activities/index.ts +20 -3
  85. package/src/temporal/activities/renew-jira-webhooks.test.ts +215 -0
  86. package/src/temporal/activities/renew-jira-webhooks.ts +144 -0
  87. package/src/temporal/constants.ts +2 -0
  88. package/src/temporal/worker.ts +11 -0
  89. package/src/temporal/workflows/index.ts +1 -0
  90. package/src/temporal/workflows/renew-jira-webhooks-cron.ts +17 -0
  91. package/tsconfig.build.tsbuildinfo +1 -1
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts"],"sourcesContent":["import {JIRA_PROVIDER} from '@shipfox/api-integration-jira-dto';\nimport {\n createJiraAgentToolsClient,\n createJiraApiClient,\n type JiraAgentToolsClient,\n type JiraApiClient,\n} from '#api/client.js';\nimport {config} from '#config.js';\nimport {JiraAgentToolsProvider} from '#core/agent-tools-provider.js';\nimport type {JiraTokenStore} from '#core/tokens.js';\nimport {createJiraWebhookProcessor} from '#core/webhook-processor.js';\nimport {registerJiraWebhook} from '#core/webhook-registration.js';\nimport {closeDb, db} from '#db/db.js';\nimport {getJiraInstallationByConnectionId} from '#db/installations.js';\nimport {migrationsPath} from '#db/migrations.js';\nimport {\n type CreateJiraIntegrationRoutesOptions,\n createJiraIntegrationRoutes,\n} from '#presentation/routes/install.js';\nimport {\n type CreateJiraWebhookRoutesOptions,\n createJiraWebhookRoutes,\n JIRA_WEBHOOK_ROUTE_PREFIX,\n} from '#presentation/routes/webhooks.js';\n\nconst TRAILING_SLASHES_RE = /\\/+$/;\n\nexport type {JiraProvider} from '@shipfox/api-integration-jira-dto';\nexport type {\n JiraAccessibleResource,\n JiraAgentToolHttpMethod,\n JiraAgentToolQueryValue,\n JiraAgentToolRequest,\n JiraAgentToolResponse,\n JiraAgentToolsClient,\n JiraApiClient,\n JiraAuthorization,\n JiraDynamicWebhookRegistration,\n JiraIdentity,\n} from '#api/client.js';\nexport {\n createJiraAgentToolsClient,\n createJiraApiClient,\n JIRA_DYNAMIC_WEBHOOK_EVENTS,\n JIRA_DYNAMIC_WEBHOOK_JQL,\n mapJiraError,\n} from '#api/client.js';\nexport type {\n JiraAgentToolCatalogEntry,\n JiraAgentToolId,\n JiraAgentToolRequiredScope,\n} from '#core/agent-tools.js';\nexport {\n jiraAgentToolCatalog,\n jiraAgentToolSelectionCatalog,\n jiraPlainTextToAdf,\n} from '#core/agent-tools.js';\nexport type {\n JiraAgentToolsProviderOptions,\n JiraToolCallResult,\n} from '#core/agent-tools-provider.js';\nexport {JiraAgentToolsProvider} from '#core/agent-tools-provider.js';\nexport type {DisconnectJiraInstallationParams} from '#core/disconnect.js';\nexport {disconnectJiraInstallation} from '#core/disconnect.js';\nexport {\n JiraAccessTokenMissingError,\n JiraAuthorizationScopeMismatchError,\n JiraConnectionAlreadyLinkedError,\n JiraConnectionNotFoundError,\n JiraInstallationAlreadyLinkedError,\n JiraInstallationSiteMismatchError,\n JiraInstallStateActorMismatchError,\n JiraInstallStateError,\n JiraIntegrationProviderError,\n JiraOAuthCallbackError,\n JiraOfflineAccessNotGrantedError,\n JiraPendingSelectionNotFoundError,\n JiraSiteSelectionMismatchError,\n JiraTokenUnrefreshableError,\n} from '#core/errors.js';\nexport type {ConnectJiraInstallationInput, HandleJiraCallbackParams} from '#core/install.js';\nexport {\n handleJiraCallback,\n handleJiraOAuthCallbackError,\n handleJiraSiteSelection,\n} from '#core/install.js';\nexport type {JiraPendingSelectionSecretsStore, JiraPendingSelectionStore} from '#core/pending.js';\nexport {createJiraPendingSelectionStore, jiraPendingSecretsNamespace} from '#core/pending.js';\nexport {\n assertJiraAuthorizationScopes,\n formatJiraOAuthScopes,\n JIRA_OAUTH_SCOPES,\n} from '#core/scopes.js';\nexport {signJiraInstallState, verifyJiraInstallState} from '#core/state.js';\nexport type {\n CreateJiraTokenStoreParams,\n GetJiraAccessTokenParams,\n JiraConnectionResolverResult,\n JiraSecretsStore,\n JiraTokenStore,\n StoreJiraTokensParams,\n} from '#core/tokens.js';\nexport {createJiraTokenStore, jiraSecretsNamespace} from '#core/tokens.js';\nexport type {\n CreateJiraWebhookProcessorOptions,\n JiraWebhookProcessor,\n} from '#core/webhook-processor.js';\nexport {createJiraWebhookProcessor} from '#core/webhook-processor.js';\nexport type {RegisterJiraWebhookParams} from '#core/webhook-registration.js';\nexport {JIRA_WEBHOOK_TTL_MS, registerJiraWebhook} from '#core/webhook-registration.js';\nexport type {\n JiraInstallation,\n JiraInstallationLock,\n JiraInstallationStatus,\n UpdateJiraInstallationWebhookParams,\n UpsertJiraInstallationParams,\n} from '#db/installations.js';\nexport {\n deleteJiraInstallationByConnectionId,\n getJiraInstallationByCloudId,\n getJiraInstallationByConnectionId,\n getJiraInstallationByWebhookId,\n listJiraInstallationsDueForTokenRefresh,\n markJiraInstallationRevoked,\n updateJiraInstallationTokenExpiry,\n updateJiraInstallationWebhook,\n upsertJiraInstallation,\n withJiraRefreshLock,\n withJiraRefreshLockAndWait,\n withJiraWebhookRegistrationLock,\n} from '#db/installations.js';\nexport type {CreateJiraWebhookRoutesOptions} from '#presentation/routes/webhooks.js';\nexport {createJiraWebhookRoutes} from '#presentation/routes/webhooks.js';\nexport {createJiraMaintenanceWorker} from '#temporal/worker.js';\nexport {closeDb, config, db, migrationsPath};\n\nexport interface CreateJiraIntegrationProviderOptions {\n jira?: JiraApiClient | undefined;\n agentTools?:\n | {\n tokenStore: Pick<JiraTokenStore, 'getAccessToken'>;\n jira?: JiraAgentToolsClient | undefined;\n }\n | undefined;\n getJiraInstallationByConnectionId?: typeof getJiraInstallationByConnectionId | undefined;\n cleanup?:\n | {\n deleteConnectionRecords?: (\n connection: {id: string},\n options: {tx: unknown},\n ) => Promise<void>;\n deleteConnectionSecrets?: (connection: {id: string; workspaceId: string}) => Promise<void>;\n }\n | undefined;\n routes?: JiraIntegrationProviderRoutesOptions | undefined;\n}\n\ntype JiraIntegrationProviderRoutesOptions = Omit<\n CreateJiraIntegrationRoutesOptions,\n 'jira' | 'connectionCapabilities' | 'registerJiraWebhook'\n> &\n Omit<CreateJiraWebhookRoutesOptions, 'processor'>;\n\nexport function createJiraIntegrationProvider(options: CreateJiraIntegrationProviderOptions = {}) {\n const jira = options.jira ?? createJiraApiClient();\n const getInstallationByConnectionId =\n options.getJiraInstallationByConnectionId ?? getJiraInstallationByConnectionId;\n const adapters = options.agentTools\n ? {\n agent_tools: new JiraAgentToolsProvider({\n jira: options.agentTools.jira ?? createJiraAgentToolsClient(),\n tokenStore: options.agentTools.tokenStore,\n }),\n }\n : {};\n const webhookOptions = toJiraWebhookOptions(options.routes);\n const webhookProcessor = webhookOptions ? createJiraWebhookProcessor(webhookOptions) : undefined;\n const webhookRoutes = webhookOptions\n ? [\n createJiraWebhookRoutes({\n coreDb: webhookOptions.coreDb,\n publishIntegrationEventReceived: webhookOptions.publishIntegrationEventReceived,\n recordDeliveryOnly: webhookOptions.recordDeliveryOnly,\n getIntegrationConnectionById: webhookOptions.getIntegrationConnectionById,\n processor: webhookProcessor,\n }),\n ]\n : [];\n const routes = options.routes\n ? [\n createJiraIntegrationRoutes({\n jira,\n connectionCapabilities: adapters.agent_tools ? ['agent_tools'] : [],\n ...options.routes,\n registerJiraWebhook: (input) =>\n registerJiraWebhook({\n jira,\n connectionId: input.connectionId,\n cloudId: input.cloudId,\n accessToken: input.accessToken,\n webhookUrl: jiraWebhookUrl(input.connectionId),\n ...(input.withRegistrationLock\n ? {withRegistrationLock: input.withRegistrationLock}\n : {}),\n ...(input.onRegistrationSuccess\n ? {onRegistrationSuccess: input.onRegistrationSuccess}\n : {}),\n ...(input.onRegistrationFailure\n ? {onRegistrationFailure: input.onRegistrationFailure}\n : {}),\n }).then(() => undefined),\n }),\n ...webhookRoutes,\n ]\n : [];\n return {\n provider: JIRA_PROVIDER,\n displayName: 'Jira',\n adapters,\n async connectionExternalUrl(connection: {id: string}): Promise<string | undefined> {\n return (await getInstallationByConnectionId(connection.id))?.siteUrl;\n },\n ...options.cleanup,\n routes,\n webhookProcessors: webhookProcessor\n ? [{routeIds: ['jira'] as const, processor: webhookProcessor}]\n : undefined,\n };\n}\n\nfunction jiraWebhookUrl(connectionId: string): string {\n return `${config.JIRA_WEBHOOK_BASE_URL.replace(TRAILING_SLASHES_RE, '')}${JIRA_WEBHOOK_ROUTE_PREFIX}/${connectionId}`;\n}\n\nfunction toJiraWebhookOptions(\n routes: CreateJiraIntegrationProviderOptions['routes'],\n): CreateJiraWebhookRoutesOptions | undefined {\n if (!routes) return undefined;\n if (\n routes.coreDb === undefined ||\n routes.publishIntegrationEventReceived === undefined ||\n routes.recordDeliveryOnly === undefined ||\n routes.getIntegrationConnectionById === undefined\n )\n throw new Error(\n 'Jira integration provider requires all webhook receiver dependencies: coreDb, publishIntegrationEventReceived, recordDeliveryOnly, and getIntegrationConnectionById',\n );\n return {\n coreDb: routes.coreDb,\n publishIntegrationEventReceived: routes.publishIntegrationEventReceived,\n recordDeliveryOnly: routes.recordDeliveryOnly,\n getIntegrationConnectionById: routes.getIntegrationConnectionById,\n };\n}\n"],"names":["JIRA_PROVIDER","createJiraAgentToolsClient","createJiraApiClient","config","JiraAgentToolsProvider","createJiraWebhookProcessor","registerJiraWebhook","closeDb","db","getJiraInstallationByConnectionId","migrationsPath","createJiraIntegrationRoutes","createJiraWebhookRoutes","JIRA_WEBHOOK_ROUTE_PREFIX","TRAILING_SLASHES_RE","JIRA_DYNAMIC_WEBHOOK_EVENTS","JIRA_DYNAMIC_WEBHOOK_JQL","mapJiraError","jiraAgentToolCatalog","jiraAgentToolSelectionCatalog","jiraPlainTextToAdf","disconnectJiraInstallation","JiraAccessTokenMissingError","JiraAuthorizationScopeMismatchError","JiraConnectionAlreadyLinkedError","JiraConnectionNotFoundError","JiraInstallationAlreadyLinkedError","JiraInstallationSiteMismatchError","JiraInstallStateActorMismatchError","JiraInstallStateError","JiraIntegrationProviderError","JiraOAuthCallbackError","JiraOfflineAccessNotGrantedError","JiraPendingSelectionNotFoundError","JiraSiteSelectionMismatchError","JiraTokenUnrefreshableError","handleJiraCallback","handleJiraOAuthCallbackError","handleJiraSiteSelection","createJiraPendingSelectionStore","jiraPendingSecretsNamespace","assertJiraAuthorizationScopes","formatJiraOAuthScopes","JIRA_OAUTH_SCOPES","signJiraInstallState","verifyJiraInstallState","createJiraTokenStore","jiraSecretsNamespace","JIRA_WEBHOOK_TTL_MS","deleteJiraInstallationByConnectionId","getJiraInstallationByCloudId","getJiraInstallationByWebhookId","listJiraInstallationsDueForTokenRefresh","markJiraInstallationRevoked","updateJiraInstallationTokenExpiry","updateJiraInstallationWebhook","upsertJiraInstallation","withJiraRefreshLock","withJiraRefreshLockAndWait","withJiraWebhookRegistrationLock","createJiraMaintenanceWorker","createJiraIntegrationProvider","options","jira","getInstallationByConnectionId","adapters","agentTools","agent_tools","tokenStore","webhookOptions","toJiraWebhookOptions","routes","webhookProcessor","undefined","webhookRoutes","coreDb","publishIntegrationEventReceived","recordDeliveryOnly","getIntegrationConnectionById","processor","connectionCapabilities","input","connectionId","cloudId","accessToken","webhookUrl","jiraWebhookUrl","withRegistrationLock","onRegistrationSuccess","onRegistrationFailure","then","provider","displayName","connectionExternalUrl","connection","id","siteUrl","cleanup","webhookProcessors","routeIds","JIRA_WEBHOOK_BASE_URL","replace","Error"],"mappings":"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"}
1
+ {"version":3,"sources":["../src/index.ts"],"sourcesContent":["import {JIRA_PROVIDER} from '@shipfox/api-integration-jira-dto';\nimport {\n createJiraAgentToolsClient,\n createJiraApiClient,\n type JiraAgentToolsClient,\n type JiraApiClient,\n} from '#api/client.js';\nimport {config} from '#config.js';\nimport {JiraAgentToolsProvider} from '#core/agent-tools-provider.js';\nimport type {JiraTokenStore} from '#core/tokens.js';\nimport {createJiraWebhookProcessor} from '#core/webhook-processor.js';\nimport {registerJiraWebhook} from '#core/webhook-registration.js';\nimport {jiraWebhookUrl} from '#core/webhook-url.js';\nimport {closeDb, db} from '#db/db.js';\nimport {getJiraInstallationByConnectionId} from '#db/installations.js';\nimport {migrationsPath} from '#db/migrations.js';\nimport {\n type CreateJiraIntegrationRoutesOptions,\n createJiraIntegrationRoutes,\n} from '#presentation/routes/install.js';\nimport {\n type CreateJiraWebhookRoutesOptions,\n createJiraWebhookRoutes,\n} from '#presentation/routes/webhooks.js';\n\nexport type {JiraProvider} from '@shipfox/api-integration-jira-dto';\nexport type {\n JiraAccessibleResource,\n JiraAgentToolHttpMethod,\n JiraAgentToolQueryValue,\n JiraAgentToolRequest,\n JiraAgentToolResponse,\n JiraAgentToolsClient,\n JiraApiClient,\n JiraAuthorization,\n JiraDynamicWebhookRegistration,\n JiraIdentity,\n} from '#api/client.js';\nexport {\n createJiraAgentToolsClient,\n createJiraApiClient,\n JIRA_DYNAMIC_WEBHOOK_EVENTS,\n JIRA_DYNAMIC_WEBHOOK_JQL,\n mapJiraError,\n} from '#api/client.js';\nexport type {\n JiraAgentToolCatalogEntry,\n JiraAgentToolId,\n JiraAgentToolRequiredScope,\n} from '#core/agent-tools.js';\nexport {\n jiraAgentToolCatalog,\n jiraAgentToolSelectionCatalog,\n jiraPlainTextToAdf,\n} from '#core/agent-tools.js';\nexport type {\n JiraAgentToolsProviderOptions,\n JiraToolCallResult,\n} from '#core/agent-tools-provider.js';\nexport {JiraAgentToolsProvider} from '#core/agent-tools-provider.js';\nexport type {\n DeregisterJiraWebhooksParams,\n DisconnectJiraInstallationParams,\n} from '#core/disconnect.js';\nexport {\n deregisterJiraWebhooks,\n disconnectJiraInstallation,\n prepareJiraWebhookDeregistration,\n} from '#core/disconnect.js';\nexport {\n JiraAccessTokenMissingError,\n JiraAuthorizationScopeMismatchError,\n JiraConnectionAlreadyLinkedError,\n JiraConnectionNotFoundError,\n JiraInstallationAlreadyLinkedError,\n JiraInstallationSiteMismatchError,\n JiraInstallStateActorMismatchError,\n JiraInstallStateError,\n JiraIntegrationProviderError,\n JiraOAuthCallbackError,\n JiraOfflineAccessNotGrantedError,\n JiraPendingSelectionNotFoundError,\n JiraSiteSelectionMismatchError,\n JiraTokenUnrefreshableError,\n} from '#core/errors.js';\nexport type {ConnectJiraInstallationInput, HandleJiraCallbackParams} from '#core/install.js';\nexport {\n handleJiraCallback,\n handleJiraOAuthCallbackError,\n handleJiraSiteSelection,\n} from '#core/install.js';\nexport type {JiraPendingSelectionSecretsStore, JiraPendingSelectionStore} from '#core/pending.js';\nexport {createJiraPendingSelectionStore, jiraPendingSecretsNamespace} from '#core/pending.js';\nexport {\n assertJiraAuthorizationScopes,\n formatJiraOAuthScopes,\n JIRA_OAUTH_SCOPES,\n} from '#core/scopes.js';\nexport {signJiraInstallState, verifyJiraInstallState} from '#core/state.js';\nexport type {\n CreateJiraTokenStoreParams,\n GetJiraAccessTokenParams,\n JiraConnectionResolverResult,\n JiraSecretsStore,\n JiraTokenStore,\n StoreJiraTokensParams,\n} from '#core/tokens.js';\nexport {createJiraTokenStore, jiraSecretsNamespace} from '#core/tokens.js';\nexport type {\n CreateJiraWebhookProcessorOptions,\n JiraWebhookProcessor,\n} from '#core/webhook-processor.js';\nexport {createJiraWebhookProcessor} from '#core/webhook-processor.js';\nexport type {RegisterJiraWebhookParams} from '#core/webhook-registration.js';\nexport {JIRA_WEBHOOK_TTL_MS, registerJiraWebhook} from '#core/webhook-registration.js';\nexport {JIRA_WEBHOOK_ROUTE_PREFIX, jiraWebhookUrl} from '#core/webhook-url.js';\nexport type {\n JiraInstallation,\n JiraInstallationLock,\n JiraInstallationStatus,\n UpdateJiraInstallationWebhookIfUnchangedParams,\n UpdateJiraInstallationWebhookParams,\n UpsertJiraInstallationParams,\n} from '#db/installations.js';\nexport {\n deleteJiraInstallationByConnectionId,\n getJiraInstallationByCloudId,\n getJiraInstallationByConnectionId,\n getJiraInstallationByWebhookId,\n listJiraInstallationsDueForTokenRefresh,\n listJiraInstallationsDueForWebhookRenewal,\n markJiraInstallationRevoked,\n updateJiraInstallationTokenExpiry,\n updateJiraInstallationWebhook,\n updateJiraInstallationWebhookIfUnchanged,\n upsertJiraInstallation,\n withJiraRefreshLock,\n withJiraRefreshLockAndWait,\n withJiraWebhookRegistrationLock,\n} from '#db/installations.js';\nexport type {CreateJiraWebhookRoutesOptions} from '#presentation/routes/webhooks.js';\nexport {createJiraWebhookRoutes} from '#presentation/routes/webhooks.js';\nexport {createJiraMaintenanceWorker} from '#temporal/worker.js';\nexport {closeDb, config, db, migrationsPath};\n\nexport interface CreateJiraIntegrationProviderOptions {\n jira?: JiraApiClient | undefined;\n agentTools?:\n | {\n tokenStore: Pick<JiraTokenStore, 'getAccessToken'>;\n jira?: JiraAgentToolsClient | undefined;\n }\n | undefined;\n getJiraInstallationByConnectionId?: typeof getJiraInstallationByConnectionId | undefined;\n cleanup?:\n | {\n deleteConnectionRemoteResources?: (connection: {\n id: string;\n }) => Promise<(() => Promise<void>) | undefined>;\n withConnectionDeletionLock?: (\n connection: {id: string},\n fn: () => Promise<void>,\n ) => Promise<void>;\n deleteConnectionRecords?: (\n connection: {id: string},\n options: {tx: unknown},\n ) => Promise<void>;\n deleteConnectionSecrets?: (connection: {id: string; workspaceId: string}) => Promise<void>;\n }\n | undefined;\n routes?: JiraIntegrationProviderRoutesOptions | undefined;\n}\n\ntype JiraIntegrationProviderRoutesOptions = Omit<\n CreateJiraIntegrationRoutesOptions,\n 'jira' | 'connectionCapabilities' | 'registerJiraWebhook'\n> &\n Omit<CreateJiraWebhookRoutesOptions, 'processor'>;\n\nexport function createJiraIntegrationProvider(options: CreateJiraIntegrationProviderOptions = {}) {\n const jira = options.jira ?? createJiraApiClient();\n const getInstallationByConnectionId =\n options.getJiraInstallationByConnectionId ?? getJiraInstallationByConnectionId;\n const adapters = options.agentTools\n ? {\n agent_tools: new JiraAgentToolsProvider({\n jira: options.agentTools.jira ?? createJiraAgentToolsClient(),\n tokenStore: options.agentTools.tokenStore,\n }),\n }\n : {};\n const webhookOptions = toJiraWebhookOptions(options.routes);\n const webhookProcessor = webhookOptions ? createJiraWebhookProcessor(webhookOptions) : undefined;\n const webhookRoutes = webhookOptions\n ? [\n createJiraWebhookRoutes({\n coreDb: webhookOptions.coreDb,\n publishIntegrationEventReceived: webhookOptions.publishIntegrationEventReceived,\n recordDeliveryOnly: webhookOptions.recordDeliveryOnly,\n getIntegrationConnectionById: webhookOptions.getIntegrationConnectionById,\n processor: webhookProcessor,\n }),\n ]\n : [];\n const routes = options.routes\n ? [\n createJiraIntegrationRoutes({\n jira,\n connectionCapabilities: adapters.agent_tools ? ['agent_tools'] : [],\n ...options.routes,\n registerJiraWebhook: (input) =>\n registerJiraWebhook({\n jira,\n connectionId: input.connectionId,\n cloudId: input.cloudId,\n accessToken: input.accessToken,\n webhookUrl: jiraWebhookUrl(input.connectionId),\n ...(input.withRegistrationLock\n ? {withRegistrationLock: input.withRegistrationLock}\n : {}),\n ...(input.onRegistrationSuccess\n ? {onRegistrationSuccess: input.onRegistrationSuccess}\n : {}),\n ...(input.onRegistrationFailure\n ? {onRegistrationFailure: input.onRegistrationFailure}\n : {}),\n }).then(() => undefined),\n }),\n ...webhookRoutes,\n ]\n : [];\n return {\n provider: JIRA_PROVIDER,\n displayName: 'Jira',\n adapters,\n async connectionExternalUrl(connection: {id: string}): Promise<string | undefined> {\n return (await getInstallationByConnectionId(connection.id))?.siteUrl;\n },\n ...options.cleanup,\n routes,\n webhookProcessors: webhookProcessor\n ? [{routeIds: ['jira'] as const, processor: webhookProcessor}]\n : undefined,\n };\n}\n\nfunction toJiraWebhookOptions(\n routes: CreateJiraIntegrationProviderOptions['routes'],\n): CreateJiraWebhookRoutesOptions | undefined {\n if (!routes) return undefined;\n if (\n routes.coreDb === undefined ||\n routes.publishIntegrationEventReceived === undefined ||\n routes.recordDeliveryOnly === undefined ||\n routes.getIntegrationConnectionById === undefined\n )\n throw new Error(\n 'Jira integration provider requires all webhook receiver dependencies: coreDb, publishIntegrationEventReceived, recordDeliveryOnly, and getIntegrationConnectionById',\n );\n return {\n coreDb: routes.coreDb,\n publishIntegrationEventReceived: routes.publishIntegrationEventReceived,\n recordDeliveryOnly: routes.recordDeliveryOnly,\n getIntegrationConnectionById: routes.getIntegrationConnectionById,\n };\n}\n"],"names":["JIRA_PROVIDER","createJiraAgentToolsClient","createJiraApiClient","config","JiraAgentToolsProvider","createJiraWebhookProcessor","registerJiraWebhook","jiraWebhookUrl","closeDb","db","getJiraInstallationByConnectionId","migrationsPath","createJiraIntegrationRoutes","createJiraWebhookRoutes","JIRA_DYNAMIC_WEBHOOK_EVENTS","JIRA_DYNAMIC_WEBHOOK_JQL","mapJiraError","jiraAgentToolCatalog","jiraAgentToolSelectionCatalog","jiraPlainTextToAdf","deregisterJiraWebhooks","disconnectJiraInstallation","prepareJiraWebhookDeregistration","JiraAccessTokenMissingError","JiraAuthorizationScopeMismatchError","JiraConnectionAlreadyLinkedError","JiraConnectionNotFoundError","JiraInstallationAlreadyLinkedError","JiraInstallationSiteMismatchError","JiraInstallStateActorMismatchError","JiraInstallStateError","JiraIntegrationProviderError","JiraOAuthCallbackError","JiraOfflineAccessNotGrantedError","JiraPendingSelectionNotFoundError","JiraSiteSelectionMismatchError","JiraTokenUnrefreshableError","handleJiraCallback","handleJiraOAuthCallbackError","handleJiraSiteSelection","createJiraPendingSelectionStore","jiraPendingSecretsNamespace","assertJiraAuthorizationScopes","formatJiraOAuthScopes","JIRA_OAUTH_SCOPES","signJiraInstallState","verifyJiraInstallState","createJiraTokenStore","jiraSecretsNamespace","JIRA_WEBHOOK_TTL_MS","JIRA_WEBHOOK_ROUTE_PREFIX","deleteJiraInstallationByConnectionId","getJiraInstallationByCloudId","getJiraInstallationByWebhookId","listJiraInstallationsDueForTokenRefresh","listJiraInstallationsDueForWebhookRenewal","markJiraInstallationRevoked","updateJiraInstallationTokenExpiry","updateJiraInstallationWebhook","updateJiraInstallationWebhookIfUnchanged","upsertJiraInstallation","withJiraRefreshLock","withJiraRefreshLockAndWait","withJiraWebhookRegistrationLock","createJiraMaintenanceWorker","createJiraIntegrationProvider","options","jira","getInstallationByConnectionId","adapters","agentTools","agent_tools","tokenStore","webhookOptions","toJiraWebhookOptions","routes","webhookProcessor","undefined","webhookRoutes","coreDb","publishIntegrationEventReceived","recordDeliveryOnly","getIntegrationConnectionById","processor","connectionCapabilities","input","connectionId","cloudId","accessToken","webhookUrl","withRegistrationLock","onRegistrationSuccess","onRegistrationFailure","then","provider","displayName","connectionExternalUrl","connection","id","siteUrl","cleanup","webhookProcessors","routeIds","Error"],"mappings":"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"}
@@ -1,6 +1,7 @@
1
1
  import { type RouteGroup } from '@shipfox/node-fastify';
2
2
  import { type CreateJiraWebhookProcessorOptions, type JiraWebhookProcessor } from '#core/webhook-processor.js';
3
- export declare const JIRA_WEBHOOK_ROUTE_PREFIX = "/webhooks/integrations/jira";
3
+ import { JIRA_WEBHOOK_ROUTE_PREFIX } from '#core/webhook-url.js';
4
+ export { JIRA_WEBHOOK_ROUTE_PREFIX };
4
5
  export interface CreateJiraWebhookRoutesOptions extends Omit<CreateJiraWebhookProcessorOptions, 'getJiraInstallationByConnectionId'> {
5
6
  processor?: JiraWebhookProcessor | undefined;
6
7
  }
@@ -1 +1 @@
1
- {"version":3,"file":"webhooks.d.ts","sourceRoot":"","sources":["../../../src/presentation/routes/webhooks.ts"],"names":[],"mappings":"AAGA,OAAO,EAGL,KAAK,UAAU,EAGhB,MAAM,uBAAuB,CAAC;AAE/B,OAAO,EACL,KAAK,iCAAiC,EAEtC,KAAK,oBAAoB,EAC1B,MAAM,4BAA4B,CAAC;AAGpC,eAAO,MAAM,yBAAyB,gCAAgC,CAAC;AAEvE,MAAM,WAAW,8BACf,SAAQ,IAAI,CAAC,iCAAiC,EAAE,mCAAmC,CAAC;IACpF,SAAS,CAAC,EAAE,oBAAoB,GAAG,SAAS,CAAC;CAC9C;AAED,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,8BAA8B,GAAG,UAAU,CAgC3F"}
1
+ {"version":3,"file":"webhooks.d.ts","sourceRoot":"","sources":["../../../src/presentation/routes/webhooks.ts"],"names":[],"mappings":"AAGA,OAAO,EAGL,KAAK,UAAU,EAGhB,MAAM,uBAAuB,CAAC;AAE/B,OAAO,EACL,KAAK,iCAAiC,EAEtC,KAAK,oBAAoB,EAC1B,MAAM,4BAA4B,CAAC;AACpC,OAAO,EAAC,yBAAyB,EAAC,MAAM,sBAAsB,CAAC;AAI/D,OAAO,EAAC,yBAAyB,EAAC,CAAC;AAEnC,MAAM,WAAW,8BACf,SAAQ,IAAI,CAAC,iCAAiC,EAAE,mCAAmC,CAAC;IACpF,SAAS,CAAC,EAAE,oBAAoB,GAAG,SAAS,CAAC;CAC9C;AAED,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,8BAA8B,GAAG,UAAU,CAgC3F"}
@@ -3,10 +3,11 @@ import { createStoredWebhookRequest, WEBHOOK_MAX_RAW_BODY_BYTES } from '@shipfox
3
3
  import { ClientError, defineRoute, rawBodyPlugin, WEBHOOK_BODY_LIMIT } from '@shipfox/node-fastify';
4
4
  import { z } from 'zod';
5
5
  import { createJiraWebhookProcessor } from '#core/webhook-processor.js';
6
+ import { JIRA_WEBHOOK_ROUTE_PREFIX } from '#core/webhook-url.js';
6
7
  const jiraWebhookParamsSchema = z.object({
7
8
  connectionId: z.string().uuid()
8
9
  });
9
- export const JIRA_WEBHOOK_ROUTE_PREFIX = '/webhooks/integrations/jira';
10
+ export { JIRA_WEBHOOK_ROUTE_PREFIX };
10
11
  export function createJiraWebhookRoutes(options) {
11
12
  const processor = options.processor ?? createJiraWebhookProcessor(options);
12
13
  const route = defineRoute({
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/presentation/routes/webhooks.ts"],"sourcesContent":["import {randomUUID} from 'node:crypto';\nimport type {StoredWebhookRequest, WebhookProcessingResult} from '@shipfox/api-integration-spi';\nimport {createStoredWebhookRequest, WEBHOOK_MAX_RAW_BODY_BYTES} from '@shipfox/api-integration-spi';\nimport {\n ClientError,\n defineRoute,\n type RouteGroup,\n rawBodyPlugin,\n WEBHOOK_BODY_LIMIT,\n} from '@shipfox/node-fastify';\nimport {z} from 'zod';\nimport {\n type CreateJiraWebhookProcessorOptions,\n createJiraWebhookProcessor,\n type JiraWebhookProcessor,\n} from '#core/webhook-processor.js';\n\nconst jiraWebhookParamsSchema = z.object({connectionId: z.string().uuid()});\nexport const JIRA_WEBHOOK_ROUTE_PREFIX = '/webhooks/integrations/jira';\n\nexport interface CreateJiraWebhookRoutesOptions\n extends Omit<CreateJiraWebhookProcessorOptions, 'getJiraInstallationByConnectionId'> {\n processor?: JiraWebhookProcessor | undefined;\n}\n\nexport function createJiraWebhookRoutes(options: CreateJiraWebhookRoutesOptions): RouteGroup {\n const processor = options.processor ?? createJiraWebhookProcessor(options);\n const route = defineRoute({\n method: 'POST',\n path: '/:connectionId',\n auth: [],\n description: 'Jira dynamic webhook receiver.',\n options: {bodyLimit: WEBHOOK_BODY_LIMIT},\n schema: {params: jiraWebhookParamsSchema},\n handler: async (request, reply) => {\n const body = request.body;\n if (!(body instanceof Uint8Array)) {\n throw new ClientError('Expected raw JSON body', 'invalid-webhook-request', {status: 400});\n }\n const result = await processor.process(\n createJiraStoredWebhookRequest({\n body,\n connectionId: request.params.connectionId,\n headers: request.headers,\n rawQueryString: request.raw.url?.split('?')[1] ?? '',\n }),\n );\n return sendJiraWebhookResponse(reply, result);\n },\n });\n\n return {\n prefix: JIRA_WEBHOOK_ROUTE_PREFIX,\n auth: [],\n plugins: [rawBodyPlugin],\n routes: [route],\n };\n}\n\nfunction createJiraStoredWebhookRequest(input: {\n body: Uint8Array;\n connectionId: string;\n headers: Record<string, string | string[] | undefined>;\n rawQueryString: string;\n}): StoredWebhookRequest {\n if (input.body.byteLength > WEBHOOK_MAX_RAW_BODY_BYTES) {\n throw new ClientError('Webhook request body is too large', 'body-too-large', {status: 413});\n }\n try {\n return createStoredWebhookRequest({\n requestId: randomUUID(),\n routeId: 'jira',\n receivedAt: new Date().toISOString(),\n rawQueryString: input.rawQueryString,\n headers: jiraWebhookHeaders(input.headers),\n body: input.body,\n connectionId: input.connectionId,\n });\n } catch (error) {\n throw new ClientError('Webhook request metadata is invalid', 'invalid-webhook-request', {\n cause: error,\n });\n }\n}\n\nfunction jiraWebhookHeaders(\n headers: Record<string, string | string[] | undefined>,\n): Record<string, string> {\n return Object.fromEntries(\n ['authorization', 'content-type', 'x-atlassian-webhook-identifier'].flatMap((name) => {\n const value = headers[name];\n return typeof value === 'string' ? [[name, value]] : [];\n }),\n );\n}\n\nfunction sendJiraWebhookResponse(\n reply: {code(statusCode: number): void},\n result: WebhookProcessingResult,\n) {\n if (result.outcome !== 'discarded') {\n reply.code(200);\n return null;\n }\n if (result.reason === 'invalid_signature' || result.reason === 'missing_required_input') {\n reply.code(401);\n return {error: 'invalid authorization'};\n }\n if (result.reason === 'malformed_payload') {\n reply.code(400);\n return {error: 'malformed JSON'};\n }\n reply.code(200);\n return null;\n}\n"],"names":["randomUUID","createStoredWebhookRequest","WEBHOOK_MAX_RAW_BODY_BYTES","ClientError","defineRoute","rawBodyPlugin","WEBHOOK_BODY_LIMIT","z","createJiraWebhookProcessor","jiraWebhookParamsSchema","object","connectionId","string","uuid","JIRA_WEBHOOK_ROUTE_PREFIX","createJiraWebhookRoutes","options","processor","route","method","path","auth","description","bodyLimit","schema","params","handler","request","reply","body","Uint8Array","status","result","process","createJiraStoredWebhookRequest","headers","rawQueryString","raw","url","split","sendJiraWebhookResponse","prefix","plugins","routes","input","byteLength","requestId","routeId","receivedAt","Date","toISOString","jiraWebhookHeaders","error","cause","Object","fromEntries","flatMap","name","value","outcome","code","reason"],"mappings":"AAAA,SAAQA,UAAU,QAAO,cAAc;AAEvC,SAAQC,0BAA0B,EAAEC,0BAA0B,QAAO,+BAA+B;AACpG,SACEC,WAAW,EACXC,WAAW,EAEXC,aAAa,EACbC,kBAAkB,QACb,wBAAwB;AAC/B,SAAQC,CAAC,QAAO,MAAM;AACtB,SAEEC,0BAA0B,QAErB,6BAA6B;AAEpC,MAAMC,0BAA0BF,EAAEG,MAAM,CAAC;IAACC,cAAcJ,EAAEK,MAAM,GAAGC,IAAI;AAAE;AACzE,OAAO,MAAMC,4BAA4B,8BAA8B;AAOvE,OAAO,SAASC,wBAAwBC,OAAuC;IAC7E,MAAMC,YAAYD,QAAQC,SAAS,IAAIT,2BAA2BQ;IAClE,MAAME,QAAQd,YAAY;QACxBe,QAAQ;QACRC,MAAM;QACNC,MAAM,EAAE;QACRC,aAAa;QACbN,SAAS;YAACO,WAAWjB;QAAkB;QACvCkB,QAAQ;YAACC,QAAQhB;QAAuB;QACxCiB,SAAS,OAAOC,SAASC;YACvB,MAAMC,OAAOF,QAAQE,IAAI;YACzB,IAAI,CAAEA,CAAAA,gBAAgBC,UAAS,GAAI;gBACjC,MAAM,IAAI3B,YAAY,0BAA0B,2BAA2B;oBAAC4B,QAAQ;gBAAG;YACzF;YACA,MAAMC,SAAS,MAAMf,UAAUgB,OAAO,CACpCC,+BAA+B;gBAC7BL;gBACAlB,cAAcgB,QAAQF,MAAM,CAACd,YAAY;gBACzCwB,SAASR,QAAQQ,OAAO;gBACxBC,gBAAgBT,QAAQU,GAAG,CAACC,GAAG,EAAEC,MAAM,IAAI,CAAC,EAAE,IAAI;YACpD;YAEF,OAAOC,wBAAwBZ,OAAOI;QACxC;IACF;IAEA,OAAO;QACLS,QAAQ3B;QACRO,MAAM,EAAE;QACRqB,SAAS;YAACrC;SAAc;QACxBsC,QAAQ;YAACzB;SAAM;IACjB;AACF;AAEA,SAASgB,+BAA+BU,KAKvC;IACC,IAAIA,MAAMf,IAAI,CAACgB,UAAU,GAAG3C,4BAA4B;QACtD,MAAM,IAAIC,YAAY,qCAAqC,kBAAkB;YAAC4B,QAAQ;QAAG;IAC3F;IACA,IAAI;QACF,OAAO9B,2BAA2B;YAChC6C,WAAW9C;YACX+C,SAAS;YACTC,YAAY,IAAIC,OAAOC,WAAW;YAClCd,gBAAgBQ,MAAMR,cAAc;YACpCD,SAASgB,mBAAmBP,MAAMT,OAAO;YACzCN,MAAMe,MAAMf,IAAI;YAChBlB,cAAciC,MAAMjC,YAAY;QAClC;IACF,EAAE,OAAOyC,OAAO;QACd,MAAM,IAAIjD,YAAY,uCAAuC,2BAA2B;YACtFkD,OAAOD;QACT;IACF;AACF;AAEA,SAASD,mBACPhB,OAAsD;IAEtD,OAAOmB,OAAOC,WAAW,CACvB;QAAC;QAAiB;QAAgB;KAAiC,CAACC,OAAO,CAAC,CAACC;QAC3E,MAAMC,QAAQvB,OAAO,CAACsB,KAAK;QAC3B,OAAO,OAAOC,UAAU,WAAW;YAAC;gBAACD;gBAAMC;aAAM;SAAC,GAAG,EAAE;IACzD;AAEJ;AAEA,SAASlB,wBACPZ,KAAuC,EACvCI,MAA+B;IAE/B,IAAIA,OAAO2B,OAAO,KAAK,aAAa;QAClC/B,MAAMgC,IAAI,CAAC;QACX,OAAO;IACT;IACA,IAAI5B,OAAO6B,MAAM,KAAK,uBAAuB7B,OAAO6B,MAAM,KAAK,0BAA0B;QACvFjC,MAAMgC,IAAI,CAAC;QACX,OAAO;YAACR,OAAO;QAAuB;IACxC;IACA,IAAIpB,OAAO6B,MAAM,KAAK,qBAAqB;QACzCjC,MAAMgC,IAAI,CAAC;QACX,OAAO;YAACR,OAAO;QAAgB;IACjC;IACAxB,MAAMgC,IAAI,CAAC;IACX,OAAO;AACT"}
1
+ {"version":3,"sources":["../../../src/presentation/routes/webhooks.ts"],"sourcesContent":["import {randomUUID} from 'node:crypto';\nimport type {StoredWebhookRequest, WebhookProcessingResult} from '@shipfox/api-integration-spi';\nimport {createStoredWebhookRequest, WEBHOOK_MAX_RAW_BODY_BYTES} from '@shipfox/api-integration-spi';\nimport {\n ClientError,\n defineRoute,\n type RouteGroup,\n rawBodyPlugin,\n WEBHOOK_BODY_LIMIT,\n} from '@shipfox/node-fastify';\nimport {z} from 'zod';\nimport {\n type CreateJiraWebhookProcessorOptions,\n createJiraWebhookProcessor,\n type JiraWebhookProcessor,\n} from '#core/webhook-processor.js';\nimport {JIRA_WEBHOOK_ROUTE_PREFIX} from '#core/webhook-url.js';\n\nconst jiraWebhookParamsSchema = z.object({connectionId: z.string().uuid()});\n\nexport {JIRA_WEBHOOK_ROUTE_PREFIX};\n\nexport interface CreateJiraWebhookRoutesOptions\n extends Omit<CreateJiraWebhookProcessorOptions, 'getJiraInstallationByConnectionId'> {\n processor?: JiraWebhookProcessor | undefined;\n}\n\nexport function createJiraWebhookRoutes(options: CreateJiraWebhookRoutesOptions): RouteGroup {\n const processor = options.processor ?? createJiraWebhookProcessor(options);\n const route = defineRoute({\n method: 'POST',\n path: '/:connectionId',\n auth: [],\n description: 'Jira dynamic webhook receiver.',\n options: {bodyLimit: WEBHOOK_BODY_LIMIT},\n schema: {params: jiraWebhookParamsSchema},\n handler: async (request, reply) => {\n const body = request.body;\n if (!(body instanceof Uint8Array)) {\n throw new ClientError('Expected raw JSON body', 'invalid-webhook-request', {status: 400});\n }\n const result = await processor.process(\n createJiraStoredWebhookRequest({\n body,\n connectionId: request.params.connectionId,\n headers: request.headers,\n rawQueryString: request.raw.url?.split('?')[1] ?? '',\n }),\n );\n return sendJiraWebhookResponse(reply, result);\n },\n });\n\n return {\n prefix: JIRA_WEBHOOK_ROUTE_PREFIX,\n auth: [],\n plugins: [rawBodyPlugin],\n routes: [route],\n };\n}\n\nfunction createJiraStoredWebhookRequest(input: {\n body: Uint8Array;\n connectionId: string;\n headers: Record<string, string | string[] | undefined>;\n rawQueryString: string;\n}): StoredWebhookRequest {\n if (input.body.byteLength > WEBHOOK_MAX_RAW_BODY_BYTES) {\n throw new ClientError('Webhook request body is too large', 'body-too-large', {status: 413});\n }\n try {\n return createStoredWebhookRequest({\n requestId: randomUUID(),\n routeId: 'jira',\n receivedAt: new Date().toISOString(),\n rawQueryString: input.rawQueryString,\n headers: jiraWebhookHeaders(input.headers),\n body: input.body,\n connectionId: input.connectionId,\n });\n } catch (error) {\n throw new ClientError('Webhook request metadata is invalid', 'invalid-webhook-request', {\n cause: error,\n });\n }\n}\n\nfunction jiraWebhookHeaders(\n headers: Record<string, string | string[] | undefined>,\n): Record<string, string> {\n return Object.fromEntries(\n ['authorization', 'content-type', 'x-atlassian-webhook-identifier'].flatMap((name) => {\n const value = headers[name];\n return typeof value === 'string' ? [[name, value]] : [];\n }),\n );\n}\n\nfunction sendJiraWebhookResponse(\n reply: {code(statusCode: number): void},\n result: WebhookProcessingResult,\n) {\n if (result.outcome !== 'discarded') {\n reply.code(200);\n return null;\n }\n if (result.reason === 'invalid_signature' || result.reason === 'missing_required_input') {\n reply.code(401);\n return {error: 'invalid authorization'};\n }\n if (result.reason === 'malformed_payload') {\n reply.code(400);\n return {error: 'malformed JSON'};\n }\n reply.code(200);\n return null;\n}\n"],"names":["randomUUID","createStoredWebhookRequest","WEBHOOK_MAX_RAW_BODY_BYTES","ClientError","defineRoute","rawBodyPlugin","WEBHOOK_BODY_LIMIT","z","createJiraWebhookProcessor","JIRA_WEBHOOK_ROUTE_PREFIX","jiraWebhookParamsSchema","object","connectionId","string","uuid","createJiraWebhookRoutes","options","processor","route","method","path","auth","description","bodyLimit","schema","params","handler","request","reply","body","Uint8Array","status","result","process","createJiraStoredWebhookRequest","headers","rawQueryString","raw","url","split","sendJiraWebhookResponse","prefix","plugins","routes","input","byteLength","requestId","routeId","receivedAt","Date","toISOString","jiraWebhookHeaders","error","cause","Object","fromEntries","flatMap","name","value","outcome","code","reason"],"mappings":"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"}
@@ -1,2 +1,9 @@
1
- export { type CreateJiraMaintenanceActivitiesOptions, createJiraMaintenanceActivities, type JiraTokenRefreshActivityResult, } from './refresh-jira-tokens.js';
1
+ import { type CreateJiraMaintenanceActivitiesOptions as CreateJiraTokenMaintenanceActivitiesOptions, type JiraTokenRefreshActivityResult } from './refresh-jira-tokens.js';
2
+ import { type CreateJiraWebhookRenewalActivitiesOptions, type JiraWebhookRenewalActivityResult } from './renew-jira-webhooks.js';
3
+ export type CreateJiraMaintenanceActivitiesOptions = CreateJiraTokenMaintenanceActivitiesOptions & CreateJiraWebhookRenewalActivitiesOptions;
4
+ export declare function createJiraMaintenanceActivities(options: CreateJiraMaintenanceActivitiesOptions): {
5
+ refreshJiraTokensActivity(): Promise<JiraTokenRefreshActivityResult>;
6
+ renewJiraWebhooksActivity(): Promise<JiraWebhookRenewalActivityResult>;
7
+ };
8
+ export type { JiraTokenRefreshActivityResult, JiraWebhookRenewalActivityResult };
2
9
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/temporal/activities/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,sCAAsC,EAC3C,+BAA+B,EAC/B,KAAK,8BAA8B,GACpC,MAAM,0BAA0B,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/temporal/activities/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,sCAAsC,IAAI,2CAA2C,EAE1F,KAAK,8BAA8B,EACpC,MAAM,0BAA0B,CAAC;AAClC,OAAO,EACL,KAAK,yCAAyC,EAE9C,KAAK,gCAAgC,EACtC,MAAM,0BAA0B,CAAC;AAElC,MAAM,MAAM,sCAAsC,GAAG,2CAA2C,GAC9F,yCAAyC,CAAC;AAE5C,wBAAgB,+BAA+B,CAAC,OAAO,EAAE,sCAAsC;;;EAK9F;AAED,YAAY,EAAC,8BAA8B,EAAE,gCAAgC,EAAC,CAAC"}
@@ -1,3 +1,10 @@
1
- export { createJiraMaintenanceActivities } from './refresh-jira-tokens.js';
1
+ import { createJiraMaintenanceActivities as createJiraTokenMaintenanceActivities } from './refresh-jira-tokens.js';
2
+ import { createJiraWebhookRenewalActivities } from './renew-jira-webhooks.js';
3
+ export function createJiraMaintenanceActivities(options) {
4
+ return {
5
+ ...createJiraTokenMaintenanceActivities(options),
6
+ ...createJiraWebhookRenewalActivities(options)
7
+ };
8
+ }
2
9
 
3
10
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/temporal/activities/index.ts"],"sourcesContent":["export {\n type CreateJiraMaintenanceActivitiesOptions,\n createJiraMaintenanceActivities,\n type JiraTokenRefreshActivityResult,\n} from './refresh-jira-tokens.js';\n"],"names":["createJiraMaintenanceActivities"],"mappings":"AAAA,SAEEA,+BAA+B,QAE1B,2BAA2B"}
1
+ {"version":3,"sources":["../../../src/temporal/activities/index.ts"],"sourcesContent":["import {\n type CreateJiraMaintenanceActivitiesOptions as CreateJiraTokenMaintenanceActivitiesOptions,\n createJiraMaintenanceActivities as createJiraTokenMaintenanceActivities,\n type JiraTokenRefreshActivityResult,\n} from './refresh-jira-tokens.js';\nimport {\n type CreateJiraWebhookRenewalActivitiesOptions,\n createJiraWebhookRenewalActivities,\n type JiraWebhookRenewalActivityResult,\n} from './renew-jira-webhooks.js';\n\nexport type CreateJiraMaintenanceActivitiesOptions = CreateJiraTokenMaintenanceActivitiesOptions &\n CreateJiraWebhookRenewalActivitiesOptions;\n\nexport function createJiraMaintenanceActivities(options: CreateJiraMaintenanceActivitiesOptions) {\n return {\n ...createJiraTokenMaintenanceActivities(options),\n ...createJiraWebhookRenewalActivities(options),\n };\n}\n\nexport type {JiraTokenRefreshActivityResult, JiraWebhookRenewalActivityResult};\n"],"names":["createJiraMaintenanceActivities","createJiraTokenMaintenanceActivities","createJiraWebhookRenewalActivities","options"],"mappings":"AAAA,SAEEA,mCAAmCC,oCAAoC,QAElE,2BAA2B;AAClC,SAEEC,kCAAkC,QAE7B,2BAA2B;AAKlC,OAAO,SAASF,gCAAgCG,OAA+C;IAC7F,OAAO;QACL,GAAGF,qCAAqCE,QAAQ;QAChD,GAAGD,mCAAmCC,QAAQ;IAChD;AACF"}
@@ -0,0 +1,26 @@
1
+ import type { IntegrationConnection } from '@shipfox/api-integration-spi';
2
+ import type { JiraApiClient } from '#api/client.js';
3
+ import type { JiraTokenStore } from '#core/tokens.js';
4
+ import { registerJiraWebhook } from '#core/webhook-registration.js';
5
+ import { listJiraInstallationsDueForWebhookRenewal, updateJiraInstallationWebhookIfUnchanged } from '#db/installations.js';
6
+ export interface JiraWebhookRenewalActivityResult {
7
+ renewed: number;
8
+ reregistered: number;
9
+ skipped: number;
10
+ failed: number;
11
+ }
12
+ export interface CreateJiraWebhookRenewalActivitiesOptions {
13
+ tokenStore: Pick<JiraTokenStore, 'getAccessToken'>;
14
+ jira?: Pick<JiraApiClient, 'refreshDynamicWebhooks' | 'registerDynamicWebhook' | 'deleteDynamicWebhook'> | undefined;
15
+ webhookUrlForConnection?: ((connectionId: string) => string) | undefined;
16
+ resolveConnection(connectionId: string): Promise<Pick<IntegrationConnection, 'lifecycleStatus'> | undefined>;
17
+ listInstallations?: typeof listJiraInstallationsDueForWebhookRenewal | undefined;
18
+ updateInstallation?: typeof updateJiraInstallationWebhookIfUnchanged | undefined;
19
+ registerWebhook?: typeof registerJiraWebhook | undefined;
20
+ now?: (() => Date) | undefined;
21
+ heartbeat?: (() => void) | undefined;
22
+ }
23
+ export declare function createJiraWebhookRenewalActivities(options: CreateJiraWebhookRenewalActivitiesOptions): {
24
+ renewJiraWebhooksActivity(): Promise<JiraWebhookRenewalActivityResult>;
25
+ };
26
+ //# sourceMappingURL=renew-jira-webhooks.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"renew-jira-webhooks.d.ts","sourceRoot":"","sources":["../../../src/temporal/activities/renew-jira-webhooks.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,qBAAqB,EAAC,MAAM,8BAA8B,CAAC;AAExE,OAAO,KAAK,EAAC,aAAa,EAAC,MAAM,gBAAgB,CAAC;AAClD,OAAO,KAAK,EAAC,cAAc,EAAC,MAAM,iBAAiB,CAAC;AACpD,OAAO,EAAC,mBAAmB,EAAC,MAAM,+BAA+B,CAAC;AAClE,OAAO,EAEL,yCAAyC,EACzC,wCAAwC,EACzC,MAAM,sBAAsB,CAAC;AAQ9B,MAAM,WAAW,gCAAgC;IAC/C,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,EAAE,MAAM,CAAC;IACrB,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,yCAAyC;IACxD,UAAU,EAAE,IAAI,CAAC,cAAc,EAAE,gBAAgB,CAAC,CAAC;IACnD,IAAI,CAAC,EACD,IAAI,CACF,aAAa,EACb,wBAAwB,GAAG,wBAAwB,GAAG,sBAAsB,CAC7E,GACD,SAAS,CAAC;IACd,uBAAuB,CAAC,EAAE,CAAC,CAAC,YAAY,EAAE,MAAM,KAAK,MAAM,CAAC,GAAG,SAAS,CAAC;IACzE,iBAAiB,CACf,YAAY,EAAE,MAAM,GACnB,OAAO,CAAC,IAAI,CAAC,qBAAqB,EAAE,iBAAiB,CAAC,GAAG,SAAS,CAAC,CAAC;IACvE,iBAAiB,CAAC,EAAE,OAAO,yCAAyC,GAAG,SAAS,CAAC;IACjF,kBAAkB,CAAC,EAAE,OAAO,wCAAwC,GAAG,SAAS,CAAC;IACjF,eAAe,CAAC,EAAE,OAAO,mBAAmB,GAAG,SAAS,CAAC;IACzD,GAAG,CAAC,EAAE,CAAC,MAAM,IAAI,CAAC,GAAG,SAAS,CAAC;IAC/B,SAAS,CAAC,EAAE,CAAC,MAAM,IAAI,CAAC,GAAG,SAAS,CAAC;CACtC;AAED,wBAAgB,kCAAkC,CAChD,OAAO,EAAE,yCAAyC;IAS1C,yBAAyB,IAAI,OAAO,CAAC,gCAAgC,CAAC;EAkF/E"}
@@ -0,0 +1,96 @@
1
+ import { logger } from '@shipfox/node-opentelemetry';
2
+ import { registerJiraWebhook } from '#core/webhook-registration.js';
3
+ import { listJiraInstallationsDueForWebhookRenewal, updateJiraInstallationWebhookIfUnchanged } from '#db/installations.js';
4
+ import { JIRA_WEBHOOK_RENEWAL_SWEEP_BATCH_SIZE, JIRA_WEBHOOK_RENEWAL_THRESHOLD_MS } from '#temporal/constants.js';
5
+ const JIRA_WEBHOOK_HEARTBEAT_INTERVAL_MS = 15_000;
6
+ export function createJiraWebhookRenewalActivities(options) {
7
+ const listInstallations = options.listInstallations ?? listJiraInstallationsDueForWebhookRenewal;
8
+ const updateInstallation = options.updateInstallation ?? updateJiraInstallationWebhookIfUnchanged;
9
+ const registerWebhook = options.registerWebhook ?? registerJiraWebhook;
10
+ const now = options.now ?? (()=>new Date());
11
+ const heartbeat = options.heartbeat ?? (()=>undefined);
12
+ return {
13
+ async renewJiraWebhooksActivity () {
14
+ const renewalDeadline = new Date(now().getTime() + JIRA_WEBHOOK_RENEWAL_THRESHOLD_MS);
15
+ const installations = await listInstallations({
16
+ before: renewalDeadline,
17
+ limit: JIRA_WEBHOOK_RENEWAL_SWEEP_BATCH_SIZE
18
+ });
19
+ let renewed = 0;
20
+ let reregistered = 0;
21
+ let skipped = 0;
22
+ let failed = 0;
23
+ for (const installation of installations){
24
+ const heartbeatInterval = setInterval(heartbeat, JIRA_WEBHOOK_HEARTBEAT_INTERVAL_MS);
25
+ try {
26
+ heartbeat();
27
+ if (!isDueForRenewal(installation, renewalDeadline)) {
28
+ skipped += 1;
29
+ continue;
30
+ }
31
+ const connection = await options.resolveConnection(installation.connectionId);
32
+ if (connection?.lifecycleStatus !== 'active') {
33
+ skipped += 1;
34
+ continue;
35
+ }
36
+ if (!options.jira || !options.webhookUrlForConnection) {
37
+ throw new Error('Jira webhook renewal dependencies are not configured');
38
+ }
39
+ const accessToken = await options.tokenStore.getAccessToken({
40
+ connectionId: installation.connectionId
41
+ });
42
+ const webhookExpiresAt = installation.webhookIds.length === 0 ? undefined : await options.jira.refreshDynamicWebhooks({
43
+ accessToken,
44
+ cloudId: installation.cloudId,
45
+ webhookIds: installation.webhookIds
46
+ });
47
+ if (webhookExpiresAt === undefined) {
48
+ await registerWebhook({
49
+ jira: options.jira,
50
+ connectionId: installation.connectionId,
51
+ cloudId: installation.cloudId,
52
+ accessToken,
53
+ webhookUrl: options.webhookUrlForConnection(installation.connectionId),
54
+ now,
55
+ replaceExistingWebhooks: true
56
+ });
57
+ reregistered += 1;
58
+ } else {
59
+ const updated = await updateInstallation({
60
+ connectionId: installation.connectionId,
61
+ webhookIds: installation.webhookIds,
62
+ webhookExpiresAt,
63
+ expectedWebhookIds: installation.webhookIds,
64
+ expectedWebhookExpiresAt: installation.webhookExpiresAt
65
+ });
66
+ if (!updated) {
67
+ skipped += 1;
68
+ continue;
69
+ }
70
+ renewed += 1;
71
+ }
72
+ } catch (error) {
73
+ failed += 1;
74
+ logger().warn({
75
+ err: error,
76
+ connectionId: installation.connectionId
77
+ }, 'Jira webhook renewal failed');
78
+ } finally{
79
+ clearInterval(heartbeatInterval);
80
+ heartbeat();
81
+ }
82
+ }
83
+ return {
84
+ renewed,
85
+ reregistered,
86
+ skipped,
87
+ failed
88
+ };
89
+ }
90
+ };
91
+ }
92
+ function isDueForRenewal(installation, renewalDeadline) {
93
+ return installation.status === 'installed' && installation.webhookExpiresAt !== null && installation.webhookExpiresAt.getTime() <= renewalDeadline.getTime();
94
+ }
95
+
96
+ //# sourceMappingURL=renew-jira-webhooks.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/temporal/activities/renew-jira-webhooks.ts"],"sourcesContent":["import type {IntegrationConnection} from '@shipfox/api-integration-spi';\nimport {logger} from '@shipfox/node-opentelemetry';\nimport type {JiraApiClient} from '#api/client.js';\nimport type {JiraTokenStore} from '#core/tokens.js';\nimport {registerJiraWebhook} from '#core/webhook-registration.js';\nimport {\n type JiraInstallation,\n listJiraInstallationsDueForWebhookRenewal,\n updateJiraInstallationWebhookIfUnchanged,\n} from '#db/installations.js';\nimport {\n JIRA_WEBHOOK_RENEWAL_SWEEP_BATCH_SIZE,\n JIRA_WEBHOOK_RENEWAL_THRESHOLD_MS,\n} from '#temporal/constants.js';\n\nconst JIRA_WEBHOOK_HEARTBEAT_INTERVAL_MS = 15_000;\n\nexport interface JiraWebhookRenewalActivityResult {\n renewed: number;\n reregistered: number;\n skipped: number;\n failed: number;\n}\n\nexport interface CreateJiraWebhookRenewalActivitiesOptions {\n tokenStore: Pick<JiraTokenStore, 'getAccessToken'>;\n jira?:\n | Pick<\n JiraApiClient,\n 'refreshDynamicWebhooks' | 'registerDynamicWebhook' | 'deleteDynamicWebhook'\n >\n | undefined;\n webhookUrlForConnection?: ((connectionId: string) => string) | undefined;\n resolveConnection(\n connectionId: string,\n ): Promise<Pick<IntegrationConnection, 'lifecycleStatus'> | undefined>;\n listInstallations?: typeof listJiraInstallationsDueForWebhookRenewal | undefined;\n updateInstallation?: typeof updateJiraInstallationWebhookIfUnchanged | undefined;\n registerWebhook?: typeof registerJiraWebhook | undefined;\n now?: (() => Date) | undefined;\n heartbeat?: (() => void) | undefined;\n}\n\nexport function createJiraWebhookRenewalActivities(\n options: CreateJiraWebhookRenewalActivitiesOptions,\n) {\n const listInstallations = options.listInstallations ?? listJiraInstallationsDueForWebhookRenewal;\n const updateInstallation = options.updateInstallation ?? updateJiraInstallationWebhookIfUnchanged;\n const registerWebhook = options.registerWebhook ?? registerJiraWebhook;\n const now = options.now ?? (() => new Date());\n const heartbeat = options.heartbeat ?? (() => undefined);\n\n return {\n async renewJiraWebhooksActivity(): Promise<JiraWebhookRenewalActivityResult> {\n const renewalDeadline = new Date(now().getTime() + JIRA_WEBHOOK_RENEWAL_THRESHOLD_MS);\n const installations = await listInstallations({\n before: renewalDeadline,\n limit: JIRA_WEBHOOK_RENEWAL_SWEEP_BATCH_SIZE,\n });\n let renewed = 0;\n let reregistered = 0;\n let skipped = 0;\n let failed = 0;\n\n for (const installation of installations) {\n const heartbeatInterval = setInterval(heartbeat, JIRA_WEBHOOK_HEARTBEAT_INTERVAL_MS);\n try {\n heartbeat();\n if (!isDueForRenewal(installation, renewalDeadline)) {\n skipped += 1;\n continue;\n }\n\n const connection = await options.resolveConnection(installation.connectionId);\n if (connection?.lifecycleStatus !== 'active') {\n skipped += 1;\n continue;\n }\n\n if (!options.jira || !options.webhookUrlForConnection) {\n throw new Error('Jira webhook renewal dependencies are not configured');\n }\n\n const accessToken = await options.tokenStore.getAccessToken({\n connectionId: installation.connectionId,\n });\n const webhookExpiresAt =\n installation.webhookIds.length === 0\n ? undefined\n : await options.jira.refreshDynamicWebhooks({\n accessToken,\n cloudId: installation.cloudId,\n webhookIds: installation.webhookIds,\n });\n\n if (webhookExpiresAt === undefined) {\n await registerWebhook({\n jira: options.jira,\n connectionId: installation.connectionId,\n cloudId: installation.cloudId,\n accessToken,\n webhookUrl: options.webhookUrlForConnection(installation.connectionId),\n now,\n replaceExistingWebhooks: true,\n });\n reregistered += 1;\n } else {\n const updated = await updateInstallation({\n connectionId: installation.connectionId,\n webhookIds: installation.webhookIds,\n webhookExpiresAt,\n expectedWebhookIds: installation.webhookIds,\n expectedWebhookExpiresAt: installation.webhookExpiresAt,\n });\n if (!updated) {\n skipped += 1;\n continue;\n }\n renewed += 1;\n }\n } catch (error) {\n failed += 1;\n logger().warn(\n {err: error, connectionId: installation.connectionId},\n 'Jira webhook renewal failed',\n );\n } finally {\n clearInterval(heartbeatInterval);\n heartbeat();\n }\n }\n\n return {renewed, reregistered, skipped, failed};\n },\n };\n}\n\nfunction isDueForRenewal(installation: JiraInstallation, renewalDeadline: Date): boolean {\n return (\n installation.status === 'installed' &&\n installation.webhookExpiresAt !== null &&\n installation.webhookExpiresAt.getTime() <= renewalDeadline.getTime()\n );\n}\n"],"names":["logger","registerJiraWebhook","listJiraInstallationsDueForWebhookRenewal","updateJiraInstallationWebhookIfUnchanged","JIRA_WEBHOOK_RENEWAL_SWEEP_BATCH_SIZE","JIRA_WEBHOOK_RENEWAL_THRESHOLD_MS","JIRA_WEBHOOK_HEARTBEAT_INTERVAL_MS","createJiraWebhookRenewalActivities","options","listInstallations","updateInstallation","registerWebhook","now","Date","heartbeat","undefined","renewJiraWebhooksActivity","renewalDeadline","getTime","installations","before","limit","renewed","reregistered","skipped","failed","installation","heartbeatInterval","setInterval","isDueForRenewal","connection","resolveConnection","connectionId","lifecycleStatus","jira","webhookUrlForConnection","Error","accessToken","tokenStore","getAccessToken","webhookExpiresAt","webhookIds","length","refreshDynamicWebhooks","cloudId","webhookUrl","replaceExistingWebhooks","updated","expectedWebhookIds","expectedWebhookExpiresAt","error","warn","err","clearInterval","status"],"mappings":"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"}
@@ -1,3 +1,5 @@
1
+ export declare const JIRA_WEBHOOK_RENEWAL_THRESHOLD_MS: number;
2
+ export declare const JIRA_WEBHOOK_RENEWAL_SWEEP_BATCH_SIZE = 20;
1
3
  export declare const JIRA_REFRESH_TOKEN_IDLE_WINDOW_MS: number;
2
4
  export declare const JIRA_REFRESH_TOKEN_REFRESH_LEAD_TIME_MS: number;
3
5
  export declare const JIRA_REFRESH_TOKEN_PROACTIVE_REFRESH_AFTER_MS: number;
@@ -1 +1 @@
1
- {"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../src/temporal/constants.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,iCAAiC,QAAkB,CAAC;AACjE,eAAO,MAAM,uCAAuC,QAAkB,CAAC;AACvE,eAAO,MAAM,6CAA6C,QACmB,CAAC;AAC9E,eAAO,MAAM,mCAAmC,KAAK,CAAC;AACtD,eAAO,MAAM,2BAA2B,kCAAkC,CAAC"}
1
+ {"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../src/temporal/constants.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,iCAAiC,QAAiB,CAAC;AAChE,eAAO,MAAM,qCAAqC,KAAK,CAAC;AACxD,eAAO,MAAM,iCAAiC,QAAkB,CAAC;AACjE,eAAO,MAAM,uCAAuC,QAAkB,CAAC;AACvE,eAAO,MAAM,6CAA6C,QACmB,CAAC;AAC9E,eAAO,MAAM,mCAAmC,KAAK,CAAC;AACtD,eAAO,MAAM,2BAA2B,kCAAkC,CAAC"}
@@ -1,4 +1,6 @@
1
1
  const MS_PER_DAY = 24 * 60 * 60 * 1000;
2
+ export const JIRA_WEBHOOK_RENEWAL_THRESHOLD_MS = 7 * MS_PER_DAY;
3
+ export const JIRA_WEBHOOK_RENEWAL_SWEEP_BATCH_SIZE = 20;
2
4
  export const JIRA_REFRESH_TOKEN_IDLE_WINDOW_MS = 90 * MS_PER_DAY;
3
5
  export const JIRA_REFRESH_TOKEN_REFRESH_LEAD_TIME_MS = 14 * MS_PER_DAY;
4
6
  export const JIRA_REFRESH_TOKEN_PROACTIVE_REFRESH_AFTER_MS = JIRA_REFRESH_TOKEN_IDLE_WINDOW_MS - JIRA_REFRESH_TOKEN_REFRESH_LEAD_TIME_MS;
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/temporal/constants.ts"],"sourcesContent":["const MS_PER_DAY = 24 * 60 * 60 * 1000;\n\nexport const JIRA_REFRESH_TOKEN_IDLE_WINDOW_MS = 90 * MS_PER_DAY;\nexport const JIRA_REFRESH_TOKEN_REFRESH_LEAD_TIME_MS = 14 * MS_PER_DAY;\nexport const JIRA_REFRESH_TOKEN_PROACTIVE_REFRESH_AFTER_MS =\n JIRA_REFRESH_TOKEN_IDLE_WINDOW_MS - JIRA_REFRESH_TOKEN_REFRESH_LEAD_TIME_MS;\nexport const JIRA_REFRESH_TOKEN_SWEEP_BATCH_SIZE = 20;\nexport const JIRA_MAINTENANCE_TASK_QUEUE = 'integrations-jira-maintenance';\n"],"names":["MS_PER_DAY","JIRA_REFRESH_TOKEN_IDLE_WINDOW_MS","JIRA_REFRESH_TOKEN_REFRESH_LEAD_TIME_MS","JIRA_REFRESH_TOKEN_PROACTIVE_REFRESH_AFTER_MS","JIRA_REFRESH_TOKEN_SWEEP_BATCH_SIZE","JIRA_MAINTENANCE_TASK_QUEUE"],"mappings":"AAAA,MAAMA,aAAa,KAAK,KAAK,KAAK;AAElC,OAAO,MAAMC,oCAAoC,KAAKD,WAAW;AACjE,OAAO,MAAME,0CAA0C,KAAKF,WAAW;AACvE,OAAO,MAAMG,gDACXF,oCAAoCC,wCAAwC;AAC9E,OAAO,MAAME,sCAAsC,GAAG;AACtD,OAAO,MAAMC,8BAA8B,gCAAgC"}
1
+ {"version":3,"sources":["../../src/temporal/constants.ts"],"sourcesContent":["const MS_PER_DAY = 24 * 60 * 60 * 1000;\n\nexport const JIRA_WEBHOOK_RENEWAL_THRESHOLD_MS = 7 * MS_PER_DAY;\nexport const JIRA_WEBHOOK_RENEWAL_SWEEP_BATCH_SIZE = 20;\nexport const JIRA_REFRESH_TOKEN_IDLE_WINDOW_MS = 90 * MS_PER_DAY;\nexport const JIRA_REFRESH_TOKEN_REFRESH_LEAD_TIME_MS = 14 * MS_PER_DAY;\nexport const JIRA_REFRESH_TOKEN_PROACTIVE_REFRESH_AFTER_MS =\n JIRA_REFRESH_TOKEN_IDLE_WINDOW_MS - JIRA_REFRESH_TOKEN_REFRESH_LEAD_TIME_MS;\nexport const JIRA_REFRESH_TOKEN_SWEEP_BATCH_SIZE = 20;\nexport const JIRA_MAINTENANCE_TASK_QUEUE = 'integrations-jira-maintenance';\n"],"names":["MS_PER_DAY","JIRA_WEBHOOK_RENEWAL_THRESHOLD_MS","JIRA_WEBHOOK_RENEWAL_SWEEP_BATCH_SIZE","JIRA_REFRESH_TOKEN_IDLE_WINDOW_MS","JIRA_REFRESH_TOKEN_REFRESH_LEAD_TIME_MS","JIRA_REFRESH_TOKEN_PROACTIVE_REFRESH_AFTER_MS","JIRA_REFRESH_TOKEN_SWEEP_BATCH_SIZE","JIRA_MAINTENANCE_TASK_QUEUE"],"mappings":"AAAA,MAAMA,aAAa,KAAK,KAAK,KAAK;AAElC,OAAO,MAAMC,oCAAoC,IAAID,WAAW;AAChE,OAAO,MAAME,wCAAwC,GAAG;AACxD,OAAO,MAAMC,oCAAoC,KAAKH,WAAW;AACjE,OAAO,MAAMI,0CAA0C,KAAKJ,WAAW;AACvE,OAAO,MAAMK,gDACXF,oCAAoCC,wCAAwC;AAC9E,OAAO,MAAME,sCAAsC,GAAG;AACtD,OAAO,MAAMC,8BAA8B,gCAAgC"}
@@ -1,8 +1,11 @@
1
1
  import type { IntegrationConnection } from '@shipfox/api-integration-spi';
2
2
  import type { ModuleWorker } from '@shipfox/node-module';
3
+ import type { JiraApiClient } from '#api/client.js';
3
4
  import type { JiraTokenStore } from '#core/tokens.js';
4
5
  export interface CreateJiraMaintenanceWorkerOptions {
5
6
  tokenStore: Pick<JiraTokenStore, 'getAccessToken'>;
7
+ jira: Pick<JiraApiClient, 'refreshDynamicWebhooks' | 'registerDynamicWebhook' | 'deleteDynamicWebhook'>;
8
+ webhookUrlForConnection: (connectionId: string) => string;
6
9
  resolveConnection(connectionId: string): Promise<Pick<IntegrationConnection, 'lifecycleStatus'> | undefined>;
7
10
  }
8
11
  export declare function createJiraMaintenanceWorker(options: CreateJiraMaintenanceWorkerOptions): ModuleWorker;
@@ -1 +1 @@
1
- {"version":3,"file":"worker.d.ts","sourceRoot":"","sources":["../../src/temporal/worker.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAC,qBAAqB,EAAC,MAAM,8BAA8B,CAAC;AACxE,OAAO,KAAK,EAAC,YAAY,EAAC,MAAM,sBAAsB,CAAC;AAEvD,OAAO,KAAK,EAAC,cAAc,EAAC,MAAM,iBAAiB,CAAC;AAOpD,MAAM,WAAW,kCAAkC;IACjD,UAAU,EAAE,IAAI,CAAC,cAAc,EAAE,gBAAgB,CAAC,CAAC;IACnD,iBAAiB,CACf,YAAY,EAAE,MAAM,GACnB,OAAO,CAAC,IAAI,CAAC,qBAAqB,EAAE,iBAAiB,CAAC,GAAG,SAAS,CAAC,CAAC;CACxE;AAED,wBAAgB,2BAA2B,CACzC,OAAO,EAAE,kCAAkC,GAC1C,YAAY,CAiBd"}
1
+ {"version":3,"file":"worker.d.ts","sourceRoot":"","sources":["../../src/temporal/worker.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAC,qBAAqB,EAAC,MAAM,8BAA8B,CAAC;AACxE,OAAO,KAAK,EAAC,YAAY,EAAC,MAAM,sBAAsB,CAAC;AAEvD,OAAO,KAAK,EAAC,aAAa,EAAC,MAAM,gBAAgB,CAAC;AAClD,OAAO,KAAK,EAAC,cAAc,EAAC,MAAM,iBAAiB,CAAC;AAOpD,MAAM,WAAW,kCAAkC;IACjD,UAAU,EAAE,IAAI,CAAC,cAAc,EAAE,gBAAgB,CAAC,CAAC;IACnD,IAAI,EAAE,IAAI,CACR,aAAa,EACb,wBAAwB,GAAG,wBAAwB,GAAG,sBAAsB,CAC7E,CAAC;IACF,uBAAuB,EAAE,CAAC,YAAY,EAAE,MAAM,KAAK,MAAM,CAAC;IAC1D,iBAAiB,CACf,YAAY,EAAE,MAAM,GACnB,OAAO,CAAC,IAAI,CAAC,qBAAqB,EAAE,iBAAiB,CAAC,GAAG,SAAS,CAAC,CAAC;CACxE;AAED,wBAAgB,2BAA2B,CACzC,OAAO,EAAE,kCAAkC,GAC1C,YAAY,CAsBd"}
@@ -18,6 +18,11 @@ export function createJiraMaintenanceWorker(options) {
18
18
  name: 'refreshJiraTokensCron',
19
19
  id: 'jira-refresh-tokens',
20
20
  cronSchedule: '0 */6 * * *'
21
+ },
22
+ {
23
+ name: 'renewJiraWebhooksCron',
24
+ id: 'jira-renew-webhooks',
25
+ cronSchedule: '0 */6 * * *'
21
26
  }
22
27
  ]
23
28
  };
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/temporal/worker.ts"],"sourcesContent":["import {dirname, resolve} from 'node:path';\nimport {fileURLToPath} from 'node:url';\nimport type {IntegrationConnection} from '@shipfox/api-integration-spi';\nimport type {ModuleWorker} from '@shipfox/node-module';\nimport {Context} from '@temporalio/activity';\nimport type {JiraTokenStore} from '#core/tokens.js';\nimport {createJiraMaintenanceActivities} from '#temporal/activities/index.js';\nimport {JIRA_MAINTENANCE_TASK_QUEUE} from '#temporal/constants.js';\n\nconst packageRoot = resolve(dirname(fileURLToPath(import.meta.url)), '../..');\nconst workflowsPath = resolve(packageRoot, 'dist/temporal/workflows/index.js');\n\nexport interface CreateJiraMaintenanceWorkerOptions {\n tokenStore: Pick<JiraTokenStore, 'getAccessToken'>;\n resolveConnection(\n connectionId: string,\n ): Promise<Pick<IntegrationConnection, 'lifecycleStatus'> | undefined>;\n}\n\nexport function createJiraMaintenanceWorker(\n options: CreateJiraMaintenanceWorkerOptions,\n): ModuleWorker {\n return {\n taskQueue: JIRA_MAINTENANCE_TASK_QUEUE,\n workflowsPath,\n activities: () =>\n createJiraMaintenanceActivities({\n ...options,\n heartbeat: () => Context.current().heartbeat(),\n }),\n workflows: [\n {\n name: 'refreshJiraTokensCron',\n id: 'jira-refresh-tokens',\n cronSchedule: '0 */6 * * *',\n },\n ],\n };\n}\n"],"names":["dirname","resolve","fileURLToPath","Context","createJiraMaintenanceActivities","JIRA_MAINTENANCE_TASK_QUEUE","packageRoot","url","workflowsPath","createJiraMaintenanceWorker","options","taskQueue","activities","heartbeat","current","workflows","name","id","cronSchedule"],"mappings":"AAAA,SAAQA,OAAO,EAAEC,OAAO,QAAO,YAAY;AAC3C,SAAQC,aAAa,QAAO,WAAW;AAGvC,SAAQC,OAAO,QAAO,uBAAuB;AAE7C,SAAQC,+BAA+B,QAAO,gCAAgC;AAC9E,SAAQC,2BAA2B,QAAO,yBAAyB;AAEnE,MAAMC,cAAcL,QAAQD,QAAQE,cAAc,YAAYK,GAAG,IAAI;AACrE,MAAMC,gBAAgBP,QAAQK,aAAa;AAS3C,OAAO,SAASG,4BACdC,OAA2C;IAE3C,OAAO;QACLC,WAAWN;QACXG;QACAI,YAAY,IACVR,gCAAgC;gBAC9B,GAAGM,OAAO;gBACVG,WAAW,IAAMV,QAAQW,OAAO,GAAGD,SAAS;YAC9C;QACFE,WAAW;YACT;gBACEC,MAAM;gBACNC,IAAI;gBACJC,cAAc;YAChB;SACD;IACH;AACF"}
1
+ {"version":3,"sources":["../../src/temporal/worker.ts"],"sourcesContent":["import {dirname, resolve} from 'node:path';\nimport {fileURLToPath} from 'node:url';\nimport type {IntegrationConnection} from '@shipfox/api-integration-spi';\nimport type {ModuleWorker} from '@shipfox/node-module';\nimport {Context} from '@temporalio/activity';\nimport type {JiraApiClient} from '#api/client.js';\nimport type {JiraTokenStore} from '#core/tokens.js';\nimport {createJiraMaintenanceActivities} from '#temporal/activities/index.js';\nimport {JIRA_MAINTENANCE_TASK_QUEUE} from '#temporal/constants.js';\n\nconst packageRoot = resolve(dirname(fileURLToPath(import.meta.url)), '../..');\nconst workflowsPath = resolve(packageRoot, 'dist/temporal/workflows/index.js');\n\nexport interface CreateJiraMaintenanceWorkerOptions {\n tokenStore: Pick<JiraTokenStore, 'getAccessToken'>;\n jira: Pick<\n JiraApiClient,\n 'refreshDynamicWebhooks' | 'registerDynamicWebhook' | 'deleteDynamicWebhook'\n >;\n webhookUrlForConnection: (connectionId: string) => string;\n resolveConnection(\n connectionId: string,\n ): Promise<Pick<IntegrationConnection, 'lifecycleStatus'> | undefined>;\n}\n\nexport function createJiraMaintenanceWorker(\n options: CreateJiraMaintenanceWorkerOptions,\n): ModuleWorker {\n return {\n taskQueue: JIRA_MAINTENANCE_TASK_QUEUE,\n workflowsPath,\n activities: () =>\n createJiraMaintenanceActivities({\n ...options,\n heartbeat: () => Context.current().heartbeat(),\n }),\n workflows: [\n {\n name: 'refreshJiraTokensCron',\n id: 'jira-refresh-tokens',\n cronSchedule: '0 */6 * * *',\n },\n {\n name: 'renewJiraWebhooksCron',\n id: 'jira-renew-webhooks',\n cronSchedule: '0 */6 * * *',\n },\n ],\n };\n}\n"],"names":["dirname","resolve","fileURLToPath","Context","createJiraMaintenanceActivities","JIRA_MAINTENANCE_TASK_QUEUE","packageRoot","url","workflowsPath","createJiraMaintenanceWorker","options","taskQueue","activities","heartbeat","current","workflows","name","id","cronSchedule"],"mappings":"AAAA,SAAQA,OAAO,EAAEC,OAAO,QAAO,YAAY;AAC3C,SAAQC,aAAa,QAAO,WAAW;AAGvC,SAAQC,OAAO,QAAO,uBAAuB;AAG7C,SAAQC,+BAA+B,QAAO,gCAAgC;AAC9E,SAAQC,2BAA2B,QAAO,yBAAyB;AAEnE,MAAMC,cAAcL,QAAQD,QAAQE,cAAc,YAAYK,GAAG,IAAI;AACrE,MAAMC,gBAAgBP,QAAQK,aAAa;AAc3C,OAAO,SAASG,4BACdC,OAA2C;IAE3C,OAAO;QACLC,WAAWN;QACXG;QACAI,YAAY,IACVR,gCAAgC;gBAC9B,GAAGM,OAAO;gBACVG,WAAW,IAAMV,QAAQW,OAAO,GAAGD,SAAS;YAC9C;QACFE,WAAW;YACT;gBACEC,MAAM;gBACNC,IAAI;gBACJC,cAAc;YAChB;YACA;gBACEF,MAAM;gBACNC,IAAI;gBACJC,cAAc;YAChB;SACD;IACH;AACF"}