@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,148 @@
1
+ /**
2
+ * Shared GraphQL transport wrapper for service modules (issue #329).
3
+ *
4
+ * Replaces 8 near-identical `callGateway` / `callTalentProfile`
5
+ * helpers that previously lived inside individual service files
6
+ * (`services/{applications,availability,contracts,engagements,jobs,
7
+ * payments,profile/skills,timesheet}`). The Zod-validation hook
8
+ * (`buildWireShapeError`, Z-3 / #286) used to be duplicated across 9
9
+ * sites; here it lives once.
10
+ *
11
+ * The per-service helpers all shared a common envelope but differed in
12
+ * three bounded ways:
13
+ *
14
+ * 1. **Surface**: mobile-gateway (via `stockTransport`) or
15
+ * talent-profile (via `impersonatedTransport`). Resolved here by
16
+ * delegating to `callSurface`, which dispatches based on
17
+ * `SURFACES_REQUIRING_IMPERSONATION`.
18
+ * 2. **Domain error class**: each service threw its own typed error
19
+ * (`ApplicationsError`, `JobsError`, …) so callers can pattern-
20
+ * match `instanceof ServiceError && err.code === "GRAPHQL_ERROR"`
21
+ * without importing a cross-domain enum. We accept the class
22
+ * itself via the `errorFactory` parameter and instantiate it
23
+ * with the code strings every existing helper already used.
24
+ * 3. **Viewer-binding check**: `applications` requires that the
25
+ * response include a non-null `viewer` (the gateway treats a
26
+ * missing viewer as "session valid but no viewer bound", which
27
+ * should surface as `NO_VIEWER` rather than a generic error). All
28
+ * other services omit this check. Toggled via
29
+ * `opts.requireViewer`.
30
+ *
31
+ * `profile/shared.ts#callTalentProfile` remains a separate helper for
32
+ * the moment because its signature differs (it returns the raw
33
+ * `TransportResponse`, takes a `verb` parameter for error tagging, and
34
+ * defers top-level error handling to `ensureNoTopLevelErrors`). The 4
35
+ * profile sub-domains (`industries`, `education`, `employment`,
36
+ * `certifications`) consume it, so a separate migration will handle
37
+ * that consolidation — see #329 follow-up.
38
+ *
39
+ * @see {@link callGatewayShared}
40
+ */
41
+ import type { z } from "zod";
42
+ import type { ToptalSurface } from "../../types.js";
43
+ /**
44
+ * Codes that {@link callGatewayShared} may throw via its
45
+ * {@link DomainErrorFactory}. Every consuming service's per-domain
46
+ * error code union (e.g. `ApplicationsErrorCode`, `JobsErrorCode`)
47
+ * must be a superset of this set (plus its own domain-specific
48
+ * extensions like `NOT_FOUND`).
49
+ *
50
+ * `NO_VIEWER` is included unconditionally even though only callers
51
+ * passing `opts.requireViewer: true` will see it — services that
52
+ * don't opt into the viewer check still need their factory's code
53
+ * union to permit it for the parameter type to satisfy the factory
54
+ * signature. The runtime never throws `NO_VIEWER` for these services.
55
+ */
56
+ export type SharedTransportErrorCode = "NETWORK_ERROR" | "GRAPHQL_ERROR" | "WIRE_SHAPE_ERROR" | "NO_VIEWER" | "UNKNOWN";
57
+ /**
58
+ * Constructor signature for any domain-error class consumed by
59
+ * {@link callGatewayShared}.
60
+ *
61
+ * The `code` parameter is typed as {@link SharedTransportErrorCode}.
62
+ * Each consuming service's domain error code union
63
+ * (e.g. `ApplicationsErrorCode`, `JobsErrorCode`) must be a
64
+ * **superset** of {@link SharedTransportErrorCode} — i.e., every
65
+ * shared code is one of the domain's accepted code strings. Under
66
+ * TypeScript's constructor-parameter contravariance, a class whose
67
+ * constructor accepts a wider code union (e.g.
68
+ * `ApplicationsErrorCode = "NO_VIEWER" | "NOT_FOUND" | …shared codes`)
69
+ * satisfies `new (code: SharedTransportErrorCode, …) => ApplicationsError`.
70
+ *
71
+ * This is verified at compile time at every `callGatewayShared` call
72
+ * site: passing a domain error class whose code union is missing a
73
+ * shared code (e.g. lacks `NO_VIEWER`) raises an assignment error.
74
+ */
75
+ export interface DomainErrorFactory<E extends Error> {
76
+ new (code: SharedTransportErrorCode, message: string, options?: {
77
+ cause?: unknown;
78
+ }): E;
79
+ }
80
+ /**
81
+ * Optional knobs for {@link callGatewayShared}.
82
+ */
83
+ export interface CallGatewaySharedOptions<T> {
84
+ /**
85
+ * Zod schema applied to `body.data` before returning. On parse
86
+ * failure the helper throws `errorFactory("WIRE_SHAPE_ERROR", …)`
87
+ * with the original {@link z.ZodError} chained via `cause` and a
88
+ * field-level diff in the message per
89
+ * `docs/wire-validation-error-format.md` (Z-3 / #286). When
90
+ * omitted, the existing pass-through behavior is preserved.
91
+ *
92
+ * `| undefined` accommodates `exactOptionalPropertyTypes` — per-
93
+ * service wrappers thread their own `schema?: z.ZodType<T>`
94
+ * parameter through unchanged (which may be `undefined`).
95
+ */
96
+ schema?: z.ZodType<T> | undefined;
97
+ /**
98
+ * When `true`, the helper additionally narrows `data` to
99
+ * `{ viewer: { id: string } | null }` and throws
100
+ * `errorFactory("NO_VIEWER", …)` if `data.viewer === null`. Used
101
+ * by `applications` (the gateway returns `viewer === null` when
102
+ * the session is technically valid but no viewer is bound — e.g.
103
+ * the bearer maps to a non-talent account). Other services either
104
+ * use schemas that already constrain `viewer` or don't carry a
105
+ * `viewer` field in their wire shape.
106
+ */
107
+ requireViewer?: boolean | undefined;
108
+ }
109
+ /**
110
+ * Fire a GraphQL request against a Toptal surface and turn
111
+ * transport-level outcomes into a typed domain error.
112
+ *
113
+ * Surface routing: {@link impersonatedTransport} for surfaces in
114
+ * {@link SURFACES_REQUIRING_IMPERSONATION} (talent-profile,
115
+ * scheduler), {@link stockTransport} otherwise (mobile-gateway).
116
+ * Routing is inlined here rather than delegating to `callSurface`
117
+ * because existing service-level tests mock these transport
118
+ * functions directly via `vi.mock("../../transport.js", …)`;
119
+ * routing through `callSurface` would bypass those mocks
120
+ * (the function captures a closure reference at module-load time).
121
+ *
122
+ * Error mapping:
123
+ * - {@link TtctlError} subclasses ({@link AuthRevokedError},
124
+ * `Cf403Error`, etc.) propagate as-is so the CLI / MCP surfaces
125
+ * apply uniform `recovery` rendering.
126
+ * - Other transport throws → `errorFactory("NETWORK_ERROR", …)`.
127
+ * - HTTP 401 → {@link AuthRevokedError}.
128
+ * - Non-2xx → `errorFactory("UNKNOWN", …)`.
129
+ * - Top-level `errors[]` with an auth-revoked extension code (per
130
+ * {@link isAuthRevokedExtensionCode}) → {@link AuthRevokedError}.
131
+ * - Top-level `errors[]` otherwise → `errorFactory("GRAPHQL_ERROR", …)`
132
+ * with the offending {@link GraphQLErrorEntry} chained via `cause`
133
+ * (callers that remap to a domain-specific code — e.g. contracts
134
+ * translating `Record not found` to `NOT_FOUND` — can lift the wire
135
+ * message off `err.cause.message` without parsing `err.message`).
136
+ * - Missing `data` field → `errorFactory("UNKNOWN", …)`.
137
+ * - Zod parse failure (when `schema` provided) →
138
+ * `errorFactory("WIRE_SHAPE_ERROR", …)` carrying the diff payload.
139
+ * - `data.viewer === null` (when `requireViewer` true) →
140
+ * `errorFactory("NO_VIEWER", …)`.
141
+ *
142
+ * Returns the validated `body.data` narrowed to `T`. When `schema` is
143
+ * omitted, the cast is unverified — callers should provide a schema
144
+ * for any operation whose wire shape is gappy in the synthesized SDL
145
+ * (CLAUDE.md § Track 1 vs Track 2 disposition).
146
+ */
147
+ export declare function callGatewayShared<T, E extends Error>(surface: ToptalSurface, token: string, operationName: string, query: string, variables: Record<string, unknown>, errorFactory: DomainErrorFactory<E>, opts?: CallGatewaySharedOptions<T>): Promise<T>;
148
+ //# sourceMappingURL=transport.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"transport.d.ts","sourceRoot":"","sources":["../../../src/services/_shared/transport.ts"],"names":[],"mappings":"AAGA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuCG;AAEH,OAAO,KAAK,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAO7B,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAIpD;;;;;;;;;;;;GAYG;AACH,MAAM,MAAM,wBAAwB,GAAG,eAAe,GAAG,eAAe,GAAG,kBAAkB,GAAG,WAAW,GAAG,SAAS,CAAC;AAExH;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,WAAW,kBAAkB,CAAC,CAAC,SAAS,KAAK;IACjD,KAAK,IAAI,EAAE,wBAAwB,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,OAAO,CAAA;KAAE,GAAG,CAAC,CAAC;CACzF;AAED;;GAEG;AACH,MAAM,WAAW,wBAAwB,CAAC,CAAC;IACzC;;;;;;;;;;;OAWG;IACH,MAAM,CAAC,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,SAAS,CAAC;IAClC;;;;;;;;;OASG;IACH,aAAa,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;CACrC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqCG;AACH,wBAAsB,iBAAiB,CAAC,CAAC,EAAE,CAAC,SAAS,KAAK,EACxD,OAAO,EAAE,aAAa,EACtB,KAAK,EAAE,MAAM,EACb,aAAa,EAAE,MAAM,EACrB,KAAK,EAAE,MAAM,EACb,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAClC,YAAY,EAAE,kBAAkB,CAAC,CAAC,CAAC,EACnC,IAAI,CAAC,EAAE,wBAAwB,CAAC,CAAC,CAAC,GACjC,OAAO,CAAC,CAAC,CAAC,CAyDZ"}
@@ -0,0 +1,102 @@
1
+ // SPDX-License-Identifier: AGPL-3.0-only
2
+ // Copyright (C) 2026 Oleksii PELYKH
3
+ import { AuthRevokedError, TtctlError } from "../../auth/errors.js";
4
+ import { buildWireShapeError } from "../../lib/wire-shape.js";
5
+ import { impersonatedTransport, stockTransport } from "../../transport.js";
6
+ import { SURFACES_REQUIRING_IMPERSONATION } from "../../types.js";
7
+ import { isAuthRevokedExtensionCode } from "../profile/shared.js";
8
+ /**
9
+ * Fire a GraphQL request against a Toptal surface and turn
10
+ * transport-level outcomes into a typed domain error.
11
+ *
12
+ * Surface routing: {@link impersonatedTransport} for surfaces in
13
+ * {@link SURFACES_REQUIRING_IMPERSONATION} (talent-profile,
14
+ * scheduler), {@link stockTransport} otherwise (mobile-gateway).
15
+ * Routing is inlined here rather than delegating to `callSurface`
16
+ * because existing service-level tests mock these transport
17
+ * functions directly via `vi.mock("../../transport.js", …)`;
18
+ * routing through `callSurface` would bypass those mocks
19
+ * (the function captures a closure reference at module-load time).
20
+ *
21
+ * Error mapping:
22
+ * - {@link TtctlError} subclasses ({@link AuthRevokedError},
23
+ * `Cf403Error`, etc.) propagate as-is so the CLI / MCP surfaces
24
+ * apply uniform `recovery` rendering.
25
+ * - Other transport throws → `errorFactory("NETWORK_ERROR", …)`.
26
+ * - HTTP 401 → {@link AuthRevokedError}.
27
+ * - Non-2xx → `errorFactory("UNKNOWN", …)`.
28
+ * - Top-level `errors[]` with an auth-revoked extension code (per
29
+ * {@link isAuthRevokedExtensionCode}) → {@link AuthRevokedError}.
30
+ * - Top-level `errors[]` otherwise → `errorFactory("GRAPHQL_ERROR", …)`
31
+ * with the offending {@link GraphQLErrorEntry} chained via `cause`
32
+ * (callers that remap to a domain-specific code — e.g. contracts
33
+ * translating `Record not found` to `NOT_FOUND` — can lift the wire
34
+ * message off `err.cause.message` without parsing `err.message`).
35
+ * - Missing `data` field → `errorFactory("UNKNOWN", …)`.
36
+ * - Zod parse failure (when `schema` provided) →
37
+ * `errorFactory("WIRE_SHAPE_ERROR", …)` carrying the diff payload.
38
+ * - `data.viewer === null` (when `requireViewer` true) →
39
+ * `errorFactory("NO_VIEWER", …)`.
40
+ *
41
+ * Returns the validated `body.data` narrowed to `T`. When `schema` is
42
+ * omitted, the cast is unverified — callers should provide a schema
43
+ * for any operation whose wire shape is gappy in the synthesized SDL
44
+ * (CLAUDE.md § Track 1 vs Track 2 disposition).
45
+ */
46
+ export async function callGatewayShared(surface, token, operationName, query, variables, errorFactory, opts) {
47
+ const transport = SURFACES_REQUIRING_IMPERSONATION.has(surface) ? impersonatedTransport : stockTransport;
48
+ let res;
49
+ try {
50
+ res = await transport({
51
+ surface,
52
+ authToken: token,
53
+ body: { operationName, query, variables },
54
+ });
55
+ }
56
+ catch (err) {
57
+ if (err instanceof TtctlError)
58
+ throw err;
59
+ throw new errorFactory("NETWORK_ERROR", `${operationName} request failed: ${err.message}`, {
60
+ cause: err,
61
+ });
62
+ }
63
+ if (res.status === 401) {
64
+ throw new AuthRevokedError("Session is invalid or expired.");
65
+ }
66
+ if (res.status < 200 || res.status >= 300) {
67
+ throw new errorFactory("UNKNOWN", `${operationName} returned HTTP ${res.status.toString()}`);
68
+ }
69
+ const body = res.body;
70
+ if (body && Array.isArray(body.errors) && body.errors.length > 0) {
71
+ const first = body.errors[0];
72
+ if (isAuthRevokedExtensionCode(first?.extensions?.code)) {
73
+ throw new AuthRevokedError("Session is invalid or expired.");
74
+ }
75
+ throw new errorFactory("GRAPHQL_ERROR", `${operationName} failed: ${first?.message ?? "GraphQL error"}`, {
76
+ cause: first,
77
+ });
78
+ }
79
+ if (!body?.data) {
80
+ throw new errorFactory("UNKNOWN", `${operationName} response had no \`data\` field`);
81
+ }
82
+ let data;
83
+ if (opts?.schema !== undefined) {
84
+ const parsed = opts.schema.safeParse(body.data);
85
+ if (!parsed.success) {
86
+ const payload = buildWireShapeError(operationName, parsed.error, body.data);
87
+ throw new errorFactory("WIRE_SHAPE_ERROR", payload.message, { cause: parsed.error });
88
+ }
89
+ data = parsed.data;
90
+ }
91
+ else {
92
+ data = body.data;
93
+ }
94
+ if (opts?.requireViewer === true) {
95
+ const withViewer = data;
96
+ if (withViewer.viewer === null) {
97
+ throw new errorFactory("NO_VIEWER", "Session is valid but no viewer is bound to it.");
98
+ }
99
+ }
100
+ return data;
101
+ }
102
+ //# sourceMappingURL=transport.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"transport.js","sourceRoot":"","sources":["../../../src/services/_shared/transport.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,210 @@
1
+ /**
2
+ * Applications-domain error codes. Mirrors the `ProfileError` /
3
+ * `SkillsError` shape per project convention so each sub-domain carries
4
+ * its own typed error class without callers having to import a shared
5
+ * cross-domain enum. Auth-revoked failures throw `AuthRevokedError`
6
+ * (cross-cutting `TtctlError` subclass per #77), not a code on this
7
+ * enum.
8
+ *
9
+ * `NOT_FOUND` is specific to `show()`: the gateway returns a successful
10
+ * response with `viewer.jobActivityItem === null` when the supplied id
11
+ * doesn't resolve to an item the signed-in user can see (no separate
12
+ * 404 status). The service translates that explicit null to a typed
13
+ * `NOT_FOUND` so the CLI can render a "no such application" line and
14
+ * the MCP tool can return a structured `(NOT_FOUND)` error response.
15
+ */
16
+ export type ApplicationsErrorCode = "NO_VIEWER" | "NOT_FOUND" | "GRAPHQL_ERROR" | "NETWORK_ERROR" | "WIRE_SHAPE_ERROR" | "UNKNOWN";
17
+ export declare class ApplicationsError extends Error {
18
+ readonly code: ApplicationsErrorCode;
19
+ readonly name = "ApplicationsError";
20
+ constructor(code: ApplicationsErrorCode, message: string, options?: {
21
+ cause?: unknown;
22
+ });
23
+ }
24
+ /**
25
+ * The five known values of `JobActivityItemStatusGroupEnum` from the
26
+ * synthesized schema (`../research/graphql/gateway/schema.graphql`
27
+ * line 176). Re-declared here as a literal-typed tuple so consumers
28
+ * (CLI flag validation, MCP `z.enum`, `stats()` iteration) share one
29
+ * source of truth without depending on the codegen output.
30
+ *
31
+ * Order matches the schema declaration. `stats()` iterates this array
32
+ * to issue one count call per group.
33
+ */
34
+ export declare const STATUS_GROUPS: readonly ["ACTIVE_ENGAGEMENT", "ARCHIVED", "CLOSED_ENGAGEMENT", "ON_CLIENT_REVIEW", "ON_RECRUITER_REVIEW"];
35
+ export type StatusGroup = (typeof STATUS_GROUPS)[number];
36
+ /**
37
+ * Optional list filter — both fields fold straight into the captured
38
+ * operation's variables (`keywords`, `onlyStatusGroupFilter`).
39
+ */
40
+ export interface ListOptions {
41
+ /**
42
+ * Free-text keyword filter. Each entry is matched server-side against
43
+ * job title, client name, and other indexed fields. Multiple keywords
44
+ * AND together (per observed behavior in the mobile app).
45
+ */
46
+ keywords?: string[];
47
+ /**
48
+ * Restrict the list to one or more status groups. When omitted the
49
+ * server returns rows from every group.
50
+ */
51
+ statusGroups?: StatusGroup[];
52
+ }
53
+ /**
54
+ * Status payload — both `statusV2` (specific) and `statusGroupV2`
55
+ * (coarse, one of {@link STATUS_GROUPS}) carry the same shape on the
56
+ * wire. `verbose` is the human-readable label the Toptal UI shows
57
+ * (e.g. "Active Engagement", "Archived").
58
+ */
59
+ export interface ApplicationStatus {
60
+ value: string;
61
+ verbose: string;
62
+ }
63
+ /**
64
+ * Reference to a job an activity row points at. The full `TalentJob`
65
+ * type carries 30+ fields; this projection surfaces only what `list` /
66
+ * `show` render. `client.fullName` is the company name as the user
67
+ * sees it.
68
+ */
69
+ export interface ApplicationJobRef {
70
+ id: string;
71
+ title: string | null;
72
+ url: string | null;
73
+ client: {
74
+ id: string;
75
+ fullName: string | null;
76
+ } | null;
77
+ }
78
+ /**
79
+ * One row in the activity list — the CLI's `applications list` and the
80
+ * MCP's `ttctl_applications_list` both surface this shape. `engagement`,
81
+ * `jobApplication`, `availabilityRequest`, and `interview` are all
82
+ * presence indicators (only `id` is selected) — a non-null value tells
83
+ * the consumer "this row has reached the corresponding lifecycle
84
+ * stage". The `mostRelevantApplication` union from the captured
85
+ * operation is intentionally elided here: it duplicates information
86
+ * `jobApplication` / `availabilityRequest` already carry.
87
+ */
88
+ export interface JobActivityItem {
89
+ id: string;
90
+ statusV2: ApplicationStatus;
91
+ statusGroupV2: ApplicationStatus;
92
+ statusColor: string | null;
93
+ lastUpdatedAt: string;
94
+ job: ApplicationJobRef;
95
+ jobApplication: {
96
+ id: string;
97
+ } | null;
98
+ engagement: {
99
+ id: string;
100
+ } | null;
101
+ availabilityRequest: {
102
+ id: string;
103
+ } | null;
104
+ interview: {
105
+ id: string;
106
+ } | null;
107
+ }
108
+ /**
109
+ * Detail-view shape for `applications show <id>`. Extends
110
+ * {@link JobActivityItem} with extra job metadata (description, work
111
+ * type, dates) and engagement / application detail fields (rate,
112
+ * commitment, current billing cycle).
113
+ *
114
+ * Field selection is deliberately conservative — the captured
115
+ * `JobActivityItem` operation pulls in the full `jobData` +
116
+ * `jobActivityEngagementData` fragments (~50 fields). The shape here
117
+ * picks the fields the CLI's `pretty` formatter actually renders;
118
+ * future expansions can additively widen the projection.
119
+ */
120
+ export interface JobActivityItemDetail extends JobActivityItem {
121
+ job: ApplicationJobRef & {
122
+ descriptionMd: string | null;
123
+ expectedHours: number | null;
124
+ commitment: {
125
+ slug: string;
126
+ } | null;
127
+ workType: {
128
+ slug: string;
129
+ } | null;
130
+ specialization: {
131
+ title: string;
132
+ } | null;
133
+ startDate: string | null;
134
+ postedWhen: string | null;
135
+ estimatedLength: {
136
+ enumValue: string;
137
+ } | null;
138
+ isCoaching: boolean | null;
139
+ isToptalProject: boolean | null;
140
+ };
141
+ jobApplication: {
142
+ id: string;
143
+ requestedHourlyRate: {
144
+ decimal: string;
145
+ } | null;
146
+ } | null;
147
+ engagement: {
148
+ id: string;
149
+ startDate: string | null;
150
+ endDate: string | null;
151
+ commitment: {
152
+ slug: string;
153
+ } | null;
154
+ expectedHours: number | null;
155
+ } | null;
156
+ }
157
+ /**
158
+ * Aggregate stats payload returned by `stats()`. `total` is the sum
159
+ * across all status groups (also the cross-check value — the
160
+ * unfiltered list call returns the same number); each entry in
161
+ * `groups` is a server-provided count for the named status group.
162
+ */
163
+ export interface ApplicationsStats {
164
+ total: number;
165
+ groups: {
166
+ name: StatusGroup;
167
+ count: number;
168
+ }[];
169
+ }
170
+ /**
171
+ * List the signed-in user's job activity items (applications,
172
+ * availability requests, interviews, engagements).
173
+ *
174
+ * Default scope is whatever the server returns when neither filter is
175
+ * supplied (empirically the full unpaginated set, capped at the
176
+ * server's default limit). The returned array preserves server order;
177
+ * the CLI / MCP do not re-sort.
178
+ *
179
+ * **AC scope adjustment** (per #15 user decision 2026-05-10): the
180
+ * operation accepts NO date filter and NO pagination args. `--from` /
181
+ * `--to` and `--page` / `--per-page` flags are deliberately not exposed
182
+ * by this leaf; the AC items that referenced them are deferred. See
183
+ * `.tmp/workitem-15.md` § Open Questions (RESOLVED) for the rationale.
184
+ */
185
+ export declare function list(token: string, opts?: ListOptions): Promise<JobActivityItem[]>;
186
+ export declare function show(token: string, id: string): Promise<JobActivityItemDetail>;
187
+ /**
188
+ * Aggregate per-status-group counts plus the overall total. Issues N+1
189
+ * `JobActivityItems` calls — one per `JobActivityItemStatusGroupEnum`
190
+ * value — in parallel via `Promise.all`. Each call's
191
+ * `data.viewer.jobActivityList.totalCount` is a server-provided
192
+ * scalar; the helper does NOT count the returned `entities` array
193
+ * (which would be the synthesis the AC forbids).
194
+ *
195
+ * `total` is the sum of per-group counts. The unfiltered call's
196
+ * `totalCount` would yield the same number; we don't issue an extra
197
+ * call to verify because the per-group sum is already authoritative.
198
+ *
199
+ * **Failure mode**: `Promise.all` rejects on the first failed call. A
200
+ * single GraphQL error on one of the 5 groups loses the 4 successful
201
+ * counts. This is intentional: `applications stats` is an aggregate;
202
+ * surfacing partial counts (e.g. "118 total" when one group's call
203
+ * failed) would be misleading because the user reads `total` as
204
+ * authoritative. The right behavior on partial failure is "show no
205
+ * stats and surface the error" — the caller (`runApplicationsStats`)
206
+ * routes the rejection through the structured error envelope so the
207
+ * user knows exactly what went wrong.
208
+ */
209
+ export declare function stats(token: string): Promise<ApplicationsStats>;
210
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/services/applications/index.ts"],"names":[],"mappings":"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"}