@ttctl/core 0.0.0 → 0.1.0-rc.1

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 (195) hide show
  1. package/README.md +49 -9
  2. package/dist/__generated__/gateway.d.ts +4546 -0
  3. package/dist/__generated__/gateway.d.ts.map +1 -0
  4. package/dist/__generated__/gateway.js +9 -0
  5. package/dist/__generated__/gateway.js.map +1 -0
  6. package/dist/__generated__/talent-profile-zod-schemas.d.ts +1187 -0
  7. package/dist/__generated__/talent-profile-zod-schemas.d.ts.map +1 -0
  8. package/dist/__generated__/talent-profile-zod-schemas.js +1136 -0
  9. package/dist/__generated__/talent-profile-zod-schemas.js.map +1 -0
  10. package/dist/__generated__/talent-profile.d.ts +1397 -0
  11. package/dist/__generated__/talent-profile.d.ts.map +1 -0
  12. package/dist/__generated__/talent-profile.js +9 -0
  13. package/dist/__generated__/talent-profile.js.map +1 -0
  14. package/dist/__generated__/zod-schemas.d.ts +2895 -0
  15. package/dist/__generated__/zod-schemas.d.ts.map +1 -0
  16. package/dist/__generated__/zod-schemas.js +3121 -0
  17. package/dist/__generated__/zod-schemas.js.map +1 -0
  18. package/dist/__tests__/fixtures/profile/builders.d.ts +74 -0
  19. package/dist/__tests__/fixtures/profile/builders.d.ts.map +1 -0
  20. package/dist/__tests__/fixtures/profile/builders.js +196 -0
  21. package/dist/__tests__/fixtures/profile/builders.js.map +1 -0
  22. package/dist/__tests__/fixtures/profile/data.d.ts +39 -0
  23. package/dist/__tests__/fixtures/profile/data.d.ts.map +1 -0
  24. package/dist/__tests__/fixtures/profile/data.js +230 -0
  25. package/dist/__tests__/fixtures/profile/data.js.map +1 -0
  26. package/dist/__tests__/fixtures/profile/index.d.ts +9 -0
  27. package/dist/__tests__/fixtures/profile/index.d.ts.map +1 -0
  28. package/dist/__tests__/fixtures/profile/index.js +10 -0
  29. package/dist/__tests__/fixtures/profile/index.js.map +1 -0
  30. package/dist/__tests__/fixtures/profile/types.d.ts +53 -0
  31. package/dist/__tests__/fixtures/profile/types.d.ts.map +1 -0
  32. package/dist/__tests__/fixtures/profile/types.js +4 -0
  33. package/dist/__tests__/fixtures/profile/types.js.map +1 -0
  34. package/dist/auth/errors.d.ts +82 -0
  35. package/dist/auth/errors.d.ts.map +1 -0
  36. package/dist/auth/errors.js +68 -0
  37. package/dist/auth/errors.js.map +1 -0
  38. package/dist/auth.d.ts +192 -0
  39. package/dist/auth.d.ts.map +1 -0
  40. package/dist/auth.js +294 -0
  41. package/dist/auth.js.map +1 -0
  42. package/dist/config.d.ts +212 -0
  43. package/dist/config.d.ts.map +1 -0
  44. package/dist/config.js +349 -0
  45. package/dist/config.js.map +1 -0
  46. package/dist/configLock.d.ts +50 -0
  47. package/dist/configLock.d.ts.map +1 -0
  48. package/dist/configLock.js +88 -0
  49. package/dist/configLock.js.map +1 -0
  50. package/dist/configWriter.d.ts +97 -0
  51. package/dist/configWriter.d.ts.map +1 -0
  52. package/dist/configWriter.js +687 -0
  53. package/dist/configWriter.js.map +1 -0
  54. package/dist/index.d.ts +37 -0
  55. package/dist/index.d.ts.map +1 -0
  56. package/dist/index.js +28 -0
  57. package/dist/index.js.map +1 -0
  58. package/dist/kill-switch.d.ts +161 -0
  59. package/dist/kill-switch.d.ts.map +1 -0
  60. package/dist/kill-switch.js +235 -0
  61. package/dist/kill-switch.js.map +1 -0
  62. package/dist/lib/date.d.ts +58 -0
  63. package/dist/lib/date.d.ts.map +1 -0
  64. package/dist/lib/date.js +104 -0
  65. package/dist/lib/date.js.map +1 -0
  66. package/dist/lib/diagnostic-log.d.ts +159 -0
  67. package/dist/lib/diagnostic-log.d.ts.map +1 -0
  68. package/dist/lib/diagnostic-log.js +186 -0
  69. package/dist/lib/diagnostic-log.js.map +1 -0
  70. package/dist/lib/package-version.d.ts +19 -0
  71. package/dist/lib/package-version.d.ts.map +1 -0
  72. package/dist/lib/package-version.js +38 -0
  73. package/dist/lib/package-version.js.map +1 -0
  74. package/dist/lib/redact.d.ts +153 -0
  75. package/dist/lib/redact.d.ts.map +1 -0
  76. package/dist/lib/redact.js +207 -0
  77. package/dist/lib/redact.js.map +1 -0
  78. package/dist/lib/text.d.ts +14 -0
  79. package/dist/lib/text.d.ts.map +1 -0
  80. package/dist/lib/text.js +21 -0
  81. package/dist/lib/text.js.map +1 -0
  82. package/dist/lib/wire-shape.d.ts +131 -0
  83. package/dist/lib/wire-shape.d.ts.map +1 -0
  84. package/dist/lib/wire-shape.js +376 -0
  85. package/dist/lib/wire-shape.js.map +1 -0
  86. package/dist/onepassword.d.ts +29 -0
  87. package/dist/onepassword.d.ts.map +1 -0
  88. package/dist/onepassword.js +112 -0
  89. package/dist/onepassword.js.map +1 -0
  90. package/dist/services/_shared/transport.d.ts +148 -0
  91. package/dist/services/_shared/transport.d.ts.map +1 -0
  92. package/dist/services/_shared/transport.js +102 -0
  93. package/dist/services/_shared/transport.js.map +1 -0
  94. package/dist/services/applications/index.d.ts +210 -0
  95. package/dist/services/applications/index.d.ts.map +1 -0
  96. package/dist/services/applications/index.js +240 -0
  97. package/dist/services/applications/index.js.map +1 -0
  98. package/dist/services/availability/index.d.ts +254 -0
  99. package/dist/services/availability/index.d.ts.map +1 -0
  100. package/dist/services/availability/index.js +310 -0
  101. package/dist/services/availability/index.js.map +1 -0
  102. package/dist/services/contracts/index.d.ts +132 -0
  103. package/dist/services/contracts/index.d.ts.map +1 -0
  104. package/dist/services/contracts/index.js +211 -0
  105. package/dist/services/contracts/index.js.map +1 -0
  106. package/dist/services/engagements/index.d.ts +504 -0
  107. package/dist/services/engagements/index.d.ts.map +1 -0
  108. package/dist/services/engagements/index.js +613 -0
  109. package/dist/services/engagements/index.js.map +1 -0
  110. package/dist/services/jobs/index.d.ts +490 -0
  111. package/dist/services/jobs/index.d.ts.map +1 -0
  112. package/dist/services/jobs/index.js +753 -0
  113. package/dist/services/jobs/index.js.map +1 -0
  114. package/dist/services/payments/index.d.ts +415 -0
  115. package/dist/services/payments/index.d.ts.map +1 -0
  116. package/dist/services/payments/index.js +636 -0
  117. package/dist/services/payments/index.js.map +1 -0
  118. package/dist/services/profile/__tests__/fixtures.d.ts +214 -0
  119. package/dist/services/profile/__tests__/fixtures.d.ts.map +1 -0
  120. package/dist/services/profile/__tests__/fixtures.js +176 -0
  121. package/dist/services/profile/__tests__/fixtures.js.map +1 -0
  122. package/dist/services/profile/basic/index.d.ts +390 -0
  123. package/dist/services/profile/basic/index.d.ts.map +1 -0
  124. package/dist/services/profile/basic/index.js +1007 -0
  125. package/dist/services/profile/basic/index.js.map +1 -0
  126. package/dist/services/profile/certifications/index.d.ts +74 -0
  127. package/dist/services/profile/certifications/index.d.ts.map +1 -0
  128. package/dist/services/profile/certifications/index.js +169 -0
  129. package/dist/services/profile/certifications/index.js.map +1 -0
  130. package/dist/services/profile/education/index.d.ts +73 -0
  131. package/dist/services/profile/education/index.d.ts.map +1 -0
  132. package/dist/services/profile/education/index.js +168 -0
  133. package/dist/services/profile/education/index.js.map +1 -0
  134. package/dist/services/profile/employment/index.d.ts +111 -0
  135. package/dist/services/profile/employment/index.d.ts.map +1 -0
  136. package/dist/services/profile/employment/index.js +202 -0
  137. package/dist/services/profile/employment/index.js.map +1 -0
  138. package/dist/services/profile/external/index.d.ts +219 -0
  139. package/dist/services/profile/external/index.d.ts.map +1 -0
  140. package/dist/services/profile/external/index.js +560 -0
  141. package/dist/services/profile/external/index.js.map +1 -0
  142. package/dist/services/profile/index.d.ts +24 -0
  143. package/dist/services/profile/index.d.ts.map +1 -0
  144. package/dist/services/profile/index.js +26 -0
  145. package/dist/services/profile/index.js.map +1 -0
  146. package/dist/services/profile/industries/index.d.ts +130 -0
  147. package/dist/services/profile/industries/index.d.ts.map +1 -0
  148. package/dist/services/profile/industries/index.js +292 -0
  149. package/dist/services/profile/industries/index.js.map +1 -0
  150. package/dist/services/profile/portfolio/index.d.ts +352 -0
  151. package/dist/services/profile/portfolio/index.d.ts.map +1 -0
  152. package/dist/services/profile/portfolio/index.js +833 -0
  153. package/dist/services/profile/portfolio/index.js.map +1 -0
  154. package/dist/services/profile/resume/index.d.ts +60 -0
  155. package/dist/services/profile/resume/index.d.ts.map +1 -0
  156. package/dist/services/profile/resume/index.js +212 -0
  157. package/dist/services/profile/resume/index.js.map +1 -0
  158. package/dist/services/profile/reviews/index.d.ts +137 -0
  159. package/dist/services/profile/reviews/index.d.ts.map +1 -0
  160. package/dist/services/profile/reviews/index.js +431 -0
  161. package/dist/services/profile/reviews/index.js.map +1 -0
  162. package/dist/services/profile/shared.d.ts +127 -0
  163. package/dist/services/profile/shared.d.ts.map +1 -0
  164. package/dist/services/profile/shared.js +155 -0
  165. package/dist/services/profile/shared.js.map +1 -0
  166. package/dist/services/profile/skills/index.d.ts +212 -0
  167. package/dist/services/profile/skills/index.d.ts.map +1 -0
  168. package/dist/services/profile/skills/index.js +461 -0
  169. package/dist/services/profile/skills/index.js.map +1 -0
  170. package/dist/services/profile/visas/index.d.ts +74 -0
  171. package/dist/services/profile/visas/index.d.ts.map +1 -0
  172. package/dist/services/profile/visas/index.js +306 -0
  173. package/dist/services/profile/visas/index.js.map +1 -0
  174. package/dist/services/timesheet/index.d.ts +326 -0
  175. package/dist/services/timesheet/index.d.ts.map +1 -0
  176. package/dist/services/timesheet/index.js +324 -0
  177. package/dist/services/timesheet/index.js.map +1 -0
  178. package/dist/services/translations.d.ts +79 -0
  179. package/dist/services/translations.d.ts.map +1 -0
  180. package/dist/services/translations.js +136 -0
  181. package/dist/services/translations.js.map +1 -0
  182. package/dist/transport-resilience.d.ts +136 -0
  183. package/dist/transport-resilience.d.ts.map +1 -0
  184. package/dist/transport-resilience.js +247 -0
  185. package/dist/transport-resilience.js.map +1 -0
  186. package/dist/transport.d.ts +408 -0
  187. package/dist/transport.d.ts.map +1 -0
  188. package/dist/transport.js +691 -0
  189. package/dist/transport.js.map +1 -0
  190. package/dist/types.d.ts +41 -0
  191. package/dist/types.d.ts.map +1 -0
  192. package/dist/types.js +18 -0
  193. package/dist/types.js.map +1 -0
  194. package/package.json +40 -12
  195. package/index.js +0 -7
