@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,352 @@
1
+ /**
2
+ * Portfolio sub-domain error codes. All file-shape and field-shape
3
+ * validation failures collapse into `VALIDATION_ERROR`; the cross-cutting
4
+ * `AuthRevokedError` / `Cf403Error` (from `TtctlError` hierarchy) propagate
5
+ * unchanged so the CLI / MCP surfaces apply their uniform `Recovery: ...`
6
+ * presentation per #77.
7
+ */
8
+ export type PortfolioErrorCode = "NO_VIEWER" | "GRAPHQL_ERROR" | "NETWORK_ERROR" | "USER_ERROR" | "VALIDATION_ERROR" | "FILE_NOT_FOUND" | "FILE_READ_ERROR" | "WIRE_SHAPE_ERROR" | "UNKNOWN";
9
+ export declare class PortfolioError extends Error {
10
+ readonly code: PortfolioErrorCode;
11
+ readonly name = "PortfolioError";
12
+ constructor(code: PortfolioErrorCode, message: string, options?: {
13
+ cause?: unknown;
14
+ });
15
+ }
16
+ /**
17
+ * Skill reference shape carried by `createPortfolioItem` /
18
+ * `updatePortfolioItem` inputs. Extracted from the Portfolio fragment
19
+ * (`research/graphql/talent_profile/fragments/Portfolio.graphql`) which
20
+ * names `skills.nodes[].id` and `.name` — the input variant takes
21
+ * `{ id, name }` per the Pattern 1/2 inferred shapes in
22
+ * `research/notes/10-mutation-input-patterns.md`.
23
+ */
24
+ export interface SkillRef {
25
+ id: string;
26
+ name: string;
27
+ }
28
+ /**
29
+ * Portfolio item kind enumeration. Empirically the server requires this
30
+ * as a non-null field on `CreatePortfolioItemInput.portfolioItem`. The
31
+ * WRITE-side enum uses **lowercase snake_case** values — the
32
+ * SCREAMING_SNAKE forms returned by the read-side `PortfolioItemKindEnum`
33
+ * in `research/graphql/gateway/schema.graphql` are REJECTED on create
34
+ * with `"kind: is not included in the list"` (verified live 2026-05-16
35
+ * during issue #314 investigation, see `.tmp/probe-portfolio-kind.mjs`).
36
+ *
37
+ * Use the {@link PORTFOLIO_ITEM_KIND} constant for autocomplete-friendly
38
+ * references. The {@link PortfolioItemKind} type is derived so adding a
39
+ * member here automatically extends the type.
40
+ */
41
+ export declare const PORTFOLIO_ITEM_KIND: {
42
+ readonly ACCOMPLISHMENT: "accomplishment";
43
+ readonly BASIC: "basic";
44
+ readonly CLASSIC: "classic";
45
+ readonly CODE_BASE: "code_base";
46
+ readonly OTHER_AMAZING_THINGS: "other_amazing_things";
47
+ };
48
+ export type PortfolioItemKind = (typeof PORTFOLIO_ITEM_KIND)[keyof typeof PORTFOLIO_ITEM_KIND];
49
+ /**
50
+ * Portfolio item write-side input shape.
51
+ *
52
+ * **[INFERRED — partially verified live]** Mirrors the read-side `Portfolio`
53
+ * fragment field-by-field per Pattern 1/2 in
54
+ * `research/notes/10-mutation-input-patterns.md`. The `UPDATE_BASIC_INFO`
55
+ * precedent showed that wrapper-key inference can be falsified by live
56
+ * capture (`profile` vs the predicted `basicInfo`). The 2026-05-15 batch
57
+ * (issue #314) live-discovered that `kind`, `showViaToptal`, and `skills`
58
+ * are non-null required on create — {@link add} applies safe defaults so
59
+ * existing callers do not need to thread these fields.
60
+ */
61
+ export interface PortfolioItemInput {
62
+ title?: string;
63
+ description?: string;
64
+ link?: string;
65
+ websiteUrl?: string;
66
+ accomplishment?: string;
67
+ publicationPermit?: boolean;
68
+ clientOrCompanyName?: string;
69
+ toptalRelated?: boolean;
70
+ showViaToptal?: boolean;
71
+ highlight?: boolean;
72
+ kind?: PortfolioItemKind;
73
+ skills?: SkillRef[];
74
+ /**
75
+ * Catalog Industry IDs (from `industriesAutocomplete`) that this
76
+ * portfolio item belongs to. Required by the server on create — empty
77
+ * array surfaces as `industries: You can't leave this empty` USER_ERROR
78
+ * (verified live 2026-05-16, see `.tmp/probe-portfolio-industries.mjs`).
79
+ *
80
+ * **Per-item explicit choice**: industries are NOT defaulted from
81
+ * `Profile.basicInfoIndustries`, `industriesAutocomplete`, skill
82
+ * inference, or any other source. Each portfolio item's industry
83
+ * association is the caller's deliberate decision; auto-defaulting
84
+ * would silently mis-tag work and pollute the portfolio.
85
+ */
86
+ industryIds?: string[];
87
+ /**
88
+ * Cover-image cache name returned by a prior `uploadCover()` call. The
89
+ * two-step "upload, then create with the cache name" flow is what the
90
+ * talent-profile web client uses to bind a cover to a new portfolio
91
+ * item — the read-side `Portfolio.coverImage` field surfaces a URL
92
+ * once the server has resolved the cache name.
93
+ */
94
+ coverImage?: string;
95
+ }
96
+ /**
97
+ * Read-side portfolio item shape — projection of the `Portfolio` fragment.
98
+ * Service callers receive this on `list()` / mutation responses; the
99
+ * mutation responses also surface the full mutated list on `profile.portfolioItems.nodes`.
100
+ *
101
+ * The `kind`, `skills`, and `industries` fields are populated for callers
102
+ * that need the full state (e.g. {@link update}'s read-modify-write
103
+ * path); the server enforces these as non-null on `update` mutations.
104
+ */
105
+ export interface PortfolioItem {
106
+ id: string;
107
+ title: string | null;
108
+ description: string | null;
109
+ link: string | null;
110
+ highlight: boolean;
111
+ coverImage: string | null;
112
+ accomplishment: string | null;
113
+ publicationPermit: boolean | null;
114
+ clientOrCompanyName: string | null;
115
+ websiteUrl: string | null;
116
+ toptalRelated: boolean | null;
117
+ showViaToptal: boolean | null;
118
+ kind: PortfolioItemKind | null;
119
+ skills: SkillRef[];
120
+ industries: {
121
+ id: string;
122
+ name: string;
123
+ }[];
124
+ }
125
+ /**
126
+ * Fetch the signed-in user's portfolio items. Takes the user's auth token
127
+ * and returns the typed array; the empty-list case returns `[]` (not
128
+ * `null`).
129
+ */
130
+ export declare function list(token: string): Promise<PortfolioItem[]>;
131
+ /**
132
+ * Create a new portfolio item.
133
+ *
134
+ * Returns the full updated portfolio list — the server treats portfolio
135
+ * items as a profile-scoped collection, and the mutation response always
136
+ * carries the post-mutation snapshot. Callers that only want the new item
137
+ * find it as the last entry (or by matching `title`).
138
+ *
139
+ * **Required-field defaults**: live capture (issue #314, batch 2026-05-15;
140
+ * extended 2026-05-16 with empirical re-investigation via
141
+ * `.tmp/probe-portfolio-*.mjs`) showed the server requires `kind`,
142
+ * `showViaToptal`, `skills`, `description`, `publicationPermit`, and
143
+ * `industryIds` as non-null (and `description` carries a ≥200-character
144
+ * minimum-length constraint). We project safe defaults so existing
145
+ * callers (e.g. the `ttctl profile portfolio add --title ...` CLI
146
+ * surface) do not need to thread the structural fields; users who want
147
+ * explicit control can still pass them through.
148
+ *
149
+ * - `kind` defaults to `"basic"` — the most neutral enum member,
150
+ * matching a portfolio entry with only `title` / `description` /
151
+ * `link` and no special structural framing (vs. `accomplishment`,
152
+ * `classic` case-study, `code_base` repo, or `other_amazing_things`).
153
+ * Note: write-side enum is LOWERCASE; the synthesized read-side
154
+ * `PortfolioItemKindEnum` uses SCREAMING_SNAKE which is rejected on
155
+ * create.
156
+ * - `showViaToptal` defaults to `true` — a TTCtl-created item is
157
+ * intended for visibility on the user's Toptal profile; users who
158
+ * want to hide can `update` after create.
159
+ * - `skills` defaults to the first profile skill — preserves the
160
+ * "minimal CLI invocation just works" UX; empty-profile case
161
+ * surfaces VALIDATION_ERROR.
162
+ * - `description` defaults to {@link DEFAULT_PORTFOLIO_DESCRIPTION},
163
+ * a 273-character placeholder that satisfies the server's ≥200-char
164
+ * minimum and obviously reads as a placeholder users would refine
165
+ * via `ttctl profile portfolio update`.
166
+ * - `publicationPermit` defaults to `true`. The server treats `false`
167
+ * as blank (`USER_ERROR code: blank, key: publicationPermit`) — only
168
+ * `true` is accepted on create. Users who want to flip the field can
169
+ * `update` after create (the update path may handle `false`
170
+ * differently — uninvestigated).
171
+ * - `industryIds` is **REQUIRED** — caller MUST supply at least one
172
+ * catalog Industry ID per portfolio item. We do NOT default from
173
+ * `Profile.basicInfoIndustries`, `industriesAutocomplete`, or skill
174
+ * inference: each portfolio item's industry association is the
175
+ * caller's deliberate choice; auto-defaulting would silently mis-tag
176
+ * work. Discover IDs via `ttctl profile industries autocomplete
177
+ * <query>`.
178
+ */
179
+ /**
180
+ * `add()` parameter shape: `PortfolioItemInput` with `industryIds` narrowed
181
+ * to a required field. `update()` still accepts the base
182
+ * `PortfolioItemInput` (where `industryIds` is optional — partial-update
183
+ * semantics). Splitting at the function-parameter level keeps a single
184
+ * input vocabulary and lets TypeScript catch missing-industries at the
185
+ * call site instead of waiting for the runtime guard.
186
+ *
187
+ * The empty-array case is still checked at runtime — `[]` is structurally
188
+ * a `string[]` but semantically invalid; TS lacks a native non-empty-array
189
+ * type and `[string, ...string[]]` would be hostile to spread-from-array
190
+ * call sites.
191
+ */
192
+ export type PortfolioItemAddInput = PortfolioItemInput & {
193
+ industryIds: string[];
194
+ };
195
+ export declare function add(token: string, input: PortfolioItemAddInput): Promise<PortfolioItem[]>;
196
+ /**
197
+ * Update a portfolio item by id. Conceptually a partial update — callers
198
+ * supply only the fields they want to change — but the server's
199
+ * `updatePortfolioItem` mutation enforces full-replace semantics on
200
+ * `PortfolioItemUpdateInput` non-null fields. Verified live 2026-05-16
201
+ * (probe `.tmp/probe-portfolio-update-shape2.mjs`): the update input
202
+ * shape DIFFERS from create:
203
+ *
204
+ * - GQL-level non-null required: `showViaToptal`, `skills`.
205
+ * - USER_ERROR (`code: blank`) if missing: `description` (≥200 chars),
206
+ * `publicationPermit`, `industries` (i.e. `industryIds`).
207
+ * - **NOT defined** on `PortfolioItemUpdateInput` (rejected at GQL
208
+ * layer): `kind`, `coverImage`. These are write-once on create; to
209
+ * change a cover, the caller goes through `uploadCover()` →
210
+ * separate mutation, not via `update`.
211
+ *
212
+ * To preserve the partial-update UX over the full-replace wire shape,
213
+ * this function does read-modify-write: fetch the current item, merge
214
+ * caller's `changes` on top of the current state, then send the merged
215
+ * input. The mutation response carries the full post-mutation list,
216
+ * which is returned to callers as `PortfolioItem[]`.
217
+ *
218
+ * The function ACCEPTS the broader `PortfolioItemInput` shape (which
219
+ * still types `kind` / `coverImage`) so callers don't need a separate
220
+ * partial type, but it INTENTIONALLY DROPS those fields from the merged
221
+ * payload before sending — keeping them would surface a confusing
222
+ * "Field is not defined on PortfolioItemUpdateInput" GraphQL error.
223
+ */
224
+ export declare function update(token: string, id: string, changes: PortfolioItemInput): Promise<PortfolioItem[]>;
225
+ /** Remove a portfolio item by id. Returns the post-removal list. */
226
+ export declare function remove(token: string, id: string): Promise<PortfolioItem[]>;
227
+ /**
228
+ * Reorder portfolio items by setting `id` to the absolute `position`. The
229
+ * CLI surface translates the more user-friendly `--before <id>` /
230
+ * `--after <id>` flags to this absolute position; the helpers
231
+ * {@link positionBefore} / {@link positionAfter} compute the position
232
+ * given the current list.
233
+ *
234
+ * Wire shape (verified live 2026-05-16, probe
235
+ * `.tmp/probe-portfolio-reorder.mjs`): the position lives INSIDE
236
+ * `portfolioItem: { position: Int! }` — NOT at the top level of
237
+ * `ChangePortfolioItemPositionInput`. The naive `{ portfolioItemId,
238
+ * position }` shape is rejected with "Field is not defined on
239
+ * ChangePortfolioItemPositionInput" (for `position`) and
240
+ * "portfolioItem (Expected value to not be null)".
241
+ */
242
+ export declare function reorder(token: string, id: string, position: number): Promise<PortfolioItem[]>;
243
+ /**
244
+ * Compute the absolute position (0-based) the moved item should land at,
245
+ * given a target item to be placed BEFORE. Returns `null` if `targetId`
246
+ * is not in the list. The current list is required because the server's
247
+ * `changePortfolioItemPosition` takes an absolute index, not a relative
248
+ * one — the CLI computes the index from a friendlier neighbour-anchored
249
+ * flag.
250
+ *
251
+ * Verified live 2026-05-16: the server interprets `position` against the
252
+ * POST-REMOVAL list (i.e. it first removes the moving item, then inserts
253
+ * at `position`). Valid range is `[0, N-1]` where `N` is the original
254
+ * list length; `position = N` (= the naive "after the last item")
255
+ * returns `USER_ERROR code: invalidPosition` ("Position should be
256
+ * greater or equal to 0 and less than the number of items").
257
+ *
258
+ * When `movingId` is supplied AND points at an item that exists in
259
+ * `items`, that item is filtered out before computing the target's
260
+ * index — this correctly handles the case where the moving item is
261
+ * already in the list and sits before the target (removing it shifts
262
+ * the target left by 1).
263
+ */
264
+ export declare function positionBefore(items: PortfolioItem[], targetId: string, movingId?: string): number | null;
265
+ /**
266
+ * Compute the absolute position the moved item should land at, given a
267
+ * target item to be placed AFTER. Returns `null` if `targetId` is not in
268
+ * the list.
269
+ *
270
+ * Same post-removal semantics as {@link positionBefore} — pass the
271
+ * `movingId` so the helper can filter it out of `items` before
272
+ * computing the target's index. Without `movingId`, the helper assumes
273
+ * the moving item is not present and computes `idx + 1` directly; that
274
+ * value will be one too high for the common "move A `--after` B" CLI
275
+ * flow when both items are in the list and A is before B, and the
276
+ * server will reject it.
277
+ */
278
+ export declare function positionAfter(items: PortfolioItem[], targetId: string, movingId?: string): number | null;
279
+ /**
280
+ * Set or clear the "highlight" flag on a portfolio item. Returns the
281
+ * minimal `{ id, highlight }` projection from the mutation payload —
282
+ * fetching the full updated item is a separate `list()` round-trip when
283
+ * needed.
284
+ */
285
+ export declare function highlight(token: string, id: string, flag?: boolean): Promise<{
286
+ id: string;
287
+ highlight: boolean;
288
+ }>;
289
+ /**
290
+ * File-upload input — service callers pass either a filesystem path (the
291
+ * helper opens it) or a pre-loaded {@link MultipartFile} buffer. The MCP
292
+ * surface uses the buffer path for hosts that lack filesystem access (it
293
+ * decodes base64 first); the CLI surface uses the path-based variant.
294
+ */
295
+ export type FileSource = {
296
+ kind: "path";
297
+ path: string;
298
+ } | {
299
+ kind: "buffer";
300
+ filename: string;
301
+ content: Buffer | Uint8Array;
302
+ contentType?: string;
303
+ };
304
+ export interface UploadPortfolioCoverResult {
305
+ coverImageCacheName: string | null;
306
+ coverImageUrl: string | null;
307
+ }
308
+ /**
309
+ * Crop transformation input for {@link uploadCover}. Pixel-based; all
310
+ * four values are required by the server. {@link uploadCover} accepts
311
+ * this as an optional parameter — when omitted, the service attempts to
312
+ * read the source image's dimensions (PNG header parsing) and defaults
313
+ * to a whole-image crop. For non-PNG sources or parse failures, the
314
+ * service falls back to an oversized `(0, 0, 99999, 99999)` bounding
315
+ * box and lets the server clamp.
316
+ */
317
+ export interface PortfolioCoverTransformation {
318
+ cropX: number;
319
+ cropY: number;
320
+ cropW: number;
321
+ cropH: number;
322
+ }
323
+ /**
324
+ * Upload a cover image for a portfolio item. The cover image is bound to
325
+ * the user's profile rather than a specific portfolio item — the response
326
+ * carries a `coverImageCacheName` the caller passes back into a
327
+ * subsequent `update()` call (or `add()` for new items) via the
328
+ * `coverImage` field.
329
+ *
330
+ * The `transformation` parameter is optional. When omitted, the service
331
+ * resolves a sensible default: PNG sources have their dimensions read
332
+ * from the IHDR header and used as the whole-image crop
333
+ * `(0, 0, width, height)`; non-PNG sources fall back to a large
334
+ * bounding box `(0, 0, 99999, 99999)` (the server clamps oversized
335
+ * crops). Callers who need explicit control pass `transformation`
336
+ * directly.
337
+ *
338
+ * The server enforces a minimum cover-image size of 750x500px — the
339
+ * service does NOT pre-validate this; callers receive a `USER_ERROR`
340
+ * (`code: invalidImage`) when the image is too small.
341
+ */
342
+ export declare function uploadCover(token: string, source: FileSource, transformation?: PortfolioCoverTransformation): Promise<UploadPortfolioCoverResult>;
343
+ export interface UploadPortfolioFileResult {
344
+ fileCacheName: string | null;
345
+ fileUrl: string | null;
346
+ }
347
+ /**
348
+ * Upload a file attachment associated with the user's portfolio. Returns
349
+ * the cache name + url; the CLI surface prints both for downstream use.
350
+ */
351
+ export declare function uploadFile(token: string, source: FileSource): Promise<UploadPortfolioFileResult>;
352
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/services/profile/portfolio/index.ts"],"names":[],"mappings":"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"}