@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,2 @@
1
+ $ shipfox-swc
2
+ Successfully compiled: 35 files with swc (66.48ms)
@@ -0,0 +1 @@
1
+ $ shipfox-tsc-emit
@@ -0,0 +1 @@
1
+ $ shipfox-tsc-check
package/CHANGELOG.md ADDED
@@ -0,0 +1,117 @@
1
+ # @shipfox/api-projects
2
+
3
+ ## 2.0.0
4
+
5
+ ### Minor Changes
6
+
7
+ - 1b0d344: Publishes the complete API runtime closure with packed-consumer-safe internal imports and records its exact package set in application releases.
8
+
9
+ ### Patch Changes
10
+
11
+ - Updated dependencies [0cd6dd4]
12
+ - Updated dependencies [a68458a]
13
+ - Updated dependencies [6eba800]
14
+ - Updated dependencies [1b0d344]
15
+ - Updated dependencies [521e006]
16
+ - @shipfox/node-module@0.2.0
17
+ - @shipfox/api-integration-core@2.0.0
18
+ - @shipfox/node-temporal@0.2.0
19
+ - @shipfox/api-auth-context@2.0.0
20
+ - @shipfox/api-integration-core-dto@2.0.0
21
+ - @shipfox/api-projects-dto@2.0.0
22
+ - @shipfox/node-drizzle@0.2.1
23
+ - @shipfox/node-fastify@0.2.1
24
+ - @shipfox/node-opentelemetry@0.5.0
25
+ - @shipfox/node-outbox@0.2.1
26
+ - @shipfox/node-postgres@0.4.1
27
+
28
+ ## 0.1.2
29
+
30
+ ### Patch Changes
31
+
32
+ - Updated dependencies [705dd43]
33
+ - @shipfox/node-outbox@0.2.0
34
+ - @shipfox/api-integration-core@0.1.2
35
+ - @shipfox/node-module@0.1.2
36
+
37
+ ## 0.1.1
38
+
39
+ ### Patch Changes
40
+
41
+ - Updated dependencies [ec75cd5]
42
+ - Updated dependencies [6a1fb54]
43
+ - @shipfox/node-drizzle@0.2.0
44
+ - @shipfox/node-postgres@0.4.0
45
+ - @shipfox/api-integration-core@0.1.1
46
+ - @shipfox/node-module@0.1.1
47
+ - @shipfox/node-outbox@0.1.1
48
+
49
+ ## 0.1.0
50
+
51
+ ### Minor Changes
52
+
53
+ - 43fd0c1: Adds HTTP-first E2E project setup contracts and routes for creating synthetic projects without source-control setup.
54
+
55
+ ### Patch Changes
56
+
57
+ - 115655e: Moves source-event translation to the integration module: source-control providers emit a typed, provider-agnostic `INTEGRATION_SOURCE_COMMIT_PUSHED` event via one transactional publisher, projects subscribes to it instead of decoding GitHub payloads, and branch-deletion pushes are dropped at the source.
58
+ - 72ce351: Removes the legacy workspace API-key auth surface, its DTOs, project-access branch, database table, and token prefix support.
59
+ - ae7a63c: Adds daily dispatched outbox row retention with bounded cleanup batches and retention indexes on module outbox tables.
60
+ - 3bea87f: Adds a typed `subscriberFactory` that binds each outbox event name to its payload type at construction, so subscriber handlers receive a typed `(payload, event)` and the per-handler `event.payload as X` casts are gone; a private brand makes the factory the only way to build a module subscriber.
61
+ - 82d22e4: Make the workspace-membership gate stateless. `requireWorkspaceAccess` now lives in `@shipfox/api-auth-context` and authorizes a request purely from the verified session-token claims, replacing the `requireMembership` gate in `@shipfox/api-workspaces` that read the workspace row from the database on every workspace-scoped request. Membership and role already travel in the token, so the check needs no database access.
62
+
63
+ This removes the per-request database read and severs the runtime dependency on `@shipfox/api-workspaces` from feature modules that only needed the membership gate (integration providers, secrets, projects, agent, runners). Workspace existence and `active`-status enforcement, which no code path currently exercises, moves off the hot path; enforce it at token issuance when workspace suspension is introduced.
64
+
65
+ - 8ecba0f: Adds OpenTelemetry project creation, source-commit handling, and current project-count metrics.
66
+ - 27770eb: Tightens signup, workspace, and project display-name validation with shared trimming, control and format-character rejection, length limits, and contextual client form errors.
67
+ - 2933c33: Adds drain-boundary Zod validation for current outbox publisher event payloads.
68
+ - Updated dependencies [0948b67]
69
+ - Updated dependencies [34ba284]
70
+ - Updated dependencies [5707d6d]
71
+ - Updated dependencies [b9c3f32]
72
+ - Updated dependencies [a81b68c]
73
+ - Updated dependencies [115655e]
74
+ - Updated dependencies [c0a883c]
75
+ - Updated dependencies [72ce351]
76
+ - Updated dependencies [e47f8da]
77
+ - Updated dependencies [a68ed61]
78
+ - Updated dependencies [ce062a9]
79
+ - Updated dependencies [7b175f5]
80
+ - Updated dependencies [f3614ae]
81
+ - Updated dependencies [f98c2be]
82
+ - Updated dependencies [ae7a63c]
83
+ - Updated dependencies [5729548]
84
+ - Updated dependencies [d245be8]
85
+ - Updated dependencies [f92122b]
86
+ - Updated dependencies [f8f339a]
87
+ - Updated dependencies [58f51bd]
88
+ - Updated dependencies [570ac69]
89
+ - Updated dependencies [857fd73]
90
+ - Updated dependencies [444ac89]
91
+ - Updated dependencies [75520ff]
92
+ - Updated dependencies [b8e49ff]
93
+ - Updated dependencies [5b8ed32]
94
+ - Updated dependencies [417f128]
95
+ - Updated dependencies [d6d4862]
96
+ - Updated dependencies [c0a883c]
97
+ - Updated dependencies [6077301]
98
+ - Updated dependencies [3bea87f]
99
+ - Updated dependencies [82d22e4]
100
+ - Updated dependencies [01be723]
101
+ - Updated dependencies [27770eb]
102
+ - Updated dependencies [2933c33]
103
+ - Updated dependencies [43fd0c1]
104
+ - Updated dependencies [6181819]
105
+ - Updated dependencies [8b9c3e0]
106
+ - Updated dependencies [9c149d1]
107
+ - @shipfox/api-integration-core@0.1.0
108
+ - @shipfox/node-fastify@0.2.0
109
+ - @shipfox/node-drizzle@0.1.0
110
+ - @shipfox/api-auth-context@0.1.0
111
+ - @shipfox/api-integration-core-dto@0.1.0
112
+ - @shipfox/node-opentelemetry@0.4.2
113
+ - @shipfox/node-postgres@0.3.2
114
+ - @shipfox/node-temporal@0.1.1
115
+ - @shipfox/node-module@0.1.0
116
+ - @shipfox/node-outbox@0.1.0
117
+ - @shipfox/api-projects-dto@0.1.0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Shipfox
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,2 @@
1
+ export type * from './project.js';
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/core/entities/index.ts"],"names":[],"mappings":"AAAA,mBAAmB,cAAc,CAAC"}
@@ -0,0 +1,3 @@
1
+ export { };
2
+
3
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/core/entities/index.ts"],"sourcesContent":["export type * from './project.js';\n"],"names":[],"mappings":"AAAA,WAAkC"}
@@ -0,0 +1,10 @@
1
+ export interface Project {
2
+ id: string;
3
+ workspaceId: string;
4
+ sourceConnectionId: string;
5
+ sourceExternalRepositoryId: string;
6
+ name: string;
7
+ createdAt: Date;
8
+ updatedAt: Date;
9
+ }
10
+ //# sourceMappingURL=project.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"project.d.ts","sourceRoot":"","sources":["../../../src/core/entities/project.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,OAAO;IACtB,EAAE,EAAE,MAAM,CAAC;IACX,WAAW,EAAE,MAAM,CAAC;IACpB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,0BAA0B,EAAE,MAAM,CAAC;IACnC,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,IAAI,CAAC;IAChB,SAAS,EAAE,IAAI,CAAC;CACjB"}
@@ -0,0 +1,3 @@
1
+ export { };
2
+
3
+ //# sourceMappingURL=project.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/core/entities/project.ts"],"sourcesContent":["export interface Project {\n id: string;\n workspaceId: string;\n sourceConnectionId: string;\n sourceExternalRepositoryId: string;\n name: string;\n createdAt: Date;\n updatedAt: Date;\n}\n"],"names":[],"mappings":"AAAA,WAQC"}
@@ -0,0 +1,13 @@
1
+ export declare class ProjectNotFoundError extends Error {
2
+ constructor(projectId: string);
3
+ }
4
+ export declare class ProjectAccessDeniedError extends Error {
5
+ constructor(projectId: string);
6
+ }
7
+ export declare class ProjectAlreadyExistsError extends Error {
8
+ readonly existingProjectId: string;
9
+ readonly sourceConnectionId: string;
10
+ readonly sourceExternalRepositoryId: string;
11
+ constructor(existingProjectId: string, sourceConnectionId: string, sourceExternalRepositoryId: string);
12
+ }
13
+ //# sourceMappingURL=errors.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../src/core/errors.ts"],"names":[],"mappings":"AAAA,qBAAa,oBAAqB,SAAQ,KAAK;gBACjC,SAAS,EAAE,MAAM;CAI9B;AAED,qBAAa,wBAAyB,SAAQ,KAAK;gBACrC,SAAS,EAAE,MAAM;CAI9B;AAED,qBAAa,yBAA0B,SAAQ,KAAK;aAEhC,iBAAiB,EAAE,MAAM;aACzB,kBAAkB,EAAE,MAAM;aAC1B,0BAA0B,EAAE,MAAM;gBAFlC,iBAAiB,EAAE,MAAM,EACzB,kBAAkB,EAAE,MAAM,EAC1B,0BAA0B,EAAE,MAAM;CAOrD"}
@@ -0,0 +1,20 @@
1
+ export class ProjectNotFoundError extends Error {
2
+ constructor(projectId){
3
+ super(`Project not found: ${projectId}`);
4
+ this.name = 'ProjectNotFoundError';
5
+ }
6
+ }
7
+ export class ProjectAccessDeniedError extends Error {
8
+ constructor(projectId){
9
+ super(`Access denied for project: ${projectId}`);
10
+ this.name = 'ProjectAccessDeniedError';
11
+ }
12
+ }
13
+ export class ProjectAlreadyExistsError extends Error {
14
+ constructor(existingProjectId, sourceConnectionId, sourceExternalRepositoryId){
15
+ super(`Project already exists for source repository: ${sourceConnectionId}/${sourceExternalRepositoryId}`), this.existingProjectId = existingProjectId, this.sourceConnectionId = sourceConnectionId, this.sourceExternalRepositoryId = sourceExternalRepositoryId;
16
+ this.name = 'ProjectAlreadyExistsError';
17
+ }
18
+ }
19
+
20
+ //# sourceMappingURL=errors.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/core/errors.ts"],"sourcesContent":["export class ProjectNotFoundError extends Error {\n constructor(projectId: string) {\n super(`Project not found: ${projectId}`);\n this.name = 'ProjectNotFoundError';\n }\n}\n\nexport class ProjectAccessDeniedError extends Error {\n constructor(projectId: string) {\n super(`Access denied for project: ${projectId}`);\n this.name = 'ProjectAccessDeniedError';\n }\n}\n\nexport class ProjectAlreadyExistsError extends Error {\n constructor(\n public readonly existingProjectId: string,\n public readonly sourceConnectionId: string,\n public readonly sourceExternalRepositoryId: string,\n ) {\n super(\n `Project already exists for source repository: ${sourceConnectionId}/${sourceExternalRepositoryId}`,\n );\n this.name = 'ProjectAlreadyExistsError';\n }\n}\n"],"names":["ProjectNotFoundError","Error","projectId","name","ProjectAccessDeniedError","ProjectAlreadyExistsError","existingProjectId","sourceConnectionId","sourceExternalRepositoryId"],"mappings":"AAAA,OAAO,MAAMA,6BAA6BC;IACxC,YAAYC,SAAiB,CAAE;QAC7B,KAAK,CAAC,CAAC,mBAAmB,EAAEA,WAAW;QACvC,IAAI,CAACC,IAAI,GAAG;IACd;AACF;AAEA,OAAO,MAAMC,iCAAiCH;IAC5C,YAAYC,SAAiB,CAAE;QAC7B,KAAK,CAAC,CAAC,2BAA2B,EAAEA,WAAW;QAC/C,IAAI,CAACC,IAAI,GAAG;IACd;AACF;AAEA,OAAO,MAAME,kCAAkCJ;IAC7C,YACE,AAAgBK,iBAAyB,EACzC,AAAgBC,kBAA0B,EAC1C,AAAgBC,0BAAkC,CAClD;QACA,KAAK,CACH,CAAC,8CAA8C,EAAED,mBAAmB,CAAC,EAAEC,4BAA4B,QALrFF,oBAAAA,wBACAC,qBAAAA,yBACAC,6BAAAA;QAKhB,IAAI,CAACL,IAAI,GAAG;IACd;AACF"}
@@ -0,0 +1,5 @@
1
+ export type * from './entities/index.js';
2
+ export { ProjectAccessDeniedError, ProjectAlreadyExistsError, ProjectNotFoundError, } from './errors.js';
3
+ export type { CreateProjectFromSourceParams } from './projects.js';
4
+ export { createProjectFromSource } from './projects.js';
5
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/core/index.ts"],"names":[],"mappings":"AAAA,mBAAmB,qBAAqB,CAAC;AACzC,OAAO,EACL,wBAAwB,EACxB,yBAAyB,EACzB,oBAAoB,GACrB,MAAM,aAAa,CAAC;AACrB,YAAY,EAAC,6BAA6B,EAAC,MAAM,eAAe,CAAC;AACjE,OAAO,EAAC,uBAAuB,EAAC,MAAM,eAAe,CAAC"}
@@ -0,0 +1,4 @@
1
+ export { ProjectAccessDeniedError, ProjectAlreadyExistsError, ProjectNotFoundError } from './errors.js';
2
+ export { createProjectFromSource } from './projects.js';
3
+
4
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/core/index.ts"],"sourcesContent":["export type * from './entities/index.js';\nexport {\n ProjectAccessDeniedError,\n ProjectAlreadyExistsError,\n ProjectNotFoundError,\n} from './errors.js';\nexport type {CreateProjectFromSourceParams} from './projects.js';\nexport {createProjectFromSource} from './projects.js';\n"],"names":["ProjectAccessDeniedError","ProjectAlreadyExistsError","ProjectNotFoundError","createProjectFromSource"],"mappings":"AACA,SACEA,wBAAwB,EACxBC,yBAAyB,EACzBC,oBAAoB,QACf,cAAc;AAErB,SAAQC,uBAAuB,QAAO,gBAAgB"}
@@ -0,0 +1,12 @@
1
+ import type { IntegrationSourceControlService } from '@shipfox/api-integration-core';
2
+ import type { Project } from './entities/project.js';
3
+ export interface CreateProjectFromSourceParams {
4
+ actorId: string;
5
+ workspaceId: string;
6
+ name: string;
7
+ sourceConnectionId: string;
8
+ sourceExternalRepositoryId: string;
9
+ sourceControl: IntegrationSourceControlService;
10
+ }
11
+ export declare function createProjectFromSource(params: CreateProjectFromSourceParams): Promise<Project>;
12
+ //# sourceMappingURL=projects.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"projects.d.ts","sourceRoot":"","sources":["../../src/core/projects.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,+BAA+B,EAAC,MAAM,+BAA+B,CAAC;AAYnF,OAAO,KAAK,EAAC,OAAO,EAAC,MAAM,uBAAuB,CAAC;AAGnD,MAAM,WAAW,6BAA6B;IAC5C,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,kBAAkB,EAAE,MAAM,CAAC;IAC3B,0BAA0B,EAAE,MAAM,CAAC;IACnC,aAAa,EAAE,+BAA+B,CAAC;CAChD;AAED,wBAAsB,uBAAuB,CAC3C,MAAM,EAAE,6BAA6B,GACpC,OAAO,CAAC,OAAO,CAAC,CAsElB"}
@@ -0,0 +1,62 @@
1
+ import { PROJECT_CREATED, PROJECT_SOURCE_BOUND } from '@shipfox/api-projects-dto';
2
+ import { writeOutboxEvent } from '@shipfox/node-outbox';
3
+ import { and, eq } from 'drizzle-orm';
4
+ import { db } from '#db/db.js';
5
+ import { projectsOutbox } from '#db/schema/outbox.js';
6
+ import { projects, toProject } from '#db/schema/projects.js';
7
+ import { recordProjectCreated } from '#metrics/instance.js';
8
+ import { ProjectAlreadyExistsError } from './errors.js';
9
+ export async function createProjectFromSource(params) {
10
+ const source = await params.sourceControl.resolveRepository({
11
+ workspaceId: params.workspaceId,
12
+ connectionId: params.sourceConnectionId,
13
+ externalRepositoryId: params.sourceExternalRepositoryId
14
+ });
15
+ const project = await db().transaction(async (tx)=>{
16
+ const [projectRow] = await tx.insert(projects).values({
17
+ workspaceId: params.workspaceId,
18
+ sourceConnectionId: source.connection.id,
19
+ sourceExternalRepositoryId: source.repository.externalRepositoryId,
20
+ name: params.name
21
+ }).onConflictDoNothing({
22
+ target: [
23
+ projects.sourceConnectionId,
24
+ projects.sourceExternalRepositoryId
25
+ ]
26
+ }).returning();
27
+ if (!projectRow) {
28
+ const [existing] = await tx.select().from(projects).where(and(eq(projects.sourceConnectionId, source.connection.id), eq(projects.sourceExternalRepositoryId, source.repository.externalRepositoryId))).limit(1);
29
+ if (existing) {
30
+ throw new ProjectAlreadyExistsError(existing.id, source.connection.id, source.repository.externalRepositoryId);
31
+ }
32
+ throw new Error('Project insert returned no rows');
33
+ }
34
+ const project = toProject(projectRow);
35
+ await writeOutboxEvent(tx, projectsOutbox, {
36
+ type: PROJECT_CREATED,
37
+ payload: {
38
+ actorId: params.actorId,
39
+ workspaceId: project.workspaceId,
40
+ projectId: project.id,
41
+ sourceConnectionId: project.sourceConnectionId,
42
+ sourceExternalRepositoryId: project.sourceExternalRepositoryId
43
+ }
44
+ });
45
+ await writeOutboxEvent(tx, projectsOutbox, {
46
+ type: PROJECT_SOURCE_BOUND,
47
+ payload: {
48
+ actorId: params.actorId,
49
+ workspaceId: project.workspaceId,
50
+ projectId: project.id,
51
+ sourceConnectionId: project.sourceConnectionId,
52
+ provider: source.connection.provider,
53
+ externalRepositoryId: project.sourceExternalRepositoryId
54
+ }
55
+ });
56
+ return project;
57
+ });
58
+ recordProjectCreated();
59
+ return project;
60
+ }
61
+
62
+ //# sourceMappingURL=projects.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/core/projects.ts"],"sourcesContent":["import type {IntegrationSourceControlService} from '@shipfox/api-integration-core';\nimport {\n PROJECT_CREATED,\n PROJECT_SOURCE_BOUND,\n type ProjectsEventMap,\n} from '@shipfox/api-projects-dto';\nimport {writeOutboxEvent} from '@shipfox/node-outbox';\nimport {and, eq} from 'drizzle-orm';\nimport {db} from '#db/db.js';\nimport {projectsOutbox} from '#db/schema/outbox.js';\nimport {projects, toProject} from '#db/schema/projects.js';\nimport {recordProjectCreated} from '#metrics/instance.js';\nimport type {Project} from './entities/project.js';\nimport {ProjectAlreadyExistsError} from './errors.js';\n\nexport interface CreateProjectFromSourceParams {\n actorId: string;\n workspaceId: string;\n name: string;\n sourceConnectionId: string;\n sourceExternalRepositoryId: string;\n sourceControl: IntegrationSourceControlService;\n}\n\nexport async function createProjectFromSource(\n params: CreateProjectFromSourceParams,\n): Promise<Project> {\n const source = await params.sourceControl.resolveRepository({\n workspaceId: params.workspaceId,\n connectionId: params.sourceConnectionId,\n externalRepositoryId: params.sourceExternalRepositoryId,\n });\n\n const project = await db().transaction(async (tx) => {\n const [projectRow] = await tx\n .insert(projects)\n .values({\n workspaceId: params.workspaceId,\n sourceConnectionId: source.connection.id,\n sourceExternalRepositoryId: source.repository.externalRepositoryId,\n name: params.name,\n })\n .onConflictDoNothing({\n target: [projects.sourceConnectionId, projects.sourceExternalRepositoryId],\n })\n .returning();\n\n if (!projectRow) {\n const [existing] = await tx\n .select()\n .from(projects)\n .where(\n and(\n eq(projects.sourceConnectionId, source.connection.id),\n eq(projects.sourceExternalRepositoryId, source.repository.externalRepositoryId),\n ),\n )\n .limit(1);\n if (existing) {\n throw new ProjectAlreadyExistsError(\n existing.id,\n source.connection.id,\n source.repository.externalRepositoryId,\n );\n }\n throw new Error('Project insert returned no rows');\n }\n\n const project = toProject(projectRow);\n\n await writeOutboxEvent<ProjectsEventMap>(tx, projectsOutbox, {\n type: PROJECT_CREATED,\n payload: {\n actorId: params.actorId,\n workspaceId: project.workspaceId,\n projectId: project.id,\n sourceConnectionId: project.sourceConnectionId,\n sourceExternalRepositoryId: project.sourceExternalRepositoryId,\n },\n });\n await writeOutboxEvent<ProjectsEventMap>(tx, projectsOutbox, {\n type: PROJECT_SOURCE_BOUND,\n payload: {\n actorId: params.actorId,\n workspaceId: project.workspaceId,\n projectId: project.id,\n sourceConnectionId: project.sourceConnectionId,\n provider: source.connection.provider,\n externalRepositoryId: project.sourceExternalRepositoryId,\n },\n });\n\n return project;\n });\n recordProjectCreated();\n return project;\n}\n"],"names":["PROJECT_CREATED","PROJECT_SOURCE_BOUND","writeOutboxEvent","and","eq","db","projectsOutbox","projects","toProject","recordProjectCreated","ProjectAlreadyExistsError","createProjectFromSource","params","source","sourceControl","resolveRepository","workspaceId","connectionId","sourceConnectionId","externalRepositoryId","sourceExternalRepositoryId","project","transaction","tx","projectRow","insert","values","connection","id","repository","name","onConflictDoNothing","target","returning","existing","select","from","where","limit","Error","type","payload","actorId","projectId","provider"],"mappings":"AACA,SACEA,eAAe,EACfC,oBAAoB,QAEf,4BAA4B;AACnC,SAAQC,gBAAgB,QAAO,uBAAuB;AACtD,SAAQC,GAAG,EAAEC,EAAE,QAAO,cAAc;AACpC,SAAQC,EAAE,QAAO,YAAY;AAC7B,SAAQC,cAAc,QAAO,uBAAuB;AACpD,SAAQC,QAAQ,EAAEC,SAAS,QAAO,yBAAyB;AAC3D,SAAQC,oBAAoB,QAAO,uBAAuB;AAE1D,SAAQC,yBAAyB,QAAO,cAAc;AAWtD,OAAO,eAAeC,wBACpBC,MAAqC;IAErC,MAAMC,SAAS,MAAMD,OAAOE,aAAa,CAACC,iBAAiB,CAAC;QAC1DC,aAAaJ,OAAOI,WAAW;QAC/BC,cAAcL,OAAOM,kBAAkB;QACvCC,sBAAsBP,OAAOQ,0BAA0B;IACzD;IAEA,MAAMC,UAAU,MAAMhB,KAAKiB,WAAW,CAAC,OAAOC;QAC5C,MAAM,CAACC,WAAW,GAAG,MAAMD,GACxBE,MAAM,CAAClB,UACPmB,MAAM,CAAC;YACNV,aAAaJ,OAAOI,WAAW;YAC/BE,oBAAoBL,OAAOc,UAAU,CAACC,EAAE;YACxCR,4BAA4BP,OAAOgB,UAAU,CAACV,oBAAoB;YAClEW,MAAMlB,OAAOkB,IAAI;QACnB,GACCC,mBAAmB,CAAC;YACnBC,QAAQ;gBAACzB,SAASW,kBAAkB;gBAAEX,SAASa,0BAA0B;aAAC;QAC5E,GACCa,SAAS;QAEZ,IAAI,CAACT,YAAY;YACf,MAAM,CAACU,SAAS,GAAG,MAAMX,GACtBY,MAAM,GACNC,IAAI,CAAC7B,UACL8B,KAAK,CACJlC,IACEC,GAAGG,SAASW,kBAAkB,EAAEL,OAAOc,UAAU,CAACC,EAAE,GACpDxB,GAAGG,SAASa,0BAA0B,EAAEP,OAAOgB,UAAU,CAACV,oBAAoB,IAGjFmB,KAAK,CAAC;YACT,IAAIJ,UAAU;gBACZ,MAAM,IAAIxB,0BACRwB,SAASN,EAAE,EACXf,OAAOc,UAAU,CAACC,EAAE,EACpBf,OAAOgB,UAAU,CAACV,oBAAoB;YAE1C;YACA,MAAM,IAAIoB,MAAM;QAClB;QAEA,MAAMlB,UAAUb,UAAUgB;QAE1B,MAAMtB,iBAAmCqB,IAAIjB,gBAAgB;YAC3DkC,MAAMxC;YACNyC,SAAS;gBACPC,SAAS9B,OAAO8B,OAAO;gBACvB1B,aAAaK,QAAQL,WAAW;gBAChC2B,WAAWtB,QAAQO,EAAE;gBACrBV,oBAAoBG,QAAQH,kBAAkB;gBAC9CE,4BAA4BC,QAAQD,0BAA0B;YAChE;QACF;QACA,MAAMlB,iBAAmCqB,IAAIjB,gBAAgB;YAC3DkC,MAAMvC;YACNwC,SAAS;gBACPC,SAAS9B,OAAO8B,OAAO;gBACvB1B,aAAaK,QAAQL,WAAW;gBAChC2B,WAAWtB,QAAQO,EAAE;gBACrBV,oBAAoBG,QAAQH,kBAAkB;gBAC9C0B,UAAU/B,OAAOc,UAAU,CAACiB,QAAQ;gBACpCzB,sBAAsBE,QAAQD,0BAA0B;YAC1D;QACF;QAEA,OAAOC;IACT;IACAZ;IACA,OAAOY;AACT"}