@executor-js/plugin-graphql 0.1.0 → 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (37) hide show
  1. package/dist/AddGraphqlSource-LGXJQEAR.js +239 -0
  2. package/dist/AddGraphqlSource-LGXJQEAR.js.map +1 -0
  3. package/dist/EditGraphqlSource-5Y47ZAZ7.js +251 -0
  4. package/dist/EditGraphqlSource-5Y47ZAZ7.js.map +1 -0
  5. package/dist/GraphqlSourceSummary-F3JWR4YN.js +70 -0
  6. package/dist/GraphqlSourceSummary-F3JWR4YN.js.map +1 -0
  7. package/dist/api/group.d.ts +169 -13
  8. package/dist/api/handlers.d.ts +15 -3
  9. package/dist/api/index.d.ts +410 -0
  10. package/dist/chunk-7QSGNR4C.js +162 -0
  11. package/dist/chunk-7QSGNR4C.js.map +1 -0
  12. package/dist/chunk-HDPYOBBG.js +1633 -0
  13. package/dist/chunk-HDPYOBBG.js.map +1 -0
  14. package/dist/chunk-M4SJY6CB.js +45 -0
  15. package/dist/chunk-M4SJY6CB.js.map +1 -0
  16. package/dist/chunk-WPRU5C6M.js +182 -0
  17. package/dist/chunk-WPRU5C6M.js.map +1 -0
  18. package/dist/client.js +75 -0
  19. package/dist/client.js.map +1 -0
  20. package/dist/core.js +32 -10
  21. package/dist/index.js +2 -1
  22. package/dist/react/GraphqlSourceFields.d.ts +8 -0
  23. package/dist/react/GraphqlSourceSummary.d.ts +3 -1
  24. package/dist/react/atoms.d.ts +170 -10
  25. package/dist/react/client.d.ts +164 -12
  26. package/dist/sdk/index.d.ts +1 -1
  27. package/dist/sdk/introspect.d.ts +437 -43
  28. package/dist/sdk/invoke.d.ts +3 -2
  29. package/dist/sdk/plugin.d.ts +120 -170
  30. package/dist/sdk/store.d.ts +84 -11
  31. package/dist/sdk/types.d.ts +107 -3
  32. package/dist/testing/index.d.ts +52 -0
  33. package/dist/testing.js +131 -0
  34. package/dist/testing.js.map +1 -0
  35. package/package.json +18 -4
  36. package/dist/chunk-EIC5WI6C.js +0 -1225
  37. package/dist/chunk-EIC5WI6C.js.map +0 -1
