@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.
Files changed (202) hide show
  1. package/.turbo/turbo-build.log +2 -0
  2. package/.turbo/turbo-type$colon$emit.log +1 -0
  3. package/.turbo/turbo-type.log +1 -0
  4. package/CHANGELOG.md +117 -0
  5. package/LICENSE +21 -0
  6. package/dist/core/entities/index.d.ts +2 -0
  7. package/dist/core/entities/index.d.ts.map +1 -0
  8. package/dist/core/entities/index.js +3 -0
  9. package/dist/core/entities/index.js.map +1 -0
  10. package/dist/core/entities/project.d.ts +10 -0
  11. package/dist/core/entities/project.d.ts.map +1 -0
  12. package/dist/core/entities/project.js +3 -0
  13. package/dist/core/entities/project.js.map +1 -0
  14. package/dist/core/errors.d.ts +13 -0
  15. package/dist/core/errors.d.ts.map +1 -0
  16. package/dist/core/errors.js +20 -0
  17. package/dist/core/errors.js.map +1 -0
  18. package/dist/core/index.d.ts +5 -0
  19. package/dist/core/index.d.ts.map +1 -0
  20. package/dist/core/index.js +4 -0
  21. package/dist/core/index.js.map +1 -0
  22. package/dist/core/projects.d.ts +12 -0
  23. package/dist/core/projects.d.ts.map +1 -0
  24. package/dist/core/projects.js +62 -0
  25. package/dist/core/projects.js.map +1 -0
  26. package/dist/db/db.d.ts +763 -0
  27. package/dist/db/db.d.ts.map +1 -0
  28. package/dist/db/db.js +22 -0
  29. package/dist/db/db.js.map +1 -0
  30. package/dist/db/index.d.ts +8 -0
  31. package/dist/db/index.d.ts.map +1 -0
  32. package/dist/db/index.js +10 -0
  33. package/dist/db/index.js.map +1 -0
  34. package/dist/db/integration-event-dedup.d.ts +17 -0
  35. package/dist/db/integration-event-dedup.d.ts.map +1 -0
  36. package/dist/db/integration-event-dedup.js +27 -0
  37. package/dist/db/integration-event-dedup.js.map +1 -0
  38. package/dist/db/projects.d.ts +36 -0
  39. package/dist/db/projects.d.ts.map +1 -0
  40. package/dist/db/projects.js +84 -0
  41. package/dist/db/projects.js.map +1 -0
  42. package/dist/db/schema/common.d.ts +2 -0
  43. package/dist/db/schema/common.d.ts.map +1 -0
  44. package/dist/db/schema/common.js +4 -0
  45. package/dist/db/schema/common.js.map +1 -0
  46. package/dist/db/schema/integration-event-dedup.d.ts +59 -0
  47. package/dist/db/schema/integration-event-dedup.d.ts.map +1 -0
  48. package/dist/db/schema/integration-event-dedup.js +19 -0
  49. package/dist/db/schema/integration-event-dedup.js.map +1 -0
  50. package/dist/db/schema/outbox.d.ts +195 -0
  51. package/dist/db/schema/outbox.d.ts.map +1 -0
  52. package/dist/db/schema/outbox.js +5 -0
  53. package/dist/db/schema/outbox.js.map +1 -0
  54. package/dist/db/schema/projects.d.ts +131 -0
  55. package/dist/db/schema/projects.d.ts.map +1 -0
  56. package/dist/db/schema/projects.js +32 -0
  57. package/dist/db/schema/projects.js.map +1 -0
  58. package/dist/index.d.ts +12 -0
  59. package/dist/index.d.ts.map +1 -0
  60. package/dist/index.js +59 -0
  61. package/dist/index.js.map +1 -0
  62. package/dist/metrics/index.d.ts +3 -0
  63. package/dist/metrics/index.d.ts.map +1 -0
  64. package/dist/metrics/index.js +4 -0
  65. package/dist/metrics/index.js.map +1 -0
  66. package/dist/metrics/instance.d.ts +4 -0
  67. package/dist/metrics/instance.d.ts.map +1 -0
  68. package/dist/metrics/instance.js +25 -0
  69. package/dist/metrics/instance.js.map +1 -0
  70. package/dist/metrics/service.d.ts +2 -0
  71. package/dist/metrics/service.d.ts.map +1 -0
  72. package/dist/metrics/service.js +15 -0
  73. package/dist/metrics/service.js.map +1 -0
  74. package/dist/presentation/auth/require-project-access.d.ts +12 -0
  75. package/dist/presentation/auth/require-project-access.d.ts.map +1 -0
  76. package/dist/presentation/auth/require-project-access.js +25 -0
  77. package/dist/presentation/auth/require-project-access.js.map +1 -0
  78. package/dist/presentation/dto/index.d.ts +2 -0
  79. package/dist/presentation/dto/index.d.ts.map +1 -0
  80. package/dist/presentation/dto/index.js +3 -0
  81. package/dist/presentation/dto/index.js.map +1 -0
  82. package/dist/presentation/dto/project.d.ts +13 -0
  83. package/dist/presentation/dto/project.d.ts.map +1 -0
  84. package/dist/presentation/dto/project.js +15 -0
  85. package/dist/presentation/dto/project.js.map +1 -0
  86. package/dist/presentation/e2eRoutes/create-project.d.ts +2 -0
  87. package/dist/presentation/e2eRoutes/create-project.d.ts.map +1 -0
  88. package/dist/presentation/e2eRoutes/create-project.js +45 -0
  89. package/dist/presentation/e2eRoutes/create-project.js.map +1 -0
  90. package/dist/presentation/e2eRoutes/index.d.ts +3 -0
  91. package/dist/presentation/e2eRoutes/index.d.ts.map +1 -0
  92. package/dist/presentation/e2eRoutes/index.js +9 -0
  93. package/dist/presentation/e2eRoutes/index.js.map +1 -0
  94. package/dist/presentation/index.d.ts +3 -0
  95. package/dist/presentation/index.d.ts.map +1 -0
  96. package/dist/presentation/index.js +4 -0
  97. package/dist/presentation/index.js.map +1 -0
  98. package/dist/presentation/routes/create-project.d.ts +3 -0
  99. package/dist/presentation/routes/create-project.d.ts.map +1 -0
  100. package/dist/presentation/routes/create-project.js +94 -0
  101. package/dist/presentation/routes/create-project.js.map +1 -0
  102. package/dist/presentation/routes/cursor.d.ts +2 -0
  103. package/dist/presentation/routes/cursor.d.ts.map +1 -0
  104. package/dist/presentation/routes/cursor.js +3 -0
  105. package/dist/presentation/routes/cursor.js.map +1 -0
  106. package/dist/presentation/routes/get-project.d.ts +2 -0
  107. package/dist/presentation/routes/get-project.d.ts.map +1 -0
  108. package/dist/presentation/routes/get-project.js +30 -0
  109. package/dist/presentation/routes/get-project.js.map +1 -0
  110. package/dist/presentation/routes/index.d.ts +4 -0
  111. package/dist/presentation/routes/index.d.ts.map +1 -0
  112. package/dist/presentation/routes/index.js +17 -0
  113. package/dist/presentation/routes/index.js.map +1 -0
  114. package/dist/presentation/routes/list-projects.d.ts +2 -0
  115. package/dist/presentation/routes/list-projects.d.ts.map +1 -0
  116. package/dist/presentation/routes/list-projects.js +43 -0
  117. package/dist/presentation/routes/list-projects.js.map +1 -0
  118. package/dist/presentation/subscribers/index.d.ts +2 -0
  119. package/dist/presentation/subscribers/index.d.ts.map +1 -0
  120. package/dist/presentation/subscribers/index.js +3 -0
  121. package/dist/presentation/subscribers/index.js.map +1 -0
  122. package/dist/presentation/subscribers/on-source-commit-pushed.d.ts +4 -0
  123. package/dist/presentation/subscribers/on-source-commit-pushed.d.ts.map +1 -0
  124. package/dist/presentation/subscribers/on-source-commit-pushed.js +54 -0
  125. package/dist/presentation/subscribers/on-source-commit-pushed.js.map +1 -0
  126. package/dist/temporal/activities/index.d.ts +5 -0
  127. package/dist/temporal/activities/index.d.ts.map +1 -0
  128. package/dist/temporal/activities/index.js +8 -0
  129. package/dist/temporal/activities/index.js.map +1 -0
  130. package/dist/temporal/activities/prune-integration-event-dedup.d.ts +4 -0
  131. package/dist/temporal/activities/prune-integration-event-dedup.d.ts.map +1 -0
  132. package/dist/temporal/activities/prune-integration-event-dedup.js +11 -0
  133. package/dist/temporal/activities/prune-integration-event-dedup.js.map +1 -0
  134. package/dist/temporal/constants.d.ts +3 -0
  135. package/dist/temporal/constants.d.ts.map +1 -0
  136. package/dist/temporal/constants.js +4 -0
  137. package/dist/temporal/constants.js.map +1 -0
  138. package/dist/temporal/workflows/index.d.ts +2 -0
  139. package/dist/temporal/workflows/index.d.ts.map +1 -0
  140. package/dist/temporal/workflows/index.js +3 -0
  141. package/dist/temporal/workflows/index.js.map +1 -0
  142. package/dist/temporal/workflows/prune-integration-event-dedup-cron.d.ts +2 -0
  143. package/dist/temporal/workflows/prune-integration-event-dedup-cron.d.ts.map +1 -0
  144. package/dist/temporal/workflows/prune-integration-event-dedup-cron.js +14 -0
  145. package/dist/temporal/workflows/prune-integration-event-dedup-cron.js.map +1 -0
  146. package/dist/tsconfig.test.tsbuildinfo +1 -0
  147. package/drizzle/0000_initial.sql +37 -0
  148. package/drizzle/meta/0000_snapshot.json +307 -0
  149. package/drizzle/meta/_journal.json +13 -0
  150. package/drizzle.config.ts +7 -0
  151. package/package.json +76 -0
  152. package/src/core/entities/index.ts +1 -0
  153. package/src/core/entities/project.ts +9 -0
  154. package/src/core/errors.ts +26 -0
  155. package/src/core/index.ts +8 -0
  156. package/src/core/projects.test.ts +142 -0
  157. package/src/core/projects.ts +97 -0
  158. package/src/db/db.ts +22 -0
  159. package/src/db/index.ts +26 -0
  160. package/src/db/integration-event-dedup.ts +45 -0
  161. package/src/db/projects.test.ts +22 -0
  162. package/src/db/projects.ts +158 -0
  163. package/src/db/schema/common.ts +3 -0
  164. package/src/db/schema/integration-event-dedup.ts +15 -0
  165. package/src/db/schema/outbox.ts +4 -0
  166. package/src/db/schema/projects.ts +39 -0
  167. package/src/index.ts +71 -0
  168. package/src/metrics/index.ts +2 -0
  169. package/src/metrics/instance.ts +34 -0
  170. package/src/metrics/service.ts +17 -0
  171. package/src/presentation/auth/require-project-access.ts +29 -0
  172. package/src/presentation/dto/index.ts +1 -0
  173. package/src/presentation/dto/project.ts +15 -0
  174. package/src/presentation/e2eRoutes/create-project.test.ts +119 -0
  175. package/src/presentation/e2eRoutes/create-project.ts +50 -0
  176. package/src/presentation/e2eRoutes/index.ts +7 -0
  177. package/src/presentation/index.ts +2 -0
  178. package/src/presentation/routes/create-project.ts +102 -0
  179. package/src/presentation/routes/cursor.ts +5 -0
  180. package/src/presentation/routes/get-project.ts +24 -0
  181. package/src/presentation/routes/index.ts +14 -0
  182. package/src/presentation/routes/list-projects.ts +34 -0
  183. package/src/presentation/routes/projects.test.ts +266 -0
  184. package/src/presentation/subscribers/index.ts +1 -0
  185. package/src/presentation/subscribers/on-source-commit-pushed.test.ts +149 -0
  186. package/src/presentation/subscribers/on-source-commit-pushed.ts +64 -0
  187. package/src/temporal/activities/index.ts +7 -0
  188. package/src/temporal/activities/prune-integration-event-dedup.test.ts +50 -0
  189. package/src/temporal/activities/prune-integration-event-dedup.ts +9 -0
  190. package/src/temporal/constants.ts +3 -0
  191. package/src/temporal/workflows/index.ts +1 -0
  192. package/src/temporal/workflows/prune-integration-event-dedup-cron.ts +15 -0
  193. package/test/env.ts +14 -0
  194. package/test/factories/project.ts +24 -0
  195. package/test/globalSetup.ts +17 -0
  196. package/test/index.ts +1 -0
  197. package/test/setup.ts +17 -0
  198. package/tsconfig.build.json +9 -0
  199. package/tsconfig.build.tsbuildinfo +1 -0
  200. package/tsconfig.json +3 -0
  201. package/tsconfig.test.json +8 -0
  202. 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,2 @@
