// ---------------------------------------------------------------------------// Google per-service add flow, "customize your Google connection".//// The product picker emits preset ids and custom Discovery URLs. The server// fans them out into separate integrations, deriving custom identity from the// fetched Discovery document before it compiles the OpenAPI surface.// --------------------------------------------------------------------------- import { describe, expect, it } from "@effect/vitest";import { Effect, Layer } from "effect";import { HttpClient, HttpClientRequest, HttpClientResponse } from "effect/unstable/http"; import { ConnectionName, IntegrationSlug, createExecutor, AuthTemplateSlug,} from "@executor-js/sdk";import { makeTestConfig, memoryCredentialsPlugin } from "@executor-js/sdk/testing"; import { defaultGoogleHealthCheck, googlePlugin } from "./plugin"; // --- Canned Discovery documents -------------------------------------------// Each carries one method. Calendar and Gmail BOTH expose a generic `list`// method id segment, so a naive merge that keyed tools on the trailing method// name would collide. The bundle converter keys on the full method id// (`calendar.events.list`, `gmail.users.messages.list`, …), so they don't. const CALENDAR_URL = "https://www.googleapis.com/discovery/v1/apis/calendar/v3/rest";const GMAIL_URL = "https://www.googleapis.com/discovery/v1/apis/gmail/v1/rest";const SHEETS_URL = "https://www.googleapis.com/discovery/v1/apis/sheets/v4/rest";const DRIVE_URL = "https://www.googleapis.com/discovery/v1/apis/drive/v3/rest";const DOCS_URL = "https://www.googleapis.com/discovery/v1/apis/docs/v1/rest";const TASKS_URL = "https://www.googleapis.com/discovery/v1/apis/tasks/v1/rest";const PHOTOS_LIBRARY_URL = "https://www.googleapis.com/discovery/v1/apis/photoslibrary/v1/rest";const PHOTOS_PICKER_URL = "https://photospicker.googleapis.com/$discovery/rest?version=v1";const PEOPLE_URL = "https://www.googleapis.com/discovery/v1/apis/people/v1/rest";const OAUTH2_URL = "https://www.googleapis.com/discovery/v1/apis/oauth2/v2/rest";const OAUTH2_USERINFO_SCOPES = [ "openid", "https://www.googleapis.com/auth/userinfo.email", "https://www.googleapis.com/auth/userinfo.profile",] as const; const calendarDoc = { name: "calendar", version: "v3", title: "Calendar API", rootUrl: "https://www.googleapis.com/", servicePath: "calendar/v3/", auth: { oauth2: { scopes: { "https://www.googleapis.com/auth/calendar": { description: "Manage calendars" }, "https://www.googleapis.com/auth/calendar.readonly": { description: "Read calendars" }, }, }, }, resources: { events: { methods: { list: { id: "calendar.events.list", httpMethod: "GET", path: "calendars/{calendarId}/events", scopes: ["https://www.googleapis.com/auth/calendar.readonly"], parameters: { calendarId: { location: "path", required: true, type: "string" }, }, }, }, }, }, schemas: { Event: { id: "Event", type: "object", properties: { id: { type: "string" } } }, },}; const gmailDoc = { name: "gmail", version: "v1", title: "Gmail API", rootUrl: "https://gmail.googleapis.com/", servicePath: "", auth: { oauth2: { scopes: { "https://mail.google.com/": { description: "Full Gmail access" }, "https://www.googleapis.com/auth/gmail.readonly": { description: "Read Gmail" }, }, }, }, resources: { users: { resources: { messages: { methods: { // Same trailing `list` as calendar.events.list - would collide on a // naive merge; service-prefixed method id keeps them distinct. list: { id: "gmail.users.messages.list", httpMethod: "GET", path: "gmail/v1/users/{userId}/messages", scopes: ["https://www.googleapis.com/auth/gmail.readonly"], parameters: { userId: { location: "path", required: true, type: "string" }, }, }, }, }, }, }, }, schemas: { Message: { id: "Message", type: "object", properties: { id: { type: "string" } } }, },}; const driveDoc = { name: "drive", version: "v3", title: "Drive API", rootUrl: "https://www.googleapis.com/", servicePath: "drive/v3/", auth: { oauth2: { scopes: { "https://www.googleapis.com/auth/drive": { description: "Manage Drive" }, }, }, }, resources: { files: { methods: { // A third `list` - three generic method names across three APIs. list: { id: "drive.files.list", httpMethod: "GET", path: "files", scopes: ["https://www.googleapis.com/auth/drive"], parameters: {}, }, }, }, }, schemas: { File: { id: "File", type: "object", properties: { id: { type: "string" } } }, },}; const sheetsDoc = { name: "sheets", version: "v4", title: "Google Sheets API", rootUrl: "https://sheets.googleapis.com/", servicePath: "v4/", auth: { oauth2: { scopes: { "https://www.googleapis.com/auth/spreadsheets": { description: "Manage spreadsheets" }, }, }, }, resources: { spreadsheets: { methods: { get: { id: "sheets.spreadsheets.get", httpMethod: "GET", path: "spreadsheets/{spreadsheetId}", scopes: ["https://www.googleapis.com/auth/spreadsheets"], parameters: { spreadsheetId: { location: "path", required: true, type: "string" }, }, }, }, }, }, schemas: { Spreadsheet: { id: "Spreadsheet", type: "object", properties: { id: { type: "string" } } }, },}; const docsDoc = { name: "docs", version: "v1", title: "Google Docs API", rootUrl: "https://docs.googleapis.com/", servicePath: "v1/", auth: { oauth2: { scopes: { "https://www.googleapis.com/auth/documents": { description: "Manage documents" }, }, }, }, resources: { documents: { methods: { get: { id: "docs.documents.get", httpMethod: "GET", path: "documents/{documentId}", scopes: ["https://www.googleapis.com/auth/documents"], parameters: { documentId: { location: "path", required: true, type: "string" }, }, }, }, }, }, schemas: { Document: { id: "Document", type: "object", properties: { documentId: { type: "string" } } }, },}; const tasksDoc = { name: "tasks", version: "v1", title: "Tasks API", description: "Manage your tasks and task lists.", rootUrl: "https://tasks.googleapis.com/", servicePath: "tasks/v1/", auth: { oauth2: { scopes: { "https://www.googleapis.com/auth/tasks": { description: "Manage tasks" }, }, }, }, resources: { tasks: { methods: { list: { id: "tasks.tasks.list", httpMethod: "GET", path: "lists/{tasklist}/tasks", scopes: ["https://www.googleapis.com/auth/tasks"], parameters: { tasklist: { location: "path", required: true, type: "string" }, }, }, }, }, }, schemas: { Task: { id: "Task", type: "object", properties: { id: { type: "string" } } }, },}; const photosLibraryDoc = { name: "photoslibrary", version: "v1", title: "Google Photos Library API", rootUrl: "https://photoslibrary.googleapis.com/", servicePath: "v1/", auth: { oauth2: { scopes: { "https://www.googleapis.com/auth/photoslibrary": { description: "Manage the full Google Photos library", }, "https://www.googleapis.com/auth/photoslibrary.appendonly": { description: "Upload to Google Photos", }, "https://www.googleapis.com/auth/photoslibrary.readonly.appcreateddata": { description: "Read app-created Google Photos media", }, }, }, }, resources: { albums: { methods: { list: { id: "photoslibrary.albums.list", httpMethod: "GET", path: "albums", scopes: ["https://www.googleapis.com/auth/photoslibrary"], parameters: {}, }, }, }, mediaItems: { methods: { search: { id: "photoslibrary.mediaItems.search", httpMethod: "POST", path: "mediaItems:search", scopes: ["https://www.googleapis.com/auth/photoslibrary.readonly.appcreateddata"], parameters: {}, }, }, }, }, schemas: {},}; const photosPickerDoc = { name: "photospicker", version: "v1", title: "Google Photos Picker API", rootUrl: "https://photospicker.googleapis.com/", servicePath: "v1/", resources: { mediaItems: { methods: { list: { id: "photospicker.mediaItems.list", httpMethod: "GET", path: "mediaItems", parameters: {}, }, }, }, }, schemas: {},}; const peopleDoc = { name: "people", version: "v1", title: "People API", rootUrl: "https://people.googleapis.com/", servicePath: "", auth: { oauth2: { scopes: { "https://www.googleapis.com/auth/userinfo.email": { description: "See your email" }, }, }, }, resources: { people: { methods: { get: { id: "people.people.get", httpMethod: "GET", path: "v1/{+resourceName}", scopes: ["https://www.googleapis.com/auth/userinfo.email"], parameters: { resourceName: { location: "path", required: true, type: "string" }, personFields: { location: "query", type: "string" }, }, response: { $ref: "Person" }, }, }, }, }, schemas: { Person: { id: "Person", type: "object", properties: { resourceName: { type: "string" }, emailAddresses: { type: "array", items: { $ref: "EmailAddress" } }, }, }, EmailAddress: { id: "EmailAddress", type: "object", properties: { value: { type: "string" } } }, },}; const oauth2Doc = { name: "oauth2", version: "v2", title: "Google OAuth2 API", rootUrl: "https://www.googleapis.com/", servicePath: "", auth: { oauth2: { scopes: { openid: { description: "Associate you with your personal info on Google" }, "https://www.googleapis.com/auth/userinfo.email": { description: "See your primary Google Account email address", }, "https://www.googleapis.com/auth/userinfo.profile": { description: "See your personal info", }, }, }, }, methods: { tokeninfo: { id: "oauth2.tokeninfo", httpMethod: "POST", path: "oauth2/v2/tokeninfo", response: { $ref: "Tokeninfo" }, }, }, resources: { userinfo: { methods: { get: { id: "oauth2.userinfo.get", httpMethod: "GET", path: "oauth2/v2/userinfo", scopes: OAUTH2_USERINFO_SCOPES, response: { $ref: "Userinfo" }, }, }, resources: { v2: { resources: { me: { methods: { get: { id: "oauth2.userinfo.v2.me.get", httpMethod: "GET", path: "userinfo/v2/me", scopes: OAUTH2_USERINFO_SCOPES, response: { $ref: "Userinfo" }, }, }, }, }, }, }, }, }, schemas: { Tokeninfo: { id: "Tokeninfo", type: "object", properties: { audience: { type: "string" }, scope: { type: "string" }, }, }, Userinfo: { id: "Userinfo", type: "object", properties: { email: { type: "string" }, family_name: { type: "string" }, gender: { type: "string" }, given_name: { type: "string" }, hd: { type: "string" }, id: { type: "string" }, link: { type: "string" }, locale: { type: "string" }, name: { type: "string" }, picture: { type: "string" }, verified_email: { type: "boolean" }, }, }, },}; const toJson = (value: unknown): string => JSON.stringify(value); const DISCOVERY_BODIES: Readonly<Record<string, string>> = { [CALENDAR_URL]: toJson(calendarDoc), [GMAIL_URL]: toJson(gmailDoc), [SHEETS_URL]: toJson(sheetsDoc), [DRIVE_URL]: toJson(driveDoc), [DOCS_URL]: toJson(docsDoc), [TASKS_URL]: toJson(tasksDoc), [PHOTOS_LIBRARY_URL]: toJson(photosLibraryDoc), [PHOTOS_PICKER_URL]: toJson(photosPickerDoc), [PEOPLE_URL]: toJson(peopleDoc), [OAUTH2_URL]: toJson(oauth2Doc),}; interface DiscoveryHttpClientOptions { readonly failedUrls?: ReadonlySet<string>; readonly beforeResponse?: (url: string) => Effect.Effect<void, never, never>;} const waitOneTurn: Effect.Effect<void, never, never> = Effect.promise(() => Promise.resolve()).pipe( Effect.orDie,); // A stub HTTP client that serves the canned Discovery document for whichever// URL the bundle converter fetches. Service-hosted Discovery URLs carry their// version in the query string, so match the full URL before falling back to the// path-only key used by central Discovery URLs.const makeDiscoveryHttpClientLayer = (options: DiscoveryHttpClientOptions = {}) => Layer.succeed(HttpClient.HttpClient)( HttpClient.make((request: HttpClientRequest.HttpClientRequest) => { const url = new URL(request.url); const key = `${url.origin}${url.pathname}`; const body = DISCOVERY_BODIES[url.toString()] ?? DISCOVERY_BODIES[key]; const discoveryUrl = DISCOVERY_BODIES[url.toString()] !== undefined ? url.toString() : key; const failed = options.failedUrls?.has(url.toString()) === true || options.failedUrls?.has(key) === true; const response = HttpClientResponse.fromWeb( request, failed ? new Response("forced failure", { status: 503 }) : body === undefined ? new Response("not found", { status: 404 }) : new Response(body, { status: 200, headers: { "content-type": "application/json" }, }), ); return (options.beforeResponse?.(discoveryUrl) ?? Effect.void).pipe(Effect.as(response)); }), ); Lines 1–500 of 1184. Load more
// --------------------------------------------------------------------------- // Google per-service add flow, "customize your Google connection". // // The product picker emits preset ids and custom Discovery URLs. The server // fans them out into separate integrations, deriving custom identity from the // fetched Discovery document before it compiles the OpenAPI surface. // --------------------------------------------------------------------------- import { describe, expect, it } from "@effect/vitest"; import { Effect, Layer } from "effect"; import { HttpClient, HttpClientRequest, HttpClientResponse } from "effect/unstable/http"; import { ConnectionName, IntegrationSlug, createExecutor, AuthTemplateSlug, } from "@executor-js/sdk"; import { makeTestConfig, memoryCredentialsPlugin } from "@executor-js/sdk/testing"; import { defaultGoogleHealthCheck, googlePlugin } from "./plugin"; // --- Canned Discovery documents ------------------------------------------- // Each carries one method. Calendar and Gmail BOTH expose a generic `list` // method id segment, so a naive merge that keyed tools on the trailing method // name would collide. The bundle converter keys on the full method id // (`calendar.events.list`, `gmail.users.messages.list`, …), so they don't. const CALENDAR_URL = "https://www.googleapis.com/discovery/v1/apis/calendar/v3/rest"; const GMAIL_URL = "https://www.googleapis.com/discovery/v1/apis/gmail/v1/rest"; const SHEETS_URL = "https://www.googleapis.com/discovery/v1/apis/sheets/v4/rest"; const DRIVE_URL = "https://www.googleapis.com/discovery/v1/apis/drive/v3/rest"; const DOCS_URL = "https://www.googleapis.com/discovery/v1/apis/docs/v1/rest"; const TASKS_URL = "https://www.googleapis.com/discovery/v1/apis/tasks/v1/rest"; const PHOTOS_LIBRARY_URL = "https://www.googleapis.com/discovery/v1/apis/photoslibrary/v1/rest"; const PHOTOS_PICKER_URL = "https://photospicker.googleapis.com/$discovery/rest?version=v1"; const PEOPLE_URL = "https://www.googleapis.com/discovery/v1/apis/people/v1/rest"; const OAUTH2_URL = "https://www.googleapis.com/discovery/v1/apis/oauth2/v2/rest"; const OAUTH2_USERINFO_SCOPES = [ "openid", "https://www.googleapis.com/auth/userinfo.email", "https://www.googleapis.com/auth/userinfo.profile", ] as const; const calendarDoc = { name: "calendar", version: "v3", title: "Calendar API", rootUrl: "https://www.googleapis.com/", servicePath: "calendar/v3/", auth: { oauth2: { scopes: { "https://www.googleapis.com/auth/calendar": { description: "Manage calendars" }, "https://www.googleapis.com/auth/calendar.readonly": { description: "Read calendars" }, }, }, }, resources: { events: { methods: { list: { id: "calendar.events.list", httpMethod: "GET", path: "calendars/{calendarId}/events", scopes: ["https://www.googleapis.com/auth/calendar.readonly"], parameters: { calendarId: { location: "path", required: true, type: "string" }, }, }, }, }, }, schemas: { Event: { id: "Event", type: "object", properties: { id: { type: "string" } } }, }, }; const gmailDoc = { name: "gmail", version: "v1", title: "Gmail API", rootUrl: "https://gmail.googleapis.com/", servicePath: "", auth: { oauth2: { scopes: { "https://mail.google.com/": { description: "Full Gmail access" }, "https://www.googleapis.com/auth/gmail.readonly": { description: "Read Gmail" }, }, }, }, resources: { users: { resources: { messages: { methods: { // Same trailing `list` as calendar.events.list - would collide on a // naive merge; service-prefixed method id keeps them distinct. list: { id: "gmail.users.messages.list", httpMethod: "GET", path: "gmail/v1/users/{userId}/messages", scopes: ["https://www.googleapis.com/auth/gmail.readonly"], parameters: { userId: { location: "path", required: true, type: "string" }, }, }, }, }, }, }, }, schemas: { Message: { id: "Message", type: "object", properties: { id: { type: "string" } } }, }, }; const driveDoc = { name: "drive", version: "v3", title: "Drive API", rootUrl: "https://www.googleapis.com/", servicePath: "drive/v3/", auth: { oauth2: { scopes: { "https://www.googleapis.com/auth/drive": { description: "Manage Drive" }, }, }, }, resources: { files: { methods: { // A third `list` - three generic method names across three APIs. list: { id: "drive.files.list", httpMethod: "GET", path: "files", scopes: ["https://www.googleapis.com/auth/drive"], parameters: {}, }, }, }, }, schemas: { File: { id: "File", type: "object", properties: { id: { type: "string" } } }, }, }; const sheetsDoc = { name: "sheets", version: "v4", title: "Google Sheets API", rootUrl: "https://sheets.googleapis.com/", servicePath: "v4/", auth: { oauth2: { scopes: { "https://www.googleapis.com/auth/spreadsheets": { description: "Manage spreadsheets" }, }, }, }, resources: { spreadsheets: { methods: { get: { id: "sheets.spreadsheets.get", httpMethod: "GET", path: "spreadsheets/{spreadsheetId}", scopes: ["https://www.googleapis.com/auth/spreadsheets"], parameters: { spreadsheetId: { location: "path", required: true, type: "string" }, }, }, }, }, }, schemas: { Spreadsheet: { id: "Spreadsheet", type: "object", properties: { id: { type: "string" } } }, }, }; const docsDoc = { name: "docs", version: "v1", title: "Google Docs API", rootUrl: "https://docs.googleapis.com/", servicePath: "v1/", auth: { oauth2: { scopes: { "https://www.googleapis.com/auth/documents": { description: "Manage documents" }, }, }, }, resources: { documents: { methods: { get: { id: "docs.documents.get", httpMethod: "GET", path: "documents/{documentId}", scopes: ["https://www.googleapis.com/auth/documents"], parameters: { documentId: { location: "path", required: true, type: "string" }, }, }, }, }, }, schemas: { Document: { id: "Document", type: "object", properties: { documentId: { type: "string" } } }, }, }; const tasksDoc = { name: "tasks", version: "v1", title: "Tasks API", description: "Manage your tasks and task lists.", rootUrl: "https://tasks.googleapis.com/", servicePath: "tasks/v1/", auth: { oauth2: { scopes: { "https://www.googleapis.com/auth/tasks": { description: "Manage tasks" }, }, }, }, resources: { tasks: { methods: { list: { id: "tasks.tasks.list", httpMethod: "GET", path: "lists/{tasklist}/tasks", scopes: ["https://www.googleapis.com/auth/tasks"], parameters: { tasklist: { location: "path", required: true, type: "string" }, }, }, }, }, }, schemas: { Task: { id: "Task", type: "object", properties: { id: { type: "string" } } }, }, }; const photosLibraryDoc = { name: "photoslibrary", version: "v1", title: "Google Photos Library API", rootUrl: "https://photoslibrary.googleapis.com/", servicePath: "v1/", auth: { oauth2: { scopes: { "https://www.googleapis.com/auth/photoslibrary": { description: "Manage the full Google Photos library", }, "https://www.googleapis.com/auth/photoslibrary.appendonly": { description: "Upload to Google Photos", }, "https://www.googleapis.com/auth/photoslibrary.readonly.appcreateddata": { description: "Read app-created Google Photos media", }, }, }, }, resources: { albums: { methods: { list: { id: "photoslibrary.albums.list", httpMethod: "GET", path: "albums", scopes: ["https://www.googleapis.com/auth/photoslibrary"], parameters: {}, }, }, }, mediaItems: { methods: { search: { id: "photoslibrary.mediaItems.search", httpMethod: "POST", path: "mediaItems:search", scopes: ["https://www.googleapis.com/auth/photoslibrary.readonly.appcreateddata"], parameters: {}, }, }, }, }, schemas: {}, }; const photosPickerDoc = { name: "photospicker", version: "v1", title: "Google Photos Picker API", rootUrl: "https://photospicker.googleapis.com/", servicePath: "v1/", resources: { mediaItems: { methods: { list: { id: "photospicker.mediaItems.list", httpMethod: "GET", path: "mediaItems", parameters: {}, }, }, }, }, schemas: {}, }; const peopleDoc = { name: "people", version: "v1", title: "People API", rootUrl: "https://people.googleapis.com/", servicePath: "", auth: { oauth2: { scopes: { "https://www.googleapis.com/auth/userinfo.email": { description: "See your email" }, }, }, }, resources: { people: { methods: { get: { id: "people.people.get", httpMethod: "GET", path: "v1/{+resourceName}", scopes: ["https://www.googleapis.com/auth/userinfo.email"], parameters: { resourceName: { location: "path", required: true, type: "string" }, personFields: { location: "query", type: "string" }, }, response: { $ref: "Person" }, }, }, }, }, schemas: { Person: { id: "Person", type: "object", properties: { resourceName: { type: "string" }, emailAddresses: { type: "array", items: { $ref: "EmailAddress" } }, }, }, EmailAddress: { id: "EmailAddress", type: "object", properties: { value: { type: "string" } } }, }, }; const oauth2Doc = { name: "oauth2", version: "v2", title: "Google OAuth2 API", rootUrl: "https://www.googleapis.com/", servicePath: "", auth: { oauth2: { scopes: { openid: { description: "Associate you with your personal info on Google" }, "https://www.googleapis.com/auth/userinfo.email": { description: "See your primary Google Account email address", }, "https://www.googleapis.com/auth/userinfo.profile": { description: "See your personal info", }, }, }, }, methods: { tokeninfo: { id: "oauth2.tokeninfo", httpMethod: "POST", path: "oauth2/v2/tokeninfo", response: { $ref: "Tokeninfo" }, }, }, resources: { userinfo: { methods: { get: { id: "oauth2.userinfo.get", httpMethod: "GET", path: "oauth2/v2/userinfo", scopes: OAUTH2_USERINFO_SCOPES, response: { $ref: "Userinfo" }, }, }, resources: { v2: { resources: { me: { methods: { get: { id: "oauth2.userinfo.v2.me.get", httpMethod: "GET", path: "userinfo/v2/me", scopes: OAUTH2_USERINFO_SCOPES, response: { $ref: "Userinfo" }, }, }, }, }, }, }, }, }, schemas: { Tokeninfo: { id: "Tokeninfo", type: "object", properties: { audience: { type: "string" }, scope: { type: "string" }, }, }, Userinfo: { id: "Userinfo", type: "object", properties: { email: { type: "string" }, family_name: { type: "string" }, gender: { type: "string" }, given_name: { type: "string" }, hd: { type: "string" }, id: { type: "string" }, link: { type: "string" }, locale: { type: "string" }, name: { type: "string" }, picture: { type: "string" }, verified_email: { type: "boolean" }, }, }, }, }; const toJson = (value: unknown): string => JSON.stringify(value); const DISCOVERY_BODIES: Readonly<Record<string, string>> = { [CALENDAR_URL]: toJson(calendarDoc), [GMAIL_URL]: toJson(gmailDoc), [SHEETS_URL]: toJson(sheetsDoc), [DRIVE_URL]: toJson(driveDoc), [DOCS_URL]: toJson(docsDoc), [TASKS_URL]: toJson(tasksDoc), [PHOTOS_LIBRARY_URL]: toJson(photosLibraryDoc), [PHOTOS_PICKER_URL]: toJson(photosPickerDoc), [PEOPLE_URL]: toJson(peopleDoc), [OAUTH2_URL]: toJson(oauth2Doc), }; interface DiscoveryHttpClientOptions { readonly failedUrls?: ReadonlySet<string>; readonly beforeResponse?: (url: string) => Effect.Effect<void, never, never>; } const waitOneTurn: Effect.Effect<void, never, never> = Effect.promise(() => Promise.resolve()).pipe( Effect.orDie, ); // A stub HTTP client that serves the canned Discovery document for whichever // URL the bundle converter fetches. Service-hosted Discovery URLs carry their // version in the query string, so match the full URL before falling back to the // path-only key used by central Discovery URLs. const makeDiscoveryHttpClientLayer = (options: DiscoveryHttpClientOptions = {}) => Layer.succeed(HttpClient.HttpClient)( HttpClient.make((request: HttpClientRequest.HttpClientRequest) => { const url = new URL(request.url); const key = `${url.origin}${url.pathname}`; const body = DISCOVERY_BODIES[url.toString()] ?? DISCOVERY_BODIES[key]; const discoveryUrl = DISCOVERY_BODIES[url.toString()] !== undefined ? url.toString() : key; const failed = options.failedUrls?.has(url.toString()) === true || options.failedUrls?.has(key) === true; const response = HttpClientResponse.fromWeb( request, failed ? new Response("forced failure", { status: 503 }) : body === undefined ? new Response("not found", { status: 404 }) : new Response(body, { status: 200, headers: { "content-type": "application/json" }, }), ); return (options.beforeResponse?.(discoveryUrl) ?? Effect.void).pipe(Effect.as(response)); }), );