@chrischall/mcp-utils 2.11.0 → 2.12.0

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 (102) hide show
  1. package/README.md +431 -12
  2. package/dist/concurrency/index.d.ts +3 -1
  3. package/dist/concurrency/index.d.ts.map +1 -1
  4. package/dist/concurrency/index.js +3 -1
  5. package/dist/concurrency/index.js.map +1 -1
  6. package/dist/concurrency/verify-after-write.d.ts +84 -0
  7. package/dist/concurrency/verify-after-write.d.ts.map +1 -0
  8. package/dist/concurrency/verify-after-write.js +108 -0
  9. package/dist/concurrency/verify-after-write.js.map +1 -0
  10. package/dist/errors/index.d.ts +35 -1
  11. package/dist/errors/index.d.ts.map +1 -1
  12. package/dist/errors/index.js +79 -1
  13. package/dist/errors/index.js.map +1 -1
  14. package/dist/fetchproxy/fallback.d.ts +130 -0
  15. package/dist/fetchproxy/fallback.d.ts.map +1 -0
  16. package/dist/fetchproxy/fallback.js +199 -0
  17. package/dist/fetchproxy/fallback.js.map +1 -0
  18. package/dist/fetchproxy/index.d.ts +31 -1
  19. package/dist/fetchproxy/index.d.ts.map +1 -1
  20. package/dist/fetchproxy/index.js +120 -13
  21. package/dist/fetchproxy/index.js.map +1 -1
  22. package/dist/fs/confine.d.ts +9 -0
  23. package/dist/fs/confine.d.ts.map +1 -1
  24. package/dist/fs/confine.js +11 -2
  25. package/dist/fs/confine.js.map +1 -1
  26. package/dist/fs/index.d.ts +9 -2
  27. package/dist/fs/index.d.ts.map +1 -1
  28. package/dist/fs/index.js +13 -4
  29. package/dist/fs/index.js.map +1 -1
  30. package/dist/fs/magic.d.ts +35 -0
  31. package/dist/fs/magic.d.ts.map +1 -0
  32. package/dist/fs/magic.js +110 -0
  33. package/dist/fs/magic.js.map +1 -0
  34. package/dist/fs/output.d.ts +14 -10
  35. package/dist/fs/output.d.ts.map +1 -1
  36. package/dist/fs/output.js +21 -45
  37. package/dist/fs/output.js.map +1 -1
  38. package/dist/fs/upload-guard.d.ts +97 -0
  39. package/dist/fs/upload-guard.d.ts.map +1 -0
  40. package/dist/fs/upload-guard.js +185 -0
  41. package/dist/fs/upload-guard.js.map +1 -0
  42. package/dist/fs/write.d.ts +100 -0
  43. package/dist/fs/write.d.ts.map +1 -0
  44. package/dist/fs/write.js +207 -0
  45. package/dist/fs/write.js.map +1 -0
  46. package/dist/graphql/client.d.ts +223 -0
  47. package/dist/graphql/client.d.ts.map +1 -0
  48. package/dist/graphql/client.js +335 -0
  49. package/dist/graphql/client.js.map +1 -0
  50. package/dist/graphql/index.d.ts +20 -0
  51. package/dist/graphql/index.d.ts.map +1 -0
  52. package/dist/graphql/index.js +20 -0
  53. package/dist/graphql/index.js.map +1 -0
  54. package/dist/graphql/operation-kind.d.ts +58 -0
  55. package/dist/graphql/operation-kind.d.ts.map +1 -0
  56. package/dist/graphql/operation-kind.js +237 -0
  57. package/dist/graphql/operation-kind.js.map +1 -0
  58. package/dist/html/index.d.ts +33 -0
  59. package/dist/html/index.d.ts.map +1 -1
  60. package/dist/html/index.js +81 -1
  61. package/dist/html/index.js.map +1 -1
  62. package/dist/http/index.d.ts +11 -1
  63. package/dist/http/index.d.ts.map +1 -1
  64. package/dist/http/index.js +35 -7
  65. package/dist/http/index.js.map +1 -1
  66. package/dist/response/index.d.ts +1 -0
  67. package/dist/response/index.d.ts.map +1 -1
  68. package/dist/response/index.js +1 -0
  69. package/dist/response/index.js.map +1 -1
  70. package/dist/response/untrusted.d.ts +72 -0
  71. package/dist/response/untrusted.d.ts.map +1 -0
  72. package/dist/response/untrusted.js +55 -0
  73. package/dist/response/untrusted.js.map +1 -0
  74. package/dist/scrape/index.d.ts +75 -0
  75. package/dist/scrape/index.d.ts.map +1 -1
  76. package/dist/scrape/index.js +272 -0
  77. package/dist/scrape/index.js.map +1 -1
  78. package/dist/server/confirm-write.d.ts +152 -0
  79. package/dist/server/confirm-write.d.ts.map +1 -0
  80. package/dist/server/confirm-write.js +107 -0
  81. package/dist/server/confirm-write.js.map +1 -0
  82. package/dist/server/index.d.ts +1 -0
  83. package/dist/server/index.d.ts.map +1 -1
  84. package/dist/server/index.js +1 -0
  85. package/dist/server/index.js.map +1 -1
  86. package/dist/session/atomic-write.d.ts +15 -0
  87. package/dist/session/atomic-write.d.ts.map +1 -0
  88. package/dist/session/atomic-write.js +42 -0
  89. package/dist/session/atomic-write.js.map +1 -0
  90. package/dist/session/file-lock.d.ts +57 -0
  91. package/dist/session/file-lock.d.ts.map +1 -0
  92. package/dist/session/file-lock.js +215 -0
  93. package/dist/session/file-lock.js.map +1 -0
  94. package/dist/session/index.d.ts +118 -2
  95. package/dist/session/index.d.ts.map +1 -1
  96. package/dist/session/index.js +200 -82
  97. package/dist/session/index.js.map +1 -1
  98. package/dist/session/login-page.d.ts +73 -0
  99. package/dist/session/login-page.d.ts.map +1 -0
  100. package/dist/session/login-page.js +143 -0
  101. package/dist/session/login-page.js.map +1 -0
  102. package/package.json +5 -1