@@ -1,1225 +0,0 @@
1
- // src/sdk/errors.ts
2
- import { Data, Schema } from "effect";
3
- var GraphqlIntrospectionError = class extends Schema.TaggedErrorClass()(
4
- "GraphqlIntrospectionError",
5
- {
6
- message: Schema.String
7
- }
8
- ) {
9
- };
10
- var GraphqlExtractionError = class extends Schema.TaggedErrorClass()(
11
- "GraphqlExtractionError",
12
- {
13
- message: Schema.String
14
- }
15
- ) {
16
- };
17
- var GraphqlInvocationError = class extends Data.TaggedError("GraphqlInvocationError") {
18
- };
19
-
20
- // src/sdk/types.ts
21
- import { Effect, Schema as Schema2 } from "effect";
22
- import { SecretBackedValue } from "@executor-js/sdk/core";
23
- var GraphqlOperationKind = Schema2.Literals(["query", "mutation"]);
24
- var GraphqlArgument = class extends Schema2.Class("GraphqlArgument")({
25
- name: Schema2.String,
26
- typeName: Schema2.String,
27
- required: Schema2.Boolean,
28
- description: Schema2.OptionFromOptional(Schema2.String)
29
- }) {
30
- };
31
- var ExtractedField = class extends Schema2.Class("ExtractedField")({
32
- /** e.g. "user", "createUser" */
33
- fieldName: Schema2.String,
34
- /** "query" or "mutation" */
35
- kind: GraphqlOperationKind,
36
- description: Schema2.OptionFromOptional(Schema2.String),
37
- arguments: Schema2.Array(GraphqlArgument),
38
- /** JSON Schema for the input (built from arguments) */
39
- inputSchema: Schema2.OptionFromOptional(Schema2.Unknown),
40
- /** The return type name for documentation */
41
- returnTypeName: Schema2.String
42
- }) {
43
- };
44
- var ExtractionResult = class extends Schema2.Class("ExtractionResult")({
45
- /** Schema name from introspection */
46
- schemaName: Schema2.OptionFromOptional(Schema2.String),
47
- fields: Schema2.Array(ExtractedField)
48
- }) {
49
- };
50
- var OperationBinding = class extends Schema2.Class("OperationBinding")({
51
- kind: GraphqlOperationKind,
52
- fieldName: Schema2.String,
53
- /** The full GraphQL query/mutation string */
54
- operationString: Schema2.String,
55
- /** Ordered variable names for mapping */
56
- variableNames: Schema2.Array(Schema2.String)
57
- }) {
58
- };
59
- var HeaderValue = SecretBackedValue;
60
- var QueryParamValue = HeaderValue;
61
- var GraphqlSourceAuth = Schema2.Union(
62
- [
63
- Schema2.Struct({ kind: Schema2.Literal("none") }),
64
- Schema2.Struct({
65
- kind: Schema2.Literal("oauth2"),
66
- connectionId: Schema2.String
67
- })
68
- ]
69
- );
70
- var InvocationConfig = class extends Schema2.Class("InvocationConfig")({
71
- /** The GraphQL endpoint URL */
72
- endpoint: Schema2.String,
73
- /** Headers applied to every request. Values can reference secrets. */
74
- headers: Schema2.Record(Schema2.String, HeaderValue).pipe(
75
- Schema2.withDecodingDefault(Effect.succeed({})),
76
- Schema2.withConstructorDefault(Effect.succeed({}))
77
- ),
78
- /** Query parameters applied to every request. Values can reference secrets. */
79
- queryParams: Schema2.Record(Schema2.String, QueryParamValue).pipe(
80
- Schema2.withDecodingDefault(Effect.succeed({})),
81
- Schema2.withConstructorDefault(Effect.succeed({}))
82
- )
83
- }) {
84
- };
85
- var InvocationResult = class extends Schema2.Class("InvocationResult")({
86
- status: Schema2.Number,
87
- data: Schema2.NullOr(Schema2.Unknown),
88
- errors: Schema2.NullOr(Schema2.Unknown)
89
- }) {
90
- };
91
-
92
- // src/sdk/introspect.ts
93
- import { Effect as Effect2 } from "effect";
94
- import { HttpClient, HttpClientRequest } from "effect/unstable/http";
95
- var INTROSPECTION_QUERY = `
96
- query IntrospectionQuery {
97
- __schema {
98
- queryType { name }
99
- mutationType { name }
100
- types {
101
- kind
102
- name
103
- description
104
- fields(includeDeprecated: false) {
105
- name
106
- description
107
- args {
108
- name
109
- description
110
- type {
111
- ...TypeRef
112
- }
113
- defaultValue
114
- }
115
- type {
116
- ...TypeRef
117
- }
118
- }
119
- inputFields {
120
- name
121
- description
122
- type {
123
- ...TypeRef
124
- }
125
- defaultValue
126
- }
127
- enumValues(includeDeprecated: false) {
128
- name
129
- description
130
- }
131
- }
132
- }
133
- }
134
-
135
- fragment TypeRef on __Type {
136
- kind
137
- name
138
- ofType {
139
- kind
140
- name
141
- ofType {
142
- kind
143
- name
144
- ofType {
145
- kind
146
- name
147
- ofType {
148
- kind
149
- name
150
- ofType {
151
- kind
152
- name
153
- ofType {
154
- kind
155
- name
156
- }
157
- }
158
- }
159
- }
160
- }
161
- }
162
- }
163
- `;
164
- var introspect = Effect2.fn("GraphQL.introspect")(function* (endpoint, headers, queryParams) {
165
- const client = yield* HttpClient.HttpClient;
166
- const requestEndpoint = queryParams && Object.keys(queryParams).length > 0 ? (() => {
167
- const url = new URL(endpoint);
168
- for (const [name, value] of Object.entries(queryParams)) {
169
- url.searchParams.set(name, value);
170
- }
171
- return url.toString();
172
- })() : endpoint;
173
- let request = HttpClientRequest.post(requestEndpoint).pipe(
174
- HttpClientRequest.setHeader("Content-Type", "application/json"),
175
- HttpClientRequest.bodyJsonUnsafe({
176
- query: INTROSPECTION_QUERY
177
- })
178
- );
179
- if (headers) {
180
- for (const [k, v] of Object.entries(headers)) {
181
- request = HttpClientRequest.setHeader(request, k, v);
182
- }
183
- }
184
- const response = yield* client.execute(request).pipe(
185
- Effect2.tapCause((cause) => Effect2.logError("graphql introspection request failed", cause)),
186
- Effect2.mapError(
187
- (err) => new GraphqlIntrospectionError({
188
- message: `Failed to reach GraphQL endpoint: ${err.message}`
189
- })
190
- )
191
- );
192
- if (response.status !== 200) {
193
- return yield* new GraphqlIntrospectionError({
194
- message: `Introspection failed with status ${response.status}`
195
- });
196
- }
197
- const raw = yield* response.json.pipe(
198
- Effect2.tapCause(
199
- (cause) => Effect2.logError("graphql introspection JSON parse failed", cause)
200
- ),
201
- Effect2.mapError(
202
- () => new GraphqlIntrospectionError({
203
- message: `Failed to parse introspection response as JSON`
204
- })
205
- )
206
- );
207
- const json = raw;
208
- if (json.errors && Array.isArray(json.errors) && json.errors.length > 0) {
209
- return yield* new GraphqlIntrospectionError({
210
- message: `Introspection returned ${json.errors.length} error(s)`
211
- });
212
- }
213
- if (!json.data?.__schema) {
214
- return yield* new GraphqlIntrospectionError({
215
- message: "Introspection response missing __schema"
216
- });
217
- }
218
- return json.data;
219
- });
220
- var parseIntrospectionJson = (text) => Effect2.try({
221
- try: () => {
222
- const parsed = JSON.parse(text);
223
- const result = parsed.data ?? parsed;
224
- if (!result.__schema) {
225
- throw new Error("Missing __schema in introspection JSON");
226
- }
227
- return result;
228
- },
229
- catch: (err) => new GraphqlIntrospectionError({
230
- message: `Failed to parse introspection JSON: ${err instanceof Error ? err.message : String(err)}`
231
- })
232
- });
233
-
234
- // src/sdk/extract.ts
235
- import { Effect as Effect3, Option } from "effect";
236
- var unwrapTypeName = (ref) => {
237
- if (ref.name) return ref.name;
238
- if (ref.ofType) return unwrapTypeName(ref.ofType);
239
- return "Unknown";
240
- };
241
- var isNonNull = (ref) => ref.kind === "NON_NULL";
242
- var buildDefinitions = (types) => {
243
- const defs = {};
244
- for (const [name, type] of types) {
245
- if (name.startsWith("__")) continue;
246
- if (type.kind === "INPUT_OBJECT" && type.inputFields) {
247
- const properties = {};
248
- const required = [];
249
- for (const field of type.inputFields) {
250
- const schema = typeRefToJsonSchema(field.type, types);
251
- if (field.description) {
252
- schema.description = field.description;
253
- }
254
- properties[field.name] = schema;
255
- if (isNonNull(field.type)) {
256
- required.push(field.name);
257
- }
258
- }
259
- const def = { type: "object", properties };
260
- if (required.length > 0) def.required = required;
261
- if (type.description) def.description = type.description;
262
- defs[name] = def;
263
- }
264
- if (type.kind === "ENUM" && type.enumValues) {
265
- defs[name] = {
266
- type: "string",
267
- enum: type.enumValues.map((v) => v.name),
268
- ...type.description ? { description: type.description } : {}
269
- };
270
- }
271
- }
272
- return defs;
273
- };
274
- var typeRefToJsonSchema = (ref, types) => {
275
- switch (ref.kind) {
276
- case "NON_NULL":
277
- return ref.ofType ? typeRefToJsonSchema(ref.ofType, types) : {};
278
- case "LIST":
279
- return {
280
- type: "array",
281
- items: ref.ofType ? typeRefToJsonSchema(ref.ofType, types) : {}
282
- };
283
- case "SCALAR":
284
- return scalarToJsonSchema(ref.name ?? "String");
285
- case "ENUM":
286
- return ref.name ? { $ref: `#/$defs/${ref.name}` } : { type: "string" };
287
- case "INPUT_OBJECT":
288
- return ref.name ? { $ref: `#/$defs/${ref.name}` } : { type: "object" };
289
- case "OBJECT":
290
- case "INTERFACE":
291
- case "UNION":
292
- return { type: "object" };
293
- default:
294
- return {};
295
- }
296
- };
297
- var scalarToJsonSchema = (name) => {
298
- switch (name) {
299
- case "String":
300
- case "ID":
301
- return { type: "string" };
302
- case "Int":
303
- return { type: "integer" };
304
- case "Float":
305
- return { type: "number" };
306
- case "Boolean":
307
- return { type: "boolean" };
308
- default:
309
- return { type: "string", description: `Custom scalar: ${name}` };
310
- }
311
- };
312
- var buildInputSchema = (args, types) => {
313
- if (args.length === 0) return void 0;
314
- const properties = {};
315
- const required = [];
316
- for (const arg of args) {
317
- const schema = typeRefToJsonSchema(arg.type, types);
318
- if (arg.description) {
319
- schema.description = arg.description;
320
- }
321
- properties[arg.name] = schema;
322
- if (isNonNull(arg.type)) {
323
- required.push(arg.name);
324
- }
325
- }
326
- const inputSchema = {
327
- type: "object",
328
- properties
329
- };
330
- if (required.length > 0) inputSchema.required = required;
331
- return inputSchema;
332
- };
333
- var formatTypeRef = (ref) => {
334
- switch (ref.kind) {
335
- case "NON_NULL":
336
- return ref.ofType ? `${formatTypeRef(ref.ofType)}!` : "Unknown!";
337
- case "LIST":
338
- return ref.ofType ? `[${formatTypeRef(ref.ofType)}]` : "[Unknown]";
339
- default:
340
- return ref.name ?? "Unknown";
341
- }
342
- };
343
- var extractFields = (_schema, kind, typeName, types) => {
344
- if (!typeName) return [];
345
- const type = types.get(typeName);
346
- if (!type?.fields) return [];
347
- return type.fields.filter((f) => !f.name.startsWith("__")).map((field) => {
348
- const args = field.args.map(
349
- (arg) => new GraphqlArgument({
350
- name: arg.name,
351
- typeName: formatTypeRef(arg.type),
352
- required: isNonNull(arg.type),
353
- description: arg.description ? Option.some(arg.description) : Option.none()
354
- })
355
- );
356
- const inputSchema = buildInputSchema(field.args, types);
357
- return new ExtractedField({
358
- fieldName: field.name,
359
- kind,
360
- description: field.description ? Option.some(field.description) : Option.none(),
361
- arguments: args,
362
- inputSchema: inputSchema ? Option.some(inputSchema) : Option.none(),
363
- returnTypeName: unwrapTypeName(field.type)
364
- });
365
- });
366
- };
367
- var extract = (introspection) => Effect3.try({
368
- try: () => {
369
- const schema = introspection.__schema;
370
- const typeMap = /* @__PURE__ */ new Map();
371
- for (const t of schema.types) {
372
- typeMap.set(t.name, t);
373
- }
374
- const definitions = buildDefinitions(typeMap);
375
- const queryFields = extractFields(schema, "query", schema.queryType?.name, typeMap);
376
- const mutationFields = extractFields(schema, "mutation", schema.mutationType?.name, typeMap);
377
- return {
378
- result: new ExtractionResult({
379
- schemaName: Option.none(),
380
- fields: [...queryFields, ...mutationFields]
381
- }),
382
- definitions
383
- };
384
- },
385
- catch: (err) => new GraphqlExtractionError({
386
- message: `Failed to extract GraphQL schema: ${err instanceof Error ? err.message : String(err)}`
387
- })
388
- });
389
-
390
- // src/sdk/invoke.ts
391
- import { Effect as Effect4, Option as Option2 } from "effect";
392
- import { HttpClient as HttpClient2, HttpClientRequest as HttpClientRequest2 } from "effect/unstable/http";
393
- import { resolveSecretBackedMap } from "@executor-js/sdk/core";
394
- var resolveHeaders = (headers, secrets) => {
395
- const entries = Object.entries(headers);
396
- const secretCount = entries.reduce(
397
- (acc, [, value]) => typeof value === "string" ? acc : acc + 1,
398
- 0
399
- );
400
- return resolveSecretBackedMap({
401
- values: headers,
402
- getSecret: (secretId) => secrets.get(secretId).pipe(Effect4.catch(() => Effect4.succeed(null))),
403
- missing: "drop",
404
- onMissing: (name) => new GraphqlInvocationError({
405
- message: `Missing secret for header "${name}"`,
406
- statusCode: Option2.none()
407
- })
408
- }).pipe(
409
- Effect4.catch(() => Effect4.succeed(void 0)),
410
- Effect4.map((resolved) => resolved ?? {}),
411
- Effect4.withSpan("plugin.graphql.secret.resolve", {
412
- attributes: {
413
- "plugin.graphql.headers.total": entries.length,
414
- "plugin.graphql.headers.secret_count": secretCount
415
- }
416
- })
417
- );
418
- };
419
- var endpointWithQueryParams = (endpoint, queryParams) => {
420
- if (Object.keys(queryParams).length === 0) return endpoint;
421
- const url = new URL(endpoint);
422
- for (const [name, value] of Object.entries(queryParams)) {
423
- url.searchParams.set(name, value);
424
- }
425
- return url.toString();
426
- };
427
- var isJsonContentType = (ct) => {
428
- if (!ct) return false;
429
- const normalized = ct.split(";")[0]?.trim().toLowerCase() ?? "";
430
- return normalized === "application/json" || normalized.includes("+json") || normalized.includes("json");
431
- };
432
- var invoke = Effect4.fn("GraphQL.invoke")(function* (operation, args, endpoint, resolvedHeaders, resolvedQueryParams = {}) {
433
- const client = yield* HttpClient2.HttpClient;
434
- const requestEndpoint = endpointWithQueryParams(endpoint, resolvedQueryParams);
435
- yield* Effect4.annotateCurrentSpan({
436
- "http.method": "POST",
437
- "http.url": requestEndpoint,
438
- "plugin.graphql.endpoint": endpoint,
439
- "plugin.graphql.operation_kind": operation.kind,
440
- "plugin.graphql.field_name": operation.fieldName,
441
- "plugin.graphql.headers.resolved_count": Object.keys(resolvedHeaders).length,
442
- "plugin.graphql.query_params.resolved_count": Object.keys(resolvedQueryParams).length
443
- });
444
- const variables = {};
445
- for (const varName of operation.variableNames) {
446
- if (args[varName] !== void 0) {
447
- variables[varName] = args[varName];
448
- }
449
- }
450
- if (typeof args.variables === "object" && args.variables !== null) {
451
- Object.assign(variables, args.variables);
452
- }
453
- let request = HttpClientRequest2.post(requestEndpoint).pipe(
454
- HttpClientRequest2.setHeader("Content-Type", "application/json"),
455
- HttpClientRequest2.bodyJsonUnsafe({
456
- query: operation.operationString,
457
- variables: Object.keys(variables).length > 0 ? variables : void 0
458
- })
459
- );
460
- for (const [name, value] of Object.entries(resolvedHeaders)) {
461
- request = HttpClientRequest2.setHeader(request, name, value);
462
- }
463
- const response = yield* client.execute(request).pipe(
464
- Effect4.mapError(
465
- (err) => new GraphqlInvocationError({
466
- message: `GraphQL request failed: ${err.message}`,
467
- statusCode: Option2.none(),
468
- cause: err
469
- })
470
- )
471
- );
472
- const status = response.status;
473
- const contentType = response.headers["content-type"] ?? null;
474
- const body = isJsonContentType(contentType) ? yield* response.json.pipe(Effect4.catch(() => response.text)) : yield* response.text;
475
- const gqlBody = body;
476
- const hasErrors = Array.isArray(gqlBody?.errors) && gqlBody.errors.length > 0;
477
- yield* Effect4.annotateCurrentSpan({
478
- "http.status_code": status,
479
- "plugin.graphql.has_errors": hasErrors,
480
- "plugin.graphql.error_count": hasErrors ? gqlBody.errors.length : 0
481
- });
482
- return new InvocationResult({
483
- status,
484
- data: gqlBody?.data ?? null,
485
- errors: hasErrors ? gqlBody.errors : null
486
- });
487
- });
488
- var invokeWithLayer = (operation, args, endpoint, resolvedHeaders, resolvedQueryParams, httpClientLayer) => invoke(operation, args, endpoint, resolvedHeaders, resolvedQueryParams).pipe(
489
- Effect4.provide(httpClientLayer),
490
- Effect4.mapError(
491
- (err) => err instanceof GraphqlInvocationError ? err : new GraphqlInvocationError({
492
- message: err instanceof Error ? err.message : String(err),
493
- statusCode: Option2.none(),
494
- cause: err
495
- })
496
- ),
497
- Effect4.withSpan("plugin.graphql.invoke", {
498
- attributes: {
499
- "plugin.graphql.endpoint": endpoint,
500
- "plugin.graphql.operation_kind": operation.kind,
501
- "plugin.graphql.field_name": operation.fieldName
502
- }
503
- })
504
- );
505
-
506
- // src/sdk/store.ts
507
- import { Effect as Effect5 } from "effect";
508
- import {
509
- defineSchema
510
- } from "@executor-js/sdk/core";
511
- var graphqlSchema = defineSchema({
512
- graphql_source: {
513
- fields: {
514
- id: { type: "string", required: true },
515
- scope_id: { type: "string", required: true, index: true },
516
- name: { type: "string", required: true },
517
- endpoint: { type: "string", required: true },
518
- headers: { type: "json", required: false },
519
- query_params: { type: "json", required: false },
520
- auth: { type: "json", required: false }
521
- }
522
- },
523
- graphql_operation: {
524
- fields: {
525
- id: { type: "string", required: true },
526
- scope_id: { type: "string", required: true, index: true },
527
- source_id: { type: "string", required: true, index: true },
528
- binding: { type: "json", required: true }
529
- }
530
- }
531
- });
532
- var decodeBinding = (value) => {
533
- const data = typeof value === "string" ? JSON.parse(value) : value;
534
- return new OperationBinding({
535
- kind: data.kind,
536
- fieldName: data.fieldName,
537
- operationString: data.operationString,
538
- variableNames: [...data.variableNames]
539
- });
540
- };
541
- var encodeBinding = (binding) => ({
542
- kind: binding.kind,
543
- fieldName: binding.fieldName,
544
- operationString: binding.operationString,
545
- variableNames: [...binding.variableNames]
546
- });
547
- var toJsonRecord = (value) => value;
548
- var decodeHeaders = (value) => {
549
- if (value == null) return {};
550
- if (typeof value === "string")
551
- return JSON.parse(value);
552
- return value;
553
- };
554
- var decodeQueryParams = (value) => {
555
- if (value == null) return {};
556
- if (typeof value === "string")
557
- return JSON.parse(value);
558
- return value;
559
- };
560
- var decodeAuth = (value) => {
561
- if (value == null) return { kind: "none" };
562
- const parsed = typeof value === "string" ? JSON.parse(value) : value;
563
- return parsed?.kind === "oauth2" && typeof parsed.connectionId === "string" ? { kind: "oauth2", connectionId: parsed.connectionId } : { kind: "none" };
564
- };
565
- var makeDefaultGraphqlStore = ({
566
- adapter: db
567
- }) => {
568
- const rowToSource = (row) => ({
569
- namespace: row.id,
570
- scope: row.scope_id,
571
- name: row.name,
572
- endpoint: row.endpoint,
573
- headers: decodeHeaders(row.headers),
574
- queryParams: decodeQueryParams(row.query_params),
575
- auth: decodeAuth(row.auth)
576
- });
577
- const rowToOperation = (row) => ({
578
- toolId: row.id,
579
- sourceId: row.source_id,
580
- binding: decodeBinding(row.binding)
581
- });
582
- const deleteSource = (namespace, scope) => Effect5.gen(function* () {
583
- yield* db.deleteMany({
584
- model: "graphql_operation",
585
- where: [
586
- { field: "source_id", value: namespace },
587
- { field: "scope_id", value: scope }
588
- ]
589
- });
590
- yield* db.delete({
591
- model: "graphql_source",
592
- where: [
593
- { field: "id", value: namespace },
594
- { field: "scope_id", value: scope }
595
- ]
596
- });
597
- });
598
- return {
599
- upsertSource: (input, operations) => Effect5.gen(function* () {
600
- yield* deleteSource(input.namespace, input.scope);
601
- yield* db.create({
602
- model: "graphql_source",
603
- data: {
604
- id: input.namespace,
605
- scope_id: input.scope,
606
- name: input.name,
607
- endpoint: input.endpoint,
608
- headers: input.headers,
609
- query_params: input.queryParams,
610
- auth: toJsonRecord(input.auth)
611
- },
612
- forceAllowId: true
613
- });
614
- if (operations.length > 0) {
615
- yield* db.createMany({
616
- model: "graphql_operation",
617
- data: operations.map((op) => ({
618
- id: op.toolId,
619
- scope_id: input.scope,
620
- source_id: op.sourceId,
621
- binding: toJsonRecord(encodeBinding(op.binding))
622
- })),
623
- forceAllowId: true
624
- });
625
- }
626
- }),
627
- updateSourceMeta: (namespace, scope, patch) => Effect5.gen(function* () {
628
- const existing = yield* db.findOne({
629
- model: "graphql_source",
630
- where: [
631
- { field: "id", value: namespace },
632
- { field: "scope_id", value: scope }
633
- ]
634
- });
635
- if (!existing) return;
636
- const update = {};
637
- if (patch.name !== void 0) update.name = patch.name;
638
- if (patch.endpoint !== void 0) update.endpoint = patch.endpoint;
639
- if (patch.headers !== void 0) {
640
- update.headers = patch.headers;
641
- }
642
- if (patch.queryParams !== void 0) {
643
- update.query_params = patch.queryParams;
644
- }
645
- if (patch.auth !== void 0) {
646
- update.auth = toJsonRecord(patch.auth);
647
- }
648
- if (Object.keys(update).length === 0) return;
649
- yield* db.update({
650
- model: "graphql_source",
651
- where: [
652
- { field: "id", value: namespace },
653
- { field: "scope_id", value: scope }
654
- ],
655
- update
656
- });
657
- }),
658
- getSource: (namespace, scope) => db.findOne({
659
- model: "graphql_source",
660
- where: [
661
- { field: "id", value: namespace },
662
- { field: "scope_id", value: scope }
663
- ]
664
- }).pipe(Effect5.map((row) => row ? rowToSource(row) : null)),
665
- listSources: () => db.findMany({ model: "graphql_source" }).pipe(Effect5.map((rows) => rows.map(rowToSource))),
666
- getOperationByToolId: (toolId, scope) => db.findOne({
667
- model: "graphql_operation",
668
- where: [
669
- { field: "id", value: toolId },
670
- { field: "scope_id", value: scope }
671
- ]
672
- }).pipe(Effect5.map((row) => row ? rowToOperation(row) : null)),
673
- listOperationsBySource: (sourceId, scope) => db.findMany({
674
- model: "graphql_operation",
675
- where: [
676
- { field: "source_id", value: sourceId },
677
- { field: "scope_id", value: scope }
678
- ]
679
- }).pipe(Effect5.map((rows) => rows.map(rowToOperation))),
680
- removeSource: (namespace, scope) => deleteSource(namespace, scope)
681
- };
682
- };
683
-
684
- // src/sdk/plugin.ts
685
- import { Effect as Effect7, Option as Option3 } from "effect";
686
- import { FetchHttpClient } from "effect/unstable/http";
687
-
688
- // src/api/group.ts
689
- import { HttpApiEndpoint, HttpApiGroup } from "effect/unstable/httpapi";
690
- import { Schema as Schema3 } from "effect";
691
- import { ScopeId } from "@executor-js/sdk/core";
692
- import { InternalError } from "@executor-js/api";
693
- var StoredSourceSchema = Schema3.Struct({
694
- namespace: Schema3.String,
695
- name: Schema3.String,
696
- endpoint: Schema3.String,
697
- headers: Schema3.Record(Schema3.String, HeaderValue),
698
- queryParams: Schema3.Record(Schema3.String, HeaderValue),
699
- auth: GraphqlSourceAuth
700
- });
701
- var ScopeParams = {
702
- scopeId: ScopeId
703
- };
704
- var SourceParams = {
705
- scopeId: ScopeId,
706
- namespace: Schema3.String
707
- };
708
- var AddSourcePayload = Schema3.Struct({
709
- endpoint: Schema3.String,
710
- name: Schema3.optional(Schema3.String),
711
- introspectionJson: Schema3.optional(Schema3.String),
712
- namespace: Schema3.optional(Schema3.String),
713
- headers: Schema3.optional(Schema3.Record(Schema3.String, Schema3.Unknown)),
714
- queryParams: Schema3.optional(Schema3.Record(Schema3.String, Schema3.Unknown)),
715
- auth: Schema3.optional(GraphqlSourceAuth)
716
- });
717
- var UpdateSourcePayload = Schema3.Struct({
718
- name: Schema3.optional(Schema3.String),
719
- endpoint: Schema3.optional(Schema3.String),
720
- headers: Schema3.optional(Schema3.Record(Schema3.String, Schema3.Unknown)),
721
- queryParams: Schema3.optional(Schema3.Record(Schema3.String, Schema3.Unknown)),
722
- auth: Schema3.optional(GraphqlSourceAuth)
723
- });
724
- var UpdateSourceResponse = Schema3.Struct({
725
- updated: Schema3.Boolean
726
- });
727
- var AddSourceResponse = Schema3.Struct({
728
- toolCount: Schema3.Number,
729
- namespace: Schema3.String
730
- });
731
- var IntrospectionError = GraphqlIntrospectionError.annotate(
732
- { httpApiStatus: 400 }
733
- );
734
- var ExtractionError = GraphqlExtractionError.annotate(
735
- { httpApiStatus: 400 }
736
- );
737
- var GraphqlErrors = [InternalError, IntrospectionError, ExtractionError];
738
- var GraphqlGroup = HttpApiGroup.make("graphql").add(
739
- HttpApiEndpoint.post("addSource", "/scopes/:scopeId/graphql/sources", {
740
- params: ScopeParams,
741
- payload: AddSourcePayload,
742
- success: AddSourceResponse,
743
- error: GraphqlErrors
744
- })
745
- ).add(
746
- HttpApiEndpoint.get("getSource", "/scopes/:scopeId/graphql/sources/:namespace", {
747
- params: SourceParams,
748
- success: Schema3.NullOr(StoredSourceSchema),
749
- error: GraphqlErrors
750
- })
751
- ).add(
752
- HttpApiEndpoint.patch("updateSource", "/scopes/:scopeId/graphql/sources/:namespace", {
753
- params: SourceParams,
754
- payload: UpdateSourcePayload,
755
- success: UpdateSourceResponse,
756
- error: GraphqlErrors
757
- })
758
- );
759
-
760
- // src/api/handlers.ts
761
- import { HttpApiBuilder } from "effect/unstable/httpapi";
762
- import { Context, Effect as Effect6 } from "effect";
763
- import { addGroup, capture } from "@executor-js/api";
764
- var GraphqlExtensionService = class extends Context.Service()("GraphqlExtensionService") {
765
- };
766
- var ExecutorApiWithGraphql = addGroup(GraphqlGroup);
767
- var GraphqlHandlers = HttpApiBuilder.group(
768
- ExecutorApiWithGraphql,
769
- "graphql",
770
- (handlers) => handlers.handle(
771
- "addSource",
772
- ({ params: path, payload }) => capture(
773
- Effect6.gen(function* () {
774
- const ext = yield* GraphqlExtensionService;
775
- const result = yield* ext.addSource({
776
- endpoint: payload.endpoint,
777
- scope: path.scopeId,
778
- name: payload.name,
779
- introspectionJson: payload.introspectionJson,
780
- namespace: payload.namespace,
781
- headers: payload.headers,
782
- queryParams: payload.queryParams,
783
- auth: payload.auth
784
- });
785
- return {
786
- toolCount: result.toolCount,
787
- namespace: result.namespace
788
- };
789
- })
790
- )
791
- ).handle(
792
- "getSource",
793
- ({ params: path }) => capture(
794
- Effect6.gen(function* () {
795
- const ext = yield* GraphqlExtensionService;
796
- return yield* ext.getSource(path.namespace, path.scopeId);
797
- })
798
- )
799
- ).handle(
800
- "updateSource",
801
- ({ params: path, payload }) => capture(
802
- Effect6.gen(function* () {
803
- const ext = yield* GraphqlExtensionService;
804
- yield* ext.updateSource(path.namespace, path.scopeId, {
805
- name: payload.name,
806
- endpoint: payload.endpoint,
807
- headers: payload.headers,
808
- queryParams: payload.queryParams,
809
- auth: payload.auth
810
- });
811
- return { updated: true };
812
- })
813
- )
814
- )
815
- );
816
-
817
- // src/sdk/plugin.ts
818
- import {
819
- definePlugin,
820
- SourceDetectionResult
821
- } from "@executor-js/sdk/core";
822
- import {
823
- headersToConfigValues
824
- } from "@executor-js/config";
825
- var namespaceFromEndpoint = (endpoint) => {
826
- try {
827
- const url = new URL(endpoint);
828
- return url.hostname.replace(/[^a-z0-9]+/gi, "_").toLowerCase();
829
- } catch {
830
- return "graphql";
831
- }
832
- };
833
- var formatTypeRef2 = (ref) => {
834
- switch (ref.kind) {
835
- case "NON_NULL":
836
- return ref.ofType ? `${formatTypeRef2(ref.ofType)}!` : "Unknown!";
837
- case "LIST":
838
- return ref.ofType ? `[${formatTypeRef2(ref.ofType)}]` : "[Unknown]";
839
- default:
840
- return ref.name ?? "Unknown";
841
- }
842
- };
843
- var unwrapTypeName2 = (ref) => {
844
- if (ref.name) return ref.name;
845
- if (ref.ofType) return unwrapTypeName2(ref.ofType);
846
- return "Unknown";
847
- };
848
- var buildSelectionSet = (ref, types, depth, seen) => {
849
- if (depth > 2) return "";
850
- const leafName = unwrapTypeName2(ref);
851
- if (seen.has(leafName)) return "";
852
- const objectType = types.get(leafName);
853
- if (!objectType?.fields) return "";
854
- const kind = objectType.kind;
855
- if (kind === "SCALAR" || kind === "ENUM") return "";
856
- seen.add(leafName);
857
- const subFields = objectType.fields.filter((f) => !f.name.startsWith("__")).slice(0, 12).map((f) => {
858
- const sub = buildSelectionSet(f.type, types, depth + 1, seen);
859
- return sub ? `${f.name} ${sub}` : f.name;
860
- });
861
- seen.delete(leafName);
862
- return subFields.length > 0 ? `{ ${subFields.join(" ")} }` : "";
863
- };
864
- var buildOperationStringForField = (kind, field, types) => {
865
- const opType = kind === "query" ? "query" : "mutation";
866
- const varDefs = field.args.map((arg) => {
867
- const typeName = formatTypeRef2(arg.type);
868
- return `$${arg.name}: ${typeName}`;
869
- });
870
- const argPasses = field.args.map((arg) => `${arg.name}: $${arg.name}`);
871
- const selectionSet = buildSelectionSet(field.type, types, 0, /* @__PURE__ */ new Set());
872
- const varDefsStr = varDefs.length > 0 ? `(${varDefs.join(", ")})` : "";
873
- const argPassStr = argPasses.length > 0 ? `(${argPasses.join(", ")})` : "";
874
- return `${opType}${varDefsStr} { ${field.name}${argPassStr}${selectionSet ? ` ${selectionSet}` : ""} }`;
875
- };
876
- var prepareOperations = (fields, introspection) => {
877
- const typeMap = /* @__PURE__ */ new Map();
878
- for (const t of introspection.__schema.types) {
879
- typeMap.set(t.name, t);
880
- }
881
- const fieldMap = /* @__PURE__ */ new Map();
882
- const schema = introspection.__schema;
883
- for (const rootKind of ["query", "mutation"]) {
884
- const typeName = rootKind === "query" ? schema.queryType?.name : schema.mutationType?.name;
885
- if (!typeName) continue;
886
- const rootType = typeMap.get(typeName);
887
- if (!rootType?.fields) continue;
888
- for (const f of rootType.fields) {
889
- if (!f.name.startsWith("__")) {
890
- fieldMap.set(`${rootKind}.${f.name}`, { kind: rootKind, field: f });
891
- }
892
- }
893
- }
894
- return fields.map((extracted) => {
895
- const prefix = extracted.kind === "mutation" ? "mutation" : "query";
896
- const toolPath = `${prefix}.${extracted.fieldName}`;
897
- const description = Option3.getOrElse(
898
- extracted.description,
899
- () => `GraphQL ${extracted.kind}: ${extracted.fieldName} -> ${extracted.returnTypeName}`
900
- );
901
- const key = `${extracted.kind}.${extracted.fieldName}`;
902
- const entry = fieldMap.get(key);
903
- const operationString = entry ? buildOperationStringForField(entry.kind, entry.field, typeMap) : `${extracted.kind} { ${extracted.fieldName} }`;
904
- const binding = new OperationBinding({
905
- kind: extracted.kind,
906
- fieldName: extracted.fieldName,
907
- operationString,
908
- variableNames: extracted.arguments.map((a) => a.name)
909
- });
910
- return {
911
- toolPath,
912
- description,
913
- inputSchema: Option3.getOrUndefined(extracted.inputSchema),
914
- binding
915
- };
916
- });
917
- };
918
- var annotationsFor = (binding) => {
919
- if (binding.kind === "mutation") {
920
- return {
921
- requiresApproval: true,
922
- approvalDescription: `mutation ${binding.fieldName}`
923
- };
924
- }
925
- return {};
926
- };
927
- var toGraphqlConfigEntry = (namespace, config) => ({
928
- kind: "graphql",
929
- endpoint: config.endpoint,
930
- introspectionJson: config.introspectionJson,
931
- namespace,
932
- headers: headersToConfigValues(config.headers)
933
- });
934
- var graphqlPlugin = definePlugin((options) => {
935
- const httpClientLayer = options?.httpClientLayer ?? FetchHttpClient.layer;
936
- return {
937
- id: "graphql",
938
- packageName: "@executor-js/plugin-graphql",
939
- schema: graphqlSchema,
940
- storage: (deps) => makeDefaultGraphqlStore(deps),
941
- extension: (ctx) => {
942
- const resolveConfigValues = (values) => Effect7.gen(function* () {
943
- if (!values) return void 0;
944
- const resolved = yield* resolveHeaders(values, ctx.secrets);
945
- return Object.keys(resolved).length > 0 ? resolved : void 0;
946
- });
947
- const resolveOAuthHeader = (auth) => Effect7.gen(function* () {
948
- if (!auth || auth.kind === "none") return void 0;
949
- const accessToken = yield* ctx.connections.accessToken(auth.connectionId).pipe(
950
- Effect7.mapError(
951
- (err) => new GraphqlIntrospectionError({
952
- message: `Failed to resolve OAuth connection "${auth.connectionId}": ${"message" in err ? err.message : String(err)}`
953
- })
954
- )
955
- );
956
- return { Authorization: `Bearer ${accessToken}` };
957
- });
958
- const resolveRequestHeaders = (headers, auth) => Effect7.gen(function* () {
959
- const resolvedHeaders = yield* resolveConfigValues(headers);
960
- const oauthHeader = yield* resolveOAuthHeader(auth);
961
- return { ...resolvedHeaders ?? {}, ...oauthHeader ?? {} };
962
- });
963
- const addSourceInternal = (config) => ctx.transaction(
964
- Effect7.gen(function* () {
965
- let introspectionResult;
966
- if (config.introspectionJson) {
967
- introspectionResult = yield* parseIntrospectionJson(
968
- config.introspectionJson
969
- );
970
- } else {
971
- const resolvedHeaders = yield* resolveRequestHeaders(
972
- config.headers,
973
- config.auth
974
- );
975
- const resolvedQueryParams = yield* resolveConfigValues(
976
- config.queryParams
977
- );
978
- introspectionResult = yield* introspect(
979
- config.endpoint,
980
- Object.keys(resolvedHeaders).length > 0 ? resolvedHeaders : void 0,
981
- resolvedQueryParams
982
- ).pipe(Effect7.provide(httpClientLayer));
983
- }
984
- const { result, definitions } = yield* extract(introspectionResult);
985
- const namespace = config.namespace ?? namespaceFromEndpoint(config.endpoint);
986
- const prepared = prepareOperations(
987
- result.fields,
988
- introspectionResult
989
- );
990
- const displayName = config.name?.trim() || namespace;
991
- const storedSource = {
992
- namespace,
993
- scope: config.scope,
994
- name: displayName,
995
- endpoint: config.endpoint,
996
- headers: config.headers ?? {},
997
- queryParams: config.queryParams ?? {},
998
- auth: config.auth ?? { kind: "none" }
999
- };
1000
- const storedOps = prepared.map((p) => ({
1001
- toolId: `${namespace}.${p.toolPath}`,
1002
- sourceId: namespace,
1003
- binding: p.binding
1004
- }));
1005
- yield* ctx.storage.upsertSource(storedSource, storedOps);
1006
- yield* ctx.core.sources.register({
1007
- id: namespace,
1008
- scope: config.scope,
1009
- kind: "graphql",
1010
- name: displayName,
1011
- url: config.endpoint,
1012
- canRemove: true,
1013
- canRefresh: false,
1014
- canEdit: true,
1015
- tools: prepared.map((p) => ({
1016
- name: p.toolPath,
1017
- description: p.description,
1018
- inputSchema: p.inputSchema
1019
- }))
1020
- });
1021
- if (Object.keys(definitions).length > 0) {
1022
- yield* ctx.core.definitions.register({
1023
- sourceId: namespace,
1024
- scope: config.scope,
1025
- definitions
1026
- });
1027
- }
1028
- return { toolCount: prepared.length, namespace };
1029
- })
1030
- );
1031
- const configFile = options?.configFile;
1032
- return {
1033
- addSource: (config) => addSourceInternal(config).pipe(
1034
- Effect7.tap(
1035
- (result) => configFile ? configFile.upsertSource(
1036
- toGraphqlConfigEntry(result.namespace, config)
1037
- ) : Effect7.void
1038
- )
1039
- ),
1040
- removeSource: (namespace, scope) => Effect7.gen(function* () {
1041
- yield* ctx.transaction(
1042
- Effect7.gen(function* () {
1043
- yield* ctx.storage.removeSource(namespace, scope);
1044
- yield* ctx.core.sources.unregister(namespace);
1045
- })
1046
- );
1047
- if (configFile) {
1048
- yield* configFile.removeSource(namespace);
1049
- }
1050
- }),
1051
- getSource: (namespace, scope) => ctx.storage.getSource(namespace, scope),
1052
- updateSource: (namespace, scope, input) => ctx.storage.updateSourceMeta(namespace, scope, {
1053
- name: input.name?.trim() || void 0,
1054
- endpoint: input.endpoint,
1055
- headers: input.headers,
1056
- queryParams: input.queryParams,
1057
- auth: input.auth
1058
- })
1059
- };
1060
- },
1061
- staticSources: (self) => [
1062
- {
1063
- id: "graphql",
1064
- kind: "control",
1065
- name: "GraphQL",
1066
- tools: [
1067
- {
1068
- name: "addSource",
1069
- description: "Add a GraphQL endpoint and register its operations as tools",
1070
- inputSchema: {
1071
- type: "object",
1072
- properties: {
1073
- endpoint: { type: "string" },
1074
- name: { type: "string" },
1075
- introspectionJson: { type: "string" },
1076
- namespace: { type: "string" },
1077
- headers: { type: "object" },
1078
- queryParams: { type: "object" },
1079
- auth: { type: "object" }
1080
- },
1081
- required: ["endpoint"]
1082
- },
1083
- outputSchema: {
1084
- type: "object",
1085
- properties: {
1086
- toolCount: { type: "number" }
1087
- },
1088
- required: ["toolCount"]
1089
- },
1090
- // Static-tool callers don't name a scope. Default to the
1091
- // outermost scope in the executor's stack — for a single-
1092
- // scope executor that's the only scope; for a per-user
1093
- // stack `[user, org]` it writes at `org` so the source is
1094
- // visible across every user.
1095
- handler: ({ ctx, args }) => self.addSource({
1096
- ...args,
1097
- scope: ctx.scopes.at(-1).id
1098
- })
1099
- }
1100
- ]
1101
- }
1102
- ],
1103
- invokeTool: ({ ctx, toolRow, args }) => Effect7.gen(function* () {
1104
- const toolScope = toolRow.scope_id;
1105
- const op = yield* ctx.storage.getOperationByToolId(
1106
- toolRow.id,
1107
- toolScope
1108
- );
1109
- if (!op) {
1110
- return yield* Effect7.fail(
1111
- new Error(`No GraphQL operation found for tool "${toolRow.id}"`)
1112
- );
1113
- }
1114
- const source = yield* ctx.storage.getSource(op.sourceId, toolScope);
1115
- if (!source) {
1116
- return yield* Effect7.fail(
1117
- new Error(`No GraphQL source found for "${op.sourceId}"`)
1118
- );
1119
- }
1120
- const resolvedHeaders = yield* resolveHeaders(
1121
- source.headers,
1122
- ctx.secrets
1123
- );
1124
- const resolvedQueryParams = yield* resolveHeaders(
1125
- source.queryParams,
1126
- ctx.secrets
1127
- );
1128
- if (source.auth.kind === "oauth2") {
1129
- const accessToken = yield* ctx.connections.accessToken(
1130
- source.auth.connectionId
1131
- );
1132
- resolvedHeaders.Authorization = `Bearer ${accessToken}`;
1133
- }
1134
- const result = yield* invokeWithLayer(
1135
- op.binding,
1136
- args ?? {},
1137
- source.endpoint,
1138
- resolvedHeaders,
1139
- resolvedQueryParams,
1140
- httpClientLayer
1141
- );
1142
- return result;
1143
- }),
1144
- resolveAnnotations: ({ ctx, sourceId, toolRows }) => Effect7.gen(function* () {
1145
- const scopes = /* @__PURE__ */ new Set();
1146
- for (const row of toolRows) {
1147
- scopes.add(row.scope_id);
1148
- }
1149
- const entries = yield* Effect7.forEach(
1150
- [...scopes],
1151
- (scope) => Effect7.gen(function* () {
1152
- const ops = yield* ctx.storage.listOperationsBySource(
1153
- sourceId,
1154
- scope
1155
- );
1156
- const byId = /* @__PURE__ */ new Map();
1157
- for (const op of ops) byId.set(op.toolId, op.binding);
1158
- return [scope, byId];
1159
- }),
1160
- { concurrency: "unbounded" }
1161
- );
1162
- const byScope = new Map(entries);
1163
- const out = {};
1164
- for (const row of toolRows) {
1165
- const binding = byScope.get(row.scope_id)?.get(row.id);
1166
- if (binding) out[row.id] = annotationsFor(binding);
1167
- }
1168
- return out;
1169
- }),
1170
- removeSource: ({ ctx, sourceId, scope }) => ctx.storage.removeSource(sourceId, scope),
1171
- detect: ({ url }) => Effect7.gen(function* () {
1172
- const trimmed = url.trim();
1173
- if (!trimmed) return null;
1174
- const parsed = yield* Effect7.try({
1175
- try: () => new URL(trimmed),
1176
- catch: (cause) => cause
1177
- }).pipe(
1178
- Effect7.option
1179
- );
1180
- if (Option3.isNone(parsed)) return null;
1181
- const ok = yield* introspect(trimmed).pipe(
1182
- Effect7.provide(httpClientLayer),
1183
- Effect7.map(() => true),
1184
- Effect7.catch(() => Effect7.succeed(false))
1185
- );
1186
- if (!ok) return null;
1187
- const name = namespaceFromEndpoint(trimmed);
1188
- return new SourceDetectionResult({
1189
- kind: "graphql",
1190
- confidence: "high",
1191
- endpoint: trimmed,
1192
- name,
1193
- namespace: name
1194
- });
1195
- }),
1196
- routes: () => GraphqlGroup,
1197
- handlers: () => GraphqlHandlers,
1198
- extensionService: GraphqlExtensionService
1199
- };
1200
- });
1201
-
1202
- export {
1203
- GraphqlIntrospectionError,
1204
- GraphqlExtractionError,
1205
- GraphqlInvocationError,
1206
- GraphqlOperationKind,
1207
- GraphqlArgument,
1208
- ExtractedField,
1209
- ExtractionResult,
1210
- OperationBinding,
1211
- HeaderValue,
1212
- GraphqlSourceAuth,
1213
- InvocationConfig,
1214
- InvocationResult,
1215
- introspect,
1216
- parseIntrospectionJson,
1217
- extract,
1218
- resolveHeaders,
1219
- invoke,
1220
- invokeWithLayer,
1221
- graphqlSchema,
1222
- makeDefaultGraphqlStore,
1223
- graphqlPlugin
1224
- };
1225
- //# sourceMappingURL=chunk-EIC5WI6C.js.map