Rhys Sullivanmcp / openapibc109b48 months agoHistory
81 lines · 2.4 KB · TypeScript
RawDownload
import * as Data from "effect/Data";import * as Effect from "effect/Effect";import { pipe } from "effect/Function";import * as ParseResult from "effect/ParseResult";import * as Schema from "effect/Schema"; import { extractOpenApiManifestJsonWithWasm } from "./openapi-extractor-wasm";import {  OpenApiToolManifestSchema,  type OpenApiSpecInput,  type OpenApiToolManifest,} from "./openapi-types"; type OpenApiExtractionStage = "validate" | "extract"; export class OpenApiExtractionError extends Data.TaggedError("OpenApiExtractionError")<{  sourceName: string;  stage: OpenApiExtractionStage;  message: string;  details: string | null;}> {} const manifestFromJsonSchema = Schema.parseJson(OpenApiToolManifestSchema);const decodeManifestFromJson = Schema.decodeUnknown(manifestFromJsonSchema); const toExtractionError = (  sourceName: string,  stage: OpenApiExtractionStage,  cause: unknown,): OpenApiExtractionError =>  cause instanceof OpenApiExtractionError    ? cause    : new OpenApiExtractionError({        sourceName,        stage,        message: "OpenAPI extraction failed",        details: ParseResult.isParseError(cause)          ? ParseResult.TreeFormatter.formatErrorSync(cause)          : String(cause),      }); const normalizeOpenApiDocumentText = (  sourceName: string,  openApiSpec: OpenApiSpecInput,): Effect.Effect<string, OpenApiExtractionError> => {  if (typeof openApiSpec === "string") {    return Effect.succeed(openApiSpec);  }   return Effect.try({    try: () => JSON.stringify(openApiSpec),    catch: (cause) =>      new OpenApiExtractionError({        sourceName,        stage: "validate",        message: "Unable to serialize OpenAPI input",        details: String(cause),      }),  });}; export const extractOpenApiManifest = (  sourceName: string,  openApiSpec: OpenApiSpecInput,): Effect.Effect<OpenApiToolManifest, OpenApiExtractionError> =>  Effect.gen(function* () {    const openApiDocumentText = yield* normalizeOpenApiDocumentText(      sourceName,      openApiSpec,    );     const manifestJson = yield* Effect.tryPromise({      try: () => extractOpenApiManifestJsonWithWasm(sourceName, openApiDocumentText),      catch: (cause) => toExtractionError(sourceName, "extract", cause),    });     return yield* pipe(      decodeManifestFromJson(manifestJson),      Effect.mapError((cause) => toExtractionError(sourceName, "extract", cause)),    );  });