@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.
- package/README.md +49 -9
- package/dist/__generated__/gateway.d.ts +4546 -0
- package/dist/__generated__/gateway.d.ts.map +1 -0
- package/dist/__generated__/gateway.js +9 -0
- package/dist/__generated__/gateway.js.map +1 -0
- package/dist/__generated__/talent-profile-zod-schemas.d.ts +1187 -0
- package/dist/__generated__/talent-profile-zod-schemas.d.ts.map +1 -0
- package/dist/__generated__/talent-profile-zod-schemas.js +1136 -0
- package/dist/__generated__/talent-profile-zod-schemas.js.map +1 -0
- package/dist/__generated__/talent-profile.d.ts +1397 -0
- package/dist/__generated__/talent-profile.d.ts.map +1 -0
- package/dist/__generated__/talent-profile.js +9 -0
- package/dist/__generated__/talent-profile.js.map +1 -0
- package/dist/__generated__/zod-schemas.d.ts +2895 -0
- package/dist/__generated__/zod-schemas.d.ts.map +1 -0
- package/dist/__generated__/zod-schemas.js +3121 -0
- package/dist/__generated__/zod-schemas.js.map +1 -0
- package/dist/__tests__/fixtures/profile/builders.d.ts +74 -0
- package/dist/__tests__/fixtures/profile/builders.d.ts.map +1 -0
- package/dist/__tests__/fixtures/profile/builders.js +196 -0
- package/dist/__tests__/fixtures/profile/builders.js.map +1 -0
- package/dist/__tests__/fixtures/profile/data.d.ts +39 -0
- package/dist/__tests__/fixtures/profile/data.d.ts.map +1 -0
- package/dist/__tests__/fixtures/profile/data.js +230 -0
- package/dist/__tests__/fixtures/profile/data.js.map +1 -0
- package/dist/__tests__/fixtures/profile/index.d.ts +9 -0
- package/dist/__tests__/fixtures/profile/index.d.ts.map +1 -0
- package/dist/__tests__/fixtures/profile/index.js +10 -0
- package/dist/__tests__/fixtures/profile/index.js.map +1 -0
- package/dist/__tests__/fixtures/profile/types.d.ts +53 -0
- package/dist/__tests__/fixtures/profile/types.d.ts.map +1 -0
- package/dist/__tests__/fixtures/profile/types.js +4 -0
- package/dist/__tests__/fixtures/profile/types.js.map +1 -0
- package/dist/auth/errors.d.ts +82 -0
- package/dist/auth/errors.d.ts.map +1 -0
- package/dist/auth/errors.js +68 -0
- package/dist/auth/errors.js.map +1 -0
- package/dist/auth.d.ts +192 -0
- package/dist/auth.d.ts.map +1 -0
- package/dist/auth.js +294 -0
- package/dist/auth.js.map +1 -0
- package/dist/config.d.ts +212 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +349 -0
- package/dist/config.js.map +1 -0
- package/dist/configLock.d.ts +50 -0
- package/dist/configLock.d.ts.map +1 -0
- package/dist/configLock.js +88 -0
- package/dist/configLock.js.map +1 -0
- package/dist/configWriter.d.ts +97 -0
- package/dist/configWriter.d.ts.map +1 -0
- package/dist/configWriter.js +687 -0
- package/dist/configWriter.js.map +1 -0
- package/dist/index.d.ts +37 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +28 -0
- package/dist/index.js.map +1 -0
- package/dist/kill-switch.d.ts +161 -0
- package/dist/kill-switch.d.ts.map +1 -0
- package/dist/kill-switch.js +235 -0
- package/dist/kill-switch.js.map +1 -0
- package/dist/lib/date.d.ts +58 -0
- package/dist/lib/date.d.ts.map +1 -0
- package/dist/lib/date.js +104 -0
- package/dist/lib/date.js.map +1 -0
- package/dist/lib/diagnostic-log.d.ts +159 -0
- package/dist/lib/diagnostic-log.d.ts.map +1 -0
- package/dist/lib/diagnostic-log.js +186 -0
- package/dist/lib/diagnostic-log.js.map +1 -0
- package/dist/lib/package-version.d.ts +19 -0
- package/dist/lib/package-version.d.ts.map +1 -0
- package/dist/lib/package-version.js +38 -0
- package/dist/lib/package-version.js.map +1 -0
- package/dist/lib/redact.d.ts +153 -0
- package/dist/lib/redact.d.ts.map +1 -0
- package/dist/lib/redact.js +207 -0
- package/dist/lib/redact.js.map +1 -0
- package/dist/lib/text.d.ts +14 -0
- package/dist/lib/text.d.ts.map +1 -0
- package/dist/lib/text.js +21 -0
- package/dist/lib/text.js.map +1 -0
- package/dist/lib/wire-shape.d.ts +131 -0
- package/dist/lib/wire-shape.d.ts.map +1 -0
- package/dist/lib/wire-shape.js +376 -0
- package/dist/lib/wire-shape.js.map +1 -0
- package/dist/onepassword.d.ts +29 -0
- package/dist/onepassword.d.ts.map +1 -0
- package/dist/onepassword.js +112 -0
- package/dist/onepassword.js.map +1 -0
- package/dist/services/_shared/transport.d.ts +148 -0
- package/dist/services/_shared/transport.d.ts.map +1 -0
- package/dist/services/_shared/transport.js +102 -0
- package/dist/services/_shared/transport.js.map +1 -0
- package/dist/services/applications/index.d.ts +210 -0
- package/dist/services/applications/index.d.ts.map +1 -0
- package/dist/services/applications/index.js +240 -0
- package/dist/services/applications/index.js.map +1 -0
- package/dist/services/availability/index.d.ts +254 -0
- package/dist/services/availability/index.d.ts.map +1 -0
- package/dist/services/availability/index.js +310 -0
- package/dist/services/availability/index.js.map +1 -0
- package/dist/services/contracts/index.d.ts +132 -0
- package/dist/services/contracts/index.d.ts.map +1 -0
- package/dist/services/contracts/index.js +211 -0
- package/dist/services/contracts/index.js.map +1 -0
- package/dist/services/engagements/index.d.ts +504 -0
- package/dist/services/engagements/index.d.ts.map +1 -0
- package/dist/services/engagements/index.js +613 -0
- package/dist/services/engagements/index.js.map +1 -0
- package/dist/services/jobs/index.d.ts +490 -0
- package/dist/services/jobs/index.d.ts.map +1 -0
- package/dist/services/jobs/index.js +753 -0
- package/dist/services/jobs/index.js.map +1 -0
- package/dist/services/payments/index.d.ts +415 -0
- package/dist/services/payments/index.d.ts.map +1 -0
- package/dist/services/payments/index.js +636 -0
- package/dist/services/payments/index.js.map +1 -0
- package/dist/services/profile/__tests__/fixtures.d.ts +214 -0
- package/dist/services/profile/__tests__/fixtures.d.ts.map +1 -0
- package/dist/services/profile/__tests__/fixtures.js +176 -0
- package/dist/services/profile/__tests__/fixtures.js.map +1 -0
- package/dist/services/profile/basic/index.d.ts +390 -0
- package/dist/services/profile/basic/index.d.ts.map +1 -0
- package/dist/services/profile/basic/index.js +1007 -0
- package/dist/services/profile/basic/index.js.map +1 -0
- package/dist/services/profile/certifications/index.d.ts +74 -0
- package/dist/services/profile/certifications/index.d.ts.map +1 -0
- package/dist/services/profile/certifications/index.js +169 -0
- package/dist/services/profile/certifications/index.js.map +1 -0
- package/dist/services/profile/education/index.d.ts +73 -0
- package/dist/services/profile/education/index.d.ts.map +1 -0
- package/dist/services/profile/education/index.js +168 -0
- package/dist/services/profile/education/index.js.map +1 -0
- package/dist/services/profile/employment/index.d.ts +111 -0
- package/dist/services/profile/employment/index.d.ts.map +1 -0
- package/dist/services/profile/employment/index.js +202 -0
- package/dist/services/profile/employment/index.js.map +1 -0
- package/dist/services/profile/external/index.d.ts +219 -0
- package/dist/services/profile/external/index.d.ts.map +1 -0
- package/dist/services/profile/external/index.js +560 -0
- package/dist/services/profile/external/index.js.map +1 -0
- package/dist/services/profile/index.d.ts +24 -0
- package/dist/services/profile/index.d.ts.map +1 -0
- package/dist/services/profile/index.js +26 -0
- package/dist/services/profile/index.js.map +1 -0
- package/dist/services/profile/industries/index.d.ts +130 -0
- package/dist/services/profile/industries/index.d.ts.map +1 -0
- package/dist/services/profile/industries/index.js +292 -0
- package/dist/services/profile/industries/index.js.map +1 -0
- package/dist/services/profile/portfolio/index.d.ts +352 -0
- package/dist/services/profile/portfolio/index.d.ts.map +1 -0
- package/dist/services/profile/portfolio/index.js +833 -0
- package/dist/services/profile/portfolio/index.js.map +1 -0
- package/dist/services/profile/resume/index.d.ts +60 -0
- package/dist/services/profile/resume/index.d.ts.map +1 -0
- package/dist/services/profile/resume/index.js +212 -0
- package/dist/services/profile/resume/index.js.map +1 -0
- package/dist/services/profile/reviews/index.d.ts +137 -0
- package/dist/services/profile/reviews/index.d.ts.map +1 -0
- package/dist/services/profile/reviews/index.js +431 -0
- package/dist/services/profile/reviews/index.js.map +1 -0
- package/dist/services/profile/shared.d.ts +127 -0
- package/dist/services/profile/shared.d.ts.map +1 -0
- package/dist/services/profile/shared.js +155 -0
- package/dist/services/profile/shared.js.map +1 -0
- package/dist/services/profile/skills/index.d.ts +212 -0
- package/dist/services/profile/skills/index.d.ts.map +1 -0
- package/dist/services/profile/skills/index.js +461 -0
- package/dist/services/profile/skills/index.js.map +1 -0
- package/dist/services/profile/visas/index.d.ts +74 -0
- package/dist/services/profile/visas/index.d.ts.map +1 -0
- package/dist/services/profile/visas/index.js +306 -0
- package/dist/services/profile/visas/index.js.map +1 -0
- package/dist/services/timesheet/index.d.ts +326 -0
- package/dist/services/timesheet/index.d.ts.map +1 -0
- package/dist/services/timesheet/index.js +324 -0
- package/dist/services/timesheet/index.js.map +1 -0
- package/dist/services/translations.d.ts +79 -0
- package/dist/services/translations.d.ts.map +1 -0
- package/dist/services/translations.js +136 -0
- package/dist/services/translations.js.map +1 -0
- package/dist/transport-resilience.d.ts +136 -0
- package/dist/transport-resilience.d.ts.map +1 -0
- package/dist/transport-resilience.js +247 -0
- package/dist/transport-resilience.js.map +1 -0
- package/dist/transport.d.ts +408 -0
- package/dist/transport.d.ts.map +1 -0
- package/dist/transport.js +691 -0
- package/dist/transport.js.map +1 -0
- package/dist/types.d.ts +41 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +18 -0
- package/dist/types.js.map +1 -0
- package/package.json +40 -12
- 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"}
|