import { HttpApiEndpoint, HttpApiGroup, HttpApiSchema } from "effect/unstable/httpapi";import { Schema } from "effect";import { InternalError, ScopeId, SecretBackedValue } from "@executor-js/sdk/core";import { GoogleDiscoveryParseError, GoogleDiscoverySourceError } from "../sdk/errors";import { GoogleDiscoveryStoredSourceSchema } from "../sdk/stored-source"; export { HttpApiSchema }; const DiscoveryCredentialsPayload = Schema.Struct({ headers: Schema.optional(Schema.Record(Schema.String, SecretBackedValue)), queryParams: Schema.optional(Schema.Record(Schema.String, SecretBackedValue)),}); const AuthPayload = Schema.Union([ Schema.Struct({ kind: Schema.Literal("none"), }), Schema.Struct({ kind: Schema.Literal("oauth2"), connectionId: Schema.String, clientIdSecretId: Schema.String, clientSecretSecretId: Schema.NullOr(Schema.String), scopes: Schema.Array(Schema.String), }),]); const ProbePayload = Schema.Struct({ discoveryUrl: Schema.String, credentials: Schema.optional(DiscoveryCredentialsPayload),}); const ProbeOperation = Schema.Struct({ toolPath: Schema.String, method: Schema.String, pathTemplate: Schema.String, description: Schema.NullOr(Schema.String),}); const ProbeResponse = Schema.Struct({ name: Schema.String, title: Schema.NullOr(Schema.String), service: Schema.String, version: Schema.String, toolCount: Schema.Number, scopes: Schema.Array(Schema.String), operations: Schema.Array(ProbeOperation),}); const AddSourcePayload = Schema.Struct({ name: Schema.String, discoveryUrl: Schema.String, credentials: Schema.optional(DiscoveryCredentialsPayload), namespace: Schema.optional(Schema.String), auth: AuthPayload,}); const AddSourceResponse = Schema.Struct({ toolCount: Schema.Number, namespace: Schema.String,}); const UpdateSourcePayload = Schema.Struct({ name: Schema.optional(Schema.String), auth: Schema.optional(AuthPayload),}); const UpdateSourceResponse = Schema.Struct({ updated: Schema.Boolean,}); // OAuth start/complete/callback payloads/responses live on the shared// `/scopes/:scopeId/oauth/*` group in `@executor-js/api` now — no// plugin-specific OAuth schemas needed here. export class GoogleDiscoveryApiError extends Schema.TaggedErrorClass<GoogleDiscoveryApiError>()( "GoogleDiscoveryApiError", { message: Schema.String, }, { httpApiStatus: 400 },) {} const GoogleDiscoveryErrors = [ InternalError, GoogleDiscoveryApiError, GoogleDiscoveryParseError, GoogleDiscoverySourceError,] as const; // ---------------------------------------------------------------------------// Group//// Domain errors + the shared opaque 500 (`InternalError`) are declared// once at the group level via `.addError(...)` — every endpoint// inherits them. The domain error carries its HTTP status via// `HttpApiSchema.annotations`; `InternalError` is the public 5xx// surface, translated from `StorageError` at the HTTP edge by// `withCapture`. No per-endpoint `.addError(...)`, no per-handler// InternalError — handlers just `return yield* ext.foo(...)`.// --------------------------------------------------------------------------- export const GoogleDiscoveryGroup = HttpApiGroup.make("googleDiscovery") .add( HttpApiEndpoint.post("probeDiscovery", "/scopes/:scopeId/google-discovery/probe", { params: { scopeId: ScopeId }, payload: ProbePayload, success: ProbeResponse, error: GoogleDiscoveryErrors, }), ) .add( HttpApiEndpoint.post("addSource", "/scopes/:scopeId/google-discovery/sources", { params: { scopeId: ScopeId }, payload: AddSourcePayload, success: AddSourceResponse, error: GoogleDiscoveryErrors, }), ) .add( HttpApiEndpoint.patch("updateSource", "/scopes/:scopeId/google-discovery/sources/:namespace", { params: { scopeId: ScopeId, namespace: Schema.String }, payload: UpdateSourcePayload, success: UpdateSourceResponse, error: GoogleDiscoveryErrors, }), ) .add( HttpApiEndpoint.get("getSource", "/scopes/:scopeId/google-discovery/sources/:namespace", { params: { scopeId: ScopeId, namespace: Schema.String }, success: Schema.NullOr(GoogleDiscoveryStoredSourceSchema), error: GoogleDiscoveryErrors, }), );// Errors are declared per endpoint in Effect v4.
import { HttpApiEndpoint, HttpApiGroup, HttpApiSchema } from "effect/unstable/httpapi";
import { Schema } from "effect";
import { InternalError, ScopeId, SecretBackedValue } from "@executor-js/sdk/core";
import { GoogleDiscoveryParseError, GoogleDiscoverySourceError } from "../sdk/errors";
import { GoogleDiscoveryStoredSourceSchema } from "../sdk/stored-source";
export { HttpApiSchema };
const DiscoveryCredentialsPayload = Schema.Struct({
headers: Schema.optional(Schema.Record(Schema.String, SecretBackedValue)),
queryParams: Schema.optional(Schema.Record(Schema.String, SecretBackedValue)),
});
const AuthPayload = Schema.Union([
Schema.Struct({
kind: Schema.Literal("none"),
}),
Schema.Struct({
kind: Schema.Literal("oauth2"),
connectionId: Schema.String,
clientIdSecretId: Schema.String,
clientSecretSecretId: Schema.NullOr(Schema.String),
scopes: Schema.Array(Schema.String),
}),
]);
const ProbePayload = Schema.Struct({
discoveryUrl: Schema.String,
credentials: Schema.optional(DiscoveryCredentialsPayload),
});
const ProbeOperation = Schema.Struct({
toolPath: Schema.String,
method: Schema.String,
pathTemplate: Schema.String,
description: Schema.NullOr(Schema.String),
});
const ProbeResponse = Schema.Struct({
name: Schema.String,
title: Schema.NullOr(Schema.String),
service: Schema.String,
version: Schema.String,
toolCount: Schema.Number,
scopes: Schema.Array(Schema.String),
operations: Schema.Array(ProbeOperation),
});
const AddSourcePayload = Schema.Struct({
name: Schema.String,
discoveryUrl: Schema.String,
credentials: Schema.optional(DiscoveryCredentialsPayload),
namespace: Schema.optional(Schema.String),
auth: AuthPayload,
});
const AddSourceResponse = Schema.Struct({
toolCount: Schema.Number,
namespace: Schema.String,
});
const UpdateSourcePayload = Schema.Struct({
name: Schema.optional(Schema.String),
auth: Schema.optional(AuthPayload),
});
const UpdateSourceResponse = Schema.Struct({
updated: Schema.Boolean,
});
// OAuth start/complete/callback payloads/responses live on the shared
// `/scopes/:scopeId/oauth/*` group in `@executor-js/api` now — no
// plugin-specific OAuth schemas needed here.
export class GoogleDiscoveryApiError extends Schema.TaggedErrorClass<GoogleDiscoveryApiError>()(
"GoogleDiscoveryApiError",
{
message: Schema.String,
},
{ httpApiStatus: 400 },
) {}
const GoogleDiscoveryErrors = [
InternalError,
GoogleDiscoveryApiError,
GoogleDiscoveryParseError,
GoogleDiscoverySourceError,
] as const;
// ---------------------------------------------------------------------------
// Group
//
// Domain errors + the shared opaque 500 (`InternalError`) are declared
// once at the group level via `.addError(...)` — every endpoint
// inherits them. The domain error carries its HTTP status via
// `HttpApiSchema.annotations`; `InternalError` is the public 5xx
// surface, translated from `StorageError` at the HTTP edge by
// `withCapture`. No per-endpoint `.addError(...)`, no per-handler
// InternalError — handlers just `return yield* ext.foo(...)`.
// ---------------------------------------------------------------------------
export const GoogleDiscoveryGroup = HttpApiGroup.make("googleDiscovery")
.add(
HttpApiEndpoint.post("probeDiscovery", "/scopes/:scopeId/google-discovery/probe", {
params: { scopeId: ScopeId },
payload: ProbePayload,
success: ProbeResponse,
error: GoogleDiscoveryErrors,
}),
)
.add(
HttpApiEndpoint.post("addSource", "/scopes/:scopeId/google-discovery/sources", {
params: { scopeId: ScopeId },
payload: AddSourcePayload,
success: AddSourceResponse,
error: GoogleDiscoveryErrors,
}),
)
.add(
HttpApiEndpoint.patch("updateSource", "/scopes/:scopeId/google-discovery/sources/:namespace", {
params: { scopeId: ScopeId, namespace: Schema.String },
payload: UpdateSourcePayload,
success: UpdateSourceResponse,
error: GoogleDiscoveryErrors,
}),
)
.add(
HttpApiEndpoint.get("getSource", "/scopes/:scopeId/google-discovery/sources/:namespace", {
params: { scopeId: ScopeId, namespace: Schema.String },
success: Schema.NullOr(GoogleDiscoveryStoredSourceSchema),
error: GoogleDiscoveryErrors,
}),
);
// Errors are declared per endpoint in Effect v4.