@shipfox/api-projects 2.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 +2 -0
- package/.turbo/turbo-type$colon$emit.log +1 -0
- package/.turbo/turbo-type.log +1 -0
- package/CHANGELOG.md +117 -0
- package/LICENSE +21 -0
- package/dist/core/entities/index.d.ts +2 -0
- package/dist/core/entities/index.d.ts.map +1 -0
- package/dist/core/entities/index.js +3 -0
- package/dist/core/entities/index.js.map +1 -0
- package/dist/core/entities/project.d.ts +10 -0
- package/dist/core/entities/project.d.ts.map +1 -0
- package/dist/core/entities/project.js +3 -0
- package/dist/core/entities/project.js.map +1 -0
- package/dist/core/errors.d.ts +13 -0
- package/dist/core/errors.d.ts.map +1 -0
- package/dist/core/errors.js +20 -0
- package/dist/core/errors.js.map +1 -0
- package/dist/core/index.d.ts +5 -0
- package/dist/core/index.d.ts.map +1 -0
- package/dist/core/index.js +4 -0
- package/dist/core/index.js.map +1 -0
- package/dist/core/projects.d.ts +12 -0
- package/dist/core/projects.d.ts.map +1 -0
- package/dist/core/projects.js +62 -0
- package/dist/core/projects.js.map +1 -0
- package/dist/db/db.d.ts +763 -0
- package/dist/db/db.d.ts.map +1 -0
- package/dist/db/db.js +22 -0
- package/dist/db/db.js.map +1 -0
- package/dist/db/index.d.ts +8 -0
- package/dist/db/index.d.ts.map +1 -0
- package/dist/db/index.js +10 -0
- package/dist/db/index.js.map +1 -0
- package/dist/db/integration-event-dedup.d.ts +17 -0
- package/dist/db/integration-event-dedup.d.ts.map +1 -0
- package/dist/db/integration-event-dedup.js +27 -0
- package/dist/db/integration-event-dedup.js.map +1 -0
- package/dist/db/projects.d.ts +36 -0
- package/dist/db/projects.d.ts.map +1 -0
- package/dist/db/projects.js +84 -0
- package/dist/db/projects.js.map +1 -0
- package/dist/db/schema/common.d.ts +2 -0
- package/dist/db/schema/common.d.ts.map +1 -0
- package/dist/db/schema/common.js +4 -0
- package/dist/db/schema/common.js.map +1 -0
- package/dist/db/schema/integration-event-dedup.d.ts +59 -0
- package/dist/db/schema/integration-event-dedup.d.ts.map +1 -0
- package/dist/db/schema/integration-event-dedup.js +19 -0
- package/dist/db/schema/integration-event-dedup.js.map +1 -0
- package/dist/db/schema/outbox.d.ts +195 -0
- package/dist/db/schema/outbox.d.ts.map +1 -0
- package/dist/db/schema/outbox.js +5 -0
- package/dist/db/schema/outbox.js.map +1 -0
- package/dist/db/schema/projects.d.ts +131 -0
- package/dist/db/schema/projects.d.ts.map +1 -0
- package/dist/db/schema/projects.js +32 -0
- package/dist/db/schema/projects.js.map +1 -0
- package/dist/index.d.ts +12 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +59 -0
- package/dist/index.js.map +1 -0
- package/dist/metrics/index.d.ts +3 -0
- package/dist/metrics/index.d.ts.map +1 -0
- package/dist/metrics/index.js +4 -0
- package/dist/metrics/index.js.map +1 -0
- package/dist/metrics/instance.d.ts +4 -0
- package/dist/metrics/instance.d.ts.map +1 -0
- package/dist/metrics/instance.js +25 -0
- package/dist/metrics/instance.js.map +1 -0
- package/dist/metrics/service.d.ts +2 -0
- package/dist/metrics/service.d.ts.map +1 -0
- package/dist/metrics/service.js +15 -0
- package/dist/metrics/service.js.map +1 -0
- package/dist/presentation/auth/require-project-access.d.ts +12 -0
- package/dist/presentation/auth/require-project-access.d.ts.map +1 -0
- package/dist/presentation/auth/require-project-access.js +25 -0
- package/dist/presentation/auth/require-project-access.js.map +1 -0
- package/dist/presentation/dto/index.d.ts +2 -0
- package/dist/presentation/dto/index.d.ts.map +1 -0
- package/dist/presentation/dto/index.js +3 -0
- package/dist/presentation/dto/index.js.map +1 -0
- package/dist/presentation/dto/project.d.ts +13 -0
- package/dist/presentation/dto/project.d.ts.map +1 -0
- package/dist/presentation/dto/project.js +15 -0
- package/dist/presentation/dto/project.js.map +1 -0
- package/dist/presentation/e2eRoutes/create-project.d.ts +2 -0
- package/dist/presentation/e2eRoutes/create-project.d.ts.map +1 -0
- package/dist/presentation/e2eRoutes/create-project.js +45 -0
- package/dist/presentation/e2eRoutes/create-project.js.map +1 -0
- package/dist/presentation/e2eRoutes/index.d.ts +3 -0
- package/dist/presentation/e2eRoutes/index.d.ts.map +1 -0
- package/dist/presentation/e2eRoutes/index.js +9 -0
- package/dist/presentation/e2eRoutes/index.js.map +1 -0
- package/dist/presentation/index.d.ts +3 -0
- package/dist/presentation/index.d.ts.map +1 -0
- package/dist/presentation/index.js +4 -0
- package/dist/presentation/index.js.map +1 -0
- package/dist/presentation/routes/create-project.d.ts +3 -0
- package/dist/presentation/routes/create-project.d.ts.map +1 -0
- package/dist/presentation/routes/create-project.js +94 -0
- package/dist/presentation/routes/create-project.js.map +1 -0
- package/dist/presentation/routes/cursor.d.ts +2 -0
- package/dist/presentation/routes/cursor.d.ts.map +1 -0
- package/dist/presentation/routes/cursor.js +3 -0
- package/dist/presentation/routes/cursor.js.map +1 -0
- package/dist/presentation/routes/get-project.d.ts +2 -0
- package/dist/presentation/routes/get-project.d.ts.map +1 -0
- package/dist/presentation/routes/get-project.js +30 -0
- package/dist/presentation/routes/get-project.js.map +1 -0
- package/dist/presentation/routes/index.d.ts +4 -0
- package/dist/presentation/routes/index.d.ts.map +1 -0
- package/dist/presentation/routes/index.js +17 -0
- package/dist/presentation/routes/index.js.map +1 -0
- package/dist/presentation/routes/list-projects.d.ts +2 -0
- package/dist/presentation/routes/list-projects.d.ts.map +1 -0
- package/dist/presentation/routes/list-projects.js +43 -0
- package/dist/presentation/routes/list-projects.js.map +1 -0
- package/dist/presentation/subscribers/index.d.ts +2 -0
- package/dist/presentation/subscribers/index.d.ts.map +1 -0
- package/dist/presentation/subscribers/index.js +3 -0
- package/dist/presentation/subscribers/index.js.map +1 -0
- package/dist/presentation/subscribers/on-source-commit-pushed.d.ts +4 -0
- package/dist/presentation/subscribers/on-source-commit-pushed.d.ts.map +1 -0
- package/dist/presentation/subscribers/on-source-commit-pushed.js +54 -0
- package/dist/presentation/subscribers/on-source-commit-pushed.js.map +1 -0
- package/dist/temporal/activities/index.d.ts +5 -0
- package/dist/temporal/activities/index.d.ts.map +1 -0
- package/dist/temporal/activities/index.js +8 -0
- package/dist/temporal/activities/index.js.map +1 -0
- package/dist/temporal/activities/prune-integration-event-dedup.d.ts +4 -0
- package/dist/temporal/activities/prune-integration-event-dedup.d.ts.map +1 -0
- package/dist/temporal/activities/prune-integration-event-dedup.js +11 -0
- package/dist/temporal/activities/prune-integration-event-dedup.js.map +1 -0
- package/dist/temporal/constants.d.ts +3 -0
- package/dist/temporal/constants.d.ts.map +1 -0
- package/dist/temporal/constants.js +4 -0
- package/dist/temporal/constants.js.map +1 -0
- package/dist/temporal/workflows/index.d.ts +2 -0
- package/dist/temporal/workflows/index.d.ts.map +1 -0
- package/dist/temporal/workflows/index.js +3 -0
- package/dist/temporal/workflows/index.js.map +1 -0
- package/dist/temporal/workflows/prune-integration-event-dedup-cron.d.ts +2 -0
- package/dist/temporal/workflows/prune-integration-event-dedup-cron.d.ts.map +1 -0
- package/dist/temporal/workflows/prune-integration-event-dedup-cron.js +14 -0
- package/dist/temporal/workflows/prune-integration-event-dedup-cron.js.map +1 -0
- package/dist/tsconfig.test.tsbuildinfo +1 -0
- package/drizzle/0000_initial.sql +37 -0
- package/drizzle/meta/0000_snapshot.json +307 -0
- package/drizzle/meta/_journal.json +13 -0
- package/drizzle.config.ts +7 -0
- package/package.json +76 -0
- package/src/core/entities/index.ts +1 -0
- package/src/core/entities/project.ts +9 -0
- package/src/core/errors.ts +26 -0
- package/src/core/index.ts +8 -0
- package/src/core/projects.test.ts +142 -0
- package/src/core/projects.ts +97 -0
- package/src/db/db.ts +22 -0
- package/src/db/index.ts +26 -0
- package/src/db/integration-event-dedup.ts +45 -0
- package/src/db/projects.test.ts +22 -0
- package/src/db/projects.ts +158 -0
- package/src/db/schema/common.ts +3 -0
- package/src/db/schema/integration-event-dedup.ts +15 -0
- package/src/db/schema/outbox.ts +4 -0
- package/src/db/schema/projects.ts +39 -0
- package/src/index.ts +71 -0
- package/src/metrics/index.ts +2 -0
- package/src/metrics/instance.ts +34 -0
- package/src/metrics/service.ts +17 -0
- package/src/presentation/auth/require-project-access.ts +29 -0
- package/src/presentation/dto/index.ts +1 -0
- package/src/presentation/dto/project.ts +15 -0
- package/src/presentation/e2eRoutes/create-project.test.ts +119 -0
- package/src/presentation/e2eRoutes/create-project.ts +50 -0
- package/src/presentation/e2eRoutes/index.ts +7 -0
- package/src/presentation/index.ts +2 -0
- package/src/presentation/routes/create-project.ts +102 -0
- package/src/presentation/routes/cursor.ts +5 -0
- package/src/presentation/routes/get-project.ts +24 -0
- package/src/presentation/routes/index.ts +14 -0
- package/src/presentation/routes/list-projects.ts +34 -0
- package/src/presentation/routes/projects.test.ts +266 -0
- package/src/presentation/subscribers/index.ts +1 -0
- package/src/presentation/subscribers/on-source-commit-pushed.test.ts +149 -0
- package/src/presentation/subscribers/on-source-commit-pushed.ts +64 -0
- package/src/temporal/activities/index.ts +7 -0
- package/src/temporal/activities/prune-integration-event-dedup.test.ts +50 -0
- package/src/temporal/activities/prune-integration-event-dedup.ts +9 -0
- package/src/temporal/constants.ts +3 -0
- package/src/temporal/workflows/index.ts +1 -0
- package/src/temporal/workflows/prune-integration-event-dedup-cron.ts +15 -0
- package/test/env.ts +14 -0
- package/test/factories/project.ts +24 -0
- package/test/globalSetup.ts +17 -0
- package/test/index.ts +1 -0
- package/test/setup.ts +17 -0
- package/tsconfig.build.json +9 -0
- package/tsconfig.build.tsbuildinfo +1 -0
- package/tsconfig.json +3 -0
- package/tsconfig.test.json +8 -0
- package/vitest.config.ts +12 -0
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import { AUTH_USER, requireUserContext, requireWorkspaceAccess } from '@shipfox/api-auth-context';
|
|
2
|
+
import { IntegrationCapabilityUnavailableError, IntegrationConnectionInactiveError, IntegrationConnectionNotFoundError, IntegrationConnectionWorkspaceMismatchError, IntegrationProviderError, IntegrationProviderUnavailableError } from '@shipfox/api-integration-core';
|
|
3
|
+
import { createProjectBodySchema, projectResponseSchema } from '@shipfox/api-projects-dto';
|
|
4
|
+
import { ClientError, defineRoute } from '@shipfox/node-fastify';
|
|
5
|
+
import { createProjectFromSource, ProjectAlreadyExistsError } from '#core/index.js';
|
|
6
|
+
import { toProjectDto } from '#presentation/dto/index.js';
|
|
7
|
+
function providerStatus(reason) {
|
|
8
|
+
if (reason === 'rate-limited') return 429;
|
|
9
|
+
if (reason === 'timeout' || reason === 'provider-unavailable') return 503;
|
|
10
|
+
return 422;
|
|
11
|
+
}
|
|
12
|
+
function isProviderError(error) {
|
|
13
|
+
return error instanceof IntegrationProviderError || error instanceof Error && 'reason' in error && typeof error.reason === 'string' && (error.reason === 'repository-not-found' || error.reason === 'access-denied' || error.reason === 'rate-limited' || error.reason === 'timeout' || error.reason === 'provider-unavailable' || error.reason === 'malformed-provider-response');
|
|
14
|
+
}
|
|
15
|
+
export function createProjectRoute(sourceControl) {
|
|
16
|
+
return defineRoute({
|
|
17
|
+
method: 'POST',
|
|
18
|
+
path: '/',
|
|
19
|
+
auth: AUTH_USER,
|
|
20
|
+
description: 'Create a project bound to a source repository.',
|
|
21
|
+
schema: {
|
|
22
|
+
body: createProjectBodySchema,
|
|
23
|
+
response: {
|
|
24
|
+
201: projectResponseSchema
|
|
25
|
+
}
|
|
26
|
+
},
|
|
27
|
+
errorHandler: (error)=>{
|
|
28
|
+
if (error instanceof IntegrationConnectionNotFoundError) {
|
|
29
|
+
throw new ClientError(error.message, 'source-connection-not-found', {
|
|
30
|
+
status: 404
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
if (error instanceof IntegrationConnectionWorkspaceMismatchError) {
|
|
34
|
+
throw new ClientError(error.message, 'forbidden', {
|
|
35
|
+
status: 403
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
if (error instanceof IntegrationConnectionInactiveError) {
|
|
39
|
+
throw new ClientError(error.message, 'source-connection-inactive', {
|
|
40
|
+
status: 422
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
if (error instanceof IntegrationProviderUnavailableError) {
|
|
44
|
+
throw new ClientError(error.message, 'integration-provider-unavailable', {
|
|
45
|
+
status: 422
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
if (error instanceof IntegrationCapabilityUnavailableError) {
|
|
49
|
+
throw new ClientError(error.message, 'integration-capability-unavailable', {
|
|
50
|
+
status: 422
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
if (error instanceof ProjectAlreadyExistsError) {
|
|
54
|
+
throw new ClientError(error.message, 'project-already-exists', {
|
|
55
|
+
details: {
|
|
56
|
+
existing_project_id: error.existingProjectId,
|
|
57
|
+
source_connection_id: error.sourceConnectionId,
|
|
58
|
+
source_external_repository_id: error.sourceExternalRepositoryId
|
|
59
|
+
},
|
|
60
|
+
status: 409
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
if (isProviderError(error)) {
|
|
64
|
+
throw new ClientError(error.message, error.reason, {
|
|
65
|
+
details: {
|
|
66
|
+
retry_after_seconds: error.retryAfterSeconds
|
|
67
|
+
},
|
|
68
|
+
status: providerStatus(error.reason)
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
throw error;
|
|
72
|
+
},
|
|
73
|
+
handler: async (request, reply)=>{
|
|
74
|
+
const { workspace_id: workspaceId, name, source } = request.body;
|
|
75
|
+
const actor = requireUserContext(request);
|
|
76
|
+
requireWorkspaceAccess({
|
|
77
|
+
request,
|
|
78
|
+
workspaceId
|
|
79
|
+
});
|
|
80
|
+
const project = await createProjectFromSource({
|
|
81
|
+
actorId: actor.userId,
|
|
82
|
+
workspaceId,
|
|
83
|
+
name,
|
|
84
|
+
sourceConnectionId: source.connection_id,
|
|
85
|
+
sourceExternalRepositoryId: source.external_repository_id,
|
|
86
|
+
sourceControl
|
|
87
|
+
});
|
|
88
|
+
reply.status(201);
|
|
89
|
+
return toProjectDto(project);
|
|
90
|
+
}
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
//# sourceMappingURL=create-project.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/presentation/routes/create-project.ts"],"sourcesContent":["import {AUTH_USER, requireUserContext, requireWorkspaceAccess} from '@shipfox/api-auth-context';\nimport {\n IntegrationCapabilityUnavailableError,\n IntegrationConnectionInactiveError,\n IntegrationConnectionNotFoundError,\n IntegrationConnectionWorkspaceMismatchError,\n IntegrationProviderError,\n type IntegrationProviderErrorReason,\n IntegrationProviderUnavailableError,\n type IntegrationSourceControlService,\n} from '@shipfox/api-integration-core';\nimport {createProjectBodySchema, projectResponseSchema} from '@shipfox/api-projects-dto';\nimport {ClientError, defineRoute} from '@shipfox/node-fastify';\nimport {createProjectFromSource, ProjectAlreadyExistsError} from '#core/index.js';\nimport {toProjectDto} from '#presentation/dto/index.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 === 'access-denied' ||\n error.reason === 'rate-limited' ||\n error.reason === 'timeout' ||\n error.reason === 'provider-unavailable' ||\n error.reason === 'malformed-provider-response'))\n );\n}\n\nexport function createProjectRoute(sourceControl: IntegrationSourceControlService) {\n return defineRoute({\n method: 'POST',\n path: '/',\n auth: AUTH_USER,\n description: 'Create a project bound to a source repository.',\n schema: {\n body: createProjectBodySchema,\n response: {\n 201: projectResponseSchema,\n },\n },\n errorHandler: (error) => {\n if (error instanceof IntegrationConnectionNotFoundError) {\n throw new ClientError(error.message, 'source-connection-not-found', {status: 404});\n }\n if (error instanceof IntegrationConnectionWorkspaceMismatchError) {\n throw new ClientError(error.message, 'forbidden', {status: 403});\n }\n if (error instanceof IntegrationConnectionInactiveError) {\n throw new ClientError(error.message, 'source-connection-inactive', {status: 422});\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 ProjectAlreadyExistsError) {\n throw new ClientError(error.message, 'project-already-exists', {\n details: {\n existing_project_id: error.existingProjectId,\n source_connection_id: error.sourceConnectionId,\n source_external_repository_id: error.sourceExternalRepositoryId,\n },\n status: 409,\n });\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 handler: async (request, reply) => {\n const {workspace_id: workspaceId, name, source} = request.body;\n const actor = requireUserContext(request);\n\n requireWorkspaceAccess({request, workspaceId});\n const project = await createProjectFromSource({\n actorId: actor.userId,\n workspaceId,\n name,\n sourceConnectionId: source.connection_id,\n sourceExternalRepositoryId: source.external_repository_id,\n sourceControl,\n });\n\n reply.status(201);\n return toProjectDto(project);\n },\n });\n}\n"],"names":["AUTH_USER","requireUserContext","requireWorkspaceAccess","IntegrationCapabilityUnavailableError","IntegrationConnectionInactiveError","IntegrationConnectionNotFoundError","IntegrationConnectionWorkspaceMismatchError","IntegrationProviderError","IntegrationProviderUnavailableError","createProjectBodySchema","projectResponseSchema","ClientError","defineRoute","createProjectFromSource","ProjectAlreadyExistsError","toProjectDto","providerStatus","reason","isProviderError","error","Error","createProjectRoute","sourceControl","method","path","auth","description","schema","body","response","errorHandler","message","status","details","existing_project_id","existingProjectId","source_connection_id","sourceConnectionId","source_external_repository_id","sourceExternalRepositoryId","retry_after_seconds","retryAfterSeconds","handler","request","reply","workspace_id","workspaceId","name","source","actor","project","actorId","userId","connection_id","external_repository_id"],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cursor.d.ts","sourceRoot":"","sources":["../../../src/presentation/routes/cursor.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,uBAAuB,IAAI,mBAAmB,EAC9C,uBAAuB,IAAI,mBAAmB,EAC9C,KAAK,iBAAiB,IAAI,aAAa,GACxC,MAAM,uBAAuB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/presentation/routes/cursor.ts"],"sourcesContent":["export {\n decodeTimestampIdCursor as decodeProjectCursor,\n encodeTimestampIdCursor as encodeProjectCursor,\n type TimestampIdCursor as ProjectCursor,\n} from '@shipfox/node-drizzle';\n"],"names":["decodeTimestampIdCursor","decodeProjectCursor","encodeTimestampIdCursor","encodeProjectCursor"],"mappings":"AAAA,SACEA,2BAA2BC,mBAAmB,EAC9CC,2BAA2BC,mBAAmB,QAEzC,wBAAwB"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"get-project.d.ts","sourceRoot":"","sources":["../../../src/presentation/routes/get-project.ts"],"names":[],"mappings":"AAOA,eAAO,MAAM,eAAe,iDAgB1B,CAAC"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { AUTH_USER } from '@shipfox/api-auth-context';
|
|
2
|
+
import { projectResponseSchema } from '@shipfox/api-projects-dto';
|
|
3
|
+
import { defineRoute } from '@shipfox/node-fastify';
|
|
4
|
+
import { z } from 'zod';
|
|
5
|
+
import { requireProjectAccess } from '#presentation/auth/require-project-access.js';
|
|
6
|
+
import { toProjectDto } from '#presentation/dto/index.js';
|
|
7
|
+
export const getProjectRoute = defineRoute({
|
|
8
|
+
method: 'GET',
|
|
9
|
+
path: '/:projectId',
|
|
10
|
+
auth: AUTH_USER,
|
|
11
|
+
description: 'Get a project.',
|
|
12
|
+
schema: {
|
|
13
|
+
params: z.object({
|
|
14
|
+
projectId: z.string().uuid()
|
|
15
|
+
}),
|
|
16
|
+
response: {
|
|
17
|
+
200: projectResponseSchema
|
|
18
|
+
}
|
|
19
|
+
},
|
|
20
|
+
handler: async (request)=>{
|
|
21
|
+
const { projectId } = request.params;
|
|
22
|
+
const { project } = await requireProjectAccess({
|
|
23
|
+
request,
|
|
24
|
+
projectId
|
|
25
|
+
});
|
|
26
|
+
return toProjectDto(project);
|
|
27
|
+
}
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
//# sourceMappingURL=get-project.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/presentation/routes/get-project.ts"],"sourcesContent":["import {AUTH_USER} from '@shipfox/api-auth-context';\nimport {projectResponseSchema} from '@shipfox/api-projects-dto';\nimport {defineRoute} from '@shipfox/node-fastify';\nimport {z} from 'zod';\nimport {requireProjectAccess} from '#presentation/auth/require-project-access.js';\nimport {toProjectDto} from '#presentation/dto/index.js';\n\nexport const getProjectRoute = defineRoute({\n method: 'GET',\n path: '/:projectId',\n auth: AUTH_USER,\n description: 'Get a project.',\n schema: {\n params: z.object({projectId: z.string().uuid()}),\n response: {\n 200: projectResponseSchema,\n },\n },\n handler: async (request) => {\n const {projectId} = request.params;\n const {project} = await requireProjectAccess({request, projectId});\n return toProjectDto(project);\n },\n});\n"],"names":["AUTH_USER","projectResponseSchema","defineRoute","z","requireProjectAccess","toProjectDto","getProjectRoute","method","path","auth","description","schema","params","object","projectId","string","uuid","response","handler","request","project"],"mappings":"AAAA,SAAQA,SAAS,QAAO,4BAA4B;AACpD,SAAQC,qBAAqB,QAAO,4BAA4B;AAChE,SAAQC,WAAW,QAAO,wBAAwB;AAClD,SAAQC,CAAC,QAAO,MAAM;AACtB,SAAQC,oBAAoB,QAAO,+CAA+C;AAClF,SAAQC,YAAY,QAAO,6BAA6B;AAExD,OAAO,MAAMC,kBAAkBJ,YAAY;IACzCK,QAAQ;IACRC,MAAM;IACNC,MAAMT;IACNU,aAAa;IACbC,QAAQ;QACNC,QAAQT,EAAEU,MAAM,CAAC;YAACC,WAAWX,EAAEY,MAAM,GAAGC,IAAI;QAAE;QAC9CC,UAAU;YACR,KAAKhB;QACP;IACF;IACAiB,SAAS,OAAOC;QACd,MAAM,EAACL,SAAS,EAAC,GAAGK,QAAQP,MAAM;QAClC,MAAM,EAACQ,OAAO,EAAC,GAAG,MAAMhB,qBAAqB;YAACe;YAASL;QAAS;QAChE,OAAOT,aAAae;IACtB;AACF,GAAG"}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { IntegrationSourceControlService } from '@shipfox/api-integration-core';
|
|
2
|
+
import type { RouteGroup } from '@shipfox/node-fastify';
|
|
3
|
+
export declare function createProjectRoutes(sourceControl: IntegrationSourceControlService): RouteGroup[];
|
|
4
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/presentation/routes/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,+BAA+B,EAAC,MAAM,+BAA+B,CAAC;AACnF,OAAO,KAAK,EAAC,UAAU,EAAC,MAAM,uBAAuB,CAAC;AAKtD,wBAAgB,mBAAmB,CAAC,aAAa,EAAE,+BAA+B,GAAG,UAAU,EAAE,CAOhG"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { createProjectRoute } from './create-project.js';
|
|
2
|
+
import { getProjectRoute } from './get-project.js';
|
|
3
|
+
import { listProjectsRoute } from './list-projects.js';
|
|
4
|
+
export function createProjectRoutes(sourceControl) {
|
|
5
|
+
return [
|
|
6
|
+
{
|
|
7
|
+
prefix: '/projects',
|
|
8
|
+
routes: [
|
|
9
|
+
createProjectRoute(sourceControl),
|
|
10
|
+
listProjectsRoute,
|
|
11
|
+
getProjectRoute
|
|
12
|
+
]
|
|
13
|
+
}
|
|
14
|
+
];
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/presentation/routes/index.ts"],"sourcesContent":["import type {IntegrationSourceControlService} from '@shipfox/api-integration-core';\nimport type {RouteGroup} from '@shipfox/node-fastify';\nimport {createProjectRoute} from './create-project.js';\nimport {getProjectRoute} from './get-project.js';\nimport {listProjectsRoute} from './list-projects.js';\n\nexport function createProjectRoutes(sourceControl: IntegrationSourceControlService): RouteGroup[] {\n return [\n {\n prefix: '/projects',\n routes: [createProjectRoute(sourceControl), listProjectsRoute, getProjectRoute],\n },\n ];\n}\n"],"names":["createProjectRoute","getProjectRoute","listProjectsRoute","createProjectRoutes","sourceControl","prefix","routes"],"mappings":"AAEA,SAAQA,kBAAkB,QAAO,sBAAsB;AACvD,SAAQC,eAAe,QAAO,mBAAmB;AACjD,SAAQC,iBAAiB,QAAO,qBAAqB;AAErD,OAAO,SAASC,oBAAoBC,aAA8C;IAChF,OAAO;QACL;YACEC,QAAQ;YACRC,QAAQ;gBAACN,mBAAmBI;gBAAgBF;gBAAmBD;aAAgB;QACjF;KACD;AACH"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"list-projects.d.ts","sourceRoot":"","sources":["../../../src/presentation/routes/list-projects.ts"],"names":[],"mappings":"AAOA,eAAO,MAAM,iBAAiB,iDA0B5B,CAAC"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { AUTH_USER, requireWorkspaceAccess } from '@shipfox/api-auth-context';
|
|
2
|
+
import { listProjectsQuerySchema, listProjectsResponseSchema } from '@shipfox/api-projects-dto';
|
|
3
|
+
import { ClientError, defineRoute } from '@shipfox/node-fastify';
|
|
4
|
+
import { listProjects } from '#db/index.js';
|
|
5
|
+
import { toProjectDto } from '#presentation/dto/index.js';
|
|
6
|
+
import { decodeProjectCursor, encodeProjectCursor } from './cursor.js';
|
|
7
|
+
export const listProjectsRoute = defineRoute({
|
|
8
|
+
method: 'GET',
|
|
9
|
+
path: '/',
|
|
10
|
+
auth: AUTH_USER,
|
|
11
|
+
description: 'List projects in a workspace.',
|
|
12
|
+
schema: {
|
|
13
|
+
querystring: listProjectsQuerySchema,
|
|
14
|
+
response: {
|
|
15
|
+
200: listProjectsResponseSchema
|
|
16
|
+
}
|
|
17
|
+
},
|
|
18
|
+
handler: async (request)=>{
|
|
19
|
+
const { workspace_id: workspaceId, limit, cursor, search } = request.query;
|
|
20
|
+
const decodedCursor = decodeProjectCursor(cursor);
|
|
21
|
+
if (cursor && !decodedCursor) {
|
|
22
|
+
throw new ClientError('Invalid cursor', 'invalid-cursor', {
|
|
23
|
+
status: 400
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
requireWorkspaceAccess({
|
|
27
|
+
request,
|
|
28
|
+
workspaceId
|
|
29
|
+
});
|
|
30
|
+
const result = await listProjects({
|
|
31
|
+
workspaceId,
|
|
32
|
+
limit,
|
|
33
|
+
cursor: decodedCursor,
|
|
34
|
+
search
|
|
35
|
+
});
|
|
36
|
+
return {
|
|
37
|
+
projects: result.projects.map(toProjectDto),
|
|
38
|
+
next_cursor: result.nextCursor ? encodeProjectCursor(result.nextCursor) : null
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
//# sourceMappingURL=list-projects.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/presentation/routes/list-projects.ts"],"sourcesContent":["import {AUTH_USER, requireWorkspaceAccess} from '@shipfox/api-auth-context';\nimport {listProjectsQuerySchema, listProjectsResponseSchema} from '@shipfox/api-projects-dto';\nimport {ClientError, defineRoute} from '@shipfox/node-fastify';\nimport {listProjects} from '#db/index.js';\nimport {toProjectDto} from '#presentation/dto/index.js';\nimport {decodeProjectCursor, encodeProjectCursor} from './cursor.js';\n\nexport const listProjectsRoute = defineRoute({\n method: 'GET',\n path: '/',\n auth: AUTH_USER,\n description: 'List projects in a workspace.',\n schema: {\n querystring: listProjectsQuerySchema,\n response: {\n 200: listProjectsResponseSchema,\n },\n },\n handler: async (request) => {\n const {workspace_id: workspaceId, limit, cursor, search} = request.query;\n const decodedCursor = decodeProjectCursor(cursor);\n if (cursor && !decodedCursor) {\n throw new ClientError('Invalid cursor', 'invalid-cursor', {status: 400});\n }\n\n requireWorkspaceAccess({request, workspaceId});\n const result = await listProjects({workspaceId, limit, cursor: decodedCursor, search});\n\n return {\n projects: result.projects.map(toProjectDto),\n next_cursor: result.nextCursor ? encodeProjectCursor(result.nextCursor) : null,\n };\n },\n});\n"],"names":["AUTH_USER","requireWorkspaceAccess","listProjectsQuerySchema","listProjectsResponseSchema","ClientError","defineRoute","listProjects","toProjectDto","decodeProjectCursor","encodeProjectCursor","listProjectsRoute","method","path","auth","description","schema","querystring","response","handler","request","workspace_id","workspaceId","limit","cursor","search","query","decodedCursor","status","result","projects","map","next_cursor","nextCursor"],"mappings":"AAAA,SAAQA,SAAS,EAAEC,sBAAsB,QAAO,4BAA4B;AAC5E,SAAQC,uBAAuB,EAAEC,0BAA0B,QAAO,4BAA4B;AAC9F,SAAQC,WAAW,EAAEC,WAAW,QAAO,wBAAwB;AAC/D,SAAQC,YAAY,QAAO,eAAe;AAC1C,SAAQC,YAAY,QAAO,6BAA6B;AACxD,SAAQC,mBAAmB,EAAEC,mBAAmB,QAAO,cAAc;AAErE,OAAO,MAAMC,oBAAoBL,YAAY;IAC3CM,QAAQ;IACRC,MAAM;IACNC,MAAMb;IACNc,aAAa;IACbC,QAAQ;QACNC,aAAad;QACbe,UAAU;YACR,KAAKd;QACP;IACF;IACAe,SAAS,OAAOC;QACd,MAAM,EAACC,cAAcC,WAAW,EAAEC,KAAK,EAAEC,MAAM,EAAEC,MAAM,EAAC,GAAGL,QAAQM,KAAK;QACxE,MAAMC,gBAAgBlB,oBAAoBe;QAC1C,IAAIA,UAAU,CAACG,eAAe;YAC5B,MAAM,IAAItB,YAAY,kBAAkB,kBAAkB;gBAACuB,QAAQ;YAAG;QACxE;QAEA1B,uBAAuB;YAACkB;YAASE;QAAW;QAC5C,MAAMO,SAAS,MAAMtB,aAAa;YAACe;YAAaC;YAAOC,QAAQG;YAAeF;QAAM;QAEpF,OAAO;YACLK,UAAUD,OAAOC,QAAQ,CAACC,GAAG,CAACvB;YAC9BwB,aAAaH,OAAOI,UAAU,GAAGvB,oBAAoBmB,OAAOI,UAAU,IAAI;QAC5E;IACF;AACF,GAAG"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/presentation/subscribers/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,oBAAoB,EAAC,MAAM,8BAA8B,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/presentation/subscribers/index.ts"],"sourcesContent":["export {onSourceCommitPushed} from './on-source-commit-pushed.js';\n"],"names":["onSourceCommitPushed"],"mappings":"AAAA,SAAQA,oBAAoB,QAAO,+BAA+B"}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { IntegrationSourceCommitPushedEvent } from '@shipfox/api-integration-core-dto';
|
|
2
|
+
import { type DomainEvent } from '@shipfox/node-outbox';
|
|
3
|
+
export declare function onSourceCommitPushed(payload: IntegrationSourceCommitPushedEvent, event: DomainEvent<IntegrationSourceCommitPushedEvent>): Promise<void>;
|
|
4
|
+
//# sourceMappingURL=on-source-commit-pushed.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"on-source-commit-pushed.d.ts","sourceRoot":"","sources":["../../../src/presentation/subscribers/on-source-commit-pushed.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,kCAAkC,EAAC,MAAM,mCAAmC,CAAC;AAG1F,OAAO,EAAC,KAAK,WAAW,EAAmB,MAAM,sBAAsB,CAAC;AAOxE,wBAAsB,oBAAoB,CACxC,OAAO,EAAE,kCAAkC,EAC3C,KAAK,EAAE,WAAW,CAAC,kCAAkC,CAAC,GACrD,OAAO,CAAC,IAAI,CAAC,CAkDf"}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { PROJECT_SOURCE_COMMIT_OBSERVED } from '@shipfox/api-projects-dto';
|
|
2
|
+
import { logger } from '@shipfox/node-opentelemetry';
|
|
3
|
+
import { writeOutboxEvent } from '@shipfox/node-outbox';
|
|
4
|
+
import { db } from '#db/db.js';
|
|
5
|
+
import { recordIntegrationEventForProject } from '#db/integration-event-dedup.js';
|
|
6
|
+
import { getProjectBySource } from '#db/projects.js';
|
|
7
|
+
import { projectsOutbox } from '#db/schema/outbox.js';
|
|
8
|
+
import { recordSourceCommitPushed } from '#metrics/instance.js';
|
|
9
|
+
export async function onSourceCommitPushed(payload, event) {
|
|
10
|
+
const { provider, workspaceId, connectionId, push } = payload;
|
|
11
|
+
// Projects only track the default branch; other branches are someone else's policy.
|
|
12
|
+
if (!push.isDefaultBranch) {
|
|
13
|
+
recordSourceCommitPushed('non_default_branch');
|
|
14
|
+
return;
|
|
15
|
+
}
|
|
16
|
+
const project = await getProjectBySource({
|
|
17
|
+
workspaceId,
|
|
18
|
+
sourceConnectionId: connectionId,
|
|
19
|
+
sourceExternalRepositoryId: push.externalRepositoryId
|
|
20
|
+
});
|
|
21
|
+
if (!project) {
|
|
22
|
+
logger().info({
|
|
23
|
+
eventId: event.id,
|
|
24
|
+
connectionId,
|
|
25
|
+
externalRepositoryId: push.externalRepositoryId
|
|
26
|
+
}, 'source commit pushed: no project bound to source, dropping');
|
|
27
|
+
recordSourceCommitPushed('unbound_source');
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
const outcome = await db().transaction(async (tx)=>{
|
|
31
|
+
const { firstSeen } = await recordIntegrationEventForProject({
|
|
32
|
+
tx,
|
|
33
|
+
integrationEventId: event.id,
|
|
34
|
+
projectId: project.id
|
|
35
|
+
});
|
|
36
|
+
if (!firstSeen) return 'duplicate';
|
|
37
|
+
await writeOutboxEvent(tx, projectsOutbox, {
|
|
38
|
+
type: PROJECT_SOURCE_COMMIT_OBSERVED,
|
|
39
|
+
payload: {
|
|
40
|
+
workspaceId: project.workspaceId,
|
|
41
|
+
projectId: project.id,
|
|
42
|
+
sourceConnectionId: project.sourceConnectionId,
|
|
43
|
+
provider,
|
|
44
|
+
externalRepositoryId: push.externalRepositoryId,
|
|
45
|
+
ref: push.ref,
|
|
46
|
+
headCommitSha: push.headCommitSha
|
|
47
|
+
}
|
|
48
|
+
});
|
|
49
|
+
return 'observed';
|
|
50
|
+
});
|
|
51
|
+
recordSourceCommitPushed(outcome);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
//# sourceMappingURL=on-source-commit-pushed.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/presentation/subscribers/on-source-commit-pushed.ts"],"sourcesContent":["import type {IntegrationSourceCommitPushedEvent} from '@shipfox/api-integration-core-dto';\nimport {PROJECT_SOURCE_COMMIT_OBSERVED} from '@shipfox/api-projects-dto';\nimport {logger} from '@shipfox/node-opentelemetry';\nimport {type DomainEvent, writeOutboxEvent} from '@shipfox/node-outbox';\nimport {db} from '#db/db.js';\nimport {recordIntegrationEventForProject} from '#db/integration-event-dedup.js';\nimport {getProjectBySource} from '#db/projects.js';\nimport {projectsOutbox} from '#db/schema/outbox.js';\nimport {recordSourceCommitPushed, type SourceCommitPushedOutcome} from '#metrics/instance.js';\n\nexport async function onSourceCommitPushed(\n payload: IntegrationSourceCommitPushedEvent,\n event: DomainEvent<IntegrationSourceCommitPushedEvent>,\n): Promise<void> {\n const {provider, workspaceId, connectionId, push} = payload;\n\n // Projects only track the default branch; other branches are someone else's policy.\n if (!push.isDefaultBranch) {\n recordSourceCommitPushed('non_default_branch');\n return;\n }\n\n const project = await getProjectBySource({\n workspaceId,\n sourceConnectionId: connectionId,\n sourceExternalRepositoryId: push.externalRepositoryId,\n });\n if (!project) {\n logger().info(\n {\n eventId: event.id,\n connectionId,\n externalRepositoryId: push.externalRepositoryId,\n },\n 'source commit pushed: no project bound to source, dropping',\n );\n recordSourceCommitPushed('unbound_source');\n return;\n }\n\n const outcome = await db().transaction<SourceCommitPushedOutcome>(async (tx) => {\n const {firstSeen} = await recordIntegrationEventForProject({\n tx,\n integrationEventId: event.id,\n projectId: project.id,\n });\n if (!firstSeen) return 'duplicate';\n\n await writeOutboxEvent(tx, projectsOutbox, {\n type: PROJECT_SOURCE_COMMIT_OBSERVED,\n payload: {\n workspaceId: project.workspaceId,\n projectId: project.id,\n sourceConnectionId: project.sourceConnectionId,\n provider,\n externalRepositoryId: push.externalRepositoryId,\n ref: push.ref,\n headCommitSha: push.headCommitSha,\n },\n });\n return 'observed';\n });\n recordSourceCommitPushed(outcome);\n}\n"],"names":["PROJECT_SOURCE_COMMIT_OBSERVED","logger","writeOutboxEvent","db","recordIntegrationEventForProject","getProjectBySource","projectsOutbox","recordSourceCommitPushed","onSourceCommitPushed","payload","event","provider","workspaceId","connectionId","push","isDefaultBranch","project","sourceConnectionId","sourceExternalRepositoryId","externalRepositoryId","info","eventId","id","outcome","transaction","tx","firstSeen","integrationEventId","projectId","type","ref","headCommitSha"],"mappings":"AACA,SAAQA,8BAA8B,QAAO,4BAA4B;AACzE,SAAQC,MAAM,QAAO,8BAA8B;AACnD,SAA0BC,gBAAgB,QAAO,uBAAuB;AACxE,SAAQC,EAAE,QAAO,YAAY;AAC7B,SAAQC,gCAAgC,QAAO,iCAAiC;AAChF,SAAQC,kBAAkB,QAAO,kBAAkB;AACnD,SAAQC,cAAc,QAAO,uBAAuB;AACpD,SAAQC,wBAAwB,QAAuC,uBAAuB;AAE9F,OAAO,eAAeC,qBACpBC,OAA2C,EAC3CC,KAAsD;IAEtD,MAAM,EAACC,QAAQ,EAAEC,WAAW,EAAEC,YAAY,EAAEC,IAAI,EAAC,GAAGL;IAEpD,oFAAoF;IACpF,IAAI,CAACK,KAAKC,eAAe,EAAE;QACzBR,yBAAyB;QACzB;IACF;IAEA,MAAMS,UAAU,MAAMX,mBAAmB;QACvCO;QACAK,oBAAoBJ;QACpBK,4BAA4BJ,KAAKK,oBAAoB;IACvD;IACA,IAAI,CAACH,SAAS;QACZf,SAASmB,IAAI,CACX;YACEC,SAASX,MAAMY,EAAE;YACjBT;YACAM,sBAAsBL,KAAKK,oBAAoB;QACjD,GACA;QAEFZ,yBAAyB;QACzB;IACF;IAEA,MAAMgB,UAAU,MAAMpB,KAAKqB,WAAW,CAA4B,OAAOC;QACvE,MAAM,EAACC,SAAS,EAAC,GAAG,MAAMtB,iCAAiC;YACzDqB;YACAE,oBAAoBjB,MAAMY,EAAE;YAC5BM,WAAWZ,QAAQM,EAAE;QACvB;QACA,IAAI,CAACI,WAAW,OAAO;QAEvB,MAAMxB,iBAAiBuB,IAAInB,gBAAgB;YACzCuB,MAAM7B;YACNS,SAAS;gBACPG,aAAaI,QAAQJ,WAAW;gBAChCgB,WAAWZ,QAAQM,EAAE;gBACrBL,oBAAoBD,QAAQC,kBAAkB;gBAC9CN;gBACAQ,sBAAsBL,KAAKK,oBAAoB;gBAC/CW,KAAKhB,KAAKgB,GAAG;gBACbC,eAAejB,KAAKiB,aAAa;YACnC;QACF;QACA,OAAO;IACT;IACAxB,yBAAyBgB;AAC3B"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { pruneIntegrationEventDedupActivity } from './prune-integration-event-dedup.js';
|
|
2
|
+
export declare function createProjectsMaintenanceActivities(): {
|
|
3
|
+
pruneIntegrationEventDedupActivity: typeof pruneIntegrationEventDedupActivity;
|
|
4
|
+
};
|
|
5
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/temporal/activities/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,kCAAkC,EAAC,MAAM,oCAAoC,CAAC;AAEtF,wBAAgB,mCAAmC;;EAIlD"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/temporal/activities/index.ts"],"sourcesContent":["import {pruneIntegrationEventDedupActivity} from './prune-integration-event-dedup.js';\n\nexport function createProjectsMaintenanceActivities() {\n return {\n pruneIntegrationEventDedupActivity,\n };\n}\n"],"names":["pruneIntegrationEventDedupActivity","createProjectsMaintenanceActivities"],"mappings":"AAAA,SAAQA,kCAAkC,QAAO,qCAAqC;AAEtF,OAAO,SAASC;IACd,OAAO;QACLD;IACF;AACF"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prune-integration-event-dedup.d.ts","sourceRoot":"","sources":["../../../src/temporal/activities/prune-integration-event-dedup.ts"],"names":[],"mappings":"AAKA,wBAAsB,kCAAkC,IAAI,OAAO,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAC,CAAC,CAGrF"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { pruneIntegrationEventDedup } from '#db/integration-event-dedup.js';
|
|
2
|
+
import { INTEGRATION_EVENT_DEDUP_RETENTION_DAYS } from '#temporal/constants.js';
|
|
3
|
+
const MS_PER_DAY = 24 * 60 * 60 * 1000;
|
|
4
|
+
export async function pruneIntegrationEventDedupActivity() {
|
|
5
|
+
const olderThan = new Date(Date.now() - INTEGRATION_EVENT_DEDUP_RETENTION_DAYS * MS_PER_DAY);
|
|
6
|
+
return await pruneIntegrationEventDedup({
|
|
7
|
+
olderThan
|
|
8
|
+
});
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
//# sourceMappingURL=prune-integration-event-dedup.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/temporal/activities/prune-integration-event-dedup.ts"],"sourcesContent":["import {pruneIntegrationEventDedup} from '#db/integration-event-dedup.js';\nimport {INTEGRATION_EVENT_DEDUP_RETENTION_DAYS} from '#temporal/constants.js';\n\nconst MS_PER_DAY = 24 * 60 * 60 * 1000;\n\nexport async function pruneIntegrationEventDedupActivity(): Promise<{deleted: number}> {\n const olderThan = new Date(Date.now() - INTEGRATION_EVENT_DEDUP_RETENTION_DAYS * MS_PER_DAY);\n return await pruneIntegrationEventDedup({olderThan});\n}\n"],"names":["pruneIntegrationEventDedup","INTEGRATION_EVENT_DEDUP_RETENTION_DAYS","MS_PER_DAY","pruneIntegrationEventDedupActivity","olderThan","Date","now"],"mappings":"AAAA,SAAQA,0BAA0B,QAAO,iCAAiC;AAC1E,SAAQC,sCAAsC,QAAO,yBAAyB;AAE9E,MAAMC,aAAa,KAAK,KAAK,KAAK;AAElC,OAAO,eAAeC;IACpB,MAAMC,YAAY,IAAIC,KAAKA,KAAKC,GAAG,KAAKL,yCAAyCC;IACjF,OAAO,MAAMF,2BAA2B;QAACI;IAAS;AACpD"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../src/temporal/constants.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,+BAA+B,yBAAyB,CAAC;AAEtE,eAAO,MAAM,sCAAsC,KAAK,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/temporal/constants.ts"],"sourcesContent":["export const PROJECTS_MAINTENANCE_TASK_QUEUE = 'projects-maintenance';\n\nexport const INTEGRATION_EVENT_DEDUP_RETENTION_DAYS = 30;\n"],"names":["PROJECTS_MAINTENANCE_TASK_QUEUE","INTEGRATION_EVENT_DEDUP_RETENTION_DAYS"],"mappings":"AAAA,OAAO,MAAMA,kCAAkC,uBAAuB;AAEtE,OAAO,MAAMC,yCAAyC,GAAG"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/temporal/workflows/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,8BAA8B,EAAC,MAAM,yCAAyC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/temporal/workflows/index.ts"],"sourcesContent":["export {pruneIntegrationEventDedupCron} from './prune-integration-event-dedup-cron.js';\n"],"names":["pruneIntegrationEventDedupCron"],"mappings":"AAAA,SAAQA,8BAA8B,QAAO,0CAA0C"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prune-integration-event-dedup-cron.d.ts","sourceRoot":"","sources":["../../../src/temporal/workflows/prune-integration-event-dedup-cron.ts"],"names":[],"mappings":"AASA,wBAAsB,8BAA8B,IAAI,OAAO,CAAC,IAAI,CAAC,CAKpE"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { log, proxyActivities } from '@temporalio/workflow';
|
|
2
|
+
const { pruneIntegrationEventDedupActivity } = proxyActivities({
|
|
3
|
+
startToCloseTimeout: '5 minutes'
|
|
4
|
+
});
|
|
5
|
+
export async function pruneIntegrationEventDedupCron() {
|
|
6
|
+
const { deleted } = await pruneIntegrationEventDedupActivity();
|
|
7
|
+
if (deleted > 0) {
|
|
8
|
+
log.info('Pruned projects integration event dedup rows', {
|
|
9
|
+
deleted
|
|
10
|
+
});
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
//# sourceMappingURL=prune-integration-event-dedup-cron.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/temporal/workflows/prune-integration-event-dedup-cron.ts"],"sourcesContent":["import {log, proxyActivities} from '@temporalio/workflow';\nimport type {createProjectsMaintenanceActivities} from '../activities/index.js';\n\nconst {pruneIntegrationEventDedupActivity} = proxyActivities<\n ReturnType<typeof createProjectsMaintenanceActivities>\n>({\n startToCloseTimeout: '5 minutes',\n});\n\nexport async function pruneIntegrationEventDedupCron(): Promise<void> {\n const {deleted} = await pruneIntegrationEventDedupActivity();\n if (deleted > 0) {\n log.info('Pruned projects integration event dedup rows', {deleted});\n }\n}\n"],"names":["log","proxyActivities","pruneIntegrationEventDedupActivity","startToCloseTimeout","pruneIntegrationEventDedupCron","deleted","info"],"mappings":"AAAA,SAAQA,GAAG,EAAEC,eAAe,QAAO,uBAAuB;AAG1D,MAAM,EAACC,kCAAkC,EAAC,GAAGD,gBAE3C;IACAE,qBAAqB;AACvB;AAEA,OAAO,eAAeC;IACpB,MAAM,EAACC,OAAO,EAAC,GAAG,MAAMH;IACxB,IAAIG,UAAU,GAAG;QACfL,IAAIM,IAAI,CAAC,gDAAgD;YAACD;QAAO;IACnE;AACF"}
|