@@ -0,0 +1,223 @@
1
+ /**
2
+ * `createGraphqlClient` — the GraphQL-over-HTTP POST transport.
3
+ *
4
+ * Consolidates the hand-rolled GraphQL clients in vibo-mcp (`src/client.ts`
5
+ * `ViboClient.post` / `readGraphQLBody` / `unwrap` / `transportError`, the
6
+ * reference implementation) and thumbtack-mcp (`src/client.ts`
7
+ * `ThumbtackClient.graphql`) — chrischall/fleet-audit#1138, #1128. Both POST
8
+ * `{ query, variables }`, treat `errors[]` on an HTTP 200 as a failure, join
9
+ * and truncate the messages, and refuse a non-JSON 2xx as a challenge page;
10
+ * vibo adds auth-code classification, a refresh-and-replay-once, CDN/WAF
11
+ * detection, a timeout plus the caller's cancellation, and a write-aware
12
+ * transport error.
13
+ *
14
+ * It composes the `http` module's pieces rather than re-deriving them:
15
+ * {@link detectEdgeBlock} / {@link EdgeBlockedError} for refusals in front of
16
+ * the API, {@link RetryPolicy} and `parseRetryAfterMs` for 429s,
17
+ * {@link UnauthorizedError} / {@link RateLimitedError} /
18
+ * {@link UpstreamHttpError} for the statuses `createApiClient` already names,
19
+ * `formatApiError` / `truncateErrorMessage` so no upstream body or message
20
+ * reaches a tool result unredacted, and `withAmbientCancellation` so a
21
+ * cancelled tool call stops its request.
22
+ *
23
+ * It is not built ON `createApiClient` because a GraphQL server's error
24
+ * answer is a JSON body at whatever status (Apollo validation errors are a
25
+ * 400, vibo's permission denials a 403) and `fetchJson` turns every non-2xx
26
+ * into a message string, losing the `errors[]` this layer exists to read.
27
+ */
28
+ import { McpToolError } from '../errors/index.js';
29
+ import { type RetryPolicy } from '../http/index.js';
30
+ /** One entry of a GraphQL response's `errors[]`. */
31
+ export interface GraphqlError {
32
+ message?: string;
33
+ /** Some servers (vibo) put the code at the top level… */
34
+ code?: string;
35
+ /** …the spec-blessed home is `extensions.code`. */
36
+ extensions?: {
37
+ code?: string;
38
+ [key: string]: unknown;
39
+ };
40
+ path?: ReadonlyArray<string | number>;
41
+ [key: string]: unknown;
42
+ }
43
+ /** A GraphQL request. */
44
+ export interface GraphqlRequest {
45
+ /** The document. */
46
+ query: string;
47
+ /** Sent only when given. */
48
+ variables?: Record<string, unknown>;
49
+ /** Sent only when given. */
50
+ operationName?: string;
51
+ /** Extra headers for this request, merged over the client's. */
52
+ headers?: Record<string, string>;
53
+ /**
54
+ * Treat the request as safe to repeat even though the document contains a
55
+ * mutation — a sign-in or token refresh, say. It then gets a read's retry
56
+ * policy and a read's transport-error wording. Defaults to what
57
+ * {@link isReadOnlyGraphqlDocument} says about the document.
58
+ */
59
+ idempotent?: boolean;
60
+ }
61
+ /** What {@link GraphqlClient.execute} returns: the parsed envelope plus the HTTP status. */
62
+ export interface GraphqlResult<T = unknown> {
63
+ status: number;
64
+ headers: Headers;
65
+ data?: T | null;
66
+ /** Normalized to an array of objects when present. */
67
+ errors?: GraphqlError[];
68
+ extensions?: Record<string, unknown>;
69
+ }
70
+ /** What {@link GraphqlClientOptions.mapError} is shown. */
71
+ export interface GraphqlErrorContext {
72
+ status: number;
73
+ errors: readonly GraphqlError[];
74
+ data: unknown;
75
+ }
76
+ /** Options for {@link createGraphqlClient}. */
77
+ export interface GraphqlClientOptions {
78
+ /** Absolute URL of the GraphQL endpoint. */
79
+ endpoint: string;
80
+ /** Human name of the upstream, used in messages. Defaults to the endpoint's host. */
81
+ serviceName?: string;
82
+ /**
83
+ * Headers sent on every request — a record, or a (possibly async) function
84
+ * re-read per request, which is where a rotating credential such as vibo's
85
+ * `x-token` belongs. A request's own `headers` override these.
86
+ */
87
+ headers?: Record<string, string> | (() => Record<string, string> | Promise<Record<string, string>>);
88
+ /**
89
+ * Per-attempt timeout in ms, from the request until the body is read.
90
+ * Defaults to 30 000 (both copies used 30 s); `0` disables it. The caller's
91
+ * cancellation applies either way.
92
+ */
93
+ timeout?: number;
94
+ /**
95
+ * 429 retry policy, as `createApiClient`'s: defaults to one retry after 2 s.
96
+ * Other `statuses` (transient 5xx) are retried only for a read-only or
97
+ * `idempotent` request — a 5xx on a mutation may have committed it. A 429
98
+ * is retried for a write too: a rate-limited request was refused, not run.
99
+ */
100
+ retry?: RetryPolicy;
101
+ /**
102
+ * Whether a response is an expired / missing session. Defaults to
103
+ * {@link isGraphqlAuthError}: HTTP 401, or an `UNAUTHENTICATED` /
104
+ * `UNAUTHORIZED` code. Never consulted for a CDN/WAF refusal.
105
+ */
106
+ isAuthError?: (status: number, errors: readonly GraphqlError[]) => boolean;
107
+ /**
108
+ * Re-authenticate after an auth failure (refresh the token, log in again).
109
+ * When set, the request is replayed ONCE with freshly read headers; a second
110
+ * auth failure throws. Single-flighting concurrent refreshes is the
111
+ * caller's job (a `TokenManager` or `createCachedTokenSource` does it).
112
+ */
113
+ onAuthError?: () => Promise<void> | void;
114
+ /** The error an unrecovered auth failure throws. Defaults to {@link UnauthorizedError}. */
115
+ onUnauthorized?: () => Error;
116
+ /** The error an exhausted 429 throws. Defaults to {@link RateLimitedError}. */
117
+ onRateLimited?: () => Error;
118
+ /**
119
+ * Claim a failed response before the default mapping — return an error to
120
+ * throw it, or `undefined` to fall through. Runs after any auth replay, on
121
+ * every response {@link GraphqlClient.request} would otherwise reject (and
122
+ * on none it would accept). The place for site rules such as vibo's
123
+ * "FORBIDDEN / HTTP 403 is a permission denial, not an expired session".
124
+ */
125
+ mapError?: (ctx: GraphqlErrorContext) => Error | undefined;
126
+ /** Hint attached to the {@link GraphqlResponseError} for an `errors[]` answer. */
127
+ errorHint?: string;
128
+ /**
129
+ * Hint for a write whose outcome is unknown (timed out / connection dropped
130
+ * after sending). Name the tool that checks the state.
131
+ */
132
+ writeOutcomeHint?: string;
133
+ /** Injectable fetch. Defaults to the global `fetch`. */
134
+ fetchImpl?: typeof fetch;
135
+ /** Injectable sleep for retries (tests). */
136
+ sleep?: (ms: number) => Promise<void>;
137
+ }
138
+ /** The client surface {@link createGraphqlClient} returns. */
139
+ export interface GraphqlClient {
140
+ /**
141
+ * Send a request and return its parsed envelope, `errors[]` and all — for a
142
+ * raw passthrough tool that shows the caller what the server said. Still
143
+ * throws for everything that is not a GraphQL answer: a transport failure,
144
+ * a CDN/WAF refusal, an exhausted 429, or a body that is not a GraphQL
145
+ * response object (a non-JSON error page is an {@link UpstreamHttpError}).
146
+ * An auth failure is replayed once when `onAuthError` is set, then
147
+ * returned as-is.
148
+ */
149
+ execute<T = unknown>(request: GraphqlRequest): Promise<GraphqlResult<T>>;
150
+ /**
151
+ * Send a request and return its `data`, throwing for any failure: the
152
+ * `execute` failures, an auth failure ({@link UnauthorizedError} or
153
+ * `onUnauthorized`), `errors[]` ({@link GraphqlResponseError}, even beside
154
+ * partial data), a JSON non-2xx with no `errors[]`
155
+ * ({@link UpstreamHttpError}), or a response with no data.
156
+ */
157
+ request<T = unknown>(query: string, variables?: Record<string, unknown>, opts?: Omit<GraphqlRequest, 'query' | 'variables'>): Promise<T>;
158
+ }
159
+ /**
160
+ * The server answered, but with GraphQL `errors[]` (or with something that is
161
+ * not a GraphQL response at all — then `errors` is empty). The message joins
162
+ * the messages, redacted and truncated; the raw entries, any partial `data`,
163
+ * and the codes ride along for callers that branch.
164
+ */
165
+ export declare class GraphqlResponseError extends McpToolError {
166
+ readonly status: number;
167
+ readonly errors: readonly GraphqlError[];
168
+ readonly data: unknown;
169
+ /** Every `code` / `extensions.code` present, in order. */
170
+ readonly codes: readonly string[];
171
+ constructor(message: string, details: {
172
+ status: number;
173
+ errors?: readonly GraphqlError[];
174
+ data?: unknown;
175
+ hint?: string;
176
+ });
177
+ }
178
+ /**
179
+ * The request never produced a response: it timed out, or the connection
180
+ * failed. For a read that is safe to retry. For a write the outcome is
181
+ * UNKNOWN — the server may already have committed it — so `outcomeUnknown` is
182
+ * set, the message says so, and the hint asks for a state check before any
183
+ * retry (a confirmation gate cannot stop a blind retry: a fresh preview earns
184
+ * a fresh approval). A caller's cancellation is not this error; its abort is
185
+ * rethrown untouched.
186
+ */
187
+ export declare class GraphqlTransportError extends McpToolError {
188
+ readonly timedOut: boolean;
189
+ readonly outcomeUnknown: boolean;
190
+ constructor(message: string, details: {
191
+ timedOut: boolean;
192
+ outcomeUnknown: boolean;
193
+ hint: string;
194
+ cause: unknown;
195
+ });
196
+ }
197
+ /** The error code of one `errors[]` entry: top-level `code`, else `extensions.code`. */
198
+ export declare function graphqlErrorCode(error: GraphqlError): string | undefined;
199
+ /**
200
+ * The default expired-session test: HTTP 401, or an `UNAUTHENTICATED` /
201
+ * `UNAUTHORIZED` code. `FORBIDDEN` is deliberately not one — it is a
202
+ * permission denial, and refreshing a token cannot fix it.
203
+ */
204
+ export declare function isGraphqlAuthError(status: number, errors: readonly GraphqlError[]): boolean;
205
+ /**
206
+ * Build a GraphQL-over-HTTP client: POST `{ query, variables?, operationName? }`
207
+ * as JSON, read `errors[]` at any status, and map every other outcome onto the
208
+ * package's existing error types. See {@link GraphqlClient} for what each
209
+ * method throws and {@link GraphqlClientOptions} for the hooks.
210
+ *
211
+ * ```ts
212
+ * const gql = createGraphqlClient({
213
+ * endpoint: 'https://api.vibodj.com/v2/graphql',
214
+ * serviceName: 'Vibo',
215
+ * headers: async () => ({ 'x-token': await tokens.current() }),
216
+ * onAuthError: () => tokens.refresh(),
217
+ * onUnauthorized: () => new SessionNotAuthenticatedError('Vibo', 'https://web.vibodj.com'),
218
+ * });
219
+ * const { me } = await gql.request<{ me: { id: string } }>('query Me { me { id } }');
220
+ * ```
221
+ */
222
+ export declare function createGraphqlClient(opts: GraphqlClientOptions): GraphqlClient;
223
+ //# sourceMappingURL=client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/graphql/client.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,335 @@
1
+ /**
2
+ * `createGraphqlClient` — the GraphQL-over-HTTP POST transport.
3
+ *
4
+ * Consolidates the hand-rolled GraphQL clients in vibo-mcp (`src/client.ts`
5
+ * `ViboClient.post` / `readGraphQLBody` / `unwrap` / `transportError`, the
6
+ * reference implementation) and thumbtack-mcp (`src/client.ts`
7
+ * `ThumbtackClient.graphql`) — chrischall/fleet-audit#1138, #1128. Both POST
8
+ * `{ query, variables }`, treat `errors[]` on an HTTP 200 as a failure, join
9
+ * and truncate the messages, and refuse a non-JSON 2xx as a challenge page;
10
+ * vibo adds auth-code classification, a refresh-and-replay-once, CDN/WAF
11
+ * detection, a timeout plus the caller's cancellation, and a write-aware
12
+ * transport error.
13
+ *
14
+ * It composes the `http` module's pieces rather than re-deriving them:
15
+ * {@link detectEdgeBlock} / {@link EdgeBlockedError} for refusals in front of
16
+ * the API, {@link RetryPolicy} and `parseRetryAfterMs` for 429s,
17
+ * {@link UnauthorizedError} / {@link RateLimitedError} /
18
+ * {@link UpstreamHttpError} for the statuses `createApiClient` already names,
19
+ * `formatApiError` / `truncateErrorMessage` so no upstream body or message
20
+ * reaches a tool result unredacted, and `withAmbientCancellation` so a
21
+ * cancelled tool call stops its request.
22
+ *
23
+ * It is not built ON `createApiClient` because a GraphQL server's error
24
+ * answer is a JSON body at whatever status (Apollo validation errors are a
25
+ * 400, vibo's permission denials a 403) and `fetchJson` turns every non-2xx
26
+ * into a message string, losing the `errors[]` this layer exists to read.
27
+ */
28
+ import { withAmbientCancellation } from '../cancel/index.js';
29
+ import { McpToolError, messageOf, truncateErrorMessage } from '../errors/index.js';
30
+ import { EdgeBlockedError, RateLimitedError, UnauthorizedError, UpstreamHttpError, detectEdgeBlock, formatApiError, parseRetryAfterMs, } from '../http/index.js';
31
+ import { isReadOnlyGraphqlDocument } from './operation-kind.js';
32
+ /**
33
+ * The server answered, but with GraphQL `errors[]` (or with something that is
34
+ * not a GraphQL response at all — then `errors` is empty). The message joins
35
+ * the messages, redacted and truncated; the raw entries, any partial `data`,
36
+ * and the codes ride along for callers that branch.
37
+ */
38
+ export class GraphqlResponseError extends McpToolError {
39
+ status;
40
+ errors;
41
+ data;
42
+ /** Every `code` / `extensions.code` present, in order. */
43
+ codes;
44
+ constructor(message, details) {
45
+ super(message, details.hint !== undefined ? { hint: details.hint } : undefined);
46
+ this.name = 'GraphqlResponseError';
47
+ this.status = details.status;
48
+ this.errors = details.errors ?? [];
49
+ this.data = details.data;
50
+ this.codes = this.errors.map(graphqlErrorCode).filter((c) => c !== undefined);
51
+ }
52
+ }
53
+ /**
54
+ * The request never produced a response: it timed out, or the connection
55
+ * failed. For a read that is safe to retry. For a write the outcome is
56
+ * UNKNOWN — the server may already have committed it — so `outcomeUnknown` is
57
+ * set, the message says so, and the hint asks for a state check before any
58
+ * retry (a confirmation gate cannot stop a blind retry: a fresh preview earns
59
+ * a fresh approval). A caller's cancellation is not this error; its abort is
60
+ * rethrown untouched.
61
+ */
62
+ export class GraphqlTransportError extends McpToolError {
63
+ timedOut;
64
+ outcomeUnknown;
65
+ constructor(message, details) {
66
+ super(message, { hint: details.hint, cause: details.cause });
67
+ this.name = 'GraphqlTransportError';
68
+ this.timedOut = details.timedOut;
69
+ this.outcomeUnknown = details.outcomeUnknown;
70
+ }
71
+ }
72
+ /** The error code of one `errors[]` entry: top-level `code`, else `extensions.code`. */
73
+ export function graphqlErrorCode(error) {
74
+ const code = error.code ?? error.extensions?.code;
75
+ return typeof code === 'string' ? code : undefined;
76
+ }
77
+ const AUTH_CODES = new Set(['UNAUTHENTICATED', 'UNAUTHORIZED']);
78
+ /**
79
+ * The default expired-session test: HTTP 401, or an `UNAUTHENTICATED` /
80
+ * `UNAUTHORIZED` code. `FORBIDDEN` is deliberately not one — it is a
81
+ * permission denial, and refreshing a token cannot fix it.
82
+ */
83
+ export function isGraphqlAuthError(status, errors) {
84
+ if (status === 401)
85
+ return true;
86
+ return errors.some((e) => {
87
+ const code = graphqlErrorCode(e);
88
+ return code !== undefined && AUTH_CODES.has(code);
89
+ });
90
+ }
91
+ const DEFAULT_TIMEOUT_MS = 30_000;
92
+ const DEFAULT_RETRY = { count: 1, delayMs: 2000 };
93
+ const defaultSleep = (ms) => new Promise((r) => setTimeout(r, ms));
94
+ /** Thrown internally when our own timer fired. */
95
+ class TimedOut extends Error {
96
+ }
97
+ function objectOf(value) {
98
+ return typeof value === 'object' && value !== null && !Array.isArray(value)
99
+ ? value
100
+ : undefined;
101
+ }
102
+ /** `errors` as an array of objects, whatever shape the server sent. */
103
+ function normalizeErrors(raw) {
104
+ if (raw === undefined || raw === null)
105
+ return undefined;
106
+ const list = Array.isArray(raw) ? raw : [raw];
107
+ return list.map((e) => {
108
+ const obj = objectOf(e);
109
+ if (obj)
110
+ return obj;
111
+ return { message: typeof e === 'string' ? e : String(e) };
112
+ });
113
+ }
114
+ /** Parse a body into a GraphQL envelope, or `undefined` when it is not one. */
115
+ function parseEnvelope(text) {
116
+ let parsed;
117
+ try {
118
+ parsed = JSON.parse(text);
119
+ }
120
+ catch {
121
+ return undefined;
122
+ }
123
+ const obj = objectOf(parsed);
124
+ if (!obj)
125
+ return undefined;
126
+ const errors = normalizeErrors(obj.errors);
127
+ const extensions = objectOf(obj.extensions);
128
+ return {
129
+ ...('data' in obj ? { data: obj.data } : {}),
130
+ ...(errors !== undefined ? { errors } : {}),
131
+ ...(extensions !== undefined ? { extensions } : {}),
132
+ };
133
+ }
134
+ function hostOf(url) {
135
+ try {
136
+ return new URL(url).host;
137
+ }
138
+ catch {
139
+ return url;
140
+ }
141
+ }
142
+ function pathOf(url) {
143
+ try {
144
+ return new URL(url).pathname;
145
+ }
146
+ catch {
147
+ return url;
148
+ }
149
+ }
150
+ /**
151
+ * Build a GraphQL-over-HTTP client: POST `{ query, variables?, operationName? }`
152
+ * as JSON, read `errors[]` at any status, and map every other outcome onto the
153
+ * package's existing error types. See {@link GraphqlClient} for what each
154
+ * method throws and {@link GraphqlClientOptions} for the hooks.
155
+ *
156
+ * ```ts
157
+ * const gql = createGraphqlClient({
158
+ * endpoint: 'https://api.vibodj.com/v2/graphql',
159
+ * serviceName: 'Vibo',
160
+ * headers: async () => ({ 'x-token': await tokens.current() }),
161
+ * onAuthError: () => tokens.refresh(),
162
+ * onUnauthorized: () => new SessionNotAuthenticatedError('Vibo', 'https://web.vibodj.com'),
163
+ * });
164
+ * const { me } = await gql.request<{ me: { id: string } }>('query Me { me { id } }');
165
+ * ```
166
+ */
167
+ export function createGraphqlClient(opts) {
168
+ const service = opts.serviceName ?? hostOf(opts.endpoint);
169
+ const path = pathOf(opts.endpoint);
170
+ const doFetch = opts.fetchImpl ?? fetch;
171
+ const sleep = opts.sleep ?? defaultSleep;
172
+ const timeoutMs = opts.timeout ?? DEFAULT_TIMEOUT_MS;
173
+ const retry = opts.retry ?? DEFAULT_RETRY;
174
+ const retryStatuses = retry.statuses ?? [429];
175
+ const isAuth = opts.isAuthError ?? isGraphqlAuthError;
176
+ async function headersFor(req) {
177
+ const base = typeof opts.headers === 'function' ? await opts.headers() : (opts.headers ?? {});
178
+ return { 'content-type': 'application/json', accept: 'application/json', ...base, ...req.headers };
179
+ }
180
+ /**
181
+ * One HTTP attempt, bounded from the request until the body has been read.
182
+ * The read is RACED against the timer rather than trusting the body stream
183
+ * to honour the abort, so a `fetchImpl` that ignores the signal is bounded
184
+ * too.
185
+ */
186
+ async function attempt(init) {
187
+ const controller = timeoutMs > 0 ? new AbortController() : undefined;
188
+ let timer;
189
+ let expired;
190
+ if (controller) {
191
+ expired = new Promise((_resolve, reject) => {
192
+ controller.signal.addEventListener('abort', () => reject(new TimedOut()), { once: true });
193
+ });
194
+ expired.catch(() => { });
195
+ timer = setTimeout(() => controller.abort(), timeoutMs);
196
+ }
197
+ const signal = withAmbientCancellation(controller?.signal);
198
+ const work = (async () => {
199
+ const res = await doFetch(opts.endpoint, { ...init, ...(signal ? { signal } : {}) });
200
+ return { res, text: await res.text() };
201
+ })();
202
+ work.catch(() => { });
203
+ try {
204
+ return await (expired ? Promise.race([work, expired]) : work);
205
+ }
206
+ catch (err) {
207
+ // Told apart by WHICH signal fired: an abort is an `AbortError` whichever
208
+ // end caused it, and a caller's cancellation is not this service timing out.
209
+ if (controller?.signal.aborted)
210
+ throw new TimedOut();
211
+ throw err;
212
+ }
213
+ finally {
214
+ clearTimeout(timer);
215
+ }
216
+ }
217
+ function transportError(err, timedOut, write) {
218
+ const what = timedOut
219
+ ? `Request to ${service} timed out after ${timeoutMs}ms`
220
+ : `Request to ${service} failed: ${truncateErrorMessage(messageOf(err), 200)}`;
221
+ if (write) {
222
+ return new GraphqlTransportError(`${what} — the change may already have been applied (outcome is unknown).`, {
223
+ timedOut,
224
+ outcomeUnknown: true,
225
+ hint: opts.writeOutcomeHint ??
226
+ 'Do not repeat this write blindly — check the current state first, and retry only if the change is not there.',
227
+ cause: err,
228
+ });
229
+ }
230
+ return new GraphqlTransportError(`${what}.`, {
231
+ timedOut,
232
+ outcomeUnknown: false,
233
+ hint: `The ${service} API may be slow or unreachable — check your connection and retry.`,
234
+ cause: err,
235
+ });
236
+ }
237
+ /** Send with the retry policy; returns the final response and its body. */
238
+ async function send(req, write) {
239
+ const body = JSON.stringify({
240
+ query: req.query,
241
+ ...(req.variables !== undefined ? { variables: req.variables } : {}),
242
+ ...(req.operationName !== undefined ? { operationName: req.operationName } : {}),
243
+ });
244
+ for (let tries = 0;; tries++) {
245
+ let sent;
246
+ try {
247
+ sent = await attempt({ method: 'POST', headers: await headersFor(req), body });
248
+ }
249
+ catch (err) {
250
+ if (err instanceof TimedOut)
251
+ throw transportError(err, true, write);
252
+ if (err instanceof Error && err.name === 'AbortError')
253
+ throw err; // the caller cancelled
254
+ throw transportError(err, false, write);
255
+ }
256
+ const status = sent.res.status;
257
+ const retryable = retryStatuses.includes(status) && (status === 429 || !write);
258
+ if (retryable && tries < retry.count) {
259
+ const delay = retry.honorRetryAfter
260
+ ? parseRetryAfterMs(sent.res.headers.get('retry-after'), {
261
+ defaultMs: retry.delayMs,
262
+ capMs: retry.maxRetryAfterMs ?? 30_000,
263
+ })
264
+ : retry.delayMs;
265
+ await sleep(delay);
266
+ continue;
267
+ }
268
+ return sent;
269
+ }
270
+ }
271
+ async function execute(req) {
272
+ const write = req.idempotent === true ? false : !isReadOnlyGraphqlDocument(req.query);
273
+ for (let replayed = false;; replayed = true) {
274
+ const { res, text } = await send(req, write);
275
+ const status = res.status;
276
+ if (status >= 400) {
277
+ const edge = detectEdgeBlock({ body: text, headers: res.headers, status });
278
+ if (edge)
279
+ throw new EdgeBlockedError(status, edge.vendor, { service, method: 'POST', path });
280
+ }
281
+ if (status === 429)
282
+ throw opts.onRateLimited ? opts.onRateLimited() : new RateLimitedError(service);
283
+ const envelope = parseEnvelope(text);
284
+ if (envelope === undefined) {
285
+ if (status >= 400 && status !== 401) {
286
+ throw new UpstreamHttpError(status, formatApiError(status, 'POST', path, text, { service }));
287
+ }
288
+ if (status < 400) {
289
+ const edge = detectEdgeBlock({ body: text, headers: res.headers, status });
290
+ if (edge)
291
+ throw new EdgeBlockedError(status, edge.vendor, { service, method: 'POST', path });
292
+ throw new GraphqlResponseError(text.trim().length === 0
293
+ ? `${service} GraphQL API returned an empty response (HTTP ${status}).`
294
+ : `${service} GraphQL API returned a non-JSON body (HTTP ${status}) — this is usually a challenge or error page, not data.`, { status, hint: 'Retry shortly. If it persists, the endpoint or its request shape has changed.' });
295
+ }
296
+ }
297
+ const result = { status, headers: res.headers, ...envelope };
298
+ if (!replayed && opts.onAuthError && isAuth(status, result.errors ?? [])) {
299
+ await opts.onAuthError();
300
+ continue;
301
+ }
302
+ return result;
303
+ }
304
+ }
305
+ async function request(query, variables, more = {}) {
306
+ const result = await execute({ ...more, query, ...(variables !== undefined ? { variables } : {}) });
307
+ const { status, data } = result;
308
+ const errors = result.errors ?? [];
309
+ const failed = errors.length > 0 || status >= 400 || data === undefined || data === null;
310
+ if (failed && opts.mapError) {
311
+ const mapped = opts.mapError({ status, errors, data });
312
+ if (mapped)
313
+ throw mapped;
314
+ }
315
+ if (isAuth(status, errors))
316
+ throw opts.onUnauthorized ? opts.onUnauthorized() : new UnauthorizedError(service);
317
+ if (errors.length > 0) {
318
+ const detail = errors.map((e) => (typeof e.message === 'string' && e.message ? e.message : 'Unknown error')).join('; ');
319
+ throw new GraphqlResponseError(`${service} GraphQL error: ${truncateErrorMessage(detail)}`, {
320
+ status,
321
+ errors,
322
+ data,
323
+ ...(opts.errorHint !== undefined ? { hint: opts.errorHint } : {}),
324
+ });
325
+ }
326
+ if (status >= 400)
327
+ throw new UpstreamHttpError(status, `${service} GraphQL API returned HTTP ${status}.`);
328
+ if (data === undefined || data === null) {
329
+ throw new GraphqlResponseError(`${service} GraphQL API returned an empty response.`, { status });
330
+ }
331
+ return data;
332
+ }
333
+ return { execute, request };
334
+ }
335
+ //# sourceMappingURL=client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/graphql/client.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,20 @@
1
+ /**
2
+ * `@chrischall/mcp-utils/graphql` — a GraphQL-over-HTTP transport and a
3
+ * GraphQL operation-kind lexer.
4
+ *
5
+ * Zero optional peers (it builds on the core `http`, `errors` and `cancel`
6
+ * modules only). It is a subpath rather than part of the core barrel for the
7
+ * same reason `/healthcheck` is: only the handful of GraphQL servers in the
8
+ * fleet need it.
9
+ *
10
+ * - {@link createGraphqlClient} — POST `{ query, variables, operationName }`,
11
+ * `errors[]` at any status, auth replay, CDN/WAF detection, timeout and
12
+ * cancellation, write-aware transport errors (vibo-mcp / thumbtack-mcp,
13
+ * chrischall/fleet-audit#1138, #1128).
14
+ * - {@link graphqlOperationKinds} / {@link isReadOnlyGraphqlDocument} — is a
15
+ * document a query, mutation or subscription (onehome-mcp / hemnet-mcp /
16
+ * booli-mcp / vibo-mcp, chrischall/fleet-audit#1080, #988, #1020).
17
+ */
18
+ export * from './client.js';
19
+ export * from './operation-kind.js';
20
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/graphql/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,cAAc,aAAa,CAAC;AAC5B,cAAc,qBAAqB,CAAC"}
@@ -0,0 +1,20 @@
1
+ /**
2
+ * `@chrischall/mcp-utils/graphql` — a GraphQL-over-HTTP transport and a
3
+ * GraphQL operation-kind lexer.
4
+ *
5
+ * Zero optional peers (it builds on the core `http`, `errors` and `cancel`
6
+ * modules only). It is a subpath rather than part of the core barrel for the
7
+ * same reason `/healthcheck` is: only the handful of GraphQL servers in the
8
+ * fleet need it.
9
+ *
10
+ * - {@link createGraphqlClient} — POST `{ query, variables, operationName }`,
11
+ * `errors[]` at any status, auth replay, CDN/WAF detection, timeout and
12
+ * cancellation, write-aware transport errors (vibo-mcp / thumbtack-mcp,
13
+ * chrischall/fleet-audit#1138, #1128).
14
+ * - {@link graphqlOperationKinds} / {@link isReadOnlyGraphqlDocument} — is a
15
+ * document a query, mutation or subscription (onehome-mcp / hemnet-mcp /
16
+ * booli-mcp / vibo-mcp, chrischall/fleet-audit#1080, #988, #1020).
17
+ */
18
+ export * from './client.js';
19
+ export * from './operation-kind.js';
20
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/graphql/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,cAAc,aAAa,CAAC;AAC5B,cAAc,qBAAqB,CAAC"}