import { HttpApiBuilder } from "effect/unstable/httpapi";import { Context, Effect } from "effect"; import { addGroup, capture } from "@executor-js/api";import type { GraphqlPluginExtension } from "../sdk/plugin";import { GraphqlGroup } from "./group"; // ---------------------------------------------------------------------------// Service tag//// Holds the plugin's extension. The host app provides an already-wrapped// extension via `Layer.succeed(GraphqlExtensionService, executor.graphql)`.// Handlers see plugin SDK errors in the typed channel (matched by// `.addError(...)` on the group) and `InternalError` for `StorageError`// translated by `capture` at the HTTP edge.// --------------------------------------------------------------------------- export class GraphqlExtensionService extends Context.Service< GraphqlExtensionService, GraphqlPluginExtension>()("GraphqlExtensionService") {} // ---------------------------------------------------------------------------// Composed API — core + graphql group// --------------------------------------------------------------------------- const ExecutorApiWithGraphql = addGroup(GraphqlGroup); // ---------------------------------------------------------------------------// Handlers// --------------------------------------------------------------------------- export const GraphqlHandlers = HttpApiBuilder.group(ExecutorApiWithGraphql, "graphql", (handlers) => handlers .handle("addIntegration", ({ payload }) => capture( Effect.gen(function* () { const ext = yield* GraphqlExtensionService; const result = yield* ext.addIntegration({ endpoint: payload.endpoint, slug: payload.slug, name: payload.name, description: payload.description, introspectionJson: payload.introspectionJson, headers: payload.headers, queryParams: payload.queryParams, authenticationTemplate: payload.authenticationTemplate, }); return { slug: result.slug, name: result.name }; }), ), ) .handle("getIntegration", ({ params: path }) => capture( Effect.gen(function* () { const ext = yield* GraphqlExtensionService; return yield* ext.getIntegration(path.slug); }), ), ) .handle("getConfig", ({ params: path }) => capture( Effect.gen(function* () { const ext = yield* GraphqlExtensionService; const config = yield* ext.getConfig(path.slug); return config ? { endpoint: config.endpoint, name: config.name, headers: config.headers ? { ...config.headers } : undefined, queryParams: config.queryParams ? { ...config.queryParams } : undefined, authenticationTemplate: [...config.authenticationTemplate], } : null; }), ), ) .handle("configure", ({ params: path, payload }) => capture( Effect.gen(function* () { const ext = yield* GraphqlExtensionService; const authenticationTemplate = yield* ext.configureAuth(path.slug, { authenticationTemplate: payload.authenticationTemplate, mode: payload.mode ?? "merge", }); return { authenticationTemplate: [...authenticationTemplate] }; }), ), ),);
import { HttpApiBuilder } from "effect/unstable/httpapi";
import { Context, Effect } from "effect";
import { addGroup, capture } from "@executor-js/api";
import type { GraphqlPluginExtension } from "../sdk/plugin";
import { GraphqlGroup } from "./group";
// ---------------------------------------------------------------------------
// Service tag
//
// Holds the plugin's extension. The host app provides an already-wrapped
// extension via `Layer.succeed(GraphqlExtensionService, executor.graphql)`.
// Handlers see plugin SDK errors in the typed channel (matched by
// `.addError(...)` on the group) and `InternalError` for `StorageError`
// translated by `capture` at the HTTP edge.
// ---------------------------------------------------------------------------
export class GraphqlExtensionService extends Context.Service<
GraphqlExtensionService,
GraphqlPluginExtension
>()("GraphqlExtensionService") {}
// ---------------------------------------------------------------------------
// Composed API — core + graphql group
// ---------------------------------------------------------------------------
const ExecutorApiWithGraphql = addGroup(GraphqlGroup);
// ---------------------------------------------------------------------------
// Handlers
// ---------------------------------------------------------------------------
export const GraphqlHandlers = HttpApiBuilder.group(ExecutorApiWithGraphql, "graphql", (handlers) =>
handlers
.handle("addIntegration", ({ payload }) =>
capture(
Effect.gen(function* () {
const ext = yield* GraphqlExtensionService;
const result = yield* ext.addIntegration({
endpoint: payload.endpoint,
slug: payload.slug,
name: payload.name,
description: payload.description,
introspectionJson: payload.introspectionJson,
headers: payload.headers,
queryParams: payload.queryParams,
authenticationTemplate: payload.authenticationTemplate,
});
return { slug: result.slug, name: result.name };
}),
),
)
.handle("getIntegration", ({ params: path }) =>
capture(
Effect.gen(function* () {
const ext = yield* GraphqlExtensionService;
return yield* ext.getIntegration(path.slug);
}),
),
)
.handle("getConfig", ({ params: path }) =>
capture(
Effect.gen(function* () {
const ext = yield* GraphqlExtensionService;
const config = yield* ext.getConfig(path.slug);
return config
? {
endpoint: config.endpoint,
name: config.name,
headers: config.headers ? { ...config.headers } : undefined,
queryParams: config.queryParams ? { ...config.queryParams } : undefined,
authenticationTemplate: [...config.authenticationTemplate],
}
: null;
}),
),
)
.handle("configure", ({ params: path, payload }) =>
capture(
Effect.gen(function* () {
const ext = yield* GraphqlExtensionService;
const authenticationTemplate = yield* ext.configureAuth(path.slug, {
authenticationTemplate: payload.authenticationTemplate,
mode: payload.mode ?? "merge",
});
return { authenticationTemplate: [...authenticationTemplate] };
}),
),
),
);