@@ -0,0 +1,613 @@
1
+ // SPDX-License-Identifier: AGPL-3.0-only
2
+ // Copyright (C) 2026 Oleksii PELYKH
3
+ import { buildDryRunPreview } from "../../transport.js";
4
+ import { callGatewayShared } from "../_shared/transport.js";
5
+ export class EngagementsError extends Error {
6
+ code;
7
+ name = "EngagementsError";
8
+ constructor(code, message, options) {
9
+ super(message, options);
10
+ this.code = code;
11
+ }
12
+ }
13
+ /**
14
+ * Engagement-bearing status groups in `JobActivityItemStatusGroupEnum`.
15
+ * Used both by `list` (default filter) and `stats` (per-group counts).
16
+ *
17
+ * Note: `ARCHIVED` is intentionally NOT included — that group includes
18
+ * archived non-engagement items too (archived applications, archived
19
+ * interviews). Users wanting an archived engagement view should use
20
+ * `applications list --status-group ARCHIVED` and filter further.
21
+ */
22
+ export const ENGAGEMENT_STATUS_GROUPS = ["ACTIVE_ENGAGEMENT", "CLOSED_ENGAGEMENT"];
23
+ /**
24
+ * Public `--status` filter values for `list`. Maps to one or both
25
+ * {@link ENGAGEMENT_STATUS_GROUPS} entries.
26
+ */
27
+ export const ENGAGEMENT_LIST_STATUSES = ["active", "past", "all"];
28
+ function listStatusToGroups(status) {
29
+ switch (status) {
30
+ case "active":
31
+ return ["ACTIVE_ENGAGEMENT"];
32
+ case "past":
33
+ return ["CLOSED_ENGAGEMENT"];
34
+ case "all":
35
+ return ["ACTIVE_ENGAGEMENT", "CLOSED_ENGAGEMENT"];
36
+ }
37
+ }
38
+ // ---------------------------------------------------------------------
39
+ // GraphQL operation strings
40
+ //
41
+ // `JobActivityItems` and `JobActivityItem` are reused operation names
42
+ // (matching the captured operations) with selection sets specifically
43
+ // tailored to the engagement projection.
44
+ //
45
+ // Break operations are used VERBATIM from the captured documents in
46
+ // `../research/graphql/gateway/operations/mobile/`.
47
+ // ---------------------------------------------------------------------
48
+ const ENGAGEMENTS_LIST_QUERY = `query JobActivityItems($keywords: [String!], $onlyStatusGroupFilter: [JobActivityItemStatusGroupEnum!]) {
49
+ viewer {
50
+ __typename
51
+ id
52
+ jobActivityList(keywords: $keywords, statusGroupV2: { only: $onlyStatusGroupFilter }) {
53
+ __typename
54
+ entities {
55
+ __typename
56
+ id
57
+ statusV2 { __typename value verbose }
58
+ statusGroupV2 { __typename value verbose }
59
+ statusColor
60
+ lastUpdatedAt
61
+ job {
62
+ __typename
63
+ id
64
+ title
65
+ url
66
+ client { __typename id fullName }
67
+ }
68
+ engagement {
69
+ __typename
70
+ id
71
+ startDate
72
+ endDate
73
+ expectedHours
74
+ commitment { __typename slug }
75
+ }
76
+ }
77
+ totalCount
78
+ }
79
+ }
80
+ }`;
81
+ const ENGAGEMENT_SHOW_QUERY = `query JobActivityItem($id: ID!) {
82
+ viewer {
83
+ __typename
84
+ id
85
+ jobActivityItem(id: $id) {
86
+ __typename
87
+ id
88
+ statusV2 { __typename value verbose }
89
+ statusGroupV2 { __typename value verbose }
90
+ statusColor
91
+ lastUpdatedAt
92
+ job {
93
+ __typename
94
+ id
95
+ title
96
+ url
97
+ descriptionMd
98
+ expectedHours
99
+ startDate
100
+ commitment { __typename slug }
101
+ workType { __typename slug }
102
+ specialization { __typename title }
103
+ isCoaching
104
+ isToptalProject
105
+ client { __typename id fullName }
106
+ }
107
+ engagement {
108
+ __typename
109
+ id
110
+ startDate
111
+ endDate
112
+ expectedHours
113
+ commitment { __typename slug }
114
+ eligibleForPayment
115
+ eligibleToViewTimesheets
116
+ eligibleToViewTimeOffs
117
+ billCycle { __typename verbose }
118
+ currentAgreement {
119
+ __typename
120
+ applicationRate
121
+ talentHourlyRate
122
+ talentRate
123
+ marketplaceMargin
124
+ timePeriod
125
+ commitment { __typename slug }
126
+ }
127
+ earning {
128
+ __typename
129
+ paid { __typename decimal }
130
+ }
131
+ proposedEnd { __typename endDate status }
132
+ engagementBreaks {
133
+ __typename
134
+ ...engagementBreakData
135
+ }
136
+ }
137
+ }
138
+ }
139
+ }
140
+
141
+ fragment engagementBreakData on TalentEngagementBreak {
142
+ __typename
143
+ id
144
+ startDate
145
+ endDate
146
+ comment
147
+ operations {
148
+ __typename
149
+ removeEngagementBreak { __typename callable }
150
+ rescheduleEngagementBreak { __typename callable }
151
+ }
152
+ }`;
153
+ // Verbatim from `../research/graphql/gateway/operations/mobile/EngagementBreaks.graphql`.
154
+ const ENGAGEMENT_BREAKS_QUERY = `query EngagementBreaks($jobActivityItemId: ID!) { viewer { __typename id jobActivityItem(id: $jobActivityItemId) { __typename id engagement { __typename id engagementBreaks { __typename ...engagementBreakData } } } } } fragment engagementBreakData on TalentEngagementBreak { __typename id startDate endDate comment operations { __typename removeEngagementBreak { __typename callable } rescheduleEngagementBreak { __typename callable } } }`;
155
+ // Verbatim from `../research/graphql/gateway/operations/mobile/CreateEngagementBreak.graphql`.
156
+ const CREATE_ENGAGEMENT_BREAK_MUTATION = `mutation CreateEngagementBreak($engagementId: ID!, $startDate: Date!, $endDate: Date!, $reasonIdentifier: String!, $comment: String) { engagement(id: $engagementId) { __typename createBreak(input: { startDate: $startDate endDate: $endDate reasonIdentifier: $reasonIdentifier comment: $comment } ) { __typename ...mutationResultFields break { __typename ...engagementBreakData engagement { __typename id engagementBreaks { __typename id } } } } } } fragment mutationResultFields on MutationResult { __typename errors { __typename key message code } success } fragment engagementBreakData on TalentEngagementBreak { __typename id startDate endDate comment operations { __typename removeEngagementBreak { __typename callable } rescheduleEngagementBreak { __typename callable } } }`;
157
+ // Verbatim from `../research/graphql/gateway/operations/mobile/CancelEngagementBreak.graphql`.
158
+ const CANCEL_ENGAGEMENT_BREAK_MUTATION = `mutation CancelEngagementBreak($engagementBreakId: ID!) { engagementBreak(id: $engagementBreakId) { __typename cancel(input: { } ) { __typename ...mutationResultFields break { __typename id engagement { __typename id engagementBreaks { __typename id } } } } } } fragment mutationResultFields on MutationResult { __typename errors { __typename key message code } success }`;
159
+ // Verbatim from `../research/graphql/gateway/operations/mobile/RescheduleEngagementBreak.graphql` (#155).
160
+ const RESCHEDULE_ENGAGEMENT_BREAK_MUTATION = `mutation RescheduleEngagementBreak($engagementBreakId: ID!, $startDate: Date!, $endDate: Date!) { engagementBreak(id: $engagementBreakId) { __typename reschedule(input: { startDate: $startDate endDate: $endDate } ) { __typename ...mutationResultFields break { __typename ...engagementBreakData } } } } fragment mutationResultFields on MutationResult { __typename errors { __typename key message code } success } fragment engagementBreakData on TalentEngagementBreak { __typename id startDate endDate comment operations { __typename removeEngagementBreak { __typename callable } rescheduleEngagementBreak { __typename callable } } }`;
161
+ // Minimal projection on `PlatformConfiguration` — we only need the
162
+ // `engagementBreakReasons` field for the reasons-catalog discovery
163
+ // query, NOT the full platformConfigurationData fragment captured in
164
+ // `../research/graphql/gateway/operations/mobile/PlatformConfiguration.graphql`.
165
+ // The narrower projection keeps the round-trip cheap and the test
166
+ // surface focused; the full fragment is available in the research
167
+ // repo if other engagement code later needs more fields.
168
+ //
169
+ // Per CLAUDE.md § Schema/contract validation rule, this operation is
170
+ // hand-authored (NOT in `codegen.config.ts` documents) → mandatory live
171
+ // E2E coverage. See `packages/e2e/src/29-engagements-breaks-reasons.e2e.test.ts`.
172
+ const ENGAGEMENT_BREAK_REASONS_QUERY = `query PlatformConfiguration { platformConfiguration { __typename id engagementBreakReasons { __typename identifier nameForRole } } }`;
173
+ const NOT_FOUND_MESSAGE_PATTERN = /Record not found/i;
174
+ /**
175
+ * Thin per-service wrapper around {@link callGatewayShared} (issue
176
+ * #329). Pins the mobile-gateway surface and the
177
+ * {@link EngagementsError} domain class.
178
+ */
179
+ async function callGateway(token, operationName, query, variables, schema) {
180
+ return callGatewayShared("mobile-gateway", token, operationName, query, variables, EngagementsError, { schema });
181
+ }
182
+ /**
183
+ * Project a wire `EngagementsListEntity` into the public
184
+ * {@link EngagementListItem} shape. Engagement subobject may be null
185
+ * (defensive — though a status filter of ACTIVE_ENGAGEMENT or
186
+ * CLOSED_ENGAGEMENT should always return rows with an engagement).
187
+ */
188
+ function projectListItem(entity) {
189
+ return {
190
+ id: entity.id,
191
+ engagementId: entity.engagement?.id ?? null,
192
+ statusV2: entity.statusV2,
193
+ statusGroupV2: entity.statusGroupV2,
194
+ statusColor: entity.statusColor,
195
+ lastUpdatedAt: entity.lastUpdatedAt,
196
+ job: entity.job,
197
+ startDate: entity.engagement?.startDate ?? null,
198
+ endDate: entity.engagement?.endDate ?? null,
199
+ expectedHours: entity.engagement?.expectedHours ?? null,
200
+ commitment: entity.engagement?.commitment ?? null,
201
+ };
202
+ }
203
+ /**
204
+ * List the signed-in user's engagements.
205
+ *
206
+ * Default scope is active engagements only (`status: "active"` →
207
+ * `ACTIVE_ENGAGEMENT`). `status: "past"` returns closed engagements
208
+ * (`CLOSED_ENGAGEMENT`); `status: "all"` returns both.
209
+ *
210
+ * The returned array preserves server order; the CLI / MCP do not
211
+ * re-sort.
212
+ */
213
+ export async function list(token, opts = {}) {
214
+ const status = opts.status ?? "active";
215
+ const groups = listStatusToGroups(status);
216
+ const variables = {
217
+ keywords: opts.keywords !== undefined && opts.keywords.length > 0 ? opts.keywords : null,
218
+ onlyStatusGroupFilter: groups,
219
+ };
220
+ const data = await callGateway(token, "JobActivityItems", ENGAGEMENTS_LIST_QUERY, variables);
221
+ if (data.viewer === null) {
222
+ throw new EngagementsError("NO_VIEWER", "Session is valid but no viewer is bound to it.");
223
+ }
224
+ if (data.viewer.jobActivityList === null) {
225
+ return [];
226
+ }
227
+ return (data.viewer.jobActivityList.entities ?? []).map(projectListItem);
228
+ }
229
+ /**
230
+ * Fetch a single engagement's detail by `jobActivityItem.id`.
231
+ *
232
+ * Throws `EngagementsError("NOT_FOUND")` when the id doesn't resolve
233
+ * (matches `applications.show` semantics — both the
234
+ * "Record not found" GraphQL error path AND the data-shape sentinel
235
+ * `viewer.jobActivityItem === null`).
236
+ *
237
+ * Throws `EngagementsError("NO_ENGAGEMENT")` when the row exists but
238
+ * has no engagement (e.g., an interview-only row that never reached
239
+ * engagement status).
240
+ */
241
+ export async function show(token, id) {
242
+ let data;
243
+ try {
244
+ data = await callGateway(token, "JobActivityItem", ENGAGEMENT_SHOW_QUERY, { id });
245
+ }
246
+ catch (err) {
247
+ if (err instanceof EngagementsError &&
248
+ err.code === "GRAPHQL_ERROR" &&
249
+ NOT_FOUND_MESSAGE_PATTERN.test(err.message)) {
250
+ throw new EngagementsError("NOT_FOUND", `No engagement found with id "${id}" (or you don't have access to it).`, {
251
+ cause: err,
252
+ });
253
+ }
254
+ throw err;
255
+ }
256
+ if (data.viewer === null) {
257
+ throw new EngagementsError("NO_VIEWER", "Session is valid but no viewer is bound to it.");
258
+ }
259
+ if (data.viewer.jobActivityItem === null) {
260
+ throw new EngagementsError("NOT_FOUND", `No engagement found with id "${id}" (or you don't have access to it).`);
261
+ }
262
+ const item = data.viewer.jobActivityItem;
263
+ if (item.engagement === null) {
264
+ throw new EngagementsError("NO_ENGAGEMENT", `Activity item "${id}" exists but has no engagement (likely an application or interview that never became an engagement).`);
265
+ }
266
+ return {
267
+ id: item.id,
268
+ engagementId: item.engagement.id,
269
+ statusV2: item.statusV2,
270
+ statusGroupV2: item.statusGroupV2,
271
+ statusColor: item.statusColor,
272
+ lastUpdatedAt: item.lastUpdatedAt,
273
+ job: item.job,
274
+ startDate: item.engagement.startDate,
275
+ endDate: item.engagement.endDate,
276
+ expectedHours: item.engagement.expectedHours,
277
+ commitment: item.engagement.commitment,
278
+ currentAgreement: item.engagement.currentAgreement,
279
+ billCycle: item.engagement.billCycle,
280
+ earning: item.engagement.earning,
281
+ eligibleForPayment: item.engagement.eligibleForPayment,
282
+ eligibleToViewTimesheets: item.engagement.eligibleToViewTimesheets,
283
+ eligibleToViewTimeOffs: item.engagement.eligibleToViewTimeOffs,
284
+ proposedEnd: item.engagement.proposedEnd,
285
+ breaks: item.engagement.engagementBreaks ?? [],
286
+ };
287
+ }
288
+ /**
289
+ * Aggregate per-engagement-status-group counts plus the overall total.
290
+ * Issues 2 calls in parallel (one per {@link ENGAGEMENT_STATUS_GROUPS}
291
+ * value).
292
+ *
293
+ * Each `count` is server-provided (`totalCount`), no client-side
294
+ * synthesis.
295
+ */
296
+ export async function stats(token) {
297
+ const groupResults = await Promise.all(ENGAGEMENT_STATUS_GROUPS.map(async (group) => {
298
+ const data = await callGateway(token, "JobActivityItems", ENGAGEMENTS_LIST_QUERY, {
299
+ keywords: null,
300
+ onlyStatusGroupFilter: [group],
301
+ });
302
+ const count = data.viewer?.jobActivityList?.totalCount ?? 0;
303
+ return { name: group, count };
304
+ }));
305
+ const total = groupResults.reduce((sum, g) => sum + g.count, 0);
306
+ return { total, groups: groupResults };
307
+ }
308
+ /**
309
+ * Internal: fetch the underlying `engagement.id` from a
310
+ * `jobActivityItem.id`. Used by `breaks.add` (which needs the
311
+ * engagement id for the mutation root) since the public CLI/MCP
312
+ * surface accepts the activity-item id.
313
+ *
314
+ * Reuses `EngagementBreaks` query (it returns engagement.id alongside
315
+ * the breaks list) so this is a normal query, not an extra round-trip
316
+ * specifically for id translation.
317
+ *
318
+ * Throws `EngagementsError("NOT_FOUND")` / `"NO_ENGAGEMENT"` with
319
+ * matching semantics to `show()`.
320
+ */
321
+ async function fetchEngagementBreaksAndId(token, jobActivityItemId) {
322
+ let data;
323
+ try {
324
+ data = await callGateway(token, "EngagementBreaks", ENGAGEMENT_BREAKS_QUERY, {
325
+ jobActivityItemId,
326
+ });
327
+ }
328
+ catch (err) {
329
+ if (err instanceof EngagementsError &&
330
+ err.code === "GRAPHQL_ERROR" &&
331
+ NOT_FOUND_MESSAGE_PATTERN.test(err.message)) {
332
+ throw new EngagementsError("NOT_FOUND", `No engagement found with id "${jobActivityItemId}" (or you don't have access to it).`, { cause: err });
333
+ }
334
+ throw err;
335
+ }
336
+ if (data.viewer === null) {
337
+ throw new EngagementsError("NO_VIEWER", "Session is valid but no viewer is bound to it.");
338
+ }
339
+ if (data.viewer.jobActivityItem === null) {
340
+ throw new EngagementsError("NOT_FOUND", `No engagement found with id "${jobActivityItemId}" (or you don't have access to it).`);
341
+ }
342
+ if (data.viewer.jobActivityItem.engagement === null) {
343
+ throw new EngagementsError("NO_ENGAGEMENT", `Activity item "${jobActivityItemId}" exists but has no engagement.`);
344
+ }
345
+ return {
346
+ engagementId: data.viewer.jobActivityItem.engagement.id,
347
+ breaks: data.viewer.jobActivityItem.engagement.engagementBreaks ?? [],
348
+ };
349
+ }
350
+ function formatMutationErrors(prefix, errors) {
351
+ if (errors == null || errors.length === 0) {
352
+ return `${prefix}: no error detail returned.`;
353
+ }
354
+ const parts = errors.map((e) => {
355
+ const fields = [];
356
+ if (e.code != null)
357
+ fields.push(`code=${e.code}`);
358
+ if (e.key != null)
359
+ fields.push(`key=${e.key}`);
360
+ const head = fields.length > 0 ? `[${fields.join(", ")}] ` : "";
361
+ return `${head}${e.message ?? "(no message)"}`;
362
+ });
363
+ return `${prefix}: ${parts.join("; ")}`;
364
+ }
365
+ /**
366
+ * Engagement breaks management. Sub-namespace under the service so the
367
+ * public surface stays `engagements.breaks.{list, add, remove, reschedule}` —
368
+ * matches the CLI verb path `engagements breaks {list, add, remove, reschedule}`.
369
+ */
370
+ export const breaks = {
371
+ /**
372
+ * List breaks for an engagement (by `jobActivityItem.id`).
373
+ *
374
+ * Reuses the captured `EngagementBreaks` operation verbatim. The
375
+ * returned array preserves server order.
376
+ */
377
+ async list(token, jobActivityItemId) {
378
+ const { breaks: breakList } = await fetchEngagementBreaksAndId(token, jobActivityItemId);
379
+ return breakList;
380
+ },
381
+ /**
382
+ * Schedule a new break on an engagement (by `jobActivityItem.id`).
383
+ *
384
+ * Internally fetches the underlying `engagement.id` first
385
+ * ({@link fetchEngagementBreaksAndId}) — adds one round-trip but
386
+ * keeps the CLI/MCP surface consistent (the user always passes the
387
+ * activity-item id, never the underlying engagement id).
388
+ *
389
+ * `reasonIdentifier` is the server-side reason key. The mutation
390
+ * marks it `String!` AND the server rejects empty strings (validated
391
+ * by live API: `code=blank, key=reasonId`), so the caller must
392
+ * supply a valid value — see {@link AddBreakOptions} for the known
393
+ * catalog and the discovery path.
394
+ *
395
+ * Throws `EngagementsError("MUTATION_ERROR")` when the gateway
396
+ * returns `success: false` (overlapping break dates, validation
397
+ * failures, etc.).
398
+ *
399
+ * Dry-run path (issue #163): when invoked with `options.dryRun ===
400
+ * true`, builds a {@link DryRunPreview} of the mutation WITHOUT
401
+ * invoking the gateway transport — including the prefetch
402
+ * `EngagementBreaks` query (per the AC's "no GraphQL request is
403
+ * sent" requirement). The preview's `variables.engagementId` is
404
+ * populated with the caller-supplied `jobActivityItemId` as a
405
+ * placeholder; the wire SHAPE (field names, operation, surface,
406
+ * redacted headers) is verbatim. The actual `engagement.id` resolves
407
+ * at apply time via the skipped prefetch.
408
+ */
409
+ async add(token, jobActivityItemId, opts, options = {}) {
410
+ if (options.dryRun === true) {
411
+ // Skip the prefetch entirely — the AC mandates zero transport
412
+ // calls in dry-run mode. The literal `jobActivityItemId` stands
413
+ // in for `engagementId` so the preview's variable structure
414
+ // matches the wire shape; the CLI envelope surfaces a `notice`
415
+ // explaining the deferred resolution.
416
+ const previewVariables = {
417
+ engagementId: jobActivityItemId,
418
+ startDate: opts.startDate,
419
+ endDate: opts.endDate,
420
+ reasonIdentifier: opts.reasonIdentifier,
421
+ comment: opts.comment ?? null,
422
+ };
423
+ return {
424
+ kind: "preview",
425
+ preview: buildDryRunPreview({
426
+ surface: "mobile-gateway",
427
+ authToken: token,
428
+ body: {
429
+ operationName: "CreateEngagementBreak",
430
+ query: CREATE_ENGAGEMENT_BREAK_MUTATION,
431
+ variables: previewVariables,
432
+ },
433
+ }),
434
+ };
435
+ }
436
+ const { engagementId } = await fetchEngagementBreaksAndId(token, jobActivityItemId);
437
+ const variables = {
438
+ engagementId,
439
+ startDate: opts.startDate,
440
+ endDate: opts.endDate,
441
+ reasonIdentifier: opts.reasonIdentifier,
442
+ comment: opts.comment ?? null,
443
+ };
444
+ const data = await callGateway(token, "CreateEngagementBreak", CREATE_ENGAGEMENT_BREAK_MUTATION, variables);
445
+ if (data.engagement === null) {
446
+ throw new EngagementsError("NOT_FOUND", `Engagement "${engagementId}" no longer exists.`);
447
+ }
448
+ const result = data.engagement.createBreak;
449
+ if (result === null) {
450
+ throw new EngagementsError("UNKNOWN", "CreateEngagementBreak returned a null payload.");
451
+ }
452
+ if (!result.success) {
453
+ throw new EngagementsError("MUTATION_ERROR", formatMutationErrors("CreateEngagementBreak failed", result.errors));
454
+ }
455
+ if (result.break === null) {
456
+ throw new EngagementsError("UNKNOWN", "CreateEngagementBreak returned success but the `break` payload was null.");
457
+ }
458
+ return { kind: "applied", result: result.break };
459
+ },
460
+ /**
461
+ * Fetch the engagement-break reasons catalog — the valid
462
+ * `--reason-id` values for {@link breaks.add}.
463
+ *
464
+ * Issues `PlatformConfiguration` against the mobile gateway with a
465
+ * minimal projection (`engagementBreakReasons { identifier
466
+ * nameForRole }`). Returns a defensively-cleaned, sorted-by-identifier
467
+ * list:
468
+ * - null wire entries (`[FeedbackReason]!` — list non-null but
469
+ * items nullable per Toptal SDL convention) are filtered out.
470
+ * - sort is locale-independent, case-insensitive on `identifier`
471
+ * so consumers get a stable, predictable order across runs.
472
+ *
473
+ * **CLAUDE.md schema/contract**: this operation is hand-authored
474
+ * (NOT in `codegen.config.ts`) → live E2E coverage required pre-merge.
475
+ * See `packages/e2e/src/29-engagements-breaks-reasons.e2e.test.ts`.
476
+ *
477
+ * `EngagementsError("NO_VIEWER")` is not raised here:
478
+ * `platformConfiguration` is a viewer-agnostic root field on the
479
+ * gateway (the catalog is the same regardless of viewer), so the
480
+ * `data.viewer === null` defensive branch from the other operations
481
+ * does not apply. Auth failures still surface via `AuthRevokedError`
482
+ * per the standard `callGateway` semantics.
483
+ */
484
+ async reasonsList(token) {
485
+ const data = await callGateway(token, "PlatformConfiguration", ENGAGEMENT_BREAK_REASONS_QUERY, {});
486
+ if (data.platformConfiguration === null) {
487
+ // Defensive: the gateway should never return null for this root
488
+ // field in practice, but the schema marks
489
+ // `platformConfiguration: PlatformConfiguration` as nullable, so
490
+ // cover the case rather than letting the wire-shape mismatch
491
+ // surface as a runtime TypeError.
492
+ return [];
493
+ }
494
+ const wireItems = data.platformConfiguration.engagementBreakReasons ?? [];
495
+ const cleaned = wireItems
496
+ .filter((r) => r != null)
497
+ .map((r) => ({ identifier: r.identifier, nameForRole: r.nameForRole }));
498
+ cleaned.sort((a, b) => a.identifier.localeCompare(b.identifier, undefined, { sensitivity: "base" }));
499
+ return cleaned;
500
+ },
501
+ /**
502
+ * Cancel a break by `engagementBreak.id`. The id is what
503
+ * `breaks.list` returns; users can copy it directly.
504
+ *
505
+ * Returns `{ id }` of the cancelled break for envelope wrapping.
506
+ * Throws `EngagementsError("MUTATION_ERROR")` on `success: false`.
507
+ *
508
+ * Dry-run path (issue #163): when invoked with `options.dryRun ===
509
+ * true`, builds a {@link DryRunPreview} of the mutation without
510
+ * invoking the gateway transport and returns it wrapped in
511
+ * {@link EngagementBreaksDryRunPreviewOutcome}. The single
512
+ * `engagementBreakId` variable is preserved verbatim — no
513
+ * translation needed for this mutation.
514
+ */
515
+ async remove(token, engagementBreakId, options = {}) {
516
+ const variables = { engagementBreakId };
517
+ if (options.dryRun === true) {
518
+ return {
519
+ kind: "preview",
520
+ preview: buildDryRunPreview({
521
+ surface: "mobile-gateway",
522
+ authToken: token,
523
+ body: {
524
+ operationName: "CancelEngagementBreak",
525
+ query: CANCEL_ENGAGEMENT_BREAK_MUTATION,
526
+ variables,
527
+ },
528
+ }),
529
+ };
530
+ }
531
+ const data = await callGateway(token, "CancelEngagementBreak", CANCEL_ENGAGEMENT_BREAK_MUTATION, variables);
532
+ if (data.engagementBreak === null) {
533
+ throw new EngagementsError("NOT_FOUND", `Engagement break "${engagementBreakId}" not found.`);
534
+ }
535
+ const result = data.engagementBreak.cancel;
536
+ if (result === null) {
537
+ throw new EngagementsError("UNKNOWN", "CancelEngagementBreak returned a null payload.");
538
+ }
539
+ if (!result.success) {
540
+ throw new EngagementsError("MUTATION_ERROR", formatMutationErrors("CancelEngagementBreak failed", result.errors));
541
+ }
542
+ return { kind: "applied", result: { id: engagementBreakId } };
543
+ },
544
+ /**
545
+ * Reschedule an existing break to a new date window by
546
+ * `engagementBreak.id` (#155). The id is what `breaks.list` returns
547
+ * (and what `breaks.add` returns after creating one); users can pass
548
+ * it directly without any translation. The mutation root is
549
+ * `engagementBreak(id: $engagementBreakId)` — same root as
550
+ * {@link breaks.remove}, NOT
551
+ * `engagement(id: ...).rescheduleBreak(...)` — so no engagement-id
552
+ * prefetch is needed (unlike {@link breaks.add}).
553
+ *
554
+ * The wire input has only `startDate` + `endDate`. There is NO
555
+ * `comment` or `reasonIdentifier` field on the mutation input — the
556
+ * server preserves the existing break's reason and comment across the
557
+ * reschedule. Callers wanting to change those fields must
558
+ * `remove` + `add` instead.
559
+ *
560
+ * Returns the FULL post-mutation {@link EngagementBreak} (with
561
+ * refreshed dates + preserved comment/operations), wrapped in the
562
+ * apply outcome — mirroring {@link breaks.add}, not
563
+ * {@link breaks.remove} (which returns only `{ id }` because cancel
564
+ * has nothing meaningful to surface).
565
+ *
566
+ * Throws `EngagementsError("NOT_FOUND")` when the break id resolves
567
+ * to `null engagementBreak`; throws `EngagementsError("MUTATION_ERROR")`
568
+ * when the gateway returns `success: false` (overlapping windows,
569
+ * validation failures).
570
+ *
571
+ * Dry-run path: when invoked with `options.dryRun === true`, builds a
572
+ * {@link DryRunPreview} of the mutation without invoking the gateway
573
+ * transport. The single trio `{ engagementBreakId, startDate, endDate }`
574
+ * is preserved verbatim — no translation needed.
575
+ */
576
+ async reschedule(token, engagementBreakId, opts, options = {}) {
577
+ const variables = {
578
+ engagementBreakId,
579
+ startDate: opts.startDate,
580
+ endDate: opts.endDate,
581
+ };
582
+ if (options.dryRun === true) {
583
+ return {
584
+ kind: "preview",
585
+ preview: buildDryRunPreview({
586
+ surface: "mobile-gateway",
587
+ authToken: token,
588
+ body: {
589
+ operationName: "RescheduleEngagementBreak",
590
+ query: RESCHEDULE_ENGAGEMENT_BREAK_MUTATION,
591
+ variables,
592
+ },
593
+ }),
594
+ };
595
+ }
596
+ const data = await callGateway(token, "RescheduleEngagementBreak", RESCHEDULE_ENGAGEMENT_BREAK_MUTATION, variables);
597
+ if (data.engagementBreak === null) {
598
+ throw new EngagementsError("NOT_FOUND", `Engagement break "${engagementBreakId}" not found.`);
599
+ }
600
+ const result = data.engagementBreak.reschedule;
601
+ if (result === null) {
602
+ throw new EngagementsError("UNKNOWN", "RescheduleEngagementBreak returned a null payload.");
603
+ }
604
+ if (!result.success) {
605
+ throw new EngagementsError("MUTATION_ERROR", formatMutationErrors("RescheduleEngagementBreak failed", result.errors));
606
+ }
607
+ if (result.break === null) {
608
+ throw new EngagementsError("UNKNOWN", "RescheduleEngagementBreak returned success but the `break` payload was null.");
609
+ }
610
+ return { kind: "applied", result: result.break };
611
+ },
612
+ };
613
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/services/engagements/index.ts"],"names":[],"mappings":"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"}