@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,461 @@
1
+ // SPDX-License-Identifier: AGPL-3.0-only
2
+ // Copyright (C) 2026 Oleksii PELYKH
3
+ import { callGatewayShared } from "../../_shared/transport.js";
4
+ export class SkillsError extends Error {
5
+ code;
6
+ name = "SkillsError";
7
+ constructor(code, message, options) {
8
+ super(message, options);
9
+ this.code = code;
10
+ }
11
+ }
12
+ /**
13
+ * Thin per-service wrapper around {@link callGatewayShared} (issue
14
+ * #329). Pins the talent-profile surface and the {@link SkillsError}
15
+ * domain class. The `variables: unknown` parameter (cast to
16
+ * `Record<string, unknown>` here) preserves the historical signature
17
+ * — every leaf in this file constructs a fresh variables literal that
18
+ * is structurally a `Record` regardless of nominal typing.
19
+ */
20
+ async function callTalentProfile(token, operationName, query, variables, schema) {
21
+ return callGatewayShared("talent-profile", token, operationName, query, variables, SkillsError, { schema });
22
+ }
23
+ // -----------------------------------------------------------------------
24
+ // GraphQL operation documents
25
+ //
26
+ // These mirror `research/graphql/talent_profile/operations/*.graphql`,
27
+ // stripped of the unwired fragment dependencies (`MutationResultFragment`,
28
+ // `UserErrorFragment`, `ProfileCompletion`, `RealTimeFields`,
29
+ // `SkillsReadiness`, `ProfileRecommendations`) that the codegen pipeline
30
+ // hasn't yet been pointed at. The fragments are inlined to the minimum
31
+ // shape each leaf consumes — same pattern as `UPDATE_BASIC_INFO_MUTATION`
32
+ // in `profile.basic`.
33
+ //
34
+ // **Operation names are SCREAMING_CASE for mutations and camelCase for
35
+ // queries**, matching the bundle-extracted documents — see
36
+ // `research/notes/05-talent-profile-api.md` for the rationale (the server
37
+ // matches `operationName` literally and the React app sends these forms).
38
+ // -----------------------------------------------------------------------
39
+ const ADD_PROFILE_SKILL_SET_MUTATION = `mutation ADD_PROFILE_SKILL_SET($input: AddProfileSkillSetInput!) {
40
+ addProfileSkillSet(input: $input) {
41
+ skillSet {
42
+ id
43
+ experience
44
+ rating
45
+ public
46
+ position
47
+ skill { id name }
48
+ connections { totalCount }
49
+ }
50
+ success
51
+ notice
52
+ errors { code key message }
53
+ }
54
+ }`;
55
+ const REMOVE_PROFILE_SKILL_SET_MUTATION = `mutation REMOVE_PROFILE_SKILL_SET($input: RemoveProfileSkillSetInput!) {
56
+ removeProfileSkillSet(input: $input) {
57
+ success
58
+ notice
59
+ errors { code key message }
60
+ profile { id }
61
+ }
62
+ }`;
63
+ const UPDATE_RATING_MUTATION = `mutation UPDATE_PROFILE_SKILL_SET_RATING($input: UpdateProfileSkillSetRatingInput!) {
64
+ updateProfileSkillSetRating(input: $input) {
65
+ skillSet { id rating }
66
+ success
67
+ notice
68
+ errors { code key message }
69
+ }
70
+ }`;
71
+ const UPDATE_EXPERIENCE_MUTATION = `mutation UPDATE_PROFILE_SKILL_SET_EXPERIENCE($input: UpdateProfileSkillSetExperienceInput!) {
72
+ updateProfileSkillSetExperience(input: $input) {
73
+ skillSet { id experience }
74
+ success
75
+ notice
76
+ errors { code key message }
77
+ }
78
+ }`;
79
+ const UPDATE_PUBLICITY_MUTATION = `mutation UPDATE_PROFILE_SKILL_SET_PUBLICITY($input: UpdateProfileSkillSetPublicityInput!) {
80
+ updateProfileSkillSetPublicity(input: $input) {
81
+ skillSet { id public }
82
+ success
83
+ notice
84
+ errors { code key message }
85
+ }
86
+ }`;
87
+ const GET_SKILL_SET_QUERY = `query GetSkillSetWithConnections($id: ID!) {
88
+ node(id: $id) {
89
+ ... on ProfileSkillSet {
90
+ id
91
+ experience
92
+ rating
93
+ public
94
+ position
95
+ skill { id name }
96
+ connections {
97
+ totalCount
98
+ nodes {
99
+ ... on Node { id }
100
+ }
101
+ }
102
+ }
103
+ }
104
+ }`;
105
+ const LIST_SKILL_SETS_QUERY = `query getSkillSetsWithConnectionsWithConnectionsCount($profileId: ID!) {
106
+ profile(id: $profileId) {
107
+ id
108
+ skillSets {
109
+ nodes {
110
+ id
111
+ experience
112
+ rating
113
+ public
114
+ position
115
+ skill { id name }
116
+ connections { totalCount }
117
+ }
118
+ }
119
+ }
120
+ }`;
121
+ const AUTOCOMPLETE_SKILLS_QUERY = `query GET_SKILLS_FOR_AUTOCOMPLETE($profileId: ID!, $search: String!, $limit: Int!, $withoutIds: [ID!]) {
122
+ profile(id: $profileId) {
123
+ id
124
+ skillsAutocomplete(search: $search, limit: $limit, withoutIds: $withoutIds) {
125
+ id
126
+ name
127
+ }
128
+ }
129
+ }`;
130
+ const SKILLS_READINESS_QUERY = `query getSkillsReadiness($profileId: ID!) {
131
+ profile(id: $profileId) {
132
+ id
133
+ skillsReadiness {
134
+ isExpertProficiencyCountSatisfied
135
+ isHighlightedItemsCountAndExperienceSatisfied
136
+ isItemsCountSatisfied
137
+ isProficiencyNotSetCountSatisfied
138
+ isProgrammingLanguageSatisfied
139
+ }
140
+ }
141
+ }`;
142
+ function normaliseSkillSet(wire) {
143
+ return {
144
+ id: wire.id,
145
+ experience: wire.experience,
146
+ rating: wire.rating,
147
+ public: wire.public,
148
+ position: wire.position,
149
+ skill: wire.skill,
150
+ connectionsCount: wire.connections.totalCount,
151
+ };
152
+ }
153
+ function raiseUserErrors(operation, errors) {
154
+ if (!Array.isArray(errors) || errors.length === 0)
155
+ return;
156
+ const first = errors[0];
157
+ const fieldHint = first?.key ? ` (${first.key})` : "";
158
+ throw new SkillsError("USER_ERROR", `${operation} rejected${fieldHint}: ${first?.message ?? "unknown error"}`);
159
+ }
160
+ // -----------------------------------------------------------------------
161
+ // add(skillName)
162
+ // -----------------------------------------------------------------------
163
+ /**
164
+ * Add a skill to the signed-in user's profile. Identifies the skill by
165
+ * its catalog name (e.g. `"TypeScript"`); the server resolves the name to
166
+ * a `Skill` id under the hood and returns the newly-attached
167
+ * `ProfileSkillSet` with default `rating`/`experience`/`public` values.
168
+ *
169
+ * Use {@link autocomplete} first if the caller needs to disambiguate
170
+ * between candidate skills (e.g., "Postgres" vs "PostgreSQL"). Once the
171
+ * skill is added, configure proficiency via {@link set}.
172
+ *
173
+ * Errors:
174
+ * - `SkillsError` `VALIDATION_ERROR` when `name` is empty or whitespace-only.
175
+ * - `SkillsError` `USER_ERROR` when the server reports a domain failure
176
+ * (e.g., skill already on profile, name not in catalog).
177
+ * - `AuthRevokedError`, `Cf403Error`, plus the standard
178
+ * `GRAPHQL_ERROR`/`NETWORK_ERROR`/`UNKNOWN` codes from the shared
179
+ * transport-error path.
180
+ */
181
+ export async function add(token, name) {
182
+ const trimmed = name.trim();
183
+ if (trimmed.length === 0) {
184
+ throw new SkillsError("VALIDATION_ERROR", "Skill name is required.");
185
+ }
186
+ const data = await callTalentProfile(token, "ADD_PROFILE_SKILL_SET", ADD_PROFILE_SKILL_SET_MUTATION, {
187
+ input: { name: trimmed },
188
+ });
189
+ const payload = data.addProfileSkillSet;
190
+ if (!payload) {
191
+ throw new SkillsError("UNKNOWN", "ADD_PROFILE_SKILL_SET response had no `data.addProfileSkillSet` field");
192
+ }
193
+ raiseUserErrors("Skill add", payload.errors);
194
+ if (payload.success === false) {
195
+ throw new SkillsError("USER_ERROR", `Skill add reported success=false${payload.notice ? `: ${payload.notice}` : ""}`);
196
+ }
197
+ if (!payload.skillSet) {
198
+ throw new SkillsError("UNKNOWN", "Skill add succeeded but response had no `skillSet` payload");
199
+ }
200
+ return normaliseSkillSet(payload.skillSet);
201
+ }
202
+ // -----------------------------------------------------------------------
203
+ // rm(skillSetId)
204
+ // -----------------------------------------------------------------------
205
+ /**
206
+ * Remove a skill from the signed-in user's profile by its ProfileSkillSet
207
+ * id (NOT the Skill catalog id). Removal cascades to any connections the
208
+ * skill set held to portfolio items, education, employment, or
209
+ * certifications — the server cleans those up server-side, no per-edge
210
+ * call required from the client.
211
+ *
212
+ * Errors:
213
+ * - `SkillsError` `VALIDATION_ERROR` when `id` is empty.
214
+ * - `SkillsError` `USER_ERROR` when the id doesn't match a skill set on
215
+ * the user's profile (caller used a stale id).
216
+ * - Standard transport-error path (auth-revoked / Cf403 / GraphQL /
217
+ * network / unknown).
218
+ */
219
+ export async function rm(token, id) {
220
+ if (id.trim().length === 0) {
221
+ throw new SkillsError("VALIDATION_ERROR", "Skill set id is required.");
222
+ }
223
+ const data = await callTalentProfile(token, "REMOVE_PROFILE_SKILL_SET", REMOVE_PROFILE_SKILL_SET_MUTATION, { input: { skillSetId: id } });
224
+ const payload = data.removeProfileSkillSet;
225
+ if (!payload) {
226
+ throw new SkillsError("UNKNOWN", "REMOVE_PROFILE_SKILL_SET response had no `data.removeProfileSkillSet` field");
227
+ }
228
+ raiseUserErrors("Skill remove", payload.errors);
229
+ if (payload.success === false) {
230
+ throw new SkillsError("USER_ERROR", `Skill remove reported success=false${payload.notice ? `: ${payload.notice}` : ""}`);
231
+ }
232
+ }
233
+ // -----------------------------------------------------------------------
234
+ // set(id, fields)
235
+ // -----------------------------------------------------------------------
236
+ /**
237
+ * Update one or more fields on an existing skill set. Multi-flag atomic
238
+ * semantics: each provided field fires its own GraphQL mutation
239
+ * (`UPDATE_PROFILE_SKILL_SET_RATING` / `_EXPERIENCE` / `_PUBLICITY`)
240
+ * sequentially. **Partial-failure behavior**: if mutation N succeeds but
241
+ * mutation N+1 fails, the prior changes are NOT rolled back — the server
242
+ * lacks a multi-field atomic path, so the client serialises the updates
243
+ * and reports a `PARTIAL_FAILURE` error carrying which fields landed and
244
+ * which didn't. Callers re-issue only the missing fields after handling
245
+ * the failure.
246
+ *
247
+ * The mutation order is `rating → experience → public`, deterministic so
248
+ * tests can predict the call sequence.
249
+ *
250
+ * Errors:
251
+ * - `SkillsError` `VALIDATION_ERROR` when `id` is empty OR no fields
252
+ * are supplied.
253
+ * - `SkillsError` `PARTIAL_FAILURE` when the second or third mutation
254
+ * fails after at least one earlier mutation succeeded. The error
255
+ * message names the failing field and the underlying message; the
256
+ * error's `cause` carries the per-field failure for callers that want
257
+ * structured access. The successful fields are reflected in the
258
+ * `result` snapshot included on the error.
259
+ * - `SkillsError` `USER_ERROR` when the FIRST mutation fails — caller
260
+ * sees the same shape they'd see from a single-flag invocation.
261
+ * - Standard transport-error path.
262
+ */
263
+ export async function set(token, id, fields) {
264
+ if (id.trim().length === 0) {
265
+ throw new SkillsError("VALIDATION_ERROR", "Skill set id is required.");
266
+ }
267
+ if (fields.rating === undefined && fields.experience === undefined && fields.public === undefined) {
268
+ throw new SkillsError("VALIDATION_ERROR", "Skill update requires at least one of `rating`, `experience`, or `public`.");
269
+ }
270
+ const result = {
271
+ id,
272
+ rating: null,
273
+ experience: null,
274
+ public: null,
275
+ notices: [],
276
+ };
277
+ const completed = [];
278
+ // Helper used per-mutation: drives the first call as a normal failure
279
+ // (USER_ERROR / standard transport error), and any subsequent failure
280
+ // as PARTIAL_FAILURE so the caller can reason about which writes landed.
281
+ const runStep = async (field, fire) => {
282
+ try {
283
+ await fire();
284
+ completed.push(field);
285
+ }
286
+ catch (err) {
287
+ if (completed.length === 0)
288
+ throw err;
289
+ throw new SkillsError("PARTIAL_FAILURE", `Skill update partially failed: ${completed.join(", ")} succeeded, ${field} failed: ${err.message}`, { cause: err });
290
+ }
291
+ };
292
+ if (fields.rating !== undefined) {
293
+ const rating = fields.rating;
294
+ await runStep("rating", async () => {
295
+ const data = await callTalentProfile(token, "UPDATE_PROFILE_SKILL_SET_RATING", UPDATE_RATING_MUTATION, { input: { skillSetId: id, skillSet: { rating } } });
296
+ const payload = data.updateProfileSkillSetRating;
297
+ if (!payload) {
298
+ throw new SkillsError("UNKNOWN", "UPDATE_PROFILE_SKILL_SET_RATING response had no payload");
299
+ }
300
+ raiseUserErrors("Skill rating update", payload.errors);
301
+ if (payload.success === false) {
302
+ throw new SkillsError("USER_ERROR", `Skill rating update reported success=false${payload.notice ? `: ${payload.notice}` : ""}`);
303
+ }
304
+ result.rating = payload.skillSet?.rating ?? rating;
305
+ if (payload.notice)
306
+ result.notices.push(payload.notice);
307
+ });
308
+ }
309
+ if (fields.experience !== undefined) {
310
+ const experience = fields.experience;
311
+ await runStep("experience", async () => {
312
+ const data = await callTalentProfile(token, "UPDATE_PROFILE_SKILL_SET_EXPERIENCE", UPDATE_EXPERIENCE_MUTATION, { input: { skillSetId: id, skillSet: { experience } } });
313
+ const payload = data.updateProfileSkillSetExperience;
314
+ if (!payload) {
315
+ throw new SkillsError("UNKNOWN", "UPDATE_PROFILE_SKILL_SET_EXPERIENCE response had no payload");
316
+ }
317
+ raiseUserErrors("Skill experience update", payload.errors);
318
+ if (payload.success === false) {
319
+ throw new SkillsError("USER_ERROR", `Skill experience update reported success=false${payload.notice ? `: ${payload.notice}` : ""}`);
320
+ }
321
+ result.experience = payload.skillSet?.experience ?? experience;
322
+ if (payload.notice)
323
+ result.notices.push(payload.notice);
324
+ });
325
+ }
326
+ if (fields.public !== undefined) {
327
+ const isPublic = fields.public;
328
+ await runStep("public", async () => {
329
+ const data = await callTalentProfile(token, "UPDATE_PROFILE_SKILL_SET_PUBLICITY", UPDATE_PUBLICITY_MUTATION, { input: { skillSetId: id, skillSet: { public: isPublic } } });
330
+ const payload = data.updateProfileSkillSetPublicity;
331
+ if (!payload) {
332
+ throw new SkillsError("UNKNOWN", "UPDATE_PROFILE_SKILL_SET_PUBLICITY response had no payload");
333
+ }
334
+ raiseUserErrors("Skill publicity update", payload.errors);
335
+ if (payload.success === false) {
336
+ throw new SkillsError("USER_ERROR", `Skill publicity update reported success=false${payload.notice ? `: ${payload.notice}` : ""}`);
337
+ }
338
+ result.public = payload.skillSet?.public ?? isPublic;
339
+ if (payload.notice)
340
+ result.notices.push(payload.notice);
341
+ });
342
+ }
343
+ return result;
344
+ }
345
+ // -----------------------------------------------------------------------
346
+ // show(id)
347
+ // -----------------------------------------------------------------------
348
+ /**
349
+ * Fetch a single skill set by its id, including its connection edges to
350
+ * portfolio items / employment / education / certifications. Useful when
351
+ * the caller already has the id (from `list()` or a recent mutation) and
352
+ * needs to display the full detail without paging.
353
+ *
354
+ * Errors:
355
+ * - `SkillsError` `VALIDATION_ERROR` when `id` is empty.
356
+ * - `SkillsError` `USER_ERROR` when the id doesn't resolve to a
357
+ * `ProfileSkillSet` (server returns `node: null`).
358
+ * - Standard transport-error path.
359
+ */
360
+ export async function show(token, id) {
361
+ if (id.trim().length === 0) {
362
+ throw new SkillsError("VALIDATION_ERROR", "Skill set id is required.");
363
+ }
364
+ const data = await callTalentProfile(token, "GetSkillSetWithConnections", GET_SKILL_SET_QUERY, {
365
+ id,
366
+ });
367
+ if (!data.node) {
368
+ throw new SkillsError("USER_ERROR", `No ProfileSkillSet found with id "${id}".`);
369
+ }
370
+ return normaliseSkillSet(data.node);
371
+ }
372
+ // -----------------------------------------------------------------------
373
+ // list(profileId)
374
+ // -----------------------------------------------------------------------
375
+ /**
376
+ * List every skill set on the signed-in user's profile, with each entry
377
+ * carrying its connection-count summary (the digits the portal shows next
378
+ * to "linked to N items"). Order matches the server's `position` field;
379
+ * callers that need a specific sort apply it after fetching.
380
+ *
381
+ * The talent-profile surface keys this query on `profileId` rather than
382
+ * resolving it server-side from the auth token, so the caller passes the
383
+ * `profileId` it has on hand (typically obtained from `profile.basic.show`
384
+ * or cached for the session).
385
+ *
386
+ * Errors:
387
+ * - `SkillsError` `VALIDATION_ERROR` when `profileId` is empty.
388
+ * - `SkillsError` `USER_ERROR` when the profile id doesn't resolve.
389
+ * - Standard transport-error path.
390
+ */
391
+ export async function list(token, profileId) {
392
+ if (profileId.trim().length === 0) {
393
+ throw new SkillsError("VALIDATION_ERROR", "Profile id is required.");
394
+ }
395
+ const data = await callTalentProfile(token, "getSkillSetsWithConnectionsWithConnectionsCount", LIST_SKILL_SETS_QUERY, { profileId });
396
+ if (!data.profile) {
397
+ throw new SkillsError("USER_ERROR", `No profile found with id "${profileId}".`);
398
+ }
399
+ return data.profile.skillSets.nodes.filter((n) => n !== null).map(normaliseSkillSet);
400
+ }
401
+ // -----------------------------------------------------------------------
402
+ // autocomplete(profileId, query, options?)
403
+ // -----------------------------------------------------------------------
404
+ /**
405
+ * Search the global skill catalog for entries matching `search`,
406
+ * suitable for populating an autocomplete dropdown. The server scopes
407
+ * results to skills the talent's vertical permits and excludes any ids
408
+ * passed in `withoutIds` (typically the talent's existing skill-set
409
+ * skill ids, so the dropdown doesn't suggest skills they already have).
410
+ *
411
+ * `limit` defaults to 10 (matches the portal's default page size).
412
+ *
413
+ * Errors:
414
+ * - `SkillsError` `VALIDATION_ERROR` when `profileId` or `search` is empty.
415
+ * - Standard transport-error path.
416
+ */
417
+ export async function autocomplete(token, profileId, search, options = {}) {
418
+ if (profileId.trim().length === 0) {
419
+ throw new SkillsError("VALIDATION_ERROR", "Profile id is required.");
420
+ }
421
+ if (search.trim().length === 0) {
422
+ throw new SkillsError("VALIDATION_ERROR", "Search query is required.");
423
+ }
424
+ const data = await callTalentProfile(token, "GET_SKILLS_FOR_AUTOCOMPLETE", AUTOCOMPLETE_SKILLS_QUERY, {
425
+ profileId,
426
+ search: search.trim(),
427
+ limit: options.limit ?? 10,
428
+ withoutIds: options.withoutIds ?? [],
429
+ });
430
+ if (!data.profile) {
431
+ throw new SkillsError("USER_ERROR", `No profile found with id "${profileId}".`);
432
+ }
433
+ return data.profile.skillsAutocomplete;
434
+ }
435
+ // -----------------------------------------------------------------------
436
+ // readiness(profileId)
437
+ // -----------------------------------------------------------------------
438
+ /**
439
+ * Fetch the skill-readiness snapshot for the user's profile — the same
440
+ * heuristics the portal uses to gate the "ready to apply" state on the
441
+ * skills section. Useful for surfacing a checklist of remaining tasks
442
+ * via CLI or MCP.
443
+ *
444
+ * Errors:
445
+ * - `SkillsError` `VALIDATION_ERROR` when `profileId` is empty.
446
+ * - `SkillsError` `USER_ERROR` when the profile id doesn't resolve.
447
+ * - Standard transport-error path.
448
+ */
449
+ export async function readiness(token, profileId) {
450
+ if (profileId.trim().length === 0) {
451
+ throw new SkillsError("VALIDATION_ERROR", "Profile id is required.");
452
+ }
453
+ const data = await callTalentProfile(token, "getSkillsReadiness", SKILLS_READINESS_QUERY, {
454
+ profileId,
455
+ });
456
+ if (!data.profile) {
457
+ throw new SkillsError("USER_ERROR", `No profile found with id "${profileId}".`);
458
+ }
459
+ return data.profile.skillsReadiness;
460
+ }
461
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/services/profile/skills/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,74 @@
1
+ /**
2
+ * Visas sub-domain error codes. Cross-cutting auth/Cloudflare failures
3
+ * propagate as `TtctlError` subclasses unchanged.
4
+ */
5
+ export type VisasErrorCode = "NO_VIEWER" | "GRAPHQL_ERROR" | "NETWORK_ERROR" | "USER_ERROR" | "VALIDATION_ERROR" | "WIRE_SHAPE_ERROR" | "UNKNOWN";
6
+ export declare class VisasError extends Error {
7
+ readonly code: VisasErrorCode;
8
+ readonly name = "VisasError";
9
+ constructor(code: VisasErrorCode, message: string, options?: {
10
+ cause?: unknown;
11
+ });
12
+ }
13
+ /**
14
+ * Read-side `TravelVisa` shape. Mirrors the `TravelVisa` fragment in
15
+ * `research/graphql/talent_profile/fragments/TravelVisa.graphql`. The
16
+ * server names the country sub-object — TTCtl flattens it onto the
17
+ * top-level shape for ergonomic access at the CLI layer.
18
+ */
19
+ export interface TravelVisa {
20
+ id: string;
21
+ countryId: string;
22
+ countryName: string;
23
+ visaType: string;
24
+ expiryDate: string | null;
25
+ }
26
+ /**
27
+ * Write-side `TravelVisaInput`. The country reference uses `countryId`
28
+ * (the ID returned by the read-side `country.id`); `visaType` is a free
29
+ * string the server validates against its catalog of known visa types.
30
+ *
31
+ * **[INFERRED]** Wrapper key `travelVisa` (Pattern 1/2 from
32
+ * `research/notes/10-mutation-input-patterns.md`); falsifiable by live
33
+ * capture if the server rejects the wrapper.
34
+ */
35
+ export interface TravelVisaInput {
36
+ countryId?: string;
37
+ visaType?: string;
38
+ expiryDate?: string;
39
+ }
40
+ /**
41
+ * Fetch the signed-in user's travel-visa records. Empty list returns `[]`,
42
+ * never `null`.
43
+ */
44
+ export declare function list(token: string): Promise<TravelVisa[]>;
45
+ /**
46
+ * Create a new travel-visa record.
47
+ *
48
+ * Both `countryId` and `visaType` are required by the AC; `expiryDate`
49
+ * is optional. The wire-side error path returns `errors[]` on the
50
+ * mutation payload when the server rejects (e.g. unknown country,
51
+ * malformed date) — those collapse into `USER_ERROR`.
52
+ */
53
+ export declare function add(token: string, input: TravelVisaInput): Promise<TravelVisa[]>;
54
+ /**
55
+ * Update a travel-visa record by id.
56
+ *
57
+ * `UpdateTravelVisaInput.travelVisa` is treated as a **full-document
58
+ * replacement** by the server — `countryId` and `visaType` are
59
+ * non-nullable on the input even when the caller doesn't want to change
60
+ * them. Sending only the patched field returns
61
+ * `Variable $input of type UpdateTravelVisaInput! was provided invalid
62
+ * value for travelVisa.countryId/visaType (Expected value to not be
63
+ * null)` (verified live 2026-05-15, see #317).
64
+ *
65
+ * To preserve the partial-update UX over the full-replace wire shape,
66
+ * this function does read-modify-write: fetch the current record via
67
+ * {@link list}, merge caller's `changes` on top of the current state,
68
+ * then send the merged input. Same pattern as
69
+ * `services/profile/portfolio/index.ts` `update` (PR #323 / #314).
70
+ */
71
+ export declare function update(token: string, id: string, changes: TravelVisaInput): Promise<TravelVisa[]>;
72
+ /** Remove a travel-visa record by id. */
73
+ export declare function remove(token: string, id: string): Promise<TravelVisa[]>;
74
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/services/profile/visas/index.ts"],"names":[],"mappings":"AAQA;;;GAGG;AACH,MAAM,MAAM,cAAc,GACtB,WAAW,GACX,eAAe,GACf,eAAe,GACf,YAAY,GACZ,kBAAkB,GAClB,kBAAkB,GAClB,SAAS,CAAC;AAEd,qBAAa,UAAW,SAAQ,KAAK;aAGjB,IAAI,EAAE,cAAc;IAFtC,SAAkB,IAAI,gBAAgB;gBAEpB,IAAI,EAAE,cAAc,EACpC,OAAO,EAAE,MAAM,EACf,OAAO,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,OAAO,CAAA;KAAE;CAIhC;AAaD;;;;;GAKG;AACH,MAAM,WAAW,UAAU;IACzB,EAAE,EAAE,MAAM,CAAC;IACX,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;CAC3B;AAED;;;;;;;;GAQG;AACH,MAAM,WAAW,eAAe;IAC9B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AA2GD;;;GAGG;AACH,wBAAsB,IAAI,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,EAAE,CAAC,CAkB/D;AAoCD;;;;;;;GAOG;AACH,wBAAsB,GAAG,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,eAAe,GAAG,OAAO,CAAC,UAAU,EAAE,CAAC,CA4BtF;AA+BD;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAsB,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,eAAe,GAAG,OAAO,CAAC,UAAU,EAAE,CAAC,CAsCvG;AA0BD,yCAAyC;AACzC,wBAAsB,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,EAAE,CAAC,CAmB7E"}