api-invoke 0.1.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.
- package/LICENSE +21 -0
- package/README.md +428 -0
- package/dist/chunk-TXAOTXB4.js +543 -0
- package/dist/chunk-TXAOTXB4.js.map +1 -0
- package/dist/index.cjs +2430 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +1359 -0
- package/dist/index.d.ts +1359 -0
- package/dist/index.js +1783 -0
- package/dist/index.js.map +1 -0
- package/dist/parser-PMZEKQPK.js +3 -0
- package/dist/parser-PMZEKQPK.js.map +1 -0
- package/package.json +54 -0
|
@@ -0,0 +1,543 @@
|
|
|
1
|
+
// src/core/types.ts
|
|
2
|
+
var HttpMethod = {
|
|
3
|
+
GET: "GET",
|
|
4
|
+
POST: "POST",
|
|
5
|
+
PUT: "PUT",
|
|
6
|
+
PATCH: "PATCH",
|
|
7
|
+
DELETE: "DELETE",
|
|
8
|
+
HEAD: "HEAD",
|
|
9
|
+
OPTIONS: "OPTIONS"
|
|
10
|
+
};
|
|
11
|
+
var ParamLocation = {
|
|
12
|
+
PATH: "path",
|
|
13
|
+
QUERY: "query",
|
|
14
|
+
HEADER: "header",
|
|
15
|
+
COOKIE: "cookie"
|
|
16
|
+
};
|
|
17
|
+
var AuthType = {
|
|
18
|
+
BEARER: "bearer",
|
|
19
|
+
BASIC: "basic",
|
|
20
|
+
API_KEY: "apiKey",
|
|
21
|
+
QUERY_PARAM: "queryParam",
|
|
22
|
+
OAUTH2: "oauth2",
|
|
23
|
+
COOKIE: "cookie"
|
|
24
|
+
};
|
|
25
|
+
var SpecFormat = {
|
|
26
|
+
OPENAPI_3: "openapi-3",
|
|
27
|
+
OPENAPI_2: "openapi-2",
|
|
28
|
+
RAW_URL: "raw-url",
|
|
29
|
+
MANUAL: "manual",
|
|
30
|
+
GRAPHQL: "graphql"
|
|
31
|
+
};
|
|
32
|
+
var HeaderName = {
|
|
33
|
+
ACCEPT: "Accept",
|
|
34
|
+
AUTHORIZATION: "Authorization",
|
|
35
|
+
CONTENT_TYPE: "Content-Type",
|
|
36
|
+
COOKIE: "Cookie"
|
|
37
|
+
};
|
|
38
|
+
var ContentType = {
|
|
39
|
+
JSON: "application/json",
|
|
40
|
+
FORM_URLENCODED: "application/x-www-form-urlencoded",
|
|
41
|
+
MULTIPART: "multipart/form-data",
|
|
42
|
+
XML: "application/xml",
|
|
43
|
+
OCTET_STREAM: "application/octet-stream",
|
|
44
|
+
TEXT: "text/plain",
|
|
45
|
+
SSE: "text/event-stream"
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
// src/core/errors.ts
|
|
49
|
+
var ErrorKind = {
|
|
50
|
+
CORS: "cors",
|
|
51
|
+
NETWORK: "network",
|
|
52
|
+
AUTH: "auth",
|
|
53
|
+
HTTP: "http",
|
|
54
|
+
PARSE: "parse",
|
|
55
|
+
RATE_LIMIT: "rate-limit",
|
|
56
|
+
TIMEOUT: "timeout",
|
|
57
|
+
GRAPHQL: "graphql"
|
|
58
|
+
};
|
|
59
|
+
var API_INVOKE_ERROR_NAME = "ApiInvokeError";
|
|
60
|
+
var ApiInvokeError = class extends Error {
|
|
61
|
+
/** Error classification for programmatic handling. */
|
|
62
|
+
kind;
|
|
63
|
+
/** HTTP status code, if the error originated from an HTTP response. */
|
|
64
|
+
status;
|
|
65
|
+
/** Human-readable suggestion for how to resolve this error. */
|
|
66
|
+
suggestion;
|
|
67
|
+
/** Whether retrying the request might succeed (e.g. true for rate limits, network errors). */
|
|
68
|
+
retryable;
|
|
69
|
+
/** Response body from the API (when available). May be parsed JSON, a string, or binary data depending on the response content type. */
|
|
70
|
+
responseBody;
|
|
71
|
+
constructor(opts) {
|
|
72
|
+
super(opts.message);
|
|
73
|
+
this.name = API_INVOKE_ERROR_NAME;
|
|
74
|
+
this.kind = opts.kind;
|
|
75
|
+
this.suggestion = opts.suggestion;
|
|
76
|
+
this.retryable = opts.retryable ?? false;
|
|
77
|
+
this.status = opts.status;
|
|
78
|
+
this.responseBody = opts.responseBody;
|
|
79
|
+
}
|
|
80
|
+
};
|
|
81
|
+
function corsError(url) {
|
|
82
|
+
return new ApiInvokeError({
|
|
83
|
+
kind: ErrorKind.CORS,
|
|
84
|
+
message: `Cannot access ${url} \u2014 blocked by CORS policy.`,
|
|
85
|
+
suggestion: "This API does not allow browser requests. Use a CORS proxy or server-side execution.",
|
|
86
|
+
retryable: false
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
function networkError(url) {
|
|
90
|
+
return new ApiInvokeError({
|
|
91
|
+
kind: ErrorKind.NETWORK,
|
|
92
|
+
message: `Network error while fetching ${url}.`,
|
|
93
|
+
suggestion: "Check your internet connection and verify the URL is correct.",
|
|
94
|
+
retryable: true
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
function authError(url, status, responseBody) {
|
|
98
|
+
return new ApiInvokeError({
|
|
99
|
+
kind: ErrorKind.AUTH,
|
|
100
|
+
message: status === 401 ? `Authentication failed for ${url} (401)` : `Authorization denied for ${url} (403)`,
|
|
101
|
+
suggestion: status === 401 ? "Check your credentials. The server rejected your authentication." : "Your credentials are valid but you lack permission for this resource.",
|
|
102
|
+
retryable: false,
|
|
103
|
+
status,
|
|
104
|
+
responseBody
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
function httpError(url, status, statusText, responseBody) {
|
|
108
|
+
const retryable = status === 429 || status >= 500;
|
|
109
|
+
const kind = status === 429 ? ErrorKind.RATE_LIMIT : ErrorKind.HTTP;
|
|
110
|
+
let suggestion;
|
|
111
|
+
if (status === 404) {
|
|
112
|
+
suggestion = "The endpoint was not found. Check the URL path.";
|
|
113
|
+
} else if (status === 429) {
|
|
114
|
+
suggestion = "Rate limited. Wait and retry.";
|
|
115
|
+
} else if (status >= 500) {
|
|
116
|
+
suggestion = "The API server is having issues. Try again later.";
|
|
117
|
+
} else {
|
|
118
|
+
suggestion = `The API returned an error (${status}). Verify the request.`;
|
|
119
|
+
}
|
|
120
|
+
return new ApiInvokeError({
|
|
121
|
+
kind,
|
|
122
|
+
message: `API returned ${status} ${statusText} for ${url}.`,
|
|
123
|
+
suggestion,
|
|
124
|
+
retryable,
|
|
125
|
+
status,
|
|
126
|
+
responseBody
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
function parseError(url, expectedType = "JSON") {
|
|
130
|
+
return new ApiInvokeError({
|
|
131
|
+
kind: ErrorKind.PARSE,
|
|
132
|
+
message: `Failed to parse response from ${url} as ${expectedType}.`,
|
|
133
|
+
suggestion: `The API response body could not be read as ${expectedType}. Verify the endpoint returns the expected content type.`,
|
|
134
|
+
retryable: false
|
|
135
|
+
});
|
|
136
|
+
}
|
|
137
|
+
function graphqlError(messages, status, responseBody) {
|
|
138
|
+
return new ApiInvokeError({
|
|
139
|
+
kind: ErrorKind.GRAPHQL,
|
|
140
|
+
message: `GraphQL errors: ${messages}`,
|
|
141
|
+
suggestion: "Check the query and variables for correctness.",
|
|
142
|
+
retryable: false,
|
|
143
|
+
status,
|
|
144
|
+
responseBody
|
|
145
|
+
});
|
|
146
|
+
}
|
|
147
|
+
function timeoutError(url) {
|
|
148
|
+
return new ApiInvokeError({
|
|
149
|
+
kind: ErrorKind.TIMEOUT,
|
|
150
|
+
message: `Request to ${url} timed out.`,
|
|
151
|
+
suggestion: "The server took too long to respond. Try again or increase the timeout.",
|
|
152
|
+
retryable: true
|
|
153
|
+
});
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
// src/adapters/graphql/introspection.ts
|
|
157
|
+
var TypeKind = {
|
|
158
|
+
SCALAR: "SCALAR",
|
|
159
|
+
OBJECT: "OBJECT",
|
|
160
|
+
ENUM: "ENUM",
|
|
161
|
+
INPUT_OBJECT: "INPUT_OBJECT",
|
|
162
|
+
NON_NULL: "NON_NULL",
|
|
163
|
+
LIST: "LIST",
|
|
164
|
+
UNION: "UNION",
|
|
165
|
+
INTERFACE: "INTERFACE"
|
|
166
|
+
};
|
|
167
|
+
var INTROSPECTION_QUERY = `query IntrospectionQuery {
|
|
168
|
+
__schema {
|
|
169
|
+
queryType { name }
|
|
170
|
+
mutationType { name }
|
|
171
|
+
subscriptionType { name }
|
|
172
|
+
types {
|
|
173
|
+
kind name description
|
|
174
|
+
fields(includeDeprecated: false) {
|
|
175
|
+
name description
|
|
176
|
+
args { name description type { ...TypeRef } defaultValue }
|
|
177
|
+
type { ...TypeRef }
|
|
178
|
+
}
|
|
179
|
+
inputFields { name description type { ...TypeRef } defaultValue }
|
|
180
|
+
enumValues(includeDeprecated: false) { name description }
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
fragment TypeRef on __Type {
|
|
185
|
+
kind name ofType { kind name ofType { kind name ofType { kind name ofType { kind name ofType { kind name ofType { kind name } } } } } }
|
|
186
|
+
}`;
|
|
187
|
+
|
|
188
|
+
// src/adapters/graphql/query-builder.ts
|
|
189
|
+
var DEFAULT_MAX_DEPTH = 2;
|
|
190
|
+
function formatTypeRef(ref) {
|
|
191
|
+
if (ref.kind === TypeKind.NON_NULL) {
|
|
192
|
+
return ref.ofType ? `${formatTypeRef(ref.ofType)}!` : "unknown!";
|
|
193
|
+
}
|
|
194
|
+
if (ref.kind === TypeKind.LIST) {
|
|
195
|
+
return ref.ofType ? `[${formatTypeRef(ref.ofType)}]` : "[unknown]";
|
|
196
|
+
}
|
|
197
|
+
return ref.name ?? "unknown";
|
|
198
|
+
}
|
|
199
|
+
function unwrapType(ref) {
|
|
200
|
+
let current = ref;
|
|
201
|
+
while ((current.kind === TypeKind.NON_NULL || current.kind === TypeKind.LIST) && current.ofType) {
|
|
202
|
+
current = current.ofType;
|
|
203
|
+
}
|
|
204
|
+
return current;
|
|
205
|
+
}
|
|
206
|
+
function isNonNull(ref) {
|
|
207
|
+
return ref.kind === TypeKind.NON_NULL;
|
|
208
|
+
}
|
|
209
|
+
function buildQueryString(operationType, field, typeMap, maxDepth = DEFAULT_MAX_DEPTH) {
|
|
210
|
+
const varDefs = buildVariableDefinitions(field.args);
|
|
211
|
+
const fieldArgs = buildFieldArguments(field.args);
|
|
212
|
+
const selection = buildSelectionSet(field.type, typeMap, maxDepth, /* @__PURE__ */ new Set());
|
|
213
|
+
const varPart = varDefs ? `(${varDefs})` : "";
|
|
214
|
+
const argPart = fieldArgs ? `(${fieldArgs})` : "";
|
|
215
|
+
const selPart = selection ? ` ${selection}` : "";
|
|
216
|
+
return `${operationType} ${field.name}${varPart} { ${field.name}${argPart}${selPart} }`;
|
|
217
|
+
}
|
|
218
|
+
function buildVariableDefinitions(args) {
|
|
219
|
+
if (args.length === 0) return "";
|
|
220
|
+
return args.map((a) => `$${a.name}: ${formatTypeRef(a.type)}`).join(", ");
|
|
221
|
+
}
|
|
222
|
+
function buildFieldArguments(args) {
|
|
223
|
+
if (args.length === 0) return "";
|
|
224
|
+
return args.map((a) => `${a.name}: $${a.name}`).join(", ");
|
|
225
|
+
}
|
|
226
|
+
function buildSelectionSet(typeRef, typeMap, depth, visited) {
|
|
227
|
+
const base = unwrapType(typeRef);
|
|
228
|
+
if (!base.name) return "";
|
|
229
|
+
const type = typeMap.get(base.name);
|
|
230
|
+
if (!type || !type.fields) return "";
|
|
231
|
+
if (base.kind === TypeKind.UNION || base.kind === TypeKind.INTERFACE) {
|
|
232
|
+
return buildUnionSelection();
|
|
233
|
+
}
|
|
234
|
+
if (base.kind !== TypeKind.OBJECT) return "";
|
|
235
|
+
if (visited.has(base.name)) return "";
|
|
236
|
+
visited.add(base.name);
|
|
237
|
+
const fields = [];
|
|
238
|
+
for (const f of type.fields) {
|
|
239
|
+
const fieldBase = unwrapType(f.type);
|
|
240
|
+
if (fieldBase.kind === TypeKind.SCALAR || fieldBase.kind === TypeKind.ENUM) {
|
|
241
|
+
fields.push(f.name);
|
|
242
|
+
} else if (depth > 0 && (fieldBase.kind === TypeKind.OBJECT || fieldBase.kind === TypeKind.UNION || fieldBase.kind === TypeKind.INTERFACE)) {
|
|
243
|
+
const nested = buildSelectionSet(f.type, typeMap, depth - 1, new Set(visited));
|
|
244
|
+
if (nested) {
|
|
245
|
+
fields.push(`${f.name} ${nested}`);
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
visited.delete(base.name);
|
|
250
|
+
if (fields.length === 0) return "";
|
|
251
|
+
return `{ ${fields.join(" ")} }`;
|
|
252
|
+
}
|
|
253
|
+
function buildUnionSelection(type, typeMap, depth, visited) {
|
|
254
|
+
return "{ __typename }";
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
// src/adapters/graphql/parser.ts
|
|
258
|
+
async function parseGraphQLSchema(input, options) {
|
|
259
|
+
const maxDepth = options?.maxDepth ?? 2;
|
|
260
|
+
let schema;
|
|
261
|
+
let endpoint;
|
|
262
|
+
if (typeof input === "string") {
|
|
263
|
+
if (!input.startsWith("http")) {
|
|
264
|
+
throw new ApiInvokeError({
|
|
265
|
+
kind: ErrorKind.PARSE,
|
|
266
|
+
message: "GraphQL input must be an endpoint URL (starting with http) or an introspection JSON object. SDL parsing is not yet supported.",
|
|
267
|
+
suggestion: 'Pass a URL like "https://api.example.com/graphql" or an introspection result object.',
|
|
268
|
+
retryable: false
|
|
269
|
+
});
|
|
270
|
+
}
|
|
271
|
+
endpoint = options?.endpoint ?? input;
|
|
272
|
+
schema = await fetchIntrospection(input, options?.fetch);
|
|
273
|
+
} else {
|
|
274
|
+
schema = extractSchema(input);
|
|
275
|
+
endpoint = options?.endpoint ?? "/graphql";
|
|
276
|
+
}
|
|
277
|
+
const path = extractPath(endpoint);
|
|
278
|
+
const typeMap = buildTypeMap(schema.types);
|
|
279
|
+
const operations = [];
|
|
280
|
+
if (schema.queryType?.name) {
|
|
281
|
+
const queryType = typeMap.get(schema.queryType.name);
|
|
282
|
+
if (queryType?.fields) {
|
|
283
|
+
for (const field of queryType.fields) {
|
|
284
|
+
operations.push(buildOperation(field, "query", path, typeMap, maxDepth));
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
if (schema.mutationType?.name) {
|
|
289
|
+
const mutationType = typeMap.get(schema.mutationType.name);
|
|
290
|
+
if (mutationType?.fields) {
|
|
291
|
+
for (const field of mutationType.fields) {
|
|
292
|
+
operations.push(buildOperation(field, "mutation", path, typeMap, maxDepth));
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
if (schema.subscriptionType?.name) {
|
|
297
|
+
const subType = typeMap.get(schema.subscriptionType.name);
|
|
298
|
+
if (subType?.fields) {
|
|
299
|
+
for (const field of subType.fields) {
|
|
300
|
+
operations.push(buildOperation(field, "subscription", path, typeMap, maxDepth));
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
const title = extractTitle(endpoint);
|
|
305
|
+
return {
|
|
306
|
+
title,
|
|
307
|
+
version: "1.0.0",
|
|
308
|
+
baseUrl: extractBaseUrl(endpoint),
|
|
309
|
+
operations,
|
|
310
|
+
authSchemes: [],
|
|
311
|
+
specFormat: SpecFormat.GRAPHQL
|
|
312
|
+
};
|
|
313
|
+
}
|
|
314
|
+
async function fetchIntrospection(url, fetchFn) {
|
|
315
|
+
const doFetch = fetchFn ?? globalThis.fetch;
|
|
316
|
+
let response;
|
|
317
|
+
try {
|
|
318
|
+
response = await doFetch(url, {
|
|
319
|
+
method: "POST",
|
|
320
|
+
headers: { "Content-Type": "application/json" },
|
|
321
|
+
body: JSON.stringify({ query: INTROSPECTION_QUERY })
|
|
322
|
+
});
|
|
323
|
+
} catch (err) {
|
|
324
|
+
throw new ApiInvokeError({
|
|
325
|
+
kind: ErrorKind.NETWORK,
|
|
326
|
+
message: `Failed to fetch GraphQL introspection from ${url}: ${err instanceof Error ? err.message : String(err)}`,
|
|
327
|
+
suggestion: "Check the endpoint URL and your network connection.",
|
|
328
|
+
retryable: true
|
|
329
|
+
});
|
|
330
|
+
}
|
|
331
|
+
if (!response.ok) {
|
|
332
|
+
throw new ApiInvokeError({
|
|
333
|
+
kind: ErrorKind.HTTP,
|
|
334
|
+
message: `GraphQL introspection failed with HTTP ${response.status} from ${url}.`,
|
|
335
|
+
suggestion: "Verify the endpoint supports introspection and is accessible.",
|
|
336
|
+
retryable: response.status >= 500,
|
|
337
|
+
status: response.status
|
|
338
|
+
});
|
|
339
|
+
}
|
|
340
|
+
let json;
|
|
341
|
+
const cloned = response.clone();
|
|
342
|
+
try {
|
|
343
|
+
json = await response.json();
|
|
344
|
+
} catch (err) {
|
|
345
|
+
let body;
|
|
346
|
+
try {
|
|
347
|
+
body = (await cloned.text()).slice(0, 200);
|
|
348
|
+
} catch {
|
|
349
|
+
}
|
|
350
|
+
throw new ApiInvokeError({
|
|
351
|
+
kind: ErrorKind.PARSE,
|
|
352
|
+
message: `GraphQL introspection response from ${url} is not valid JSON${err instanceof Error ? `: ${err.message}` : ""}.`,
|
|
353
|
+
suggestion: `The endpoint returned a non-JSON response${body ? ` (starts with: "${body}")` : ""}. Verify it is a GraphQL endpoint.`,
|
|
354
|
+
retryable: false
|
|
355
|
+
});
|
|
356
|
+
}
|
|
357
|
+
return extractSchema(json);
|
|
358
|
+
}
|
|
359
|
+
function extractSchema(obj) {
|
|
360
|
+
const record = obj;
|
|
361
|
+
if (record.__schema && typeof record.__schema === "object") {
|
|
362
|
+
return record.__schema;
|
|
363
|
+
}
|
|
364
|
+
if (record.data && typeof record.data === "object") {
|
|
365
|
+
const data = record.data;
|
|
366
|
+
if (data.__schema && typeof data.__schema === "object") {
|
|
367
|
+
return data.__schema;
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
throw new ApiInvokeError({
|
|
371
|
+
kind: ErrorKind.PARSE,
|
|
372
|
+
message: "Invalid GraphQL introspection result: expected { __schema: ... } or { data: { __schema: ... } }.",
|
|
373
|
+
suggestion: "Pass a valid introspection result object or a URL to a GraphQL endpoint.",
|
|
374
|
+
retryable: false
|
|
375
|
+
});
|
|
376
|
+
}
|
|
377
|
+
function buildTypeMap(types) {
|
|
378
|
+
const map = /* @__PURE__ */ new Map();
|
|
379
|
+
for (const type of types) {
|
|
380
|
+
map.set(type.name, type);
|
|
381
|
+
}
|
|
382
|
+
return map;
|
|
383
|
+
}
|
|
384
|
+
function extractPath(endpoint) {
|
|
385
|
+
try {
|
|
386
|
+
return new URL(endpoint).pathname;
|
|
387
|
+
} catch {
|
|
388
|
+
return "/graphql";
|
|
389
|
+
}
|
|
390
|
+
}
|
|
391
|
+
function extractBaseUrl(endpoint) {
|
|
392
|
+
try {
|
|
393
|
+
const url = new URL(endpoint);
|
|
394
|
+
return url.origin;
|
|
395
|
+
} catch {
|
|
396
|
+
return "";
|
|
397
|
+
}
|
|
398
|
+
}
|
|
399
|
+
function extractTitle(endpoint, _schema) {
|
|
400
|
+
try {
|
|
401
|
+
const url = new URL(endpoint);
|
|
402
|
+
return `GraphQL API (${url.hostname})`;
|
|
403
|
+
} catch {
|
|
404
|
+
return "GraphQL API";
|
|
405
|
+
}
|
|
406
|
+
}
|
|
407
|
+
function buildOperation(field, operationType, path, typeMap, maxDepth) {
|
|
408
|
+
const id = operationType === "mutation" ? `mutation_${field.name}` : operationType === "subscription" ? `subscription_${field.name}` : field.name;
|
|
409
|
+
const tags = [operationType];
|
|
410
|
+
const queryString = operationType !== "subscription" ? buildQueryString(operationType, field, typeMap, maxDepth) : void 0;
|
|
411
|
+
const requestBody = buildRequestBody(field.args, typeMap);
|
|
412
|
+
const responseSchema = buildResponseSchema(field.type, typeMap);
|
|
413
|
+
const operation = {
|
|
414
|
+
id,
|
|
415
|
+
path,
|
|
416
|
+
method: HttpMethod.POST,
|
|
417
|
+
summary: field.description ?? `GraphQL ${operationType}: ${field.name}`,
|
|
418
|
+
parameters: [],
|
|
419
|
+
requestBody,
|
|
420
|
+
responseSchema,
|
|
421
|
+
tags
|
|
422
|
+
};
|
|
423
|
+
if (queryString) {
|
|
424
|
+
const argNames = new Set(field.args.map((a) => a.name));
|
|
425
|
+
operation.buildBody = (args) => {
|
|
426
|
+
const variables = {};
|
|
427
|
+
for (const [k, v] of Object.entries(args)) {
|
|
428
|
+
if (argNames.has(k)) variables[k] = v;
|
|
429
|
+
}
|
|
430
|
+
return { query: queryString, variables };
|
|
431
|
+
};
|
|
432
|
+
}
|
|
433
|
+
return operation;
|
|
434
|
+
}
|
|
435
|
+
function buildRequestBody(args, typeMap) {
|
|
436
|
+
if (args.length === 0) return void 0;
|
|
437
|
+
const properties = {};
|
|
438
|
+
const required = [];
|
|
439
|
+
for (const arg of args) {
|
|
440
|
+
properties[arg.name] = mapInputValueToProperty(arg, typeMap);
|
|
441
|
+
if (isNonNull(arg.type)) {
|
|
442
|
+
required.push(arg.name);
|
|
443
|
+
}
|
|
444
|
+
}
|
|
445
|
+
return {
|
|
446
|
+
required: required.length > 0,
|
|
447
|
+
contentType: ContentType.JSON,
|
|
448
|
+
schema: {
|
|
449
|
+
type: "object",
|
|
450
|
+
raw: { type: "object", properties },
|
|
451
|
+
properties,
|
|
452
|
+
required: required.length > 0 ? required : void 0
|
|
453
|
+
}
|
|
454
|
+
};
|
|
455
|
+
}
|
|
456
|
+
function mapInputValueToProperty(input, typeMap) {
|
|
457
|
+
const base = unwrapType(input.type);
|
|
458
|
+
const description = input.description ? `${input.description} (${formatTypeRef(input.type)})` : formatTypeRef(input.type);
|
|
459
|
+
const isList = isListType(input.type);
|
|
460
|
+
if (base.kind === TypeKind.SCALAR) {
|
|
461
|
+
const mapped = mapScalarType(base.name ?? "String");
|
|
462
|
+
const prop = {
|
|
463
|
+
type: isList ? "array" : mapped.type,
|
|
464
|
+
description
|
|
465
|
+
};
|
|
466
|
+
if (mapped.format) prop.format = mapped.format;
|
|
467
|
+
if (input.defaultValue != null) prop.default = input.defaultValue;
|
|
468
|
+
return prop;
|
|
469
|
+
}
|
|
470
|
+
if (base.kind === TypeKind.ENUM) {
|
|
471
|
+
const enumType = typeMap.get(base.name ?? "");
|
|
472
|
+
const enumValues = enumType?.enumValues?.map((e) => e.name);
|
|
473
|
+
return {
|
|
474
|
+
type: isList ? "array" : "string",
|
|
475
|
+
description,
|
|
476
|
+
enum: enumValues
|
|
477
|
+
};
|
|
478
|
+
}
|
|
479
|
+
if (base.kind === TypeKind.INPUT_OBJECT) {
|
|
480
|
+
return {
|
|
481
|
+
type: isList ? "array" : "object",
|
|
482
|
+
description,
|
|
483
|
+
nested: true
|
|
484
|
+
};
|
|
485
|
+
}
|
|
486
|
+
return { type: "string", description };
|
|
487
|
+
}
|
|
488
|
+
function isListType(ref) {
|
|
489
|
+
let current = ref;
|
|
490
|
+
while (current) {
|
|
491
|
+
if (current.kind === TypeKind.LIST) return true;
|
|
492
|
+
current = current.ofType;
|
|
493
|
+
}
|
|
494
|
+
return false;
|
|
495
|
+
}
|
|
496
|
+
function mapScalarType(name) {
|
|
497
|
+
switch (name) {
|
|
498
|
+
case "String":
|
|
499
|
+
case "ID":
|
|
500
|
+
return { type: "string" };
|
|
501
|
+
case "Int":
|
|
502
|
+
return { type: "integer" };
|
|
503
|
+
case "Float":
|
|
504
|
+
return { type: "number" };
|
|
505
|
+
case "Boolean":
|
|
506
|
+
return { type: "boolean" };
|
|
507
|
+
default:
|
|
508
|
+
return { type: "string", format: name.toLowerCase() };
|
|
509
|
+
}
|
|
510
|
+
}
|
|
511
|
+
function buildResponseSchema(typeRef, typeMap) {
|
|
512
|
+
const base = unwrapType(typeRef);
|
|
513
|
+
if (!base.name) return void 0;
|
|
514
|
+
if (base.kind === TypeKind.SCALAR) {
|
|
515
|
+
const mapped = mapScalarType(base.name);
|
|
516
|
+
return { type: mapped.type, format: mapped.format };
|
|
517
|
+
}
|
|
518
|
+
if (base.kind === TypeKind.ENUM) {
|
|
519
|
+
const enumType = typeMap.get(base.name);
|
|
520
|
+
return { type: "string", enum: enumType?.enumValues?.map((e) => e.name) };
|
|
521
|
+
}
|
|
522
|
+
if (base.kind === TypeKind.OBJECT) {
|
|
523
|
+
const objType = typeMap.get(base.name);
|
|
524
|
+
if (!objType?.fields) return { type: "object" };
|
|
525
|
+
const properties = {};
|
|
526
|
+
for (const f of objType.fields) {
|
|
527
|
+
const fieldBase = unwrapType(f.type);
|
|
528
|
+
if (fieldBase.kind === TypeKind.SCALAR) {
|
|
529
|
+
properties[f.name] = mapScalarType(fieldBase.name ?? "String");
|
|
530
|
+
} else if (fieldBase.kind === TypeKind.ENUM) {
|
|
531
|
+
properties[f.name] = { type: "string" };
|
|
532
|
+
} else {
|
|
533
|
+
properties[f.name] = { type: "object" };
|
|
534
|
+
}
|
|
535
|
+
}
|
|
536
|
+
return { type: "object", properties };
|
|
537
|
+
}
|
|
538
|
+
return { type: "object" };
|
|
539
|
+
}
|
|
540
|
+
|
|
541
|
+
export { API_INVOKE_ERROR_NAME, ApiInvokeError, AuthType, ContentType, ErrorKind, HeaderName, HttpMethod, ParamLocation, SpecFormat, authError, corsError, graphqlError, httpError, networkError, parseError, parseGraphQLSchema, timeoutError };
|
|
542
|
+
//# sourceMappingURL=chunk-TXAOTXB4.js.map
|
|
543
|
+
//# sourceMappingURL=chunk-TXAOTXB4.js.map
|