@shipfox/api-integration-core 13.0.0 → 14.0.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 (89) hide show
  1. package/.turbo/turbo-build.log +4 -4
  2. package/CHANGELOG.md +44 -0
  3. package/dist/core/event-catalogs.d.ts +18 -0
  4. package/dist/core/event-catalogs.d.ts.map +1 -0
  5. package/dist/core/event-catalogs.js +27 -0
  6. package/dist/core/event-catalogs.js.map +1 -0
  7. package/dist/core/providers/registry.d.ts +1 -0
  8. package/dist/core/providers/registry.d.ts.map +1 -1
  9. package/dist/core/providers/registry.js +4 -1
  10. package/dist/core/providers/registry.js.map +1 -1
  11. package/dist/core/providers/source-control.d.ts +1 -1
  12. package/dist/core/providers/source-control.d.ts.map +1 -1
  13. package/dist/core/providers/source-control.js.map +1 -1
  14. package/dist/core/source-control-service.d.ts +5 -1
  15. package/dist/core/source-control-service.d.ts.map +1 -1
  16. package/dist/core/source-control-service.js +12 -0
  17. package/dist/core/source-control-service.js.map +1 -1
  18. package/dist/db/connections.d.ts +4 -1
  19. package/dist/db/connections.d.ts.map +1 -1
  20. package/dist/db/connections.js +15 -6
  21. package/dist/db/connections.js.map +1 -1
  22. package/dist/index.d.ts +1 -1
  23. package/dist/index.d.ts.map +1 -1
  24. package/dist/index.js.map +1 -1
  25. package/dist/metrics/instance.d.ts.map +1 -1
  26. package/dist/metrics/instance.js +2 -0
  27. package/dist/metrics/instance.js.map +1 -1
  28. package/dist/presentation/inter-module.d.ts.map +1 -1
  29. package/dist/presentation/inter-module.js +27 -5
  30. package/dist/presentation/inter-module.js.map +1 -1
  31. package/dist/presentation/routes/errors.d.ts.map +1 -1
  32. package/dist/presentation/routes/errors.js +1 -1
  33. package/dist/presentation/routes/errors.js.map +1 -1
  34. package/dist/presentation/routes/manage-connections.d.ts.map +1 -1
  35. package/dist/presentation/routes/manage-connections.js +7 -3
  36. package/dist/presentation/routes/manage-connections.js.map +1 -1
  37. package/dist/providers/gitea.d.ts.map +1 -1
  38. package/dist/providers/gitea.js +5 -1
  39. package/dist/providers/gitea.js.map +1 -1
  40. package/dist/providers/github.d.ts.map +1 -1
  41. package/dist/providers/github.js +6 -5
  42. package/dist/providers/github.js.map +1 -1
  43. package/dist/providers/jira.d.ts.map +1 -1
  44. package/dist/providers/jira.js +7 -2
  45. package/dist/providers/jira.js.map +1 -1
  46. package/dist/providers/linear.d.ts.map +1 -1
  47. package/dist/providers/linear.js +6 -4
  48. package/dist/providers/linear.js.map +1 -1
  49. package/dist/providers/sentry.d.ts.map +1 -1
  50. package/dist/providers/sentry.js +3 -1
  51. package/dist/providers/sentry.js.map +1 -1
  52. package/dist/providers/slack.d.ts.map +1 -1
  53. package/dist/providers/slack.js +6 -4
  54. package/dist/providers/slack.js.map +1 -1
  55. package/dist/tsconfig.test.tsbuildinfo +1 -1
  56. package/package.json +12 -12
  57. package/src/core/agent-tool-selection.test.ts +4 -0
  58. package/src/core/event-catalogs.test.ts +16 -0
  59. package/src/core/event-catalogs.ts +34 -0
  60. package/src/core/providers/registry.test.ts +4 -0
  61. package/src/core/providers/registry.ts +9 -3
  62. package/src/core/providers/source-control.ts +2 -0
  63. package/src/core/secret-cleanup.test.ts +1 -0
  64. package/src/core/source-control-service.test.ts +48 -0
  65. package/src/core/source-control-service.ts +16 -0
  66. package/src/db/connections.test.ts +167 -0
  67. package/src/db/connections.ts +21 -4
  68. package/src/db/secret-cleanups.test.ts +1 -0
  69. package/src/index.ts +2 -0
  70. package/src/metrics/instance.ts +2 -0
  71. package/src/presentation/inter-module.test.ts +219 -0
  72. package/src/presentation/inter-module.ts +28 -3
  73. package/src/presentation/routes/errors.ts +3 -0
  74. package/src/presentation/routes/list-connections.test.ts +13 -1
  75. package/src/presentation/routes/list-repositories.test.ts +9 -0
  76. package/src/presentation/routes/manage-connections.test.ts +52 -0
  77. package/src/presentation/routes/manage-connections.ts +6 -2
  78. package/src/providers/gitea.ts +5 -0
  79. package/src/providers/github.ts +6 -1
  80. package/src/providers/jira.test.ts +3 -0
  81. package/src/providers/jira.ts +6 -0
  82. package/src/providers/linear.test.ts +3 -0
  83. package/src/providers/linear.ts +6 -1
  84. package/src/providers/modules.test.ts +64 -1
  85. package/src/providers/sentry.ts +3 -0
  86. package/src/providers/slack.test.ts +4 -0
  87. package/src/providers/slack.ts +6 -1
  88. package/test/route-utils.ts +4 -0
  89. package/tsconfig.build.tsbuildinfo +1 -1
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts"],"sourcesContent":["import {dirname, resolve} from 'node:path';\nimport {fileURLToPath} from 'node:url';\nimport {\n integrationsEventSchemas,\n type StoredWebhookRequest,\n type WebhookProcessingResult,\n type WebhookRequestProcessor,\n type WebhookRouteId,\n} from '@shipfox/api-integration-spi';\nimport type {WorkflowsModuleClient} from '@shipfox/api-workflows-dto/inter-module';\nimport type {WorkspacesInterModuleClient} from '@shipfox/api-workspaces-dto/inter-module';\nimport {reportError} from '@shipfox/node-error-monitoring';\nimport type {ModuleService, ShipfoxModule} from '@shipfox/node-module';\nimport {logger} from '@shipfox/node-opentelemetry';\nimport type {IntegrationProvider} from '#core/entities/provider.js';\nimport {WebhookProcessorNotConfiguredError} from '#core/errors.js';\nimport {\n createIntegrationProviderRegistry,\n type IntegrationProviderRegistry,\n} from '#core/providers/registry.js';\nimport {\n createSourceControlIntegrationService,\n type IntegrationSourceControlService,\n} from '#core/source-control-service.js';\nimport {getIntegrationConnectionById} from '#db/connections.js';\nimport {db} from '#db/db.js';\nimport {migrationsPath} from '#db/migrations.js';\nimport {integrationsOutbox} from '#db/schema/outbox.js';\nimport {createIntegrationsInterModulePresentation} from '#presentation/inter-module.js';\nimport {createIntegrationRoutes} from '#presentation/routes/index.js';\nimport {loadEnabledProviderModules} from '#providers/modules.js';\nimport type {\n IntegrationModuleParts,\n IntegrationProviderSecrets,\n WebhookProcessorRegistration,\n} from '#providers/types.js';\nimport {createIntegrationsMaintenanceActivities} from '#temporal/activities/index.js';\nimport {INTEGRATIONS_MAINTENANCE_TASK_QUEUE} from '#temporal/constants.js';\n\nconst packageRoot = resolve(dirname(fileURLToPath(import.meta.url)), '..');\nconst maintenanceWorkflowsPath = resolve(packageRoot, 'dist/temporal/workflows/index.js');\n\nexport type {\n StoredWebhookRequest,\n WebhookProcessingResult,\n WebhookRequestProcessor,\n WebhookRouteId,\n} from '@shipfox/api-integration-spi';\nexport {\n buildProviderRepositoryId,\n MAX_REPOSITORY_FILE_BYTES,\n parseProviderRepositoryId,\n} from '@shipfox/api-integration-spi';\nexport type {\n AgentToolCatalogs,\n AgentToolSelectionCatalogs,\n LoadWorkspaceConnectionSnapshot,\n WorkspaceConnectionSnapshot,\n WorkspaceConnectionSnapshotEntry,\n} from '#core/agent-tool-selection.js';\nexport {\n buildAgentToolCatalogs,\n buildAgentToolSelectionCatalogs,\n createWorkspaceConnectionSnapshotLoader,\n} from '#core/agent-tool-selection.js';\nexport type {\n IntegrationConnection,\n IntegrationConnectionLifecycleStatus,\n} from '#core/entities/connection.js';\nexport type {\n IntegrationCapability,\n IntegrationProvider,\n IntegrationProviderAdapters,\n IntegrationProviderKind,\n RegisteredIntegrationProvider,\n} from '#core/entities/provider.js';\nexport type {IntegrationProviderErrorReason} from '#core/errors.js';\nexport {\n ConnectionSlugConflictError,\n IntegrationCapabilityUnavailableError,\n IntegrationCheckoutUnsupportedError,\n IntegrationConnectionInactiveError,\n IntegrationConnectionNotFoundError,\n IntegrationConnectionWorkspaceMismatchError,\n IntegrationProviderError,\n IntegrationProviderUnavailableError,\n WebhookProcessorNotConfiguredError,\n} from '#core/errors.js';\nexport type {\n AgentToolCallInput,\n AgentToolCatalogEntry,\n AgentToolCatalogMethod,\n AgentToolJsonSchema,\n AgentToolSensitivity,\n AgentToolSession,\n AgentToolsProvider,\n OpenAgentToolsSessionInput,\n} from '#core/providers/agent-tools.js';\nexport {redactCheckoutSpec} from '#core/providers/redact-checkout-spec.js';\nexport type {IntegrationProviderRegistry} from '#core/providers/registry.js';\nexport type {\n CheckoutCredentials,\n CheckoutPermissions,\n CheckoutSpec,\n CreateCheckoutSpecInput,\n FetchFileInput,\n FileEntry,\n FilePage,\n FileSnapshot,\n ListFilesInput,\n ListRepositoriesInput,\n RepositoryPage,\n RepositorySnapshot,\n RepositoryVisibility,\n ResolveRepositoryInput,\n SourceControlProvider,\n TriggerReference,\n} from '#core/providers/source-control.js';\nexport type {IntegrationSourceControlService} from '#core/source-control-service.js';\nexport {createSourceControlIntegrationService} from '#core/source-control-service.js';\nexport type {\n GetIntegrationConnectionByIdFn,\n GetIntegrationConnectionBySlugFn,\n} from '#db/connections.js';\nexport {getIntegrationConnectionById, getIntegrationConnectionBySlug} from '#db/connections.js';\nexport type {\n ClaimWebhookDeliveryFn,\n PublishIntegrationEventReceivedFn,\n PublishIntegrationEventReceivedParams,\n PublishIntegrationEventReceivedResult,\n PublishSourcePushFn,\n PublishSourcePushParams,\n PublishSourceRepositoryUpdatedFn,\n PublishSourceRepositoryUpdatedParams,\n RecordDeliveryOnlyFn,\n RecordDeliveryOnlyParams,\n} from '#db/webhook-deliveries.js';\nexport {\n claimWebhookDelivery,\n pruneWebhookDeliveries,\n publishSourceRepositoryUpdated,\n} from '#db/webhook-deliveries.js';\nexport {integrationRouteErrorHandler} from '#presentation/routes/errors.js';\n\nexport interface CreateIntegrationsModuleOptions {\n providers?: IntegrationProvider[] | undefined;\n /**\n * Pre-built module parts, bypassing config-gated provider loading. Test-only seam\n * for exercising a provider's database, workers, or startup tasks directly. Takes\n * precedence over `providers`.\n */\n parts?: IntegrationModuleParts[] | undefined;\n secrets?: IntegrationProviderSecrets | undefined;\n workspaces?: WorkspacesInterModuleClient | undefined;\n agentTools?:\n | {\n workflows: WorkflowsModuleClient;\n }\n | undefined;\n webhookDeliverySource?: WebhookDeliverySource | undefined;\n}\n\n/**\n * Hosted runtimes implement this port to receive stored webhook requests. The\n * integration module starts its returned service after migrations complete.\n */\nexport interface WebhookDeliverySource {\n createService(processor: WebhookRequestProcessor): ModuleService;\n}\n\nexport interface IntegrationsContext {\n module: ShipfoxModule;\n registry: IntegrationProviderRegistry;\n capabilities: {\n sourceControl: IntegrationSourceControlService;\n };\n sourceControl: IntegrationSourceControlService;\n webhookProcessor: WebhookRequestProcessor;\n /**\n * Runs every enabled provider's one-shot boot-time tasks, after modules are initialized\n * (migrations done). Failures are isolated and logged, never rethrown, so a provider task\n * can never gate API boot. No-op when no enabled provider contributes a task.\n */\n runStartupTasks: () => Promise<void>;\n}\n\nexport async function createIntegrationsModule(\n options: CreateIntegrationsModuleOptions = {},\n): Promise<ShipfoxModule> {\n return (await createIntegrationsContext(options)).module;\n}\n\nexport async function createIntegrationsContext(\n options: CreateIntegrationsModuleOptions = {},\n): Promise<IntegrationsContext> {\n const workspaces = options.workspaces;\n const parts: IntegrationModuleParts[] =\n options.parts ??\n (options.providers\n ? options.providers.map((provider) => ({\n provider,\n webhookProcessors: provider.webhookProcessors,\n }))\n : await loadEnabledProviderModules({\n secrets: options.secrets,\n ...(workspaces\n ? {\n requireActiveWorkspaceMembership: (input: {\n workspaceId: string;\n userId: string;\n memberships: ReadonlyArray<\n import('@shipfox/api-auth-context').UserContextMembership\n >;\n }) =>\n workspaces.requireActiveMembership({\n ...input,\n memberships: [...input.memberships],\n }),\n }\n : {}),\n }));\n\n const registry = createIntegrationProviderRegistry(parts.map((part) => part.provider));\n const sourceControl = createSourceControlIntegrationService({\n registry,\n getIntegrationConnectionById,\n });\n const webhookProcessor = createComposedWebhookProcessor(\n parts.flatMap((part) => part.webhookProcessors ?? []),\n );\n\n async function runStartupTasks(): Promise<void> {\n for (const task of parts.flatMap((part) => part.startupTasks ?? [])) {\n // A provider convenience must never gate API boot.\n try {\n await task();\n } catch (error) {\n logger().error({err: error}, 'Integration startup task failed, continuing boot');\n reportError(error, {boundary: 'integration.startup'});\n }\n }\n }\n\n const module: ShipfoxModule = {\n name: 'integrations',\n interModulePresentations: [\n createIntegrationsInterModulePresentation({registry, sourceControl}),\n ],\n startupTasks: runStartupTasks,\n database: [\n {db, migrationsPath, databaseNamespace: 'integrations'},\n ...parts.flatMap((part) => (part.database ? [part.database] : [])),\n ],\n routes: createIntegrationRoutes(registry, sourceControl, {\n agentTools: options.agentTools\n ? {\n workflows: options.agentTools.workflows,\n getIntegrationConnectionById,\n }\n : undefined,\n }),\n e2eRoutes: parts.flatMap((part) => part.e2eRoutes ?? []),\n publishers: [\n {name: 'integrations', table: integrationsOutbox, db, eventSchemas: integrationsEventSchemas},\n ],\n workers: [\n {\n taskQueue: INTEGRATIONS_MAINTENANCE_TASK_QUEUE,\n workflowsPath: maintenanceWorkflowsPath,\n activities: () => createIntegrationsMaintenanceActivities({registry}),\n workflows: [\n {\n name: 'pruneWebhookDeliveriesCron',\n id: 'integrations-prune-webhook-deliveries',\n cronSchedule: '0 3 * * *',\n },\n {\n name: 'cleanupIntegrationSecretsCron',\n id: 'integrations-cleanup-secret-namespaces',\n cronSchedule: '*/5 * * * *',\n },\n ],\n },\n ...parts.flatMap((part) => part.workers ?? []),\n ],\n ...(options.webhookDeliverySource\n ? {services: [options.webhookDeliverySource.createService(webhookProcessor)]}\n : {}),\n };\n\n return {\n module,\n registry,\n capabilities: {sourceControl},\n sourceControl,\n webhookProcessor,\n runStartupTasks,\n };\n}\n\nfunction createComposedWebhookProcessor(\n registrations: WebhookProcessorRegistration[],\n): WebhookRequestProcessor {\n const processors = new Map<WebhookRouteId, WebhookRequestProcessor>();\n for (const registration of registrations) {\n for (const routeId of registration.routeIds) {\n if (processors.has(routeId)) {\n throw new Error(`Webhook processor is registered more than once for ${routeId}`);\n }\n processors.set(routeId, registration.processor);\n }\n }\n\n return {\n async process(request: StoredWebhookRequest): Promise<WebhookProcessingResult> {\n const processor = processors.get(request.route_id);\n if (!processor) {\n throw new WebhookProcessorNotConfiguredError(request.route_id);\n }\n return await processor.process(request);\n },\n };\n}\n"],"names":["dirname","resolve","fileURLToPath","integrationsEventSchemas","reportError","logger","WebhookProcessorNotConfiguredError","createIntegrationProviderRegistry","createSourceControlIntegrationService","getIntegrationConnectionById","db","migrationsPath","integrationsOutbox","createIntegrationsInterModulePresentation","createIntegrationRoutes","loadEnabledProviderModules","createIntegrationsMaintenanceActivities","INTEGRATIONS_MAINTENANCE_TASK_QUEUE","packageRoot","url","maintenanceWorkflowsPath","buildProviderRepositoryId","MAX_REPOSITORY_FILE_BYTES","parseProviderRepositoryId","buildAgentToolCatalogs","buildAgentToolSelectionCatalogs","createWorkspaceConnectionSnapshotLoader","ConnectionSlugConflictError","IntegrationCapabilityUnavailableError","IntegrationCheckoutUnsupportedError","IntegrationConnectionInactiveError","IntegrationConnectionNotFoundError","IntegrationConnectionWorkspaceMismatchError","IntegrationProviderError","IntegrationProviderUnavailableError","redactCheckoutSpec","getIntegrationConnectionBySlug","claimWebhookDelivery","pruneWebhookDeliveries","publishSourceRepositoryUpdated","integrationRouteErrorHandler","createIntegrationsModule","options","createIntegrationsContext","module","workspaces","parts","providers","map","provider","webhookProcessors","secrets","requireActiveWorkspaceMembership","input","requireActiveMembership","memberships","registry","part","sourceControl","webhookProcessor","createComposedWebhookProcessor","flatMap","runStartupTasks","task","startupTasks","error","err","boundary","name","interModulePresentations","database","databaseNamespace","routes","agentTools","workflows","undefined","e2eRoutes","publishers","table","eventSchemas","workers","taskQueue","workflowsPath","activities","id","cronSchedule","webhookDeliverySource","services","createService","capabilities","registrations","processors","Map","registration","routeId","routeIds","has","Error","set","processor","process","request","get","route_id"],"mappings":"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"}
1
+ {"version":3,"sources":["../src/index.ts"],"sourcesContent":["import {dirname, resolve} from 'node:path';\nimport {fileURLToPath} from 'node:url';\nimport {\n integrationsEventSchemas,\n type StoredWebhookRequest,\n type WebhookProcessingResult,\n type WebhookRequestProcessor,\n type WebhookRouteId,\n} from '@shipfox/api-integration-spi';\nimport type {WorkflowsModuleClient} from '@shipfox/api-workflows-dto/inter-module';\nimport type {WorkspacesInterModuleClient} from '@shipfox/api-workspaces-dto/inter-module';\nimport {reportError} from '@shipfox/node-error-monitoring';\nimport type {ModuleService, ShipfoxModule} from '@shipfox/node-module';\nimport {logger} from '@shipfox/node-opentelemetry';\nimport type {IntegrationProvider} from '#core/entities/provider.js';\nimport {WebhookProcessorNotConfiguredError} from '#core/errors.js';\nimport {\n createIntegrationProviderRegistry,\n type IntegrationProviderRegistry,\n} from '#core/providers/registry.js';\nimport {\n createSourceControlIntegrationService,\n type IntegrationSourceControlService,\n} from '#core/source-control-service.js';\nimport {getIntegrationConnectionById} from '#db/connections.js';\nimport {db} from '#db/db.js';\nimport {migrationsPath} from '#db/migrations.js';\nimport {integrationsOutbox} from '#db/schema/outbox.js';\nimport {createIntegrationsInterModulePresentation} from '#presentation/inter-module.js';\nimport {createIntegrationRoutes} from '#presentation/routes/index.js';\nimport {loadEnabledProviderModules} from '#providers/modules.js';\nimport type {\n IntegrationModuleParts,\n IntegrationProviderSecrets,\n WebhookProcessorRegistration,\n} from '#providers/types.js';\nimport {createIntegrationsMaintenanceActivities} from '#temporal/activities/index.js';\nimport {INTEGRATIONS_MAINTENANCE_TASK_QUEUE} from '#temporal/constants.js';\n\nconst packageRoot = resolve(dirname(fileURLToPath(import.meta.url)), '..');\nconst maintenanceWorkflowsPath = resolve(packageRoot, 'dist/temporal/workflows/index.js');\n\nexport type {\n StoredWebhookRequest,\n WebhookProcessingResult,\n WebhookRequestProcessor,\n WebhookRouteId,\n} from '@shipfox/api-integration-spi';\nexport {\n buildProviderRepositoryId,\n MAX_REPOSITORY_FILE_BYTES,\n parseProviderRepositoryId,\n} from '@shipfox/api-integration-spi';\nexport type {\n AgentToolCatalogs,\n AgentToolSelectionCatalogs,\n LoadWorkspaceConnectionSnapshot,\n WorkspaceConnectionSnapshot,\n WorkspaceConnectionSnapshotEntry,\n} from '#core/agent-tool-selection.js';\nexport {\n buildAgentToolCatalogs,\n buildAgentToolSelectionCatalogs,\n createWorkspaceConnectionSnapshotLoader,\n} from '#core/agent-tool-selection.js';\nexport type {\n IntegrationConnection,\n IntegrationConnectionLifecycleStatus,\n} from '#core/entities/connection.js';\nexport type {\n IntegrationCapability,\n IntegrationProvider,\n IntegrationProviderAdapters,\n IntegrationProviderKind,\n RegisteredIntegrationProvider,\n} from '#core/entities/provider.js';\nexport type {IntegrationProviderErrorReason} from '#core/errors.js';\nexport {\n ConnectionSlugConflictError,\n IntegrationCapabilityUnavailableError,\n IntegrationCheckoutUnsupportedError,\n IntegrationConnectionInactiveError,\n IntegrationConnectionNotFoundError,\n IntegrationConnectionWorkspaceMismatchError,\n IntegrationProviderError,\n IntegrationProviderUnavailableError,\n WebhookProcessorNotConfiguredError,\n} from '#core/errors.js';\nexport type {\n AgentToolCallInput,\n AgentToolCatalogEntry,\n AgentToolCatalogMethod,\n AgentToolJsonSchema,\n AgentToolSensitivity,\n AgentToolSession,\n AgentToolsProvider,\n OpenAgentToolsSessionInput,\n} from '#core/providers/agent-tools.js';\nexport {redactCheckoutSpec} from '#core/providers/redact-checkout-spec.js';\nexport type {IntegrationProviderRegistry} from '#core/providers/registry.js';\nexport type {\n CheckoutCredentials,\n CheckoutPermissions,\n CheckoutSpec,\n CreateCheckoutSpecInput,\n FetchFileInput,\n FileEntry,\n FilePage,\n FileSnapshot,\n ListFilesInput,\n ListRepositoriesInput,\n RepositoryPage,\n RepositorySnapshot,\n RepositoryVisibility,\n ResolvedRef,\n ResolveRefInput,\n ResolveRepositoryInput,\n SourceControlProvider,\n TriggerReference,\n} from '#core/providers/source-control.js';\nexport type {IntegrationSourceControlService} from '#core/source-control-service.js';\nexport {createSourceControlIntegrationService} from '#core/source-control-service.js';\nexport type {\n GetIntegrationConnectionByIdFn,\n GetIntegrationConnectionBySlugFn,\n} from '#db/connections.js';\nexport {getIntegrationConnectionById, getIntegrationConnectionBySlug} from '#db/connections.js';\nexport type {\n ClaimWebhookDeliveryFn,\n PublishIntegrationEventReceivedFn,\n PublishIntegrationEventReceivedParams,\n PublishIntegrationEventReceivedResult,\n PublishSourcePushFn,\n PublishSourcePushParams,\n PublishSourceRepositoryUpdatedFn,\n PublishSourceRepositoryUpdatedParams,\n RecordDeliveryOnlyFn,\n RecordDeliveryOnlyParams,\n} from '#db/webhook-deliveries.js';\nexport {\n claimWebhookDelivery,\n pruneWebhookDeliveries,\n publishSourceRepositoryUpdated,\n} from '#db/webhook-deliveries.js';\nexport {integrationRouteErrorHandler} from '#presentation/routes/errors.js';\n\nexport interface CreateIntegrationsModuleOptions {\n providers?: IntegrationProvider[] | undefined;\n /**\n * Pre-built module parts, bypassing config-gated provider loading. Test-only seam\n * for exercising a provider's database, workers, or startup tasks directly. Takes\n * precedence over `providers`.\n */\n parts?: IntegrationModuleParts[] | undefined;\n secrets?: IntegrationProviderSecrets | undefined;\n workspaces?: WorkspacesInterModuleClient | undefined;\n agentTools?:\n | {\n workflows: WorkflowsModuleClient;\n }\n | undefined;\n webhookDeliverySource?: WebhookDeliverySource | undefined;\n}\n\n/**\n * Hosted runtimes implement this port to receive stored webhook requests. The\n * integration module starts its returned service after migrations complete.\n */\nexport interface WebhookDeliverySource {\n createService(processor: WebhookRequestProcessor): ModuleService;\n}\n\nexport interface IntegrationsContext {\n module: ShipfoxModule;\n registry: IntegrationProviderRegistry;\n capabilities: {\n sourceControl: IntegrationSourceControlService;\n };\n sourceControl: IntegrationSourceControlService;\n webhookProcessor: WebhookRequestProcessor;\n /**\n * Runs every enabled provider's one-shot boot-time tasks, after modules are initialized\n * (migrations done). Failures are isolated and logged, never rethrown, so a provider task\n * can never gate API boot. No-op when no enabled provider contributes a task.\n */\n runStartupTasks: () => Promise<void>;\n}\n\nexport async function createIntegrationsModule(\n options: CreateIntegrationsModuleOptions = {},\n): Promise<ShipfoxModule> {\n return (await createIntegrationsContext(options)).module;\n}\n\nexport async function createIntegrationsContext(\n options: CreateIntegrationsModuleOptions = {},\n): Promise<IntegrationsContext> {\n const workspaces = options.workspaces;\n const parts: IntegrationModuleParts[] =\n options.parts ??\n (options.providers\n ? options.providers.map((provider) => ({\n provider,\n webhookProcessors: provider.webhookProcessors,\n }))\n : await loadEnabledProviderModules({\n secrets: options.secrets,\n ...(workspaces\n ? {\n requireActiveWorkspaceMembership: (input: {\n workspaceId: string;\n userId: string;\n memberships: ReadonlyArray<\n import('@shipfox/api-auth-context').UserContextMembership\n >;\n }) =>\n workspaces.requireActiveMembership({\n ...input,\n memberships: [...input.memberships],\n }),\n }\n : {}),\n }));\n\n const registry = createIntegrationProviderRegistry(parts.map((part) => part.provider));\n const sourceControl = createSourceControlIntegrationService({\n registry,\n getIntegrationConnectionById,\n });\n const webhookProcessor = createComposedWebhookProcessor(\n parts.flatMap((part) => part.webhookProcessors ?? []),\n );\n\n async function runStartupTasks(): Promise<void> {\n for (const task of parts.flatMap((part) => part.startupTasks ?? [])) {\n // A provider convenience must never gate API boot.\n try {\n await task();\n } catch (error) {\n logger().error({err: error}, 'Integration startup task failed, continuing boot');\n reportError(error, {boundary: 'integration.startup'});\n }\n }\n }\n\n const module: ShipfoxModule = {\n name: 'integrations',\n interModulePresentations: [\n createIntegrationsInterModulePresentation({registry, sourceControl}),\n ],\n startupTasks: runStartupTasks,\n database: [\n {db, migrationsPath, databaseNamespace: 'integrations'},\n ...parts.flatMap((part) => (part.database ? [part.database] : [])),\n ],\n routes: createIntegrationRoutes(registry, sourceControl, {\n agentTools: options.agentTools\n ? {\n workflows: options.agentTools.workflows,\n getIntegrationConnectionById,\n }\n : undefined,\n }),\n e2eRoutes: parts.flatMap((part) => part.e2eRoutes ?? []),\n publishers: [\n {name: 'integrations', table: integrationsOutbox, db, eventSchemas: integrationsEventSchemas},\n ],\n workers: [\n {\n taskQueue: INTEGRATIONS_MAINTENANCE_TASK_QUEUE,\n workflowsPath: maintenanceWorkflowsPath,\n activities: () => createIntegrationsMaintenanceActivities({registry}),\n workflows: [\n {\n name: 'pruneWebhookDeliveriesCron',\n id: 'integrations-prune-webhook-deliveries',\n cronSchedule: '0 3 * * *',\n },\n {\n name: 'cleanupIntegrationSecretsCron',\n id: 'integrations-cleanup-secret-namespaces',\n cronSchedule: '*/5 * * * *',\n },\n ],\n },\n ...parts.flatMap((part) => part.workers ?? []),\n ],\n ...(options.webhookDeliverySource\n ? {services: [options.webhookDeliverySource.createService(webhookProcessor)]}\n : {}),\n };\n\n return {\n module,\n registry,\n capabilities: {sourceControl},\n sourceControl,\n webhookProcessor,\n runStartupTasks,\n };\n}\n\nfunction createComposedWebhookProcessor(\n registrations: WebhookProcessorRegistration[],\n): WebhookRequestProcessor {\n const processors = new Map<WebhookRouteId, WebhookRequestProcessor>();\n for (const registration of registrations) {\n for (const routeId of registration.routeIds) {\n if (processors.has(routeId)) {\n throw new Error(`Webhook processor is registered more than once for ${routeId}`);\n }\n processors.set(routeId, registration.processor);\n }\n }\n\n return {\n async process(request: StoredWebhookRequest): Promise<WebhookProcessingResult> {\n const processor = processors.get(request.route_id);\n if (!processor) {\n throw new WebhookProcessorNotConfiguredError(request.route_id);\n }\n return await processor.process(request);\n },\n };\n}\n"],"names":["dirname","resolve","fileURLToPath","integrationsEventSchemas","reportError","logger","WebhookProcessorNotConfiguredError","createIntegrationProviderRegistry","createSourceControlIntegrationService","getIntegrationConnectionById","db","migrationsPath","integrationsOutbox","createIntegrationsInterModulePresentation","createIntegrationRoutes","loadEnabledProviderModules","createIntegrationsMaintenanceActivities","INTEGRATIONS_MAINTENANCE_TASK_QUEUE","packageRoot","url","maintenanceWorkflowsPath","buildProviderRepositoryId","MAX_REPOSITORY_FILE_BYTES","parseProviderRepositoryId","buildAgentToolCatalogs","buildAgentToolSelectionCatalogs","createWorkspaceConnectionSnapshotLoader","ConnectionSlugConflictError","IntegrationCapabilityUnavailableError","IntegrationCheckoutUnsupportedError","IntegrationConnectionInactiveError","IntegrationConnectionNotFoundError","IntegrationConnectionWorkspaceMismatchError","IntegrationProviderError","IntegrationProviderUnavailableError","redactCheckoutSpec","getIntegrationConnectionBySlug","claimWebhookDelivery","pruneWebhookDeliveries","publishSourceRepositoryUpdated","integrationRouteErrorHandler","createIntegrationsModule","options","createIntegrationsContext","module","workspaces","parts","providers","map","provider","webhookProcessors","secrets","requireActiveWorkspaceMembership","input","requireActiveMembership","memberships","registry","part","sourceControl","webhookProcessor","createComposedWebhookProcessor","flatMap","runStartupTasks","task","startupTasks","error","err","boundary","name","interModulePresentations","database","databaseNamespace","routes","agentTools","workflows","undefined","e2eRoutes","publishers","table","eventSchemas","workers","taskQueue","workflowsPath","activities","id","cronSchedule","webhookDeliverySource","services","createService","capabilities","registrations","processors","Map","registration","routeId","routeIds","has","Error","set","processor","process","request","get","route_id"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"instance.d.ts","sourceRoot":"","sources":["../../src/metrics/instance.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,8BAA8B,EAAC,MAAM,8BAA8B,CAAC;AAKjF,MAAM,MAAM,+BAA+B,GACvC,SAAS,GACT,YAAY,GACZ,iBAAiB,GACjB,WAAW,CAAC;AAEhB,MAAM,MAAM,iCAAiC,GACzC,iBAAiB,GACjB,SAAS,GACT,kBAAkB,GAClB,yBAAyB,GACzB,8BAA8B,CAAC;AAEnC,MAAM,MAAM,kCAAkC,GAAG,iCAAiC,GAAG,MAAM,CAAC;AAuC5F,wBAAgB,8BAA8B,CAAC,MAAM,EAAE;IACrD,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,+BAA+B,CAAC;IACzC,UAAU,EAAE,kCAAkC,CAAC;CAChD,GAAG,IAAI,CAEP;AAED,wBAAgB,0CAA0C,CACxD,KAAK,EAAE,OAAO,GACb,iCAAiC,CAInC"}
1
+ {"version":3,"file":"instance.d.ts","sourceRoot":"","sources":["../../src/metrics/instance.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,8BAA8B,EAAC,MAAM,8BAA8B,CAAC;AAKjF,MAAM,MAAM,+BAA+B,GACvC,SAAS,GACT,YAAY,GACZ,iBAAiB,GACjB,WAAW,CAAC;AAEhB,MAAM,MAAM,iCAAiC,GACzC,iBAAiB,GACjB,SAAS,GACT,kBAAkB,GAClB,yBAAyB,GACzB,8BAA8B,CAAC;AAEnC,MAAM,MAAM,kCAAkC,GAAG,iCAAiC,GAAG,MAAM,CAAC;AAyC5F,wBAAgB,8BAA8B,CAAC,MAAM,EAAE;IACrD,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,+BAA+B,CAAC;IACzC,UAAU,EAAE,kCAAkC,CAAC;CAChD,GAAG,IAAI,CAEP;AAED,wBAAgB,0CAA0C,CACxD,KAAK,EAAE,OAAO,GACb,iCAAiC,CAInC"}
@@ -8,6 +8,8 @@ const integrationAgentToolCallErrorCodes = new Set([
8
8
  'repository-not-found',
9
9
  'installation-not-found',
10
10
  'file-not-found',
11
+ 'ref-not-found',
12
+ 'ref-invalid',
11
13
  'access-denied',
12
14
  'rate-limited',
13
15
  'timeout',
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/metrics/instance.ts"],"sourcesContent":["import type {IntegrationProviderErrorReason} from '@shipfox/api-integration-spi';\nimport {instanceMetrics} from '@shipfox/node-opentelemetry';\n\nconst meter = instanceMetrics.getMeter('integrations');\n\nexport type IntegrationAgentToolCallOutcome =\n | 'success'\n | 'tool-error'\n | 'invalid-request'\n | 'exception';\n\nexport type IntegrationAgentToolCallErrorCode =\n | 'invalid-request'\n | 'unknown'\n | 'provider-timeout'\n | 'credentials-unavailable'\n | IntegrationProviderErrorReason;\n\nexport type IntegrationAgentToolCallErrorLabel = IntegrationAgentToolCallErrorCode | 'none';\n\nconst integrationAgentToolCallErrorCodes = new Set<string>([\n 'invalid-request',\n 'unknown',\n 'provider-timeout',\n 'credentials-unavailable',\n 'repository-not-found',\n 'installation-not-found',\n 'file-not-found',\n 'access-denied',\n 'rate-limited',\n 'timeout',\n 'provider-unavailable',\n 'provider-rejected',\n 'malformed-provider-response',\n 'content-too-large',\n 'too-many-files',\n]);\n\nconst agentToolCallCount = meter.createCounter<{\n provider: string;\n tool: string;\n method: string;\n outcome: IntegrationAgentToolCallOutcome;\n error_code: IntegrationAgentToolCallErrorLabel;\n}>('integrations_agent_tool_call', {\n description:\n 'Integration agent tool calls by provider, tool, method, outcome, and bounded error code',\n});\n\nfunction recordMetric(record: () => void): void {\n try {\n record();\n } catch {\n // Metrics must not affect integration tool call outcomes.\n }\n}\n\nexport function recordIntegrationAgentToolCall(params: {\n provider: string;\n tool: string;\n method: string;\n outcome: IntegrationAgentToolCallOutcome;\n error_code: IntegrationAgentToolCallErrorLabel;\n}): void {\n recordMetric(() => agentToolCallCount.add(1, params));\n}\n\nexport function normalizeIntegrationAgentToolCallErrorCode(\n value: unknown,\n): IntegrationAgentToolCallErrorCode {\n return typeof value === 'string' && integrationAgentToolCallErrorCodes.has(value)\n ? (value as IntegrationAgentToolCallErrorCode)\n : 'unknown';\n}\n"],"names":["instanceMetrics","meter","getMeter","integrationAgentToolCallErrorCodes","Set","agentToolCallCount","createCounter","description","recordMetric","record","recordIntegrationAgentToolCall","params","add","normalizeIntegrationAgentToolCallErrorCode","value","has"],"mappings":"AACA,SAAQA,eAAe,QAAO,8BAA8B;AAE5D,MAAMC,QAAQD,gBAAgBE,QAAQ,CAAC;AAiBvC,MAAMC,qCAAqC,IAAIC,IAAY;IACzD;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;CACD;AAED,MAAMC,qBAAqBJ,MAAMK,aAAa,CAM3C,gCAAgC;IACjCC,aACE;AACJ;AAEA,SAASC,aAAaC,MAAkB;IACtC,IAAI;QACFA;IACF,EAAE,OAAM;IACN,0DAA0D;IAC5D;AACF;AAEA,OAAO,SAASC,+BAA+BC,MAM9C;IACCH,aAAa,IAAMH,mBAAmBO,GAAG,CAAC,GAAGD;AAC/C;AAEA,OAAO,SAASE,2CACdC,KAAc;IAEd,OAAO,OAAOA,UAAU,YAAYX,mCAAmCY,GAAG,CAACD,SACtEA,QACD;AACN"}
1
+ {"version":3,"sources":["../../src/metrics/instance.ts"],"sourcesContent":["import type {IntegrationProviderErrorReason} from '@shipfox/api-integration-spi';\nimport {instanceMetrics} from '@shipfox/node-opentelemetry';\n\nconst meter = instanceMetrics.getMeter('integrations');\n\nexport type IntegrationAgentToolCallOutcome =\n | 'success'\n | 'tool-error'\n | 'invalid-request'\n | 'exception';\n\nexport type IntegrationAgentToolCallErrorCode =\n | 'invalid-request'\n | 'unknown'\n | 'provider-timeout'\n | 'credentials-unavailable'\n | IntegrationProviderErrorReason;\n\nexport type IntegrationAgentToolCallErrorLabel = IntegrationAgentToolCallErrorCode | 'none';\n\nconst integrationAgentToolCallErrorCodes = new Set<string>([\n 'invalid-request',\n 'unknown',\n 'provider-timeout',\n 'credentials-unavailable',\n 'repository-not-found',\n 'installation-not-found',\n 'file-not-found',\n 'ref-not-found',\n 'ref-invalid',\n 'access-denied',\n 'rate-limited',\n 'timeout',\n 'provider-unavailable',\n 'provider-rejected',\n 'malformed-provider-response',\n 'content-too-large',\n 'too-many-files',\n]);\n\nconst agentToolCallCount = meter.createCounter<{\n provider: string;\n tool: string;\n method: string;\n outcome: IntegrationAgentToolCallOutcome;\n error_code: IntegrationAgentToolCallErrorLabel;\n}>('integrations_agent_tool_call', {\n description:\n 'Integration agent tool calls by provider, tool, method, outcome, and bounded error code',\n});\n\nfunction recordMetric(record: () => void): void {\n try {\n record();\n } catch {\n // Metrics must not affect integration tool call outcomes.\n }\n}\n\nexport function recordIntegrationAgentToolCall(params: {\n provider: string;\n tool: string;\n method: string;\n outcome: IntegrationAgentToolCallOutcome;\n error_code: IntegrationAgentToolCallErrorLabel;\n}): void {\n recordMetric(() => agentToolCallCount.add(1, params));\n}\n\nexport function normalizeIntegrationAgentToolCallErrorCode(\n value: unknown,\n): IntegrationAgentToolCallErrorCode {\n return typeof value === 'string' && integrationAgentToolCallErrorCodes.has(value)\n ? (value as IntegrationAgentToolCallErrorCode)\n : 'unknown';\n}\n"],"names":["instanceMetrics","meter","getMeter","integrationAgentToolCallErrorCodes","Set","agentToolCallCount","createCounter","description","recordMetric","record","recordIntegrationAgentToolCall","params","add","normalizeIntegrationAgentToolCallErrorCode","value","has"],"mappings":"AACA,SAAQA,eAAe,QAAO,8BAA8B;AAE5D,MAAMC,QAAQD,gBAAgBE,QAAQ,CAAC;AAiBvC,MAAMC,qCAAqC,IAAIC,IAAY;IACzD;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;CACD;AAED,MAAMC,qBAAqBJ,MAAMK,aAAa,CAM3C,gCAAgC;IACjCC,aACE;AACJ;AAEA,SAASC,aAAaC,MAAkB;IACtC,IAAI;QACFA;IACF,EAAE,OAAM;IACN,0DAA0D;IAC5D;AACF;AAEA,OAAO,SAASC,+BAA+BC,MAM9C;IACCH,aAAa,IAAMH,mBAAmBO,GAAG,CAAC,GAAGD;AAC/C;AAEA,OAAO,SAASE,2CACdC,KAAc;IAEd,OAAO,OAAOA,UAAU,YAAYX,mCAAmCY,GAAG,CAACD,SACtEA,QACD;AACN"}
@@ -1 +1 @@
1
- {"version":3,"file":"inter-module.d.ts","sourceRoot":"","sources":["../../src/presentation/inter-module.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,+BAA+B,EAAC,MAAM,gDAAgD,CAAC;AAC/F,OAAO,EAIL,KAAK,uBAAuB,EAC7B,MAAM,uBAAuB,CAAC;AAe/B,OAAO,KAAK,EAAC,2BAA2B,EAAC,MAAM,6BAA6B,CAAC;AAC7E,OAAO,KAAK,EAAC,+BAA+B,EAAC,MAAM,iCAAiC,CAAC;AAGrF,wBAAgB,yCAAyC,CAAC,MAAM,EAAE;IAChE,QAAQ,EAAE,2BAA2B,CAAC;IACtC,aAAa,EAAE,+BAA+B,CAAC;CAChD,GAAG,uBAAuB,CAAC,OAAO,+BAA+B,CAAC,CAyFlE"}
1
+ {"version":3,"file":"inter-module.d.ts","sourceRoot":"","sources":["../../src/presentation/inter-module.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,+BAA+B,EAAC,MAAM,gDAAgD,CAAC;AAC/F,OAAO,EAIL,KAAK,uBAAuB,EAC7B,MAAM,uBAAuB,CAAC;AAgB/B,OAAO,KAAK,EAAC,2BAA2B,EAAC,MAAM,6BAA6B,CAAC;AAC7E,OAAO,KAAK,EAAC,+BAA+B,EAAC,MAAM,iCAAiC,CAAC;AAGrF,wBAAgB,yCAAyC,CAAC,MAAM,EAAE;IAChE,QAAQ,EAAE,2BAA2B,CAAC;IACtC,aAAa,EAAE,+BAA+B,CAAC;CAChD,GAAG,uBAAuB,CAAC,OAAO,+BAA+B,CAAC,CAiGlE"}
@@ -2,6 +2,7 @@ import { integrationsInterModuleContract } from '@shipfox/api-integration-core-d
2
2
  import { createInterModuleKnownError, defineInterModulePresentation } from '@shipfox/inter-module';
3
3
  import { buildAgentToolCatalogs, buildAgentToolSelectionCatalogs, createWorkspaceConnectionSnapshotLoader } from '#core/agent-tool-selection.js';
4
4
  import { IntegrationCapabilityUnavailableError, IntegrationCheckoutUnsupportedError, IntegrationConnectionInactiveError, IntegrationConnectionNotFoundError, IntegrationConnectionWorkspaceMismatchError, IntegrationProviderError, IntegrationProviderUnavailableError } from '#core/errors.js';
5
+ import { buildFixedEventProviders, buildProviderEventCatalogs } from '#core/event-catalogs.js';
5
6
  import { getIntegrationConnectionById, getIntegrationConnectionBySlug } from '#db/connections.js';
6
7
  export function createIntegrationsInterModulePresentation(params) {
7
8
  const contract = integrationsInterModuleContract;
@@ -26,6 +27,7 @@ export function createIntegrationsInterModulePresentation(params) {
26
27
  } : null;
27
28
  },
28
29
  resolveTriggerReference: async (input)=>await known(contract.methods.resolveTriggerReference, input, async ()=>await params.sourceControl.resolveTriggerReference(input)),
30
+ resolveSourceRef: async (input)=>await known(contract.methods.resolveSourceRef, input, async ()=>await params.sourceControl.resolveSourceRef(input)),
29
31
  listSourceFiles: async (input)=>await known(contract.methods.listSourceFiles, input, async ()=>await params.sourceControl.listFiles(input)),
30
32
  fetchSourceFile: async (input)=>await known(contract.methods.fetchSourceFile, input, async ()=>await params.sourceControl.fetchFile(input)),
31
33
  createCheckoutSpec: async (input)=>await known(contract.methods.createCheckoutSpec, input, async ()=>{
@@ -82,6 +84,8 @@ export function createIntegrationsInterModulePresentation(params) {
82
84
  ...value.capabilities
83
85
  ]
84
86
  })),
87
+ eventCatalogs: buildProviderEventCatalogs(params.registry),
88
+ fixedEventProviders: buildFixedEventProviders(params.registry),
85
89
  defaultConnection: defaultConnection ? {
86
90
  id: defaultConnection.id,
87
91
  slug: defaultConnection.slug,
@@ -118,13 +122,31 @@ function mapError(method, input, error) {
118
122
  if (error instanceof IntegrationCheckoutUnsupportedError) return createInterModuleKnownError(method, 'checkout-unsupported', {
119
123
  provider: error.provider
120
124
  });
121
- if (error instanceof IntegrationProviderError) return createInterModuleKnownError(method, 'provider-failure', {
122
- reason: error.reason,
123
- ...error.retryAfterSeconds === undefined ? {} : {
124
- retryAfterSeconds: error.retryAfterSeconds
125
+ if (error instanceof IntegrationProviderError) {
126
+ // Only methods that resolve refs declare these codes; other methods keep
127
+ // seeing the failure as a generic provider failure.
128
+ if (error.reason === 'ref-not-found' && 'ref-not-found' in method.errors) {
129
+ return createInterModuleKnownError(method, 'ref-not-found', refDetails(input));
125
130
  }
126
- });
131
+ if (error.reason === 'ref-invalid' && 'ref-invalid' in method.errors) {
132
+ return createInterModuleKnownError(method, 'ref-invalid', refDetails(input));
133
+ }
134
+ return createInterModuleKnownError(method, 'provider-failure', {
135
+ reason: error.reason,
136
+ ...error.retryAfterSeconds === undefined ? {} : {
137
+ retryAfterSeconds: error.retryAfterSeconds
138
+ }
139
+ });
140
+ }
127
141
  return error;
128
142
  }
143
+ function refDetails(input) {
144
+ if (input.ref === undefined) {
145
+ throw new Error('Ref error mapping requires a ref input');
146
+ }
147
+ return {
148
+ ref: input.ref
149
+ };
150
+ }
129
151
 
130
152
  //# sourceMappingURL=inter-module.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/presentation/inter-module.ts"],"sourcesContent":["import {integrationsInterModuleContract} from '@shipfox/api-integration-core-dto/inter-module';\nimport {\n createInterModuleKnownError,\n defineInterModulePresentation,\n type InterModuleMethodContract,\n type InterModulePresentation,\n} from '@shipfox/inter-module';\nimport {\n buildAgentToolCatalogs,\n buildAgentToolSelectionCatalogs,\n createWorkspaceConnectionSnapshotLoader,\n} from '#core/agent-tool-selection.js';\nimport {\n IntegrationCapabilityUnavailableError,\n IntegrationCheckoutUnsupportedError,\n IntegrationConnectionInactiveError,\n IntegrationConnectionNotFoundError,\n IntegrationConnectionWorkspaceMismatchError,\n IntegrationProviderError,\n IntegrationProviderUnavailableError,\n} from '#core/errors.js';\nimport type {IntegrationProviderRegistry} from '#core/providers/registry.js';\nimport type {IntegrationSourceControlService} from '#core/source-control-service.js';\nimport {getIntegrationConnectionById, getIntegrationConnectionBySlug} from '#db/connections.js';\n\nexport function createIntegrationsInterModulePresentation(params: {\n registry: IntegrationProviderRegistry;\n sourceControl: IntegrationSourceControlService;\n}): InterModulePresentation<typeof integrationsInterModuleContract> {\n const contract = integrationsInterModuleContract;\n return defineInterModulePresentation(contract, {\n resolveSourceRepository: async (input) =>\n await known(contract.methods.resolveSourceRepository, input, async () => {\n const resolved = await params.sourceControl.resolveRepository(input);\n return {\n connection: {\n id: resolved.connection.id,\n provider: resolved.connection.provider,\n slug: resolved.connection.slug,\n },\n repository: resolved.repository,\n };\n }),\n resolveConnection: async (input) => {\n const resolved = await getIntegrationConnectionBySlug(input);\n return resolved ? {id: resolved.id, provider: resolved.provider, slug: resolved.slug} : null;\n },\n resolveTriggerReference: async (input) =>\n await known(\n contract.methods.resolveTriggerReference,\n input,\n async () => await params.sourceControl.resolveTriggerReference(input),\n ),\n listSourceFiles: async (input) =>\n await known(\n contract.methods.listSourceFiles,\n input,\n async () => await params.sourceControl.listFiles(input),\n ),\n fetchSourceFile: async (input) =>\n await known(\n contract.methods.fetchSourceFile,\n input,\n async () => await params.sourceControl.fetchFile(input),\n ),\n createCheckoutSpec: async (input) =>\n await known(contract.methods.createCheckoutSpec, input, async () => {\n const spec = await params.sourceControl.createCheckoutSpec(input);\n return {\n repositoryUrl: spec.repositoryUrl,\n ref: spec.ref,\n ...(spec.credentials\n ? {\n credentials: {\n ...spec.credentials,\n expiresAt: spec.credentials.expiresAt.toISOString(),\n },\n }\n : {}),\n ...(spec.gitAuthor === undefined ? {} : {gitAuthor: spec.gitAuthor}),\n };\n }),\n getAgentToolsContext: async (input) =>\n await known(contract.methods.getAgentToolsContext, input, async () => {\n const [selectionCatalogs, catalogs, snapshot, defaultConnection] = await Promise.all([\n buildAgentToolSelectionCatalogs(params.registry),\n buildAgentToolCatalogs(params.registry),\n createWorkspaceConnectionSnapshotLoader(params.registry)(input.workspaceId),\n getIntegrationConnectionById(input.defaultConnectionId),\n ]);\n return {\n selectionCatalogs: [...selectionCatalogs].map(([provider, value]) => ({\n provider,\n selectors: value.selectors.map((selector) => ({...selector})),\n })),\n catalogs: [...catalogs].map(([provider, tools]) => ({\n provider,\n tools: tools.map(({methods, ...tool}) => ({\n ...tool,\n ...(methods === undefined ? {} : {methods: methods.map((method) => ({...method}))}),\n })),\n })),\n workspaceConnections: [...snapshot].map(([slug, value]) => ({\n slug,\n ...value,\n capabilities: [...value.capabilities],\n })),\n defaultConnection: defaultConnection\n ? {\n id: defaultConnection.id,\n slug: defaultConnection.slug,\n provider: defaultConnection.provider,\n }\n : null,\n };\n }),\n });\n}\n\nasync function known<Output>(\n method: InterModuleMethodContract,\n input: {connectionId?: string; defaultConnectionId?: string},\n operation: () => Promise<Output>,\n): Promise<Output> {\n try {\n return await operation();\n } catch (error) {\n throw mapError(method, input, error);\n }\n}\nfunction mapError(\n method: InterModuleMethodContract,\n input: {connectionId?: string; defaultConnectionId?: string},\n error: unknown,\n): unknown {\n if (error instanceof IntegrationConnectionNotFoundError)\n return createInterModuleKnownError(method, 'connection-not-found', {\n connectionId: input.connectionId ?? input.defaultConnectionId,\n });\n if (error instanceof IntegrationConnectionInactiveError)\n return createInterModuleKnownError(method, 'connection-inactive', {\n connectionId: input.connectionId,\n });\n if (error instanceof IntegrationConnectionWorkspaceMismatchError)\n return createInterModuleKnownError(method, 'connection-workspace-mismatch', {\n connectionId: input.connectionId,\n });\n if (error instanceof IntegrationProviderUnavailableError)\n return createInterModuleKnownError(method, 'provider-unavailable', {provider: error.provider});\n if (error instanceof IntegrationCapabilityUnavailableError)\n return createInterModuleKnownError(method, 'capability-unavailable', {\n provider: error.provider,\n capability: error.capability,\n });\n if (error instanceof IntegrationCheckoutUnsupportedError)\n return createInterModuleKnownError(method, 'checkout-unsupported', {provider: error.provider});\n if (error instanceof IntegrationProviderError)\n return createInterModuleKnownError(method, 'provider-failure', {\n reason: error.reason,\n ...(error.retryAfterSeconds === undefined\n ? {}\n : {retryAfterSeconds: error.retryAfterSeconds}),\n });\n return error;\n}\n"],"names":["integrationsInterModuleContract","createInterModuleKnownError","defineInterModulePresentation","buildAgentToolCatalogs","buildAgentToolSelectionCatalogs","createWorkspaceConnectionSnapshotLoader","IntegrationCapabilityUnavailableError","IntegrationCheckoutUnsupportedError","IntegrationConnectionInactiveError","IntegrationConnectionNotFoundError","IntegrationConnectionWorkspaceMismatchError","IntegrationProviderError","IntegrationProviderUnavailableError","getIntegrationConnectionById","getIntegrationConnectionBySlug","createIntegrationsInterModulePresentation","params","contract","resolveSourceRepository","input","known","methods","resolved","sourceControl","resolveRepository","connection","id","provider","slug","repository","resolveConnection","resolveTriggerReference","listSourceFiles","listFiles","fetchSourceFile","fetchFile","createCheckoutSpec","spec","repositoryUrl","ref","credentials","expiresAt","toISOString","gitAuthor","undefined","getAgentToolsContext","selectionCatalogs","catalogs","snapshot","defaultConnection","Promise","all","registry","workspaceId","defaultConnectionId","map","value","selectors","selector","tools","tool","method","workspaceConnections","capabilities","operation","error","mapError","connectionId","capability","reason","retryAfterSeconds"],"mappings":"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"}
1
+ {"version":3,"sources":["../../src/presentation/inter-module.ts"],"sourcesContent":["import {integrationsInterModuleContract} from '@shipfox/api-integration-core-dto/inter-module';\nimport {\n createInterModuleKnownError,\n defineInterModulePresentation,\n type InterModuleMethodContract,\n type InterModulePresentation,\n} from '@shipfox/inter-module';\nimport {\n buildAgentToolCatalogs,\n buildAgentToolSelectionCatalogs,\n createWorkspaceConnectionSnapshotLoader,\n} from '#core/agent-tool-selection.js';\nimport {\n IntegrationCapabilityUnavailableError,\n IntegrationCheckoutUnsupportedError,\n IntegrationConnectionInactiveError,\n IntegrationConnectionNotFoundError,\n IntegrationConnectionWorkspaceMismatchError,\n IntegrationProviderError,\n IntegrationProviderUnavailableError,\n} from '#core/errors.js';\nimport {buildFixedEventProviders, buildProviderEventCatalogs} from '#core/event-catalogs.js';\nimport type {IntegrationProviderRegistry} from '#core/providers/registry.js';\nimport type {IntegrationSourceControlService} from '#core/source-control-service.js';\nimport {getIntegrationConnectionById, getIntegrationConnectionBySlug} from '#db/connections.js';\n\nexport function createIntegrationsInterModulePresentation(params: {\n registry: IntegrationProviderRegistry;\n sourceControl: IntegrationSourceControlService;\n}): InterModulePresentation<typeof integrationsInterModuleContract> {\n const contract = integrationsInterModuleContract;\n return defineInterModulePresentation(contract, {\n resolveSourceRepository: async (input) =>\n await known(contract.methods.resolveSourceRepository, input, async () => {\n const resolved = await params.sourceControl.resolveRepository(input);\n return {\n connection: {\n id: resolved.connection.id,\n provider: resolved.connection.provider,\n slug: resolved.connection.slug,\n },\n repository: resolved.repository,\n };\n }),\n resolveConnection: async (input) => {\n const resolved = await getIntegrationConnectionBySlug(input);\n return resolved ? {id: resolved.id, provider: resolved.provider, slug: resolved.slug} : null;\n },\n resolveTriggerReference: async (input) =>\n await known(\n contract.methods.resolveTriggerReference,\n input,\n async () => await params.sourceControl.resolveTriggerReference(input),\n ),\n resolveSourceRef: async (input) =>\n await known(\n contract.methods.resolveSourceRef,\n input,\n async () => await params.sourceControl.resolveSourceRef(input),\n ),\n listSourceFiles: async (input) =>\n await known(\n contract.methods.listSourceFiles,\n input,\n async () => await params.sourceControl.listFiles(input),\n ),\n fetchSourceFile: async (input) =>\n await known(\n contract.methods.fetchSourceFile,\n input,\n async () => await params.sourceControl.fetchFile(input),\n ),\n createCheckoutSpec: async (input) =>\n await known(contract.methods.createCheckoutSpec, input, async () => {\n const spec = await params.sourceControl.createCheckoutSpec(input);\n return {\n repositoryUrl: spec.repositoryUrl,\n ref: spec.ref,\n ...(spec.credentials\n ? {\n credentials: {\n ...spec.credentials,\n expiresAt: spec.credentials.expiresAt.toISOString(),\n },\n }\n : {}),\n ...(spec.gitAuthor === undefined ? {} : {gitAuthor: spec.gitAuthor}),\n };\n }),\n getAgentToolsContext: async (input) =>\n await known(contract.methods.getAgentToolsContext, input, async () => {\n const [selectionCatalogs, catalogs, snapshot, defaultConnection] = await Promise.all([\n buildAgentToolSelectionCatalogs(params.registry),\n buildAgentToolCatalogs(params.registry),\n createWorkspaceConnectionSnapshotLoader(params.registry)(input.workspaceId),\n getIntegrationConnectionById(input.defaultConnectionId),\n ]);\n return {\n selectionCatalogs: [...selectionCatalogs].map(([provider, value]) => ({\n provider,\n selectors: value.selectors.map((selector) => ({...selector})),\n })),\n catalogs: [...catalogs].map(([provider, tools]) => ({\n provider,\n tools: tools.map(({methods, ...tool}) => ({\n ...tool,\n ...(methods === undefined ? {} : {methods: methods.map((method) => ({...method}))}),\n })),\n })),\n workspaceConnections: [...snapshot].map(([slug, value]) => ({\n slug,\n ...value,\n capabilities: [...value.capabilities],\n })),\n eventCatalogs: buildProviderEventCatalogs(params.registry),\n fixedEventProviders: buildFixedEventProviders(params.registry),\n defaultConnection: defaultConnection\n ? {\n id: defaultConnection.id,\n slug: defaultConnection.slug,\n provider: defaultConnection.provider,\n }\n : null,\n };\n }),\n });\n}\n\nasync function known<Output>(\n method: InterModuleMethodContract,\n input: {connectionId?: string; defaultConnectionId?: string; ref?: string | undefined},\n operation: () => Promise<Output>,\n): Promise<Output> {\n try {\n return await operation();\n } catch (error) {\n throw mapError(method, input, error);\n }\n}\nfunction mapError(\n method: InterModuleMethodContract,\n input: {connectionId?: string; defaultConnectionId?: string; ref?: string | undefined},\n error: unknown,\n): unknown {\n if (error instanceof IntegrationConnectionNotFoundError)\n return createInterModuleKnownError(method, 'connection-not-found', {\n connectionId: input.connectionId ?? input.defaultConnectionId,\n });\n if (error instanceof IntegrationConnectionInactiveError)\n return createInterModuleKnownError(method, 'connection-inactive', {\n connectionId: input.connectionId,\n });\n if (error instanceof IntegrationConnectionWorkspaceMismatchError)\n return createInterModuleKnownError(method, 'connection-workspace-mismatch', {\n connectionId: input.connectionId,\n });\n if (error instanceof IntegrationProviderUnavailableError)\n return createInterModuleKnownError(method, 'provider-unavailable', {provider: error.provider});\n if (error instanceof IntegrationCapabilityUnavailableError)\n return createInterModuleKnownError(method, 'capability-unavailable', {\n provider: error.provider,\n capability: error.capability,\n });\n if (error instanceof IntegrationCheckoutUnsupportedError)\n return createInterModuleKnownError(method, 'checkout-unsupported', {provider: error.provider});\n if (error instanceof IntegrationProviderError) {\n // Only methods that resolve refs declare these codes; other methods keep\n // seeing the failure as a generic provider failure.\n if (error.reason === 'ref-not-found' && 'ref-not-found' in method.errors) {\n return createInterModuleKnownError(method, 'ref-not-found', refDetails(input));\n }\n if (error.reason === 'ref-invalid' && 'ref-invalid' in method.errors) {\n return createInterModuleKnownError(method, 'ref-invalid', refDetails(input));\n }\n return createInterModuleKnownError(method, 'provider-failure', {\n reason: error.reason,\n ...(error.retryAfterSeconds === undefined\n ? {}\n : {retryAfterSeconds: error.retryAfterSeconds}),\n });\n }\n return error;\n}\n\nfunction refDetails(input: {ref?: string | undefined}): {ref: string} {\n if (input.ref === undefined) {\n throw new Error('Ref error mapping requires a ref input');\n }\n return {ref: input.ref};\n}\n"],"names":["integrationsInterModuleContract","createInterModuleKnownError","defineInterModulePresentation","buildAgentToolCatalogs","buildAgentToolSelectionCatalogs","createWorkspaceConnectionSnapshotLoader","IntegrationCapabilityUnavailableError","IntegrationCheckoutUnsupportedError","IntegrationConnectionInactiveError","IntegrationConnectionNotFoundError","IntegrationConnectionWorkspaceMismatchError","IntegrationProviderError","IntegrationProviderUnavailableError","buildFixedEventProviders","buildProviderEventCatalogs","getIntegrationConnectionById","getIntegrationConnectionBySlug","createIntegrationsInterModulePresentation","params","contract","resolveSourceRepository","input","known","methods","resolved","sourceControl","resolveRepository","connection","id","provider","slug","repository","resolveConnection","resolveTriggerReference","resolveSourceRef","listSourceFiles","listFiles","fetchSourceFile","fetchFile","createCheckoutSpec","spec","repositoryUrl","ref","credentials","expiresAt","toISOString","gitAuthor","undefined","getAgentToolsContext","selectionCatalogs","catalogs","snapshot","defaultConnection","Promise","all","registry","workspaceId","defaultConnectionId","map","value","selectors","selector","tools","tool","method","workspaceConnections","capabilities","eventCatalogs","fixedEventProviders","operation","error","mapError","connectionId","capability","reason","errors","refDetails","retryAfterSeconds","Error"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../../src/presentation/routes/errors.ts"],"names":[],"mappings":"AAqCA,wBAAgB,4BAA4B,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,CA0BlE"}
1
+ {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../../src/presentation/routes/errors.ts"],"names":[],"mappings":"AAwCA,wBAAgB,4BAA4B,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,CA0BlE"}
@@ -6,7 +6,7 @@ function providerStatus(reason) {
6
6
  return 422;
7
7
  }
8
8
  function isProviderError(error) {
9
- return error instanceof IntegrationProviderError || error instanceof Error && 'reason' in error && typeof error.reason === 'string' && (error.reason === 'repository-not-found' || error.reason === 'file-not-found' || error.reason === 'access-denied' || error.reason === 'rate-limited' || error.reason === 'timeout' || error.reason === 'provider-unavailable' || error.reason === 'provider-rejected' || error.reason === 'malformed-provider-response' || error.reason === 'content-too-large' || error.reason === 'too-many-files');
9
+ return error instanceof IntegrationProviderError || error instanceof Error && 'reason' in error && typeof error.reason === 'string' && (error.reason === 'repository-not-found' || error.reason === 'installation-not-found' || error.reason === 'file-not-found' || error.reason === 'ref-not-found' || error.reason === 'ref-invalid' || error.reason === 'access-denied' || error.reason === 'rate-limited' || error.reason === 'timeout' || error.reason === 'provider-unavailable' || error.reason === 'provider-rejected' || error.reason === 'malformed-provider-response' || error.reason === 'content-too-large' || error.reason === 'too-many-files');
10
10
  }
11
11
  export function integrationRouteErrorHandler(error) {
12
12
  if (error instanceof IntegrationConnectionNotFoundError) {
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/presentation/routes/errors.ts"],"sourcesContent":["import {ClientError} from '@shipfox/node-fastify';\nimport {\n IntegrationCapabilityUnavailableError,\n IntegrationCheckoutUnsupportedError,\n IntegrationConnectionInactiveError,\n IntegrationConnectionNotFoundError,\n IntegrationConnectionWorkspaceMismatchError,\n IntegrationProviderError,\n type IntegrationProviderErrorReason,\n IntegrationProviderUnavailableError,\n} from '#core/errors.js';\n\nfunction providerStatus(reason: IntegrationProviderErrorReason): number {\n if (reason === 'rate-limited') return 429;\n if (reason === 'timeout' || reason === 'provider-unavailable') return 503;\n return 422;\n}\n\nfunction isProviderError(error: unknown): error is IntegrationProviderError {\n return (\n error instanceof IntegrationProviderError ||\n (error instanceof Error &&\n 'reason' in error &&\n typeof error.reason === 'string' &&\n (error.reason === 'repository-not-found' ||\n error.reason === 'file-not-found' ||\n error.reason === 'access-denied' ||\n error.reason === 'rate-limited' ||\n error.reason === 'timeout' ||\n error.reason === 'provider-unavailable' ||\n error.reason === 'provider-rejected' ||\n error.reason === 'malformed-provider-response' ||\n error.reason === 'content-too-large' ||\n error.reason === 'too-many-files'))\n );\n}\n\nexport function integrationRouteErrorHandler(error: unknown): never {\n if (error instanceof IntegrationConnectionNotFoundError) {\n throw new ClientError(error.message, 'integration-connection-not-found', {status: 404});\n }\n if (error instanceof IntegrationConnectionInactiveError) {\n throw new ClientError(error.message, 'integration-connection-inactive', {status: 422});\n }\n if (error instanceof IntegrationConnectionWorkspaceMismatchError) {\n throw new ClientError(error.message, 'forbidden', {status: 403});\n }\n if (error instanceof IntegrationProviderUnavailableError) {\n throw new ClientError(error.message, 'integration-provider-unavailable', {status: 422});\n }\n if (error instanceof IntegrationCapabilityUnavailableError) {\n throw new ClientError(error.message, 'integration-capability-unavailable', {status: 422});\n }\n if (error instanceof IntegrationCheckoutUnsupportedError) {\n throw new ClientError(error.message, 'integration-checkout-unsupported', {status: 422});\n }\n if (isProviderError(error)) {\n throw new ClientError(error.message, error.reason, {\n details: {retry_after_seconds: error.retryAfterSeconds},\n status: providerStatus(error.reason),\n });\n }\n throw error;\n}\n"],"names":["ClientError","IntegrationCapabilityUnavailableError","IntegrationCheckoutUnsupportedError","IntegrationConnectionInactiveError","IntegrationConnectionNotFoundError","IntegrationConnectionWorkspaceMismatchError","IntegrationProviderError","IntegrationProviderUnavailableError","providerStatus","reason","isProviderError","error","Error","integrationRouteErrorHandler","message","status","details","retry_after_seconds","retryAfterSeconds"],"mappings":"AAAA,SAAQA,WAAW,QAAO,wBAAwB;AAClD,SACEC,qCAAqC,EACrCC,mCAAmC,EACnCC,kCAAkC,EAClCC,kCAAkC,EAClCC,2CAA2C,EAC3CC,wBAAwB,EAExBC,mCAAmC,QAC9B,kBAAkB;AAEzB,SAASC,eAAeC,MAAsC;IAC5D,IAAIA,WAAW,gBAAgB,OAAO;IACtC,IAAIA,WAAW,aAAaA,WAAW,wBAAwB,OAAO;IACtE,OAAO;AACT;AAEA,SAASC,gBAAgBC,KAAc;IACrC,OACEA,iBAAiBL,4BAChBK,iBAAiBC,SAChB,YAAYD,SACZ,OAAOA,MAAMF,MAAM,KAAK,YACvBE,CAAAA,MAAMF,MAAM,KAAK,0BAChBE,MAAMF,MAAM,KAAK,oBACjBE,MAAMF,MAAM,KAAK,mBACjBE,MAAMF,MAAM,KAAK,kBACjBE,MAAMF,MAAM,KAAK,aACjBE,MAAMF,MAAM,KAAK,0BACjBE,MAAMF,MAAM,KAAK,uBACjBE,MAAMF,MAAM,KAAK,iCACjBE,MAAMF,MAAM,KAAK,uBACjBE,MAAMF,MAAM,KAAK,gBAAe;AAExC;AAEA,OAAO,SAASI,6BAA6BF,KAAc;IACzD,IAAIA,iBAAiBP,oCAAoC;QACvD,MAAM,IAAIJ,YAAYW,MAAMG,OAAO,EAAE,oCAAoC;YAACC,QAAQ;QAAG;IACvF;IACA,IAAIJ,iBAAiBR,oCAAoC;QACvD,MAAM,IAAIH,YAAYW,MAAMG,OAAO,EAAE,mCAAmC;YAACC,QAAQ;QAAG;IACtF;IACA,IAAIJ,iBAAiBN,6CAA6C;QAChE,MAAM,IAAIL,YAAYW,MAAMG,OAAO,EAAE,aAAa;YAACC,QAAQ;QAAG;IAChE;IACA,IAAIJ,iBAAiBJ,qCAAqC;QACxD,MAAM,IAAIP,YAAYW,MAAMG,OAAO,EAAE,oCAAoC;YAACC,QAAQ;QAAG;IACvF;IACA,IAAIJ,iBAAiBV,uCAAuC;QAC1D,MAAM,IAAID,YAAYW,MAAMG,OAAO,EAAE,sCAAsC;YAACC,QAAQ;QAAG;IACzF;IACA,IAAIJ,iBAAiBT,qCAAqC;QACxD,MAAM,IAAIF,YAAYW,MAAMG,OAAO,EAAE,oCAAoC;YAACC,QAAQ;QAAG;IACvF;IACA,IAAIL,gBAAgBC,QAAQ;QAC1B,MAAM,IAAIX,YAAYW,MAAMG,OAAO,EAAEH,MAAMF,MAAM,EAAE;YACjDO,SAAS;gBAACC,qBAAqBN,MAAMO,iBAAiB;YAAA;YACtDH,QAAQP,eAAeG,MAAMF,MAAM;QACrC;IACF;IACA,MAAME;AACR"}
1
+ {"version":3,"sources":["../../../src/presentation/routes/errors.ts"],"sourcesContent":["import {ClientError} from '@shipfox/node-fastify';\nimport {\n IntegrationCapabilityUnavailableError,\n IntegrationCheckoutUnsupportedError,\n IntegrationConnectionInactiveError,\n IntegrationConnectionNotFoundError,\n IntegrationConnectionWorkspaceMismatchError,\n IntegrationProviderError,\n type IntegrationProviderErrorReason,\n IntegrationProviderUnavailableError,\n} from '#core/errors.js';\n\nfunction providerStatus(reason: IntegrationProviderErrorReason): number {\n if (reason === 'rate-limited') return 429;\n if (reason === 'timeout' || reason === 'provider-unavailable') return 503;\n return 422;\n}\n\nfunction isProviderError(error: unknown): error is IntegrationProviderError {\n return (\n error instanceof IntegrationProviderError ||\n (error instanceof Error &&\n 'reason' in error &&\n typeof error.reason === 'string' &&\n (error.reason === 'repository-not-found' ||\n error.reason === 'installation-not-found' ||\n error.reason === 'file-not-found' ||\n error.reason === 'ref-not-found' ||\n error.reason === 'ref-invalid' ||\n error.reason === 'access-denied' ||\n error.reason === 'rate-limited' ||\n error.reason === 'timeout' ||\n error.reason === 'provider-unavailable' ||\n error.reason === 'provider-rejected' ||\n error.reason === 'malformed-provider-response' ||\n error.reason === 'content-too-large' ||\n error.reason === 'too-many-files'))\n );\n}\n\nexport function integrationRouteErrorHandler(error: unknown): never {\n if (error instanceof IntegrationConnectionNotFoundError) {\n throw new ClientError(error.message, 'integration-connection-not-found', {status: 404});\n }\n if (error instanceof IntegrationConnectionInactiveError) {\n throw new ClientError(error.message, 'integration-connection-inactive', {status: 422});\n }\n if (error instanceof IntegrationConnectionWorkspaceMismatchError) {\n throw new ClientError(error.message, 'forbidden', {status: 403});\n }\n if (error instanceof IntegrationProviderUnavailableError) {\n throw new ClientError(error.message, 'integration-provider-unavailable', {status: 422});\n }\n if (error instanceof IntegrationCapabilityUnavailableError) {\n throw new ClientError(error.message, 'integration-capability-unavailable', {status: 422});\n }\n if (error instanceof IntegrationCheckoutUnsupportedError) {\n throw new ClientError(error.message, 'integration-checkout-unsupported', {status: 422});\n }\n if (isProviderError(error)) {\n throw new ClientError(error.message, error.reason, {\n details: {retry_after_seconds: error.retryAfterSeconds},\n status: providerStatus(error.reason),\n });\n }\n throw error;\n}\n"],"names":["ClientError","IntegrationCapabilityUnavailableError","IntegrationCheckoutUnsupportedError","IntegrationConnectionInactiveError","IntegrationConnectionNotFoundError","IntegrationConnectionWorkspaceMismatchError","IntegrationProviderError","IntegrationProviderUnavailableError","providerStatus","reason","isProviderError","error","Error","integrationRouteErrorHandler","message","status","details","retry_after_seconds","retryAfterSeconds"],"mappings":"AAAA,SAAQA,WAAW,QAAO,wBAAwB;AAClD,SACEC,qCAAqC,EACrCC,mCAAmC,EACnCC,kCAAkC,EAClCC,kCAAkC,EAClCC,2CAA2C,EAC3CC,wBAAwB,EAExBC,mCAAmC,QAC9B,kBAAkB;AAEzB,SAASC,eAAeC,MAAsC;IAC5D,IAAIA,WAAW,gBAAgB,OAAO;IACtC,IAAIA,WAAW,aAAaA,WAAW,wBAAwB,OAAO;IACtE,OAAO;AACT;AAEA,SAASC,gBAAgBC,KAAc;IACrC,OACEA,iBAAiBL,4BAChBK,iBAAiBC,SAChB,YAAYD,SACZ,OAAOA,MAAMF,MAAM,KAAK,YACvBE,CAAAA,MAAMF,MAAM,KAAK,0BAChBE,MAAMF,MAAM,KAAK,4BACjBE,MAAMF,MAAM,KAAK,oBACjBE,MAAMF,MAAM,KAAK,mBACjBE,MAAMF,MAAM,KAAK,iBACjBE,MAAMF,MAAM,KAAK,mBACjBE,MAAMF,MAAM,KAAK,kBACjBE,MAAMF,MAAM,KAAK,aACjBE,MAAMF,MAAM,KAAK,0BACjBE,MAAMF,MAAM,KAAK,uBACjBE,MAAMF,MAAM,KAAK,iCACjBE,MAAMF,MAAM,KAAK,uBACjBE,MAAMF,MAAM,KAAK,gBAAe;AAExC;AAEA,OAAO,SAASI,6BAA6BF,KAAc;IACzD,IAAIA,iBAAiBP,oCAAoC;QACvD,MAAM,IAAIJ,YAAYW,MAAMG,OAAO,EAAE,oCAAoC;YAACC,QAAQ;QAAG;IACvF;IACA,IAAIJ,iBAAiBR,oCAAoC;QACvD,MAAM,IAAIH,YAAYW,MAAMG,OAAO,EAAE,mCAAmC;YAACC,QAAQ;QAAG;IACtF;IACA,IAAIJ,iBAAiBN,6CAA6C;QAChE,MAAM,IAAIL,YAAYW,MAAMG,OAAO,EAAE,aAAa;YAACC,QAAQ;QAAG;IAChE;IACA,IAAIJ,iBAAiBJ,qCAAqC;QACxD,MAAM,IAAIP,YAAYW,MAAMG,OAAO,EAAE,oCAAoC;YAACC,QAAQ;QAAG;IACvF;IACA,IAAIJ,iBAAiBV,uCAAuC;QAC1D,MAAM,IAAID,YAAYW,MAAMG,OAAO,EAAE,sCAAsC;YAACC,QAAQ;QAAG;IACzF;IACA,IAAIJ,iBAAiBT,qCAAqC;QACxD,MAAM,IAAIF,YAAYW,MAAMG,OAAO,EAAE,oCAAoC;YAACC,QAAQ;QAAG;IACvF;IACA,IAAIL,gBAAgBC,QAAQ;QAC1B,MAAM,IAAIX,YAAYW,MAAMG,OAAO,EAAEH,MAAMF,MAAM,EAAE;YACjDO,SAAS;gBAACC,qBAAqBN,MAAMO,iBAAiB;YAAA;YACtDH,QAAQP,eAAeG,MAAMF,MAAM;QACrC;IACF;IACA,MAAME;AACR"}
@@ -1 +1 @@
1
- {"version":3,"file":"manage-connections.d.ts","sourceRoot":"","sources":["../../../src/presentation/routes/manage-connections.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAC,2BAA2B,EAAC,MAAM,6BAA6B,CAAC;AAe7E,wBAAgB,sCAAsC,CAAC,QAAQ,EAAE,2BAA2B,mDAgC3F;AAED,wBAAgB,sCAAsC,CAAC,QAAQ,EAAE,2BAA2B,mDA8E3F"}
1
+ {"version":3,"file":"manage-connections.d.ts","sourceRoot":"","sources":["../../../src/presentation/routes/manage-connections.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAC,2BAA2B,EAAC,MAAM,6BAA6B,CAAC;AAe7E,wBAAgB,sCAAsC,CAAC,QAAQ,EAAE,2BAA2B,mDAoC3F;AAED,wBAAgB,sCAAsC,CAAC,QAAQ,EAAE,2BAA2B,mDA8E3F"}
@@ -34,18 +34,22 @@ export function createUpdateIntegrationConnectionRoute(registry) {
34
34
  request,
35
35
  workspaceId: connection.workspaceId
36
36
  });
37
+ const provider = registry.list().find((candidate)=>candidate.provider === connection.provider);
38
+ const capabilities = provider?.capabilities ?? [];
37
39
  const updated = await updateIntegrationConnectionLifecycleStatus({
38
40
  id: connection.id,
39
- lifecycleStatus: request.body.lifecycle_status
41
+ lifecycleStatus: request.body.lifecycle_status,
42
+ ...request.body.lifecycle_status === 'active' ? {
43
+ capabilities
44
+ } : {}
40
45
  });
41
46
  if (!updated) {
42
47
  throw new ClientError('Integration connection not found', 'not-found', {
43
48
  status: 404
44
49
  });
45
50
  }
46
- const provider = registry.list().find((candidate)=>candidate.provider === updated.provider);
47
51
  return toIntegrationConnectionDto(updated, {
48
- capabilities: provider?.capabilities ?? []
52
+ capabilities
49
53
  });
50
54
  }
51
55
  });
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/presentation/routes/manage-connections.ts"],"sourcesContent":["import {AUTH_USER, requireWorkspaceAccess} from '@shipfox/api-auth-context';\nimport {\n integrationConnectionDtoSchema,\n updateIntegrationConnectionBodySchema,\n} from '@shipfox/api-integration-spi';\nimport {ClientError, defineRoute} from '@shipfox/node-fastify';\nimport {z} from 'zod';\nimport type {IntegrationProviderRegistry} from '#core/providers/registry.js';\nimport {processIntegrationSecretCleanups} from '#core/secret-cleanup.js';\nimport {\n deleteIntegrationConnection,\n getIntegrationConnectionById,\n updateIntegrationConnectionLifecycleStatus,\n} from '#db/connections.js';\nimport {db} from '#db/db.js';\nimport {enqueueIntegrationSecretCleanup} from '#db/secret-cleanups.js';\nimport {toIntegrationConnectionDto} from '#presentation/dto/integrations.js';\n\nconst connectionParamsSchema = z.object({\n connectionId: z.string().uuid(),\n});\n\nexport function createUpdateIntegrationConnectionRoute(registry: IntegrationProviderRegistry) {\n return defineRoute({\n method: 'PATCH',\n path: '/integration-connections/:connectionId',\n auth: AUTH_USER,\n description: 'Update an integration connection.',\n schema: {\n params: connectionParamsSchema,\n body: updateIntegrationConnectionBodySchema,\n response: {\n 200: integrationConnectionDtoSchema,\n },\n },\n handler: async (request) => {\n const connection = await getIntegrationConnectionById(request.params.connectionId);\n if (!connection) {\n throw new ClientError('Integration connection not found', 'not-found', {status: 404});\n }\n\n requireWorkspaceAccess({request, workspaceId: connection.workspaceId});\n const updated = await updateIntegrationConnectionLifecycleStatus({\n id: connection.id,\n lifecycleStatus: request.body.lifecycle_status,\n });\n if (!updated) {\n throw new ClientError('Integration connection not found', 'not-found', {status: 404});\n }\n\n const provider = registry.list().find((candidate) => candidate.provider === updated.provider);\n return toIntegrationConnectionDto(updated, {capabilities: provider?.capabilities ?? []});\n },\n });\n}\n\nexport function createDeleteIntegrationConnectionRoute(registry: IntegrationProviderRegistry) {\n return defineRoute({\n method: 'DELETE',\n path: '/integration-connections/:connectionId',\n auth: AUTH_USER,\n description: 'Delete an integration connection.',\n schema: {\n params: connectionParamsSchema,\n response: {\n 204: z.void(),\n },\n },\n handler: async (request, reply) => {\n const connection = await getIntegrationConnectionById(request.params.connectionId);\n if (!connection) {\n throw new ClientError('Integration connection not found', 'not-found', {status: 404});\n }\n\n requireWorkspaceAccess({request, workspaceId: connection.workspaceId});\n const provider = registry\n .list()\n .find((candidate) => candidate.provider === connection.provider);\n const hasCleanupHooks =\n provider?.deleteConnectionRemoteResources !== undefined ||\n provider?.deleteConnectionRecords !== undefined ||\n provider?.deleteConnectionSecrets !== undefined;\n if (!hasCleanupHooks) {\n request.log.warn(\n {connectionId: connection.id, provider: connection.provider},\n 'Deleting integration connection without provider cleanup',\n );\n }\n const deleteConnection = async (): Promise<void> => {\n let deleteRemoteResources: (() => Promise<void>) | undefined;\n try {\n deleteRemoteResources = await provider?.deleteConnectionRemoteResources?.(connection);\n } catch (error) {\n request.log.error(\n {connectionId: connection.id, provider: connection.provider, err: error},\n 'Integration connection remote cleanup preparation failed',\n );\n }\n await db().transaction(async (tx) => {\n await provider?.deleteConnectionRecords?.(connection, {tx});\n await enqueueIntegrationSecretCleanup({connection}, {tx});\n await deleteIntegrationConnection({id: connection.id}, {tx});\n });\n try {\n await deleteRemoteResources?.();\n } catch (error) {\n request.log.error(\n {connectionId: connection.id, provider: connection.provider, err: error},\n 'Integration connection remote cleanup failed after deletion',\n );\n }\n try {\n await processIntegrationSecretCleanups({\n registry,\n connectionId: connection.id,\n connection,\n limit: 1,\n });\n } catch (error) {\n // The durable cleanup row survives, so a later sweep retries this connection.\n request.log.error(\n {connectionId: connection.id, provider: connection.provider, err: error},\n 'Integration connection secret cleanup failed after connection deletion',\n );\n }\n };\n if (provider?.withConnectionDeletionLock) {\n await provider.withConnectionDeletionLock(connection, deleteConnection);\n } else {\n await deleteConnection();\n }\n reply.status(204);\n },\n });\n}\n"],"names":["AUTH_USER","requireWorkspaceAccess","integrationConnectionDtoSchema","updateIntegrationConnectionBodySchema","ClientError","defineRoute","z","processIntegrationSecretCleanups","deleteIntegrationConnection","getIntegrationConnectionById","updateIntegrationConnectionLifecycleStatus","db","enqueueIntegrationSecretCleanup","toIntegrationConnectionDto","connectionParamsSchema","object","connectionId","string","uuid","createUpdateIntegrationConnectionRoute","registry","method","path","auth","description","schema","params","body","response","handler","request","connection","status","workspaceId","updated","id","lifecycleStatus","lifecycle_status","provider","list","find","candidate","capabilities","createDeleteIntegrationConnectionRoute","void","reply","hasCleanupHooks","deleteConnectionRemoteResources","undefined","deleteConnectionRecords","deleteConnectionSecrets","log","warn","deleteConnection","deleteRemoteResources","error","err","transaction","tx","limit","withConnectionDeletionLock"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../src/presentation/routes/manage-connections.ts"],"sourcesContent":["import {AUTH_USER, requireWorkspaceAccess} from '@shipfox/api-auth-context';\nimport {\n integrationConnectionDtoSchema,\n updateIntegrationConnectionBodySchema,\n} from '@shipfox/api-integration-spi';\nimport {ClientError, defineRoute} from '@shipfox/node-fastify';\nimport {z} from 'zod';\nimport type {IntegrationProviderRegistry} from '#core/providers/registry.js';\nimport {processIntegrationSecretCleanups} from '#core/secret-cleanup.js';\nimport {\n deleteIntegrationConnection,\n getIntegrationConnectionById,\n updateIntegrationConnectionLifecycleStatus,\n} from '#db/connections.js';\nimport {db} from '#db/db.js';\nimport {enqueueIntegrationSecretCleanup} from '#db/secret-cleanups.js';\nimport {toIntegrationConnectionDto} from '#presentation/dto/integrations.js';\n\nconst connectionParamsSchema = z.object({\n connectionId: z.string().uuid(),\n});\n\nexport function createUpdateIntegrationConnectionRoute(registry: IntegrationProviderRegistry) {\n return defineRoute({\n method: 'PATCH',\n path: '/integration-connections/:connectionId',\n auth: AUTH_USER,\n description: 'Update an integration connection.',\n schema: {\n params: connectionParamsSchema,\n body: updateIntegrationConnectionBodySchema,\n response: {\n 200: integrationConnectionDtoSchema,\n },\n },\n handler: async (request) => {\n const connection = await getIntegrationConnectionById(request.params.connectionId);\n if (!connection) {\n throw new ClientError('Integration connection not found', 'not-found', {status: 404});\n }\n\n requireWorkspaceAccess({request, workspaceId: connection.workspaceId});\n const provider = registry\n .list()\n .find((candidate) => candidate.provider === connection.provider);\n const capabilities = provider?.capabilities ?? [];\n const updated = await updateIntegrationConnectionLifecycleStatus({\n id: connection.id,\n lifecycleStatus: request.body.lifecycle_status,\n ...(request.body.lifecycle_status === 'active' ? {capabilities} : {}),\n });\n if (!updated) {\n throw new ClientError('Integration connection not found', 'not-found', {status: 404});\n }\n\n return toIntegrationConnectionDto(updated, {capabilities});\n },\n });\n}\n\nexport function createDeleteIntegrationConnectionRoute(registry: IntegrationProviderRegistry) {\n return defineRoute({\n method: 'DELETE',\n path: '/integration-connections/:connectionId',\n auth: AUTH_USER,\n description: 'Delete an integration connection.',\n schema: {\n params: connectionParamsSchema,\n response: {\n 204: z.void(),\n },\n },\n handler: async (request, reply) => {\n const connection = await getIntegrationConnectionById(request.params.connectionId);\n if (!connection) {\n throw new ClientError('Integration connection not found', 'not-found', {status: 404});\n }\n\n requireWorkspaceAccess({request, workspaceId: connection.workspaceId});\n const provider = registry\n .list()\n .find((candidate) => candidate.provider === connection.provider);\n const hasCleanupHooks =\n provider?.deleteConnectionRemoteResources !== undefined ||\n provider?.deleteConnectionRecords !== undefined ||\n provider?.deleteConnectionSecrets !== undefined;\n if (!hasCleanupHooks) {\n request.log.warn(\n {connectionId: connection.id, provider: connection.provider},\n 'Deleting integration connection without provider cleanup',\n );\n }\n const deleteConnection = async (): Promise<void> => {\n let deleteRemoteResources: (() => Promise<void>) | undefined;\n try {\n deleteRemoteResources = await provider?.deleteConnectionRemoteResources?.(connection);\n } catch (error) {\n request.log.error(\n {connectionId: connection.id, provider: connection.provider, err: error},\n 'Integration connection remote cleanup preparation failed',\n );\n }\n await db().transaction(async (tx) => {\n await provider?.deleteConnectionRecords?.(connection, {tx});\n await enqueueIntegrationSecretCleanup({connection}, {tx});\n await deleteIntegrationConnection({id: connection.id}, {tx});\n });\n try {\n await deleteRemoteResources?.();\n } catch (error) {\n request.log.error(\n {connectionId: connection.id, provider: connection.provider, err: error},\n 'Integration connection remote cleanup failed after deletion',\n );\n }\n try {\n await processIntegrationSecretCleanups({\n registry,\n connectionId: connection.id,\n connection,\n limit: 1,\n });\n } catch (error) {\n // The durable cleanup row survives, so a later sweep retries this connection.\n request.log.error(\n {connectionId: connection.id, provider: connection.provider, err: error},\n 'Integration connection secret cleanup failed after connection deletion',\n );\n }\n };\n if (provider?.withConnectionDeletionLock) {\n await provider.withConnectionDeletionLock(connection, deleteConnection);\n } else {\n await deleteConnection();\n }\n reply.status(204);\n },\n });\n}\n"],"names":["AUTH_USER","requireWorkspaceAccess","integrationConnectionDtoSchema","updateIntegrationConnectionBodySchema","ClientError","defineRoute","z","processIntegrationSecretCleanups","deleteIntegrationConnection","getIntegrationConnectionById","updateIntegrationConnectionLifecycleStatus","db","enqueueIntegrationSecretCleanup","toIntegrationConnectionDto","connectionParamsSchema","object","connectionId","string","uuid","createUpdateIntegrationConnectionRoute","registry","method","path","auth","description","schema","params","body","response","handler","request","connection","status","workspaceId","provider","list","find","candidate","capabilities","updated","id","lifecycleStatus","lifecycle_status","createDeleteIntegrationConnectionRoute","void","reply","hasCleanupHooks","deleteConnectionRemoteResources","undefined","deleteConnectionRecords","deleteConnectionSecrets","log","warn","deleteConnection","deleteRemoteResources","error","err","transaction","tx","limit","withConnectionDeletionLock"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"gitea.d.ts","sourceRoot":"","sources":["../../src/providers/gitea.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAyB,yBAAyB,EAAC,MAAM,qBAAqB,CAAC;AAiF3F,eAAO,MAAM,mBAAmB,EAAE,yBAIjC,CAAC"}
1
+ {"version":3,"file":"gitea.d.ts","sourceRoot":"","sources":["../../src/providers/gitea.ts"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAyB,yBAAyB,EAAC,MAAM,qBAAqB,CAAC;AAoF3F,eAAO,MAAM,mBAAmB,EAAE,yBAIjC,CAAC"}
@@ -1,10 +1,12 @@
1
1
  import { config } from '#config.js';
2
+ import { getIntegrationProviderCapabilities } from '#core/providers/registry.js';
2
3
  import { getIntegrationConnectionById, resolveUniqueConnectionSlug, upsertIntegrationConnection } from '#db/connections.js';
3
4
  import { db } from '#db/db.js';
4
5
  import { publishSourcePush, recordDeliveryOnly } from '#db/webhook-deliveries.js';
5
6
  import { retryConnectionSlugCollision, slugifyConnectionSlug } from '#providers/connection-slug.js';
6
7
  async function loadGiteaModuleParts() {
7
8
  const { createGiteaIntegrationProvider, getGiteaConnectionByOrg, upsertGiteaConnection, db: giteaDb, migrationsPath: giteaMigrationsPath } = await import('@shipfox/api-integration-gitea');
9
+ let providerCapabilities = [];
8
10
  async function getExistingGiteaConnection(input) {
9
11
  const row = await getGiteaConnectionByOrg(input.org);
10
12
  if (!row) return undefined;
@@ -31,7 +33,8 @@ async function loadGiteaModuleParts() {
31
33
  externalAccountId: input.org,
32
34
  slug,
33
35
  displayName: input.displayName,
34
- lifecycleStatus: 'active'
36
+ lifecycleStatus: 'active',
37
+ capabilities: providerCapabilities
35
38
  }, {
36
39
  tx
37
40
  });
@@ -52,6 +55,7 @@ async function loadGiteaModuleParts() {
52
55
  getIntegrationConnectionById,
53
56
  coreDb: db
54
57
  });
58
+ providerCapabilities = getIntegrationProviderCapabilities(integrationProvider.adapters);
55
59
  return {
56
60
  provider: integrationProvider,
57
61
  webhookProcessors: integrationProvider.webhookProcessors,
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/providers/gitea.ts"],"sourcesContent":["import type {ConnectGiteaConnectionInput} from '@shipfox/api-integration-gitea';\nimport type {IntegrationConnection as CoreIntegrationConnection} from '@shipfox/api-integration-spi';\nimport {config} from '#config.js';\nimport {\n getIntegrationConnectionById,\n resolveUniqueConnectionSlug,\n upsertIntegrationConnection,\n} from '#db/connections.js';\nimport {db} from '#db/db.js';\nimport {publishSourcePush, recordDeliveryOnly} from '#db/webhook-deliveries.js';\nimport {retryConnectionSlugCollision, slugifyConnectionSlug} from '#providers/connection-slug.js';\nimport type {IntegrationModuleParts, IntegrationProviderModule} from '#providers/types.js';\n\nasync function loadGiteaModuleParts(): Promise<IntegrationModuleParts> {\n const {\n createGiteaIntegrationProvider,\n getGiteaConnectionByOrg,\n upsertGiteaConnection,\n db: giteaDb,\n migrationsPath: giteaMigrationsPath,\n } = await import('@shipfox/api-integration-gitea');\n\n async function getExistingGiteaConnection(input: {\n org: string;\n }): Promise<CoreIntegrationConnection<'gitea'> | undefined> {\n const row = await getGiteaConnectionByOrg(input.org);\n if (!row) return undefined;\n const connection = await getIntegrationConnectionById(row.connectionId);\n if (!connection) return undefined;\n return connection as CoreIntegrationConnection<'gitea'>;\n }\n\n async function connectGiteaConnection(\n input: ConnectGiteaConnectionInput,\n ): Promise<CoreIntegrationConnection<'gitea'>> {\n return await retryConnectionSlugCollision(() =>\n db().transaction(async (tx) => {\n const baseSlug = slugifyConnectionSlug(`gitea_${input.org}`, {fallback: 'gitea'});\n const slug = await resolveUniqueConnectionSlug(\n {\n workspaceId: input.workspaceId,\n provider: 'gitea',\n externalAccountId: input.org,\n baseSlug,\n },\n {tx},\n );\n const connection = await upsertIntegrationConnection(\n {\n workspaceId: input.workspaceId,\n provider: 'gitea',\n externalAccountId: input.org,\n slug,\n displayName: input.displayName,\n lifecycleStatus: 'active',\n },\n {tx},\n );\n\n await upsertGiteaConnection(\n {\n connectionId: connection.id,\n org: input.org,\n },\n {tx},\n );\n\n return connection as CoreIntegrationConnection<'gitea'>;\n }),\n );\n }\n\n const integrationProvider = createGiteaIntegrationProvider({\n getExistingGiteaConnection,\n connectGiteaConnection,\n publishSourcePush,\n recordDeliveryOnly,\n getIntegrationConnectionById,\n coreDb: db,\n });\n\n return {\n provider: integrationProvider,\n webhookProcessors: integrationProvider.webhookProcessors,\n database: {\n db: giteaDb,\n migrationsPath: giteaMigrationsPath,\n databaseNamespace: 'integrations_gitea',\n },\n };\n}\n\nexport const giteaProviderModule: IntegrationProviderModule = {\n id: 'gitea',\n enabled: config.INTEGRATIONS_ENABLE_GITEA_PROVIDER,\n load: loadGiteaModuleParts,\n};\n"],"names":["config","getIntegrationConnectionById","resolveUniqueConnectionSlug","upsertIntegrationConnection","db","publishSourcePush","recordDeliveryOnly","retryConnectionSlugCollision","slugifyConnectionSlug","loadGiteaModuleParts","createGiteaIntegrationProvider","getGiteaConnectionByOrg","upsertGiteaConnection","giteaDb","migrationsPath","giteaMigrationsPath","getExistingGiteaConnection","input","row","org","undefined","connection","connectionId","connectGiteaConnection","transaction","tx","baseSlug","fallback","slug","workspaceId","provider","externalAccountId","displayName","lifecycleStatus","id","integrationProvider","coreDb","webhookProcessors","database","databaseNamespace","giteaProviderModule","enabled","INTEGRATIONS_ENABLE_GITEA_PROVIDER","load"],"mappings":"AAEA,SAAQA,MAAM,QAAO,aAAa;AAClC,SACEC,4BAA4B,EAC5BC,2BAA2B,EAC3BC,2BAA2B,QACtB,qBAAqB;AAC5B,SAAQC,EAAE,QAAO,YAAY;AAC7B,SAAQC,iBAAiB,EAAEC,kBAAkB,QAAO,4BAA4B;AAChF,SAAQC,4BAA4B,EAAEC,qBAAqB,QAAO,gCAAgC;AAGlG,eAAeC;IACb,MAAM,EACJC,8BAA8B,EAC9BC,uBAAuB,EACvBC,qBAAqB,EACrBR,IAAIS,OAAO,EACXC,gBAAgBC,mBAAmB,EACpC,GAAG,MAAM,MAAM,CAAC;IAEjB,eAAeC,2BAA2BC,KAEzC;QACC,MAAMC,MAAM,MAAMP,wBAAwBM,MAAME,GAAG;QACnD,IAAI,CAACD,KAAK,OAAOE;QACjB,MAAMC,aAAa,MAAMpB,6BAA6BiB,IAAII,YAAY;QACtE,IAAI,CAACD,YAAY,OAAOD;QACxB,OAAOC;IACT;IAEA,eAAeE,uBACbN,KAAkC;QAElC,OAAO,MAAMV,6BAA6B,IACxCH,KAAKoB,WAAW,CAAC,OAAOC;gBACtB,MAAMC,WAAWlB,sBAAsB,CAAC,MAAM,EAAES,MAAME,GAAG,EAAE,EAAE;oBAACQ,UAAU;gBAAO;gBAC/E,MAAMC,OAAO,MAAM1B,4BACjB;oBACE2B,aAAaZ,MAAMY,WAAW;oBAC9BC,UAAU;oBACVC,mBAAmBd,MAAME,GAAG;oBAC5BO;gBACF,GACA;oBAACD;gBAAE;gBAEL,MAAMJ,aAAa,MAAMlB,4BACvB;oBACE0B,aAAaZ,MAAMY,WAAW;oBAC9BC,UAAU;oBACVC,mBAAmBd,MAAME,GAAG;oBAC5BS;oBACAI,aAAaf,MAAMe,WAAW;oBAC9BC,iBAAiB;gBACnB,GACA;oBAACR;gBAAE;gBAGL,MAAMb,sBACJ;oBACEU,cAAcD,WAAWa,EAAE;oBAC3Bf,KAAKF,MAAME,GAAG;gBAChB,GACA;oBAACM;gBAAE;gBAGL,OAAOJ;YACT;IAEJ;IAEA,MAAMc,sBAAsBzB,+BAA+B;QACzDM;QACAO;QACAlB;QACAC;QACAL;QACAmC,QAAQhC;IACV;IAEA,OAAO;QACL0B,UAAUK;QACVE,mBAAmBF,oBAAoBE,iBAAiB;QACxDC,UAAU;YACRlC,IAAIS;YACJC,gBAAgBC;YAChBwB,mBAAmB;QACrB;IACF;AACF;AAEA,OAAO,MAAMC,sBAAiD;IAC5DN,IAAI;IACJO,SAASzC,OAAO0C,kCAAkC;IAClDC,MAAMlC;AACR,EAAE"}
1
+ {"version":3,"sources":["../../src/providers/gitea.ts"],"sourcesContent":["import type {ConnectGiteaConnectionInput} from '@shipfox/api-integration-gitea';\nimport type {IntegrationConnection as CoreIntegrationConnection} from '@shipfox/api-integration-spi';\nimport {config} from '#config.js';\nimport type {IntegrationCapability} from '#core/entities/provider.js';\nimport {getIntegrationProviderCapabilities} from '#core/providers/registry.js';\nimport {\n getIntegrationConnectionById,\n resolveUniqueConnectionSlug,\n upsertIntegrationConnection,\n} from '#db/connections.js';\nimport {db} from '#db/db.js';\nimport {publishSourcePush, recordDeliveryOnly} from '#db/webhook-deliveries.js';\nimport {retryConnectionSlugCollision, slugifyConnectionSlug} from '#providers/connection-slug.js';\nimport type {IntegrationModuleParts, IntegrationProviderModule} from '#providers/types.js';\n\nasync function loadGiteaModuleParts(): Promise<IntegrationModuleParts> {\n const {\n createGiteaIntegrationProvider,\n getGiteaConnectionByOrg,\n upsertGiteaConnection,\n db: giteaDb,\n migrationsPath: giteaMigrationsPath,\n } = await import('@shipfox/api-integration-gitea');\n let providerCapabilities: IntegrationCapability[] = [];\n\n async function getExistingGiteaConnection(input: {\n org: string;\n }): Promise<CoreIntegrationConnection<'gitea'> | undefined> {\n const row = await getGiteaConnectionByOrg(input.org);\n if (!row) return undefined;\n const connection = await getIntegrationConnectionById(row.connectionId);\n if (!connection) return undefined;\n return connection as CoreIntegrationConnection<'gitea'>;\n }\n\n async function connectGiteaConnection(\n input: ConnectGiteaConnectionInput,\n ): Promise<CoreIntegrationConnection<'gitea'>> {\n return await retryConnectionSlugCollision(() =>\n db().transaction(async (tx) => {\n const baseSlug = slugifyConnectionSlug(`gitea_${input.org}`, {fallback: 'gitea'});\n const slug = await resolveUniqueConnectionSlug(\n {\n workspaceId: input.workspaceId,\n provider: 'gitea',\n externalAccountId: input.org,\n baseSlug,\n },\n {tx},\n );\n const connection = await upsertIntegrationConnection(\n {\n workspaceId: input.workspaceId,\n provider: 'gitea',\n externalAccountId: input.org,\n slug,\n displayName: input.displayName,\n lifecycleStatus: 'active',\n capabilities: providerCapabilities,\n },\n {tx},\n );\n\n await upsertGiteaConnection(\n {\n connectionId: connection.id,\n org: input.org,\n },\n {tx},\n );\n\n return connection as CoreIntegrationConnection<'gitea'>;\n }),\n );\n }\n\n const integrationProvider = createGiteaIntegrationProvider({\n getExistingGiteaConnection,\n connectGiteaConnection,\n publishSourcePush,\n recordDeliveryOnly,\n getIntegrationConnectionById,\n coreDb: db,\n });\n providerCapabilities = getIntegrationProviderCapabilities(integrationProvider.adapters);\n\n return {\n provider: integrationProvider,\n webhookProcessors: integrationProvider.webhookProcessors,\n database: {\n db: giteaDb,\n migrationsPath: giteaMigrationsPath,\n databaseNamespace: 'integrations_gitea',\n },\n };\n}\n\nexport const giteaProviderModule: IntegrationProviderModule = {\n id: 'gitea',\n enabled: config.INTEGRATIONS_ENABLE_GITEA_PROVIDER,\n load: loadGiteaModuleParts,\n};\n"],"names":["config","getIntegrationProviderCapabilities","getIntegrationConnectionById","resolveUniqueConnectionSlug","upsertIntegrationConnection","db","publishSourcePush","recordDeliveryOnly","retryConnectionSlugCollision","slugifyConnectionSlug","loadGiteaModuleParts","createGiteaIntegrationProvider","getGiteaConnectionByOrg","upsertGiteaConnection","giteaDb","migrationsPath","giteaMigrationsPath","providerCapabilities","getExistingGiteaConnection","input","row","org","undefined","connection","connectionId","connectGiteaConnection","transaction","tx","baseSlug","fallback","slug","workspaceId","provider","externalAccountId","displayName","lifecycleStatus","capabilities","id","integrationProvider","coreDb","adapters","webhookProcessors","database","databaseNamespace","giteaProviderModule","enabled","INTEGRATIONS_ENABLE_GITEA_PROVIDER","load"],"mappings":"AAEA,SAAQA,MAAM,QAAO,aAAa;AAElC,SAAQC,kCAAkC,QAAO,8BAA8B;AAC/E,SACEC,4BAA4B,EAC5BC,2BAA2B,EAC3BC,2BAA2B,QACtB,qBAAqB;AAC5B,SAAQC,EAAE,QAAO,YAAY;AAC7B,SAAQC,iBAAiB,EAAEC,kBAAkB,QAAO,4BAA4B;AAChF,SAAQC,4BAA4B,EAAEC,qBAAqB,QAAO,gCAAgC;AAGlG,eAAeC;IACb,MAAM,EACJC,8BAA8B,EAC9BC,uBAAuB,EACvBC,qBAAqB,EACrBR,IAAIS,OAAO,EACXC,gBAAgBC,mBAAmB,EACpC,GAAG,MAAM,MAAM,CAAC;IACjB,IAAIC,uBAAgD,EAAE;IAEtD,eAAeC,2BAA2BC,KAEzC;QACC,MAAMC,MAAM,MAAMR,wBAAwBO,MAAME,GAAG;QACnD,IAAI,CAACD,KAAK,OAAOE;QACjB,MAAMC,aAAa,MAAMrB,6BAA6BkB,IAAII,YAAY;QACtE,IAAI,CAACD,YAAY,OAAOD;QACxB,OAAOC;IACT;IAEA,eAAeE,uBACbN,KAAkC;QAElC,OAAO,MAAMX,6BAA6B,IACxCH,KAAKqB,WAAW,CAAC,OAAOC;gBACtB,MAAMC,WAAWnB,sBAAsB,CAAC,MAAM,EAAEU,MAAME,GAAG,EAAE,EAAE;oBAACQ,UAAU;gBAAO;gBAC/E,MAAMC,OAAO,MAAM3B,4BACjB;oBACE4B,aAAaZ,MAAMY,WAAW;oBAC9BC,UAAU;oBACVC,mBAAmBd,MAAME,GAAG;oBAC5BO;gBACF,GACA;oBAACD;gBAAE;gBAEL,MAAMJ,aAAa,MAAMnB,4BACvB;oBACE2B,aAAaZ,MAAMY,WAAW;oBAC9BC,UAAU;oBACVC,mBAAmBd,MAAME,GAAG;oBAC5BS;oBACAI,aAAaf,MAAMe,WAAW;oBAC9BC,iBAAiB;oBACjBC,cAAcnB;gBAChB,GACA;oBAACU;gBAAE;gBAGL,MAAMd,sBACJ;oBACEW,cAAcD,WAAWc,EAAE;oBAC3BhB,KAAKF,MAAME,GAAG;gBAChB,GACA;oBAACM;gBAAE;gBAGL,OAAOJ;YACT;IAEJ;IAEA,MAAMe,sBAAsB3B,+BAA+B;QACzDO;QACAO;QACAnB;QACAC;QACAL;QACAqC,QAAQlC;IACV;IACAY,uBAAuBhB,mCAAmCqC,oBAAoBE,QAAQ;IAEtF,OAAO;QACLR,UAAUM;QACVG,mBAAmBH,oBAAoBG,iBAAiB;QACxDC,UAAU;YACRrC,IAAIS;YACJC,gBAAgBC;YAChB2B,mBAAmB;QACrB;IACF;AACF;AAEA,OAAO,MAAMC,sBAAiD;IAC5DP,IAAI;IACJQ,SAAS7C,OAAO8C,kCAAkC;IAClDC,MAAMrC;AACR,EAAE"}
@@ -1 +1 @@
1
- {"version":3,"file":"github.d.ts","sourceRoot":"","sources":["../../src/providers/github.ts"],"names":[],"mappings":"AAgBA,OAAO,KAAK,EAEV,yBAAyB,EAE1B,MAAM,qBAAqB,CAAC;AA4H7B,eAAO,MAAM,oBAAoB,EAAE,yBAIlC,CAAC"}
1
+ {"version":3,"file":"github.d.ts","sourceRoot":"","sources":["../../src/providers/github.ts"],"names":[],"mappings":"AAkBA,OAAO,KAAK,EAEV,yBAAyB,EAE1B,MAAM,qBAAqB,CAAC;AA+H7B,eAAO,MAAM,oBAAoB,EAAE,yBAIlC,CAAC"}
@@ -1,4 +1,5 @@
1
1
  import { config } from '#config.js';
2
+ import { getIntegrationProviderCapabilities } from '#core/providers/registry.js';
2
3
  import { getIntegrationConnectionById, resolveUniqueConnectionSlug, upsertIntegrationConnection } from '#db/connections.js';
3
4
  import { db } from '#db/db.js';
4
5
  import { publishIntegrationEventReceived, publishSourcePush, publishSourceRepositoryUpdated, recordDeliveryOnly } from '#db/webhook-deliveries.js';
@@ -24,6 +25,7 @@ async function loadGithubModuleParts(options = {}) {
24
25
  }
25
26
  } : undefined
26
27
  });
28
+ let providerCapabilities = [];
27
29
  async function getExistingGithubConnection(input) {
28
30
  const installation = await getGithubInstallationByInstallationId(input.installationId);
29
31
  if (!installation) return undefined;
@@ -50,7 +52,8 @@ async function loadGithubModuleParts(options = {}) {
50
52
  externalAccountId: input.installationId,
51
53
  slug,
52
54
  displayName: input.displayName,
53
- lifecycleStatus: 'active'
55
+ lifecycleStatus: 'active',
56
+ capabilities: providerCapabilities
54
57
  }, {
55
58
  tx
56
59
  });
@@ -80,6 +83,7 @@ async function loadGithubModuleParts(options = {}) {
80
83
  requireActiveWorkspaceMembership: options.requireActiveWorkspaceMembership
81
84
  } : {}
82
85
  });
86
+ providerCapabilities = getIntegrationProviderCapabilities(integrationProvider.adapters);
83
87
  return {
84
88
  provider: integrationProvider,
85
89
  webhookProcessors: integrationProvider.webhookProcessors,
@@ -87,10 +91,7 @@ async function loadGithubModuleParts(options = {}) {
87
91
  createGithubE2eRoutes({
88
92
  getExistingGithubConnection,
89
93
  connectGithubInstallation,
90
- connectionCapabilities: [
91
- 'source_control',
92
- 'agent_tools'
93
- ]
94
+ connectionCapabilities: providerCapabilities
94
95
  })
95
96
  ],
96
97
  database: {
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/providers/github.ts"],"sourcesContent":["import type {ConnectGithubInstallationInput} from '@shipfox/api-integration-github';\nimport type {IntegrationConnection as CoreIntegrationConnection} from '@shipfox/api-integration-spi';\nimport {config} from '#config.js';\nimport {\n getIntegrationConnectionById,\n resolveUniqueConnectionSlug,\n upsertIntegrationConnection,\n} from '#db/connections.js';\nimport {db} from '#db/db.js';\nimport {\n publishIntegrationEventReceived,\n publishSourcePush,\n publishSourceRepositoryUpdated,\n recordDeliveryOnly,\n} from '#db/webhook-deliveries.js';\nimport {retryConnectionSlugCollision, slugifyConnectionSlug} from '#providers/connection-slug.js';\nimport type {\n IntegrationModuleParts,\n IntegrationProviderModule,\n IntegrationProviderModuleLoadOptions,\n} from '#providers/types.js';\n\nasync function loadGithubModuleParts(\n options: IntegrationProviderModuleLoadOptions = {},\n): Promise<IntegrationModuleParts> {\n const {\n createGithubInstallationTokenProvider,\n createGithubE2eRoutes,\n encodeInstallationTokenEnvelope,\n createGithubIntegrationProvider,\n getGithubInstallationByInstallationId,\n githubInstallationTokenNamespace,\n db: githubDb,\n migrationsPath: githubMigrationsPath,\n upsertGithubInstallation,\n } = await import('@shipfox/api-integration-github');\n\n const tokenProvider = createGithubInstallationTokenProvider({\n getIntegrationConnectionById,\n secretStore: options.secrets?.github\n ? {\n read: async (workspaceId, installationId) =>\n (await options.secrets?.github?.getSecret({\n workspaceId,\n namespace: githubInstallationTokenNamespace(installationId),\n key: 'envelope',\n })) ?? null,\n write: async (workspaceId, installationId, envelope) => {\n await options.secrets?.github?.setSecrets({\n workspaceId,\n namespace: githubInstallationTokenNamespace(installationId),\n values: {envelope: encodeInstallationTokenEnvelope(envelope)},\n });\n },\n }\n : undefined,\n });\n\n async function getExistingGithubConnection(input: {\n installationId: string;\n }): Promise<CoreIntegrationConnection<'github'> | undefined> {\n const installation = await getGithubInstallationByInstallationId(input.installationId);\n if (!installation) return undefined;\n const connection = await getIntegrationConnectionById(installation.connectionId);\n if (!connection) return undefined;\n return connection as CoreIntegrationConnection<'github'>;\n }\n\n async function connectGithubInstallation(\n input: ConnectGithubInstallationInput,\n ): Promise<CoreIntegrationConnection<'github'>> {\n return await retryConnectionSlugCollision(() =>\n db().transaction(async (tx) => {\n const baseSlug = slugifyConnectionSlug(`github_${input.installation.accountLogin}`, {\n fallback: 'github',\n });\n const slug = await resolveUniqueConnectionSlug(\n {\n workspaceId: input.workspaceId,\n provider: 'github',\n externalAccountId: input.installationId,\n baseSlug,\n },\n {tx},\n );\n const connection = await upsertIntegrationConnection(\n {\n workspaceId: input.workspaceId,\n provider: 'github',\n externalAccountId: input.installationId,\n slug,\n displayName: input.displayName,\n lifecycleStatus: 'active',\n },\n {tx},\n );\n\n await upsertGithubInstallation(\n {\n connectionId: connection.id,\n ...input.installation,\n },\n {tx},\n );\n\n return connection as CoreIntegrationConnection<'github'>;\n }),\n );\n }\n\n const integrationProvider = createGithubIntegrationProvider({\n getExistingGithubConnection,\n connectGithubInstallation,\n publishIntegrationEventReceived,\n publishSourceRepositoryUpdated,\n publishSourcePush,\n recordDeliveryOnly,\n getIntegrationConnectionById,\n coreDb: db,\n deleteSecrets: options.secrets?.deleteSecrets,\n agentTools: {tokenProvider},\n ...(options.requireActiveWorkspaceMembership\n ? {requireActiveWorkspaceMembership: options.requireActiveWorkspaceMembership}\n : {}),\n });\n\n return {\n provider: integrationProvider,\n webhookProcessors: integrationProvider.webhookProcessors,\n e2eRoutes: [\n createGithubE2eRoutes({\n getExistingGithubConnection,\n connectGithubInstallation,\n connectionCapabilities: ['source_control', 'agent_tools'],\n }),\n ],\n database: {\n db: githubDb,\n migrationsPath: githubMigrationsPath,\n databaseNamespace: 'integrations_github',\n },\n };\n}\n\nexport const githubProviderModule: IntegrationProviderModule = {\n id: 'github',\n enabled: config.INTEGRATIONS_ENABLE_GITHUB_PROVIDER,\n load: loadGithubModuleParts,\n};\n"],"names":["config","getIntegrationConnectionById","resolveUniqueConnectionSlug","upsertIntegrationConnection","db","publishIntegrationEventReceived","publishSourcePush","publishSourceRepositoryUpdated","recordDeliveryOnly","retryConnectionSlugCollision","slugifyConnectionSlug","loadGithubModuleParts","options","createGithubInstallationTokenProvider","createGithubE2eRoutes","encodeInstallationTokenEnvelope","createGithubIntegrationProvider","getGithubInstallationByInstallationId","githubInstallationTokenNamespace","githubDb","migrationsPath","githubMigrationsPath","upsertGithubInstallation","tokenProvider","secretStore","secrets","github","read","workspaceId","installationId","getSecret","namespace","key","write","envelope","setSecrets","values","undefined","getExistingGithubConnection","input","installation","connection","connectionId","connectGithubInstallation","transaction","tx","baseSlug","accountLogin","fallback","slug","provider","externalAccountId","displayName","lifecycleStatus","id","integrationProvider","coreDb","deleteSecrets","agentTools","requireActiveWorkspaceMembership","webhookProcessors","e2eRoutes","connectionCapabilities","database","databaseNamespace","githubProviderModule","enabled","INTEGRATIONS_ENABLE_GITHUB_PROVIDER","load"],"mappings":"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"}
1
+ {"version":3,"sources":["../../src/providers/github.ts"],"sourcesContent":["import type {ConnectGithubInstallationInput} from '@shipfox/api-integration-github';\nimport type {IntegrationConnection as CoreIntegrationConnection} from '@shipfox/api-integration-spi';\nimport {config} from '#config.js';\nimport type {IntegrationCapability} from '#core/entities/provider.js';\nimport {getIntegrationProviderCapabilities} from '#core/providers/registry.js';\nimport {\n getIntegrationConnectionById,\n resolveUniqueConnectionSlug,\n upsertIntegrationConnection,\n} from '#db/connections.js';\nimport {db} from '#db/db.js';\nimport {\n publishIntegrationEventReceived,\n publishSourcePush,\n publishSourceRepositoryUpdated,\n recordDeliveryOnly,\n} from '#db/webhook-deliveries.js';\nimport {retryConnectionSlugCollision, slugifyConnectionSlug} from '#providers/connection-slug.js';\nimport type {\n IntegrationModuleParts,\n IntegrationProviderModule,\n IntegrationProviderModuleLoadOptions,\n} from '#providers/types.js';\n\nasync function loadGithubModuleParts(\n options: IntegrationProviderModuleLoadOptions = {},\n): Promise<IntegrationModuleParts> {\n const {\n createGithubInstallationTokenProvider,\n createGithubE2eRoutes,\n encodeInstallationTokenEnvelope,\n createGithubIntegrationProvider,\n getGithubInstallationByInstallationId,\n githubInstallationTokenNamespace,\n db: githubDb,\n migrationsPath: githubMigrationsPath,\n upsertGithubInstallation,\n } = await import('@shipfox/api-integration-github');\n\n const tokenProvider = createGithubInstallationTokenProvider({\n getIntegrationConnectionById,\n secretStore: options.secrets?.github\n ? {\n read: async (workspaceId, installationId) =>\n (await options.secrets?.github?.getSecret({\n workspaceId,\n namespace: githubInstallationTokenNamespace(installationId),\n key: 'envelope',\n })) ?? null,\n write: async (workspaceId, installationId, envelope) => {\n await options.secrets?.github?.setSecrets({\n workspaceId,\n namespace: githubInstallationTokenNamespace(installationId),\n values: {envelope: encodeInstallationTokenEnvelope(envelope)},\n });\n },\n }\n : undefined,\n });\n let providerCapabilities: IntegrationCapability[] = [];\n\n async function getExistingGithubConnection(input: {\n installationId: string;\n }): Promise<CoreIntegrationConnection<'github'> | undefined> {\n const installation = await getGithubInstallationByInstallationId(input.installationId);\n if (!installation) return undefined;\n const connection = await getIntegrationConnectionById(installation.connectionId);\n if (!connection) return undefined;\n return connection as CoreIntegrationConnection<'github'>;\n }\n\n async function connectGithubInstallation(\n input: ConnectGithubInstallationInput,\n ): Promise<CoreIntegrationConnection<'github'>> {\n return await retryConnectionSlugCollision(() =>\n db().transaction(async (tx) => {\n const baseSlug = slugifyConnectionSlug(`github_${input.installation.accountLogin}`, {\n fallback: 'github',\n });\n const slug = await resolveUniqueConnectionSlug(\n {\n workspaceId: input.workspaceId,\n provider: 'github',\n externalAccountId: input.installationId,\n baseSlug,\n },\n {tx},\n );\n const connection = await upsertIntegrationConnection(\n {\n workspaceId: input.workspaceId,\n provider: 'github',\n externalAccountId: input.installationId,\n slug,\n displayName: input.displayName,\n lifecycleStatus: 'active',\n capabilities: providerCapabilities,\n },\n {tx},\n );\n\n await upsertGithubInstallation(\n {\n connectionId: connection.id,\n ...input.installation,\n },\n {tx},\n );\n\n return connection as CoreIntegrationConnection<'github'>;\n }),\n );\n }\n\n const integrationProvider = createGithubIntegrationProvider({\n getExistingGithubConnection,\n connectGithubInstallation,\n publishIntegrationEventReceived,\n publishSourceRepositoryUpdated,\n publishSourcePush,\n recordDeliveryOnly,\n getIntegrationConnectionById,\n coreDb: db,\n deleteSecrets: options.secrets?.deleteSecrets,\n agentTools: {tokenProvider},\n ...(options.requireActiveWorkspaceMembership\n ? {requireActiveWorkspaceMembership: options.requireActiveWorkspaceMembership}\n : {}),\n });\n providerCapabilities = getIntegrationProviderCapabilities(integrationProvider.adapters);\n\n return {\n provider: integrationProvider,\n webhookProcessors: integrationProvider.webhookProcessors,\n e2eRoutes: [\n createGithubE2eRoutes({\n getExistingGithubConnection,\n connectGithubInstallation,\n connectionCapabilities: providerCapabilities,\n }),\n ],\n database: {\n db: githubDb,\n migrationsPath: githubMigrationsPath,\n databaseNamespace: 'integrations_github',\n },\n };\n}\n\nexport const githubProviderModule: IntegrationProviderModule = {\n id: 'github',\n enabled: config.INTEGRATIONS_ENABLE_GITHUB_PROVIDER,\n load: loadGithubModuleParts,\n};\n"],"names":["config","getIntegrationProviderCapabilities","getIntegrationConnectionById","resolveUniqueConnectionSlug","upsertIntegrationConnection","db","publishIntegrationEventReceived","publishSourcePush","publishSourceRepositoryUpdated","recordDeliveryOnly","retryConnectionSlugCollision","slugifyConnectionSlug","loadGithubModuleParts","options","createGithubInstallationTokenProvider","createGithubE2eRoutes","encodeInstallationTokenEnvelope","createGithubIntegrationProvider","getGithubInstallationByInstallationId","githubInstallationTokenNamespace","githubDb","migrationsPath","githubMigrationsPath","upsertGithubInstallation","tokenProvider","secretStore","secrets","github","read","workspaceId","installationId","getSecret","namespace","key","write","envelope","setSecrets","values","undefined","providerCapabilities","getExistingGithubConnection","input","installation","connection","connectionId","connectGithubInstallation","transaction","tx","baseSlug","accountLogin","fallback","slug","provider","externalAccountId","displayName","lifecycleStatus","capabilities","id","integrationProvider","coreDb","deleteSecrets","agentTools","requireActiveWorkspaceMembership","adapters","webhookProcessors","e2eRoutes","connectionCapabilities","database","databaseNamespace","githubProviderModule","enabled","INTEGRATIONS_ENABLE_GITHUB_PROVIDER","load"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"jira.d.ts","sourceRoot":"","sources":["../../src/providers/jira.ts"],"names":[],"mappings":"AAiBA,OAAO,KAAK,EAAyB,yBAAyB,EAAC,MAAM,qBAAqB,CAAC;AAiP3F,eAAO,MAAM,kBAAkB,EAAE,yBAIhC,CAAC"}
1
+ {"version":3,"file":"jira.d.ts","sourceRoot":"","sources":["../../src/providers/jira.ts"],"names":[],"mappings":"AAmBA,OAAO,KAAK,EAAyB,yBAAyB,EAAC,MAAM,qBAAqB,CAAC;AAqP3F,eAAO,MAAM,kBAAkB,EAAE,yBAIhC,CAAC"}