@executor-js/plugin-graphql 1.4.33 → 1.5.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/AddGraphqlSource-P3D3UXRJ.js +179 -0
- package/dist/AddGraphqlSource-P3D3UXRJ.js.map +1 -0
- package/dist/EditGraphqlSource-FVF67CTP.js +38 -0
- package/dist/EditGraphqlSource-FVF67CTP.js.map +1 -0
- package/dist/GraphqlAccountsPanel-GBNFHLFH.js +9 -0
- package/dist/GraphqlAccountsPanel-GBNFHLFH.js.map +1 -0
- package/dist/api/group.d.ts +108 -119
- package/dist/api/handlers.d.ts +9 -7
- package/dist/api/index.d.ts +117 -104
- package/dist/chunk-2Y3J3CVO.js +191 -0
- package/dist/chunk-2Y3J3CVO.js.map +1 -0
- package/dist/chunk-ADQTI2OK.js +1309 -0
- package/dist/chunk-ADQTI2OK.js.map +1 -0
- package/dist/{chunk-UIAHATHP.js → chunk-N5GJE7R6.js} +42 -58
- package/dist/chunk-N5GJE7R6.js.map +1 -0
- package/dist/chunk-VCYDSSIK.js +79 -0
- package/dist/chunk-VCYDSSIK.js.map +1 -0
- package/dist/client.js +7 -7
- package/dist/client.js.map +1 -1
- package/dist/core.js +20 -28
- package/dist/index.js +2 -2
- package/dist/react/AddGraphqlSource.d.ts +1 -1
- package/dist/react/EditGraphqlSource.d.ts +2 -2
- package/dist/react/GraphqlAccountsPanel.d.ts +6 -0
- package/dist/react/GraphqlSignInButton.d.ts +6 -2
- package/dist/react/GraphqlSourceFields.d.ts +2 -2
- package/dist/react/atoms.d.ts +95 -205
- package/dist/react/auth-method-config.d.ts +9 -0
- package/dist/react/client.d.ts +108 -97
- package/dist/react/defaults.d.ts +16 -2
- package/dist/react/index.d.ts +2 -2
- package/dist/react/source-plugin.d.ts +2 -2
- package/dist/sdk/errors.d.ts +8 -6
- package/dist/sdk/index.d.ts +5 -5
- package/dist/sdk/introspect.d.ts +1 -1
- package/dist/sdk/invoke.d.ts +1 -4
- package/dist/sdk/plugin.d.ts +94 -104
- package/dist/sdk/store.d.ts +11 -28
- package/dist/sdk/types.d.ts +110 -72
- package/package.json +5 -4
- package/dist/AddGraphqlSource-CJCUUYNM.js +0 -250
- package/dist/AddGraphqlSource-CJCUUYNM.js.map +0 -1
- package/dist/EditGraphqlSource-YLTPUYW4.js +0 -267
- package/dist/EditGraphqlSource-YLTPUYW4.js.map +0 -1
- package/dist/GraphqlSourceSummary-YWJX6ONU.js +0 -70
- package/dist/GraphqlSourceSummary-YWJX6ONU.js.map +0 -1
- package/dist/chunk-2252RTCE.js +0 -1730
- package/dist/chunk-2252RTCE.js.map +0 -1
- package/dist/chunk-D3FN3ZDA.js +0 -125
- package/dist/chunk-D3FN3ZDA.js.map +0 -1
- package/dist/chunk-M4SJY6CB.js +0 -45
- package/dist/chunk-M4SJY6CB.js.map +0 -1
- package/dist/chunk-UIAHATHP.js.map +0 -1
- package/dist/react/GraphqlSourceSummary.d.ts +0 -5
package/dist/chunk-2252RTCE.js
DELETED
|
@@ -1,1730 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
graphqlPresets
|
|
3
|
-
} from "./chunk-D6E4WAYW.js";
|
|
4
|
-
import {
|
|
5
|
-
ExtractedField,
|
|
6
|
-
ExtractionResult,
|
|
7
|
-
GRAPHQL_OAUTH_CONNECTION_SLOT,
|
|
8
|
-
GraphqlArgument,
|
|
9
|
-
GraphqlAuthRequiredError,
|
|
10
|
-
GraphqlConfiguredValueInput,
|
|
11
|
-
GraphqlCredentialInput,
|
|
12
|
-
GraphqlExtractionError,
|
|
13
|
-
GraphqlIntrospectionError,
|
|
14
|
-
GraphqlInvocationError,
|
|
15
|
-
GraphqlSourceAuth,
|
|
16
|
-
GraphqlSourceAuthInput,
|
|
17
|
-
InvocationResult,
|
|
18
|
-
OperationBinding,
|
|
19
|
-
graphqlHeaderSlot,
|
|
20
|
-
graphqlQueryParamSlot
|
|
21
|
-
} from "./chunk-UIAHATHP.js";
|
|
22
|
-
|
|
23
|
-
// src/sdk/introspect.ts
|
|
24
|
-
import { Effect, Option, Schema } from "effect";
|
|
25
|
-
import { HttpClient, HttpClientRequest } from "effect/unstable/http";
|
|
26
|
-
var INTROSPECTION_QUERY = `
|
|
27
|
-
query IntrospectionQuery {
|
|
28
|
-
__schema {
|
|
29
|
-
queryType { name }
|
|
30
|
-
mutationType { name }
|
|
31
|
-
types {
|
|
32
|
-
kind
|
|
33
|
-
name
|
|
34
|
-
description
|
|
35
|
-
fields(includeDeprecated: false) {
|
|
36
|
-
name
|
|
37
|
-
description
|
|
38
|
-
args {
|
|
39
|
-
name
|
|
40
|
-
description
|
|
41
|
-
type {
|
|
42
|
-
...TypeRef
|
|
43
|
-
}
|
|
44
|
-
defaultValue
|
|
45
|
-
}
|
|
46
|
-
type {
|
|
47
|
-
...TypeRef
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
inputFields {
|
|
51
|
-
name
|
|
52
|
-
description
|
|
53
|
-
type {
|
|
54
|
-
...TypeRef
|
|
55
|
-
}
|
|
56
|
-
defaultValue
|
|
57
|
-
}
|
|
58
|
-
enumValues(includeDeprecated: false) {
|
|
59
|
-
name
|
|
60
|
-
description
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
fragment TypeRef on __Type {
|
|
67
|
-
kind
|
|
68
|
-
name
|
|
69
|
-
ofType {
|
|
70
|
-
kind
|
|
71
|
-
name
|
|
72
|
-
ofType {
|
|
73
|
-
kind
|
|
74
|
-
name
|
|
75
|
-
ofType {
|
|
76
|
-
kind
|
|
77
|
-
name
|
|
78
|
-
ofType {
|
|
79
|
-
kind
|
|
80
|
-
name
|
|
81
|
-
ofType {
|
|
82
|
-
kind
|
|
83
|
-
name
|
|
84
|
-
ofType {
|
|
85
|
-
kind
|
|
86
|
-
name
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
|
-
`;
|
|
95
|
-
var IntrospectionTypeRefLeaf = Schema.Struct({
|
|
96
|
-
kind: Schema.String,
|
|
97
|
-
name: Schema.NullOr(Schema.String),
|
|
98
|
-
ofType: Schema.optional(Schema.Null)
|
|
99
|
-
});
|
|
100
|
-
var IntrospectionTypeRef5 = Schema.Struct({
|
|
101
|
-
kind: Schema.String,
|
|
102
|
-
name: Schema.NullOr(Schema.String),
|
|
103
|
-
ofType: Schema.optional(Schema.NullOr(IntrospectionTypeRefLeaf))
|
|
104
|
-
});
|
|
105
|
-
var IntrospectionTypeRef4 = Schema.Struct({
|
|
106
|
-
kind: Schema.String,
|
|
107
|
-
name: Schema.NullOr(Schema.String),
|
|
108
|
-
ofType: Schema.optional(Schema.NullOr(IntrospectionTypeRef5))
|
|
109
|
-
});
|
|
110
|
-
var IntrospectionTypeRef3 = Schema.Struct({
|
|
111
|
-
kind: Schema.String,
|
|
112
|
-
name: Schema.NullOr(Schema.String),
|
|
113
|
-
ofType: Schema.optional(Schema.NullOr(IntrospectionTypeRef4))
|
|
114
|
-
});
|
|
115
|
-
var IntrospectionTypeRef2 = Schema.Struct({
|
|
116
|
-
kind: Schema.String,
|
|
117
|
-
name: Schema.NullOr(Schema.String),
|
|
118
|
-
ofType: Schema.optional(Schema.NullOr(IntrospectionTypeRef3))
|
|
119
|
-
});
|
|
120
|
-
var IntrospectionTypeRefSchema = Schema.Struct({
|
|
121
|
-
kind: Schema.String,
|
|
122
|
-
name: Schema.NullOr(Schema.String),
|
|
123
|
-
ofType: Schema.optional(Schema.NullOr(IntrospectionTypeRef2))
|
|
124
|
-
});
|
|
125
|
-
var IntrospectionInputValueSchema = Schema.Struct({
|
|
126
|
-
name: Schema.String,
|
|
127
|
-
description: Schema.NullOr(Schema.String),
|
|
128
|
-
type: IntrospectionTypeRefSchema,
|
|
129
|
-
defaultValue: Schema.NullOr(Schema.String)
|
|
130
|
-
});
|
|
131
|
-
var IntrospectionFieldSchema = Schema.Struct({
|
|
132
|
-
name: Schema.String,
|
|
133
|
-
description: Schema.NullOr(Schema.String),
|
|
134
|
-
args: Schema.Array(IntrospectionInputValueSchema),
|
|
135
|
-
type: IntrospectionTypeRefSchema
|
|
136
|
-
});
|
|
137
|
-
var IntrospectionTypeSchema = Schema.Struct({
|
|
138
|
-
kind: Schema.String,
|
|
139
|
-
name: Schema.String,
|
|
140
|
-
description: Schema.NullOr(Schema.String),
|
|
141
|
-
fields: Schema.NullOr(Schema.Array(IntrospectionFieldSchema)),
|
|
142
|
-
inputFields: Schema.NullOr(Schema.Array(IntrospectionInputValueSchema)),
|
|
143
|
-
enumValues: Schema.NullOr(
|
|
144
|
-
Schema.Array(
|
|
145
|
-
Schema.Struct({
|
|
146
|
-
name: Schema.String,
|
|
147
|
-
description: Schema.NullOr(Schema.String)
|
|
148
|
-
})
|
|
149
|
-
)
|
|
150
|
-
)
|
|
151
|
-
});
|
|
152
|
-
var IntrospectionResultSchema = Schema.Struct({
|
|
153
|
-
__schema: Schema.Struct({
|
|
154
|
-
queryType: Schema.NullOr(Schema.Struct({ name: Schema.String })),
|
|
155
|
-
mutationType: Schema.NullOr(Schema.Struct({ name: Schema.String })),
|
|
156
|
-
types: Schema.Array(IntrospectionTypeSchema)
|
|
157
|
-
})
|
|
158
|
-
});
|
|
159
|
-
var IntrospectionResponseSchema = Schema.Struct({
|
|
160
|
-
data: Schema.optional(IntrospectionResultSchema),
|
|
161
|
-
errors: Schema.optional(Schema.Array(Schema.Unknown))
|
|
162
|
-
});
|
|
163
|
-
var UpstreamErrorResponseSchema = Schema.Struct({
|
|
164
|
-
message: Schema.optional(Schema.String),
|
|
165
|
-
errors: Schema.optional(
|
|
166
|
-
Schema.Array(
|
|
167
|
-
Schema.Struct({
|
|
168
|
-
message: Schema.optional(Schema.String)
|
|
169
|
-
})
|
|
170
|
-
)
|
|
171
|
-
)
|
|
172
|
-
});
|
|
173
|
-
var IntrospectionJsonSchema = Schema.Union([
|
|
174
|
-
Schema.Struct({ data: IntrospectionResultSchema }),
|
|
175
|
-
IntrospectionResultSchema
|
|
176
|
-
]);
|
|
177
|
-
var JsonTextSchema = Schema.fromJsonString(Schema.Unknown);
|
|
178
|
-
var decodeUpstreamErrorResponse = Schema.decodeUnknownOption(UpstreamErrorResponseSchema);
|
|
179
|
-
var firstUpstreamErrorMessage = (value) => {
|
|
180
|
-
const decoded = decodeUpstreamErrorResponse(value);
|
|
181
|
-
return Option.match(decoded, {
|
|
182
|
-
onNone: () => null,
|
|
183
|
-
onSome: (response) => {
|
|
184
|
-
if (response.message) return response.message;
|
|
185
|
-
for (const entry of response.errors ?? []) {
|
|
186
|
-
const message = entry.message;
|
|
187
|
-
if (message) return message;
|
|
188
|
-
}
|
|
189
|
-
return null;
|
|
190
|
-
}
|
|
191
|
-
});
|
|
192
|
-
};
|
|
193
|
-
var redactUpstreamBody = (body) => body.replaceAll(
|
|
194
|
-
/("(?:access_token|refresh_token|id_token|client_secret|token|authorization)"\s*:\s*")[^"]*(")/gi,
|
|
195
|
-
"$1[redacted]$2"
|
|
196
|
-
).replaceAll(
|
|
197
|
-
/((?:access_token|refresh_token|id_token|client_secret|token|authorization)=)[^&\s]*/gi,
|
|
198
|
-
"$1[redacted]"
|
|
199
|
-
).replaceAll(
|
|
200
|
-
/((?:authorization|access-token|refresh-token|id-token|client-secret|token)\s*:\s*)(?:bearer\s+)?[^\s,;]+/gi,
|
|
201
|
-
"$1[redacted]"
|
|
202
|
-
);
|
|
203
|
-
var upstreamTextMessage = (body) => {
|
|
204
|
-
const text = redactUpstreamBody(body.replaceAll(/\s+/g, " ").trim());
|
|
205
|
-
if (text.length === 0) return null;
|
|
206
|
-
return text.length > 500 ? `${text.slice(0, 500)}...` : text;
|
|
207
|
-
};
|
|
208
|
-
var introspect = Effect.fn("GraphQL.introspect")(function* (endpoint, headers, queryParams) {
|
|
209
|
-
const client = yield* HttpClient.HttpClient;
|
|
210
|
-
const requestEndpoint = queryParams && Object.keys(queryParams).length > 0 ? (() => {
|
|
211
|
-
const url = new URL(endpoint);
|
|
212
|
-
for (const [name, value] of Object.entries(queryParams)) {
|
|
213
|
-
url.searchParams.set(name, value);
|
|
214
|
-
}
|
|
215
|
-
return url.toString();
|
|
216
|
-
})() : endpoint;
|
|
217
|
-
let request = HttpClientRequest.post(requestEndpoint).pipe(
|
|
218
|
-
HttpClientRequest.setHeader("Content-Type", "application/json"),
|
|
219
|
-
HttpClientRequest.setHeader("Accept", "application/json"),
|
|
220
|
-
HttpClientRequest.setHeader("User-Agent", "executor-graphql"),
|
|
221
|
-
HttpClientRequest.bodyJsonUnsafe({
|
|
222
|
-
query: INTROSPECTION_QUERY
|
|
223
|
-
})
|
|
224
|
-
);
|
|
225
|
-
if (headers) {
|
|
226
|
-
for (const [k, v] of Object.entries(headers)) {
|
|
227
|
-
request = HttpClientRequest.setHeader(request, k, v);
|
|
228
|
-
}
|
|
229
|
-
}
|
|
230
|
-
const response = yield* client.execute(request).pipe(
|
|
231
|
-
Effect.tapCause((cause) => Effect.logError("graphql introspection request failed", cause)),
|
|
232
|
-
Effect.mapError(
|
|
233
|
-
() => new GraphqlIntrospectionError({
|
|
234
|
-
message: "Failed to reach GraphQL endpoint"
|
|
235
|
-
})
|
|
236
|
-
)
|
|
237
|
-
);
|
|
238
|
-
if (response.status !== 200) {
|
|
239
|
-
const responseText = yield* response.text.pipe(Effect.catch(() => Effect.succeed("")));
|
|
240
|
-
const raw2 = responseText ? yield* Schema.decodeUnknownEffect(JsonTextSchema)(responseText).pipe(
|
|
241
|
-
Effect.catch(() => Effect.succeed(null))
|
|
242
|
-
) : null;
|
|
243
|
-
const upstreamMessage = upstreamTextMessage(
|
|
244
|
-
(raw2 === null ? null : firstUpstreamErrorMessage(raw2)) ?? responseText
|
|
245
|
-
);
|
|
246
|
-
return yield* new GraphqlIntrospectionError({
|
|
247
|
-
message: upstreamMessage ? `Introspection failed with status ${response.status}: ${upstreamMessage}` : `Introspection failed with status ${response.status}`
|
|
248
|
-
});
|
|
249
|
-
}
|
|
250
|
-
const raw = yield* response.json.pipe(
|
|
251
|
-
Effect.tapCause((cause) => Effect.logError("graphql introspection JSON parse failed", cause)),
|
|
252
|
-
Effect.mapError(
|
|
253
|
-
() => new GraphqlIntrospectionError({
|
|
254
|
-
message: `Failed to parse introspection response as JSON`
|
|
255
|
-
})
|
|
256
|
-
)
|
|
257
|
-
);
|
|
258
|
-
const json = yield* Schema.decodeUnknownEffect(IntrospectionResponseSchema)(raw).pipe(
|
|
259
|
-
Effect.mapError(
|
|
260
|
-
() => new GraphqlIntrospectionError({
|
|
261
|
-
message: "Introspection response has an invalid shape"
|
|
262
|
-
})
|
|
263
|
-
)
|
|
264
|
-
);
|
|
265
|
-
if (json.errors && Array.isArray(json.errors) && json.errors.length > 0) {
|
|
266
|
-
const upstreamMessage = firstUpstreamErrorMessage(json);
|
|
267
|
-
return yield* new GraphqlIntrospectionError({
|
|
268
|
-
message: upstreamMessage ? `Introspection returned ${json.errors.length} error(s): ${upstreamMessage}` : `Introspection returned ${json.errors.length} error(s)`
|
|
269
|
-
});
|
|
270
|
-
}
|
|
271
|
-
if (!json.data?.__schema) {
|
|
272
|
-
return yield* new GraphqlIntrospectionError({
|
|
273
|
-
message: "Introspection response missing __schema"
|
|
274
|
-
});
|
|
275
|
-
}
|
|
276
|
-
return json.data;
|
|
277
|
-
});
|
|
278
|
-
var parseIntrospectionJson = (text) => Schema.decodeUnknownEffect(Schema.fromJsonString(IntrospectionJsonSchema))(text).pipe(
|
|
279
|
-
Effect.map((parsed) => "data" in parsed ? parsed.data : parsed),
|
|
280
|
-
Effect.mapError(
|
|
281
|
-
() => new GraphqlIntrospectionError({
|
|
282
|
-
message: "Failed to parse introspection JSON"
|
|
283
|
-
})
|
|
284
|
-
)
|
|
285
|
-
);
|
|
286
|
-
|
|
287
|
-
// src/sdk/extract.ts
|
|
288
|
-
import { Effect as Effect2, Match, Option as Option2 } from "effect";
|
|
289
|
-
var unwrapTypeName = (ref) => {
|
|
290
|
-
if (ref.name) return ref.name;
|
|
291
|
-
if (ref.ofType) return unwrapTypeName(ref.ofType);
|
|
292
|
-
return "Unknown";
|
|
293
|
-
};
|
|
294
|
-
var isNonNull = (ref) => ref.kind === "NON_NULL";
|
|
295
|
-
var buildDefinitions = (types) => {
|
|
296
|
-
const defs = {};
|
|
297
|
-
for (const [name, type] of types) {
|
|
298
|
-
if (name.startsWith("__")) continue;
|
|
299
|
-
if (type.kind === "INPUT_OBJECT" && type.inputFields) {
|
|
300
|
-
const properties = {};
|
|
301
|
-
const required = [];
|
|
302
|
-
for (const field of type.inputFields) {
|
|
303
|
-
const schema = typeRefToJsonSchema(field.type, types);
|
|
304
|
-
if (field.description) {
|
|
305
|
-
schema.description = field.description;
|
|
306
|
-
}
|
|
307
|
-
properties[field.name] = schema;
|
|
308
|
-
if (isNonNull(field.type)) {
|
|
309
|
-
required.push(field.name);
|
|
310
|
-
}
|
|
311
|
-
}
|
|
312
|
-
const def = { type: "object", properties };
|
|
313
|
-
if (required.length > 0) def.required = required;
|
|
314
|
-
if (type.description) def.description = type.description;
|
|
315
|
-
defs[name] = def;
|
|
316
|
-
}
|
|
317
|
-
if (type.kind === "ENUM" && type.enumValues) {
|
|
318
|
-
defs[name] = {
|
|
319
|
-
type: "string",
|
|
320
|
-
enum: type.enumValues.map((v) => v.name),
|
|
321
|
-
...type.description ? { description: type.description } : {}
|
|
322
|
-
};
|
|
323
|
-
}
|
|
324
|
-
}
|
|
325
|
-
return defs;
|
|
326
|
-
};
|
|
327
|
-
var typeRefToJsonSchema = (ref, types) => Match.value(ref.kind).pipe(
|
|
328
|
-
Match.when(
|
|
329
|
-
"NON_NULL",
|
|
330
|
-
() => ref.ofType ? typeRefToJsonSchema(ref.ofType, types) : {}
|
|
331
|
-
),
|
|
332
|
-
Match.when(
|
|
333
|
-
"LIST",
|
|
334
|
-
() => ({
|
|
335
|
-
type: "array",
|
|
336
|
-
items: ref.ofType ? typeRefToJsonSchema(ref.ofType, types) : {}
|
|
337
|
-
})
|
|
338
|
-
),
|
|
339
|
-
Match.when("SCALAR", () => scalarToJsonSchema(ref.name ?? "String")),
|
|
340
|
-
Match.when(
|
|
341
|
-
"ENUM",
|
|
342
|
-
() => ref.name ? { $ref: `#/$defs/${ref.name}` } : { type: "string" }
|
|
343
|
-
),
|
|
344
|
-
Match.when(
|
|
345
|
-
"INPUT_OBJECT",
|
|
346
|
-
() => ref.name ? { $ref: `#/$defs/${ref.name}` } : { type: "object" }
|
|
347
|
-
),
|
|
348
|
-
Match.whenOr(
|
|
349
|
-
"OBJECT",
|
|
350
|
-
"INTERFACE",
|
|
351
|
-
"UNION",
|
|
352
|
-
() => ({ type: "object" })
|
|
353
|
-
),
|
|
354
|
-
Match.option,
|
|
355
|
-
Option2.getOrElse(() => ({}))
|
|
356
|
-
);
|
|
357
|
-
var scalarToJsonSchema = (name) => Match.value(name).pipe(
|
|
358
|
-
Match.whenOr("String", "ID", () => ({ type: "string" })),
|
|
359
|
-
Match.when("Int", () => ({ type: "integer" })),
|
|
360
|
-
Match.when("Float", () => ({ type: "number" })),
|
|
361
|
-
Match.when("Boolean", () => ({ type: "boolean" })),
|
|
362
|
-
Match.option,
|
|
363
|
-
Option2.getOrElse(
|
|
364
|
-
() => ({ type: "string", description: `Custom scalar: ${name}` })
|
|
365
|
-
)
|
|
366
|
-
);
|
|
367
|
-
var buildInputSchema = (args, types) => {
|
|
368
|
-
if (args.length === 0) return void 0;
|
|
369
|
-
const properties = {};
|
|
370
|
-
const required = [];
|
|
371
|
-
for (const arg of args) {
|
|
372
|
-
const schema = typeRefToJsonSchema(arg.type, types);
|
|
373
|
-
if (arg.description) {
|
|
374
|
-
schema.description = arg.description;
|
|
375
|
-
}
|
|
376
|
-
properties[arg.name] = schema;
|
|
377
|
-
if (isNonNull(arg.type)) {
|
|
378
|
-
required.push(arg.name);
|
|
379
|
-
}
|
|
380
|
-
}
|
|
381
|
-
const inputSchema = {
|
|
382
|
-
type: "object",
|
|
383
|
-
properties
|
|
384
|
-
};
|
|
385
|
-
if (required.length > 0) inputSchema.required = required;
|
|
386
|
-
return inputSchema;
|
|
387
|
-
};
|
|
388
|
-
var formatTypeRef = (ref) => Match.value(ref.kind).pipe(
|
|
389
|
-
Match.when("NON_NULL", () => ref.ofType ? `${formatTypeRef(ref.ofType)}!` : "Unknown!"),
|
|
390
|
-
Match.when("LIST", () => ref.ofType ? `[${formatTypeRef(ref.ofType)}]` : "[Unknown]"),
|
|
391
|
-
Match.option,
|
|
392
|
-
Option2.getOrElse(() => ref.name ?? "Unknown")
|
|
393
|
-
);
|
|
394
|
-
var extractFields = (_schema, kind, typeName, types) => {
|
|
395
|
-
if (!typeName) return [];
|
|
396
|
-
const type = types.get(typeName);
|
|
397
|
-
if (!type?.fields) return [];
|
|
398
|
-
return type.fields.filter((f) => !f.name.startsWith("__")).map((field) => {
|
|
399
|
-
const args = field.args.map(
|
|
400
|
-
(arg) => GraphqlArgument.make({
|
|
401
|
-
name: arg.name,
|
|
402
|
-
typeName: formatTypeRef(arg.type),
|
|
403
|
-
required: isNonNull(arg.type),
|
|
404
|
-
description: arg.description ? Option2.some(arg.description) : Option2.none()
|
|
405
|
-
})
|
|
406
|
-
);
|
|
407
|
-
const inputSchema = buildInputSchema(field.args, types);
|
|
408
|
-
return ExtractedField.make({
|
|
409
|
-
fieldName: field.name,
|
|
410
|
-
kind,
|
|
411
|
-
description: field.description ? Option2.some(field.description) : Option2.none(),
|
|
412
|
-
arguments: args,
|
|
413
|
-
inputSchema: inputSchema ? Option2.some(inputSchema) : Option2.none(),
|
|
414
|
-
returnTypeName: unwrapTypeName(field.type)
|
|
415
|
-
});
|
|
416
|
-
});
|
|
417
|
-
};
|
|
418
|
-
var extract = (introspection) => Effect2.try({
|
|
419
|
-
try: () => {
|
|
420
|
-
const schema = introspection.__schema;
|
|
421
|
-
const typeMap = /* @__PURE__ */ new Map();
|
|
422
|
-
for (const t of schema.types) {
|
|
423
|
-
typeMap.set(t.name, t);
|
|
424
|
-
}
|
|
425
|
-
const definitions = buildDefinitions(typeMap);
|
|
426
|
-
const queryFields = extractFields(schema, "query", schema.queryType?.name, typeMap);
|
|
427
|
-
const mutationFields = extractFields(schema, "mutation", schema.mutationType?.name, typeMap);
|
|
428
|
-
return {
|
|
429
|
-
result: ExtractionResult.make({
|
|
430
|
-
schemaName: Option2.none(),
|
|
431
|
-
fields: [...queryFields, ...mutationFields]
|
|
432
|
-
}),
|
|
433
|
-
definitions
|
|
434
|
-
};
|
|
435
|
-
},
|
|
436
|
-
catch: () => new GraphqlExtractionError({
|
|
437
|
-
message: "Failed to extract GraphQL schema"
|
|
438
|
-
})
|
|
439
|
-
});
|
|
440
|
-
|
|
441
|
-
// src/sdk/invoke.ts
|
|
442
|
-
import { Effect as Effect3, Option as Option3 } from "effect";
|
|
443
|
-
import { HttpClient as HttpClient2, HttpClientRequest as HttpClientRequest2 } from "effect/unstable/http";
|
|
444
|
-
import { resolveSecretBackedMap } from "@executor-js/sdk/core";
|
|
445
|
-
var resolveHeaders = (headers, secrets) => {
|
|
446
|
-
const entries = Object.entries(headers);
|
|
447
|
-
const secretCount = entries.reduce(
|
|
448
|
-
(acc, [, value]) => typeof value === "string" ? acc : acc + 1,
|
|
449
|
-
0
|
|
450
|
-
);
|
|
451
|
-
return resolveSecretBackedMap({
|
|
452
|
-
values: headers,
|
|
453
|
-
getSecret: (secretId) => secrets.get(secretId).pipe(Effect3.catch(() => Effect3.succeed(null))),
|
|
454
|
-
missing: "drop",
|
|
455
|
-
onMissing: (name) => new GraphqlInvocationError({
|
|
456
|
-
message: `Missing secret for header "${name}"`,
|
|
457
|
-
statusCode: Option3.none()
|
|
458
|
-
})
|
|
459
|
-
}).pipe(
|
|
460
|
-
Effect3.catch(() => Effect3.succeed(void 0)),
|
|
461
|
-
Effect3.map((resolved) => resolved ?? {}),
|
|
462
|
-
Effect3.withSpan("plugin.graphql.secret.resolve", {
|
|
463
|
-
attributes: {
|
|
464
|
-
"plugin.graphql.headers.total": entries.length,
|
|
465
|
-
"plugin.graphql.headers.secret_count": secretCount
|
|
466
|
-
}
|
|
467
|
-
})
|
|
468
|
-
);
|
|
469
|
-
};
|
|
470
|
-
var endpointWithQueryParams = (endpoint, queryParams) => {
|
|
471
|
-
if (Object.keys(queryParams).length === 0) return endpoint;
|
|
472
|
-
const url = new URL(endpoint);
|
|
473
|
-
for (const [name, value] of Object.entries(queryParams)) {
|
|
474
|
-
url.searchParams.set(name, value);
|
|
475
|
-
}
|
|
476
|
-
return url.toString();
|
|
477
|
-
};
|
|
478
|
-
var endpointForTelemetry = (endpoint) => {
|
|
479
|
-
if (!URL.canParse(endpoint)) return endpoint;
|
|
480
|
-
const url = new URL(endpoint);
|
|
481
|
-
url.search = "";
|
|
482
|
-
url.hash = "";
|
|
483
|
-
return url.toString();
|
|
484
|
-
};
|
|
485
|
-
var isJsonContentType = (ct) => {
|
|
486
|
-
if (!ct) return false;
|
|
487
|
-
const normalized = ct.split(";")[0]?.trim().toLowerCase() ?? "";
|
|
488
|
-
return normalized === "application/json" || normalized.includes("+json") || normalized.includes("json");
|
|
489
|
-
};
|
|
490
|
-
var invoke = Effect3.fn("GraphQL.invoke")(function* (operation, args, endpoint, resolvedHeaders, resolvedQueryParams = {}) {
|
|
491
|
-
const client = yield* HttpClient2.HttpClient;
|
|
492
|
-
const requestEndpoint = endpointWithQueryParams(endpoint, resolvedQueryParams);
|
|
493
|
-
const telemetryEndpoint = endpointForTelemetry(endpoint);
|
|
494
|
-
yield* Effect3.annotateCurrentSpan({
|
|
495
|
-
"http.method": "POST",
|
|
496
|
-
"http.url": telemetryEndpoint,
|
|
497
|
-
"plugin.graphql.endpoint": telemetryEndpoint,
|
|
498
|
-
"plugin.graphql.operation_kind": operation.kind,
|
|
499
|
-
"plugin.graphql.field_name": operation.fieldName,
|
|
500
|
-
"plugin.graphql.headers.resolved_count": Object.keys(resolvedHeaders).length,
|
|
501
|
-
"plugin.graphql.query_params.resolved_count": Object.keys(resolvedQueryParams).length
|
|
502
|
-
});
|
|
503
|
-
const variables = {};
|
|
504
|
-
for (const varName of operation.variableNames) {
|
|
505
|
-
if (args[varName] !== void 0) {
|
|
506
|
-
variables[varName] = args[varName];
|
|
507
|
-
}
|
|
508
|
-
}
|
|
509
|
-
if (typeof args.variables === "object" && args.variables !== null) {
|
|
510
|
-
Object.assign(variables, args.variables);
|
|
511
|
-
}
|
|
512
|
-
let request = HttpClientRequest2.post(requestEndpoint).pipe(
|
|
513
|
-
HttpClientRequest2.setHeader("Content-Type", "application/json"),
|
|
514
|
-
HttpClientRequest2.bodyJsonUnsafe({
|
|
515
|
-
query: operation.operationString,
|
|
516
|
-
variables: Object.keys(variables).length > 0 ? variables : void 0
|
|
517
|
-
})
|
|
518
|
-
);
|
|
519
|
-
for (const [name, value] of Object.entries(resolvedHeaders)) {
|
|
520
|
-
request = HttpClientRequest2.setHeader(request, name, value);
|
|
521
|
-
}
|
|
522
|
-
const response = yield* client.execute(request).pipe(
|
|
523
|
-
Effect3.mapError(
|
|
524
|
-
(err) => new GraphqlInvocationError({
|
|
525
|
-
message: "GraphQL request failed",
|
|
526
|
-
statusCode: Option3.none(),
|
|
527
|
-
cause: err
|
|
528
|
-
})
|
|
529
|
-
)
|
|
530
|
-
);
|
|
531
|
-
const status = response.status;
|
|
532
|
-
const contentType = response.headers["content-type"] ?? null;
|
|
533
|
-
const body = isJsonContentType(contentType) ? yield* response.json.pipe(Effect3.catch(() => response.text)) : yield* response.text;
|
|
534
|
-
const gqlBody = body;
|
|
535
|
-
const hasErrors = Array.isArray(gqlBody?.errors) && gqlBody.errors.length > 0;
|
|
536
|
-
yield* Effect3.annotateCurrentSpan({
|
|
537
|
-
"http.status_code": status,
|
|
538
|
-
"plugin.graphql.has_errors": hasErrors,
|
|
539
|
-
"plugin.graphql.error_count": hasErrors ? gqlBody.errors.length : 0
|
|
540
|
-
});
|
|
541
|
-
return InvocationResult.make({
|
|
542
|
-
status,
|
|
543
|
-
data: gqlBody?.data ?? null,
|
|
544
|
-
errors: hasErrors ? gqlBody.errors : null
|
|
545
|
-
});
|
|
546
|
-
});
|
|
547
|
-
var invokeWithLayer = (operation, args, endpoint, resolvedHeaders, resolvedQueryParams, httpClientLayer) => invoke(operation, args, endpoint, resolvedHeaders, resolvedQueryParams).pipe(
|
|
548
|
-
Effect3.provide(httpClientLayer),
|
|
549
|
-
Effect3.withSpan("plugin.graphql.invoke", {
|
|
550
|
-
attributes: {
|
|
551
|
-
"plugin.graphql.endpoint": endpointForTelemetry(endpoint),
|
|
552
|
-
"plugin.graphql.operation_kind": operation.kind,
|
|
553
|
-
"plugin.graphql.field_name": operation.fieldName
|
|
554
|
-
}
|
|
555
|
-
})
|
|
556
|
-
);
|
|
557
|
-
|
|
558
|
-
// src/sdk/store.ts
|
|
559
|
-
import { Effect as Effect4, Option as Option4, Predicate, Schema as Schema2 } from "effect";
|
|
560
|
-
import {
|
|
561
|
-
ConfiguredCredentialBinding
|
|
562
|
-
} from "@executor-js/sdk/core";
|
|
563
|
-
var graphqlSchema = {};
|
|
564
|
-
var SOURCE_COLLECTION = "source";
|
|
565
|
-
var OPERATION_COLLECTION = "operation";
|
|
566
|
-
var OperationBindingFromJsonString = Schema2.fromJsonString(OperationBinding);
|
|
567
|
-
var decodeOperationBindingFromJsonString = Schema2.decodeUnknownSync(
|
|
568
|
-
OperationBindingFromJsonString
|
|
569
|
-
);
|
|
570
|
-
var decodeOperationBinding = Schema2.decodeUnknownSync(OperationBinding);
|
|
571
|
-
var encodeBinding = Schema2.encodeSync(OperationBinding);
|
|
572
|
-
var decodeBinding = (value) => {
|
|
573
|
-
if (typeof value === "string") return decodeOperationBindingFromJsonString(value);
|
|
574
|
-
return decodeOperationBinding(value);
|
|
575
|
-
};
|
|
576
|
-
var toJsonRecord = (value) => value;
|
|
577
|
-
var OptionalNullableString = Schema2.optional(Schema2.NullOr(Schema2.String));
|
|
578
|
-
var ConfiguredCredentialBindingStorage = Schema2.Struct({
|
|
579
|
-
kind: Schema2.Literal("binding"),
|
|
580
|
-
slot: Schema2.String,
|
|
581
|
-
prefix: OptionalNullableString
|
|
582
|
-
});
|
|
583
|
-
var ConfiguredCredentialValueStorage = Schema2.Union([
|
|
584
|
-
Schema2.String,
|
|
585
|
-
ConfiguredCredentialBindingStorage
|
|
586
|
-
]);
|
|
587
|
-
var CredentialMapStorage = Schema2.Record(Schema2.String, ConfiguredCredentialValueStorage);
|
|
588
|
-
var SourceStorage = Schema2.Struct({
|
|
589
|
-
namespace: Schema2.String,
|
|
590
|
-
scope: Schema2.String,
|
|
591
|
-
name: Schema2.String,
|
|
592
|
-
endpoint: Schema2.String,
|
|
593
|
-
headers: Schema2.optional(CredentialMapStorage),
|
|
594
|
-
queryParams: Schema2.optional(CredentialMapStorage),
|
|
595
|
-
auth: GraphqlSourceAuth
|
|
596
|
-
});
|
|
597
|
-
var OperationStorage = Schema2.Struct({
|
|
598
|
-
toolId: Schema2.String,
|
|
599
|
-
sourceId: Schema2.String,
|
|
600
|
-
binding: Schema2.Unknown
|
|
601
|
-
});
|
|
602
|
-
var decodeSourceStorage = Schema2.decodeUnknownOption(SourceStorage);
|
|
603
|
-
var decodeOperationStorage = Schema2.decodeUnknownOption(OperationStorage);
|
|
604
|
-
var normalizeCredentialMap = (values) => {
|
|
605
|
-
if (!values) return {};
|
|
606
|
-
const normalized = {};
|
|
607
|
-
for (const [name, value] of Object.entries(values)) {
|
|
608
|
-
if (typeof value === "string") {
|
|
609
|
-
normalized[name] = value;
|
|
610
|
-
continue;
|
|
611
|
-
}
|
|
612
|
-
normalized[name] = value.prefix != null ? ConfiguredCredentialBinding.make({
|
|
613
|
-
kind: "binding",
|
|
614
|
-
slot: value.slot,
|
|
615
|
-
prefix: value.prefix
|
|
616
|
-
}) : ConfiguredCredentialBinding.make({
|
|
617
|
-
kind: "binding",
|
|
618
|
-
slot: value.slot
|
|
619
|
-
});
|
|
620
|
-
}
|
|
621
|
-
return normalized;
|
|
622
|
-
};
|
|
623
|
-
var sourceData = (source) => ({
|
|
624
|
-
namespace: source.namespace,
|
|
625
|
-
scope: source.scope,
|
|
626
|
-
name: source.name,
|
|
627
|
-
endpoint: source.endpoint,
|
|
628
|
-
headers: source.headers,
|
|
629
|
-
queryParams: source.queryParams,
|
|
630
|
-
auth: source.auth
|
|
631
|
-
});
|
|
632
|
-
var operationData = (operation) => ({
|
|
633
|
-
toolId: operation.toolId,
|
|
634
|
-
sourceId: operation.sourceId,
|
|
635
|
-
binding: toJsonRecord(encodeBinding(operation.binding))
|
|
636
|
-
});
|
|
637
|
-
var rowToSource = (row) => {
|
|
638
|
-
const decoded = decodeSourceStorage(row.data);
|
|
639
|
-
if (Option4.isNone(decoded)) return null;
|
|
640
|
-
const source = decoded.value;
|
|
641
|
-
return {
|
|
642
|
-
namespace: source.namespace,
|
|
643
|
-
scope: source.scope,
|
|
644
|
-
name: source.name,
|
|
645
|
-
endpoint: source.endpoint,
|
|
646
|
-
headers: normalizeCredentialMap(source.headers),
|
|
647
|
-
queryParams: normalizeCredentialMap(source.queryParams),
|
|
648
|
-
auth: source.auth
|
|
649
|
-
};
|
|
650
|
-
};
|
|
651
|
-
var rowToOperation = (row) => {
|
|
652
|
-
const decoded = decodeOperationStorage(row.data);
|
|
653
|
-
if (Option4.isNone(decoded)) return null;
|
|
654
|
-
const operation = decoded.value;
|
|
655
|
-
return {
|
|
656
|
-
toolId: operation.toolId,
|
|
657
|
-
sourceId: operation.sourceId,
|
|
658
|
-
binding: decodeBinding(operation.binding)
|
|
659
|
-
};
|
|
660
|
-
};
|
|
661
|
-
var makeDefaultGraphqlStore = ({
|
|
662
|
-
pluginStorage
|
|
663
|
-
}) => {
|
|
664
|
-
const listOperationRowsForSourceScope = (sourceId, scope) => pluginStorage.list({
|
|
665
|
-
collection: OPERATION_COLLECTION,
|
|
666
|
-
keyPrefix: `${sourceId}.`
|
|
667
|
-
}).pipe(
|
|
668
|
-
Effect4.map(
|
|
669
|
-
(rows) => rows.filter((row) => {
|
|
670
|
-
if (String(row.scopeId) !== scope) return false;
|
|
671
|
-
return rowToOperation(row)?.sourceId === sourceId;
|
|
672
|
-
})
|
|
673
|
-
)
|
|
674
|
-
);
|
|
675
|
-
const removeOperationsForSourceScope = (sourceId, scope) => Effect4.gen(function* () {
|
|
676
|
-
const rows = yield* listOperationRowsForSourceScope(sourceId, scope);
|
|
677
|
-
for (const row of rows) {
|
|
678
|
-
yield* pluginStorage.remove({
|
|
679
|
-
scope,
|
|
680
|
-
collection: OPERATION_COLLECTION,
|
|
681
|
-
key: row.key
|
|
682
|
-
});
|
|
683
|
-
}
|
|
684
|
-
});
|
|
685
|
-
const deleteSource = (namespace, scope) => Effect4.gen(function* () {
|
|
686
|
-
yield* removeOperationsForSourceScope(namespace, scope);
|
|
687
|
-
yield* pluginStorage.remove({
|
|
688
|
-
scope,
|
|
689
|
-
collection: SOURCE_COLLECTION,
|
|
690
|
-
key: namespace
|
|
691
|
-
});
|
|
692
|
-
});
|
|
693
|
-
return {
|
|
694
|
-
upsertSource: (input, operations) => Effect4.gen(function* () {
|
|
695
|
-
yield* deleteSource(input.namespace, input.scope);
|
|
696
|
-
yield* pluginStorage.put({
|
|
697
|
-
scope: input.scope,
|
|
698
|
-
collection: SOURCE_COLLECTION,
|
|
699
|
-
key: input.namespace,
|
|
700
|
-
data: sourceData(input)
|
|
701
|
-
});
|
|
702
|
-
for (const operation of operations) {
|
|
703
|
-
yield* pluginStorage.put({
|
|
704
|
-
scope: input.scope,
|
|
705
|
-
collection: OPERATION_COLLECTION,
|
|
706
|
-
key: operation.toolId,
|
|
707
|
-
data: operationData(operation)
|
|
708
|
-
});
|
|
709
|
-
}
|
|
710
|
-
}),
|
|
711
|
-
updateSourceMeta: (namespace, scope, patch) => Effect4.gen(function* () {
|
|
712
|
-
const existing = yield* pluginStorage.getAtScope({
|
|
713
|
-
scope,
|
|
714
|
-
collection: SOURCE_COLLECTION,
|
|
715
|
-
key: namespace
|
|
716
|
-
});
|
|
717
|
-
if (!existing) return;
|
|
718
|
-
const source = rowToSource(existing);
|
|
719
|
-
if (!source) return;
|
|
720
|
-
yield* pluginStorage.put({
|
|
721
|
-
scope,
|
|
722
|
-
collection: SOURCE_COLLECTION,
|
|
723
|
-
key: namespace,
|
|
724
|
-
data: sourceData({
|
|
725
|
-
...source,
|
|
726
|
-
name: patch.name ?? source.name,
|
|
727
|
-
endpoint: patch.endpoint ?? source.endpoint,
|
|
728
|
-
headers: patch.headers ?? source.headers,
|
|
729
|
-
queryParams: patch.queryParams ?? source.queryParams,
|
|
730
|
-
auth: patch.auth ?? source.auth
|
|
731
|
-
})
|
|
732
|
-
});
|
|
733
|
-
}),
|
|
734
|
-
getSource: (namespace, scope) => pluginStorage.getAtScope({ scope, collection: SOURCE_COLLECTION, key: namespace }).pipe(Effect4.map((row) => row ? rowToSource(row) : null)),
|
|
735
|
-
listSources: () => pluginStorage.list({ collection: SOURCE_COLLECTION }).pipe(Effect4.map((rows) => rows.map(rowToSource).filter(Predicate.isNotNull))),
|
|
736
|
-
getOperationByToolId: (toolId, scope) => pluginStorage.getAtScope({ scope, collection: OPERATION_COLLECTION, key: toolId }).pipe(Effect4.map((row) => row ? rowToOperation(row) : null)),
|
|
737
|
-
listOperationsBySource: (sourceId, scope) => listOperationRowsForSourceScope(sourceId, scope).pipe(
|
|
738
|
-
Effect4.map((rows) => rows.map(rowToOperation).filter(Predicate.isNotNull))
|
|
739
|
-
),
|
|
740
|
-
removeSource: (namespace, scope) => deleteSource(namespace, scope)
|
|
741
|
-
};
|
|
742
|
-
};
|
|
743
|
-
|
|
744
|
-
// src/sdk/plugin.ts
|
|
745
|
-
import { Effect as Effect5, Match as Match2, Option as Option5, Schema as Schema3 } from "effect";
|
|
746
|
-
import {
|
|
747
|
-
definePlugin,
|
|
748
|
-
tool,
|
|
749
|
-
defaultSourceInstallScopeId,
|
|
750
|
-
ScopeId,
|
|
751
|
-
SourceDetectionResult,
|
|
752
|
-
StorageError,
|
|
753
|
-
ToolResult,
|
|
754
|
-
authToolFailure
|
|
755
|
-
} from "@executor-js/sdk/core";
|
|
756
|
-
import {
|
|
757
|
-
compileHttpNamedCredentialMap,
|
|
758
|
-
OAuth2SourceConfig,
|
|
759
|
-
httpCredentialInputToBindingValue
|
|
760
|
-
} from "@executor-js/sdk/http-source";
|
|
761
|
-
import {
|
|
762
|
-
headersToConfigValues
|
|
763
|
-
} from "@executor-js/config";
|
|
764
|
-
var GraphqlErrorBody = Schema3.Struct({ message: Schema3.String });
|
|
765
|
-
var GraphqlErrorsBody = Schema3.Array(Schema3.Unknown);
|
|
766
|
-
var decodeGraphqlErrorBody = Schema3.decodeUnknownOption(GraphqlErrorBody);
|
|
767
|
-
var decodeGraphqlErrorsBody = Schema3.decodeUnknownOption(GraphqlErrorsBody);
|
|
768
|
-
var decodeGraphqlErrors = (errors) => Option5.getOrUndefined(decodeGraphqlErrorsBody(errors));
|
|
769
|
-
var extractGraphqlErrorMessage = (errors) => errors.map((error) => Option5.getOrUndefined(decodeGraphqlErrorBody(error))?.message).find((message) => message !== void 0 && message.length > 0);
|
|
770
|
-
var GraphqlInitialCredentialsInputSchema = Schema3.Struct({
|
|
771
|
-
scope: Schema3.String,
|
|
772
|
-
headers: Schema3.optional(Schema3.Record(Schema3.String, GraphqlCredentialInput)),
|
|
773
|
-
queryParams: Schema3.optional(Schema3.Record(Schema3.String, GraphqlCredentialInput)),
|
|
774
|
-
auth: Schema3.optional(GraphqlSourceAuthInput)
|
|
775
|
-
});
|
|
776
|
-
var StaticAddSourceInputSchema = Schema3.Struct({
|
|
777
|
-
endpoint: Schema3.String,
|
|
778
|
-
name: Schema3.String,
|
|
779
|
-
introspectionJson: Schema3.optional(Schema3.String),
|
|
780
|
-
namespace: Schema3.String,
|
|
781
|
-
headers: Schema3.optional(Schema3.Record(Schema3.String, GraphqlConfiguredValueInput)),
|
|
782
|
-
queryParams: Schema3.optional(Schema3.Record(Schema3.String, GraphqlConfiguredValueInput)),
|
|
783
|
-
oauth2: Schema3.optional(OAuth2SourceConfig),
|
|
784
|
-
credentials: Schema3.optional(GraphqlInitialCredentialsInputSchema)
|
|
785
|
-
});
|
|
786
|
-
var SourceConfigureInputSchema = Schema3.Struct({
|
|
787
|
-
name: Schema3.optional(Schema3.String),
|
|
788
|
-
endpoint: Schema3.optional(Schema3.String),
|
|
789
|
-
headers: Schema3.optional(Schema3.Record(Schema3.String, GraphqlCredentialInput)),
|
|
790
|
-
queryParams: Schema3.optional(Schema3.Record(Schema3.String, GraphqlCredentialInput)),
|
|
791
|
-
auth: Schema3.optional(GraphqlSourceAuthInput)
|
|
792
|
-
});
|
|
793
|
-
var StaticConfigureSourceInputSchema = Schema3.Struct({
|
|
794
|
-
source: Schema3.Struct({
|
|
795
|
-
id: Schema3.String,
|
|
796
|
-
scope: Schema3.String
|
|
797
|
-
}),
|
|
798
|
-
scope: Schema3.String,
|
|
799
|
-
...SourceConfigureInputSchema.fields
|
|
800
|
-
});
|
|
801
|
-
var StaticConfigureSourceOutputSchema = Schema3.Struct({
|
|
802
|
-
configured: Schema3.Boolean
|
|
803
|
-
});
|
|
804
|
-
var StaticGetSourceInputSchema = Schema3.Struct({
|
|
805
|
-
namespace: Schema3.String,
|
|
806
|
-
scope: Schema3.String
|
|
807
|
-
});
|
|
808
|
-
var StaticGetSourceOutputSchema = Schema3.Struct({
|
|
809
|
-
source: Schema3.NullOr(Schema3.Unknown)
|
|
810
|
-
});
|
|
811
|
-
var StaticAddSourceInputStandardSchema = Schema3.toStandardSchemaV1(
|
|
812
|
-
Schema3.toStandardJSONSchemaV1(StaticAddSourceInputSchema)
|
|
813
|
-
);
|
|
814
|
-
var StaticAddSourceOutputStandardSchema = Schema3.toStandardSchemaV1(
|
|
815
|
-
Schema3.toStandardJSONSchemaV1(
|
|
816
|
-
Schema3.Struct({
|
|
817
|
-
namespace: Schema3.String,
|
|
818
|
-
source: Schema3.Struct({
|
|
819
|
-
id: Schema3.String,
|
|
820
|
-
scope: Schema3.String
|
|
821
|
-
}),
|
|
822
|
-
toolCount: Schema3.Number
|
|
823
|
-
})
|
|
824
|
-
)
|
|
825
|
-
);
|
|
826
|
-
var StaticGetSourceInputStandardSchema = Schema3.toStandardSchemaV1(
|
|
827
|
-
Schema3.toStandardJSONSchemaV1(StaticGetSourceInputSchema)
|
|
828
|
-
);
|
|
829
|
-
var StaticGetSourceOutputStandardSchema = Schema3.toStandardSchemaV1(
|
|
830
|
-
Schema3.toStandardJSONSchemaV1(StaticGetSourceOutputSchema)
|
|
831
|
-
);
|
|
832
|
-
var StaticConfigureSourceInputStandardSchema = Schema3.toStandardSchemaV1(
|
|
833
|
-
Schema3.toStandardJSONSchemaV1(StaticConfigureSourceInputSchema)
|
|
834
|
-
);
|
|
835
|
-
var StaticConfigureSourceOutputStandardSchema = Schema3.toStandardSchemaV1(
|
|
836
|
-
Schema3.toStandardJSONSchemaV1(StaticConfigureSourceOutputSchema)
|
|
837
|
-
);
|
|
838
|
-
var graphqlToolFailure = (code, message, details) => ToolResult.fail({
|
|
839
|
-
code,
|
|
840
|
-
message,
|
|
841
|
-
...details === void 0 ? {} : { details }
|
|
842
|
-
});
|
|
843
|
-
var graphqlAuthToolFailure = (failure) => authToolFailure({
|
|
844
|
-
code: failure.code,
|
|
845
|
-
message: failure.message,
|
|
846
|
-
source: { id: failure.sourceId, scope: failure.sourceScope },
|
|
847
|
-
credential: {
|
|
848
|
-
kind: failure.credentialKind,
|
|
849
|
-
...failure.credentialLabel ? { label: failure.credentialLabel } : {},
|
|
850
|
-
...failure.slotKey ? { slotKey: failure.slotKey } : {},
|
|
851
|
-
...failure.secretId ? { secretId: failure.secretId } : {},
|
|
852
|
-
...failure.connectionId ? { connectionId: failure.connectionId } : {}
|
|
853
|
-
},
|
|
854
|
-
...failure.status !== void 0 ? { status: failure.status } : {},
|
|
855
|
-
...failure.details !== void 0 ? {
|
|
856
|
-
upstream: {
|
|
857
|
-
...failure.status !== void 0 ? { status: failure.status } : {},
|
|
858
|
-
details: failure.details
|
|
859
|
-
}
|
|
860
|
-
} : {},
|
|
861
|
-
recovery: { configureSourceTool: "executor.graphql.configureSource" }
|
|
862
|
-
});
|
|
863
|
-
var resolveStaticScopeInput = (ctx, value) => String(
|
|
864
|
-
ctx.scopes.find((scope) => scope.name === value || String(scope.id) === value)?.id ?? value
|
|
865
|
-
);
|
|
866
|
-
var urlMatchesToken = (url, token) => {
|
|
867
|
-
const re = new RegExp(`(?:^|[^a-z0-9])${token}(?:$|[^a-z0-9])`, "i");
|
|
868
|
-
return re.test(url.hostname) || re.test(url.pathname);
|
|
869
|
-
};
|
|
870
|
-
var namespaceFromEndpoint = (endpoint) => {
|
|
871
|
-
try {
|
|
872
|
-
const url = new URL(endpoint);
|
|
873
|
-
return url.hostname.replace(/[^a-z0-9]+/gi, "_").toLowerCase();
|
|
874
|
-
} catch {
|
|
875
|
-
return "graphql";
|
|
876
|
-
}
|
|
877
|
-
};
|
|
878
|
-
var formatTypeRef2 = (ref) => Match2.value(ref.kind).pipe(
|
|
879
|
-
Match2.when("NON_NULL", () => ref.ofType ? `${formatTypeRef2(ref.ofType)}!` : "Unknown!"),
|
|
880
|
-
Match2.when("LIST", () => ref.ofType ? `[${formatTypeRef2(ref.ofType)}]` : "[Unknown]"),
|
|
881
|
-
Match2.option,
|
|
882
|
-
Option5.getOrElse(() => ref.name ?? "Unknown")
|
|
883
|
-
);
|
|
884
|
-
var unwrapTypeName2 = (ref) => {
|
|
885
|
-
if (ref.name) return ref.name;
|
|
886
|
-
if (ref.ofType) return unwrapTypeName2(ref.ofType);
|
|
887
|
-
return "Unknown";
|
|
888
|
-
};
|
|
889
|
-
var buildSelectionSet = (ref, types, depth, seen) => {
|
|
890
|
-
if (depth > 2) return "";
|
|
891
|
-
const leafName = unwrapTypeName2(ref);
|
|
892
|
-
if (seen.has(leafName)) return "";
|
|
893
|
-
const objectType = types.get(leafName);
|
|
894
|
-
if (!objectType?.fields) return "";
|
|
895
|
-
const kind = objectType.kind;
|
|
896
|
-
if (kind === "SCALAR" || kind === "ENUM") return "";
|
|
897
|
-
seen.add(leafName);
|
|
898
|
-
const subFields = objectType.fields.filter((f) => !f.name.startsWith("__")).slice(0, 12).map((f) => {
|
|
899
|
-
const sub = buildSelectionSet(f.type, types, depth + 1, seen);
|
|
900
|
-
return sub ? `${f.name} ${sub}` : f.name;
|
|
901
|
-
});
|
|
902
|
-
seen.delete(leafName);
|
|
903
|
-
return subFields.length > 0 ? `{ ${subFields.join(" ")} }` : "";
|
|
904
|
-
};
|
|
905
|
-
var buildOperationStringForField = (kind, field, types) => {
|
|
906
|
-
const opType = kind === "query" ? "query" : "mutation";
|
|
907
|
-
const varDefs = field.args.map((arg) => {
|
|
908
|
-
const typeName = formatTypeRef2(arg.type);
|
|
909
|
-
return `$${arg.name}: ${typeName}`;
|
|
910
|
-
});
|
|
911
|
-
const argPasses = field.args.map((arg) => `${arg.name}: $${arg.name}`);
|
|
912
|
-
const selectionSet = buildSelectionSet(field.type, types, 0, /* @__PURE__ */ new Set());
|
|
913
|
-
const varDefsStr = varDefs.length > 0 ? `(${varDefs.join(", ")})` : "";
|
|
914
|
-
const argPassStr = argPasses.length > 0 ? `(${argPasses.join(", ")})` : "";
|
|
915
|
-
return `${opType}${varDefsStr} { ${field.name}${argPassStr}${selectionSet ? ` ${selectionSet}` : ""} }`;
|
|
916
|
-
};
|
|
917
|
-
var prepareOperations = (fields, introspection) => {
|
|
918
|
-
const typeMap = /* @__PURE__ */ new Map();
|
|
919
|
-
for (const t of introspection.__schema.types) {
|
|
920
|
-
typeMap.set(t.name, t);
|
|
921
|
-
}
|
|
922
|
-
const fieldMap = /* @__PURE__ */ new Map();
|
|
923
|
-
const schema = introspection.__schema;
|
|
924
|
-
for (const rootKind of ["query", "mutation"]) {
|
|
925
|
-
const typeName = rootKind === "query" ? schema.queryType?.name : schema.mutationType?.name;
|
|
926
|
-
if (!typeName) continue;
|
|
927
|
-
const rootType = typeMap.get(typeName);
|
|
928
|
-
if (!rootType?.fields) continue;
|
|
929
|
-
for (const f of rootType.fields) {
|
|
930
|
-
if (!f.name.startsWith("__")) {
|
|
931
|
-
fieldMap.set(`${rootKind}.${f.name}`, { kind: rootKind, field: f });
|
|
932
|
-
}
|
|
933
|
-
}
|
|
934
|
-
}
|
|
935
|
-
return fields.map((extracted) => {
|
|
936
|
-
const prefix = extracted.kind === "mutation" ? "mutation" : "query";
|
|
937
|
-
const toolPath = `${prefix}.${extracted.fieldName}`;
|
|
938
|
-
const description = Option5.getOrElse(
|
|
939
|
-
extracted.description,
|
|
940
|
-
() => `GraphQL ${extracted.kind}: ${extracted.fieldName} -> ${extracted.returnTypeName}`
|
|
941
|
-
);
|
|
942
|
-
const key = `${extracted.kind}.${extracted.fieldName}`;
|
|
943
|
-
const entry = fieldMap.get(key);
|
|
944
|
-
const operationString = entry ? buildOperationStringForField(entry.kind, entry.field, typeMap) : `${extracted.kind} { ${extracted.fieldName} }`;
|
|
945
|
-
const binding = OperationBinding.make({
|
|
946
|
-
kind: extracted.kind,
|
|
947
|
-
fieldName: extracted.fieldName,
|
|
948
|
-
operationString,
|
|
949
|
-
variableNames: extracted.arguments.map((a) => a.name)
|
|
950
|
-
});
|
|
951
|
-
return {
|
|
952
|
-
toolPath,
|
|
953
|
-
description,
|
|
954
|
-
inputSchema: Option5.getOrUndefined(extracted.inputSchema),
|
|
955
|
-
binding
|
|
956
|
-
};
|
|
957
|
-
});
|
|
958
|
-
};
|
|
959
|
-
var annotationsFor = (binding) => {
|
|
960
|
-
if (binding.kind === "mutation") {
|
|
961
|
-
return {
|
|
962
|
-
requiresApproval: true,
|
|
963
|
-
approvalDescription: `mutation ${binding.fieldName}`
|
|
964
|
-
};
|
|
965
|
-
}
|
|
966
|
-
return {};
|
|
967
|
-
};
|
|
968
|
-
var toGraphqlConfigEntry = (namespace, config) => {
|
|
969
|
-
const headers = {};
|
|
970
|
-
for (const [name, value] of Object.entries(config.headers ?? {})) {
|
|
971
|
-
if (typeof value === "string" || !("kind" in value)) {
|
|
972
|
-
headers[name] = value;
|
|
973
|
-
}
|
|
974
|
-
}
|
|
975
|
-
return {
|
|
976
|
-
kind: "graphql",
|
|
977
|
-
endpoint: config.endpoint,
|
|
978
|
-
introspectionJson: config.introspectionJson,
|
|
979
|
-
namespace,
|
|
980
|
-
headers: headersToConfigValues(Object.keys(headers).length > 0 ? headers : void 0)
|
|
981
|
-
};
|
|
982
|
-
};
|
|
983
|
-
var GRAPHQL_PLUGIN_ID = "graphql";
|
|
984
|
-
var scopeRanks = (ctx) => new Map(ctx.scopes.map((scope, index) => [String(scope.id), index]));
|
|
985
|
-
var scopeRank = (ranks, scopeId) => ranks.get(scopeId) ?? Infinity;
|
|
986
|
-
var resolveGraphqlSourceBinding = (ctx, sourceId, sourceScope, slot) => Effect5.gen(function* () {
|
|
987
|
-
const ranks = scopeRanks(ctx);
|
|
988
|
-
const sourceSourceRank = scopeRank(ranks, sourceScope);
|
|
989
|
-
if (sourceSourceRank === Infinity) return null;
|
|
990
|
-
const bindings = yield* ctx.credentialBindings.listForSource({
|
|
991
|
-
pluginId: GRAPHQL_PLUGIN_ID,
|
|
992
|
-
sourceId,
|
|
993
|
-
sourceScope: ScopeId.make(sourceScope)
|
|
994
|
-
});
|
|
995
|
-
const binding = bindings.filter(
|
|
996
|
-
(candidate) => candidate.slotKey === slot && scopeRank(ranks, candidate.scopeId) <= sourceSourceRank
|
|
997
|
-
).sort((a, b) => scopeRank(ranks, a.scopeId) - scopeRank(ranks, b.scopeId))[0];
|
|
998
|
-
return binding ?? null;
|
|
999
|
-
});
|
|
1000
|
-
var validateGraphqlBindingTarget = (ctx, input) => Effect5.gen(function* () {
|
|
1001
|
-
const ranks = scopeRanks(ctx);
|
|
1002
|
-
const sourceSourceRank = scopeRank(ranks, input.sourceScope);
|
|
1003
|
-
const targetRank = scopeRank(ranks, input.targetScope);
|
|
1004
|
-
const scopeList = `[${ctx.scopes.map((s) => s.id).join(", ")}]`;
|
|
1005
|
-
if (sourceSourceRank === Infinity) {
|
|
1006
|
-
return yield* new StorageError({
|
|
1007
|
-
message: `GraphQL source binding references source scope "${input.sourceScope}" which is not in the executor's scope stack ${scopeList}.`,
|
|
1008
|
-
cause: void 0
|
|
1009
|
-
});
|
|
1010
|
-
}
|
|
1011
|
-
if (targetRank === Infinity) {
|
|
1012
|
-
return yield* new StorageError({
|
|
1013
|
-
message: `GraphQL source binding targets scope "${input.targetScope}" which is not in the executor's scope stack ${scopeList}.`,
|
|
1014
|
-
cause: void 0
|
|
1015
|
-
});
|
|
1016
|
-
}
|
|
1017
|
-
if (targetRank > sourceSourceRank) {
|
|
1018
|
-
return yield* new StorageError({
|
|
1019
|
-
message: `GraphQL source bindings for "${input.sourceId}" cannot be written at outer scope "${input.targetScope}" because the base source lives at "${input.sourceScope}"`,
|
|
1020
|
-
cause: void 0
|
|
1021
|
-
});
|
|
1022
|
-
}
|
|
1023
|
-
});
|
|
1024
|
-
var canonicalizeCredentialMap = compileHttpNamedCredentialMap;
|
|
1025
|
-
var canonicalizeConfiguredValueMap = (values, slotForName) => {
|
|
1026
|
-
const next = {};
|
|
1027
|
-
for (const [name, value] of Object.entries(values ?? {})) {
|
|
1028
|
-
if (typeof value === "string") {
|
|
1029
|
-
next[name] = value;
|
|
1030
|
-
continue;
|
|
1031
|
-
}
|
|
1032
|
-
next[name] = {
|
|
1033
|
-
kind: "binding",
|
|
1034
|
-
slot: slotForName(name),
|
|
1035
|
-
prefix: value.prefix
|
|
1036
|
-
};
|
|
1037
|
-
}
|
|
1038
|
-
return next;
|
|
1039
|
-
};
|
|
1040
|
-
var resolveConfiguredValueMap = (values) => {
|
|
1041
|
-
if (!values) return void 0;
|
|
1042
|
-
const resolved = {};
|
|
1043
|
-
for (const [name, value] of Object.entries(values)) {
|
|
1044
|
-
if (typeof value === "string") resolved[name] = value;
|
|
1045
|
-
}
|
|
1046
|
-
return Object.keys(resolved).length > 0 ? resolved : void 0;
|
|
1047
|
-
};
|
|
1048
|
-
var authFromOAuth2Source = (oauth2) => oauth2 ? { kind: "oauth2", connectionSlot: oauth2.connectionSlot } : { kind: "none" };
|
|
1049
|
-
var canonicalizeAuth = (auth) => {
|
|
1050
|
-
if (!auth || "kind" in auth || !auth.oauth2) return { auth: { kind: "none" }, bindings: [] };
|
|
1051
|
-
const connection = auth.oauth2.connection;
|
|
1052
|
-
return {
|
|
1053
|
-
auth: { kind: "oauth2", connectionSlot: GRAPHQL_OAUTH_CONNECTION_SLOT },
|
|
1054
|
-
bindings: connection ? [
|
|
1055
|
-
{
|
|
1056
|
-
slot: GRAPHQL_OAUTH_CONNECTION_SLOT,
|
|
1057
|
-
value: httpCredentialInputToBindingValue(connection)
|
|
1058
|
-
}
|
|
1059
|
-
] : []
|
|
1060
|
-
};
|
|
1061
|
-
};
|
|
1062
|
-
var resolveInitialCredentialValueMap = (ctx, values, bindings, targetScope) => Effect5.gen(function* () {
|
|
1063
|
-
const bySlot = new Map(bindings.map((binding) => [binding.slot, binding.value]));
|
|
1064
|
-
const resolved = {};
|
|
1065
|
-
for (const [name, value] of Object.entries(values)) {
|
|
1066
|
-
if (typeof value === "string") {
|
|
1067
|
-
resolved[name] = value;
|
|
1068
|
-
continue;
|
|
1069
|
-
}
|
|
1070
|
-
const binding = bySlot.get(value.slot);
|
|
1071
|
-
if (binding?.kind === "secret") {
|
|
1072
|
-
const secret = yield* ctx.secrets.getAtScope(binding.secretId, binding.secretScopeId ?? ScopeId.make(targetScope)).pipe(
|
|
1073
|
-
Effect5.catchTag(
|
|
1074
|
-
"SecretOwnedByConnectionError",
|
|
1075
|
-
() => Effect5.fail(
|
|
1076
|
-
new GraphqlIntrospectionError({
|
|
1077
|
-
message: `Secret not found for ${name}`
|
|
1078
|
-
})
|
|
1079
|
-
)
|
|
1080
|
-
)
|
|
1081
|
-
);
|
|
1082
|
-
if (secret === null) {
|
|
1083
|
-
return yield* new GraphqlIntrospectionError({
|
|
1084
|
-
message: `Missing secret "${binding.secretId}" for ${name}`
|
|
1085
|
-
});
|
|
1086
|
-
}
|
|
1087
|
-
resolved[name] = value.prefix ? `${value.prefix}${secret}` : secret;
|
|
1088
|
-
continue;
|
|
1089
|
-
}
|
|
1090
|
-
if (binding?.kind === "text") {
|
|
1091
|
-
resolved[name] = value.prefix ? `${value.prefix}${binding.text}` : binding.text;
|
|
1092
|
-
}
|
|
1093
|
-
}
|
|
1094
|
-
return Object.keys(resolved).length > 0 ? resolved : void 0;
|
|
1095
|
-
});
|
|
1096
|
-
var resolveInitialOAuthHeaders = (ctx, bindings, targetScope) => Effect5.gen(function* () {
|
|
1097
|
-
const connection = bindings.find(
|
|
1098
|
-
(binding) => binding.slot === GRAPHQL_OAUTH_CONNECTION_SLOT && binding.value.kind === "connection"
|
|
1099
|
-
);
|
|
1100
|
-
if (!connection || connection.value.kind !== "connection") return void 0;
|
|
1101
|
-
const connectionId = connection.value.connectionId;
|
|
1102
|
-
const accessToken = yield* ctx.connections.accessTokenAtScope(connectionId, ScopeId.make(targetScope)).pipe(
|
|
1103
|
-
Effect5.mapError(
|
|
1104
|
-
({ message }) => new GraphqlIntrospectionError({
|
|
1105
|
-
message: `Failed to resolve OAuth connection "${connectionId}": ${message}`
|
|
1106
|
-
})
|
|
1107
|
-
)
|
|
1108
|
-
);
|
|
1109
|
-
return { Authorization: `Bearer ${accessToken}` };
|
|
1110
|
-
});
|
|
1111
|
-
var resolveGraphqlBindingValueMap = (ctx, values, params) => Effect5.gen(function* () {
|
|
1112
|
-
if (!values) return void 0;
|
|
1113
|
-
const resolved = {};
|
|
1114
|
-
for (const [name, value] of Object.entries(values)) {
|
|
1115
|
-
if (typeof value === "string") {
|
|
1116
|
-
resolved[name] = value;
|
|
1117
|
-
continue;
|
|
1118
|
-
}
|
|
1119
|
-
const binding = yield* resolveGraphqlSourceBinding(
|
|
1120
|
-
ctx,
|
|
1121
|
-
params.sourceId,
|
|
1122
|
-
params.sourceScope,
|
|
1123
|
-
value.slot
|
|
1124
|
-
);
|
|
1125
|
-
if (binding?.value.kind === "secret") {
|
|
1126
|
-
const secretBinding = binding.value;
|
|
1127
|
-
const secret = yield* ctx.secrets.getAtScope(secretBinding.secretId, binding.scopeId).pipe(
|
|
1128
|
-
Effect5.catchTag(
|
|
1129
|
-
"SecretOwnedByConnectionError",
|
|
1130
|
-
() => Effect5.fail(
|
|
1131
|
-
new GraphqlAuthRequiredError({
|
|
1132
|
-
code: "credential_secret_missing",
|
|
1133
|
-
sourceId: params.sourceId,
|
|
1134
|
-
sourceScope: params.sourceScope,
|
|
1135
|
-
credentialKind: "secret",
|
|
1136
|
-
credentialLabel: name,
|
|
1137
|
-
slotKey: value.slot,
|
|
1138
|
-
secretId: String(secretBinding.secretId),
|
|
1139
|
-
message: `Secret not found for ${params.missingLabel} "${name}"`
|
|
1140
|
-
})
|
|
1141
|
-
)
|
|
1142
|
-
)
|
|
1143
|
-
);
|
|
1144
|
-
if (secret === null) {
|
|
1145
|
-
return yield* new GraphqlAuthRequiredError({
|
|
1146
|
-
code: "credential_secret_missing",
|
|
1147
|
-
sourceId: params.sourceId,
|
|
1148
|
-
sourceScope: params.sourceScope,
|
|
1149
|
-
credentialKind: "secret",
|
|
1150
|
-
credentialLabel: name,
|
|
1151
|
-
slotKey: value.slot,
|
|
1152
|
-
secretId: String(secretBinding.secretId),
|
|
1153
|
-
message: `Missing secret "${secretBinding.secretId}" for ${params.missingLabel} "${name}"`
|
|
1154
|
-
});
|
|
1155
|
-
}
|
|
1156
|
-
resolved[name] = value.prefix ? `${value.prefix}${secret}` : secret;
|
|
1157
|
-
continue;
|
|
1158
|
-
}
|
|
1159
|
-
if (binding?.value.kind === "text") {
|
|
1160
|
-
resolved[name] = value.prefix ? `${value.prefix}${binding.value.text}` : binding.value.text;
|
|
1161
|
-
continue;
|
|
1162
|
-
}
|
|
1163
|
-
return yield* new GraphqlAuthRequiredError({
|
|
1164
|
-
code: "credential_binding_missing",
|
|
1165
|
-
sourceId: params.sourceId,
|
|
1166
|
-
sourceScope: params.sourceScope,
|
|
1167
|
-
credentialKind: "secret",
|
|
1168
|
-
credentialLabel: name,
|
|
1169
|
-
slotKey: value.slot,
|
|
1170
|
-
message: `Missing binding for ${params.missingLabel} "${name}"`
|
|
1171
|
-
});
|
|
1172
|
-
}
|
|
1173
|
-
return Object.keys(resolved).length > 0 ? resolved : void 0;
|
|
1174
|
-
});
|
|
1175
|
-
var resolveGraphqlStoredOAuthHeader = (ctx, sourceId, sourceScope, auth) => Effect5.gen(function* () {
|
|
1176
|
-
if (!auth || auth.kind === "none") return void 0;
|
|
1177
|
-
const binding = yield* resolveGraphqlSourceBinding(
|
|
1178
|
-
ctx,
|
|
1179
|
-
sourceId,
|
|
1180
|
-
sourceScope,
|
|
1181
|
-
auth.connectionSlot
|
|
1182
|
-
);
|
|
1183
|
-
if (binding?.value.kind !== "connection") {
|
|
1184
|
-
return yield* new GraphqlAuthRequiredError({
|
|
1185
|
-
code: "oauth_connection_missing",
|
|
1186
|
-
sourceId,
|
|
1187
|
-
sourceScope,
|
|
1188
|
-
credentialKind: "connection",
|
|
1189
|
-
credentialLabel: "OAuth sign-in",
|
|
1190
|
-
slotKey: auth.connectionSlot,
|
|
1191
|
-
message: `Missing OAuth connection binding for GraphQL source "${sourceId}"`
|
|
1192
|
-
});
|
|
1193
|
-
}
|
|
1194
|
-
const connectionId = binding.value.connectionId;
|
|
1195
|
-
const accessToken = yield* ctx.connections.accessTokenAtScope(connectionId, binding.scopeId).pipe(
|
|
1196
|
-
Effect5.catchTags({
|
|
1197
|
-
ConnectionReauthRequiredError: ({ message, connectionId: connectionId2 }) => Effect5.fail(
|
|
1198
|
-
new GraphqlAuthRequiredError({
|
|
1199
|
-
code: "oauth_reauth_required",
|
|
1200
|
-
sourceId,
|
|
1201
|
-
sourceScope,
|
|
1202
|
-
credentialKind: "oauth",
|
|
1203
|
-
credentialLabel: "OAuth sign-in",
|
|
1204
|
-
slotKey: auth.connectionSlot,
|
|
1205
|
-
connectionId: String(connectionId2),
|
|
1206
|
-
message: `OAuth connection "${connectionId2}" needs re-authentication: ${message}`
|
|
1207
|
-
})
|
|
1208
|
-
),
|
|
1209
|
-
ConnectionNotFoundError: ({ connectionId: connectionId2 }) => Effect5.fail(
|
|
1210
|
-
new GraphqlAuthRequiredError({
|
|
1211
|
-
code: "oauth_connection_missing",
|
|
1212
|
-
sourceId,
|
|
1213
|
-
sourceScope,
|
|
1214
|
-
credentialKind: "connection",
|
|
1215
|
-
credentialLabel: "OAuth sign-in",
|
|
1216
|
-
slotKey: auth.connectionSlot,
|
|
1217
|
-
connectionId: String(connectionId2),
|
|
1218
|
-
message: `OAuth connection "${connectionId2}" was not found for GraphQL source "${sourceId}"`
|
|
1219
|
-
})
|
|
1220
|
-
),
|
|
1221
|
-
ConnectionProviderNotRegisteredError: ({ provider }) => Effect5.fail(
|
|
1222
|
-
new GraphqlAuthRequiredError({
|
|
1223
|
-
code: "oauth_connection_failed",
|
|
1224
|
-
sourceId,
|
|
1225
|
-
sourceScope,
|
|
1226
|
-
credentialKind: "oauth",
|
|
1227
|
-
credentialLabel: "OAuth sign-in",
|
|
1228
|
-
slotKey: auth.connectionSlot,
|
|
1229
|
-
connectionId: String(connectionId),
|
|
1230
|
-
message: `OAuth provider "${provider}" is not registered`
|
|
1231
|
-
})
|
|
1232
|
-
),
|
|
1233
|
-
ConnectionRefreshNotSupportedError: ({ provider, connectionId: connectionId2 }) => Effect5.fail(
|
|
1234
|
-
new GraphqlAuthRequiredError({
|
|
1235
|
-
code: "oauth_connection_failed",
|
|
1236
|
-
sourceId,
|
|
1237
|
-
sourceScope,
|
|
1238
|
-
credentialKind: "oauth",
|
|
1239
|
-
credentialLabel: "OAuth sign-in",
|
|
1240
|
-
slotKey: auth.connectionSlot,
|
|
1241
|
-
connectionId: String(connectionId2),
|
|
1242
|
-
message: `OAuth provider "${provider}" cannot refresh connection "${connectionId2}"`
|
|
1243
|
-
})
|
|
1244
|
-
),
|
|
1245
|
-
ConnectionRefreshError: ({ message, connectionId: connectionId2 }) => Effect5.fail(
|
|
1246
|
-
new GraphqlAuthRequiredError({
|
|
1247
|
-
code: "oauth_connection_failed",
|
|
1248
|
-
sourceId,
|
|
1249
|
-
sourceScope,
|
|
1250
|
-
credentialKind: "oauth",
|
|
1251
|
-
credentialLabel: "OAuth sign-in",
|
|
1252
|
-
slotKey: auth.connectionSlot,
|
|
1253
|
-
connectionId: String(connectionId2),
|
|
1254
|
-
message: `OAuth connection "${connectionId2}" refresh failed: ${message}`
|
|
1255
|
-
})
|
|
1256
|
-
)
|
|
1257
|
-
})
|
|
1258
|
-
);
|
|
1259
|
-
return { Authorization: `Bearer ${accessToken}` };
|
|
1260
|
-
});
|
|
1261
|
-
var makeGraphqlExtension = (ctx, httpClientLayer, configFile) => {
|
|
1262
|
-
const addSourceInternal = (config) => ctx.transaction(
|
|
1263
|
-
Effect5.gen(function* () {
|
|
1264
|
-
const namespace = config.namespace;
|
|
1265
|
-
const canonicalHeaders = canonicalizeConfiguredValueMap(config.headers, graphqlHeaderSlot);
|
|
1266
|
-
const canonicalQueryParams = canonicalizeConfiguredValueMap(
|
|
1267
|
-
config.queryParams,
|
|
1268
|
-
graphqlQueryParamSlot
|
|
1269
|
-
);
|
|
1270
|
-
const initialHeaders = config.credentials?.headers !== void 0 ? canonicalizeCredentialMap(config.credentials.headers, graphqlHeaderSlot) : null;
|
|
1271
|
-
const initialQueryParams = config.credentials?.queryParams !== void 0 ? canonicalizeCredentialMap(config.credentials.queryParams, graphqlQueryParamSlot) : null;
|
|
1272
|
-
const initialAuth = config.credentials?.auth !== void 0 ? canonicalizeAuth(config.credentials.auth) : null;
|
|
1273
|
-
const auth = config.oauth2 ? authFromOAuth2Source(config.oauth2) : initialAuth?.auth ?? { kind: "none" };
|
|
1274
|
-
const initialBindings = [
|
|
1275
|
-
...initialHeaders?.bindings ?? [],
|
|
1276
|
-
...initialQueryParams?.bindings ?? [],
|
|
1277
|
-
...initialAuth?.bindings ?? []
|
|
1278
|
-
];
|
|
1279
|
-
const initialScope = config.credentials?.scope;
|
|
1280
|
-
if (initialScope && initialBindings.length > 0) {
|
|
1281
|
-
yield* validateGraphqlBindingTarget(ctx, {
|
|
1282
|
-
sourceId: namespace,
|
|
1283
|
-
sourceScope: config.scope,
|
|
1284
|
-
targetScope: initialScope
|
|
1285
|
-
});
|
|
1286
|
-
}
|
|
1287
|
-
let introspectionResult;
|
|
1288
|
-
if (config.introspectionJson) {
|
|
1289
|
-
introspectionResult = yield* parseIntrospectionJson(config.introspectionJson);
|
|
1290
|
-
} else {
|
|
1291
|
-
const resolvedInitialHeaders = initialHeaders && initialScope ? yield* resolveInitialCredentialValueMap(
|
|
1292
|
-
ctx,
|
|
1293
|
-
canonicalHeaders,
|
|
1294
|
-
initialHeaders.bindings,
|
|
1295
|
-
initialScope
|
|
1296
|
-
) : void 0;
|
|
1297
|
-
const resolvedOAuthHeaders = initialAuth && initialScope ? yield* resolveInitialOAuthHeaders(ctx, initialAuth.bindings, initialScope) : void 0;
|
|
1298
|
-
const resolvedHeaders = {
|
|
1299
|
-
...resolveConfiguredValueMap(config.headers) ?? {},
|
|
1300
|
-
...resolvedInitialHeaders ?? {},
|
|
1301
|
-
...resolvedOAuthHeaders ?? {}
|
|
1302
|
-
};
|
|
1303
|
-
const resolvedInitialQueryParams = initialQueryParams && initialScope ? yield* resolveInitialCredentialValueMap(
|
|
1304
|
-
ctx,
|
|
1305
|
-
canonicalQueryParams,
|
|
1306
|
-
initialQueryParams.bindings,
|
|
1307
|
-
initialScope
|
|
1308
|
-
) : void 0;
|
|
1309
|
-
const resolvedQueryParams = {
|
|
1310
|
-
...resolveConfiguredValueMap(config.queryParams) ?? {},
|
|
1311
|
-
...resolvedInitialQueryParams ?? {}
|
|
1312
|
-
};
|
|
1313
|
-
introspectionResult = yield* introspect(
|
|
1314
|
-
config.endpoint,
|
|
1315
|
-
Object.keys(resolvedHeaders).length > 0 ? resolvedHeaders : void 0,
|
|
1316
|
-
Object.keys(resolvedQueryParams).length > 0 ? resolvedQueryParams : void 0
|
|
1317
|
-
).pipe(Effect5.provide(httpClientLayer));
|
|
1318
|
-
}
|
|
1319
|
-
const { result, definitions } = yield* extract(introspectionResult);
|
|
1320
|
-
const prepared = prepareOperations(result.fields, introspectionResult);
|
|
1321
|
-
const displayName = config.name?.trim() || namespace;
|
|
1322
|
-
const storedSource = {
|
|
1323
|
-
namespace,
|
|
1324
|
-
scope: config.scope,
|
|
1325
|
-
name: displayName,
|
|
1326
|
-
endpoint: config.endpoint,
|
|
1327
|
-
headers: canonicalHeaders,
|
|
1328
|
-
queryParams: canonicalQueryParams,
|
|
1329
|
-
auth
|
|
1330
|
-
};
|
|
1331
|
-
const storedOps = prepared.map((p) => ({
|
|
1332
|
-
toolId: `${namespace}.${p.toolPath}`,
|
|
1333
|
-
sourceId: namespace,
|
|
1334
|
-
binding: p.binding
|
|
1335
|
-
}));
|
|
1336
|
-
yield* ctx.storage.upsertSource(storedSource, storedOps);
|
|
1337
|
-
yield* ctx.core.sources.register({
|
|
1338
|
-
id: namespace,
|
|
1339
|
-
scope: config.scope,
|
|
1340
|
-
kind: "graphql",
|
|
1341
|
-
name: displayName,
|
|
1342
|
-
url: config.endpoint,
|
|
1343
|
-
canRemove: true,
|
|
1344
|
-
canRefresh: false,
|
|
1345
|
-
canEdit: true,
|
|
1346
|
-
tools: prepared.map((p) => ({
|
|
1347
|
-
name: p.toolPath,
|
|
1348
|
-
description: p.description,
|
|
1349
|
-
inputSchema: p.inputSchema
|
|
1350
|
-
}))
|
|
1351
|
-
});
|
|
1352
|
-
if (initialScope && initialBindings.length > 0) {
|
|
1353
|
-
yield* ctx.credentialBindings.replaceForSource({
|
|
1354
|
-
targetScope: ScopeId.make(initialScope),
|
|
1355
|
-
pluginId: GRAPHQL_PLUGIN_ID,
|
|
1356
|
-
sourceId: namespace,
|
|
1357
|
-
sourceScope: ScopeId.make(config.scope),
|
|
1358
|
-
slotPrefixes: [
|
|
1359
|
-
...config.credentials?.headers !== void 0 ? ["header:"] : [],
|
|
1360
|
-
...config.credentials?.queryParams !== void 0 ? ["query_param:"] : [],
|
|
1361
|
-
...config.credentials?.auth !== void 0 ? ["auth:"] : []
|
|
1362
|
-
],
|
|
1363
|
-
bindings: initialBindings.map((binding) => ({
|
|
1364
|
-
slotKey: binding.slot,
|
|
1365
|
-
value: binding.value
|
|
1366
|
-
}))
|
|
1367
|
-
});
|
|
1368
|
-
}
|
|
1369
|
-
if (Object.keys(definitions).length > 0) {
|
|
1370
|
-
yield* ctx.core.definitions.register({
|
|
1371
|
-
sourceId: namespace,
|
|
1372
|
-
scope: config.scope,
|
|
1373
|
-
definitions
|
|
1374
|
-
});
|
|
1375
|
-
}
|
|
1376
|
-
return { toolCount: prepared.length, namespace };
|
|
1377
|
-
})
|
|
1378
|
-
);
|
|
1379
|
-
const configureSource = (namespace, scope, targetScope, input) => Effect5.gen(function* () {
|
|
1380
|
-
const existing = yield* ctx.storage.getSource(namespace, scope);
|
|
1381
|
-
if (!existing) return;
|
|
1382
|
-
const canonicalHeaders = input.headers !== void 0 ? canonicalizeCredentialMap(input.headers, graphqlHeaderSlot) : null;
|
|
1383
|
-
const canonicalQueryParams = input.queryParams !== void 0 ? canonicalizeCredentialMap(input.queryParams, graphqlQueryParamSlot) : null;
|
|
1384
|
-
const canonicalAuth = input.auth !== void 0 ? canonicalizeAuth(input.auth) : null;
|
|
1385
|
-
const directBindings = [
|
|
1386
|
-
...canonicalHeaders?.bindings ?? [],
|
|
1387
|
-
...canonicalQueryParams?.bindings ?? [],
|
|
1388
|
-
...canonicalAuth?.bindings ?? []
|
|
1389
|
-
];
|
|
1390
|
-
if (directBindings.length > 0) {
|
|
1391
|
-
yield* validateGraphqlBindingTarget(ctx, {
|
|
1392
|
-
sourceId: namespace,
|
|
1393
|
-
sourceScope: scope,
|
|
1394
|
-
targetScope
|
|
1395
|
-
});
|
|
1396
|
-
}
|
|
1397
|
-
const affectedPrefixes = [
|
|
1398
|
-
...input.headers !== void 0 ? ["header:"] : [],
|
|
1399
|
-
...input.queryParams !== void 0 ? ["query_param:"] : [],
|
|
1400
|
-
...input.auth !== void 0 ? ["auth:"] : []
|
|
1401
|
-
];
|
|
1402
|
-
yield* ctx.transaction(
|
|
1403
|
-
Effect5.gen(function* () {
|
|
1404
|
-
yield* ctx.storage.updateSourceMeta(namespace, scope, {
|
|
1405
|
-
name: input.name?.trim() || void 0,
|
|
1406
|
-
endpoint: input.endpoint,
|
|
1407
|
-
headers: canonicalHeaders?.values,
|
|
1408
|
-
queryParams: canonicalQueryParams?.values,
|
|
1409
|
-
auth: canonicalAuth?.auth
|
|
1410
|
-
});
|
|
1411
|
-
if (affectedPrefixes.length > 0 || directBindings.length > 0) {
|
|
1412
|
-
yield* ctx.credentialBindings.replaceForSource({
|
|
1413
|
-
targetScope: ScopeId.make(targetScope),
|
|
1414
|
-
pluginId: GRAPHQL_PLUGIN_ID,
|
|
1415
|
-
sourceId: namespace,
|
|
1416
|
-
sourceScope: ScopeId.make(scope),
|
|
1417
|
-
slotPrefixes: affectedPrefixes,
|
|
1418
|
-
bindings: directBindings.map((binding) => ({
|
|
1419
|
-
slotKey: binding.slot,
|
|
1420
|
-
value: binding.value
|
|
1421
|
-
}))
|
|
1422
|
-
});
|
|
1423
|
-
}
|
|
1424
|
-
})
|
|
1425
|
-
);
|
|
1426
|
-
});
|
|
1427
|
-
return {
|
|
1428
|
-
addSource: (config) => addSourceInternal(config).pipe(
|
|
1429
|
-
Effect5.tap(
|
|
1430
|
-
(result) => configFile ? configFile.upsertSource(toGraphqlConfigEntry(result.namespace, config)) : Effect5.void
|
|
1431
|
-
)
|
|
1432
|
-
),
|
|
1433
|
-
removeSource: (namespace, scope) => Effect5.gen(function* () {
|
|
1434
|
-
yield* ctx.transaction(
|
|
1435
|
-
Effect5.gen(function* () {
|
|
1436
|
-
yield* ctx.credentialBindings.removeForSource({
|
|
1437
|
-
pluginId: GRAPHQL_PLUGIN_ID,
|
|
1438
|
-
sourceId: namespace,
|
|
1439
|
-
sourceScope: ScopeId.make(scope)
|
|
1440
|
-
});
|
|
1441
|
-
yield* ctx.storage.removeSource(namespace, scope);
|
|
1442
|
-
yield* ctx.core.sources.unregister({ id: namespace, targetScope: scope });
|
|
1443
|
-
})
|
|
1444
|
-
);
|
|
1445
|
-
if (configFile) {
|
|
1446
|
-
yield* configFile.removeSource(namespace);
|
|
1447
|
-
}
|
|
1448
|
-
}),
|
|
1449
|
-
getSource: (namespace, scope) => ctx.storage.getSource(namespace, scope),
|
|
1450
|
-
configureSource,
|
|
1451
|
-
configure: (source, input) => configureSource(source.id, source.scope, input.scope, input)
|
|
1452
|
-
};
|
|
1453
|
-
};
|
|
1454
|
-
var graphqlPlugin = definePlugin((options) => {
|
|
1455
|
-
return {
|
|
1456
|
-
id: "graphql",
|
|
1457
|
-
packageName: "@executor-js/plugin-graphql",
|
|
1458
|
-
sourcePresets: graphqlPresets,
|
|
1459
|
-
schema: graphqlSchema,
|
|
1460
|
-
storage: (deps) => makeDefaultGraphqlStore(deps),
|
|
1461
|
-
extension: (ctx) => makeGraphqlExtension(
|
|
1462
|
-
ctx,
|
|
1463
|
-
options?.httpClientLayer ?? ctx.httpClientLayer,
|
|
1464
|
-
options?.configFile
|
|
1465
|
-
),
|
|
1466
|
-
sourceConfigure: {
|
|
1467
|
-
type: "graphql",
|
|
1468
|
-
schema: SourceConfigureInputSchema,
|
|
1469
|
-
configure: ({ ctx, sourceId, sourceScope, targetScope, config }) => makeGraphqlExtension(
|
|
1470
|
-
ctx,
|
|
1471
|
-
options?.httpClientLayer ?? ctx.httpClientLayer,
|
|
1472
|
-
options?.configFile
|
|
1473
|
-
).configureSource(
|
|
1474
|
-
sourceId,
|
|
1475
|
-
sourceScope,
|
|
1476
|
-
targetScope,
|
|
1477
|
-
config
|
|
1478
|
-
)
|
|
1479
|
-
},
|
|
1480
|
-
staticSources: (self) => [
|
|
1481
|
-
{
|
|
1482
|
-
id: "graphql",
|
|
1483
|
-
kind: "executor",
|
|
1484
|
-
name: "GraphQL",
|
|
1485
|
-
tools: [
|
|
1486
|
-
tool({
|
|
1487
|
-
name: "getSource",
|
|
1488
|
-
description: "Inspect an existing GraphQL source, including endpoint, auth mode, configured headers/query params, and credential slots. Use this before repairing an existing source with `graphql.configureSource`, `secrets.create`, or `oauth.start`.",
|
|
1489
|
-
inputSchema: StaticGetSourceInputStandardSchema,
|
|
1490
|
-
outputSchema: StaticGetSourceOutputStandardSchema,
|
|
1491
|
-
execute: (input, { ctx }) => Effect5.map(
|
|
1492
|
-
self.getSource(input.namespace, resolveStaticScopeInput(ctx, input.scope)),
|
|
1493
|
-
(source) => ToolResult.ok({ source })
|
|
1494
|
-
)
|
|
1495
|
-
}),
|
|
1496
|
-
tool({
|
|
1497
|
-
name: "addSource",
|
|
1498
|
-
description: "Add a GraphQL endpoint and register its operations as tools. Executor chooses the source install scope (local scope locally, organization scope in cloud) and returns it as `source`. For API keys or bearer tokens, first call `executor.coreTools.secrets.create` at the user's chosen credential scope and pass secret refs through `credentials`. For OAuth, start the browser flow with `executor.coreTools.oauth.start` using `credentialScope` set to the user's chosen personal or organization credential scope, verify completion with `connections.list`, then bind the connection through `credentials` or `graphql.configureSource`.",
|
|
1499
|
-
annotations: {
|
|
1500
|
-
requiresApproval: true,
|
|
1501
|
-
approvalDescription: "Add a GraphQL source"
|
|
1502
|
-
},
|
|
1503
|
-
inputSchema: StaticAddSourceInputStandardSchema,
|
|
1504
|
-
outputSchema: StaticAddSourceOutputStandardSchema,
|
|
1505
|
-
execute: (input, { ctx }) => {
|
|
1506
|
-
const sourceScope = defaultSourceInstallScopeId(ctx.scopes);
|
|
1507
|
-
if (sourceScope === null) {
|
|
1508
|
-
return Effect5.succeed(
|
|
1509
|
-
graphqlToolFailure(
|
|
1510
|
-
"source_scope_unavailable",
|
|
1511
|
-
"Cannot add a GraphQL source because this executor has no source install scope."
|
|
1512
|
-
)
|
|
1513
|
-
);
|
|
1514
|
-
}
|
|
1515
|
-
return self.addSource({ ...input, scope: sourceScope }).pipe(
|
|
1516
|
-
Effect5.map(
|
|
1517
|
-
(result) => ToolResult.ok({
|
|
1518
|
-
...result,
|
|
1519
|
-
source: { id: result.namespace, scope: sourceScope }
|
|
1520
|
-
})
|
|
1521
|
-
),
|
|
1522
|
-
Effect5.catchTags({
|
|
1523
|
-
GraphqlIntrospectionError: ({ message }) => Effect5.succeed(graphqlToolFailure("graphql_introspection_failed", message)),
|
|
1524
|
-
GraphqlExtractionError: ({ message }) => Effect5.succeed(graphqlToolFailure("graphql_extraction_failed", message))
|
|
1525
|
-
})
|
|
1526
|
-
);
|
|
1527
|
-
}
|
|
1528
|
-
}),
|
|
1529
|
-
tool({
|
|
1530
|
-
name: "configureSource",
|
|
1531
|
-
description: 'Configure an existing GraphQL source with concrete fields. Use `source` returned by `graphql.addSource` or `sources.list`. The top-level `scope` is the credential target scope for bindings; in cloud, choose the user or organization credential scope deliberately. Pass secret refs as `{kind:"secret", secretId}` and OAuth connections as `{kind:"connection", connectionId}`.',
|
|
1532
|
-
annotations: {
|
|
1533
|
-
requiresApproval: true,
|
|
1534
|
-
approvalDescription: "Configure a GraphQL source"
|
|
1535
|
-
},
|
|
1536
|
-
inputSchema: StaticConfigureSourceInputStandardSchema,
|
|
1537
|
-
outputSchema: StaticConfigureSourceOutputStandardSchema,
|
|
1538
|
-
execute: (input, { ctx }) => {
|
|
1539
|
-
const { source, ...config } = input;
|
|
1540
|
-
const sourceScope = resolveStaticScopeInput(ctx, source.scope);
|
|
1541
|
-
const targetScope = resolveStaticScopeInput(ctx, config.scope);
|
|
1542
|
-
return Effect5.as(
|
|
1543
|
-
self.configure(
|
|
1544
|
-
{ id: source.id, scope: sourceScope },
|
|
1545
|
-
{ ...config, scope: targetScope }
|
|
1546
|
-
),
|
|
1547
|
-
ToolResult.ok({ configured: true })
|
|
1548
|
-
);
|
|
1549
|
-
}
|
|
1550
|
-
})
|
|
1551
|
-
]
|
|
1552
|
-
}
|
|
1553
|
-
],
|
|
1554
|
-
invokeTool: ({ ctx, toolRow, args }) => Effect5.gen(function* () {
|
|
1555
|
-
const httpClientLayer = options?.httpClientLayer ?? ctx.httpClientLayer;
|
|
1556
|
-
const toolScope = toolRow.scope_id;
|
|
1557
|
-
const op = yield* ctx.storage.getOperationByToolId(toolRow.id, toolScope);
|
|
1558
|
-
if (!op) {
|
|
1559
|
-
return yield* new GraphqlInvocationError({
|
|
1560
|
-
message: `No GraphQL operation found for tool "${toolRow.id}"`,
|
|
1561
|
-
statusCode: Option5.none()
|
|
1562
|
-
});
|
|
1563
|
-
}
|
|
1564
|
-
const source = yield* ctx.storage.getSource(op.sourceId, toolScope);
|
|
1565
|
-
if (!source) {
|
|
1566
|
-
return yield* new GraphqlInvocationError({
|
|
1567
|
-
message: `No GraphQL source found for "${op.sourceId}"`,
|
|
1568
|
-
statusCode: Option5.none()
|
|
1569
|
-
});
|
|
1570
|
-
}
|
|
1571
|
-
const resolvedHeaders = (yield* resolveGraphqlBindingValueMap(ctx, source.headers, {
|
|
1572
|
-
sourceId: source.namespace,
|
|
1573
|
-
sourceScope: source.scope,
|
|
1574
|
-
missingLabel: "header"
|
|
1575
|
-
})) ?? {};
|
|
1576
|
-
const resolvedQueryParams = (yield* resolveGraphqlBindingValueMap(ctx, source.queryParams, {
|
|
1577
|
-
sourceId: source.namespace,
|
|
1578
|
-
sourceScope: source.scope,
|
|
1579
|
-
missingLabel: "query parameter"
|
|
1580
|
-
})) ?? {};
|
|
1581
|
-
const oauthHeader = yield* resolveGraphqlStoredOAuthHeader(
|
|
1582
|
-
ctx,
|
|
1583
|
-
source.namespace,
|
|
1584
|
-
source.scope,
|
|
1585
|
-
source.auth
|
|
1586
|
-
);
|
|
1587
|
-
Object.assign(resolvedHeaders, oauthHeader ?? {});
|
|
1588
|
-
const result = yield* invokeWithLayer(
|
|
1589
|
-
op.binding,
|
|
1590
|
-
args ?? {},
|
|
1591
|
-
source.endpoint,
|
|
1592
|
-
resolvedHeaders,
|
|
1593
|
-
resolvedQueryParams,
|
|
1594
|
-
httpClientLayer
|
|
1595
|
-
);
|
|
1596
|
-
const errors = decodeGraphqlErrors(result.errors);
|
|
1597
|
-
if (errors !== void 0 && errors.length > 0) {
|
|
1598
|
-
const firstMessage = extractGraphqlErrorMessage(errors);
|
|
1599
|
-
return ToolResult.fail({
|
|
1600
|
-
code: "graphql_errors",
|
|
1601
|
-
message: firstMessage !== void 0 ? firstMessage : "GraphQL request returned errors",
|
|
1602
|
-
details: { errors }
|
|
1603
|
-
});
|
|
1604
|
-
}
|
|
1605
|
-
if (result.status < 200 || result.status >= 300) {
|
|
1606
|
-
if (result.status === 401 || result.status === 403) {
|
|
1607
|
-
return authToolFailure({
|
|
1608
|
-
code: "credential_rejected",
|
|
1609
|
-
status: result.status,
|
|
1610
|
-
message: `Upstream rejected credentials for GraphQL source "${source.namespace}" with HTTP ${result.status}. Re-authenticate or update the source credentials before retrying this tool.`,
|
|
1611
|
-
source: { id: source.namespace, scope: source.scope },
|
|
1612
|
-
credential: { kind: "upstream", label: "Upstream authorization" },
|
|
1613
|
-
upstream: {
|
|
1614
|
-
status: result.status,
|
|
1615
|
-
details: {
|
|
1616
|
-
data: result.data,
|
|
1617
|
-
errors: result.errors
|
|
1618
|
-
}
|
|
1619
|
-
},
|
|
1620
|
-
recovery: { configureSourceTool: "executor.graphql.configureSource" }
|
|
1621
|
-
});
|
|
1622
|
-
}
|
|
1623
|
-
return ToolResult.fail({
|
|
1624
|
-
code: "graphql_http_error",
|
|
1625
|
-
status: result.status,
|
|
1626
|
-
message: `GraphQL request failed with HTTP ${result.status}`,
|
|
1627
|
-
details: {
|
|
1628
|
-
status: result.status,
|
|
1629
|
-
data: result.data,
|
|
1630
|
-
errors: result.errors
|
|
1631
|
-
}
|
|
1632
|
-
});
|
|
1633
|
-
}
|
|
1634
|
-
return ToolResult.ok(result.data);
|
|
1635
|
-
}).pipe(
|
|
1636
|
-
Effect5.catchTag(
|
|
1637
|
-
"GraphqlAuthRequiredError",
|
|
1638
|
-
(error) => Effect5.succeed(graphqlAuthToolFailure(error))
|
|
1639
|
-
)
|
|
1640
|
-
),
|
|
1641
|
-
resolveAnnotations: ({ ctx, sourceId, toolRows }) => Effect5.gen(function* () {
|
|
1642
|
-
const scopes = /* @__PURE__ */ new Set();
|
|
1643
|
-
for (const row of toolRows) {
|
|
1644
|
-
scopes.add(row.scope_id);
|
|
1645
|
-
}
|
|
1646
|
-
const entries = yield* Effect5.forEach(
|
|
1647
|
-
[...scopes],
|
|
1648
|
-
(scope) => Effect5.gen(function* () {
|
|
1649
|
-
const ops = yield* ctx.storage.listOperationsBySource(sourceId, scope);
|
|
1650
|
-
const byId = /* @__PURE__ */ new Map();
|
|
1651
|
-
for (const op of ops) byId.set(op.toolId, op.binding);
|
|
1652
|
-
return [scope, byId];
|
|
1653
|
-
}),
|
|
1654
|
-
{ concurrency: "unbounded" }
|
|
1655
|
-
);
|
|
1656
|
-
const byScope = new Map(entries);
|
|
1657
|
-
const out = {};
|
|
1658
|
-
for (const row of toolRows) {
|
|
1659
|
-
const binding = byScope.get(row.scope_id)?.get(row.id);
|
|
1660
|
-
if (binding) out[row.id] = annotationsFor(binding);
|
|
1661
|
-
}
|
|
1662
|
-
return out;
|
|
1663
|
-
}),
|
|
1664
|
-
removeSource: ({ ctx, sourceId, scope }) => Effect5.gen(function* () {
|
|
1665
|
-
yield* ctx.transaction(
|
|
1666
|
-
Effect5.gen(function* () {
|
|
1667
|
-
yield* ctx.credentialBindings.removeForSource({
|
|
1668
|
-
pluginId: GRAPHQL_PLUGIN_ID,
|
|
1669
|
-
sourceId,
|
|
1670
|
-
sourceScope: ScopeId.make(scope)
|
|
1671
|
-
});
|
|
1672
|
-
yield* ctx.storage.removeSource(sourceId, scope);
|
|
1673
|
-
})
|
|
1674
|
-
);
|
|
1675
|
-
if (options?.configFile) {
|
|
1676
|
-
yield* options.configFile.removeSource(sourceId);
|
|
1677
|
-
}
|
|
1678
|
-
}),
|
|
1679
|
-
usagesForSecret: () => Effect5.succeed([]),
|
|
1680
|
-
usagesForConnection: () => Effect5.succeed([]),
|
|
1681
|
-
detect: ({ ctx, url }) => Effect5.gen(function* () {
|
|
1682
|
-
const httpClientLayer = options?.httpClientLayer ?? ctx.httpClientLayer;
|
|
1683
|
-
const trimmed = url.trim();
|
|
1684
|
-
if (!trimmed) return null;
|
|
1685
|
-
const parsed = yield* Effect5.try({
|
|
1686
|
-
try: () => new URL(trimmed),
|
|
1687
|
-
catch: (cause) => cause
|
|
1688
|
-
}).pipe(Effect5.option);
|
|
1689
|
-
if (Option5.isNone(parsed)) return null;
|
|
1690
|
-
const ok = yield* introspect(trimmed).pipe(
|
|
1691
|
-
Effect5.provide(httpClientLayer),
|
|
1692
|
-
Effect5.map(() => true),
|
|
1693
|
-
Effect5.catch(() => Effect5.succeed(false))
|
|
1694
|
-
);
|
|
1695
|
-
const name = namespaceFromEndpoint(trimmed);
|
|
1696
|
-
if (ok) {
|
|
1697
|
-
return SourceDetectionResult.make({
|
|
1698
|
-
kind: "graphql",
|
|
1699
|
-
confidence: "high",
|
|
1700
|
-
endpoint: trimmed,
|
|
1701
|
-
name,
|
|
1702
|
-
namespace: name
|
|
1703
|
-
});
|
|
1704
|
-
}
|
|
1705
|
-
if (urlMatchesToken(parsed.value, "graphql")) {
|
|
1706
|
-
return SourceDetectionResult.make({
|
|
1707
|
-
kind: "graphql",
|
|
1708
|
-
confidence: "low",
|
|
1709
|
-
endpoint: trimmed,
|
|
1710
|
-
name,
|
|
1711
|
-
namespace: name
|
|
1712
|
-
});
|
|
1713
|
-
}
|
|
1714
|
-
return null;
|
|
1715
|
-
})
|
|
1716
|
-
};
|
|
1717
|
-
});
|
|
1718
|
-
|
|
1719
|
-
export {
|
|
1720
|
-
introspect,
|
|
1721
|
-
parseIntrospectionJson,
|
|
1722
|
-
extract,
|
|
1723
|
-
resolveHeaders,
|
|
1724
|
-
invoke,
|
|
1725
|
-
invokeWithLayer,
|
|
1726
|
-
graphqlSchema,
|
|
1727
|
-
makeDefaultGraphqlStore,
|
|
1728
|
-
graphqlPlugin
|
|
1729
|
-
};
|
|
1730
|
-
//# sourceMappingURL=chunk-2252RTCE.js.map
|