1
+ export { decodeTimestampIdCursor as decodeProjectCursor, encodeTimestampIdCursor as encodeProjectCursor, type TimestampIdCursor as ProjectCursor, } from '@shipfox/node-drizzle';
2
+ //# sourceMappingURL=cursor.d.ts.map
@@ -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,3 @@
1
+ export { decodeTimestampIdCursor as decodeProjectCursor, encodeTimestampIdCursor as encodeProjectCursor } from '@shipfox/node-drizzle';
2
+
3
+ //# sourceMappingURL=cursor.js.map
@@ -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,2 @@
1
+ export declare const getProjectRoute: import("@shipfox/node-fastify").RouteDefinition;
2
+ //# sourceMappingURL=get-project.d.ts.map
@@ -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,2 @@
1
+ export declare const listProjectsRoute: import("@shipfox/node-fastify").RouteDefinition;
2
+ //# sourceMappingURL=list-projects.d.ts.map
@@ -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,2 @@
1
+ export { onSourceCommitPushed } from './on-source-commit-pushed.js';
2
+ //# sourceMappingURL=index.d.ts.map
@@ -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,3 @@
1
+ export { onSourceCommitPushed } from './on-source-commit-pushed.js';
2
+
3
+ //# sourceMappingURL=index.js.map
@@ -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,8 @@
1
+ import { pruneIntegrationEventDedupActivity } from './prune-integration-event-dedup.js';
2
+ export function createProjectsMaintenanceActivities() {
3
+ return {
4
+ pruneIntegrationEventDedupActivity
5
+ };
6
+ }
7
+
8
+ //# sourceMappingURL=index.js.map
@@ -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,4 @@
1
+ export declare function pruneIntegrationEventDedupActivity(): Promise<{
2
+ deleted: number;
3
+ }>;
4
+ //# sourceMappingURL=prune-integration-event-dedup.d.ts.map
@@ -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,3 @@
1
+ export declare const PROJECTS_MAINTENANCE_TASK_QUEUE = "projects-maintenance";
2
+ export declare const INTEGRATION_EVENT_DEDUP_RETENTION_DAYS = 30;
3
+ //# sourceMappingURL=constants.d.ts.map
@@ -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,4 @@
1
+ export const PROJECTS_MAINTENANCE_TASK_QUEUE = 'projects-maintenance';
2
+ export const INTEGRATION_EVENT_DEDUP_RETENTION_DAYS = 30;
3
+
4
+ //# sourceMappingURL=constants.js.map
@@ -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,2 @@
1
+ export { pruneIntegrationEventDedupCron } from './prune-integration-event-dedup-cron.js';
2
+ //# sourceMappingURL=index.d.ts.map
@@ -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,3 @@
1
+ export { pruneIntegrationEventDedupCron } from './prune-integration-event-dedup-cron.js';
2
+
3
+ //# sourceMappingURL=index.js.map
@@ -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,2 @@
1
+ export declare function pruneIntegrationEventDedupCron(): Promise<void>;
2
+ //# sourceMappingURL=prune-integration-event-dedup-cron.d.ts.map
@@ -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"}