@shipfox/api-integration-core 5.0.0 → 6.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.
- package/.turbo/turbo-build.log +4 -4
- package/CHANGELOG.md +65 -0
- package/dist/core/entities/provider.d.ts +7 -2
- package/dist/core/entities/provider.d.ts.map +1 -1
- package/dist/core/entities/provider.js.map +1 -1
- package/dist/core/errors.d.ts +7 -0
- package/dist/core/errors.d.ts.map +1 -1
- package/dist/core/errors.js +8 -2
- package/dist/core/errors.js.map +1 -1
- package/dist/index.d.ts +17 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +50 -5
- package/dist/index.js.map +1 -1
- package/dist/presentation/inter-module.d.ts +9 -0
- package/dist/presentation/inter-module.d.ts.map +1 -0
- package/dist/presentation/inter-module.js +121 -0
- package/dist/presentation/inter-module.js.map +1 -0
- package/dist/presentation/routes/agent-tools-gateway/index.d.ts +1 -0
- package/dist/presentation/routes/agent-tools-gateway/index.d.ts.map +1 -1
- package/dist/presentation/routes/agent-tools-gateway/index.js +1 -0
- package/dist/presentation/routes/agent-tools-gateway/index.js.map +1 -1
- package/dist/presentation/routes/agent-tools-gateway/resolve-authorized-tools.d.ts +5 -2
- package/dist/presentation/routes/agent-tools-gateway/resolve-authorized-tools.d.ts.map +1 -1
- package/dist/presentation/routes/agent-tools-gateway/resolve-authorized-tools.js +53 -17
- package/dist/presentation/routes/agent-tools-gateway/resolve-authorized-tools.js.map +1 -1
- package/dist/presentation/routes/index.d.ts +2 -3
- package/dist/presentation/routes/index.d.ts.map +1 -1
- package/dist/presentation/routes/index.js +2 -2
- package/dist/presentation/routes/index.js.map +1 -1
- package/dist/providers/gitea.d.ts.map +1 -1
- package/dist/providers/gitea.js +10 -8
- package/dist/providers/gitea.js.map +1 -1
- package/dist/providers/github.d.ts.map +1 -1
- package/dist/providers/github.js +18 -13
- package/dist/providers/github.js.map +1 -1
- package/dist/providers/jira.d.ts.map +1 -1
- package/dist/providers/jira.js +4 -1
- package/dist/providers/jira.js.map +1 -1
- package/dist/providers/linear.d.ts.map +1 -1
- package/dist/providers/linear.js +34 -29
- package/dist/providers/linear.js.map +1 -1
- package/dist/providers/sentry.d.ts.map +1 -1
- package/dist/providers/sentry.js +13 -11
- package/dist/providers/sentry.js.map +1 -1
- package/dist/providers/slack.d.ts.map +1 -1
- package/dist/providers/slack.js +34 -29
- package/dist/providers/slack.js.map +1 -1
- package/dist/providers/types.d.ts +12 -0
- package/dist/providers/types.d.ts.map +1 -1
- package/dist/providers/types.js.map +1 -1
- package/dist/providers/webhook.d.ts.map +1 -1
- package/dist/providers/webhook.js +11 -9
- package/dist/providers/webhook.js.map +1 -1
- package/dist/tsconfig.test.tsbuildinfo +1 -1
- package/package.json +22 -17
- package/src/core/entities/provider.ts +7 -1
- package/src/core/errors.ts +12 -2
- package/src/index.test.ts +112 -0
- package/src/index.ts +102 -9
- package/src/presentation/inter-module.ts +155 -0
- package/src/presentation/routes/agent-tools-gateway/index.ts +1 -0
- package/src/presentation/routes/agent-tools-gateway/resolve-authorized-tools.test.ts +36 -0
- package/src/presentation/routes/agent-tools-gateway/resolve-authorized-tools.ts +64 -22
- package/src/presentation/routes/index.ts +4 -5
- package/src/providers/gitea.ts +11 -8
- package/src/providers/github.ts +17 -11
- package/src/providers/jira.ts +3 -0
- package/src/providers/linear.ts +30 -24
- package/src/providers/sentry.ts +15 -12
- package/src/providers/slack.ts +31 -25
- package/src/providers/types.ts +15 -0
- package/src/providers/webhook.ts +11 -9
- package/tsconfig.build.tsbuildinfo +1 -1
|
@@ -3,6 +3,7 @@ import type { IntegrationProviderRegistry } from '#core/providers/registry.js';
|
|
|
3
3
|
import type { GetIntegrationConnectionByIdFn } from '#db/connections.js';
|
|
4
4
|
import { type LeasedAgentStepLoader } from './resolve-authorized-tools.js';
|
|
5
5
|
export type { LeasedAgentStepLoader } from './resolve-authorized-tools.js';
|
|
6
|
+
export { createWorkflowsLeasedAgentStepLoader } from './resolve-authorized-tools.js';
|
|
6
7
|
export interface CreateAgentToolsGatewayRoutesParams {
|
|
7
8
|
loadLeasedAgentStep: LeasedAgentStepLoader;
|
|
8
9
|
registry: IntegrationProviderRegistry;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/presentation/routes/agent-tools-gateway/index.ts"],"names":[],"mappings":"AAGA,OAAO,EAAc,KAAK,UAAU,EAAC,MAAM,uBAAuB,CAAC;AACnE,OAAO,KAAK,EAAC,2BAA2B,EAAC,MAAM,6BAA6B,CAAC;AAC7E,OAAO,KAAK,EAAC,8BAA8B,EAAC,MAAM,oBAAoB,CAAC;AAIvE,OAAO,EACL,KAAK,qBAAqB,EAE3B,MAAM,+BAA+B,CAAC;AAEvC,YAAY,EAAC,qBAAqB,EAAC,MAAM,+BAA+B,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/presentation/routes/agent-tools-gateway/index.ts"],"names":[],"mappings":"AAGA,OAAO,EAAc,KAAK,UAAU,EAAC,MAAM,uBAAuB,CAAC;AACnE,OAAO,KAAK,EAAC,2BAA2B,EAAC,MAAM,6BAA6B,CAAC;AAC7E,OAAO,KAAK,EAAC,8BAA8B,EAAC,MAAM,oBAAoB,CAAC;AAIvE,OAAO,EACL,KAAK,qBAAqB,EAE3B,MAAM,+BAA+B,CAAC;AAEvC,YAAY,EAAC,qBAAqB,EAAC,MAAM,+BAA+B,CAAC;AACzE,OAAO,EAAC,oCAAoC,EAAC,MAAM,+BAA+B,CAAC;AAEnF,MAAM,WAAW,mCAAmC;IAClD,mBAAmB,EAAE,qBAAqB,CAAC;IAC3C,QAAQ,EAAE,2BAA2B,CAAC;IACtC,4BAA4B,EAAE,8BAA8B,CAAC;CAC9D;AAED,wBAAgB,6BAA6B,CAC3C,MAAM,EAAE,mCAAmC,GAC1C,UAAU,CAqCZ"}
|
|
@@ -5,6 +5,7 @@ import { createIntegrationToolCallRecorder } from './audit.js';
|
|
|
5
5
|
import { createIntegrationToolDispatcher } from './dispatch.js';
|
|
6
6
|
import { buildAgentToolsMcpServer } from './mcp-server.js';
|
|
7
7
|
import { resolveAuthorizedIntegrationTools } from './resolve-authorized-tools.js';
|
|
8
|
+
export { createWorkflowsLeasedAgentStepLoader } from './resolve-authorized-tools.js';
|
|
8
9
|
export function createAgentToolsGatewayRoutes(params) {
|
|
9
10
|
const dispatchIntegrationToolCall = createIntegrationToolDispatcher({
|
|
10
11
|
registry: params.registry
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/presentation/routes/agent-tools-gateway/index.ts"],"sourcesContent":["import {StreamableHTTPServerTransport} from '@modelcontextprotocol/sdk/server/streamableHttp.js';\nimport type {Transport} from '@modelcontextprotocol/sdk/shared/transport.js';\nimport {AUTH_LEASED_JOB, requireLeasedJobContext} from '@shipfox/api-auth-context';\nimport {defineRoute, type RouteGroup} from '@shipfox/node-fastify';\nimport type {IntegrationProviderRegistry} from '#core/providers/registry.js';\nimport type {GetIntegrationConnectionByIdFn} from '#db/connections.js';\nimport {createIntegrationToolCallRecorder} from './audit.js';\nimport {createIntegrationToolDispatcher} from './dispatch.js';\nimport {buildAgentToolsMcpServer} from './mcp-server.js';\nimport {\n type LeasedAgentStepLoader,\n resolveAuthorizedIntegrationTools,\n} from './resolve-authorized-tools.js';\n\nexport type {LeasedAgentStepLoader} from './resolve-authorized-tools.js';\n\nexport interface CreateAgentToolsGatewayRoutesParams {\n loadLeasedAgentStep: LeasedAgentStepLoader;\n registry: IntegrationProviderRegistry;\n getIntegrationConnectionById: GetIntegrationConnectionByIdFn;\n}\n\nexport function createAgentToolsGatewayRoutes(\n params: CreateAgentToolsGatewayRoutesParams,\n): RouteGroup {\n const dispatchIntegrationToolCall = createIntegrationToolDispatcher({registry: params.registry});\n\n return {\n prefix: '/runs/jobs/current/integration-tools',\n auth: AUTH_LEASED_JOB,\n routes: [\n defineRoute({\n method: 'POST',\n path: '/mcp',\n description: 'Gateway MCP endpoint for integration-backed agent tools',\n handler: async (request, reply) => {\n const authorizedTools = await resolveAuthorizedIntegrationTools({\n request,\n loadLeasedAgentStep: params.loadLeasedAgentStep,\n registry: params.registry,\n getIntegrationConnectionById: params.getIntegrationConnectionById,\n });\n const server = buildAgentToolsMcpServer({\n authorizedTools,\n dispatch: dispatchIntegrationToolCall,\n recordCall: createIntegrationToolCallRecorder(requireLeasedJobContext(request)),\n });\n const transport = new StreamableHTTPServerTransport();\n\n await server.connect(transport as unknown as Transport);\n reply.raw.on('close', () => {\n void transport.close();\n void server.close();\n });\n\n reply.hijack();\n await transport.handleRequest(request.raw, reply.raw, request.body);\n },\n }),\n ],\n };\n}\n"],"names":["StreamableHTTPServerTransport","AUTH_LEASED_JOB","requireLeasedJobContext","defineRoute","createIntegrationToolCallRecorder","createIntegrationToolDispatcher","buildAgentToolsMcpServer","resolveAuthorizedIntegrationTools","createAgentToolsGatewayRoutes","params","dispatchIntegrationToolCall","registry","prefix","auth","routes","method","path","description","handler","request","reply","authorizedTools","loadLeasedAgentStep","getIntegrationConnectionById","server","dispatch","recordCall","transport","connect","raw","on","close","hijack","handleRequest","body"],"mappings":"AAAA,SAAQA,6BAA6B,QAAO,qDAAqD;AAEjG,SAAQC,eAAe,EAAEC,uBAAuB,QAAO,4BAA4B;AACnF,SAAQC,WAAW,QAAwB,wBAAwB;AAGnE,SAAQC,iCAAiC,QAAO,aAAa;AAC7D,SAAQC,+BAA+B,QAAO,gBAAgB;AAC9D,SAAQC,wBAAwB,QAAO,kBAAkB;AACzD,SAEEC,iCAAiC,QAC5B,gCAAgC;
|
|
1
|
+
{"version":3,"sources":["../../../../src/presentation/routes/agent-tools-gateway/index.ts"],"sourcesContent":["import {StreamableHTTPServerTransport} from '@modelcontextprotocol/sdk/server/streamableHttp.js';\nimport type {Transport} from '@modelcontextprotocol/sdk/shared/transport.js';\nimport {AUTH_LEASED_JOB, requireLeasedJobContext} from '@shipfox/api-auth-context';\nimport {defineRoute, type RouteGroup} from '@shipfox/node-fastify';\nimport type {IntegrationProviderRegistry} from '#core/providers/registry.js';\nimport type {GetIntegrationConnectionByIdFn} from '#db/connections.js';\nimport {createIntegrationToolCallRecorder} from './audit.js';\nimport {createIntegrationToolDispatcher} from './dispatch.js';\nimport {buildAgentToolsMcpServer} from './mcp-server.js';\nimport {\n type LeasedAgentStepLoader,\n resolveAuthorizedIntegrationTools,\n} from './resolve-authorized-tools.js';\n\nexport type {LeasedAgentStepLoader} from './resolve-authorized-tools.js';\nexport {createWorkflowsLeasedAgentStepLoader} from './resolve-authorized-tools.js';\n\nexport interface CreateAgentToolsGatewayRoutesParams {\n loadLeasedAgentStep: LeasedAgentStepLoader;\n registry: IntegrationProviderRegistry;\n getIntegrationConnectionById: GetIntegrationConnectionByIdFn;\n}\n\nexport function createAgentToolsGatewayRoutes(\n params: CreateAgentToolsGatewayRoutesParams,\n): RouteGroup {\n const dispatchIntegrationToolCall = createIntegrationToolDispatcher({registry: params.registry});\n\n return {\n prefix: '/runs/jobs/current/integration-tools',\n auth: AUTH_LEASED_JOB,\n routes: [\n defineRoute({\n method: 'POST',\n path: '/mcp',\n description: 'Gateway MCP endpoint for integration-backed agent tools',\n handler: async (request, reply) => {\n const authorizedTools = await resolveAuthorizedIntegrationTools({\n request,\n loadLeasedAgentStep: params.loadLeasedAgentStep,\n registry: params.registry,\n getIntegrationConnectionById: params.getIntegrationConnectionById,\n });\n const server = buildAgentToolsMcpServer({\n authorizedTools,\n dispatch: dispatchIntegrationToolCall,\n recordCall: createIntegrationToolCallRecorder(requireLeasedJobContext(request)),\n });\n const transport = new StreamableHTTPServerTransport();\n\n await server.connect(transport as unknown as Transport);\n reply.raw.on('close', () => {\n void transport.close();\n void server.close();\n });\n\n reply.hijack();\n await transport.handleRequest(request.raw, reply.raw, request.body);\n },\n }),\n ],\n };\n}\n"],"names":["StreamableHTTPServerTransport","AUTH_LEASED_JOB","requireLeasedJobContext","defineRoute","createIntegrationToolCallRecorder","createIntegrationToolDispatcher","buildAgentToolsMcpServer","resolveAuthorizedIntegrationTools","createWorkflowsLeasedAgentStepLoader","createAgentToolsGatewayRoutes","params","dispatchIntegrationToolCall","registry","prefix","auth","routes","method","path","description","handler","request","reply","authorizedTools","loadLeasedAgentStep","getIntegrationConnectionById","server","dispatch","recordCall","transport","connect","raw","on","close","hijack","handleRequest","body"],"mappings":"AAAA,SAAQA,6BAA6B,QAAO,qDAAqD;AAEjG,SAAQC,eAAe,EAAEC,uBAAuB,QAAO,4BAA4B;AACnF,SAAQC,WAAW,QAAwB,wBAAwB;AAGnE,SAAQC,iCAAiC,QAAO,aAAa;AAC7D,SAAQC,+BAA+B,QAAO,gBAAgB;AAC9D,SAAQC,wBAAwB,QAAO,kBAAkB;AACzD,SAEEC,iCAAiC,QAC5B,gCAAgC;AAGvC,SAAQC,oCAAoC,QAAO,gCAAgC;AAQnF,OAAO,SAASC,8BACdC,MAA2C;IAE3C,MAAMC,8BAA8BN,gCAAgC;QAACO,UAAUF,OAAOE,QAAQ;IAAA;IAE9F,OAAO;QACLC,QAAQ;QACRC,MAAMb;QACNc,QAAQ;YACNZ,YAAY;gBACVa,QAAQ;gBACRC,MAAM;gBACNC,aAAa;gBACbC,SAAS,OAAOC,SAASC;oBACvB,MAAMC,kBAAkB,MAAMf,kCAAkC;wBAC9Da;wBACAG,qBAAqBb,OAAOa,mBAAmB;wBAC/CX,UAAUF,OAAOE,QAAQ;wBACzBY,8BAA8Bd,OAAOc,4BAA4B;oBACnE;oBACA,MAAMC,SAASnB,yBAAyB;wBACtCgB;wBACAI,UAAUf;wBACVgB,YAAYvB,kCAAkCF,wBAAwBkB;oBACxE;oBACA,MAAMQ,YAAY,IAAI5B;oBAEtB,MAAMyB,OAAOI,OAAO,CAACD;oBACrBP,MAAMS,GAAG,CAACC,EAAE,CAAC,SAAS;wBACpB,KAAKH,UAAUI,KAAK;wBACpB,KAAKP,OAAOO,KAAK;oBACnB;oBAEAX,MAAMY,MAAM;oBACZ,MAAML,UAAUM,aAAa,CAACd,QAAQU,GAAG,EAAET,MAAMS,GAAG,EAAEV,QAAQe,IAAI;gBACpE;YACF;SACD;IACH;AACF"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { type MaterializedAgentIntegrationConfigDto, type MaterializedAgentIntegrationToolConfigDto } from '@shipfox/api-agent-dto';
|
|
2
|
+
import { type WorkflowsModuleClient } from '@shipfox/api-workflows-dto/inter-module';
|
|
2
3
|
import type { IntegrationConnection } from '#core/entities/connection.js';
|
|
3
4
|
import type { AgentToolJsonSchema } from '#core/providers/agent-tools.js';
|
|
4
5
|
import type { IntegrationProviderRegistry } from '#core/providers/registry.js';
|
|
@@ -8,12 +9,14 @@ export type LeasedAgentStepLoader = (params: {
|
|
|
8
9
|
stepId: string;
|
|
9
10
|
attempt: number;
|
|
10
11
|
}) => Promise<{
|
|
11
|
-
|
|
12
|
+
workspaceId: string;
|
|
13
|
+
integrations?: MaterializedAgentIntegrationConfigDto[];
|
|
14
|
+
step?: {
|
|
12
15
|
type: string;
|
|
13
16
|
config: Record<string, unknown>;
|
|
14
17
|
};
|
|
15
|
-
workspaceId: string;
|
|
16
18
|
}>;
|
|
19
|
+
export declare function createWorkflowsLeasedAgentStepLoader(workflows: WorkflowsModuleClient): LeasedAgentStepLoader;
|
|
17
20
|
export interface AuthorizedIntegrationTool {
|
|
18
21
|
mcpName: string;
|
|
19
22
|
integration: MaterializedAgentIntegrationConfigDto;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"resolve-authorized-tools.d.ts","sourceRoot":"","sources":["../../../../src/presentation/routes/agent-tools-gateway/resolve-authorized-tools.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,qCAAqC,EAC1C,KAAK,yCAAyC,EAE/C,MAAM,wBAAwB,CAAC;
|
|
1
|
+
{"version":3,"file":"resolve-authorized-tools.d.ts","sourceRoot":"","sources":["../../../../src/presentation/routes/agent-tools-gateway/resolve-authorized-tools.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,qCAAqC,EAC1C,KAAK,yCAAyC,EAE/C,MAAM,wBAAwB,CAAC;AAEhC,OAAO,EACL,KAAK,qBAAqB,EAE3B,MAAM,yCAAyC,CAAC;AAGjD,OAAO,KAAK,EAAC,qBAAqB,EAAC,MAAM,8BAA8B,CAAC;AAExE,OAAO,KAAK,EAAC,mBAAmB,EAAC,MAAM,gCAAgC,CAAC;AACxE,OAAO,KAAK,EAAC,2BAA2B,EAAC,MAAM,6BAA6B,CAAC;AAC7E,OAAO,KAAK,EAAC,8BAA8B,EAAC,MAAM,oBAAoB,CAAC;AAEvE,MAAM,MAAM,qBAAqB,GAAG,CAAC,MAAM,EAAE;IAC3C,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;CACjB,KAAK,OAAO,CAAC;IACZ,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,CAAC,EAAE,qCAAqC,EAAE,CAAC;IACvD,IAAI,CAAC,EAAE;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;KAAC,CAAC;CACxD,CAAC,CAAC;AAEH,wBAAgB,oCAAoC,CAClD,SAAS,EAAE,qBAAqB,GAC/B,qBAAqB,CAmBvB;AAiBD,MAAM,WAAW,yBAAyB;IACxC,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,qCAAqC,CAAC;IACnD,IAAI,EAAE,yCAAyC,CAAC;IAChD,UAAU,EAAE,qBAAqB,CAAC;IAClC,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,mBAAmB,CAAC;IACjC,YAAY,CAAC,EAAE,mBAAmB,GAAG,SAAS,CAAC;CAChD;AAED,MAAM,MAAM,4BAA4B,GAAG,GAAG,CAAC,MAAM,EAAE,yBAAyB,CAAC,CAAC;AAElF,MAAM,WAAW,4BAA4B;IAC3C,OAAO,EAAE,MAAM,CAAC;IAChB,mBAAmB,EAAE,qBAAqB,CAAC;IAC3C,QAAQ,EAAE,2BAA2B,CAAC;IACtC,4BAA4B,EAAE,8BAA8B,CAAC;CAC9D;AAED,wBAAsB,iCAAiC,CACrD,MAAM,EAAE,4BAA4B,GACnC,OAAO,CAAC,4BAA4B,CAAC,CAsDvC;AAkBD,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAEjD;AAED,wBAAgB,WAAW,CAAC,cAAc,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAE1E;AAED,wBAAgB,gBAAgB,CAC9B,WAAW,EAAE,mBAAmB,EAChC,iBAAiB,EAAE,SAAS,MAAM,EAAE,GACnC,mBAAmB,CAYrB"}
|
|
@@ -1,6 +1,41 @@
|
|
|
1
1
|
import { materializedAgentStepConfigSchema } from '@shipfox/api-agent-dto';
|
|
2
2
|
import { requireLeasedJobContext } from '@shipfox/api-auth-context';
|
|
3
|
+
import { workflowsInterModuleContract } from '@shipfox/api-workflows-dto/inter-module';
|
|
4
|
+
import { isInterModuleKnownError } from '@shipfox/inter-module';
|
|
3
5
|
import { ClientError } from '@shipfox/node-fastify';
|
|
6
|
+
export function createWorkflowsLeasedAgentStepLoader(workflows) {
|
|
7
|
+
return async ({ request, stepId, attempt })=>{
|
|
8
|
+
const leasedJob = requireLeasedJobContext(request);
|
|
9
|
+
try {
|
|
10
|
+
const context = await workflows.getLeasedAgentToolContext({
|
|
11
|
+
jobId: leasedJob.jobId,
|
|
12
|
+
jobExecutionId: leasedJob.jobExecutionId,
|
|
13
|
+
runnerSessionId: leasedJob.runnerSessionId,
|
|
14
|
+
stepId,
|
|
15
|
+
attempt
|
|
16
|
+
});
|
|
17
|
+
return {
|
|
18
|
+
workspaceId: context.workspaceId,
|
|
19
|
+
integrations: context.integrations
|
|
20
|
+
};
|
|
21
|
+
} catch (error) {
|
|
22
|
+
throw toLeasedAgentToolClientError(error);
|
|
23
|
+
}
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
function toLeasedAgentToolClientError(error) {
|
|
27
|
+
const method = workflowsInterModuleContract.methods.getLeasedAgentToolContext;
|
|
28
|
+
if (!isInterModuleKnownError(method, error)) return error;
|
|
29
|
+
const status = [
|
|
30
|
+
'step-attempt-mismatch',
|
|
31
|
+
'step-not-running',
|
|
32
|
+
'leased-step-not-agent',
|
|
33
|
+
'agent-step-config-invalid'
|
|
34
|
+
].includes(error.code) ? 409 : 404;
|
|
35
|
+
return new ClientError(error.code.replaceAll('-', ' '), error.code, {
|
|
36
|
+
status
|
|
37
|
+
});
|
|
38
|
+
}
|
|
4
39
|
export async function resolveAuthorizedIntegrationTools(params) {
|
|
5
40
|
const leasedJob = requireLeasedJobContext(params.request);
|
|
6
41
|
if (!leasedJob.currentStepId || leasedJob.currentStepAttempt === undefined) {
|
|
@@ -8,17 +43,13 @@ export async function resolveAuthorizedIntegrationTools(params) {
|
|
|
8
43
|
status: 409
|
|
9
44
|
});
|
|
10
45
|
}
|
|
11
|
-
const
|
|
46
|
+
const loaded = await params.loadLeasedAgentStep({
|
|
12
47
|
request: params.request,
|
|
13
48
|
stepId: leasedJob.currentStepId,
|
|
14
49
|
attempt: leasedJob.currentStepAttempt
|
|
15
50
|
});
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
status: 409
|
|
19
|
-
});
|
|
20
|
-
}
|
|
21
|
-
const integrations = parseAgentIntegrations(step.config);
|
|
51
|
+
const workspaceId = loaded.workspaceId;
|
|
52
|
+
const integrations = loaded.integrations ?? legacyIntegrations(loaded.step);
|
|
22
53
|
const authorizedTools = new Map();
|
|
23
54
|
for (const integration of integrations){
|
|
24
55
|
const connection = await loadAuthorizedConnection({
|
|
@@ -54,6 +85,21 @@ export async function resolveAuthorizedIntegrationTools(params) {
|
|
|
54
85
|
}
|
|
55
86
|
return authorizedTools;
|
|
56
87
|
}
|
|
88
|
+
function legacyIntegrations(step) {
|
|
89
|
+
if (step?.type !== 'agent') {
|
|
90
|
+
throw new ClientError('Current leased step is not an agent step', 'leased-step-not-agent', {
|
|
91
|
+
status: 409
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
try {
|
|
95
|
+
return materializedAgentStepConfigSchema.parse(step.config).integrations ?? [];
|
|
96
|
+
} catch (error) {
|
|
97
|
+
throw new ClientError('Agent step config is invalid', 'agent-step-config-invalid', {
|
|
98
|
+
status: 409,
|
|
99
|
+
cause: error
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
}
|
|
57
103
|
export function sanitizeSlug(slug) {
|
|
58
104
|
return slug.replaceAll('-', '_');
|
|
59
105
|
}
|
|
@@ -75,16 +121,6 @@ function toolInputSchema(tool) {
|
|
|
75
121
|
const authorizedMethods = tool.methods?.map((method)=>method.id) ?? [];
|
|
76
122
|
return narrowMethodEnum(tool.inputSchema, authorizedMethods);
|
|
77
123
|
}
|
|
78
|
-
function parseAgentIntegrations(config) {
|
|
79
|
-
try {
|
|
80
|
-
return materializedAgentStepConfigSchema.parse(config).integrations ?? [];
|
|
81
|
-
} catch (error) {
|
|
82
|
-
throw new ClientError('Agent step config is invalid', 'agent-step-config-invalid', {
|
|
83
|
-
status: 409,
|
|
84
|
-
cause: error
|
|
85
|
-
});
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
124
|
async function loadAuthorizedConnection(params) {
|
|
89
125
|
const connection = await params.getIntegrationConnectionById(params.integration.connectionId);
|
|
90
126
|
if (!connection) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/presentation/routes/agent-tools-gateway/resolve-authorized-tools.ts"],"sourcesContent":["import {\n type MaterializedAgentIntegrationConfigDto,\n type MaterializedAgentIntegrationToolConfigDto,\n materializedAgentStepConfigSchema,\n} from '@shipfox/api-agent-dto';\nimport {requireLeasedJobContext} from '@shipfox/api-auth-context';\nimport {ClientError} from '@shipfox/node-fastify';\nimport type {IntegrationConnection} from '#core/entities/connection.js';\nimport type {IntegrationProviderKind} from '#core/entities/provider.js';\nimport type {AgentToolJsonSchema} from '#core/providers/agent-tools.js';\nimport type {IntegrationProviderRegistry} from '#core/providers/registry.js';\nimport type {GetIntegrationConnectionByIdFn} from '#db/connections.js';\n\nexport type LeasedAgentStepLoader = (params: {\n request: object;\n stepId: string;\n attempt: number;\n}) => Promise<{\n step: {type: string; config: Record<string, unknown>};\n workspaceId: string;\n}>;\n\nexport interface AuthorizedIntegrationTool {\n mcpName: string;\n integration: MaterializedAgentIntegrationConfigDto;\n tool: MaterializedAgentIntegrationToolConfigDto;\n connection: IntegrationConnection;\n description: string;\n inputSchema: AgentToolJsonSchema;\n outputSchema?: AgentToolJsonSchema | undefined;\n}\n\nexport type AuthorizedIntegrationToolMap = Map<string, AuthorizedIntegrationTool>;\n\nexport interface ResolveAuthorizedToolsParams {\n request: object;\n loadLeasedAgentStep: LeasedAgentStepLoader;\n registry: IntegrationProviderRegistry;\n getIntegrationConnectionById: GetIntegrationConnectionByIdFn;\n}\n\nexport async function resolveAuthorizedIntegrationTools(\n params: ResolveAuthorizedToolsParams,\n): Promise<AuthorizedIntegrationToolMap> {\n const leasedJob = requireLeasedJobContext(params.request);\n if (!leasedJob.currentStepId || leasedJob.currentStepAttempt === undefined) {\n throw new ClientError('Lease does not identify a current step', 'lease-missing-step', {\n status: 409,\n });\n }\n\n const {step, workspaceId} = await params.loadLeasedAgentStep({\n request: params.request,\n stepId: leasedJob.currentStepId,\n attempt: leasedJob.currentStepAttempt,\n });\n if (step.type !== 'agent') {\n throw new ClientError('Current leased step is not an agent step', 'leased-step-not-agent', {\n status: 409,\n });\n }\n\n const integrations = parseAgentIntegrations(step.config);\n const authorizedTools: AuthorizedIntegrationToolMap = new Map();\n\n for (const integration of integrations) {\n const connection = await loadAuthorizedConnection({\n integration,\n workspaceId,\n registry: params.registry,\n getIntegrationConnectionById: params.getIntegrationConnectionById,\n });\n const catalog = await params.registry.getAdapter(integration.provider, 'agent_tools').catalog();\n const catalogByToolId = new Map(catalog.map((entry) => [entry.id, entry]));\n\n for (const tool of integration.tools) {\n const catalogTool = catalogByToolId.get(tool.id);\n const mcpName = mcpToolName(integration.connectionSlug, tool.id);\n if (authorizedTools.has(mcpName)) {\n throw new ClientError(\n 'Integration tool names collide after MCP namespacing',\n 'integration-tool-name-collision',\n {\n status: 409,\n },\n );\n }\n\n authorizedTools.set(mcpName, {\n mcpName,\n integration,\n tool,\n connection,\n // The live catalog enriches display metadata only. Frozen step config remains the allowlist.\n description: catalogTool?.description ?? tool.id,\n inputSchema: tool.methods ? toolInputSchema(tool) : tool.inputSchema,\n outputSchema: tool.outputSchema ?? catalogTool?.outputSchema,\n });\n }\n }\n\n return authorizedTools;\n}\n\nexport function sanitizeSlug(slug: string): string {\n return slug.replaceAll('-', '_');\n}\n\nexport function mcpToolName(connectionSlug: string, toolId: string): string {\n return `${sanitizeSlug(connectionSlug)}__${toolId}`;\n}\n\nexport function narrowMethodEnum(\n inputSchema: AgentToolJsonSchema,\n authorizedMethods: readonly string[],\n): AgentToolJsonSchema {\n const schema = cloneSchema(inputSchema);\n const methodSchema = getObjectProperty(schema, 'method');\n if (methodSchema) {\n narrowEnumOrConst(methodSchema, authorizedMethods);\n }\n\n // Claude rejects MCP tools with a top-level oneOf. The narrowed method enum remains the\n // authority boundary, while provider validation enforces method-specific argument shapes.\n delete schema.oneOf;\n\n return schema;\n}\n\nfunction toolInputSchema(tool: MaterializedAgentIntegrationToolConfigDto): AgentToolJsonSchema {\n const authorizedMethods = tool.methods?.map((method) => method.id) ?? [];\n return narrowMethodEnum(tool.inputSchema, authorizedMethods);\n}\n\nfunction parseAgentIntegrations(\n config: Record<string, unknown>,\n): MaterializedAgentIntegrationConfigDto[] {\n try {\n return materializedAgentStepConfigSchema.parse(config).integrations ?? [];\n } catch (error) {\n throw new ClientError('Agent step config is invalid', 'agent-step-config-invalid', {\n status: 409,\n cause: error,\n });\n }\n}\n\nasync function loadAuthorizedConnection(params: {\n integration: MaterializedAgentIntegrationConfigDto;\n workspaceId: string;\n registry: IntegrationProviderRegistry;\n getIntegrationConnectionById: GetIntegrationConnectionByIdFn;\n}): Promise<IntegrationConnection> {\n const connection = await params.getIntegrationConnectionById(params.integration.connectionId);\n if (!connection) {\n throw new ClientError(\n 'Integration connection is no longer available',\n 'integration-tool-connection-unavailable',\n {\n status: 409,\n },\n );\n }\n if (connection.workspaceId !== params.workspaceId) {\n throw new ClientError(\n 'Integration connection does not belong to the leased workspace',\n 'integration-tool-connection-unavailable',\n {\n status: 409,\n },\n );\n }\n if (connection.lifecycleStatus !== 'active') {\n throw new ClientError(\n 'Integration connection is not active',\n 'integration-tool-connection-unavailable',\n {\n status: 409,\n },\n );\n }\n if (connection.provider !== params.integration.provider) {\n throw new ClientError(\n 'Integration connection provider changed',\n 'integration-tool-connection-unavailable',\n {\n status: 409,\n },\n );\n }\n if (!providerSupportsAgentTools(params.registry, params.integration.provider)) {\n throw new ClientError(\n 'Integration provider no longer exposes agent tools',\n 'integration-tool-connection-unavailable',\n {\n status: 409,\n },\n );\n }\n\n return connection;\n}\n\nfunction providerSupportsAgentTools(\n registry: IntegrationProviderRegistry,\n provider: IntegrationProviderKind,\n): boolean {\n try {\n return registry.get(provider).capabilities.includes('agent_tools');\n } catch {\n return false;\n }\n}\n\nfunction cloneSchema(schema: AgentToolJsonSchema): AgentToolJsonSchema {\n return structuredClone(schema);\n}\n\nfunction getObjectProperty(\n schema: AgentToolJsonSchema,\n property: string,\n): AgentToolJsonSchema | null {\n const properties = schema.properties;\n if (!isRecord(properties)) return null;\n const value = properties[property];\n return isRecord(value) ? value : null;\n}\n\nfunction narrowEnumOrConst(\n schema: AgentToolJsonSchema,\n authorizedMethods: readonly string[],\n): void {\n if (Array.isArray(schema.enum)) {\n schema.enum = schema.enum.filter(\n (value): value is string => typeof value === 'string' && authorizedMethods.includes(value),\n );\n }\n if (typeof schema.const === 'string' && !authorizedMethods.includes(schema.const)) {\n delete schema.const;\n }\n}\n\nfunction isRecord(value: unknown): value is AgentToolJsonSchema {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n"],"names":["materializedAgentStepConfigSchema","requireLeasedJobContext","ClientError","resolveAuthorizedIntegrationTools","params","leasedJob","request","currentStepId","currentStepAttempt","undefined","status","step","workspaceId","loadLeasedAgentStep","stepId","attempt","type","integrations","parseAgentIntegrations","config","authorizedTools","Map","integration","connection","loadAuthorizedConnection","registry","getIntegrationConnectionById","catalog","getAdapter","provider","catalogByToolId","map","entry","id","tool","tools","catalogTool","get","mcpName","mcpToolName","connectionSlug","has","set","description","inputSchema","methods","toolInputSchema","outputSchema","sanitizeSlug","slug","replaceAll","toolId","narrowMethodEnum","authorizedMethods","schema","cloneSchema","methodSchema","getObjectProperty","narrowEnumOrConst","oneOf","method","parse","error","cause","connectionId","lifecycleStatus","providerSupportsAgentTools","capabilities","includes","structuredClone","property","properties","isRecord","value","Array","isArray","enum","filter","const"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../../../src/presentation/routes/agent-tools-gateway/resolve-authorized-tools.ts"],"sourcesContent":["import {\n type MaterializedAgentIntegrationConfigDto,\n type MaterializedAgentIntegrationToolConfigDto,\n materializedAgentStepConfigSchema,\n} from '@shipfox/api-agent-dto';\nimport {requireLeasedJobContext} from '@shipfox/api-auth-context';\nimport {\n type WorkflowsModuleClient,\n workflowsInterModuleContract,\n} from '@shipfox/api-workflows-dto/inter-module';\nimport {isInterModuleKnownError} from '@shipfox/inter-module';\nimport {ClientError} from '@shipfox/node-fastify';\nimport type {IntegrationConnection} from '#core/entities/connection.js';\nimport type {IntegrationProviderKind} from '#core/entities/provider.js';\nimport type {AgentToolJsonSchema} from '#core/providers/agent-tools.js';\nimport type {IntegrationProviderRegistry} from '#core/providers/registry.js';\nimport type {GetIntegrationConnectionByIdFn} from '#db/connections.js';\n\nexport type LeasedAgentStepLoader = (params: {\n request: object;\n stepId: string;\n attempt: number;\n}) => Promise<{\n workspaceId: string;\n integrations?: MaterializedAgentIntegrationConfigDto[];\n step?: {type: string; config: Record<string, unknown>};\n}>;\n\nexport function createWorkflowsLeasedAgentStepLoader(\n workflows: WorkflowsModuleClient,\n): LeasedAgentStepLoader {\n return async ({request, stepId, attempt}) => {\n const leasedJob = requireLeasedJobContext(request);\n try {\n const context = await workflows.getLeasedAgentToolContext({\n jobId: leasedJob.jobId,\n jobExecutionId: leasedJob.jobExecutionId,\n runnerSessionId: leasedJob.runnerSessionId,\n stepId,\n attempt,\n });\n return {\n workspaceId: context.workspaceId,\n integrations: context.integrations,\n };\n } catch (error) {\n throw toLeasedAgentToolClientError(error);\n }\n };\n}\n\nfunction toLeasedAgentToolClientError(error: unknown): unknown {\n const method = workflowsInterModuleContract.methods.getLeasedAgentToolContext;\n if (!isInterModuleKnownError(method, error)) return error;\n\n const status = [\n 'step-attempt-mismatch',\n 'step-not-running',\n 'leased-step-not-agent',\n 'agent-step-config-invalid',\n ].includes(error.code)\n ? 409\n : 404;\n return new ClientError(error.code.replaceAll('-', ' '), error.code, {status});\n}\n\nexport interface AuthorizedIntegrationTool {\n mcpName: string;\n integration: MaterializedAgentIntegrationConfigDto;\n tool: MaterializedAgentIntegrationToolConfigDto;\n connection: IntegrationConnection;\n description: string;\n inputSchema: AgentToolJsonSchema;\n outputSchema?: AgentToolJsonSchema | undefined;\n}\n\nexport type AuthorizedIntegrationToolMap = Map<string, AuthorizedIntegrationTool>;\n\nexport interface ResolveAuthorizedToolsParams {\n request: object;\n loadLeasedAgentStep: LeasedAgentStepLoader;\n registry: IntegrationProviderRegistry;\n getIntegrationConnectionById: GetIntegrationConnectionByIdFn;\n}\n\nexport async function resolveAuthorizedIntegrationTools(\n params: ResolveAuthorizedToolsParams,\n): Promise<AuthorizedIntegrationToolMap> {\n const leasedJob = requireLeasedJobContext(params.request);\n if (!leasedJob.currentStepId || leasedJob.currentStepAttempt === undefined) {\n throw new ClientError('Lease does not identify a current step', 'lease-missing-step', {\n status: 409,\n });\n }\n\n const loaded = await params.loadLeasedAgentStep({\n request: params.request,\n stepId: leasedJob.currentStepId,\n attempt: leasedJob.currentStepAttempt,\n });\n const workspaceId = loaded.workspaceId;\n const integrations = loaded.integrations ?? legacyIntegrations(loaded.step);\n const authorizedTools: AuthorizedIntegrationToolMap = new Map();\n\n for (const integration of integrations) {\n const connection = await loadAuthorizedConnection({\n integration,\n workspaceId,\n registry: params.registry,\n getIntegrationConnectionById: params.getIntegrationConnectionById,\n });\n const catalog = await params.registry.getAdapter(integration.provider, 'agent_tools').catalog();\n const catalogByToolId = new Map(catalog.map((entry) => [entry.id, entry]));\n\n for (const tool of integration.tools) {\n const catalogTool = catalogByToolId.get(tool.id);\n const mcpName = mcpToolName(integration.connectionSlug, tool.id);\n if (authorizedTools.has(mcpName)) {\n throw new ClientError(\n 'Integration tool names collide after MCP namespacing',\n 'integration-tool-name-collision',\n {\n status: 409,\n },\n );\n }\n\n authorizedTools.set(mcpName, {\n mcpName,\n integration,\n tool,\n connection,\n // The live catalog enriches display metadata only. Frozen step config remains the allowlist.\n description: catalogTool?.description ?? tool.id,\n inputSchema: tool.methods ? toolInputSchema(tool) : tool.inputSchema,\n outputSchema: tool.outputSchema ?? catalogTool?.outputSchema,\n });\n }\n }\n\n return authorizedTools;\n}\n\nfunction legacyIntegrations(step: {type: string; config: Record<string, unknown>} | undefined) {\n if (step?.type !== 'agent') {\n throw new ClientError('Current leased step is not an agent step', 'leased-step-not-agent', {\n status: 409,\n });\n }\n try {\n return materializedAgentStepConfigSchema.parse(step.config).integrations ?? [];\n } catch (error) {\n throw new ClientError('Agent step config is invalid', 'agent-step-config-invalid', {\n status: 409,\n cause: error,\n });\n }\n}\n\nexport function sanitizeSlug(slug: string): string {\n return slug.replaceAll('-', '_');\n}\n\nexport function mcpToolName(connectionSlug: string, toolId: string): string {\n return `${sanitizeSlug(connectionSlug)}__${toolId}`;\n}\n\nexport function narrowMethodEnum(\n inputSchema: AgentToolJsonSchema,\n authorizedMethods: readonly string[],\n): AgentToolJsonSchema {\n const schema = cloneSchema(inputSchema);\n const methodSchema = getObjectProperty(schema, 'method');\n if (methodSchema) {\n narrowEnumOrConst(methodSchema, authorizedMethods);\n }\n\n // Claude rejects MCP tools with a top-level oneOf. The narrowed method enum remains the\n // authority boundary, while provider validation enforces method-specific argument shapes.\n delete schema.oneOf;\n\n return schema;\n}\n\nfunction toolInputSchema(tool: MaterializedAgentIntegrationToolConfigDto): AgentToolJsonSchema {\n const authorizedMethods = tool.methods?.map((method) => method.id) ?? [];\n return narrowMethodEnum(tool.inputSchema, authorizedMethods);\n}\n\nasync function loadAuthorizedConnection(params: {\n integration: MaterializedAgentIntegrationConfigDto;\n workspaceId: string;\n registry: IntegrationProviderRegistry;\n getIntegrationConnectionById: GetIntegrationConnectionByIdFn;\n}): Promise<IntegrationConnection> {\n const connection = await params.getIntegrationConnectionById(params.integration.connectionId);\n if (!connection) {\n throw new ClientError(\n 'Integration connection is no longer available',\n 'integration-tool-connection-unavailable',\n {\n status: 409,\n },\n );\n }\n if (connection.workspaceId !== params.workspaceId) {\n throw new ClientError(\n 'Integration connection does not belong to the leased workspace',\n 'integration-tool-connection-unavailable',\n {\n status: 409,\n },\n );\n }\n if (connection.lifecycleStatus !== 'active') {\n throw new ClientError(\n 'Integration connection is not active',\n 'integration-tool-connection-unavailable',\n {\n status: 409,\n },\n );\n }\n if (connection.provider !== params.integration.provider) {\n throw new ClientError(\n 'Integration connection provider changed',\n 'integration-tool-connection-unavailable',\n {\n status: 409,\n },\n );\n }\n if (!providerSupportsAgentTools(params.registry, params.integration.provider)) {\n throw new ClientError(\n 'Integration provider no longer exposes agent tools',\n 'integration-tool-connection-unavailable',\n {\n status: 409,\n },\n );\n }\n\n return connection;\n}\n\nfunction providerSupportsAgentTools(\n registry: IntegrationProviderRegistry,\n provider: IntegrationProviderKind,\n): boolean {\n try {\n return registry.get(provider).capabilities.includes('agent_tools');\n } catch {\n return false;\n }\n}\n\nfunction cloneSchema(schema: AgentToolJsonSchema): AgentToolJsonSchema {\n return structuredClone(schema);\n}\n\nfunction getObjectProperty(\n schema: AgentToolJsonSchema,\n property: string,\n): AgentToolJsonSchema | null {\n const properties = schema.properties;\n if (!isRecord(properties)) return null;\n const value = properties[property];\n return isRecord(value) ? value : null;\n}\n\nfunction narrowEnumOrConst(\n schema: AgentToolJsonSchema,\n authorizedMethods: readonly string[],\n): void {\n if (Array.isArray(schema.enum)) {\n schema.enum = schema.enum.filter(\n (value): value is string => typeof value === 'string' && authorizedMethods.includes(value),\n );\n }\n if (typeof schema.const === 'string' && !authorizedMethods.includes(schema.const)) {\n delete schema.const;\n }\n}\n\nfunction isRecord(value: unknown): value is AgentToolJsonSchema {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n"],"names":["materializedAgentStepConfigSchema","requireLeasedJobContext","workflowsInterModuleContract","isInterModuleKnownError","ClientError","createWorkflowsLeasedAgentStepLoader","workflows","request","stepId","attempt","leasedJob","context","getLeasedAgentToolContext","jobId","jobExecutionId","runnerSessionId","workspaceId","integrations","error","toLeasedAgentToolClientError","method","methods","status","includes","code","replaceAll","resolveAuthorizedIntegrationTools","params","currentStepId","currentStepAttempt","undefined","loaded","loadLeasedAgentStep","legacyIntegrations","step","authorizedTools","Map","integration","connection","loadAuthorizedConnection","registry","getIntegrationConnectionById","catalog","getAdapter","provider","catalogByToolId","map","entry","id","tool","tools","catalogTool","get","mcpName","mcpToolName","connectionSlug","has","set","description","inputSchema","toolInputSchema","outputSchema","type","parse","config","cause","sanitizeSlug","slug","toolId","narrowMethodEnum","authorizedMethods","schema","cloneSchema","methodSchema","getObjectProperty","narrowEnumOrConst","oneOf","connectionId","lifecycleStatus","providerSupportsAgentTools","capabilities","structuredClone","property","properties","isRecord","value","Array","isArray","enum","filter","const"],"mappings":"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"}
|
|
@@ -1,12 +1,11 @@
|
|
|
1
|
+
import type { WorkflowsModuleClient } from '@shipfox/api-workflows-dto/inter-module';
|
|
1
2
|
import type { RouteExport } from '@shipfox/node-fastify';
|
|
2
3
|
import type { IntegrationProviderRegistry } from '#core/providers/registry.js';
|
|
3
4
|
import type { IntegrationSourceControlService } from '#core/source-control-service.js';
|
|
4
5
|
import type { GetIntegrationConnectionByIdFn } from '#db/connections.js';
|
|
5
|
-
import { type LeasedAgentStepLoader } from './agent-tools-gateway/index.js';
|
|
6
|
-
export type { LeasedAgentStepLoader } from './agent-tools-gateway/index.js';
|
|
7
6
|
export interface CreateIntegrationRoutesOptions {
|
|
8
7
|
agentTools?: {
|
|
9
|
-
|
|
8
|
+
workflows: WorkflowsModuleClient;
|
|
10
9
|
getIntegrationConnectionById: GetIntegrationConnectionByIdFn;
|
|
11
10
|
} | undefined;
|
|
12
11
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/presentation/routes/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,WAAW,EAAC,MAAM,uBAAuB,CAAC;AACvD,OAAO,KAAK,EAAC,2BAA2B,EAAC,MAAM,6BAA6B,CAAC;AAC7E,OAAO,KAAK,EAAC,+BAA+B,EAAC,MAAM,iCAAiC,CAAC;AACrF,OAAO,KAAK,EAAC,8BAA8B,EAAC,MAAM,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/presentation/routes/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,qBAAqB,EAAC,MAAM,yCAAyC,CAAC;AACnF,OAAO,KAAK,EAAC,WAAW,EAAC,MAAM,uBAAuB,CAAC;AACvD,OAAO,KAAK,EAAC,2BAA2B,EAAC,MAAM,6BAA6B,CAAC;AAC7E,OAAO,KAAK,EAAC,+BAA+B,EAAC,MAAM,iCAAiC,CAAC;AACrF,OAAO,KAAK,EAAC,8BAA8B,EAAC,MAAM,oBAAoB,CAAC;AAavE,MAAM,WAAW,8BAA8B;IAC7C,UAAU,CAAC,EACP;QACE,SAAS,EAAE,qBAAqB,CAAC;QACjC,4BAA4B,EAAE,8BAA8B,CAAC;KAC9D,GACD,SAAS,CAAC;CACf;AAED,wBAAgB,uBAAuB,CACrC,QAAQ,EAAE,2BAA2B,EACrC,aAAa,EAAE,+BAA+B,EAC9C,OAAO,GAAE,8BAAmC,GAC3C,WAAW,EAAE,CAqBf"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { createAgentToolsGatewayRoutes } from './agent-tools-gateway/index.js';
|
|
1
|
+
import { createAgentToolsGatewayRoutes, createWorkflowsLeasedAgentStepLoader } from './agent-tools-gateway/index.js';
|
|
2
2
|
import { createListIntegrationConnectionsRoute } from './list-connections.js';
|
|
3
3
|
import { createListIntegrationProvidersRoute } from './list-providers.js';
|
|
4
4
|
import { createListRepositoriesRoute } from './list-repositories.js';
|
|
@@ -8,7 +8,7 @@ export function createIntegrationRoutes(registry, sourceControl, options = {}) {
|
|
|
8
8
|
const agentToolsRoutes = options.agentTools ? [
|
|
9
9
|
createAgentToolsGatewayRoutes({
|
|
10
10
|
registry,
|
|
11
|
-
loadLeasedAgentStep: options.agentTools.
|
|
11
|
+
loadLeasedAgentStep: createWorkflowsLeasedAgentStepLoader(options.agentTools.workflows),
|
|
12
12
|
getIntegrationConnectionById: options.agentTools.getIntegrationConnectionById
|
|
13
13
|
})
|
|
14
14
|
] : [];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/presentation/routes/index.ts"],"sourcesContent":["import type {RouteExport} from '@shipfox/node-fastify';\nimport type {IntegrationProviderRegistry} from '#core/providers/registry.js';\nimport type {IntegrationSourceControlService} from '#core/source-control-service.js';\nimport type {GetIntegrationConnectionByIdFn} from '#db/connections.js';\nimport {\n createAgentToolsGatewayRoutes,\n
|
|
1
|
+
{"version":3,"sources":["../../../src/presentation/routes/index.ts"],"sourcesContent":["import type {WorkflowsModuleClient} from '@shipfox/api-workflows-dto/inter-module';\nimport type {RouteExport} from '@shipfox/node-fastify';\nimport type {IntegrationProviderRegistry} from '#core/providers/registry.js';\nimport type {IntegrationSourceControlService} from '#core/source-control-service.js';\nimport type {GetIntegrationConnectionByIdFn} from '#db/connections.js';\nimport {\n createAgentToolsGatewayRoutes,\n createWorkflowsLeasedAgentStepLoader,\n} from './agent-tools-gateway/index.js';\nimport {createListIntegrationConnectionsRoute} from './list-connections.js';\nimport {createListIntegrationProvidersRoute} from './list-providers.js';\nimport {createListRepositoriesRoute} from './list-repositories.js';\nimport {\n createDeleteIntegrationConnectionRoute,\n createUpdateIntegrationConnectionRoute,\n} from './manage-connections.js';\n\nexport interface CreateIntegrationRoutesOptions {\n agentTools?:\n | {\n workflows: WorkflowsModuleClient;\n getIntegrationConnectionById: GetIntegrationConnectionByIdFn;\n }\n | undefined;\n}\n\nexport function createIntegrationRoutes(\n registry: IntegrationProviderRegistry,\n sourceControl: IntegrationSourceControlService,\n options: CreateIntegrationRoutesOptions = {},\n): RouteExport[] {\n const providerRoutes = registry.list().flatMap((provider) => provider.routes ?? []);\n const agentToolsRoutes = options.agentTools\n ? [\n createAgentToolsGatewayRoutes({\n registry,\n loadLeasedAgentStep: createWorkflowsLeasedAgentStepLoader(options.agentTools.workflows),\n getIntegrationConnectionById: options.agentTools.getIntegrationConnectionById,\n }),\n ]\n : [];\n\n return [\n createListIntegrationProvidersRoute(registry),\n createListIntegrationConnectionsRoute(registry),\n createUpdateIntegrationConnectionRoute(registry),\n createDeleteIntegrationConnectionRoute(registry),\n createListRepositoriesRoute(sourceControl),\n ...agentToolsRoutes,\n ...providerRoutes,\n ];\n}\n"],"names":["createAgentToolsGatewayRoutes","createWorkflowsLeasedAgentStepLoader","createListIntegrationConnectionsRoute","createListIntegrationProvidersRoute","createListRepositoriesRoute","createDeleteIntegrationConnectionRoute","createUpdateIntegrationConnectionRoute","createIntegrationRoutes","registry","sourceControl","options","providerRoutes","list","flatMap","provider","routes","agentToolsRoutes","agentTools","loadLeasedAgentStep","workflows","getIntegrationConnectionById"],"mappings":"AAKA,SACEA,6BAA6B,EAC7BC,oCAAoC,QAC/B,iCAAiC;AACxC,SAAQC,qCAAqC,QAAO,wBAAwB;AAC5E,SAAQC,mCAAmC,QAAO,sBAAsB;AACxE,SAAQC,2BAA2B,QAAO,yBAAyB;AACnE,SACEC,sCAAsC,EACtCC,sCAAsC,QACjC,0BAA0B;AAWjC,OAAO,SAASC,wBACdC,QAAqC,EACrCC,aAA8C,EAC9CC,UAA0C,CAAC,CAAC;IAE5C,MAAMC,iBAAiBH,SAASI,IAAI,GAAGC,OAAO,CAAC,CAACC,WAAaA,SAASC,MAAM,IAAI,EAAE;IAClF,MAAMC,mBAAmBN,QAAQO,UAAU,GACvC;QACEjB,8BAA8B;YAC5BQ;YACAU,qBAAqBjB,qCAAqCS,QAAQO,UAAU,CAACE,SAAS;YACtFC,8BAA8BV,QAAQO,UAAU,CAACG,4BAA4B;QAC/E;KACD,GACD,EAAE;IAEN,OAAO;QACLjB,oCAAoCK;QACpCN,sCAAsCM;QACtCF,uCAAuCE;QACvCH,uCAAuCG;QACvCJ,4BAA4BK;WACzBO;WACAL;KACJ;AACH"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"gitea.d.ts","sourceRoot":"","sources":["../../src/providers/gitea.ts"],"names":[],"mappings":"AAcA,OAAO,KAAK,EAAyB,yBAAyB,EAAC,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"gitea.d.ts","sourceRoot":"","sources":["../../src/providers/gitea.ts"],"names":[],"mappings":"AAcA,OAAO,KAAK,EAAyB,yBAAyB,EAAC,MAAM,qBAAqB,CAAC;AAuF3F,eAAO,MAAM,mBAAmB,EAAE,yBAIjC,CAAC"}
|
package/dist/providers/gitea.js
CHANGED
|
@@ -50,15 +50,17 @@ async function loadGiteaModuleParts() {
|
|
|
50
50
|
return connection;
|
|
51
51
|
}));
|
|
52
52
|
}
|
|
53
|
+
const integrationProvider = createGiteaIntegrationProvider({
|
|
54
|
+
getExistingGiteaConnection,
|
|
55
|
+
connectGiteaConnection,
|
|
56
|
+
publishSourcePush,
|
|
57
|
+
recordDeliveryOnly,
|
|
58
|
+
getIntegrationConnectionById,
|
|
59
|
+
coreDb: db
|
|
60
|
+
});
|
|
53
61
|
return {
|
|
54
|
-
provider:
|
|
55
|
-
|
|
56
|
-
connectGiteaConnection,
|
|
57
|
-
publishSourcePush,
|
|
58
|
-
recordDeliveryOnly,
|
|
59
|
-
getIntegrationConnectionById,
|
|
60
|
-
coreDb: db
|
|
61
|
-
}),
|
|
62
|
+
provider: integrationProvider,
|
|
63
|
+
webhookProcessors: integrationProvider.webhookProcessors,
|
|
62
64
|
database: {
|
|
63
65
|
db: giteaDb,
|
|
64
66
|
migrationsPath: giteaMigrationsPath,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/providers/gitea.ts"],"sourcesContent":["import {\n type IntegrationConnection as CoreIntegrationConnection,\n slugifyConnectionSlug,\n} from '@shipfox/api-integration-core-dto';\nimport type {ConnectGiteaConnectionInput} from '@shipfox/api-integration-gitea';\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} from '#providers/connection-slug.js';\nimport type {IntegrationModuleParts, IntegrationProviderModule} from '#providers/types.js';\n\n// Stable migration-tracking table name for the Gitea provider database. This\n// must NOT depend on the provider's position in the module `database` array. A\n// positional name would shift if a provider is flag-disabled and silently\n// re-run migrations against existing tables.\nconst GITEA_MIGRATIONS_TABLE = '__drizzle_migrations_integrations_gitea';\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
|
|
1
|
+
{"version":3,"sources":["../../src/providers/gitea.ts"],"sourcesContent":["import {\n type IntegrationConnection as CoreIntegrationConnection,\n slugifyConnectionSlug,\n} from '@shipfox/api-integration-core-dto';\nimport type {ConnectGiteaConnectionInput} from '@shipfox/api-integration-gitea';\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} from '#providers/connection-slug.js';\nimport type {IntegrationModuleParts, IntegrationProviderModule} from '#providers/types.js';\n\n// Stable migration-tracking table name for the Gitea provider database. This\n// must NOT depend on the provider's position in the module `database` array. A\n// positional name would shift if a provider is flag-disabled and silently\n// re-run migrations against existing tables.\nconst GITEA_MIGRATIONS_TABLE = '__drizzle_migrations_integrations_gitea';\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 migrationsTableName: GITEA_MIGRATIONS_TABLE,\n },\n };\n}\n\nexport const giteaProviderModule: IntegrationProviderModule = {\n id: 'gitea',\n enabled: config.INTEGRATIONS_ENABLE_GITEA_PROVIDER,\n load: loadGiteaModuleParts,\n};\n"],"names":["slugifyConnectionSlug","config","getIntegrationConnectionById","resolveUniqueConnectionSlug","upsertIntegrationConnection","db","publishSourcePush","recordDeliveryOnly","retryConnectionSlugCollision","GITEA_MIGRATIONS_TABLE","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","migrationsTableName","giteaProviderModule","enabled","INTEGRATIONS_ENABLE_GITEA_PROVIDER","load"],"mappings":"AAAA,SAEEA,qBAAqB,QAChB,oCAAoC;AAE3C,SAAQC,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,QAAO,gCAAgC;AAG3E,6EAA6E;AAC7E,+EAA+E;AAC/E,0EAA0E;AAC1E,6CAA6C;AAC7C,MAAMC,yBAAyB;AAE/B,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,WAAW3B,sBAAsB,CAAC,MAAM,EAAEkB,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,qBAAqB/B;QACvB;IACF;AACF;AAEA,OAAO,MAAMgC,sBAAiD;IAC5DN,IAAI;IACJO,SAASzC,OAAO0C,kCAAkC;IAClDC,MAAMlC;AACR,EAAE"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"github.d.ts","sourceRoot":"","sources":["../../src/providers/github.ts"],"names":[],"mappings":"AAkBA,OAAO,KAAK,EAEV,yBAAyB,EAE1B,MAAM,qBAAqB,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;AAiI7B,eAAO,MAAM,oBAAoB,EAAE,yBAIlC,CAAC"}
|
package/dist/providers/github.js
CHANGED
|
@@ -69,20 +69,25 @@ async function loadGithubModuleParts(options = {}) {
|
|
|
69
69
|
return connection;
|
|
70
70
|
}));
|
|
71
71
|
}
|
|
72
|
+
const integrationProvider = createGithubIntegrationProvider({
|
|
73
|
+
getExistingGithubConnection,
|
|
74
|
+
connectGithubInstallation,
|
|
75
|
+
publishIntegrationEventReceived,
|
|
76
|
+
publishSourcePush,
|
|
77
|
+
recordDeliveryOnly,
|
|
78
|
+
getIntegrationConnectionById,
|
|
79
|
+
coreDb: db,
|
|
80
|
+
deleteSecrets: options.secrets?.deleteSecrets,
|
|
81
|
+
agentTools: {
|
|
82
|
+
tokenProvider
|
|
83
|
+
},
|
|
84
|
+
...options.requireActiveWorkspaceMembership ? {
|
|
85
|
+
requireActiveWorkspaceMembership: options.requireActiveWorkspaceMembership
|
|
86
|
+
} : {}
|
|
87
|
+
});
|
|
72
88
|
return {
|
|
73
|
-
provider:
|
|
74
|
-
|
|
75
|
-
connectGithubInstallation,
|
|
76
|
-
publishIntegrationEventReceived,
|
|
77
|
-
publishSourcePush,
|
|
78
|
-
recordDeliveryOnly,
|
|
79
|
-
getIntegrationConnectionById,
|
|
80
|
-
coreDb: db,
|
|
81
|
-
deleteSecrets: options.secrets?.deleteSecrets,
|
|
82
|
-
agentTools: {
|
|
83
|
-
tokenProvider
|
|
84
|
-
}
|
|
85
|
-
}),
|
|
89
|
+
provider: integrationProvider,
|
|
90
|
+
webhookProcessors: integrationProvider.webhookProcessors,
|
|
86
91
|
e2eRoutes: [
|
|
87
92
|
createGithubE2eRoutes({
|
|
88
93
|
getExistingGithubConnection,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/providers/github.ts"],"sourcesContent":["import {\n type IntegrationConnection as CoreIntegrationConnection,\n slugifyConnectionSlug,\n} from '@shipfox/api-integration-core-dto';\nimport type {ConnectGithubInstallationInput} from '@shipfox/api-integration-github';\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 recordDeliveryOnly,\n} from '#db/webhook-deliveries.js';\nimport {retryConnectionSlugCollision} from '#providers/connection-slug.js';\nimport type {\n IntegrationModuleParts,\n IntegrationProviderModule,\n IntegrationProviderModuleLoadOptions,\n} from '#providers/types.js';\n\n// Stable migration-tracking table name for the GitHub provider database. This\n// must NOT depend on the provider's position in the module `database` array. A\n// positional name would shift if a provider is flag-disabled and silently\n// re-run migrations against existing tables.\nconst GITHUB_MIGRATIONS_TABLE = '__drizzle_migrations_integrations_github';\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
|
|
1
|
+
{"version":3,"sources":["../../src/providers/github.ts"],"sourcesContent":["import {\n type IntegrationConnection as CoreIntegrationConnection,\n slugifyConnectionSlug,\n} from '@shipfox/api-integration-core-dto';\nimport type {ConnectGithubInstallationInput} from '@shipfox/api-integration-github';\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 recordDeliveryOnly,\n} from '#db/webhook-deliveries.js';\nimport {retryConnectionSlugCollision} from '#providers/connection-slug.js';\nimport type {\n IntegrationModuleParts,\n IntegrationProviderModule,\n IntegrationProviderModuleLoadOptions,\n} from '#providers/types.js';\n\n// Stable migration-tracking table name for the GitHub provider database. This\n// must NOT depend on the provider's position in the module `database` array. A\n// positional name would shift if a provider is flag-disabled and silently\n// re-run migrations against existing tables.\nconst GITHUB_MIGRATIONS_TABLE = '__drizzle_migrations_integrations_github';\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 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 migrationsTableName: GITHUB_MIGRATIONS_TABLE,\n },\n };\n}\n\nexport const githubProviderModule: IntegrationProviderModule = {\n id: 'github',\n enabled: config.INTEGRATIONS_ENABLE_GITHUB_PROVIDER,\n load: loadGithubModuleParts,\n};\n"],"names":["slugifyConnectionSlug","config","getIntegrationConnectionById","resolveUniqueConnectionSlug","upsertIntegrationConnection","db","publishIntegrationEventReceived","publishSourcePush","recordDeliveryOnly","retryConnectionSlugCollision","GITHUB_MIGRATIONS_TABLE","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","migrationsTableName","githubProviderModule","enabled","INTEGRATIONS_ENABLE_GITHUB_PROVIDER","load"],"mappings":"AAAA,SAEEA,qBAAqB,QAChB,oCAAoC;AAE3C,SAAQC,MAAM,QAAO,aAAa;AAClC,SACEC,4BAA4B,EAC5BC,2BAA2B,EAC3BC,2BAA2B,QACtB,qBAAqB;AAC5B,SAAQC,EAAE,QAAO,YAAY;AAC7B,SACEC,+BAA+B,EAC/BC,iBAAiB,EACjBC,kBAAkB,QACb,4BAA4B;AACnC,SAAQC,4BAA4B,QAAO,gCAAgC;AAO3E,8EAA8E;AAC9E,+EAA+E;AAC/E,0EAA0E;AAC1E,6CAA6C;AAC7C,MAAMC,0BAA0B;AAEhC,eAAeC,sBACbC,UAAgD,CAAC,CAAC;IAElD,MAAM,EACJC,qCAAqC,EACrCC,qBAAqB,EACrBC,+BAA+B,EAC/BC,+BAA+B,EAC/BC,qCAAqC,EACrCC,gCAAgC,EAChCb,IAAIc,QAAQ,EACZC,gBAAgBC,oBAAoB,EACpCC,wBAAwB,EACzB,GAAG,MAAM,MAAM,CAAC;IAEjB,MAAMC,gBAAgBV,sCAAsC;QAC1DX;QACAsB,aAAaZ,QAAQa,OAAO,EAAEC,SAC1B;YACEC,MAAM,OAAOC,aAAaC,iBACxB,AAAC,MAAMjB,QAAQa,OAAO,EAAEC,QAAQI,UAAU;oBACxCF;oBACAG,WAAWb,iCAAiCW;oBAC5CG,KAAK;gBACP,MAAO;YACTC,OAAO,OAAOL,aAAaC,gBAAgBK;gBACzC,MAAMtB,QAAQa,OAAO,EAAEC,QAAQS,WAAW;oBACxCP;oBACAG,WAAWb,iCAAiCW;oBAC5CO,QAAQ;wBAACF,UAAUnB,gCAAgCmB;oBAAS;gBAC9D;YACF;QACF,IACAG;IACN;IAEA,eAAeC,4BAA4BC,KAE1C;QACC,MAAMC,eAAe,MAAMvB,sCAAsCsB,MAAMV,cAAc;QACrF,IAAI,CAACW,cAAc,OAAOH;QAC1B,MAAMI,aAAa,MAAMvC,6BAA6BsC,aAAaE,YAAY;QAC/E,IAAI,CAACD,YAAY,OAAOJ;QACxB,OAAOI;IACT;IAEA,eAAeE,0BACbJ,KAAqC;QAErC,OAAO,MAAM9B,6BAA6B,IACxCJ,KAAKuC,WAAW,CAAC,OAAOC;gBACtB,MAAMC,WAAW9C,sBAAsB,CAAC,OAAO,EAAEuC,MAAMC,YAAY,CAACO,YAAY,EAAE,EAAE;oBAClFC,UAAU;gBACZ;gBACA,MAAMC,OAAO,MAAM9C,4BACjB;oBACEyB,aAAaW,MAAMX,WAAW;oBAC9BsB,UAAU;oBACVC,mBAAmBZ,MAAMV,cAAc;oBACvCiB;gBACF,GACA;oBAACD;gBAAE;gBAEL,MAAMJ,aAAa,MAAMrC,4BACvB;oBACEwB,aAAaW,MAAMX,WAAW;oBAC9BsB,UAAU;oBACVC,mBAAmBZ,MAAMV,cAAc;oBACvCoB;oBACAG,aAAab,MAAMa,WAAW;oBAC9BC,iBAAiB;gBACnB,GACA;oBAACR;gBAAE;gBAGL,MAAMvB,yBACJ;oBACEoB,cAAcD,WAAWa,EAAE;oBAC3B,GAAGf,MAAMC,YAAY;gBACvB,GACA;oBAACK;gBAAE;gBAGL,OAAOJ;YACT;IAEJ;IAEA,MAAMc,sBAAsBvC,gCAAgC;QAC1DsB;QACAK;QACArC;QACAC;QACAC;QACAN;QACAsD,QAAQnD;QACRoD,eAAe7C,QAAQa,OAAO,EAAEgC;QAChCC,YAAY;YAACnC;QAAa;QAC1B,GAAIX,QAAQ+C,gCAAgC,GACxC;YAACA,kCAAkC/C,QAAQ+C,gCAAgC;QAAA,IAC3E,CAAC,CAAC;IACR;IAEA,OAAO;QACLT,UAAUK;QACVK,mBAAmBL,oBAAoBK,iBAAiB;QACxDC,WAAW;YACT/C,sBAAsB;gBACpBwB;gBACAK;gBACAmB,wBAAwB;oBAAC;oBAAkB;iBAAc;YAC3D;SACD;QACDC,UAAU;YACR1D,IAAIc;YACJC,gBAAgBC;YAChB2C,qBAAqBtD;QACvB;IACF;AACF;AAEA,OAAO,MAAMuD,uBAAkD;IAC7DX,IAAI;IACJY,SAASjE,OAAOkE,mCAAmC;IACnDC,MAAMzD;AACR,EAAE"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"jira.d.ts","sourceRoot":"","sources":["../../src/providers/jira.ts"],"names":[],"mappings":"AAmBA,OAAO,KAAK,EAAyB,yBAAyB,EAAC,MAAM,qBAAqB,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;AAgJ3F,eAAO,MAAM,kBAAkB,EAAE,yBAIhC,CAAC"}
|
package/dist/providers/jira.js
CHANGED
|
@@ -102,7 +102,10 @@ async function loadJiraModuleParts(options = {}) {
|
|
|
102
102
|
pendingStore,
|
|
103
103
|
getExistingJiraConnection,
|
|
104
104
|
connectJiraInstallation,
|
|
105
|
-
disconnectJiraInstallation
|
|
105
|
+
disconnectJiraInstallation,
|
|
106
|
+
...options.requireActiveWorkspaceMembership ? {
|
|
107
|
+
requireActiveWorkspaceMembership: options.requireActiveWorkspaceMembership
|
|
108
|
+
} : {}
|
|
106
109
|
}
|
|
107
110
|
}),
|
|
108
111
|
database: {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/providers/jira.ts"],"sourcesContent":["import {\n type IntegrationConnection as CoreIntegrationConnection,\n slugifyConnectionSlug,\n} from '@shipfox/api-integration-core-dto';\nimport type {\n ConnectJiraInstallationInput,\n JiraPendingSelectionSecretsStore,\n JiraSecretsStore,\n} from '@shipfox/api-integration-jira';\nimport {config} from '#config.js';\nimport {\n deleteIntegrationConnection,\n getIntegrationConnectionById,\n resolveUniqueConnectionSlug,\n updateIntegrationConnectionLifecycleStatus,\n upsertIntegrationConnection,\n} from '#db/connections.js';\nimport {db} from '#db/db.js';\nimport {retryConnectionSlugCollision} from '#providers/connection-slug.js';\nimport type {IntegrationModuleParts, IntegrationProviderModule} from '#providers/types.js';\n\nconst JIRA_MIGRATIONS_TABLE = '__drizzle_migrations_integrations_jira';\nconst JIRA_SECRETS_NAMESPACE_PREFIX = 'system/integrations/jira/';\ntype IntegrationDb = ReturnType<typeof db>;\ntype IntegrationTx = Parameters<Parameters<IntegrationDb['transaction']>[0]>[0];\n\nasync function loadJiraModuleParts(\n options: Parameters<IntegrationProviderModule['load']>[0] = {},\n): Promise<IntegrationModuleParts> {\n const {\n createJiraIntegrationProvider,\n createJiraPendingSelectionStore,\n createJiraTokenStore,\n db: jiraDb,\n disconnectJiraInstallation: disconnectJiraInstallationRecords,\n getJiraInstallationByCloudId,\n migrationsPath,\n upsertJiraInstallation,\n } = await import('@shipfox/api-integration-jira');\n\n async function getExistingJiraConnection(input: {\n cloudId: string;\n }): Promise<CoreIntegrationConnection<'jira'> | undefined> {\n const installation = await getJiraInstallationByCloudId(input.cloudId);\n if (!installation) return undefined;\n return (await getIntegrationConnectionById(installation.connectionId)) as\n | CoreIntegrationConnection<'jira'>\n | undefined;\n }\n\n function connectJiraInstallation(\n input: ConnectJiraInstallationInput,\n ): Promise<CoreIntegrationConnection<'jira'>> {\n return retryConnectionSlugCollision(() =>\n db().transaction(async (tx) => {\n const slug = await resolveUniqueConnectionSlug(\n {\n workspaceId: input.workspaceId,\n provider: 'jira',\n externalAccountId: input.cloudId,\n baseSlug: slugifyConnectionSlug(`jira_${input.siteName || input.cloudId}`, {\n fallback: 'jira',\n }),\n },\n {tx},\n );\n const connection = await upsertIntegrationConnection(\n {\n workspaceId: input.workspaceId,\n provider: 'jira',\n externalAccountId: input.cloudId,\n slug,\n displayName: input.displayName,\n lifecycleStatus: 'active',\n },\n {tx},\n );\n await upsertJiraInstallation(\n {\n connectionId: connection.id,\n cloudId: input.cloudId,\n siteUrl: input.siteUrl,\n siteName: input.siteName,\n authorizingAccountId: input.authorizingAccountId,\n scopes: input.scopes,\n status: 'installed',\n tokenExpiresAt: input.tokenExpiresAt,\n },\n {tx},\n );\n return connection as CoreIntegrationConnection<'jira'>;\n }),\n );\n }\n\n async function disconnectJiraInstallation(input: {connectionId: string}): Promise<void> {\n await disconnectJiraInstallationRecords<IntegrationTx>({\n connectionId: input.connectionId,\n getConnection: getIntegrationConnectionById,\n deleteSecrets: (params) =>\n options.secrets?.jira?.deleteSecrets({\n ...params,\n namespace: jiraNamespaceSuffix(params.namespace),\n }) ?? Promise.resolve(0),\n transaction: (fn) => db().transaction((tx) => fn(tx)),\n deleteConnection: (params, transactionOptions) =>\n deleteIntegrationConnection({id: params.connectionId}, transactionOptions),\n });\n }\n\n const fallbackSecrets: JiraSecretsStore & JiraPendingSelectionSecretsStore = {\n getSecret: () => Promise.resolve(null),\n setSecrets: () => Promise.reject(new Error('Jira token storage is not configured')),\n deleteSecrets: () => Promise.resolve(0),\n };\n const secrets: JiraSecretsStore & JiraPendingSelectionSecretsStore = options.secrets?.jira\n ? {\n getSecret: (params) =>\n options.secrets?.jira?.getSecret({\n ...params,\n namespace: jiraNamespaceSuffix(params.namespace),\n }) ?? Promise.resolve(null),\n setSecrets: (params) =>\n options.secrets?.jira?.setSecrets({\n ...params,\n namespace: jiraNamespaceSuffix(params.namespace),\n }) ?? Promise.resolve(),\n deleteSecrets: (params) =>\n options.secrets?.jira?.deleteSecrets({\n ...params,\n namespace: jiraNamespaceSuffix(params.namespace),\n }) ?? Promise.resolve(0),\n }\n : fallbackSecrets;\n const tokenStore = createJiraTokenStore({\n resolveConnection: getIntegrationConnectionById,\n secrets,\n markConnectionError: async ({connectionId}) => {\n await updateIntegrationConnectionLifecycleStatus({\n id: connectionId,\n lifecycleStatus: 'error',\n });\n },\n });\n const pendingStore = createJiraPendingSelectionStore({secrets});\n\n return {\n provider: createJiraIntegrationProvider({\n routes: {\n tokenStore,\n pendingStore,\n getExistingJiraConnection,\n connectJiraInstallation,\n disconnectJiraInstallation,\n },\n }),\n database: {db: jiraDb, migrationsPath, migrationsTableName: JIRA_MIGRATIONS_TABLE},\n };\n}\n\nexport const jiraProviderModule: IntegrationProviderModule = {\n id: 'jira',\n enabled: config.INTEGRATIONS_ENABLE_JIRA_PROVIDER,\n load: loadJiraModuleParts,\n};\n\nfunction jiraNamespaceSuffix(namespace: string): string {\n if (!namespace.startsWith(JIRA_SECRETS_NAMESPACE_PREFIX)) {\n throw new Error('Jira provider attempted to access an unscoped secret namespace');\n }\n return namespace.slice(JIRA_SECRETS_NAMESPACE_PREFIX.length);\n}\n"],"names":["slugifyConnectionSlug","config","deleteIntegrationConnection","getIntegrationConnectionById","resolveUniqueConnectionSlug","updateIntegrationConnectionLifecycleStatus","upsertIntegrationConnection","db","retryConnectionSlugCollision","JIRA_MIGRATIONS_TABLE","JIRA_SECRETS_NAMESPACE_PREFIX","loadJiraModuleParts","options","createJiraIntegrationProvider","createJiraPendingSelectionStore","createJiraTokenStore","jiraDb","disconnectJiraInstallation","disconnectJiraInstallationRecords","getJiraInstallationByCloudId","migrationsPath","upsertJiraInstallation","getExistingJiraConnection","input","installation","cloudId","undefined","connectionId","connectJiraInstallation","transaction","tx","slug","workspaceId","provider","externalAccountId","baseSlug","siteName","fallback","connection","displayName","lifecycleStatus","id","siteUrl","authorizingAccountId","scopes","status","tokenExpiresAt","getConnection","deleteSecrets","params","secrets","jira","namespace","jiraNamespaceSuffix","Promise","resolve","fn","deleteConnection","transactionOptions","fallbackSecrets","getSecret","setSecrets","reject","Error","tokenStore","resolveConnection","markConnectionError","pendingStore","routes","database","migrationsTableName","jiraProviderModule","enabled","INTEGRATIONS_ENABLE_JIRA_PROVIDER","load","startsWith","slice","length"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../src/providers/jira.ts"],"sourcesContent":["import {\n type IntegrationConnection as CoreIntegrationConnection,\n slugifyConnectionSlug,\n} from '@shipfox/api-integration-core-dto';\nimport type {\n ConnectJiraInstallationInput,\n JiraPendingSelectionSecretsStore,\n JiraSecretsStore,\n} from '@shipfox/api-integration-jira';\nimport {config} from '#config.js';\nimport {\n deleteIntegrationConnection,\n getIntegrationConnectionById,\n resolveUniqueConnectionSlug,\n updateIntegrationConnectionLifecycleStatus,\n upsertIntegrationConnection,\n} from '#db/connections.js';\nimport {db} from '#db/db.js';\nimport {retryConnectionSlugCollision} from '#providers/connection-slug.js';\nimport type {IntegrationModuleParts, IntegrationProviderModule} from '#providers/types.js';\n\nconst JIRA_MIGRATIONS_TABLE = '__drizzle_migrations_integrations_jira';\nconst JIRA_SECRETS_NAMESPACE_PREFIX = 'system/integrations/jira/';\ntype IntegrationDb = ReturnType<typeof db>;\ntype IntegrationTx = Parameters<Parameters<IntegrationDb['transaction']>[0]>[0];\n\nasync function loadJiraModuleParts(\n options: Parameters<IntegrationProviderModule['load']>[0] = {},\n): Promise<IntegrationModuleParts> {\n const {\n createJiraIntegrationProvider,\n createJiraPendingSelectionStore,\n createJiraTokenStore,\n db: jiraDb,\n disconnectJiraInstallation: disconnectJiraInstallationRecords,\n getJiraInstallationByCloudId,\n migrationsPath,\n upsertJiraInstallation,\n } = await import('@shipfox/api-integration-jira');\n\n async function getExistingJiraConnection(input: {\n cloudId: string;\n }): Promise<CoreIntegrationConnection<'jira'> | undefined> {\n const installation = await getJiraInstallationByCloudId(input.cloudId);\n if (!installation) return undefined;\n return (await getIntegrationConnectionById(installation.connectionId)) as\n | CoreIntegrationConnection<'jira'>\n | undefined;\n }\n\n function connectJiraInstallation(\n input: ConnectJiraInstallationInput,\n ): Promise<CoreIntegrationConnection<'jira'>> {\n return retryConnectionSlugCollision(() =>\n db().transaction(async (tx) => {\n const slug = await resolveUniqueConnectionSlug(\n {\n workspaceId: input.workspaceId,\n provider: 'jira',\n externalAccountId: input.cloudId,\n baseSlug: slugifyConnectionSlug(`jira_${input.siteName || input.cloudId}`, {\n fallback: 'jira',\n }),\n },\n {tx},\n );\n const connection = await upsertIntegrationConnection(\n {\n workspaceId: input.workspaceId,\n provider: 'jira',\n externalAccountId: input.cloudId,\n slug,\n displayName: input.displayName,\n lifecycleStatus: 'active',\n },\n {tx},\n );\n await upsertJiraInstallation(\n {\n connectionId: connection.id,\n cloudId: input.cloudId,\n siteUrl: input.siteUrl,\n siteName: input.siteName,\n authorizingAccountId: input.authorizingAccountId,\n scopes: input.scopes,\n status: 'installed',\n tokenExpiresAt: input.tokenExpiresAt,\n },\n {tx},\n );\n return connection as CoreIntegrationConnection<'jira'>;\n }),\n );\n }\n\n async function disconnectJiraInstallation(input: {connectionId: string}): Promise<void> {\n await disconnectJiraInstallationRecords<IntegrationTx>({\n connectionId: input.connectionId,\n getConnection: getIntegrationConnectionById,\n deleteSecrets: (params) =>\n options.secrets?.jira?.deleteSecrets({\n ...params,\n namespace: jiraNamespaceSuffix(params.namespace),\n }) ?? Promise.resolve(0),\n transaction: (fn) => db().transaction((tx) => fn(tx)),\n deleteConnection: (params, transactionOptions) =>\n deleteIntegrationConnection({id: params.connectionId}, transactionOptions),\n });\n }\n\n const fallbackSecrets: JiraSecretsStore & JiraPendingSelectionSecretsStore = {\n getSecret: () => Promise.resolve(null),\n setSecrets: () => Promise.reject(new Error('Jira token storage is not configured')),\n deleteSecrets: () => Promise.resolve(0),\n };\n const secrets: JiraSecretsStore & JiraPendingSelectionSecretsStore = options.secrets?.jira\n ? {\n getSecret: (params) =>\n options.secrets?.jira?.getSecret({\n ...params,\n namespace: jiraNamespaceSuffix(params.namespace),\n }) ?? Promise.resolve(null),\n setSecrets: (params) =>\n options.secrets?.jira?.setSecrets({\n ...params,\n namespace: jiraNamespaceSuffix(params.namespace),\n }) ?? Promise.resolve(),\n deleteSecrets: (params) =>\n options.secrets?.jira?.deleteSecrets({\n ...params,\n namespace: jiraNamespaceSuffix(params.namespace),\n }) ?? Promise.resolve(0),\n }\n : fallbackSecrets;\n const tokenStore = createJiraTokenStore({\n resolveConnection: getIntegrationConnectionById,\n secrets,\n markConnectionError: async ({connectionId}) => {\n await updateIntegrationConnectionLifecycleStatus({\n id: connectionId,\n lifecycleStatus: 'error',\n });\n },\n });\n const pendingStore = createJiraPendingSelectionStore({secrets});\n\n return {\n provider: createJiraIntegrationProvider({\n routes: {\n tokenStore,\n pendingStore,\n getExistingJiraConnection,\n connectJiraInstallation,\n disconnectJiraInstallation,\n ...(options.requireActiveWorkspaceMembership\n ? {requireActiveWorkspaceMembership: options.requireActiveWorkspaceMembership}\n : {}),\n },\n }),\n database: {db: jiraDb, migrationsPath, migrationsTableName: JIRA_MIGRATIONS_TABLE},\n };\n}\n\nexport const jiraProviderModule: IntegrationProviderModule = {\n id: 'jira',\n enabled: config.INTEGRATIONS_ENABLE_JIRA_PROVIDER,\n load: loadJiraModuleParts,\n};\n\nfunction jiraNamespaceSuffix(namespace: string): string {\n if (!namespace.startsWith(JIRA_SECRETS_NAMESPACE_PREFIX)) {\n throw new Error('Jira provider attempted to access an unscoped secret namespace');\n }\n return namespace.slice(JIRA_SECRETS_NAMESPACE_PREFIX.length);\n}\n"],"names":["slugifyConnectionSlug","config","deleteIntegrationConnection","getIntegrationConnectionById","resolveUniqueConnectionSlug","updateIntegrationConnectionLifecycleStatus","upsertIntegrationConnection","db","retryConnectionSlugCollision","JIRA_MIGRATIONS_TABLE","JIRA_SECRETS_NAMESPACE_PREFIX","loadJiraModuleParts","options","createJiraIntegrationProvider","createJiraPendingSelectionStore","createJiraTokenStore","jiraDb","disconnectJiraInstallation","disconnectJiraInstallationRecords","getJiraInstallationByCloudId","migrationsPath","upsertJiraInstallation","getExistingJiraConnection","input","installation","cloudId","undefined","connectionId","connectJiraInstallation","transaction","tx","slug","workspaceId","provider","externalAccountId","baseSlug","siteName","fallback","connection","displayName","lifecycleStatus","id","siteUrl","authorizingAccountId","scopes","status","tokenExpiresAt","getConnection","deleteSecrets","params","secrets","jira","namespace","jiraNamespaceSuffix","Promise","resolve","fn","deleteConnection","transactionOptions","fallbackSecrets","getSecret","setSecrets","reject","Error","tokenStore","resolveConnection","markConnectionError","pendingStore","routes","requireActiveWorkspaceMembership","database","migrationsTableName","jiraProviderModule","enabled","INTEGRATIONS_ENABLE_JIRA_PROVIDER","load","startsWith","slice","length"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"linear.d.ts","sourceRoot":"","sources":["../../src/providers/linear.ts"],"names":[],"mappings":"AAkBA,OAAO,KAAK,EAAyB,yBAAyB,EAAC,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"linear.d.ts","sourceRoot":"","sources":["../../src/providers/linear.ts"],"names":[],"mappings":"AAkBA,OAAO,KAAK,EAAyB,yBAAyB,EAAC,MAAM,qBAAqB,CAAC;AAyK3F,eAAO,MAAM,oBAAoB,EAAE,yBAIlC,CAAC"}
|