@executor-js/plugin-graphql 1.4.29 → 1.4.31
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-3Z3DB4KQ.js → AddGraphqlSource-PBMKSY7Y.js} +29 -18
- package/dist/AddGraphqlSource-PBMKSY7Y.js.map +1 -0
- package/dist/{EditGraphqlSource-F37RPNKV.js → EditGraphqlSource-AFR4RQHY.js} +107 -91
- package/dist/EditGraphqlSource-AFR4RQHY.js.map +1 -0
- package/dist/{GraphqlSourceSummary-6EYBXVD2.js → GraphqlSourceSummary-MY4AW37M.js} +4 -4
- package/dist/GraphqlSourceSummary-MY4AW37M.js.map +1 -0
- package/dist/api/group.d.ts +71 -232
- package/dist/api/handlers.d.ts +5 -45
- package/dist/api/index.d.ts +76 -404
- package/dist/{chunk-PO2TPM5B.js → chunk-7S2FM3ZF.js} +578 -613
- package/dist/chunk-7S2FM3ZF.js.map +1 -0
- package/dist/chunk-D6E4WAYW.js +51 -0
- package/dist/chunk-D6E4WAYW.js.map +1 -0
- package/dist/{chunk-445ZPXHU.js → chunk-H422YIM4.js} +15 -34
- package/dist/chunk-H422YIM4.js.map +1 -0
- package/dist/{chunk-EW4Y3KEX.js → chunk-OYUIHBWZ.js} +23 -80
- package/dist/chunk-OYUIHBWZ.js.map +1 -0
- package/dist/client.js +7 -47
- package/dist/client.js.map +1 -1
- package/dist/core.js +3 -8
- package/dist/index.js +3 -2
- package/dist/react/atoms.d.ts +146 -186
- package/dist/react/client.d.ts +70 -231
- package/dist/sdk/index.d.ts +2 -2
- package/dist/sdk/introspect.d.ts +151 -151
- package/dist/sdk/invoke.d.ts +5 -5
- package/dist/sdk/plugin.d.ts +74 -228
- package/dist/sdk/presets.d.ts +1 -0
- package/dist/sdk/store.d.ts +3 -135
- package/dist/sdk/types.d.ts +31 -66
- package/dist/testing/index.d.ts +20 -2
- package/dist/testing.js +77 -29
- package/dist/testing.js.map +1 -1
- package/package.json +3 -3
- package/dist/AddGraphqlSource-3Z3DB4KQ.js.map +0 -1
- package/dist/EditGraphqlSource-F37RPNKV.js.map +0 -1
- package/dist/GraphqlSourceSummary-6EYBXVD2.js.map +0 -1
- package/dist/chunk-445ZPXHU.js.map +0 -1
- package/dist/chunk-EW4Y3KEX.js.map +0 -1
- package/dist/chunk-PO2TPM5B.js.map +0 -1
|
@@ -1,22 +1,26 @@
|
|
|
1
|
+
import {
|
|
2
|
+
graphqlPresets
|
|
3
|
+
} from "./chunk-D6E4WAYW.js";
|
|
1
4
|
import {
|
|
2
5
|
ExtractedField,
|
|
3
6
|
ExtractionResult,
|
|
4
7
|
GRAPHQL_OAUTH_CONNECTION_SLOT,
|
|
5
8
|
GraphqlArgument,
|
|
9
|
+
GraphqlConfiguredValueInput,
|
|
6
10
|
GraphqlCredentialInput,
|
|
7
11
|
GraphqlExtractionError,
|
|
8
12
|
GraphqlIntrospectionError,
|
|
9
13
|
GraphqlInvocationError,
|
|
14
|
+
GraphqlSourceAuth,
|
|
10
15
|
GraphqlSourceAuthInput,
|
|
11
|
-
GraphqlSourceBindingRef,
|
|
12
16
|
InvocationResult,
|
|
13
17
|
OperationBinding,
|
|
14
18
|
graphqlHeaderSlot,
|
|
15
19
|
graphqlQueryParamSlot
|
|
16
|
-
} from "./chunk-
|
|
20
|
+
} from "./chunk-H422YIM4.js";
|
|
17
21
|
|
|
18
22
|
// src/sdk/introspect.ts
|
|
19
|
-
import { Effect, Schema } from "effect";
|
|
23
|
+
import { Effect, Option, Schema } from "effect";
|
|
20
24
|
import { HttpClient, HttpClientRequest } from "effect/unstable/http";
|
|
21
25
|
var INTROSPECTION_QUERY = `
|
|
22
26
|
query IntrospectionQuery {
|
|
@@ -90,32 +94,32 @@ var INTROSPECTION_QUERY = `
|
|
|
90
94
|
var IntrospectionTypeRefLeaf = Schema.Struct({
|
|
91
95
|
kind: Schema.String,
|
|
92
96
|
name: Schema.NullOr(Schema.String),
|
|
93
|
-
ofType: Schema.Null
|
|
97
|
+
ofType: Schema.optional(Schema.Null)
|
|
94
98
|
});
|
|
95
99
|
var IntrospectionTypeRef5 = Schema.Struct({
|
|
96
100
|
kind: Schema.String,
|
|
97
101
|
name: Schema.NullOr(Schema.String),
|
|
98
|
-
ofType: Schema.NullOr(IntrospectionTypeRefLeaf)
|
|
102
|
+
ofType: Schema.optional(Schema.NullOr(IntrospectionTypeRefLeaf))
|
|
99
103
|
});
|
|
100
104
|
var IntrospectionTypeRef4 = Schema.Struct({
|
|
101
105
|
kind: Schema.String,
|
|
102
106
|
name: Schema.NullOr(Schema.String),
|
|
103
|
-
ofType: Schema.NullOr(IntrospectionTypeRef5)
|
|
107
|
+
ofType: Schema.optional(Schema.NullOr(IntrospectionTypeRef5))
|
|
104
108
|
});
|
|
105
109
|
var IntrospectionTypeRef3 = Schema.Struct({
|
|
106
110
|
kind: Schema.String,
|
|
107
111
|
name: Schema.NullOr(Schema.String),
|
|
108
|
-
ofType: Schema.NullOr(IntrospectionTypeRef4)
|
|
112
|
+
ofType: Schema.optional(Schema.NullOr(IntrospectionTypeRef4))
|
|
109
113
|
});
|
|
110
114
|
var IntrospectionTypeRef2 = Schema.Struct({
|
|
111
115
|
kind: Schema.String,
|
|
112
116
|
name: Schema.NullOr(Schema.String),
|
|
113
|
-
ofType: Schema.NullOr(IntrospectionTypeRef3)
|
|
117
|
+
ofType: Schema.optional(Schema.NullOr(IntrospectionTypeRef3))
|
|
114
118
|
});
|
|
115
119
|
var IntrospectionTypeRefSchema = Schema.Struct({
|
|
116
120
|
kind: Schema.String,
|
|
117
121
|
name: Schema.NullOr(Schema.String),
|
|
118
|
-
ofType: Schema.NullOr(IntrospectionTypeRef2)
|
|
122
|
+
ofType: Schema.optional(Schema.NullOr(IntrospectionTypeRef2))
|
|
119
123
|
});
|
|
120
124
|
var IntrospectionInputValueSchema = Schema.Struct({
|
|
121
125
|
name: Schema.String,
|
|
@@ -155,10 +159,51 @@ var IntrospectionResponseSchema = Schema.Struct({
|
|
|
155
159
|
data: Schema.optional(IntrospectionResultSchema),
|
|
156
160
|
errors: Schema.optional(Schema.Array(Schema.Unknown))
|
|
157
161
|
});
|
|
162
|
+
var UpstreamErrorResponseSchema = Schema.Struct({
|
|
163
|
+
message: Schema.optional(Schema.String),
|
|
164
|
+
errors: Schema.optional(
|
|
165
|
+
Schema.Array(
|
|
166
|
+
Schema.Struct({
|
|
167
|
+
message: Schema.optional(Schema.String)
|
|
168
|
+
})
|
|
169
|
+
)
|
|
170
|
+
)
|
|
171
|
+
});
|
|
158
172
|
var IntrospectionJsonSchema = Schema.Union([
|
|
159
173
|
Schema.Struct({ data: IntrospectionResultSchema }),
|
|
160
174
|
IntrospectionResultSchema
|
|
161
175
|
]);
|
|
176
|
+
var JsonTextSchema = Schema.fromJsonString(Schema.Unknown);
|
|
177
|
+
var decodeUpstreamErrorResponse = Schema.decodeUnknownOption(UpstreamErrorResponseSchema);
|
|
178
|
+
var firstUpstreamErrorMessage = (value) => {
|
|
179
|
+
const decoded = decodeUpstreamErrorResponse(value);
|
|
180
|
+
return Option.match(decoded, {
|
|
181
|
+
onNone: () => null,
|
|
182
|
+
onSome: (response) => {
|
|
183
|
+
if (response.message) return response.message;
|
|
184
|
+
for (const entry of response.errors ?? []) {
|
|
185
|
+
const message = entry.message;
|
|
186
|
+
if (message) return message;
|
|
187
|
+
}
|
|
188
|
+
return null;
|
|
189
|
+
}
|
|
190
|
+
});
|
|
191
|
+
};
|
|
192
|
+
var redactUpstreamBody = (body) => body.replaceAll(
|
|
193
|
+
/("(?:access_token|refresh_token|id_token|client_secret|token|authorization)"\s*:\s*")[^"]*(")/gi,
|
|
194
|
+
"$1[redacted]$2"
|
|
195
|
+
).replaceAll(
|
|
196
|
+
/((?:access_token|refresh_token|id_token|client_secret|token|authorization)=)[^&\s]*/gi,
|
|
197
|
+
"$1[redacted]"
|
|
198
|
+
).replaceAll(
|
|
199
|
+
/((?:authorization|access-token|refresh-token|id-token|client-secret|token)\s*:\s*)(?:bearer\s+)?[^\s,;]+/gi,
|
|
200
|
+
"$1[redacted]"
|
|
201
|
+
);
|
|
202
|
+
var upstreamTextMessage = (body) => {
|
|
203
|
+
const text = redactUpstreamBody(body.replaceAll(/\s+/g, " ").trim());
|
|
204
|
+
if (text.length === 0) return null;
|
|
205
|
+
return text.length > 500 ? `${text.slice(0, 500)}...` : text;
|
|
206
|
+
};
|
|
162
207
|
var introspect = Effect.fn("GraphQL.introspect")(function* (endpoint, headers, queryParams) {
|
|
163
208
|
const client = yield* HttpClient.HttpClient;
|
|
164
209
|
const requestEndpoint = queryParams && Object.keys(queryParams).length > 0 ? (() => {
|
|
@@ -170,6 +215,8 @@ var introspect = Effect.fn("GraphQL.introspect")(function* (endpoint, headers, q
|
|
|
170
215
|
})() : endpoint;
|
|
171
216
|
let request = HttpClientRequest.post(requestEndpoint).pipe(
|
|
172
217
|
HttpClientRequest.setHeader("Content-Type", "application/json"),
|
|
218
|
+
HttpClientRequest.setHeader("Accept", "application/json"),
|
|
219
|
+
HttpClientRequest.setHeader("User-Agent", "executor-graphql"),
|
|
173
220
|
HttpClientRequest.bodyJsonUnsafe({
|
|
174
221
|
query: INTROSPECTION_QUERY
|
|
175
222
|
})
|
|
@@ -188,8 +235,15 @@ var introspect = Effect.fn("GraphQL.introspect")(function* (endpoint, headers, q
|
|
|
188
235
|
)
|
|
189
236
|
);
|
|
190
237
|
if (response.status !== 200) {
|
|
238
|
+
const responseText = yield* response.text.pipe(Effect.catch(() => Effect.succeed("")));
|
|
239
|
+
const raw2 = responseText ? yield* Schema.decodeUnknownEffect(JsonTextSchema)(responseText).pipe(
|
|
240
|
+
Effect.catch(() => Effect.succeed(null))
|
|
241
|
+
) : null;
|
|
242
|
+
const upstreamMessage = upstreamTextMessage(
|
|
243
|
+
(raw2 === null ? null : firstUpstreamErrorMessage(raw2)) ?? responseText
|
|
244
|
+
);
|
|
191
245
|
return yield* new GraphqlIntrospectionError({
|
|
192
|
-
message: `Introspection failed with status ${response.status}`
|
|
246
|
+
message: upstreamMessage ? `Introspection failed with status ${response.status}: ${upstreamMessage}` : `Introspection failed with status ${response.status}`
|
|
193
247
|
});
|
|
194
248
|
}
|
|
195
249
|
const raw = yield* response.json.pipe(
|
|
@@ -208,8 +262,9 @@ var introspect = Effect.fn("GraphQL.introspect")(function* (endpoint, headers, q
|
|
|
208
262
|
)
|
|
209
263
|
);
|
|
210
264
|
if (json.errors && Array.isArray(json.errors) && json.errors.length > 0) {
|
|
265
|
+
const upstreamMessage = firstUpstreamErrorMessage(json);
|
|
211
266
|
return yield* new GraphqlIntrospectionError({
|
|
212
|
-
message: `Introspection returned ${json.errors.length} error(s)`
|
|
267
|
+
message: upstreamMessage ? `Introspection returned ${json.errors.length} error(s): ${upstreamMessage}` : `Introspection returned ${json.errors.length} error(s)`
|
|
213
268
|
});
|
|
214
269
|
}
|
|
215
270
|
if (!json.data?.__schema) {
|
|
@@ -229,7 +284,7 @@ var parseIntrospectionJson = (text) => Schema.decodeUnknownEffect(Schema.fromJso
|
|
|
229
284
|
);
|
|
230
285
|
|
|
231
286
|
// src/sdk/extract.ts
|
|
232
|
-
import { Effect as Effect2, Match, Option } from "effect";
|
|
287
|
+
import { Effect as Effect2, Match, Option as Option2 } from "effect";
|
|
233
288
|
var unwrapTypeName = (ref) => {
|
|
234
289
|
if (ref.name) return ref.name;
|
|
235
290
|
if (ref.ofType) return unwrapTypeName(ref.ofType);
|
|
@@ -296,7 +351,7 @@ var typeRefToJsonSchema = (ref, types) => Match.value(ref.kind).pipe(
|
|
|
296
351
|
() => ({ type: "object" })
|
|
297
352
|
),
|
|
298
353
|
Match.option,
|
|
299
|
-
|
|
354
|
+
Option2.getOrElse(() => ({}))
|
|
300
355
|
);
|
|
301
356
|
var scalarToJsonSchema = (name) => Match.value(name).pipe(
|
|
302
357
|
Match.whenOr("String", "ID", () => ({ type: "string" })),
|
|
@@ -304,7 +359,7 @@ var scalarToJsonSchema = (name) => Match.value(name).pipe(
|
|
|
304
359
|
Match.when("Float", () => ({ type: "number" })),
|
|
305
360
|
Match.when("Boolean", () => ({ type: "boolean" })),
|
|
306
361
|
Match.option,
|
|
307
|
-
|
|
362
|
+
Option2.getOrElse(
|
|
308
363
|
() => ({ type: "string", description: `Custom scalar: ${name}` })
|
|
309
364
|
)
|
|
310
365
|
);
|
|
@@ -333,7 +388,7 @@ var formatTypeRef = (ref) => Match.value(ref.kind).pipe(
|
|
|
333
388
|
Match.when("NON_NULL", () => ref.ofType ? `${formatTypeRef(ref.ofType)}!` : "Unknown!"),
|
|
334
389
|
Match.when("LIST", () => ref.ofType ? `[${formatTypeRef(ref.ofType)}]` : "[Unknown]"),
|
|
335
390
|
Match.option,
|
|
336
|
-
|
|
391
|
+
Option2.getOrElse(() => ref.name ?? "Unknown")
|
|
337
392
|
);
|
|
338
393
|
var extractFields = (_schema, kind, typeName, types) => {
|
|
339
394
|
if (!typeName) return [];
|
|
@@ -345,16 +400,16 @@ var extractFields = (_schema, kind, typeName, types) => {
|
|
|
345
400
|
name: arg.name,
|
|
346
401
|
typeName: formatTypeRef(arg.type),
|
|
347
402
|
required: isNonNull(arg.type),
|
|
348
|
-
description: arg.description ?
|
|
403
|
+
description: arg.description ? Option2.some(arg.description) : Option2.none()
|
|
349
404
|
})
|
|
350
405
|
);
|
|
351
406
|
const inputSchema = buildInputSchema(field.args, types);
|
|
352
407
|
return ExtractedField.make({
|
|
353
408
|
fieldName: field.name,
|
|
354
409
|
kind,
|
|
355
|
-
description: field.description ?
|
|
410
|
+
description: field.description ? Option2.some(field.description) : Option2.none(),
|
|
356
411
|
arguments: args,
|
|
357
|
-
inputSchema: inputSchema ?
|
|
412
|
+
inputSchema: inputSchema ? Option2.some(inputSchema) : Option2.none(),
|
|
358
413
|
returnTypeName: unwrapTypeName(field.type)
|
|
359
414
|
});
|
|
360
415
|
});
|
|
@@ -371,7 +426,7 @@ var extract = (introspection) => Effect2.try({
|
|
|
371
426
|
const mutationFields = extractFields(schema, "mutation", schema.mutationType?.name, typeMap);
|
|
372
427
|
return {
|
|
373
428
|
result: ExtractionResult.make({
|
|
374
|
-
schemaName:
|
|
429
|
+
schemaName: Option2.none(),
|
|
375
430
|
fields: [...queryFields, ...mutationFields]
|
|
376
431
|
}),
|
|
377
432
|
definitions
|
|
@@ -383,7 +438,7 @@ var extract = (introspection) => Effect2.try({
|
|
|
383
438
|
});
|
|
384
439
|
|
|
385
440
|
// src/sdk/invoke.ts
|
|
386
|
-
import { Effect as Effect3, Option as
|
|
441
|
+
import { Effect as Effect3, Option as Option3 } from "effect";
|
|
387
442
|
import { HttpClient as HttpClient2, HttpClientRequest as HttpClientRequest2 } from "effect/unstable/http";
|
|
388
443
|
import { resolveSecretBackedMap } from "@executor-js/sdk/core";
|
|
389
444
|
var resolveHeaders = (headers, secrets) => {
|
|
@@ -398,7 +453,7 @@ var resolveHeaders = (headers, secrets) => {
|
|
|
398
453
|
missing: "drop",
|
|
399
454
|
onMissing: (name) => new GraphqlInvocationError({
|
|
400
455
|
message: `Missing secret for header "${name}"`,
|
|
401
|
-
statusCode:
|
|
456
|
+
statusCode: Option3.none()
|
|
402
457
|
})
|
|
403
458
|
}).pipe(
|
|
404
459
|
Effect3.catch(() => Effect3.succeed(void 0)),
|
|
@@ -467,7 +522,7 @@ var invoke = Effect3.fn("GraphQL.invoke")(function* (operation, args, endpoint,
|
|
|
467
522
|
Effect3.mapError(
|
|
468
523
|
(err) => new GraphqlInvocationError({
|
|
469
524
|
message: "GraphQL request failed",
|
|
470
|
-
statusCode:
|
|
525
|
+
statusCode: Option3.none(),
|
|
471
526
|
cause: err
|
|
472
527
|
})
|
|
473
528
|
)
|
|
@@ -500,378 +555,291 @@ var invokeWithLayer = (operation, args, endpoint, resolvedHeaders, resolvedQuery
|
|
|
500
555
|
);
|
|
501
556
|
|
|
502
557
|
// src/sdk/store.ts
|
|
503
|
-
import { Effect as Effect4, Schema as Schema2 } from "effect";
|
|
558
|
+
import { Effect as Effect4, Option as Option4, Predicate, Schema as Schema2 } from "effect";
|
|
504
559
|
import {
|
|
505
|
-
ConfiguredCredentialBinding
|
|
506
|
-
defineSchema
|
|
560
|
+
ConfiguredCredentialBinding
|
|
507
561
|
} from "@executor-js/sdk/core";
|
|
508
|
-
var graphqlSchema =
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
id: { type: "string", required: true },
|
|
512
|
-
scope_id: { type: "string", required: true, index: true },
|
|
513
|
-
name: { type: "string", required: true },
|
|
514
|
-
endpoint: { type: "string", required: true },
|
|
515
|
-
auth_kind: {
|
|
516
|
-
type: ["none", "oauth2"],
|
|
517
|
-
required: true,
|
|
518
|
-
defaultValue: "none"
|
|
519
|
-
},
|
|
520
|
-
auth_connection_slot: {
|
|
521
|
-
type: "string",
|
|
522
|
-
required: false
|
|
523
|
-
}
|
|
524
|
-
}
|
|
525
|
-
},
|
|
526
|
-
graphql_source_header: {
|
|
527
|
-
fields: {
|
|
528
|
-
id: { type: "string", required: true },
|
|
529
|
-
scope_id: { type: "string", required: true, index: true },
|
|
530
|
-
source_id: { type: "string", required: true, index: true },
|
|
531
|
-
name: { type: "string", required: true },
|
|
532
|
-
kind: {
|
|
533
|
-
type: ["text", "binding"],
|
|
534
|
-
required: true
|
|
535
|
-
},
|
|
536
|
-
text_value: { type: "string", required: false },
|
|
537
|
-
slot_key: { type: "string", required: false },
|
|
538
|
-
prefix: { type: "string", required: false }
|
|
539
|
-
}
|
|
540
|
-
},
|
|
541
|
-
graphql_source_query_param: {
|
|
542
|
-
fields: {
|
|
543
|
-
id: { type: "string", required: true },
|
|
544
|
-
scope_id: { type: "string", required: true, index: true },
|
|
545
|
-
source_id: { type: "string", required: true, index: true },
|
|
546
|
-
name: { type: "string", required: true },
|
|
547
|
-
kind: {
|
|
548
|
-
type: ["text", "binding"],
|
|
549
|
-
required: true
|
|
550
|
-
},
|
|
551
|
-
text_value: { type: "string", required: false },
|
|
552
|
-
slot_key: { type: "string", required: false },
|
|
553
|
-
prefix: { type: "string", required: false }
|
|
554
|
-
}
|
|
555
|
-
},
|
|
556
|
-
graphql_operation: {
|
|
557
|
-
fields: {
|
|
558
|
-
id: { type: "string", required: true },
|
|
559
|
-
scope_id: { type: "string", required: true, index: true },
|
|
560
|
-
source_id: { type: "string", required: true, index: true },
|
|
561
|
-
binding: { type: "json", required: true }
|
|
562
|
-
}
|
|
563
|
-
}
|
|
564
|
-
});
|
|
562
|
+
var graphqlSchema = {};
|
|
563
|
+
var SOURCE_COLLECTION = "source";
|
|
564
|
+
var OPERATION_COLLECTION = "operation";
|
|
565
565
|
var OperationBindingFromJsonString = Schema2.fromJsonString(OperationBinding);
|
|
566
566
|
var decodeOperationBindingFromJsonString = Schema2.decodeUnknownSync(
|
|
567
567
|
OperationBindingFromJsonString
|
|
568
568
|
);
|
|
569
569
|
var decodeOperationBinding = Schema2.decodeUnknownSync(OperationBinding);
|
|
570
|
+
var encodeBinding = Schema2.encodeSync(OperationBinding);
|
|
570
571
|
var decodeBinding = (value) => {
|
|
571
|
-
if (typeof value === "string")
|
|
572
|
-
return decodeOperationBindingFromJsonString(value);
|
|
573
|
-
}
|
|
572
|
+
if (typeof value === "string") return decodeOperationBindingFromJsonString(value);
|
|
574
573
|
return decodeOperationBinding(value);
|
|
575
574
|
};
|
|
576
|
-
var encodeBinding = Schema2.encodeSync(OperationBinding);
|
|
577
575
|
var toJsonRecord = (value) => value;
|
|
578
|
-
var
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
auth_kind: Schema2.Literals(["none", "oauth2"]),
|
|
584
|
-
auth_connection_slot: Schema2.NullOr(Schema2.String).pipe(Schema2.optionalKey)
|
|
576
|
+
var OptionalNullableString = Schema2.optional(Schema2.NullOr(Schema2.String));
|
|
577
|
+
var ConfiguredCredentialBindingStorage = Schema2.Struct({
|
|
578
|
+
kind: Schema2.Literal("binding"),
|
|
579
|
+
slot: Schema2.String,
|
|
580
|
+
prefix: OptionalNullableString
|
|
585
581
|
});
|
|
586
|
-
var
|
|
582
|
+
var ConfiguredCredentialValueStorage = Schema2.Union([
|
|
583
|
+
Schema2.String,
|
|
584
|
+
ConfiguredCredentialBindingStorage
|
|
585
|
+
]);
|
|
586
|
+
var CredentialMapStorage = Schema2.Record(Schema2.String, ConfiguredCredentialValueStorage);
|
|
587
|
+
var SourceStorage = Schema2.Struct({
|
|
588
|
+
namespace: Schema2.String,
|
|
589
|
+
scope: Schema2.String,
|
|
587
590
|
name: Schema2.String,
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
591
|
+
endpoint: Schema2.String,
|
|
592
|
+
headers: Schema2.optional(CredentialMapStorage),
|
|
593
|
+
queryParams: Schema2.optional(CredentialMapStorage),
|
|
594
|
+
auth: GraphqlSourceAuth
|
|
592
595
|
});
|
|
593
|
-
var
|
|
594
|
-
|
|
595
|
-
|
|
596
|
+
var OperationStorage = Schema2.Struct({
|
|
597
|
+
toolId: Schema2.String,
|
|
598
|
+
sourceId: Schema2.String,
|
|
596
599
|
binding: Schema2.Unknown
|
|
597
600
|
});
|
|
598
|
-
var
|
|
599
|
-
var
|
|
600
|
-
var
|
|
601
|
-
|
|
602
|
-
const
|
|
603
|
-
for (const
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
out[name] = typeof row.prefix === "string" ? ConfiguredCredentialBinding.make({
|
|
608
|
-
kind: "binding",
|
|
609
|
-
slot: row.slot_key,
|
|
610
|
-
prefix: row.prefix
|
|
611
|
-
}) : ConfiguredCredentialBinding.make({
|
|
612
|
-
kind: "binding",
|
|
613
|
-
slot: row.slot_key
|
|
614
|
-
});
|
|
615
|
-
} else if (row.kind === "text" && typeof row.text_value === "string") {
|
|
616
|
-
out[name] = row.text_value;
|
|
601
|
+
var decodeSourceStorage = Schema2.decodeUnknownOption(SourceStorage);
|
|
602
|
+
var decodeOperationStorage = Schema2.decodeUnknownOption(OperationStorage);
|
|
603
|
+
var normalizeCredentialMap = (values) => {
|
|
604
|
+
if (!values) return {};
|
|
605
|
+
const normalized = {};
|
|
606
|
+
for (const [name, value] of Object.entries(values)) {
|
|
607
|
+
if (typeof value === "string") {
|
|
608
|
+
normalized[name] = value;
|
|
609
|
+
continue;
|
|
617
610
|
}
|
|
611
|
+
normalized[name] = value.prefix != null ? ConfiguredCredentialBinding.make({
|
|
612
|
+
kind: "binding",
|
|
613
|
+
slot: value.slot,
|
|
614
|
+
prefix: value.prefix
|
|
615
|
+
}) : ConfiguredCredentialBinding.make({
|
|
616
|
+
kind: "binding",
|
|
617
|
+
slot: value.slot
|
|
618
|
+
});
|
|
618
619
|
}
|
|
619
|
-
return
|
|
620
|
+
return normalized;
|
|
620
621
|
};
|
|
621
|
-
var
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
622
|
+
var sourceData = (source) => ({
|
|
623
|
+
namespace: source.namespace,
|
|
624
|
+
scope: source.scope,
|
|
625
|
+
name: source.name,
|
|
626
|
+
endpoint: source.endpoint,
|
|
627
|
+
headers: source.headers,
|
|
628
|
+
queryParams: source.queryParams,
|
|
629
|
+
auth: source.auth
|
|
630
|
+
});
|
|
631
|
+
var operationData = (operation) => ({
|
|
632
|
+
toolId: operation.toolId,
|
|
633
|
+
sourceId: operation.sourceId,
|
|
634
|
+
binding: toJsonRecord(encodeBinding(operation.binding))
|
|
635
|
+
});
|
|
636
|
+
var rowToSource = (row) => {
|
|
637
|
+
const decoded = decodeSourceStorage(row.data);
|
|
638
|
+
if (Option4.isNone(decoded)) return null;
|
|
639
|
+
const source = decoded.value;
|
|
633
640
|
return {
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
+
namespace: source.namespace,
|
|
642
|
+
scope: source.scope,
|
|
643
|
+
name: source.name,
|
|
644
|
+
endpoint: source.endpoint,
|
|
645
|
+
headers: normalizeCredentialMap(source.headers),
|
|
646
|
+
queryParams: normalizeCredentialMap(source.queryParams),
|
|
647
|
+
auth: source.auth
|
|
641
648
|
};
|
|
642
649
|
};
|
|
643
|
-
var
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
return {
|
|
650
|
+
var rowToOperation = (row) => {
|
|
651
|
+
const decoded = decodeOperationStorage(row.data);
|
|
652
|
+
if (Option4.isNone(decoded)) return null;
|
|
653
|
+
const operation = decoded.value;
|
|
654
|
+
return {
|
|
655
|
+
toolId: operation.toolId,
|
|
656
|
+
sourceId: operation.sourceId,
|
|
657
|
+
binding: decodeBinding(operation.binding)
|
|
658
|
+
};
|
|
648
659
|
};
|
|
649
660
|
var makeDefaultGraphqlStore = ({
|
|
650
|
-
|
|
661
|
+
pluginStorage
|
|
651
662
|
}) => {
|
|
652
|
-
const
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
return {
|
|
673
|
-
namespace: sourceId,
|
|
674
|
-
scope,
|
|
675
|
-
name: source.name,
|
|
676
|
-
endpoint: source.endpoint,
|
|
677
|
-
headers,
|
|
678
|
-
queryParams,
|
|
679
|
-
auth: rowToAuth(source)
|
|
680
|
-
};
|
|
681
|
-
});
|
|
682
|
-
const rowToOperation = (row) => {
|
|
683
|
-
const operation = decodeOperationRow(row);
|
|
684
|
-
return {
|
|
685
|
-
toolId: operation.id,
|
|
686
|
-
sourceId: operation.source_id,
|
|
687
|
-
binding: decodeBinding(operation.binding)
|
|
688
|
-
};
|
|
689
|
-
};
|
|
690
|
-
const replaceChildren = (model, sourceId, scope, values) => Effect4.gen(function* () {
|
|
691
|
-
yield* db.deleteMany({
|
|
692
|
-
model,
|
|
693
|
-
where: [
|
|
694
|
-
{ field: "source_id", value: sourceId },
|
|
695
|
-
{ field: "scope_id", value: scope }
|
|
696
|
-
]
|
|
697
|
-
});
|
|
698
|
-
const entries = Object.entries(values);
|
|
699
|
-
if (entries.length === 0) return;
|
|
700
|
-
yield* db.createMany({
|
|
701
|
-
model,
|
|
702
|
-
data: entries.map(([name, value]) => valueToChildRow(sourceId, scope, name, value)),
|
|
703
|
-
forceAllowId: true
|
|
704
|
-
});
|
|
663
|
+
const listOperationRowsForSourceScope = (sourceId, scope) => pluginStorage.list({
|
|
664
|
+
collection: OPERATION_COLLECTION,
|
|
665
|
+
keyPrefix: `${sourceId}.`
|
|
666
|
+
}).pipe(
|
|
667
|
+
Effect4.map(
|
|
668
|
+
(rows) => rows.filter((row) => {
|
|
669
|
+
if (String(row.scopeId) !== scope) return false;
|
|
670
|
+
return rowToOperation(row)?.sourceId === sourceId;
|
|
671
|
+
})
|
|
672
|
+
)
|
|
673
|
+
);
|
|
674
|
+
const removeOperationsForSourceScope = (sourceId, scope) => Effect4.gen(function* () {
|
|
675
|
+
const rows = yield* listOperationRowsForSourceScope(sourceId, scope);
|
|
676
|
+
for (const row of rows) {
|
|
677
|
+
yield* pluginStorage.remove({
|
|
678
|
+
scope,
|
|
679
|
+
collection: OPERATION_COLLECTION,
|
|
680
|
+
key: row.key
|
|
681
|
+
});
|
|
682
|
+
}
|
|
705
683
|
});
|
|
706
684
|
const deleteSource = (namespace, scope) => Effect4.gen(function* () {
|
|
707
|
-
yield*
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
]
|
|
713
|
-
});
|
|
714
|
-
yield* db.deleteMany({
|
|
715
|
-
model: "graphql_source_header",
|
|
716
|
-
where: [
|
|
717
|
-
{ field: "source_id", value: namespace },
|
|
718
|
-
{ field: "scope_id", value: scope }
|
|
719
|
-
]
|
|
720
|
-
});
|
|
721
|
-
yield* db.deleteMany({
|
|
722
|
-
model: "graphql_source_query_param",
|
|
723
|
-
where: [
|
|
724
|
-
{ field: "source_id", value: namespace },
|
|
725
|
-
{ field: "scope_id", value: scope }
|
|
726
|
-
]
|
|
727
|
-
});
|
|
728
|
-
yield* db.delete({
|
|
729
|
-
model: "graphql_source",
|
|
730
|
-
where: [
|
|
731
|
-
{ field: "id", value: namespace },
|
|
732
|
-
{ field: "scope_id", value: scope }
|
|
733
|
-
]
|
|
685
|
+
yield* removeOperationsForSourceScope(namespace, scope);
|
|
686
|
+
yield* pluginStorage.remove({
|
|
687
|
+
scope,
|
|
688
|
+
collection: SOURCE_COLLECTION,
|
|
689
|
+
key: namespace
|
|
734
690
|
});
|
|
735
691
|
});
|
|
736
692
|
return {
|
|
737
693
|
upsertSource: (input, operations) => Effect4.gen(function* () {
|
|
738
694
|
yield* deleteSource(input.namespace, input.scope);
|
|
739
|
-
yield*
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
name: input.name,
|
|
745
|
-
endpoint: input.endpoint,
|
|
746
|
-
auth_kind: input.auth.kind,
|
|
747
|
-
auth_connection_slot: input.auth.kind === "oauth2" ? input.auth.connectionSlot : void 0
|
|
748
|
-
},
|
|
749
|
-
forceAllowId: true
|
|
695
|
+
yield* pluginStorage.put({
|
|
696
|
+
scope: input.scope,
|
|
697
|
+
collection: SOURCE_COLLECTION,
|
|
698
|
+
key: input.namespace,
|
|
699
|
+
data: sourceData(input)
|
|
750
700
|
});
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
yield* replaceChildren(
|
|
758
|
-
"graphql_source_query_param",
|
|
759
|
-
input.namespace,
|
|
760
|
-
input.scope,
|
|
761
|
-
input.queryParams
|
|
762
|
-
);
|
|
763
|
-
if (operations.length > 0) {
|
|
764
|
-
yield* db.createMany({
|
|
765
|
-
model: "graphql_operation",
|
|
766
|
-
data: operations.map((op) => ({
|
|
767
|
-
id: op.toolId,
|
|
768
|
-
scope_id: input.scope,
|
|
769
|
-
source_id: op.sourceId,
|
|
770
|
-
binding: toJsonRecord(encodeBinding(op.binding))
|
|
771
|
-
})),
|
|
772
|
-
forceAllowId: true
|
|
701
|
+
for (const operation of operations) {
|
|
702
|
+
yield* pluginStorage.put({
|
|
703
|
+
scope: input.scope,
|
|
704
|
+
collection: OPERATION_COLLECTION,
|
|
705
|
+
key: operation.toolId,
|
|
706
|
+
data: operationData(operation)
|
|
773
707
|
});
|
|
774
708
|
}
|
|
775
709
|
}),
|
|
776
710
|
updateSourceMeta: (namespace, scope, patch) => Effect4.gen(function* () {
|
|
777
|
-
const existing = yield*
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
{ field: "scope_id", value: scope }
|
|
782
|
-
]
|
|
711
|
+
const existing = yield* pluginStorage.getAtScope({
|
|
712
|
+
scope,
|
|
713
|
+
collection: SOURCE_COLLECTION,
|
|
714
|
+
key: namespace
|
|
783
715
|
});
|
|
784
716
|
if (!existing) return;
|
|
785
|
-
const
|
|
786
|
-
if (
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
update
|
|
800
|
-
});
|
|
801
|
-
}
|
|
802
|
-
if (patch.headers !== void 0) {
|
|
803
|
-
yield* replaceChildren("graphql_source_header", namespace, scope, patch.headers);
|
|
804
|
-
}
|
|
805
|
-
if (patch.queryParams !== void 0) {
|
|
806
|
-
yield* replaceChildren("graphql_source_query_param", namespace, scope, patch.queryParams);
|
|
807
|
-
}
|
|
808
|
-
}),
|
|
809
|
-
getSource: (namespace, scope) => Effect4.gen(function* () {
|
|
810
|
-
const row = yield* db.findOne({
|
|
811
|
-
model: "graphql_source",
|
|
812
|
-
where: [
|
|
813
|
-
{ field: "id", value: namespace },
|
|
814
|
-
{ field: "scope_id", value: scope }
|
|
815
|
-
]
|
|
816
|
-
});
|
|
817
|
-
if (!row) return null;
|
|
818
|
-
return yield* rowToSourceWithChildren(row);
|
|
819
|
-
}),
|
|
820
|
-
listSources: () => Effect4.gen(function* () {
|
|
821
|
-
const rows = yield* db.findMany({ model: "graphql_source" });
|
|
822
|
-
return yield* Effect4.forEach(rows, rowToSourceWithChildren, {
|
|
823
|
-
concurrency: "unbounded"
|
|
717
|
+
const source = rowToSource(existing);
|
|
718
|
+
if (!source) return;
|
|
719
|
+
yield* pluginStorage.put({
|
|
720
|
+
scope,
|
|
721
|
+
collection: SOURCE_COLLECTION,
|
|
722
|
+
key: namespace,
|
|
723
|
+
data: sourceData({
|
|
724
|
+
...source,
|
|
725
|
+
name: patch.name ?? source.name,
|
|
726
|
+
endpoint: patch.endpoint ?? source.endpoint,
|
|
727
|
+
headers: patch.headers ?? source.headers,
|
|
728
|
+
queryParams: patch.queryParams ?? source.queryParams,
|
|
729
|
+
auth: patch.auth ?? source.auth
|
|
730
|
+
})
|
|
824
731
|
});
|
|
825
732
|
}),
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
}).pipe(Effect4.map((row) => row ? rowToOperation(row) : null)),
|
|
833
|
-
listOperationsBySource: (sourceId, scope) => db.findMany({
|
|
834
|
-
model: "graphql_operation",
|
|
835
|
-
where: [
|
|
836
|
-
{ field: "source_id", value: sourceId },
|
|
837
|
-
{ field: "scope_id", value: scope }
|
|
838
|
-
]
|
|
839
|
-
}).pipe(Effect4.map((rows) => rows.map(rowToOperation))),
|
|
733
|
+
getSource: (namespace, scope) => pluginStorage.getAtScope({ scope, collection: SOURCE_COLLECTION, key: namespace }).pipe(Effect4.map((row) => row ? rowToSource(row) : null)),
|
|
734
|
+
listSources: () => pluginStorage.list({ collection: SOURCE_COLLECTION }).pipe(Effect4.map((rows) => rows.map(rowToSource).filter(Predicate.isNotNull))),
|
|
735
|
+
getOperationByToolId: (toolId, scope) => pluginStorage.getAtScope({ scope, collection: OPERATION_COLLECTION, key: toolId }).pipe(Effect4.map((row) => row ? rowToOperation(row) : null)),
|
|
736
|
+
listOperationsBySource: (sourceId, scope) => listOperationRowsForSourceScope(sourceId, scope).pipe(
|
|
737
|
+
Effect4.map((rows) => rows.map(rowToOperation).filter(Predicate.isNotNull))
|
|
738
|
+
),
|
|
840
739
|
removeSource: (namespace, scope) => deleteSource(namespace, scope)
|
|
841
740
|
};
|
|
842
741
|
};
|
|
843
742
|
|
|
844
743
|
// src/sdk/plugin.ts
|
|
845
|
-
import { Effect as Effect5, Match as Match2, Option as
|
|
744
|
+
import { Effect as Effect5, Match as Match2, Option as Option5, Schema as Schema3 } from "effect";
|
|
846
745
|
import {
|
|
847
|
-
ConnectionId,
|
|
848
|
-
ConfiguredCredentialBinding as ConfiguredCredentialBinding2,
|
|
849
746
|
definePlugin,
|
|
850
747
|
tool,
|
|
748
|
+
defaultSourceInstallScopeId,
|
|
851
749
|
ScopeId,
|
|
852
|
-
SecretId,
|
|
853
750
|
SourceDetectionResult,
|
|
854
|
-
StorageError
|
|
751
|
+
StorageError,
|
|
752
|
+
ToolResult
|
|
855
753
|
} from "@executor-js/sdk/core";
|
|
754
|
+
import {
|
|
755
|
+
compileHttpNamedCredentialMap,
|
|
756
|
+
OAuth2SourceConfig,
|
|
757
|
+
httpCredentialInputToBindingValue
|
|
758
|
+
} from "@executor-js/sdk/http-source";
|
|
856
759
|
import {
|
|
857
760
|
headersToConfigValues
|
|
858
761
|
} from "@executor-js/config";
|
|
859
|
-
var
|
|
762
|
+
var GraphqlErrorBody = Schema3.Struct({ message: Schema3.String });
|
|
763
|
+
var GraphqlErrorsBody = Schema3.Array(Schema3.Unknown);
|
|
764
|
+
var decodeGraphqlErrorBody = Schema3.decodeUnknownOption(GraphqlErrorBody);
|
|
765
|
+
var decodeGraphqlErrorsBody = Schema3.decodeUnknownOption(GraphqlErrorsBody);
|
|
766
|
+
var decodeGraphqlErrors = (errors) => Option5.getOrUndefined(decodeGraphqlErrorsBody(errors));
|
|
767
|
+
var extractGraphqlErrorMessage = (errors) => errors.map((error) => Option5.getOrUndefined(decodeGraphqlErrorBody(error))?.message).find((message) => message !== void 0 && message.length > 0);
|
|
768
|
+
var GraphqlInitialCredentialsInputSchema = Schema3.Struct({
|
|
860
769
|
scope: Schema3.String,
|
|
770
|
+
headers: Schema3.optional(Schema3.Record(Schema3.String, GraphqlCredentialInput)),
|
|
771
|
+
queryParams: Schema3.optional(Schema3.Record(Schema3.String, GraphqlCredentialInput)),
|
|
772
|
+
auth: Schema3.optional(GraphqlSourceAuthInput)
|
|
773
|
+
});
|
|
774
|
+
var StaticAddSourceInputSchema = Schema3.Struct({
|
|
861
775
|
endpoint: Schema3.String,
|
|
862
|
-
name: Schema3.
|
|
776
|
+
name: Schema3.String,
|
|
863
777
|
introspectionJson: Schema3.optional(Schema3.String),
|
|
864
|
-
namespace: Schema3.
|
|
778
|
+
namespace: Schema3.String,
|
|
779
|
+
headers: Schema3.optional(Schema3.Record(Schema3.String, GraphqlConfiguredValueInput)),
|
|
780
|
+
queryParams: Schema3.optional(Schema3.Record(Schema3.String, GraphqlConfiguredValueInput)),
|
|
781
|
+
oauth2: Schema3.optional(OAuth2SourceConfig),
|
|
782
|
+
credentials: Schema3.optional(GraphqlInitialCredentialsInputSchema)
|
|
783
|
+
});
|
|
784
|
+
var SourceConfigureInputSchema = Schema3.Struct({
|
|
785
|
+
name: Schema3.optional(Schema3.String),
|
|
786
|
+
endpoint: Schema3.optional(Schema3.String),
|
|
865
787
|
headers: Schema3.optional(Schema3.Record(Schema3.String, GraphqlCredentialInput)),
|
|
866
788
|
queryParams: Schema3.optional(Schema3.Record(Schema3.String, GraphqlCredentialInput)),
|
|
867
|
-
credentialTargetScope: Schema3.optional(Schema3.String),
|
|
868
789
|
auth: Schema3.optional(GraphqlSourceAuthInput)
|
|
869
790
|
});
|
|
791
|
+
var StaticConfigureSourceInputSchema = Schema3.Struct({
|
|
792
|
+
source: Schema3.Struct({
|
|
793
|
+
id: Schema3.String,
|
|
794
|
+
scope: Schema3.String
|
|
795
|
+
}),
|
|
796
|
+
scope: Schema3.String,
|
|
797
|
+
...SourceConfigureInputSchema.fields
|
|
798
|
+
});
|
|
799
|
+
var StaticConfigureSourceOutputSchema = Schema3.Struct({
|
|
800
|
+
configured: Schema3.Boolean
|
|
801
|
+
});
|
|
802
|
+
var StaticGetSourceInputSchema = Schema3.Struct({
|
|
803
|
+
namespace: Schema3.String,
|
|
804
|
+
scope: Schema3.String
|
|
805
|
+
});
|
|
806
|
+
var StaticGetSourceOutputSchema = Schema3.Struct({
|
|
807
|
+
source: Schema3.NullOr(Schema3.Unknown)
|
|
808
|
+
});
|
|
870
809
|
var StaticAddSourceInputStandardSchema = Schema3.toStandardSchemaV1(
|
|
871
810
|
Schema3.toStandardJSONSchemaV1(StaticAddSourceInputSchema)
|
|
872
811
|
);
|
|
873
812
|
var StaticAddSourceOutputStandardSchema = Schema3.toStandardSchemaV1(
|
|
874
|
-
Schema3.toStandardJSONSchemaV1(
|
|
813
|
+
Schema3.toStandardJSONSchemaV1(
|
|
814
|
+
Schema3.Struct({
|
|
815
|
+
namespace: Schema3.String,
|
|
816
|
+
source: Schema3.Struct({
|
|
817
|
+
id: Schema3.String,
|
|
818
|
+
scope: Schema3.String
|
|
819
|
+
}),
|
|
820
|
+
toolCount: Schema3.Number
|
|
821
|
+
})
|
|
822
|
+
)
|
|
823
|
+
);
|
|
824
|
+
var StaticGetSourceInputStandardSchema = Schema3.toStandardSchemaV1(
|
|
825
|
+
Schema3.toStandardJSONSchemaV1(StaticGetSourceInputSchema)
|
|
826
|
+
);
|
|
827
|
+
var StaticGetSourceOutputStandardSchema = Schema3.toStandardSchemaV1(
|
|
828
|
+
Schema3.toStandardJSONSchemaV1(StaticGetSourceOutputSchema)
|
|
829
|
+
);
|
|
830
|
+
var StaticConfigureSourceInputStandardSchema = Schema3.toStandardSchemaV1(
|
|
831
|
+
Schema3.toStandardJSONSchemaV1(StaticConfigureSourceInputSchema)
|
|
832
|
+
);
|
|
833
|
+
var StaticConfigureSourceOutputStandardSchema = Schema3.toStandardSchemaV1(
|
|
834
|
+
Schema3.toStandardJSONSchemaV1(StaticConfigureSourceOutputSchema)
|
|
835
|
+
);
|
|
836
|
+
var graphqlToolFailure = (code, message, details) => ToolResult.fail({
|
|
837
|
+
code,
|
|
838
|
+
message,
|
|
839
|
+
...details === void 0 ? {} : { details }
|
|
840
|
+
});
|
|
841
|
+
var resolveStaticScopeInput = (ctx, value) => String(
|
|
842
|
+
ctx.scopes.find((scope) => scope.name === value || String(scope.id) === value)?.id ?? value
|
|
875
843
|
);
|
|
876
844
|
var urlMatchesToken = (url, token) => {
|
|
877
845
|
const re = new RegExp(`(?:^|[^a-z0-9])${token}(?:$|[^a-z0-9])`, "i");
|
|
@@ -889,7 +857,7 @@ var formatTypeRef2 = (ref) => Match2.value(ref.kind).pipe(
|
|
|
889
857
|
Match2.when("NON_NULL", () => ref.ofType ? `${formatTypeRef2(ref.ofType)}!` : "Unknown!"),
|
|
890
858
|
Match2.when("LIST", () => ref.ofType ? `[${formatTypeRef2(ref.ofType)}]` : "[Unknown]"),
|
|
891
859
|
Match2.option,
|
|
892
|
-
|
|
860
|
+
Option5.getOrElse(() => ref.name ?? "Unknown")
|
|
893
861
|
);
|
|
894
862
|
var unwrapTypeName2 = (ref) => {
|
|
895
863
|
if (ref.name) return ref.name;
|
|
@@ -945,7 +913,7 @@ var prepareOperations = (fields, introspection) => {
|
|
|
945
913
|
return fields.map((extracted) => {
|
|
946
914
|
const prefix = extracted.kind === "mutation" ? "mutation" : "query";
|
|
947
915
|
const toolPath = `${prefix}.${extracted.fieldName}`;
|
|
948
|
-
const description =
|
|
916
|
+
const description = Option5.getOrElse(
|
|
949
917
|
extracted.description,
|
|
950
918
|
() => `GraphQL ${extracted.kind}: ${extracted.fieldName} -> ${extracted.returnTypeName}`
|
|
951
919
|
);
|
|
@@ -961,7 +929,7 @@ var prepareOperations = (fields, introspection) => {
|
|
|
961
929
|
return {
|
|
962
930
|
toolPath,
|
|
963
931
|
description,
|
|
964
|
-
inputSchema:
|
|
932
|
+
inputSchema: Option5.getOrUndefined(extracted.inputSchema),
|
|
965
933
|
binding
|
|
966
934
|
};
|
|
967
935
|
});
|
|
@@ -993,26 +961,6 @@ var toGraphqlConfigEntry = (namespace, config) => {
|
|
|
993
961
|
var GRAPHQL_PLUGIN_ID = "graphql";
|
|
994
962
|
var scopeRanks = (ctx) => new Map(ctx.scopes.map((scope, index) => [String(scope.id), index]));
|
|
995
963
|
var scopeRank = (ranks, scopeId) => ranks.get(scopeId) ?? Infinity;
|
|
996
|
-
var coreBindingToGraphqlBinding = (binding) => GraphqlSourceBindingRef.make({
|
|
997
|
-
sourceId: binding.sourceId,
|
|
998
|
-
sourceScopeId: binding.sourceScopeId,
|
|
999
|
-
scopeId: binding.scopeId,
|
|
1000
|
-
slot: binding.slotKey,
|
|
1001
|
-
value: binding.value,
|
|
1002
|
-
createdAt: binding.createdAt,
|
|
1003
|
-
updatedAt: binding.updatedAt
|
|
1004
|
-
});
|
|
1005
|
-
var listGraphqlSourceBindings = (ctx, sourceId, sourceScope) => Effect5.gen(function* () {
|
|
1006
|
-
const ranks = scopeRanks(ctx);
|
|
1007
|
-
const sourceSourceRank = scopeRank(ranks, sourceScope);
|
|
1008
|
-
if (sourceSourceRank === Infinity) return [];
|
|
1009
|
-
const bindings = yield* ctx.credentialBindings.listForSource({
|
|
1010
|
-
pluginId: GRAPHQL_PLUGIN_ID,
|
|
1011
|
-
sourceId,
|
|
1012
|
-
sourceScope: ScopeId.make(sourceScope)
|
|
1013
|
-
});
|
|
1014
|
-
return bindings.filter((binding) => scopeRank(ranks, binding.scopeId) <= sourceSourceRank).map(coreBindingToGraphqlBinding);
|
|
1015
|
-
});
|
|
1016
964
|
var resolveGraphqlSourceBinding = (ctx, sourceId, sourceScope, slot) => Effect5.gen(function* () {
|
|
1017
965
|
const ranks = scopeRanks(ctx);
|
|
1018
966
|
const sourceSourceRank = scopeRank(ranks, sourceScope);
|
|
@@ -1025,7 +973,7 @@ var resolveGraphqlSourceBinding = (ctx, sourceId, sourceScope, slot) => Effect5.
|
|
|
1025
973
|
const binding = bindings.filter(
|
|
1026
974
|
(candidate) => candidate.slotKey === slot && scopeRank(ranks, candidate.scopeId) <= sourceSourceRank
|
|
1027
975
|
).sort((a, b) => scopeRank(ranks, a.scopeId) - scopeRank(ranks, b.scopeId))[0];
|
|
1028
|
-
return binding
|
|
976
|
+
return binding ?? null;
|
|
1029
977
|
});
|
|
1030
978
|
var validateGraphqlBindingTarget = (ctx, input) => Effect5.gen(function* () {
|
|
1031
979
|
const ranks = scopeRanks(ctx);
|
|
@@ -1051,70 +999,93 @@ var validateGraphqlBindingTarget = (ctx, input) => Effect5.gen(function* () {
|
|
|
1051
999
|
});
|
|
1052
1000
|
}
|
|
1053
1001
|
});
|
|
1054
|
-
var
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
return Effect5.fail(
|
|
1058
|
-
new GraphqlIntrospectionError({
|
|
1059
|
-
message: "credentialTargetScope is required when adding direct GraphQL credentials"
|
|
1060
|
-
})
|
|
1061
|
-
);
|
|
1062
|
-
};
|
|
1063
|
-
var targetScopeForBinding = (fallbackTargetScope, binding) => {
|
|
1064
|
-
const targetScope = binding.targetScope ?? fallbackTargetScope;
|
|
1065
|
-
if (targetScope) return Effect5.succeed(targetScope);
|
|
1066
|
-
return Effect5.fail(
|
|
1067
|
-
new GraphqlIntrospectionError({
|
|
1068
|
-
message: "credentialTargetScope is required when adding direct GraphQL credentials"
|
|
1069
|
-
})
|
|
1070
|
-
);
|
|
1071
|
-
};
|
|
1072
|
-
var canonicalizeCredentialMap = (values, slotForName) => {
|
|
1073
|
-
const nextValues = {};
|
|
1074
|
-
const bindings = [];
|
|
1002
|
+
var canonicalizeCredentialMap = compileHttpNamedCredentialMap;
|
|
1003
|
+
var canonicalizeConfiguredValueMap = (values, slotForName) => {
|
|
1004
|
+
const next = {};
|
|
1075
1005
|
for (const [name, value] of Object.entries(values ?? {})) {
|
|
1076
1006
|
if (typeof value === "string") {
|
|
1077
|
-
|
|
1007
|
+
next[name] = value;
|
|
1078
1008
|
continue;
|
|
1079
1009
|
}
|
|
1080
|
-
|
|
1081
|
-
nextValues[name] = value;
|
|
1082
|
-
continue;
|
|
1083
|
-
}
|
|
1084
|
-
const slot = slotForName(name);
|
|
1085
|
-
nextValues[name] = ConfiguredCredentialBinding2.make({
|
|
1010
|
+
next[name] = {
|
|
1086
1011
|
kind: "binding",
|
|
1087
|
-
slot,
|
|
1012
|
+
slot: slotForName(name),
|
|
1088
1013
|
prefix: value.prefix
|
|
1089
|
-
}
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
});
|
|
1014
|
+
};
|
|
1015
|
+
}
|
|
1016
|
+
return next;
|
|
1017
|
+
};
|
|
1018
|
+
var resolveConfiguredValueMap = (values) => {
|
|
1019
|
+
if (!values) return void 0;
|
|
1020
|
+
const resolved = {};
|
|
1021
|
+
for (const [name, value] of Object.entries(values)) {
|
|
1022
|
+
if (typeof value === "string") resolved[name] = value;
|
|
1099
1023
|
}
|
|
1100
|
-
return
|
|
1024
|
+
return Object.keys(resolved).length > 0 ? resolved : void 0;
|
|
1101
1025
|
};
|
|
1026
|
+
var authFromOAuth2Source = (oauth2) => oauth2 ? { kind: "oauth2", connectionSlot: oauth2.connectionSlot } : { kind: "none" };
|
|
1102
1027
|
var canonicalizeAuth = (auth) => {
|
|
1103
|
-
if (!auth ||
|
|
1104
|
-
|
|
1028
|
+
if (!auth || "kind" in auth || !auth.oauth2) return { auth: { kind: "none" }, bindings: [] };
|
|
1029
|
+
const connection = auth.oauth2.connection;
|
|
1105
1030
|
return {
|
|
1106
1031
|
auth: { kind: "oauth2", connectionSlot: GRAPHQL_OAUTH_CONNECTION_SLOT },
|
|
1107
|
-
bindings: [
|
|
1032
|
+
bindings: connection ? [
|
|
1108
1033
|
{
|
|
1109
1034
|
slot: GRAPHQL_OAUTH_CONNECTION_SLOT,
|
|
1110
|
-
value:
|
|
1111
|
-
kind: "connection",
|
|
1112
|
-
connectionId: ConnectionId.make(auth.connectionId)
|
|
1113
|
-
}
|
|
1035
|
+
value: httpCredentialInputToBindingValue(connection)
|
|
1114
1036
|
}
|
|
1115
|
-
]
|
|
1037
|
+
] : []
|
|
1116
1038
|
};
|
|
1117
1039
|
};
|
|
1040
|
+
var resolveInitialCredentialValueMap = (ctx, values, bindings, targetScope) => Effect5.gen(function* () {
|
|
1041
|
+
const bySlot = new Map(bindings.map((binding) => [binding.slot, binding.value]));
|
|
1042
|
+
const resolved = {};
|
|
1043
|
+
for (const [name, value] of Object.entries(values)) {
|
|
1044
|
+
if (typeof value === "string") {
|
|
1045
|
+
resolved[name] = value;
|
|
1046
|
+
continue;
|
|
1047
|
+
}
|
|
1048
|
+
const binding = bySlot.get(value.slot);
|
|
1049
|
+
if (binding?.kind === "secret") {
|
|
1050
|
+
const secret = yield* ctx.secrets.getAtScope(binding.secretId, binding.secretScopeId ?? ScopeId.make(targetScope)).pipe(
|
|
1051
|
+
Effect5.catchTag(
|
|
1052
|
+
"SecretOwnedByConnectionError",
|
|
1053
|
+
() => Effect5.fail(
|
|
1054
|
+
new GraphqlIntrospectionError({
|
|
1055
|
+
message: `Secret not found for ${name}`
|
|
1056
|
+
})
|
|
1057
|
+
)
|
|
1058
|
+
)
|
|
1059
|
+
);
|
|
1060
|
+
if (secret === null) {
|
|
1061
|
+
return yield* new GraphqlIntrospectionError({
|
|
1062
|
+
message: `Missing secret "${binding.secretId}" for ${name}`
|
|
1063
|
+
});
|
|
1064
|
+
}
|
|
1065
|
+
resolved[name] = value.prefix ? `${value.prefix}${secret}` : secret;
|
|
1066
|
+
continue;
|
|
1067
|
+
}
|
|
1068
|
+
if (binding?.kind === "text") {
|
|
1069
|
+
resolved[name] = value.prefix ? `${value.prefix}${binding.text}` : binding.text;
|
|
1070
|
+
}
|
|
1071
|
+
}
|
|
1072
|
+
return Object.keys(resolved).length > 0 ? resolved : void 0;
|
|
1073
|
+
});
|
|
1074
|
+
var resolveInitialOAuthHeaders = (ctx, bindings, targetScope) => Effect5.gen(function* () {
|
|
1075
|
+
const connection = bindings.find(
|
|
1076
|
+
(binding) => binding.slot === GRAPHQL_OAUTH_CONNECTION_SLOT && binding.value.kind === "connection"
|
|
1077
|
+
);
|
|
1078
|
+
if (!connection || connection.value.kind !== "connection") return void 0;
|
|
1079
|
+
const connectionId = connection.value.connectionId;
|
|
1080
|
+
const accessToken = yield* ctx.connections.accessTokenAtScope(connectionId, ScopeId.make(targetScope)).pipe(
|
|
1081
|
+
Effect5.mapError(
|
|
1082
|
+
({ message }) => new GraphqlIntrospectionError({
|
|
1083
|
+
message: `Failed to resolve OAuth connection "${connectionId}": ${message}`
|
|
1084
|
+
})
|
|
1085
|
+
)
|
|
1086
|
+
);
|
|
1087
|
+
return { Authorization: `Bearer ${accessToken}` };
|
|
1088
|
+
});
|
|
1118
1089
|
var resolveGraphqlBindingValueMap = (ctx, values, params) => Effect5.gen(function* () {
|
|
1119
1090
|
if (!values) return void 0;
|
|
1120
1091
|
const resolved = {};
|
|
@@ -1169,7 +1140,7 @@ var resolveGraphqlStoredOAuthHeader = (ctx, sourceId, sourceScope, auth) => Effe
|
|
|
1169
1140
|
if (binding?.value.kind !== "connection") {
|
|
1170
1141
|
return yield* new GraphqlInvocationError({
|
|
1171
1142
|
message: `Missing OAuth connection binding for GraphQL source "${sourceId}"`,
|
|
1172
|
-
statusCode:
|
|
1143
|
+
statusCode: Option5.none()
|
|
1173
1144
|
});
|
|
1174
1145
|
}
|
|
1175
1146
|
const accessToken = yield* ctx.connections.accessTokenAtScope(
|
|
@@ -1179,127 +1150,61 @@ var resolveGraphqlStoredOAuthHeader = (ctx, sourceId, sourceScope, auth) => Effe
|
|
|
1179
1150
|
return { Authorization: `Bearer ${accessToken}` };
|
|
1180
1151
|
});
|
|
1181
1152
|
var makeGraphqlExtension = (ctx, httpClientLayer, configFile) => {
|
|
1182
|
-
const resolveCredentialInputMap = (values, params) => Effect5.gen(function* () {
|
|
1183
|
-
if (!values) return void 0;
|
|
1184
|
-
const resolved = {};
|
|
1185
|
-
for (const [name, value] of Object.entries(values)) {
|
|
1186
|
-
if (typeof value === "string") {
|
|
1187
|
-
resolved[name] = value;
|
|
1188
|
-
continue;
|
|
1189
|
-
}
|
|
1190
|
-
if ("kind" in value) {
|
|
1191
|
-
const slotResolved = yield* resolveGraphqlBindingValueMap(
|
|
1192
|
-
ctx,
|
|
1193
|
-
{ [name]: value },
|
|
1194
|
-
{
|
|
1195
|
-
sourceId: params.sourceId,
|
|
1196
|
-
sourceScope: params.sourceScope,
|
|
1197
|
-
missingLabel: params.missingLabel,
|
|
1198
|
-
makeError: params.makeError
|
|
1199
|
-
}
|
|
1200
|
-
);
|
|
1201
|
-
if (slotResolved?.[name] !== void 0) resolved[name] = slotResolved[name];
|
|
1202
|
-
continue;
|
|
1203
|
-
}
|
|
1204
|
-
const secretScope = "secretScopeId" in value ? value.secretScopeId ?? value.targetScope : params.targetScope ?? params.sourceScope;
|
|
1205
|
-
const secret = yield* ctx.secrets.getAtScope(SecretId.make(value.secretId), secretScope).pipe(
|
|
1206
|
-
Effect5.catchTag(
|
|
1207
|
-
"SecretOwnedByConnectionError",
|
|
1208
|
-
() => Effect5.fail(
|
|
1209
|
-
params.makeError(`Secret not found for ${params.missingLabel} "${name}"`)
|
|
1210
|
-
)
|
|
1211
|
-
)
|
|
1212
|
-
);
|
|
1213
|
-
if (secret === null) {
|
|
1214
|
-
return yield* Effect5.fail(
|
|
1215
|
-
params.makeError(
|
|
1216
|
-
`Missing secret "${value.secretId}" for ${params.missingLabel} "${name}"`
|
|
1217
|
-
)
|
|
1218
|
-
);
|
|
1219
|
-
}
|
|
1220
|
-
resolved[name] = value.prefix ? `${value.prefix}${secret}` : secret;
|
|
1221
|
-
}
|
|
1222
|
-
return Object.keys(resolved).length > 0 ? resolved : void 0;
|
|
1223
|
-
});
|
|
1224
|
-
const resolveOAuthInputHeader = (sourceId, sourceScope, targetScope, auth) => Effect5.gen(function* () {
|
|
1225
|
-
if (!auth || auth.kind === "none") return void 0;
|
|
1226
|
-
const connection = "connectionId" in auth ? { id: auth.connectionId, scope: targetScope ?? sourceScope } : yield* Effect5.gen(function* () {
|
|
1227
|
-
const binding = yield* resolveGraphqlSourceBinding(
|
|
1228
|
-
ctx,
|
|
1229
|
-
sourceId,
|
|
1230
|
-
sourceScope,
|
|
1231
|
-
auth.connectionSlot
|
|
1232
|
-
);
|
|
1233
|
-
return binding?.value.kind === "connection" ? { id: binding.value.connectionId, scope: binding.scopeId } : null;
|
|
1234
|
-
});
|
|
1235
|
-
if (connection === null) {
|
|
1236
|
-
return yield* new GraphqlIntrospectionError({
|
|
1237
|
-
message: `Missing OAuth connection binding for "${sourceId}"`
|
|
1238
|
-
});
|
|
1239
|
-
}
|
|
1240
|
-
const accessToken = yield* ctx.connections.accessTokenAtScope(connection.id, connection.scope).pipe(
|
|
1241
|
-
Effect5.mapError(
|
|
1242
|
-
() => new GraphqlIntrospectionError({
|
|
1243
|
-
message: `Failed to resolve OAuth connection "${connection.id}"`
|
|
1244
|
-
})
|
|
1245
|
-
)
|
|
1246
|
-
);
|
|
1247
|
-
return { Authorization: `Bearer ${accessToken}` };
|
|
1248
|
-
});
|
|
1249
1153
|
const addSourceInternal = (config) => ctx.transaction(
|
|
1250
1154
|
Effect5.gen(function* () {
|
|
1251
|
-
const namespace = config.namespace
|
|
1252
|
-
const canonicalHeaders =
|
|
1253
|
-
const canonicalQueryParams =
|
|
1155
|
+
const namespace = config.namespace;
|
|
1156
|
+
const canonicalHeaders = canonicalizeConfiguredValueMap(config.headers, graphqlHeaderSlot);
|
|
1157
|
+
const canonicalQueryParams = canonicalizeConfiguredValueMap(
|
|
1254
1158
|
config.queryParams,
|
|
1255
1159
|
graphqlQueryParamSlot
|
|
1256
1160
|
);
|
|
1257
|
-
const
|
|
1258
|
-
const
|
|
1259
|
-
|
|
1260
|
-
|
|
1261
|
-
|
|
1161
|
+
const initialHeaders = config.credentials?.headers !== void 0 ? canonicalizeCredentialMap(config.credentials.headers, graphqlHeaderSlot) : null;
|
|
1162
|
+
const initialQueryParams = config.credentials?.queryParams !== void 0 ? canonicalizeCredentialMap(config.credentials.queryParams, graphqlQueryParamSlot) : null;
|
|
1163
|
+
const initialAuth = config.credentials?.auth !== void 0 ? canonicalizeAuth(config.credentials.auth) : null;
|
|
1164
|
+
const auth = config.oauth2 ? authFromOAuth2Source(config.oauth2) : initialAuth?.auth ?? { kind: "none" };
|
|
1165
|
+
const initialBindings = [
|
|
1166
|
+
...initialHeaders?.bindings ?? [],
|
|
1167
|
+
...initialQueryParams?.bindings ?? [],
|
|
1168
|
+
...initialAuth?.bindings ?? []
|
|
1262
1169
|
];
|
|
1263
|
-
|
|
1264
|
-
|
|
1265
|
-
config.credentialTargetScope,
|
|
1266
|
-
binding
|
|
1267
|
-
);
|
|
1170
|
+
const initialScope = config.credentials?.scope;
|
|
1171
|
+
if (initialScope && initialBindings.length > 0) {
|
|
1268
1172
|
yield* validateGraphqlBindingTarget(ctx, {
|
|
1269
1173
|
sourceId: namespace,
|
|
1270
1174
|
sourceScope: config.scope,
|
|
1271
|
-
targetScope:
|
|
1175
|
+
targetScope: initialScope
|
|
1272
1176
|
});
|
|
1273
1177
|
}
|
|
1274
|
-
const targetScope = directBindings[0] !== void 0 ? yield* targetScopeForBinding(config.credentialTargetScope, directBindings[0]) : void 0;
|
|
1275
1178
|
let introspectionResult;
|
|
1276
1179
|
if (config.introspectionJson) {
|
|
1277
1180
|
introspectionResult = yield* parseIntrospectionJson(config.introspectionJson);
|
|
1278
1181
|
} else {
|
|
1279
|
-
const
|
|
1280
|
-
|
|
1281
|
-
|
|
1282
|
-
|
|
1283
|
-
|
|
1284
|
-
|
|
1285
|
-
|
|
1286
|
-
const
|
|
1287
|
-
|
|
1288
|
-
|
|
1289
|
-
|
|
1290
|
-
|
|
1291
|
-
|
|
1292
|
-
|
|
1293
|
-
|
|
1294
|
-
|
|
1295
|
-
|
|
1296
|
-
|
|
1297
|
-
|
|
1298
|
-
|
|
1182
|
+
const resolvedInitialHeaders = initialHeaders && initialScope ? yield* resolveInitialCredentialValueMap(
|
|
1183
|
+
ctx,
|
|
1184
|
+
canonicalHeaders,
|
|
1185
|
+
initialHeaders.bindings,
|
|
1186
|
+
initialScope
|
|
1187
|
+
) : void 0;
|
|
1188
|
+
const resolvedOAuthHeaders = initialAuth && initialScope ? yield* resolveInitialOAuthHeaders(ctx, initialAuth.bindings, initialScope) : void 0;
|
|
1189
|
+
const resolvedHeaders = {
|
|
1190
|
+
...resolveConfiguredValueMap(config.headers) ?? {},
|
|
1191
|
+
...resolvedInitialHeaders ?? {},
|
|
1192
|
+
...resolvedOAuthHeaders ?? {}
|
|
1193
|
+
};
|
|
1194
|
+
const resolvedInitialQueryParams = initialQueryParams && initialScope ? yield* resolveInitialCredentialValueMap(
|
|
1195
|
+
ctx,
|
|
1196
|
+
canonicalQueryParams,
|
|
1197
|
+
initialQueryParams.bindings,
|
|
1198
|
+
initialScope
|
|
1199
|
+
) : void 0;
|
|
1200
|
+
const resolvedQueryParams = {
|
|
1201
|
+
...resolveConfiguredValueMap(config.queryParams) ?? {},
|
|
1202
|
+
...resolvedInitialQueryParams ?? {}
|
|
1203
|
+
};
|
|
1299
1204
|
introspectionResult = yield* introspect(
|
|
1300
1205
|
config.endpoint,
|
|
1301
|
-
|
|
1302
|
-
resolvedQueryParams
|
|
1206
|
+
Object.keys(resolvedHeaders).length > 0 ? resolvedHeaders : void 0,
|
|
1207
|
+
Object.keys(resolvedQueryParams).length > 0 ? resolvedQueryParams : void 0
|
|
1303
1208
|
).pipe(Effect5.provide(httpClientLayer));
|
|
1304
1209
|
}
|
|
1305
1210
|
const { result, definitions } = yield* extract(introspectionResult);
|
|
@@ -1310,9 +1215,9 @@ var makeGraphqlExtension = (ctx, httpClientLayer, configFile) => {
|
|
|
1310
1215
|
scope: config.scope,
|
|
1311
1216
|
name: displayName,
|
|
1312
1217
|
endpoint: config.endpoint,
|
|
1313
|
-
headers: canonicalHeaders
|
|
1314
|
-
queryParams: canonicalQueryParams
|
|
1315
|
-
auth
|
|
1218
|
+
headers: canonicalHeaders,
|
|
1219
|
+
queryParams: canonicalQueryParams,
|
|
1220
|
+
auth
|
|
1316
1221
|
};
|
|
1317
1222
|
const storedOps = prepared.map((p) => ({
|
|
1318
1223
|
toolId: `${namespace}.${p.toolPath}`,
|
|
@@ -1335,6 +1240,23 @@ var makeGraphqlExtension = (ctx, httpClientLayer, configFile) => {
|
|
|
1335
1240
|
inputSchema: p.inputSchema
|
|
1336
1241
|
}))
|
|
1337
1242
|
});
|
|
1243
|
+
if (initialScope && initialBindings.length > 0) {
|
|
1244
|
+
yield* ctx.credentialBindings.replaceForSource({
|
|
1245
|
+
targetScope: ScopeId.make(initialScope),
|
|
1246
|
+
pluginId: GRAPHQL_PLUGIN_ID,
|
|
1247
|
+
sourceId: namespace,
|
|
1248
|
+
sourceScope: ScopeId.make(config.scope),
|
|
1249
|
+
slotPrefixes: [
|
|
1250
|
+
...config.credentials?.headers !== void 0 ? ["header:"] : [],
|
|
1251
|
+
...config.credentials?.queryParams !== void 0 ? ["query_param:"] : [],
|
|
1252
|
+
...config.credentials?.auth !== void 0 ? ["auth:"] : []
|
|
1253
|
+
],
|
|
1254
|
+
bindings: initialBindings.map((binding) => ({
|
|
1255
|
+
slotKey: binding.slot,
|
|
1256
|
+
value: binding.value
|
|
1257
|
+
}))
|
|
1258
|
+
});
|
|
1259
|
+
}
|
|
1338
1260
|
if (Object.keys(definitions).length > 0) {
|
|
1339
1261
|
yield* ctx.core.definitions.register({
|
|
1340
1262
|
sourceId: namespace,
|
|
@@ -1342,25 +1264,57 @@ var makeGraphqlExtension = (ctx, httpClientLayer, configFile) => {
|
|
|
1342
1264
|
definitions
|
|
1343
1265
|
});
|
|
1344
1266
|
}
|
|
1345
|
-
|
|
1346
|
-
|
|
1347
|
-
|
|
1348
|
-
|
|
1349
|
-
|
|
1350
|
-
|
|
1351
|
-
|
|
1352
|
-
|
|
1267
|
+
return { toolCount: prepared.length, namespace };
|
|
1268
|
+
})
|
|
1269
|
+
);
|
|
1270
|
+
const configureSource = (namespace, scope, targetScope, input) => Effect5.gen(function* () {
|
|
1271
|
+
const existing = yield* ctx.storage.getSource(namespace, scope);
|
|
1272
|
+
if (!existing) return;
|
|
1273
|
+
const canonicalHeaders = input.headers !== void 0 ? canonicalizeCredentialMap(input.headers, graphqlHeaderSlot) : null;
|
|
1274
|
+
const canonicalQueryParams = input.queryParams !== void 0 ? canonicalizeCredentialMap(input.queryParams, graphqlQueryParamSlot) : null;
|
|
1275
|
+
const canonicalAuth = input.auth !== void 0 ? canonicalizeAuth(input.auth) : null;
|
|
1276
|
+
const directBindings = [
|
|
1277
|
+
...canonicalHeaders?.bindings ?? [],
|
|
1278
|
+
...canonicalQueryParams?.bindings ?? [],
|
|
1279
|
+
...canonicalAuth?.bindings ?? []
|
|
1280
|
+
];
|
|
1281
|
+
if (directBindings.length > 0) {
|
|
1282
|
+
yield* validateGraphqlBindingTarget(ctx, {
|
|
1283
|
+
sourceId: namespace,
|
|
1284
|
+
sourceScope: scope,
|
|
1285
|
+
targetScope
|
|
1286
|
+
});
|
|
1287
|
+
}
|
|
1288
|
+
const affectedPrefixes = [
|
|
1289
|
+
...input.headers !== void 0 ? ["header:"] : [],
|
|
1290
|
+
...input.queryParams !== void 0 ? ["query_param:"] : [],
|
|
1291
|
+
...input.auth !== void 0 ? ["auth:"] : []
|
|
1292
|
+
];
|
|
1293
|
+
yield* ctx.transaction(
|
|
1294
|
+
Effect5.gen(function* () {
|
|
1295
|
+
yield* ctx.storage.updateSourceMeta(namespace, scope, {
|
|
1296
|
+
name: input.name?.trim() || void 0,
|
|
1297
|
+
endpoint: input.endpoint,
|
|
1298
|
+
headers: canonicalHeaders?.values,
|
|
1299
|
+
queryParams: canonicalQueryParams?.values,
|
|
1300
|
+
auth: canonicalAuth?.auth
|
|
1301
|
+
});
|
|
1302
|
+
if (affectedPrefixes.length > 0 || directBindings.length > 0) {
|
|
1303
|
+
yield* ctx.credentialBindings.replaceForSource({
|
|
1304
|
+
targetScope: ScopeId.make(targetScope),
|
|
1353
1305
|
pluginId: GRAPHQL_PLUGIN_ID,
|
|
1354
1306
|
sourceId: namespace,
|
|
1355
|
-
sourceScope: ScopeId.make(
|
|
1356
|
-
|
|
1357
|
-
|
|
1307
|
+
sourceScope: ScopeId.make(scope),
|
|
1308
|
+
slotPrefixes: affectedPrefixes,
|
|
1309
|
+
bindings: directBindings.map((binding) => ({
|
|
1310
|
+
slotKey: binding.slot,
|
|
1311
|
+
value: binding.value
|
|
1312
|
+
}))
|
|
1358
1313
|
});
|
|
1359
1314
|
}
|
|
1360
|
-
}
|
|
1361
|
-
|
|
1362
|
-
|
|
1363
|
-
);
|
|
1315
|
+
})
|
|
1316
|
+
);
|
|
1317
|
+
});
|
|
1364
1318
|
return {
|
|
1365
1319
|
addSource: (config) => addSourceInternal(config).pipe(
|
|
1366
1320
|
Effect5.tap(
|
|
@@ -1384,93 +1338,15 @@ var makeGraphqlExtension = (ctx, httpClientLayer, configFile) => {
|
|
|
1384
1338
|
}
|
|
1385
1339
|
}),
|
|
1386
1340
|
getSource: (namespace, scope) => ctx.storage.getSource(namespace, scope),
|
|
1387
|
-
|
|
1388
|
-
|
|
1389
|
-
if (!existing) return;
|
|
1390
|
-
const canonicalHeaders = input.headers !== void 0 ? canonicalizeCredentialMap(input.headers, graphqlHeaderSlot) : null;
|
|
1391
|
-
const canonicalQueryParams = input.queryParams !== void 0 ? canonicalizeCredentialMap(input.queryParams, graphqlQueryParamSlot) : null;
|
|
1392
|
-
const canonicalAuth = input.auth !== void 0 ? canonicalizeAuth(input.auth) : null;
|
|
1393
|
-
const directBindings = [
|
|
1394
|
-
...canonicalHeaders?.bindings ?? [],
|
|
1395
|
-
...canonicalQueryParams?.bindings ?? [],
|
|
1396
|
-
...canonicalAuth?.bindings ?? []
|
|
1397
|
-
];
|
|
1398
|
-
const targetScope = yield* bindingTargetScope(input.credentialTargetScope, directBindings);
|
|
1399
|
-
if (targetScope) {
|
|
1400
|
-
yield* validateGraphqlBindingTarget(ctx, {
|
|
1401
|
-
sourceId: namespace,
|
|
1402
|
-
sourceScope: scope,
|
|
1403
|
-
targetScope
|
|
1404
|
-
});
|
|
1405
|
-
}
|
|
1406
|
-
const affectedPrefixes = [
|
|
1407
|
-
...input.headers !== void 0 ? ["header:"] : [],
|
|
1408
|
-
...input.queryParams !== void 0 ? ["query_param:"] : [],
|
|
1409
|
-
...input.auth !== void 0 ? ["auth:"] : []
|
|
1410
|
-
];
|
|
1411
|
-
const replacementTargetScope = targetScope ?? input.credentialTargetScope ?? scope;
|
|
1412
|
-
yield* ctx.transaction(
|
|
1413
|
-
Effect5.gen(function* () {
|
|
1414
|
-
yield* ctx.storage.updateSourceMeta(namespace, scope, {
|
|
1415
|
-
name: input.name?.trim() || void 0,
|
|
1416
|
-
endpoint: input.endpoint,
|
|
1417
|
-
headers: canonicalHeaders?.values,
|
|
1418
|
-
queryParams: canonicalQueryParams?.values,
|
|
1419
|
-
auth: canonicalAuth?.auth
|
|
1420
|
-
});
|
|
1421
|
-
if (affectedPrefixes.length > 0 || directBindings.length > 0) {
|
|
1422
|
-
yield* ctx.credentialBindings.replaceForSource({
|
|
1423
|
-
targetScope: ScopeId.make(replacementTargetScope),
|
|
1424
|
-
pluginId: GRAPHQL_PLUGIN_ID,
|
|
1425
|
-
sourceId: namespace,
|
|
1426
|
-
sourceScope: ScopeId.make(scope),
|
|
1427
|
-
slotPrefixes: affectedPrefixes,
|
|
1428
|
-
bindings: directBindings.map((binding) => ({
|
|
1429
|
-
slotKey: binding.slot,
|
|
1430
|
-
value: binding.value
|
|
1431
|
-
}))
|
|
1432
|
-
});
|
|
1433
|
-
}
|
|
1434
|
-
})
|
|
1435
|
-
);
|
|
1436
|
-
}),
|
|
1437
|
-
listSourceBindings: (sourceId, sourceScope) => listGraphqlSourceBindings(ctx, sourceId, sourceScope),
|
|
1438
|
-
setSourceBinding: (input) => Effect5.gen(function* () {
|
|
1439
|
-
yield* validateGraphqlBindingTarget(ctx, {
|
|
1440
|
-
sourceId: input.sourceId,
|
|
1441
|
-
sourceScope: input.sourceScope,
|
|
1442
|
-
targetScope: input.scope
|
|
1443
|
-
});
|
|
1444
|
-
const binding = yield* ctx.credentialBindings.set({
|
|
1445
|
-
targetScope: input.scope,
|
|
1446
|
-
pluginId: GRAPHQL_PLUGIN_ID,
|
|
1447
|
-
sourceId: input.sourceId,
|
|
1448
|
-
sourceScope: input.sourceScope,
|
|
1449
|
-
slotKey: input.slot,
|
|
1450
|
-
value: input.value
|
|
1451
|
-
});
|
|
1452
|
-
return coreBindingToGraphqlBinding(binding);
|
|
1453
|
-
}),
|
|
1454
|
-
removeSourceBinding: (sourceId, sourceScope, slot, scope) => Effect5.gen(function* () {
|
|
1455
|
-
yield* validateGraphqlBindingTarget(ctx, {
|
|
1456
|
-
sourceId,
|
|
1457
|
-
sourceScope,
|
|
1458
|
-
targetScope: scope
|
|
1459
|
-
});
|
|
1460
|
-
yield* ctx.credentialBindings.remove({
|
|
1461
|
-
targetScope: ScopeId.make(scope),
|
|
1462
|
-
pluginId: GRAPHQL_PLUGIN_ID,
|
|
1463
|
-
sourceId,
|
|
1464
|
-
sourceScope: ScopeId.make(sourceScope),
|
|
1465
|
-
slotKey: slot
|
|
1466
|
-
});
|
|
1467
|
-
})
|
|
1341
|
+
configureSource,
|
|
1342
|
+
configure: (source, input) => configureSource(source.id, source.scope, input.scope, input)
|
|
1468
1343
|
};
|
|
1469
1344
|
};
|
|
1470
1345
|
var graphqlPlugin = definePlugin((options) => {
|
|
1471
1346
|
return {
|
|
1472
1347
|
id: "graphql",
|
|
1473
1348
|
packageName: "@executor-js/plugin-graphql",
|
|
1349
|
+
sourcePresets: graphqlPresets,
|
|
1474
1350
|
schema: graphqlSchema,
|
|
1475
1351
|
storage: (deps) => makeDefaultGraphqlStore(deps),
|
|
1476
1352
|
extension: (ctx) => makeGraphqlExtension(
|
|
@@ -1478,22 +1354,90 @@ var graphqlPlugin = definePlugin((options) => {
|
|
|
1478
1354
|
options?.httpClientLayer ?? ctx.httpClientLayer,
|
|
1479
1355
|
options?.configFile
|
|
1480
1356
|
),
|
|
1357
|
+
sourceConfigure: {
|
|
1358
|
+
type: "graphql",
|
|
1359
|
+
schema: SourceConfigureInputSchema,
|
|
1360
|
+
configure: ({ ctx, sourceId, sourceScope, targetScope, config }) => makeGraphqlExtension(
|
|
1361
|
+
ctx,
|
|
1362
|
+
options?.httpClientLayer ?? ctx.httpClientLayer,
|
|
1363
|
+
options?.configFile
|
|
1364
|
+
).configureSource(
|
|
1365
|
+
sourceId,
|
|
1366
|
+
sourceScope,
|
|
1367
|
+
targetScope,
|
|
1368
|
+
config
|
|
1369
|
+
)
|
|
1370
|
+
},
|
|
1481
1371
|
staticSources: (self) => [
|
|
1482
1372
|
{
|
|
1483
1373
|
id: "graphql",
|
|
1484
1374
|
kind: "executor",
|
|
1485
1375
|
name: "GraphQL",
|
|
1486
1376
|
tools: [
|
|
1377
|
+
tool({
|
|
1378
|
+
name: "getSource",
|
|
1379
|
+
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`.",
|
|
1380
|
+
inputSchema: StaticGetSourceInputStandardSchema,
|
|
1381
|
+
outputSchema: StaticGetSourceOutputStandardSchema,
|
|
1382
|
+
execute: (input, { ctx }) => Effect5.map(
|
|
1383
|
+
self.getSource(input.namespace, resolveStaticScopeInput(ctx, input.scope)),
|
|
1384
|
+
(source) => ToolResult.ok({ source })
|
|
1385
|
+
)
|
|
1386
|
+
}),
|
|
1487
1387
|
tool({
|
|
1488
1388
|
name: "addSource",
|
|
1489
|
-
description: "Add a GraphQL endpoint and register its operations as tools",
|
|
1389
|
+
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`.",
|
|
1490
1390
|
annotations: {
|
|
1491
1391
|
requiresApproval: true,
|
|
1492
1392
|
approvalDescription: "Add a GraphQL source"
|
|
1493
1393
|
},
|
|
1494
1394
|
inputSchema: StaticAddSourceInputStandardSchema,
|
|
1495
1395
|
outputSchema: StaticAddSourceOutputStandardSchema,
|
|
1496
|
-
execute: (input) =>
|
|
1396
|
+
execute: (input, { ctx }) => {
|
|
1397
|
+
const sourceScope = defaultSourceInstallScopeId(ctx.scopes);
|
|
1398
|
+
if (sourceScope === null) {
|
|
1399
|
+
return Effect5.succeed(
|
|
1400
|
+
graphqlToolFailure(
|
|
1401
|
+
"source_scope_unavailable",
|
|
1402
|
+
"Cannot add a GraphQL source because this executor has no source install scope."
|
|
1403
|
+
)
|
|
1404
|
+
);
|
|
1405
|
+
}
|
|
1406
|
+
return self.addSource({ ...input, scope: sourceScope }).pipe(
|
|
1407
|
+
Effect5.map(
|
|
1408
|
+
(result) => ToolResult.ok({
|
|
1409
|
+
...result,
|
|
1410
|
+
source: { id: result.namespace, scope: sourceScope }
|
|
1411
|
+
})
|
|
1412
|
+
),
|
|
1413
|
+
Effect5.catchTags({
|
|
1414
|
+
GraphqlIntrospectionError: ({ message }) => Effect5.succeed(graphqlToolFailure("graphql_introspection_failed", message)),
|
|
1415
|
+
GraphqlExtractionError: ({ message }) => Effect5.succeed(graphqlToolFailure("graphql_extraction_failed", message))
|
|
1416
|
+
})
|
|
1417
|
+
);
|
|
1418
|
+
}
|
|
1419
|
+
}),
|
|
1420
|
+
tool({
|
|
1421
|
+
name: "configureSource",
|
|
1422
|
+
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}`.',
|
|
1423
|
+
annotations: {
|
|
1424
|
+
requiresApproval: true,
|
|
1425
|
+
approvalDescription: "Configure a GraphQL source"
|
|
1426
|
+
},
|
|
1427
|
+
inputSchema: StaticConfigureSourceInputStandardSchema,
|
|
1428
|
+
outputSchema: StaticConfigureSourceOutputStandardSchema,
|
|
1429
|
+
execute: (input, { ctx }) => {
|
|
1430
|
+
const { source, ...config } = input;
|
|
1431
|
+
const sourceScope = resolveStaticScopeInput(ctx, source.scope);
|
|
1432
|
+
const targetScope = resolveStaticScopeInput(ctx, config.scope);
|
|
1433
|
+
return Effect5.as(
|
|
1434
|
+
self.configure(
|
|
1435
|
+
{ id: source.id, scope: sourceScope },
|
|
1436
|
+
{ ...config, scope: targetScope }
|
|
1437
|
+
),
|
|
1438
|
+
ToolResult.ok({ configured: true })
|
|
1439
|
+
);
|
|
1440
|
+
}
|
|
1497
1441
|
})
|
|
1498
1442
|
]
|
|
1499
1443
|
}
|
|
@@ -1505,27 +1449,27 @@ var graphqlPlugin = definePlugin((options) => {
|
|
|
1505
1449
|
if (!op) {
|
|
1506
1450
|
return yield* new GraphqlInvocationError({
|
|
1507
1451
|
message: `No GraphQL operation found for tool "${toolRow.id}"`,
|
|
1508
|
-
statusCode:
|
|
1452
|
+
statusCode: Option5.none()
|
|
1509
1453
|
});
|
|
1510
1454
|
}
|
|
1511
1455
|
const source = yield* ctx.storage.getSource(op.sourceId, toolScope);
|
|
1512
1456
|
if (!source) {
|
|
1513
1457
|
return yield* new GraphqlInvocationError({
|
|
1514
1458
|
message: `No GraphQL source found for "${op.sourceId}"`,
|
|
1515
|
-
statusCode:
|
|
1459
|
+
statusCode: Option5.none()
|
|
1516
1460
|
});
|
|
1517
1461
|
}
|
|
1518
1462
|
const resolvedHeaders = (yield* resolveGraphqlBindingValueMap(ctx, source.headers, {
|
|
1519
1463
|
sourceId: source.namespace,
|
|
1520
1464
|
sourceScope: source.scope,
|
|
1521
1465
|
missingLabel: "header",
|
|
1522
|
-
makeError: (message) => new GraphqlInvocationError({ message, statusCode:
|
|
1466
|
+
makeError: (message) => new GraphqlInvocationError({ message, statusCode: Option5.none() })
|
|
1523
1467
|
})) ?? {};
|
|
1524
1468
|
const resolvedQueryParams = (yield* resolveGraphqlBindingValueMap(ctx, source.queryParams, {
|
|
1525
1469
|
sourceId: source.namespace,
|
|
1526
1470
|
sourceScope: source.scope,
|
|
1527
1471
|
missingLabel: "query parameter",
|
|
1528
|
-
makeError: (message) => new GraphqlInvocationError({ message, statusCode:
|
|
1472
|
+
makeError: (message) => new GraphqlInvocationError({ message, statusCode: Option5.none() })
|
|
1529
1473
|
})) ?? {};
|
|
1530
1474
|
const oauthHeader = yield* resolveGraphqlStoredOAuthHeader(
|
|
1531
1475
|
ctx,
|
|
@@ -1542,7 +1486,28 @@ var graphqlPlugin = definePlugin((options) => {
|
|
|
1542
1486
|
resolvedQueryParams,
|
|
1543
1487
|
httpClientLayer
|
|
1544
1488
|
);
|
|
1545
|
-
|
|
1489
|
+
const errors = decodeGraphqlErrors(result.errors);
|
|
1490
|
+
if (errors !== void 0 && errors.length > 0) {
|
|
1491
|
+
const firstMessage = extractGraphqlErrorMessage(errors);
|
|
1492
|
+
return ToolResult.fail({
|
|
1493
|
+
code: "graphql_errors",
|
|
1494
|
+
message: firstMessage !== void 0 ? firstMessage : "GraphQL request returned errors",
|
|
1495
|
+
details: { errors }
|
|
1496
|
+
});
|
|
1497
|
+
}
|
|
1498
|
+
if (result.status < 200 || result.status >= 300) {
|
|
1499
|
+
return ToolResult.fail({
|
|
1500
|
+
code: "graphql_http_error",
|
|
1501
|
+
status: result.status,
|
|
1502
|
+
message: `GraphQL request failed with HTTP ${result.status}`,
|
|
1503
|
+
details: {
|
|
1504
|
+
status: result.status,
|
|
1505
|
+
data: result.data,
|
|
1506
|
+
errors: result.errors
|
|
1507
|
+
}
|
|
1508
|
+
});
|
|
1509
|
+
}
|
|
1510
|
+
return ToolResult.ok(result.data);
|
|
1546
1511
|
}),
|
|
1547
1512
|
resolveAnnotations: ({ ctx, sourceId, toolRows }) => Effect5.gen(function* () {
|
|
1548
1513
|
const scopes = /* @__PURE__ */ new Set();
|
|
@@ -1592,7 +1557,7 @@ var graphqlPlugin = definePlugin((options) => {
|
|
|
1592
1557
|
try: () => new URL(trimmed),
|
|
1593
1558
|
catch: (cause) => cause
|
|
1594
1559
|
}).pipe(Effect5.option);
|
|
1595
|
-
if (
|
|
1560
|
+
if (Option5.isNone(parsed)) return null;
|
|
1596
1561
|
const ok = yield* introspect(trimmed).pipe(
|
|
1597
1562
|
Effect5.provide(httpClientLayer),
|
|
1598
1563
|
Effect5.map(() => true),
|
|
@@ -1633,4 +1598,4 @@ export {
|
|
|
1633
1598
|
makeDefaultGraphqlStore,
|
|
1634
1599
|
graphqlPlugin
|
|
1635
1600
|
};
|
|
1636
|
-
//# sourceMappingURL=chunk-
|
|
1601
|
+
//# sourceMappingURL=chunk-7S2FM3ZF.js.map
|